From 9483fbcbf424cabcc34bdd7da6d1bba947e0aa90 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 7 Jan 2020 17:33:35 +0100 Subject: packet-dcerpc-netlogon: relax the data model for netlogon_auth_key This is a change into the correct direction and allows decryption even if DCERPC security context multiplexing is not used. The final design is added as comment, which would make it possible to do decryption in all cases allowed by the protocol. Change-Id: Ided40e0028967f2a047bf2722e627800ca77054d Reviewed-on: https://code.wireshark.org/review/35680 Petri-Dish: Anders Broman Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/dissectors/packet-dcerpc-netlogon.c | 104 ++++++++++--------------------- 1 file changed, 34 insertions(+), 70 deletions(-) diff --git a/epan/dissectors/packet-dcerpc-netlogon.c b/epan/dissectors/packet-dcerpc-netlogon.c index 1b05041d1c..ea695d6290 100644 --- a/epan/dissectors/packet-dcerpc-netlogon.c +++ b/epan/dissectors/packet-dcerpc-netlogon.c @@ -557,11 +557,23 @@ static const true_false_string user_account_control_account_disabled= { }; typedef struct _netlogon_auth_key { - address src; - address dst; - guint32 srcport; - guint32 dstport; - char * name; + /* + * For now we only match the client and server ip + * addresses, as keys can be used across tcp connections. + * + * Also note that ServerChallenge and ServerAuthenticate + * can be on different tcp connections! + * + * TODO: + * * We could have a challenge table indexed by client, server + * and computer name + * * A good ServerAuthenticate could fill a session key table + * indexed by computer name. + * * A DCERPC bind/alter context could lookup the session key table + * and copy the session key to the DCERPC connection/auth_context. + */ + address client; + address server; } netlogon_auth_key; static gint @@ -569,33 +581,18 @@ netlogon_auth_equal (gconstpointer k1, gconstpointer k2) { const netlogon_auth_key *key1 = (const netlogon_auth_key *)k1; const netlogon_auth_key *key2 = (const netlogon_auth_key *)k2; - if(key1->name == NULL || key2->name ==NULL) - return ((key1->srcport == key2->srcport) && (key1->dstport == key2->dstport) && addresses_equal(&key1->src,&key2->src) && - addresses_equal(&key1->dst,&key2->dst)); - else - return ((strcmp(key1->name,key2->name)==0) && addresses_equal(&key1->src,&key2->src) && - addresses_equal(&key1->dst,&key2->dst)); + + return (addresses_equal(&key1->client,&key2->client) && addresses_equal(&key1->server,&key2->server)); } static guint netlogon_auth_hash (gconstpointer k) { const netlogon_auth_key *key1 = (const netlogon_auth_key *)k; - guint hash_val1; - if(key1->name == NULL) { - hash_val1 = key1->dstport; - hash_val1 += key1->srcport; - } - else { - unsigned int i = 0; - hash_val1 = 0; - for(i=0; key1->name[i]; i++) { - hash_val1 += key1->name[i]; - } - } + guint hash_val1 = 0; - hash_val1 = add_address_to_hash(hash_val1, &key1->src); - hash_val1 = add_address_to_hash(hash_val1, &key1->dst); + hash_val1 = add_address_to_hash(hash_val1, &key1->client); + hash_val1 = add_address_to_hash(hash_val1, &key1->server); return hash_val1; } static int @@ -2372,23 +2369,15 @@ netlogon_dissect_netrlogonsamlogoff_reply(tvbuff_t *tvb, int offset, return offset; } -static void generate_hash_key(packet_info *pinfo,unsigned char is_server,netlogon_auth_key *key,char* name) +static void generate_hash_key(packet_info *pinfo,unsigned char is_server,netlogon_auth_key *key) { if(is_server) { - key->dstport = pinfo->srcport; - key->srcport = pinfo->destport; - copy_address_shallow(&key->dst,&pinfo->src); - copy_address_shallow(&key->src,&pinfo->dst); - /* name has been durably allocated */ - key->name = name; + copy_address_shallow(&key->server,&pinfo->src); + copy_address_shallow(&key->client,&pinfo->dst); } else { - copy_address_shallow(&key->dst,&pinfo->dst); - copy_address_shallow(&key->src,&pinfo->src); - key->dstport = pinfo->destport; - key->srcport = pinfo->srcport; - /* name has been durably allocated */ - key->name = name; + copy_address_shallow(&key->server,&pinfo->dst); + copy_address_shallow(&key->client,&pinfo->src); } } @@ -2433,12 +2422,12 @@ netlogon_dissect_netrserverreqchallenge_rqst(tvbuff_t *tvb, int offset, vars->next_start = -1; vars->next = NULL; - generate_hash_key(pinfo,0,&key,NULL); + generate_hash_key(pinfo,0,&key); existing_vars = (netlogon_auth_vars *)wmem_map_lookup(netlogon_auths, &key); if (!existing_vars) { netlogon_auth_key *k = (netlogon_auth_key *)wmem_memdup(wmem_file_scope(), &key, sizeof(netlogon_auth_key)); - copy_address_wmem(wmem_file_scope(), &k->src, &key.src); - copy_address_wmem(wmem_file_scope(), &k->dst, &key.dst); + copy_address_wmem(wmem_file_scope(), &k->client, &key.client); + copy_address_wmem(wmem_file_scope(), &k->server, &key.server); debugprintf("Adding initial vars with this start packet = %d\n",vars->start); wmem_map_insert(netlogon_auths, k, vars); } @@ -2457,31 +2446,6 @@ netlogon_dissect_netrserverreqchallenge_rqst(tvbuff_t *tvb, int offset, existing_vars->next = vars; } } - /* used by other rpc that use schannel ie lsa */ -#if 0 - generate_hash_key(pinfo,0,&key,vars->client_name); - existing_vars = NULL; - existing_vars = wmem_map_lookup(schannel_auths, key); - if (!existing_vars) - { - netlogon_auth_key *k = (netlogon_auth_key *)wmem_memdup(wmem_file_scope(), &key, sizeof(netlogon_auth_key)); - copy_address_wmem(wmem_file_scope(), &k->src, &key.src); - copy_address_wmem(wmem_file_scope(), &k->dst, &key.dst); - wmem_map_insert(schannel_auths, k, vars); - } - else - { - while(existing_vars->next != NULL && existing_vars->start <= vars->start) { - existing_vars = existing_vars->next; - } - if(existing_vars->next != NULL || existing_vars == vars) { - debugprintf("It seems that I already record this vars (schannel hash)%d\n",vars->start); - } - else { - existing_vars->next_start = pinfo->num; - existing_vars->next = vars; - } -#endif return offset; } @@ -2493,7 +2457,7 @@ netlogon_dissect_netrserverreqchallenge_reply(tvbuff_t *tvb, int offset, netlogon_auth_key key; guint64 server_challenge; - generate_hash_key(pinfo,1,&key,NULL); + generate_hash_key(pinfo,1,&key); vars = (netlogon_auth_vars *)wmem_map_lookup(netlogon_auths,(gconstpointer*) &key); offset = dissect_dcerpc_8bytes(tvb, offset, pinfo, tree, drep, @@ -6622,7 +6586,7 @@ netlogon_dissect_netrserverauthenticate23_reply(tvbuff_t *tvb, int offset, offset = dissect_ntstatus(tvb, offset, pinfo, tree, di, drep, hf_netlogon_rc, NULL); - generate_hash_key(pinfo, 1 , &key, NULL); + generate_hash_key(pinfo, 1 , &key); vars = (netlogon_auth_vars *)wmem_map_lookup(netlogon_auths, &key); if(vars != NULL) { @@ -7909,7 +7873,7 @@ dissect_packet_data(tvbuff_t *tvb ,tvbuff_t *auth_tvb _U_, netlogon_auth_key key; /*debugprintf("Dissection of request data offset %d len=%d on packet %d\n",offset,tvb_length_remaining(tvb,offset),pinfo->num);*/ - generate_hash_key(pinfo,is_server,&key,NULL); + generate_hash_key(pinfo,is_server,&key); vars = (netlogon_auth_vars *)wmem_map_lookup(netlogon_auths, &key); if(vars != NULL ) { @@ -7984,7 +7948,7 @@ dissect_secchan_verf(tvbuff_t *tvb, int offset, packet_info *pinfo, guint64 confounder = 0; int update_vars = 0; - generate_hash_key(pinfo,is_server,&key,NULL); + generate_hash_key(pinfo,is_server,&key); vars = (netlogon_auth_vars *)wmem_map_lookup(netlogon_auths,(gconstpointer*) &key); if( ! (seen.isseen && seen.num == pinfo->num) ) { /* -- cgit v1.2.3