Ethereal-dev: Re: [Ethereal-dev] Patch: NTLMSSP version 1 decryption

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxx>
Date: Tue, 31 Dec 2002 00:24:49 -0800
On Sun, Dec 29, 2002 at 04:16:32PM -0500, dheitmueller wrote:
> Attached is a patch to decrypt DCE/RPC conversations that make use of
> NTLMSSP version 1. 

Checked in, with a number of bug fixes.

> Here is what is still outstanding:

	...

> * The ability to dissect the decrypted payload.  I need to be able to
> hand the TVB with the decrypted buffer back to the calling dissector. 
> Not quite sure what the best approach for this is this yet.

That's the stuff in "dcerpc_try_handoff()" (which I fixed to call the
NTLMSSP dissector only if it's actually NTLMSSP)?

One way to do that would be to set "pinfo->private_data" to point to a
"tvbuff_t *", have payload dissectors all assume that
"pinfo->private_data" points to a "tvbuff_t *" and set the "tvbuff_t *"
to which it points to the new tvb, and then do something such as

    gboolean is_encrypted;
    tvbuff_t *stub_tvb;
    int stub_offset;

	...

    saved_proto = pinfo->current_proto;
    saved_private_data = pinfo->private_data;
    if (auth_info != NULL &&
          auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
        is_encrypted = TRUE;
        stub_tvb = NULL;
        stub_offset = 0;
        length = tvb_length_remaining (tvb, offset);
        if (length > 0) {
            proto_tree_add_text(sub_tree, tvb, offset, length,
                                "Encrypted stub data (%d byte%s)",
                                length, plurality(length, "", "s"));

            switch (auth_info->auth_type) {

            case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: {
                /* NTLMSSP */
                tvbuff_t *ntlmssp_tvb;

                ntlmssp_tvb = tvb_new_subset(tvb, offset, length, length);
            
                pinfo->private_data = (void *)&stub_tvb;
                call_dissector(ntlmssp_enc_payload_handle, ntlmssp_tvb, pinfo,
                               sub_tree);
                break;
                }
            }
        }
    } else {
        is_encrypted = FALSE;
        stub_tvb = tvb;
        stub_offset = 0;
    }
    if (stub_tvb != NULL) {
        sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp;
        if (sub_dissect) {
            pinfo->current_proto = sub_proto->name;
            pinfo->private_data = (void *)info;

            init_ndr_pointer_list(pinfo);
            offset = sub_dissect (stub_tvb, stub_offset, pinfo, sub_tree, drep);

            pinfo->current_proto = saved_proto;
            pinfo->private_data = saved_private_data;
        } else {
            length = tvb_length_remaining (stub_tvb, stub_offset);
            if (length > 0) {
                proto_tree_add_text (sub_tree, stub_tvb, stub_offset, length,
                                     "Stub data (%d byte%s)", length,
                                     plurality(length, "", "s"));
            }
        }
    }

and then don't have the decrypting dissector put anything into the
protocol tree (yes, one might argue that this slightly abuses the
dissector-handle mechanism to call functions that aren't, strictly
speaking, dissectors, but that's life).

> Please email with comments, problems, etc.

Well, I fixed a number of bugs that showed up when doing regressions.

However, a problem that a regression wouldn't show up is that it appears
that you never free the ntlmssp_info structures allocated by the NTLMSSP
dissector.  You should probably allocate them from a GMemChunk (which is
a little quicker and, if there are a lot of them, a little more
memory-efficient than allocating them with "g_malloc()), and then have
"ntlmssp_init_protocol()" destroy that GMemChunk if it exists and then
create it regardless of whether it existed or not.