2 * Add-on for better NTLM v1/v2 handling
3 * Copyright 2009 Matthieu Patou <matthieu.patou@matws.net>
4 * Routines for NTLM Secure Service Provider
5 * Devin Heitmueller <dheitmueller@netilla.com>
6 * Copyright 2003, Tim Potter <tpot@samba.org>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
41 #include "packet-windows-common.h"
42 #include "packet-smb-common.h"
43 #include "packet-frame.h"
44 #include <epan/asn1.h>
45 #include "packet-kerberos.h"
46 #include <epan/prefs.h>
47 #include <epan/emem.h>
49 #include <epan/expert.h>
50 #include <epan/crypt/crypt-rc4.h>
51 #include <epan/crypt/crypt-md4.h>
52 #include <epan/crypt/crypt-md5.h>
53 #include <epan/crypt/crypt-des.h>
54 #include "packet-dcerpc.h"
55 #include "packet-gssapi.h"
56 #include <epan/crc32.h>
58 #include "packet-ntlmssp.h"
60 static int ntlmssp_tap = -1;
64 #define NTLMSSP_NEGOTIATE 1
65 #define NTLMSSP_CHALLENGE 2
66 #define NTLMSSP_AUTH 3
67 #define NTLMSSP_UNKNOWN 4
68 #define CLIENT_SIGN_TEXT "session key to client-to-server signing key magic constant"
69 #define CLIENT_SEAL_TEXT "session key to client-to-server sealing key magic constant"
70 #define SERVER_SIGN_TEXT "session key to server-to-client signing key magic constant"
71 #define SERVER_SEAL_TEXT "session key to server-to-client sealing key magic constant"
73 #define NTLMSSP_KEY_LEN 16
75 static const value_string ntlmssp_message_types[] = {
76 { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
77 { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
78 { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
79 { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
83 typedef struct _md4_pass {
84 guint8 md4[NTLMSSP_KEY_LEN];
87 static unsigned char gbl_zeros[24] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
88 static GHashTable* hash_packet = NULL;
91 * NTLMSSP negotiation flags
96 * http://davenport.sourceforge.net/ntlm.html
98 * although that document says that:
100 * 0x00010000 is "Target Type Domain";
101 * 0x00020000 is "Target Type Server"
102 * 0x00040000 is "Target Type Share";
104 * and that 0x00100000, 0x00200000, and 0x00400000 are
105 * "Request Init Response", "Request Accept Response", and
106 * "Request Non-NT Session Key", rather than those values shifted
107 * right one having those interpretations.
109 * UPDATE: Further information obtained from [MS-NLMP]:
110 * NT LAN Manager (NTLM) Authentication Protocol Specification
111 * http://msdn2.microsoft.com/en-us/library/cc236621.aspx
114 #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
115 #define NTLMSSP_NEGOTIATE_OEM 0x00000002
116 #define NTLMSSP_REQUEST_TARGET 0x00000004
117 #define NTLMSSP_NEGOTIATE_00000008 0x00000008
118 #define NTLMSSP_NEGOTIATE_SIGN 0x00000010
119 #define NTLMSSP_NEGOTIATE_SEAL 0x00000020
120 #define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040
121 #define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
122 #define NTLMSSP_NEGOTIATE_00000100 0x00000100
123 #define NTLMSSP_NEGOTIATE_NTLM 0x00000200
124 #define NTLMSSP_NEGOTIATE_NT_ONLY 0x00000400
125 #define NTLMSSP_NEGOTIATE_00000800 0x00000800
126 #define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000
127 #define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000
128 #define NTLMSSP_NEGOTIATE_00004000 0x00004000
129 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
130 #define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000
131 #define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
132 #define NTLMSSP_TARGET_TYPE_SHARE 0x00040000
133 #define NTLMSSP_NEGOTIATE_EXTENDED_SECURITY 0x00080000
134 #define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000
135 #define NTLMSSP_NEGOTIATE_00200000 0x00200000
136 #define NTLMSSP_REQUEST_NON_NT_SESSION 0x00400000
137 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
138 #define NTLMSSP_NEGOTIATE_01000000 0x01000000
139 #define NTLMSSP_NEGOTIATE_VERSION 0x02000000
140 #define NTLMSSP_NEGOTIATE_04000000 0x04000000
141 #define NTLMSSP_NEGOTIATE_08000000 0x08000000
142 #define NTLMSSP_NEGOTIATE_10000000 0x10000000
143 #define NTLMSSP_NEGOTIATE_128 0x20000000
144 #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
145 #define NTLMSSP_NEGOTIATE_56 0x80000000
147 static int proto_ntlmssp = -1;
148 static int hf_ntlmssp_auth = -1;
149 static int hf_ntlmssp_message_type = -1;
150 static int hf_ntlmssp_negotiate_flags = -1;
151 static int hf_ntlmssp_negotiate_flags_01 = -1;
152 static int hf_ntlmssp_negotiate_flags_02 = -1;
153 static int hf_ntlmssp_negotiate_flags_04 = -1;
154 static int hf_ntlmssp_negotiate_flags_08 = -1;
155 static int hf_ntlmssp_negotiate_flags_10 = -1;
156 static int hf_ntlmssp_negotiate_flags_20 = -1;
157 static int hf_ntlmssp_negotiate_flags_40 = -1;
158 static int hf_ntlmssp_negotiate_flags_80 = -1;
159 static int hf_ntlmssp_negotiate_flags_100 = -1;
160 static int hf_ntlmssp_negotiate_flags_200 = -1;
161 static int hf_ntlmssp_negotiate_flags_400 = -1;
162 static int hf_ntlmssp_negotiate_flags_800 = -1;
163 static int hf_ntlmssp_negotiate_flags_1000 = -1;
164 static int hf_ntlmssp_negotiate_flags_2000 = -1;
165 static int hf_ntlmssp_negotiate_flags_4000 = -1;
166 static int hf_ntlmssp_negotiate_flags_8000 = -1;
167 static int hf_ntlmssp_negotiate_flags_10000 = -1;
168 static int hf_ntlmssp_negotiate_flags_20000 = -1;
169 static int hf_ntlmssp_negotiate_flags_40000 = -1;
170 static int hf_ntlmssp_negotiate_flags_80000 = -1;
171 static int hf_ntlmssp_negotiate_flags_100000 = -1;
172 static int hf_ntlmssp_negotiate_flags_200000 = -1;
173 static int hf_ntlmssp_negotiate_flags_400000 = -1;
174 static int hf_ntlmssp_negotiate_flags_800000 = -1;
175 static int hf_ntlmssp_negotiate_flags_1000000 = -1;
176 static int hf_ntlmssp_negotiate_flags_2000000 = -1;
177 static int hf_ntlmssp_negotiate_flags_4000000 = -1;
178 static int hf_ntlmssp_negotiate_flags_8000000 = -1;
179 static int hf_ntlmssp_negotiate_flags_10000000 = -1;
180 static int hf_ntlmssp_negotiate_flags_20000000 = -1;
181 static int hf_ntlmssp_negotiate_flags_40000000 = -1;
182 static int hf_ntlmssp_negotiate_flags_80000000 = -1;
183 static int hf_ntlmssp_negotiate_workstation_strlen = -1;
184 static int hf_ntlmssp_negotiate_workstation_maxlen = -1;
185 static int hf_ntlmssp_negotiate_workstation_buffer = -1;
186 static int hf_ntlmssp_negotiate_workstation = -1;
187 static int hf_ntlmssp_negotiate_domain_strlen = -1;
188 static int hf_ntlmssp_negotiate_domain_maxlen = -1;
189 static int hf_ntlmssp_negotiate_domain_buffer = -1;
190 static int hf_ntlmssp_negotiate_domain = -1;
191 static int hf_ntlmssp_ntlm_server_challenge = -1;
192 static int hf_ntlmssp_ntlm_client_challenge = -1;
193 static int hf_ntlmssp_reserved = -1;
194 static int hf_ntlmssp_challenge_target_name = -1;
195 static int hf_ntlmssp_auth_username = -1;
196 static int hf_ntlmssp_auth_domain = -1;
197 static int hf_ntlmssp_auth_hostname = -1;
198 static int hf_ntlmssp_auth_lmresponse = -1;
199 static int hf_ntlmssp_auth_ntresponse = -1;
200 static int hf_ntlmssp_auth_sesskey = -1;
201 static int hf_ntlmssp_string_len = -1;
202 static int hf_ntlmssp_string_maxlen = -1;
203 static int hf_ntlmssp_string_offset = -1;
204 static int hf_ntlmssp_blob_len = -1;
205 static int hf_ntlmssp_blob_maxlen = -1;
206 static int hf_ntlmssp_blob_offset = -1;
207 static int hf_ntlmssp_version = -1;
208 static int hf_ntlmssp_version_major = -1;
209 static int hf_ntlmssp_version_minor = -1;
210 static int hf_ntlmssp_version_build_number = -1;
211 static int hf_ntlmssp_version_ntlm_current_revision = -1;
213 static int hf_ntlmssp_challenge_target_info = -1;
214 static int hf_ntlmssp_challenge_target_info_len = -1;
215 static int hf_ntlmssp_challenge_target_info_maxlen = -1;
216 static int hf_ntlmssp_challenge_target_info_offset = -1;
218 static int hf_ntlmssp_challenge_target_info_item_type = -1;
219 static int hf_ntlmssp_challenge_target_info_item_len = -1;
221 static int hf_ntlmssp_challenge_target_info_end = -1;
222 static int hf_ntlmssp_challenge_target_info_nb_computer_name = -1;
223 static int hf_ntlmssp_challenge_target_info_nb_domain_name = -1;
224 static int hf_ntlmssp_challenge_target_info_dns_computer_name = -1;
225 static int hf_ntlmssp_challenge_target_info_dns_domain_name = -1;
226 static int hf_ntlmssp_challenge_target_info_dns_tree_name = -1;
227 static int hf_ntlmssp_challenge_target_info_flags = -1;
228 static int hf_ntlmssp_challenge_target_info_timestamp = -1;
229 static int hf_ntlmssp_challenge_target_info_restrictions = -1;
230 static int hf_ntlmssp_challenge_target_info_target_name =-1;
231 static int hf_ntlmssp_challenge_target_info_channel_bindings =-1;
233 static int hf_ntlmssp_ntlmv2_response_item_type = -1;
234 static int hf_ntlmssp_ntlmv2_response_item_len = -1;
236 static int hf_ntlmssp_ntlmv2_response_end = -1;
237 static int hf_ntlmssp_ntlmv2_response_nb_computer_name = -1;
238 static int hf_ntlmssp_ntlmv2_response_nb_domain_name = -1;
239 static int hf_ntlmssp_ntlmv2_response_dns_computer_name = -1;
240 static int hf_ntlmssp_ntlmv2_response_dns_domain_name = -1;
241 static int hf_ntlmssp_ntlmv2_response_dns_tree_name = -1;
242 static int hf_ntlmssp_ntlmv2_response_flags = -1;
243 static int hf_ntlmssp_ntlmv2_response_timestamp = -1;
244 static int hf_ntlmssp_ntlmv2_response_restrictions = -1;
245 static int hf_ntlmssp_ntlmv2_response_target_name =-1;
246 static int hf_ntlmssp_ntlmv2_response_channel_bindings =-1;
248 static int hf_ntlmssp_message_integrity_code = -1;
249 static int hf_ntlmssp_verf = -1;
250 static int hf_ntlmssp_verf_vers = -1;
251 static int hf_ntlmssp_verf_body = -1;
252 static int hf_ntlmssp_verf_randompad = -1;
253 static int hf_ntlmssp_verf_hmacmd5 = -1;
254 static int hf_ntlmssp_verf_crc32 = -1;
255 static int hf_ntlmssp_verf_sequence = -1;
256 static int hf_ntlmssp_decrypted_payload = -1;
258 static int hf_ntlmssp_ntlmv2_response = -1;
259 static int hf_ntlmssp_ntlmv2_response_hmac = -1;
260 static int hf_ntlmssp_ntlmv2_response_header = -1;
261 static int hf_ntlmssp_ntlmv2_response_reserved = -1;
262 static int hf_ntlmssp_ntlmv2_response_time = -1;
263 static int hf_ntlmssp_ntlmv2_response_chal = -1;
264 static int hf_ntlmssp_ntlmv2_response_unknown = -1;
266 static gint ett_ntlmssp = -1;
267 static gint ett_ntlmssp_negotiate_flags = -1;
268 static gint ett_ntlmssp_string = -1;
269 static gint ett_ntlmssp_blob = -1;
270 static gint ett_ntlmssp_version = -1;
271 static gint ett_ntlmssp_challenge_target_info = -1;
272 static gint ett_ntlmssp_challenge_target_info_item = -1;
273 static gint ett_ntlmssp_ntlmv2_response = -1;
274 static gint ett_ntlmssp_ntlmv2_response_item = -1;
276 /* Configuration variables */
277 const char *gbl_nt_password = NULL;
279 #define MAX_BLOB_SIZE 256
280 typedef struct _ntlmssp_blob {
282 guint8 contents[MAX_BLOB_SIZE];
285 /* Used in the conversation function */
286 typedef struct _ntlmssp_info {
289 rc4_state_struct rc4_state_client;
290 rc4_state_struct rc4_state_server;
291 guint8 sign_key_client[NTLMSSP_KEY_LEN];
292 guint8 sign_key_server[NTLMSSP_KEY_LEN];
293 guint32 server_dest_port;
294 unsigned char server_challenge[8];
295 unsigned char client_challenge[8];
296 int rc4_state_initialized;
297 ntlmssp_blob ntlm_response;
298 ntlmssp_blob lm_response;
301 /* If this struct exists in the payload_decrypt, then we have already
303 typedef struct _ntlmssp_packet_info {
304 guint8 *decrypted_payload;
306 guint8 verifier[NTLMSSP_KEY_LEN];
307 gboolean payload_decrypted;
308 gboolean verifier_decrypted;
309 } ntlmssp_packet_info;
312 static void printnbyte(const guint8* tab,int nb,const char* txt,const char* txt2)
315 fprintf(stderr,"%s ",txt);
318 fprintf(stderr,"%02hhX ",*(tab+i));
320 fprintf(stderr,"%s",txt2);
323 static void printnchar(const guint8* tab,int nb,char* txt,char* txt2)
326 fprintf(stderr,"%s ",txt);
329 fprintf(stderr,"%c",*(tab+i));
331 fprintf(stderr,"%s",txt2);
335 static void printnbyte(const guint8* tab _U_,int nb _U_, const char* txt _U_,const char* txt2 _U_)
340 * GSlist of decrypted payloads.
342 static GSList *decrypted_payloads;
344 int LEBE_Convert(int value)
349 b=(value&0x0000FF00) >> 8;
350 c=(value&0x00FF0000) >> 16;
351 d=(value&0xFF000000) >> 24;
352 return (a << 24) | (b << 16) | (c << 8) | d;
355 Perform a DES encryption with a 16 bit key and 8bit data item.
356 It's in fact 3 susbsequent call to crypt_des_ecb with a 7 bit key.
357 Missing bits for the key are replaced by 0;
358 Returns output in response, which is expected to be 24 bytes.
360 static int crypt_des_ecb_long(guint8 *response,
364 guint8 pw21[21]; /* 21 bytes place for the needed key */
366 memset(pw21, 0, sizeof(pw21));
367 memcpy(pw21, key, 16);
369 memset(response, 0, 24);
370 /* crypt_des_ecb(data,key)*/
371 crypt_des_ecb(response, data, pw21, 1);
372 crypt_des_ecb(response + 8, data, pw21 + 7, 1);
373 crypt_des_ecb(response + 16, data, pw21 + 14, 1);
378 Generate a challenge response, given an eight byte challenge and
379 either the NT or the Lan Manager password hash (16 bytes).
380 Returns output in response, which is expected to be 24 bytes.
382 static int ntlmssp_generate_challenge_response(guint8 *response,
383 const guint8 *passhash,
384 const guint8 *challenge)
386 guint8 pw21[21]; /* Password hash padded to 21 bytes */
388 memset(pw21, 0x0, sizeof(pw21));
389 memcpy(pw21, passhash, 16);
391 memset(response, 0, 24);
393 crypt_des_ecb(response, challenge, pw21, 1);
394 crypt_des_ecb(response + 8, challenge, pw21 + 7, 1);
395 crypt_des_ecb(response + 16, challenge, pw21 + 14, 1);
401 /* Ultra simple ainsi to unicode converter, will only work for ascii password ...*/
402 static void str_to_unicode(const char *nt_password, char *nt_password_unicode)
404 size_t password_len = 0;
407 password_len = strlen(nt_password);
408 if(nt_password_unicode != NULL)
410 for(i=0;i<(password_len);i++)
412 nt_password_unicode[i*2]=nt_password[i];
413 nt_password_unicode[i*2+1]=0;
415 nt_password_unicode[2*password_len]='\0';
419 /* This function generate the Key Exchange Key
420 * Depending on the flags this key will either be used to crypt the exported session key
421 * or will be used directly as exported session key.
422 * Exported session key is the key that will be used for sealing and signing communication*/
425 get_keyexchange_key(unsigned char keyexchangekey[NTLMSSP_KEY_LEN],const unsigned char sessionbasekey[NTLMSSP_KEY_LEN],const unsigned char lm_challenge_response[24],int flags)
427 guint8 basekey[NTLMSSP_KEY_LEN];
430 memset(keyexchangekey,0,NTLMSSP_KEY_LEN);
431 memset(basekey,0,NTLMSSP_KEY_LEN);
432 /* sessionbasekey is either derived from lm_password_hash or from nt_password_hash depending on the key type negotiated */
433 memcpy(basekey,sessionbasekey,8);
434 memset(basekey,0xBD,8);
435 if(flags&NTLMSSP_NEGOTIATE_LM_KEY)
438 crypt_des_ecb(keyexchangekey,lm_challenge_response,basekey,1);
439 crypt_des_ecb(keyexchangekey+8,lm_challenge_response,basekey+7,1);
443 if(flags&NTLMSSP_REQUEST_NON_NT_SESSION)
445 /*People from samba tends to use the same function in this case than in the previous one but with 0 data
446 * it's not clear that it produce the good result
447 * memcpy(keyexchangekey,lm_hash,8);
448 * Let's trust samba implementation it mights seem weird but they are more often rights than the spec !
451 crypt_des_ecb(keyexchangekey,zeros,basekey,3);
452 crypt_des_ecb(keyexchangekey+8,zeros,basekey+7,1);
456 /* it is stated page 65 of NTLM SSP spec that sessionbasekey should be encrypted with hmac_md5 using the concact of both challenge
457 * when it's NTLM v1 + extended security but it turns out to be wrong !
459 memcpy(keyexchangekey,sessionbasekey,NTLMSSP_KEY_LEN);
463 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
465 get_md4pass_list(md4_pass** p_pass_list,const char* nt_password)
470 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
471 int password_len = 0;
472 char nt_password_unicode[256];
479 read_keytab_file_from_preferences();
481 for(ek=enc_key_list;ek;ek=ek->next){
482 if( ek->keylength == NTLMSSP_KEY_LEN ) {
486 memset(nt_password_hash,0,NTLMSSP_KEY_LEN);
487 if (nt_password[0] != '\0' && ( strlen(nt_password) < 129 )) {
489 password_len = strlen(nt_password);
490 str_to_unicode(nt_password,nt_password_unicode);
491 crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
494 /* Unable to calculate the session key without a password or if password is more than 128 char ......*/
498 *p_pass_list = ep_alloc(nb_pass*sizeof(md4_pass));
499 pass_list=*p_pass_list;
501 if( memcmp(nt_password_hash,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
502 memcpy(pass_list[i].md4,nt_password_hash,NTLMSSP_KEY_LEN);
505 for(ek=enc_key_list;ek;ek=ek->next){
506 if( ek->keylength == NTLMSSP_KEY_LEN ) {
507 memcpy(pass_list[i].md4,ek->keyvalue,NTLMSSP_KEY_LEN);
514 /* Create an NTLMSSP version 2 key
517 create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge , const guint8 *clientchallenge ,
518 guint8 *sessionkey ,const guint8 *encryptedsessionkey , int flags , ntlmssp_blob ntlm_response, ntlmssp_blob lm_response _U_, ntlmssp_header_t *ntlmssph ) {
519 char domain_name_unicode[256];
520 char user_uppercase[256];
522 /*guint8 md4[NTLMSSP_KEY_LEN];*/
523 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
524 unsigned char nt_proof[NTLMSSP_KEY_LEN];
525 unsigned char ntowf[NTLMSSP_KEY_LEN];
526 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
527 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
528 guint8 lm_challenge_response[24];
531 rc4_state_struct rc4state;
534 md4_pass *pass_list = NULL;
538 /* We are going to try password encrypted in keytab as well, it's an idean of Stefan Metzmacher <metze@samba.org>
539 * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
541 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
542 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
543 nb_pass = get_md4pass_list(&pass_list,nt_password);
546 memset(user_uppercase,0,256);
547 user_len = strlen(ntlmssph->acct_name);
548 if( user_len < 129 ) {
550 str_to_unicode(ntlmssph->acct_name,buf);
551 for (j = 0; j < (2*user_len); j++) {
552 if( buf[j] != '\0' ) {
553 user_uppercase[j] = toupper(buf[j]);
558 /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
561 domain_len = strlen(ntlmssph->domain_name);
562 if( domain_len < 129 ) {
563 str_to_unicode(ntlmssph->domain_name,domain_name_unicode);
566 /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
569 while (i < nb_pass ) {
570 /*fprintf(stderr,"Turn %d, ",i);*/
571 memcpy(nt_password_hash,pass_list[i].md4,NTLMSSP_KEY_LEN);
572 /*printnbyte(nt_password_hash,NTLMSSP_KEY_LEN,"Current NT password hash: ","\n");*/
574 /* ntowf computation */
576 memcpy(buf,user_uppercase,user_len*2);
577 memcpy(buf+user_len*2,domain_name_unicode,domain_len*2);
578 md5_hmac(buf,domain_len*2+user_len*2,nt_password_hash,NTLMSSP_KEY_LEN,ntowf);
581 memcpy(buf,serverchallenge,8);
582 memcpy(buf+8,clientchallenge,8);
583 md5_hmac(buf,NTLMSSP_KEY_LEN,ntowf,NTLMSSP_KEY_LEN,lm_challenge_response);
584 memcpy(lm_challenge_response+NTLMSSP_KEY_LEN,clientchallenge,8);
585 printnbyte(lm_challenge_response,24,"LM Response: ","\n");
587 /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
589 memcpy(buf,serverchallenge,8);
590 memcpy(buf+8,ntlm_response.contents+NTLMSSP_KEY_LEN,ntlm_response.length-NTLMSSP_KEY_LEN);
591 md5_hmac(buf,ntlm_response.length-8,ntowf,NTLMSSP_KEY_LEN,nt_proof);
592 printnbyte(nt_proof,NTLMSSP_KEY_LEN,"NT proof: ","\n");
593 if( !memcmp(nt_proof,ntlm_response.contents,NTLMSSP_KEY_LEN) ) {
604 md5_hmac(nt_proof,NTLMSSP_KEY_LEN,ntowf,NTLMSSP_KEY_LEN,sessionbasekey);
605 get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
606 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
607 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
609 memcpy(sessionkey,encryptedsessionkey,NTLMSSP_KEY_LEN);
610 crypt_rc4_init(&rc4state,keyexchangekey,NTLMSSP_KEY_LEN);
611 crypt_rc4(&rc4state,sessionkey,NTLMSSP_KEY_LEN);
615 memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
619 /* Create an NTLMSSP version 1 key
620 * That is more complicated logic and methods and user challenge as well.
621 * password points to the ANSI password to encrypt, challenge points to
622 * the 8 octet challenge string
625 create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, const guint8 *clientchallenge,
626 guint8 *sessionkey,const guint8 *encryptedsessionkey, int flags, const guint8 *ref_nt_challenge_response,const guint8 *ref_lm_challenge_response)
628 unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
629 unsigned char lm_password_hash[NTLMSSP_KEY_LEN];
630 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
631 unsigned char challenges_hash[NTLMSSP_KEY_LEN];
632 unsigned char challenges_hash_first8[8];
633 unsigned char challenges[NTLMSSP_KEY_LEN];
634 guint8 md4[NTLMSSP_KEY_LEN];
636 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
637 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
638 guint8 lm_challenge_response[24];
639 guint8 nt_challenge_response[24];
640 rc4_state_struct rc4state;
641 md5_state_t md5state;
642 char nt_password_unicode[256];
646 md4_pass *pass_list = NULL;
647 unsigned char lmhash_key[] =
648 {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
650 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
651 memset(lm_password_upper, 0, sizeof(lm_password_upper));
652 /* lm auth/lm session == (!NTLM_NEGOTIATE_NT_ONLY && NTLMSSP_NEGOTIATE_LM_KEY) || ! (EXTENDED_SECURITY) || ! NTLMSSP_NEGOTIATE_NTLM*/
653 /* Create a Lan Manager hash of the input password */
654 if (nt_password[0] != '\0') {
655 password_len = strlen(nt_password);
656 /*Do not forget to free nt_password_nt*/
657 str_to_unicode(nt_password,nt_password_unicode);
658 crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
659 /* Truncate password if too long */
660 if (password_len > NTLMSSP_KEY_LEN)
661 password_len = NTLMSSP_KEY_LEN;
662 for (i = 0; i < password_len; i++) {
663 lm_password_upper[i] = toupper(nt_password[i]);
668 /* Unable to calculate the session key without a password ... and we will not use one for a keytab*/
669 if( !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
673 if((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NTLMSSP_NEGOTIATE_NT_ONLY)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
674 crypt_des_ecb(lm_password_hash, lmhash_key, lm_password_upper, 1);
675 crypt_des_ecb(lm_password_hash+8, lmhash_key, lm_password_upper+7, 1);
676 ntlmssp_generate_challenge_response(lm_challenge_response,
677 lm_password_hash, serverchallenge);
678 memcpy(sessionbasekey,lm_password_hash,NTLMSSP_KEY_LEN);
682 memset(lm_challenge_response,0,24);
683 if( flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
684 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
685 nb_pass = get_md4pass_list(&pass_list,nt_password);
688 while (i < nb_pass ) {
689 /*fprintf(stderr,"Turn %d, ",i);*/
690 memcpy(nt_password_hash,pass_list[i].md4,NTLMSSP_KEY_LEN);
691 /*printnbyte(nt_password_hash,NTLMSSP_KEY_LEN,"Current NT password hash: ","\n");*/
693 memcpy(lm_challenge_response,clientchallenge,8);
695 md5_append(&md5state,serverchallenge,8);
696 md5_append(&md5state,clientchallenge,8);
697 md5_finish(&md5state,challenges_hash);
698 memcpy(challenges_hash_first8,challenges_hash,8);
699 crypt_des_ecb_long(nt_challenge_response,nt_password_hash,challenges_hash_first8);
700 if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) ) {
707 crypt_des_ecb_long(nt_challenge_response,nt_password_hash,serverchallenge);
708 if( flags & NTLMSSP_NEGOTIATE_NT_ONLY ) {
709 memcpy(lm_challenge_response,nt_challenge_response,24);
712 crypt_des_ecb_long(lm_challenge_response,lm_password_hash,serverchallenge);
714 if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) && !memcmp(ref_lm_challenge_response,lm_challenge_response,24) ) {
718 /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
719 * that sessionbasekey should be based md4(nt_password_hash) only in the case of some NT auth
720 * Otherwise it should be lm_password_hash ...*/
721 crypt_md4(md4,nt_password_hash,NTLMSSP_KEY_LEN);
722 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
723 memcpy(challenges,serverchallenge,8);
724 memcpy(challenges+8,clientchallenge,8);
725 /*md5_hmac(text,text_len,key,key_len,digest);*/
726 md5_hmac(challenges,NTLMSSP_KEY_LEN,md4,NTLMSSP_KEY_LEN,sessionbasekey);
729 memcpy(sessionbasekey,md4,NTLMSSP_KEY_LEN);
738 get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
739 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
740 /*printnbyte(nt_challenge_response,24,"NT challenge response","\n");
741 printnbyte(lm_challenge_response,24,"LM challenge response","\n");*/
742 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
743 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
745 memcpy(sessionkey,encryptedsessionkey,NTLMSSP_KEY_LEN);
746 crypt_rc4_init(&rc4state,keyexchangekey,NTLMSSP_KEY_LEN);
747 crypt_rc4(&rc4state,sessionkey,NTLMSSP_KEY_LEN);
751 memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
755 get_siging_key(guint8 *sign_key_server,guint8* sign_key_client,const guint8 key[NTLMSSP_KEY_LEN], int keylen)
757 md5_state_t md5state;
758 md5_state_t md5state2;
759 memset(sign_key_client,0,NTLMSSP_KEY_LEN);
760 memset(sign_key_server,0,NTLMSSP_KEY_LEN);
762 md5_append(&md5state,key,keylen);
763 md5_append(&md5state,CLIENT_SIGN_TEXT,strlen(CLIENT_SIGN_TEXT)+1);
764 md5_finish(&md5state,sign_key_client);
765 md5_init(&md5state2);
766 md5_append(&md5state2,key,keylen);
767 md5_append(&md5state2,SERVER_SIGN_TEXT,strlen(SERVER_SIGN_TEXT)+1);
768 md5_finish(&md5state2,sign_key_server);
772 /* We return either a 128 or 64 bit key
775 get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int flags ,int *keylen ,guint8 *clientsealkey ,guint8 *serversealkey)
777 md5_state_t md5state;
778 md5_state_t md5state2;
779 memset(clientsealkey,0,NTLMSSP_KEY_LEN);
780 memset(serversealkey,0,NTLMSSP_KEY_LEN);
781 memcpy(clientsealkey,exportedsessionkey,NTLMSSP_KEY_LEN);
782 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)
784 if (flags & NTLMSSP_NEGOTIATE_128)
786 /* The exportedsessionkey has already the good length just update the length*/
791 if (flags & NTLMSSP_NEGOTIATE_56)
793 memset(clientsealkey+7,0,9);
798 memset(clientsealkey+5,0,11);
802 memcpy(serversealkey,clientsealkey,NTLMSSP_KEY_LEN);
804 md5_append(&md5state,clientsealkey,*keylen);
805 md5_append(&md5state,CLIENT_SEAL_TEXT,strlen(CLIENT_SEAL_TEXT)+1);
806 md5_finish(&md5state,clientsealkey);
807 md5_init(&md5state2);
808 md5_append(&md5state2,serversealkey,*keylen);
809 md5_append(&md5state2,SERVER_SEAL_TEXT,strlen(SERVER_SEAL_TEXT)+1);
810 md5_finish(&md5state2,serversealkey);
814 if (flags & NTLMSSP_NEGOTIATE_128)
816 /* The exportedsessionkey has already the good length just update the length*/
822 if (flags & NTLMSSP_NEGOTIATE_56)
824 memset(clientsealkey+7,0,9);
828 memset(clientsealkey+5,0,11);
829 clientsealkey[5]=0xe5;
830 clientsealkey[6]=0x38;
831 clientsealkey[7]=0xb0;
834 serversealkey = memcpy(serversealkey,clientsealkey,*keylen);
837 /* Create an NTLMSSP version 1 key.
838 * password points to the ANSI password to encrypt, challenge points to
839 * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
840 * otherwise it will do a 40 bit key. The result is stored in
841 * sspkey (expected to be NTLMSSP_KEY_LEN octets)
843 /* dissect a string - header area contains:
846 four byte offset of string in data area
847 The function returns the offset at the end of the string header,
848 but the 'end' parameter returns the offset of the end of the string itself
849 The 'start' parameter returns the offset of the beginning of the string
850 If there's no string, just use the offset of the end of the tvb as start/end.
853 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
854 proto_tree *ntlmssp_tree,
855 gboolean unicode_strings,
856 int string_hf, int *start, int *end,
857 const char **stringp)
859 proto_tree *tree = NULL;
860 proto_item *tf = NULL;
861 gint16 string_length = tvb_get_letohs(tvb, offset);
862 gint16 string_maxlen = tvb_get_letohs(tvb, offset+2);
863 gint32 string_offset = tvb_get_letohl(tvb, offset+4);
864 const char *string_text = NULL;
868 *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
869 if (0 == string_length) {
872 proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
879 bc = result_length = string_length;
880 string_text = get_unicode_or_ascii_string(tvb, &string_offset,
881 unicode_strings, &result_length,
884 if (stringp != NULL) {
885 if (!string_text) string_text = ""; /* Make sure we don't blow up later */
887 *stringp = string_text;
891 tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
892 string_offset, result_length, string_text);
893 tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
895 proto_tree_add_uint(tree, hf_ntlmssp_string_len,
896 tvb, offset, 2, string_length);
898 proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
899 tvb, offset, 2, string_maxlen);
901 proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
902 tvb, offset, 4, string_offset);
905 *end = string_offset + string_length;
909 /* dissect a generic blob - header area contains:
912 four byte offset of blob in data area
913 The function returns the offset at the end of the blob header,
914 but the 'end' parameter returns the offset of the end of the blob itself
917 dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
918 proto_tree *ntlmssp_tree,
919 int blob_hf, int *end, ntlmssp_blob *result)
921 proto_item *tf = NULL;
922 proto_tree *tree = NULL;
923 guint16 blob_length = tvb_get_letohs(tvb, offset);
924 guint16 blob_maxlen = tvb_get_letohs(tvb, offset+2);
925 guint32 blob_offset = tvb_get_letohl(tvb, offset+4);
926 if (0 == blob_length) {
927 *end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
929 proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
930 proto_registrar_get_name(blob_hf));
935 tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
936 blob_offset, blob_length, FALSE);
937 tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
939 proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
940 tvb, offset, 2, blob_length);
942 proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
943 tvb, offset, 2, blob_maxlen);
945 proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
946 tvb, offset, 4, blob_offset);
949 *end = blob_offset + blob_length;
951 if (result != NULL) {
952 result->length = blob_length;
953 memset(result->contents, 0, MAX_BLOB_SIZE);
954 if (blob_length < MAX_BLOB_SIZE)
956 tvb_memcpy(tvb, result->contents, blob_offset, blob_length);
957 if (blob_hf == hf_ntlmssp_auth_lmresponse && !(memcmp(tvb->real_data+blob_offset+8,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",NTLMSSP_KEY_LEN)))
959 proto_tree_add_item (ntlmssp_tree,
960 hf_ntlmssp_ntlm_client_challenge,
961 tvb, blob_offset, 8, FALSE);
966 /* If we are dissecting the NTLM response and it is a NTLMv2
967 response call the appropriate dissector. */
969 if (blob_hf == hf_ntlmssp_auth_ntresponse && blob_length > 24)
971 proto_tree_add_item (ntlmssp_tree,
972 hf_ntlmssp_ntlm_client_challenge,
973 tvb, blob_offset+32, 8, FALSE);
974 dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
981 dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
982 proto_tree *ntlmssp_tree,
983 guint32 negotiate_flags)
985 proto_tree *negotiate_flags_tree = NULL;
986 proto_item *tf = NULL;
989 tf = proto_tree_add_uint (ntlmssp_tree,
990 hf_ntlmssp_negotiate_flags,
991 tvb, offset, 4, negotiate_flags);
992 negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
995 proto_tree_add_boolean (negotiate_flags_tree,
996 hf_ntlmssp_negotiate_flags_80000000,
997 tvb, offset, 4, negotiate_flags);
998 proto_tree_add_boolean (negotiate_flags_tree,
999 hf_ntlmssp_negotiate_flags_40000000,
1000 tvb, offset, 4, negotiate_flags);
1001 proto_tree_add_boolean (negotiate_flags_tree,
1002 hf_ntlmssp_negotiate_flags_20000000,
1003 tvb, offset, 4, negotiate_flags);
1004 proto_tree_add_boolean (negotiate_flags_tree,
1005 hf_ntlmssp_negotiate_flags_10000000,
1006 tvb, offset, 4, negotiate_flags);
1007 proto_tree_add_boolean (negotiate_flags_tree,
1008 hf_ntlmssp_negotiate_flags_8000000,
1009 tvb, offset, 4, negotiate_flags);
1010 proto_tree_add_boolean (negotiate_flags_tree,
1011 hf_ntlmssp_negotiate_flags_4000000,
1012 tvb, offset, 4, negotiate_flags);
1013 proto_tree_add_boolean (negotiate_flags_tree,
1014 hf_ntlmssp_negotiate_flags_2000000,
1015 tvb, offset, 4, negotiate_flags);
1016 proto_tree_add_boolean (negotiate_flags_tree,
1017 hf_ntlmssp_negotiate_flags_1000000,
1018 tvb, offset, 4, negotiate_flags);
1019 proto_tree_add_boolean (negotiate_flags_tree,
1020 hf_ntlmssp_negotiate_flags_800000,
1021 tvb, offset, 4, negotiate_flags);
1022 proto_tree_add_boolean (negotiate_flags_tree,
1023 hf_ntlmssp_negotiate_flags_400000,
1024 tvb, offset, 4, negotiate_flags);
1025 proto_tree_add_boolean (negotiate_flags_tree,
1026 hf_ntlmssp_negotiate_flags_200000,
1027 tvb, offset, 4, negotiate_flags);
1028 proto_tree_add_boolean (negotiate_flags_tree,
1029 hf_ntlmssp_negotiate_flags_100000,
1030 tvb, offset, 4, negotiate_flags);
1031 proto_tree_add_boolean (negotiate_flags_tree,
1032 hf_ntlmssp_negotiate_flags_80000,
1033 tvb, offset, 4, negotiate_flags);
1034 proto_tree_add_boolean (negotiate_flags_tree,
1035 hf_ntlmssp_negotiate_flags_40000,
1036 tvb, offset, 4, negotiate_flags);
1037 proto_tree_add_boolean (negotiate_flags_tree,
1038 hf_ntlmssp_negotiate_flags_20000,
1039 tvb, offset, 4, negotiate_flags);
1040 proto_tree_add_boolean (negotiate_flags_tree,
1041 hf_ntlmssp_negotiate_flags_10000,
1042 tvb, offset, 4, negotiate_flags);
1043 proto_tree_add_boolean (negotiate_flags_tree,
1044 hf_ntlmssp_negotiate_flags_8000,
1045 tvb, offset, 4, negotiate_flags);
1046 proto_tree_add_boolean (negotiate_flags_tree,
1047 hf_ntlmssp_negotiate_flags_4000,
1048 tvb, offset, 4, negotiate_flags);
1049 proto_tree_add_boolean (negotiate_flags_tree,
1050 hf_ntlmssp_negotiate_flags_2000,
1051 tvb, offset, 4, negotiate_flags);
1052 proto_tree_add_boolean (negotiate_flags_tree,
1053 hf_ntlmssp_negotiate_flags_1000,
1054 tvb, offset, 4, negotiate_flags);
1055 proto_tree_add_boolean (negotiate_flags_tree,
1056 hf_ntlmssp_negotiate_flags_800,
1057 tvb, offset, 4, negotiate_flags);
1058 proto_tree_add_boolean (negotiate_flags_tree,
1059 hf_ntlmssp_negotiate_flags_400,
1060 tvb, offset, 4, negotiate_flags);
1061 proto_tree_add_boolean (negotiate_flags_tree,
1062 hf_ntlmssp_negotiate_flags_200,
1063 tvb, offset, 4, negotiate_flags);
1064 proto_tree_add_boolean (negotiate_flags_tree,
1065 hf_ntlmssp_negotiate_flags_100,
1066 tvb, offset, 4, negotiate_flags);
1067 proto_tree_add_boolean (negotiate_flags_tree,
1068 hf_ntlmssp_negotiate_flags_80,
1069 tvb, offset, 4, negotiate_flags);
1070 proto_tree_add_boolean (negotiate_flags_tree,
1071 hf_ntlmssp_negotiate_flags_40,
1072 tvb, offset, 4, negotiate_flags);
1073 proto_tree_add_boolean (negotiate_flags_tree,
1074 hf_ntlmssp_negotiate_flags_20,
1075 tvb, offset, 4, negotiate_flags);
1076 proto_tree_add_boolean (negotiate_flags_tree,
1077 hf_ntlmssp_negotiate_flags_10,
1078 tvb, offset, 4, negotiate_flags);
1079 proto_tree_add_boolean (negotiate_flags_tree,
1080 hf_ntlmssp_negotiate_flags_08,
1081 tvb, offset, 4, negotiate_flags);
1082 proto_tree_add_boolean (negotiate_flags_tree,
1083 hf_ntlmssp_negotiate_flags_04,
1084 tvb, offset, 4, negotiate_flags);
1085 proto_tree_add_boolean (negotiate_flags_tree,
1086 hf_ntlmssp_negotiate_flags_02,
1087 tvb, offset, 4, negotiate_flags);
1088 proto_tree_add_boolean (negotiate_flags_tree,
1089 hf_ntlmssp_negotiate_flags_01,
1090 tvb, offset, 4, negotiate_flags);
1092 return (offset + 4);
1095 /* Dissect "version" */
1098 0 Major Version Number 1 byte
1099 1 Minor Version Number 1 byte
1100 2 Build Number short(LE)
1101 3 (Reserved) 3 bytes
1102 4 NTLM Current Revision 1 byte
1106 dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
1107 proto_tree *ntlmssp_tree)
1111 proto_tree *version_tree;
1112 tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
1113 "Version %u.%u (Build %u); NTLM Current Revision %u",
1114 tvb_get_guint8(tvb, offset),
1115 tvb_get_guint8(tvb, offset+1),
1116 tvb_get_letohs(tvb, offset+2),
1117 tvb_get_guint8(tvb, offset+7));
1118 version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
1119 proto_tree_add_item(version_tree, hf_ntlmssp_version_major , tvb, offset , 1, ENC_NA);
1120 proto_tree_add_item(version_tree, hf_ntlmssp_version_minor , tvb, offset+1, 1, ENC_NA);
1121 proto_tree_add_item(version_tree, hf_ntlmssp_version_build_number , tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1122 proto_tree_add_item(version_tree, hf_ntlmssp_version_ntlm_current_revision, tvb, offset+7, 1, ENC_NA);
1127 /* Dissect a NTLM response. This is documented at
1128 http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
1130 /* Attribute types */
1132 * XXX - the davenport document says that a type of 5 has been seen,
1133 * "apparently containing the 'parent' DNS domain for servers in
1135 * XXX: MS-NLMP info is newer than Davenport info;
1136 * The attribute type list and the attribute names below are
1137 * based upon MS-NLMP.
1140 #define NTLM_TARGET_INFO_END 0x0000
1141 #define NTLM_TARGET_INFO_NB_COMPUTER_NAME 0x0001
1142 #define NTLM_TARGET_INFO_NB_DOMAIN_NAME 0x0002
1143 #define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
1144 #define NTLM_TARGET_INFO_DNS_DOMAIN_NAME 0x0004
1145 #define NTLM_TARGET_INFO_DNS_TREE_NAME 0x0005
1146 #define NTLM_TARGET_INFO_FLAGS 0x0006
1147 #define NTLM_TARGET_INFO_TIMESTAMP 0x0007
1148 #define NTLM_TARGET_INFO_RESTRICTIONS 0x0008
1149 #define NTLM_TARGET_INFO_TARGET_NAME 0x0009
1150 #define NTLM_TARGET_INFO_CHANNEL_BINDINGS 0x000A
1152 static const value_string ntlm_name_types[] = {
1153 { NTLM_TARGET_INFO_END, "End of list" },
1154 { NTLM_TARGET_INFO_NB_COMPUTER_NAME, "NetBIOS computer name" },
1155 { NTLM_TARGET_INFO_NB_DOMAIN_NAME, "NetBIOS domain name" },
1156 { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
1157 { NTLM_TARGET_INFO_DNS_DOMAIN_NAME, "DNS domain name" },
1158 { NTLM_TARGET_INFO_DNS_TREE_NAME, "DNS tree name" },
1159 { NTLM_TARGET_INFO_FLAGS, "Flags" },
1160 { NTLM_TARGET_INFO_TIMESTAMP, "Timestamp" },
1161 { NTLM_TARGET_INFO_RESTRICTIONS, "Restrictions" },
1162 { NTLM_TARGET_INFO_TARGET_NAME, "Target Name"},
1163 { NTLM_TARGET_INFO_CHANNEL_BINDINGS, "Channel Bindings"},
1167 /* The following *must* match the order of the list of attribute types */
1168 /* Assumption: values in the list are a sequence starting with 0 and */
1169 /* with no gaps allowing a direct access of the array by attribute type */
1170 static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
1171 &hf_ntlmssp_challenge_target_info_end,
1172 &hf_ntlmssp_challenge_target_info_nb_computer_name,
1173 &hf_ntlmssp_challenge_target_info_nb_domain_name,
1174 &hf_ntlmssp_challenge_target_info_dns_computer_name,
1175 &hf_ntlmssp_challenge_target_info_dns_domain_name,
1176 &hf_ntlmssp_challenge_target_info_dns_tree_name,
1177 &hf_ntlmssp_challenge_target_info_flags,
1178 &hf_ntlmssp_challenge_target_info_timestamp,
1179 &hf_ntlmssp_challenge_target_info_restrictions,
1180 &hf_ntlmssp_challenge_target_info_target_name,
1181 &hf_ntlmssp_challenge_target_info_channel_bindings
1184 static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
1185 &hf_ntlmssp_ntlmv2_response_end,
1186 &hf_ntlmssp_ntlmv2_response_nb_computer_name,
1187 &hf_ntlmssp_ntlmv2_response_nb_domain_name,
1188 &hf_ntlmssp_ntlmv2_response_dns_computer_name,
1189 &hf_ntlmssp_ntlmv2_response_dns_domain_name,
1190 &hf_ntlmssp_ntlmv2_response_dns_tree_name,
1191 &hf_ntlmssp_ntlmv2_response_flags,
1192 &hf_ntlmssp_ntlmv2_response_timestamp,
1193 &hf_ntlmssp_ntlmv2_response_restrictions,
1194 &hf_ntlmssp_ntlmv2_response_target_name,
1195 &hf_ntlmssp_ntlmv2_response_channel_bindings
1198 typedef struct _tif {
1201 int *hf_item_length;
1202 int **hf_attr_array_p;
1205 static tif_t ntlmssp_challenge_target_info_tif = {
1206 &ett_ntlmssp_challenge_target_info_item,
1207 &hf_ntlmssp_challenge_target_info_item_type,
1208 &hf_ntlmssp_challenge_target_info_item_len,
1209 ntlmssp_hf_challenge_target_info_hf_ptr_array
1212 static tif_t ntlmssp_ntlmv2_response_tif = {
1213 &ett_ntlmssp_ntlmv2_response_item,
1214 &hf_ntlmssp_ntlmv2_response_item_type,
1215 &hf_ntlmssp_ntlmv2_response_item_len,
1216 ntlmssp_hf_ntlmv2_response_hf_ptr_array
1220 dissect_ntlmssp_target_info_list(tvbuff_t *tvb, proto_tree *tree,
1221 guint32 target_info_offset, guint16 target_info_length,
1224 guint32 item_offset;
1226 guint16 item_length;
1229 /* Now enumerate through the individual items in the list */
1230 item_offset = target_info_offset;
1232 while (item_offset < (target_info_offset + target_info_length)) {
1233 proto_item *target_info_tf;
1234 proto_tree *target_info_tree;
1235 guint32 content_offset;
1236 guint16 content_length;
1237 guint32 type_offset;
1240 int **hf_array_p = tif_p->hf_attr_array_p;
1243 type_offset = item_offset;
1244 item_type = tvb_get_letohs(tvb, type_offset);
1246 /* Content length */
1247 len_offset = type_offset + 2;
1248 content_length = tvb_get_letohs(tvb, len_offset);
1251 content_offset = len_offset + 2;
1252 item_length = content_length + 4;
1254 target_info_tf = proto_tree_add_text(tree, tvb, item_offset, item_length, "Attribute: %s",
1255 val_to_str(item_type, ntlm_name_types, "Unknown (%d)"));
1257 target_info_tree = proto_item_add_subtree (target_info_tf, *tif_p->ett);
1258 proto_tree_add_item (target_info_tree, *tif_p->hf_item_type, tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
1259 proto_tree_add_item (target_info_tree, *tif_p->hf_item_length, tvb, len_offset, 2, ENC_LITTLE_ENDIAN);
1262 case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
1263 case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
1264 case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
1265 case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
1266 case NTLM_TARGET_INFO_DNS_TREE_NAME:
1267 case NTLM_TARGET_INFO_TARGET_NAME:
1268 if (content_length > 0) {
1271 text = tvb_get_ephemeral_faked_unicode(tvb, content_offset, content_length / 2, TRUE);
1272 proto_tree_add_string(target_info_tree, *hf_array_p[item_type],
1273 tvb, content_offset, content_length, text);
1274 proto_item_append_text(target_info_tf, ": %s", text);
1278 case NTLM_TARGET_INFO_FLAGS:
1279 proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
1280 tvb, content_offset, content_length, ENC_LITTLE_ENDIAN);
1283 case NTLM_TARGET_INFO_TIMESTAMP:
1284 dissect_nt_64bit_time(tvb, target_info_tree, content_offset, *hf_array_p[item_type]);
1287 case NTLM_TARGET_INFO_RESTRICTIONS:
1288 case NTLM_TARGET_INFO_CHANNEL_BINDINGS:
1289 proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
1290 tvb, content_offset, content_length, ENC_NA);
1297 item_offset += item_length;
1302 dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
1304 proto_item *ntlmv2_item = NULL;
1305 proto_tree *ntlmv2_tree = NULL;
1308 /* Dissect NTLMv2 bits&pieces */
1309 orig_offset = offset;
1312 ntlmv2_item = proto_tree_add_item(
1313 tree, hf_ntlmssp_ntlmv2_response, tvb,
1315 ntlmv2_tree = proto_item_add_subtree(
1316 ntlmv2_item, ett_ntlmssp_ntlmv2_response);
1319 proto_tree_add_item(
1320 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hmac, tvb,
1325 proto_tree_add_item(
1326 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_header, tvb,
1331 proto_tree_add_item(
1332 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_reserved, tvb,
1337 offset = dissect_nt_64bit_time(
1338 tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time);
1340 proto_tree_add_item(
1341 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
1346 proto_tree_add_item(
1347 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_unknown, tvb,
1352 /* Variable length list of attributes */
1354 * XXX - Windows puts one or more sets of 4 bytes of additional stuff (all zeros ?)
1355 * at the end of the attributes.
1356 * Samba's smbclient doesn't.
1357 * Both of them appear to be able to connect to W2K SMB
1359 * The additional stuff will be dissected as extra "end" attributes.
1362 dissect_ntlmssp_target_info_list(tvb, ntlmv2_tree,
1363 offset, len - (offset - orig_offset),
1364 &ntlmssp_ntlmv2_response_tif);
1369 /* tapping into ntlmssph not yet implemented */
1371 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1373 guint32 negotiate_flags;
1379 /* NTLMSSP Negotiate Flags */
1380 negotiate_flags = tvb_get_letohl (tvb, offset);
1381 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1385 * XXX - the davenport document says that these might not be
1386 * sent at all, presumably meaning the length of the message
1387 * isn't enough to contain them.
1389 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1390 hf_ntlmssp_negotiate_domain,
1391 &data_start, &data_end, NULL);
1393 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1394 hf_ntlmssp_negotiate_workstation,
1395 &item_start, &item_end, NULL);
1396 data_start = MIN(data_start, item_start);
1397 data_end = MAX(data_end, item_end);
1399 /* If there are more bytes before the data block dissect a version field */
1400 if (offset < data_start) {
1401 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1408 dissect_ntlmssp_challenge_target_info_blob (tvbuff_t *tvb, int offset,
1409 proto_tree *ntlmssp_tree,
1412 guint16 challenge_target_info_length = tvb_get_letohs(tvb, offset);
1413 guint16 challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
1414 guint32 challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
1415 proto_item *tf = NULL;
1416 proto_tree *challenge_target_info_tree = NULL;
1418 /* the target info list is just a blob */
1419 if (0 == challenge_target_info_length) {
1420 *end = (challenge_target_info_offset > ((guint)offset)+8 ? challenge_target_info_offset : ((guint)offset)+8);
1422 proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
1423 "Target Info List: Empty");
1428 tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
1429 challenge_target_info_offset, challenge_target_info_length, FALSE);
1430 challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
1432 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
1433 tvb, offset, 2, challenge_target_info_length);
1435 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
1436 tvb, offset, 2, challenge_target_info_maxlen);
1438 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
1439 tvb, offset, 4, challenge_target_info_offset);
1442 dissect_ntlmssp_target_info_list(tvb, challenge_target_info_tree,
1443 challenge_target_info_offset, challenge_target_info_length,
1444 &ntlmssp_challenge_target_info_tif);
1446 *end = challenge_target_info_offset + challenge_target_info_length;
1450 /* tapping into ntlmssph not yet implemented */
1452 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
1453 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1455 guint32 negotiate_flags;
1456 int item_start, item_end;
1457 int data_start, data_end; /* MIN and MAX seen */
1458 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1459 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1460 ntlmssp_info *conv_ntlmssp_info = NULL;
1461 conversation_t *conversation;
1462 gboolean unicode_strings = FALSE;
1463 guint8 challenge[8];
1465 guint8 sspkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key */
1466 int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
1468 /* need to find unicode flag */
1469 negotiate_flags = tvb_get_letohl (tvb, offset+8);
1470 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
1471 unicode_strings = TRUE;
1475 * XXX - the davenport document (and MS-NLMP) calls this "Target Name",
1476 * presumably because non-domain targets are supported.
1477 * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
1479 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
1480 hf_ntlmssp_challenge_target_name,
1481 &item_start, &item_end, NULL);
1482 data_start = item_start;
1483 data_end = item_end;
1485 /* NTLMSSP Negotiate Flags */
1486 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1489 /* NTLMSSP NT Lan Manager Challenge */
1490 proto_tree_add_item (ntlmssp_tree,
1491 hf_ntlmssp_ntlm_server_challenge,
1492 tvb, offset, 8, FALSE);
1495 * Store the flags and the RC4 state information with the conversation,
1496 * as they're needed in order to dissect subsequent messages.
1498 conversation = find_or_create_conversation(pinfo);
1500 tvb_memcpy(tvb, tmp, offset, 8); /* challenge */
1501 /* We can face more than one NTLM exchange over the same couple of IP and ports ...*/
1502 conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
1503 /* XXX: The following code is (re)executed every time a particular frame is dissected
1504 * (in whatever order). Thus it seems to me that "multiple exchanges" might not be
1505 * handled well depending on the order that frames are visited after the initial dissection.
1507 if (!conv_ntlmssp_info || memcmp(tmp,conv_ntlmssp_info->server_challenge,8) != 0) {
1508 conv_ntlmssp_info = se_alloc(sizeof(ntlmssp_info));
1509 /* Insert the flags into the conversation */
1510 conv_ntlmssp_info->flags = negotiate_flags;
1511 /* Insert the RC4 state information into the conversation */
1512 tvb_memcpy(tvb, challenge, offset, 8);
1513 tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
1514 conv_ntlmssp_info->is_auth_ntlm_v2=0;
1515 /* Between the challenge and the user provided password, we can build the
1516 NTLMSSP key and initialize the cipher if we are not in EXTENDED SECURITY
1517 in this case we need the client challenge as well*/
1518 /* BTW this is true just if we are in LM Authentification if not the logic is a bit different.
1519 * Right now it's not very clear what is LM Authentification it __seems__ to be when
1520 * NEGOTIATE NT ONLY is not set and NEGOSIATE EXTENDED SECURITY is not set as well*/
1521 if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1523 conv_ntlmssp_info->rc4_state_initialized = 0;
1524 create_ntlmssp_v1_key(gbl_nt_password, conv_ntlmssp_info->server_challenge,NULL, sspkey,NULL,conv_ntlmssp_info->flags,conv_ntlmssp_info->ntlm_response.contents,conv_ntlmssp_info->lm_response.contents);
1525 if( memcmp(sspkey,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
1526 get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
1527 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, sspkey, ssp_key_len);
1528 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, sspkey, ssp_key_len);
1529 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1530 conv_ntlmssp_info->rc4_state_initialized = 1;
1534 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1538 /* If no more bytes (ie: no "reserved", ...) before start of data block, then return */
1539 /* XXX: According to Davenport "This form is seen in older Win9x-based systems" */
1540 /* Also: I've seen a capture with an HTTP CONNECT proxy-authentication */
1541 /* message wherein the challenge from the proxy has this form. */
1542 if (offset >= data_start) {
1546 /* Reserved (function not completely known) */
1548 * XXX - SSP key? The davenport document says
1550 * The context field is typically populated when Negotiate Local
1551 * Call is set. It contains an SSPI context handle, which allows
1552 * the client to "short-circuit" authentication and effectively
1553 * circumvent responding to the challenge. Physically, the context
1554 * is two long values. This is covered in greater detail later,
1555 * in the "Local Authentication" section.
1557 * It also says that that information may be omitted.
1559 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
1560 tvb, offset, 8, FALSE);
1564 * The presence or absence of this field is not obviously correlated
1565 * with any flags in the previous NEGOTIATE message or in this
1566 * message (other than the "Workstation Supplied" and "Domain
1567 * Supplied" flags in the NEGOTIATE message, at least in the capture
1568 * I've seen - but those also correlate with the presence of workstation
1569 * and domain name fields, so it doesn't seem to make sense that they
1570 * actually *indicate* whether the subsequent CHALLENGE has an
1573 if (offset < data_start) {
1574 offset = dissect_ntlmssp_challenge_target_info_blob(tvb, offset, ntlmssp_tree, &item_end);
1575 /* XXX: This code assumes that the address list in the data block */
1576 /* is always after the target name. Is this OK ? */
1577 data_end = MAX(data_end, item_end);
1580 /* If there are more bytes before the data block dissect a version field */
1581 if (offset < data_start) {
1582 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1585 return MAX(offset, data_end);
1589 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
1590 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
1592 int item_start, item_end;
1593 int data_start, data_end = 0;
1594 guint32 negotiate_flags;
1595 guint8 sspkey[NTLMSSP_KEY_LEN]; /* exported session key */
1596 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1597 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1598 guint8 encryptedsessionkey[NTLMSSP_KEY_LEN];
1599 ntlmssp_blob sessionblob;
1600 gboolean unicode_strings = FALSE;
1601 ntlmssp_info *conv_ntlmssp_info = NULL;
1602 conversation_t *conversation;
1605 * Get flag info from the original negotiate message, if any.
1606 * This is because the flag information is sometimes missing from
1607 * the AUTHENTICATE message, so we can't figure out whether
1608 * strings are Unicode or not by looking at *our* flags.
1609 * XXX it seems it's more from the CHALLENGE message, which is more clever in fact
1610 * because the server can change some flags.
1611 * But according to MS NTLMSSP doc it's not that simple.
1612 * In case of Conection less mode AUTHENTICATE flags should be used because they
1613 * reprensent the choice of the client after having been informed of options of the
1614 * server in the CHALLENGE message.
1615 * In Connection mode then the CHALLENGE flags should (must ?) be used
1616 * XXX: MS-NLMP says the flag field in the AUTHENTICATE message "contains the set of bit
1617 * flags (section 2.2.2.5) negotiated in the previous messages."
1618 * I read that to mean that the flags for in connection-mode AUTHENTICATE also represent
1619 * the choice of the client (for the flags which are negotiated).
1620 * XXX: In the absence of CHALLENGE flags, as a last resort we'll use the flags
1621 * (if available) from this AUTHENTICATE message.
1622 * I've seen a capture which does an HTTP CONNECT which:
1623 * - has the NEGOTIATE & CHALLENGE messages in one TCP connection;
1624 * - has the AUTHENTICATE message in a second TCP connection;
1625 * (The authentication aparently succeeded).
1627 conv_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
1628 if (conv_ntlmssp_info == NULL) {
1630 * There isn't any. Is there any from this conversation? If so,
1631 * it means this is the first time we've dissected this frame, so
1632 * we should give it flag info.
1634 /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
1635 /* so we'll have a place to store flags. */
1636 /* This is a bit brute-force but looks like it will be OK. */
1637 conversation = find_or_create_conversation(pinfo);
1638 conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
1639 if (conv_ntlmssp_info == NULL) {
1640 conv_ntlmssp_info = se_alloc0(sizeof(ntlmssp_info));
1641 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1643 /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
1644 same as the one attached to the conversation. That is: *both* point to
1645 the exact same struct in memory. Is this what is indended ? */
1646 p_add_proto_data(pinfo->fd, proto_ntlmssp, conv_ntlmssp_info);
1649 if (conv_ntlmssp_info != NULL) {
1650 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
1651 unicode_strings = TRUE;
1655 * Sometimes the session key and flags are missing.
1656 * Sometimes the session key is present but the flags are missing.
1657 * XXX Who stay so ? Reading spec I would rather say the opposite: flags are
1658 * always present, session information are always there as well but sometime
1659 * session information could be null (in case of no session)
1660 * Sometimes they're both present.
1662 * This does not correlate with any flags in the previous CHALLENGE
1663 * message, and only correlates with "Negotiate Unicode", "Workstation
1664 * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
1665 * those don't make sense as flags to use to determine this.
1667 * So we check all of the descriptors to figure out where the data
1668 * area begins, and if the session key or the flags would be in the
1669 * middle of the data area, we assume the field in question is
1672 * XXX - Reading Davenport and MS-NLMP: as I see it the possibilities are:
1673 * a. No session-key; no flags; no version ("Win9x")
1674 * b. Session-key & flags.
1675 * c. Session-key, flags & version.
1676 * In cases b and c the session key may be "null".
1680 /* Lan Manager response */
1681 data_start = tvb_get_letohl(tvb, offset+4);
1682 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1683 hf_ntlmssp_auth_lmresponse,
1685 conv_ntlmssp_info == NULL ? NULL :
1686 &conv_ntlmssp_info->lm_response);
1687 data_end = MAX(data_end, item_end);
1690 item_start = tvb_get_letohl(tvb, offset+4);
1691 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1692 hf_ntlmssp_auth_ntresponse,
1694 conv_ntlmssp_info == NULL ? NULL :
1695 &conv_ntlmssp_info->ntlm_response);
1696 if( conv_ntlmssp_info != NULL && conv_ntlmssp_info->ntlm_response.length > 24 ) {
1697 memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->ntlm_response.contents+32,8);
1699 data_start = MIN(data_start, item_start);
1700 data_end = MAX(data_end, item_end);
1701 if( conv_ntlmssp_info != NULL )
1703 if( conv_ntlmssp_info->ntlm_response.length > 24 )
1705 conv_ntlmssp_info->is_auth_ntlm_v2=1;
1709 conv_ntlmssp_info->is_auth_ntlm_v2=0;
1714 item_start = tvb_get_letohl(tvb, offset+4);
1715 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1717 hf_ntlmssp_auth_domain,
1718 &item_start, &item_end, &(ntlmssph->domain_name));
1719 /*ntlmssph->domain_name_len=item_end-item_start;*/
1720 data_start = MIN(data_start, item_start);
1721 data_end = MAX(data_end, item_end);
1724 item_start = tvb_get_letohl(tvb, offset+4);
1725 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1727 hf_ntlmssp_auth_username,
1728 &item_start, &item_end, &(ntlmssph->acct_name));
1729 /*ntlmssph->acct_name_len=item_end-item_start;*/
1730 data_start = MIN(data_start, item_start);
1731 data_end = MAX(data_end, item_end);
1733 if (check_col(pinfo->cinfo, COL_INFO))
1734 col_append_fstr(pinfo->cinfo, COL_INFO, ", User: %s\\%s",
1735 ntlmssph->domain_name, ntlmssph->acct_name);
1738 item_start = tvb_get_letohl(tvb, offset+4);
1739 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1741 hf_ntlmssp_auth_hostname,
1742 &item_start, &item_end, &(ntlmssph->host_name));
1743 data_start = MIN(data_start, item_start);
1744 data_end = MAX(data_end, item_end);
1746 memset(sessionblob.contents, 0, MAX_BLOB_SIZE);
1747 sessionblob.length = 0;
1748 if (offset < data_start) {
1750 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1751 hf_ntlmssp_auth_sesskey,
1752 &item_end, &sessionblob);
1753 data_end = MAX(data_end, item_end);
1756 if (offset < data_start) {
1757 /* NTLMSSP Negotiate Flags */
1758 negotiate_flags = tvb_get_letohl (tvb, offset);
1759 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1761 /* If no previous flags seen (ie: no previous CHALLENGE) use flags
1762 from the AUTHENTICATE message).
1763 Assumption: (flags == 0) means flags not previously seen */
1764 if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
1765 conv_ntlmssp_info->flags = negotiate_flags;
1769 /* If there are more bytes before the data block dissect a version field */
1770 if (offset < data_start) {
1771 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1774 /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
1776 if (offset < data_start) {
1777 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_message_integrity_code, tvb, offset, 16, ENC_NA);
1781 if ( sessionblob.length > NTLMSSP_KEY_LEN ) {
1782 expert_add_info_format(pinfo, NULL, PI_WARN, PI_UNDECODED, "Session blob length too long: %u", sessionblob.length);
1783 } else if( sessionblob.length != 0 ) {
1784 memcpy(encryptedsessionkey,sessionblob.contents,sessionblob.length);
1785 /* Try to attach to an existing conversation if not then it's useless to try to do so
1786 * because we are missing important information (ie. server challenge)
1788 if (conv_ntlmssp_info) {
1789 /* If we are in EXTENDED SECURITY then we can now initialize cipher */
1790 if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1792 conv_ntlmssp_info->rc4_state_initialized = 0;
1793 if( conv_ntlmssp_info->is_auth_ntlm_v2 ) {
1794 create_ntlmssp_v2_key(gbl_nt_password, conv_ntlmssp_info->server_challenge,conv_ntlmssp_info->client_challenge, sspkey,encryptedsessionkey,conv_ntlmssp_info->flags,conv_ntlmssp_info->ntlm_response,conv_ntlmssp_info->lm_response,ntlmssph);
1798 memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->lm_response.contents,8);
1799 create_ntlmssp_v1_key(gbl_nt_password, conv_ntlmssp_info->server_challenge,conv_ntlmssp_info->client_challenge, sspkey,encryptedsessionkey,conv_ntlmssp_info->flags,conv_ntlmssp_info->ntlm_response.contents,conv_ntlmssp_info->lm_response.contents);
1801 /* ssp is the exported session key */
1802 if( memcmp(sspkey,gbl_zeros,NTLMSSP_KEY_LEN) != 0) {
1803 get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
1804 get_siging_key((guint8*)&conv_ntlmssp_info->sign_key_server,(guint8*)&conv_ntlmssp_info->sign_key_client,sspkey,ssp_key_len);
1805 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, serverkey, ssp_key_len);
1806 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, clientkey, ssp_key_len);
1807 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1808 conv_ntlmssp_info->rc4_state_initialized = 1;
1813 return MAX(offset, data_end);
1816 get_sign_key(packet_info *pinfo, int cryptpeer)
1818 conversation_t *conversation;
1819 ntlmssp_info *conv_ntlmssp_info;
1821 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1822 pinfo->ptype, pinfo->srcport,
1823 pinfo->destport, 0);
1824 if (conversation == NULL) {
1825 /* We don't have a conversation. In this case, stop processing
1826 because we do not have enough info to decrypt the payload */
1830 /* We have a conversation, check for encryption state */
1831 conv_ntlmssp_info = conversation_get_proto_data(conversation,
1833 if (conv_ntlmssp_info == NULL) {
1834 /* No encryption state tied to the conversation. Therefore, we
1835 cannot decrypt the payload */
1839 /* We have the encryption state in the conversation. So return the
1840 crypt state tied to the requested peer
1842 if (cryptpeer == 1) {
1843 return (guint8*)&conv_ntlmssp_info->sign_key_client;
1845 return (guint8*)&conv_ntlmssp_info->sign_key_server;
1851 * Get the encryption state tied to this conversation. cryptpeer indicates
1852 * whether to retrieve the client key (1) or the server key (0)
1854 static rc4_state_struct *
1855 get_encrypted_state(packet_info *pinfo, int cryptpeer)
1857 conversation_t *conversation;
1858 ntlmssp_info *conv_ntlmssp_info;
1860 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1861 pinfo->ptype, pinfo->srcport,
1862 pinfo->destport, 0);
1863 if (conversation == NULL) {
1864 /* We don't have a conversation. In this case, stop processing
1865 because we do not have enough info to decrypt the payload */
1869 /* We have a conversation, check for encryption state */
1870 conv_ntlmssp_info = conversation_get_proto_data(conversation,
1872 if (conv_ntlmssp_info == NULL) {
1873 /* No encryption state tied to the conversation. Therefore, we
1874 cannot decrypt the payload */
1878 /* We have the encryption state in the conversation. So return the
1879 crypt state tied to the requested peer
1881 if (cryptpeer == 1) {
1882 return &conv_ntlmssp_info->rc4_state_client;
1884 return &conv_ntlmssp_info->rc4_state_server;
1890 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1891 packet_info *pinfo, proto_tree *tree _U_,gpointer key);
1893 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1894 packet_info *pinfo, proto_tree *tree,gpointer key);
1897 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
1898 tvbuff_t *auth_tvb _U_,
1901 dcerpc_auth_info *auth_info _U_)*/
1904 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1906 volatile int offset = 0;
1907 proto_tree *volatile ntlmssp_tree = NULL;
1908 proto_item *tf = NULL;
1910 guint32 encrypted_block_length;
1911 guint8 key[NTLMSSP_KEY_LEN];
1912 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
1914 guint32 ntlm_magic_size = 4;
1915 guint32 ntlm_signature_size = 8;
1916 guint32 ntlm_seq_size = 4;
1917 length = tvb_length (tvb);
1918 /* signature + seq + real payload */
1919 encrypted_block_length = length - ntlm_magic_size;
1921 if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
1922 /* Don't know why this would happen, but if it does, don't even bother
1923 attempting decryption/dissection */
1924 return offset + length;
1927 /* Setup a new tree for the NTLMSSP payload */
1929 tf = proto_tree_add_item (tree,
1931 tvb, offset, -1, FALSE);
1933 ntlmssp_tree = proto_item_add_subtree (tf,
1938 * Catch the ReportedBoundsError exception; the stuff we've been
1939 * handed doesn't necessarily run to the end of the packet, it's
1940 * an item inside a packet, so if it happens to be malformed (or
1941 * we, or a dissector we call, has a bug), so that an exception
1942 * is thrown, we want to report the error, but return and let
1943 * our caller dissect the rest of the packet.
1945 * If it gets a BoundsError, we can stop, as there's nothing more
1946 * in the packet after our blob to see, so we just re-throw the
1950 /* Version number */
1951 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
1952 tvb, offset, 4, TRUE);
1955 /* Encrypted body */
1956 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
1957 tvb, offset, ntlm_signature_size + ntlm_seq_size, TRUE);
1958 tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
1959 /* Try to decrypt */
1960 decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree,key);
1961 decrypt_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo, ntlmssp_tree,key);
1962 /* let's try to hook ourselves here */
1965 } CATCH(BoundsError) {
1967 } CATCH(ReportedBoundsError) {
1968 show_reported_bounds_error(tvb, pinfo, tree);
1974 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1975 packet_info *pinfo, proto_tree *tree _U_,gpointer key)
1977 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
1979 conversation_t *conversation;
1980 rc4_state_struct *rc4_state;
1981 rc4_state_struct *rc4_state_peer;
1982 ntlmssp_info *conv_ntlmssp_info = NULL;
1983 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
1984 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
1986 /* Check to see if we already have state for this packet */
1987 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
1988 if (packet_ntlmssp_info == NULL) {
1989 /* We don't have any packet state, so create one */
1990 packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
1991 p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
1993 if (!packet_ntlmssp_info->payload_decrypted) {
1994 /* Pull the challenge info from the conversation */
1995 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1996 pinfo->ptype, pinfo->srcport,
1997 pinfo->destport, 0);
1998 if (conversation == NULL) {
1999 /* There is no conversation, thus no encryption state */
2003 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2005 if (conv_ntlmssp_info == NULL) {
2006 /* There is no NTLMSSP state tied to the conversation */
2009 if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
2010 /* The crypto sybsystem is not initialized. This means that either
2011 the conversation did not include a challenge, or that we do not have the right password */
2015 stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
2017 if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == TRUE)
2019 /* Mat TBD (stderr,"Found a already decrypted packet\n");*/
2020 memcpy(packet_ntlmssp_info,stored_packet_ntlmssp_info,sizeof(ntlmssp_packet_info));
2021 /* Mat TBD printnbyte(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"Data: ","\n");*/
2025 /* Get the pair of RC4 state structures. One is used for to decrypt the
2026 payload. The other is used to re-encrypt the payload to represent
2028 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2030 rc4_state = get_encrypted_state(pinfo, 1);
2031 rc4_state_peer = get_encrypted_state(pinfo, 0);
2034 rc4_state = get_encrypted_state(pinfo, 0);
2035 rc4_state_peer = get_encrypted_state(pinfo, 1);
2038 if (rc4_state == NULL ) {
2039 /* There is no encryption state, so we cannot decrypt */
2043 /* Store the decrypted contents in the packet state struct
2044 (of course at this point, they aren't decrypted yet) */
2045 packet_ntlmssp_info->decrypted_payload = tvb_memdup(tvb, offset,
2046 encrypted_block_length);
2047 packet_ntlmssp_info->payload_len = encrypted_block_length;
2048 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2049 packet_ntlmssp_info->decrypted_payload);
2051 g_hash_table_insert(hash_packet,key,packet_ntlmssp_info);
2054 /* Do the decryption of the payload */
2055 crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
2056 encrypted_block_length);
2057 /* decrypt the verifier */
2058 /*printnchar(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"data: ","\n");*/
2059 /* We setup a temporary buffer so we can re-encrypt the payload after
2060 decryption. This is to update the opposite peer's RC4 state
2061 it's usefull when we have only one key for both conversation
2062 in case of KEY_EXCH we have independant key so this is not needed*/
2063 if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2064 peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2065 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2068 packet_ntlmssp_info->payload_decrypted = TRUE;
2072 /* Show the decrypted buffer in a new window */
2073 decr_tvb = tvb_new_real_data(packet_ntlmssp_info->decrypted_payload,
2074 encrypted_block_length,
2075 encrypted_block_length);
2077 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2078 pinfo->gssapi_decrypted_tvb = decr_tvb;
2081 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2083 volatile int offset = 0;
2084 proto_tree *volatile ntlmssp_tree = NULL;
2085 proto_item *tf = NULL;
2086 ntlmssp_header_t *ntlmssph;
2088 ntlmssph=ep_alloc(sizeof(ntlmssp_header_t));
2090 ntlmssph->domain_name=NULL;
2091 ntlmssph->acct_name=NULL;
2092 ntlmssph->host_name=NULL;
2094 /* Setup a new tree for the NTLMSSP payload */
2096 tf = proto_tree_add_item (tree,
2098 tvb, offset, -1, FALSE);
2100 ntlmssp_tree = proto_item_add_subtree (tf,
2105 * Catch the ReportedBoundsError exception; the stuff we've been
2106 * handed doesn't necessarily run to the end of the packet, it's
2107 * an item inside a packet, so if it happens to be malformed (or
2108 * we, or a dissector we call, has a bug), so that an exception
2109 * is thrown, we want to report the error, but return and let
2110 * our caller dissect the rest of the packet.
2112 * If it gets a BoundsError, we can stop, as there's nothing more
2113 * in the packet after our blob to see, so we just re-throw the
2117 /* NTLMSSP constant */
2118 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
2119 tvb, offset, 8, FALSE);
2122 /* NTLMSSP Message Type */
2123 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
2124 tvb, offset, 4, TRUE);
2125 ntlmssph->type = tvb_get_letohl (tvb, offset);
2128 if (check_col(pinfo->cinfo, COL_INFO))
2129 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2130 val_to_str(ntlmssph->type,
2131 ntlmssp_message_types,
2132 "Unknown message type"));
2134 /* Call the appropriate dissector based on the Message Type */
2135 switch (ntlmssph->type) {
2137 case NTLMSSP_NEGOTIATE:
2138 offset = dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree, ntlmssph);
2141 case NTLMSSP_CHALLENGE:
2142 offset = dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2146 offset = dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2150 /* Unrecognized message type */
2151 proto_tree_add_text (ntlmssp_tree, tvb, offset, -1,
2152 "Unrecognized NTLMSSP Message");
2155 } CATCH(BoundsError) {
2157 } CATCH(ReportedBoundsError) {
2158 show_reported_bounds_error(tvb, pinfo, tree);
2161 /*tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);*/
2167 * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
2170 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
2171 packet_info *pinfo, proto_tree *tree,gpointer key)
2173 proto_tree *decr_tree = NULL;
2174 proto_item *tf = NULL;
2175 conversation_t *conversation;
2177 rc4_state_struct *rc4_state;
2178 rc4_state_struct *rc4_state_peer;
2179 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2182 guint8 calculated_md5[NTLMSSP_KEY_LEN];
2183 ntlmssp_info *conv_ntlmssp_info = NULL;
2184 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2185 int decrypted_offset = 0;
2188 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2189 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2190 if (packet_ntlmssp_info == NULL) {
2191 /* We don't have data for this packet */
2194 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2195 pinfo->ptype, pinfo->srcport,
2196 pinfo->destport, 0);
2197 if (conversation == NULL) {
2198 /* There is no conversation, thus no encryption state */
2201 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2203 if (conv_ntlmssp_info == NULL) {
2204 /* There is no NTLMSSP state tied to the conversation */
2209 stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
2211 if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->verifier_decrypted == TRUE) {
2212 /* Mat TBD fprintf(stderr,"Found a already decrypted packet\n");*/
2213 /* In Theory it's aleady the case, and we should be more clever ... like just copying buffers ...*/
2214 packet_ntlmssp_info = stored_packet_ntlmssp_info;
2217 if (!packet_ntlmssp_info->verifier_decrypted) {
2218 if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
2219 /* The crypto sybsystem is not initialized. This means that either
2220 the conversation did not include a challenge, or we are doing
2221 something other than NTLMSSP v1 */
2224 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2225 /* client talk to server */
2226 rc4_state = get_encrypted_state(pinfo, 1);
2227 sign_key = get_sign_key(pinfo,1);
2228 rc4_state_peer = get_encrypted_state(pinfo, 0);
2230 rc4_state = get_encrypted_state(pinfo, 0);
2231 sign_key = get_sign_key(pinfo,0);
2232 rc4_state_peer = get_encrypted_state(pinfo, 1);
2235 if (rc4_state == NULL || rc4_state_peer == NULL) {
2236 /* There is no encryption state, so we cannot decrypt */
2240 /* Setup the buffer to decrypt to */
2241 tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
2242 offset, encrypted_block_length);
2244 /*if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
2245 if( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
2246 if( (NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2247 /* The spec says that if we have have a key exchange then we have a the signature that is crypted
2248 * otherwise it's just a hmac_md5(keysign,concat(message,sequence))[0..7]
2250 crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
2254 * Try to check the HMAC MD5 of the message against those calculated works great with LDAP payload but
2255 * don't with DCE/RPC calls.
2256 * Some analysis need to be done ...
2258 if( sign_key != NULL ) {
2259 check_buf = ep_alloc(packet_ntlmssp_info->payload_len+4);
2260 tvb_memcpy(tvb, &sequence,offset+8,4);
2261 memcpy(check_buf,&sequence,4);
2262 memcpy(check_buf+4,packet_ntlmssp_info->decrypted_payload,packet_ntlmssp_info->payload_len);
2263 md5_hmac(check_buf,(int)(packet_ntlmssp_info->payload_len+4),sign_key,NTLMSSP_KEY_LEN,calculated_md5);
2265 printnbyte(packet_ntlmssp_info->verifier,8,"HMAC from packet: ","\n");
2266 printnbyte(calculated_md5,8,"HMAC : ","\n");
2271 /* The packet has a PAD then a checksum then a sequence and they are encoded in this order so we can decrypt all at once */
2272 /* Do the actual decryption of the verifier */
2273 crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
2274 encrypted_block_length);
2279 /* We setup a temporary buffer so we can re-encrypt the payload after
2280 decryption. This is to update the opposite peer's RC4 state
2281 This is not needed when we just have EXTENDED SECURITY because the signature is not crypted
2282 and it's also not needed when we have key exchange because server and client have independant keys */
2283 if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SECURITY & conv_ntlmssp_info->flags)) {
2284 peer_block = ep_memdup(packet_ntlmssp_info->verifier, encrypted_block_length);
2285 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2288 /* Mark the packet as decrypted so that subsequent attempts to dissect
2289 the packet use the already decrypted payload instead of attempting
2291 packet_ntlmssp_info->verifier_decrypted = TRUE;
2294 /* Show the decrypted buffer in a new window */
2295 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
2296 encrypted_block_length,
2297 encrypted_block_length);
2298 add_new_data_source(pinfo, decr_tvb,
2299 "Decrypted NTLMSSP Verifier");
2301 /* Show the decrypted payload in the tree */
2302 tf = proto_tree_add_text(tree, decr_tvb, 0, -1,
2303 "Decrypted Verifier (%d byte%s)",
2304 encrypted_block_length,
2305 plurality(encrypted_block_length, "", "s"));
2306 decr_tree = proto_item_add_subtree (tf, ett_ntlmssp);
2308 if(( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
2309 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
2310 decr_tvb, decrypted_offset, 8,TRUE);
2311 decrypted_offset += 8;
2315 /* Incrementing sequence number of DCE conversation */
2316 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2317 decr_tvb, decrypted_offset, 4, TRUE);
2318 decrypted_offset += 4;
2322 /* RANDOM PAD usually it's 0 */
2323 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
2324 decr_tvb, decrypted_offset, 4, TRUE);
2325 decrypted_offset += 4;
2327 /* CRC32 of the DCE fragment data */
2328 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
2329 decr_tvb, decrypted_offset, 4, TRUE);
2330 decrypted_offset += 4;
2332 /* Incrementing sequence number of DCE conversation */
2333 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2334 decr_tvb, decrypted_offset, 4, TRUE);
2335 decrypted_offset += 4;
2339 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious*/
2341 dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *tree)
2343 volatile int offset = 0;
2344 proto_tree *volatile ntlmssp_tree = NULL;
2345 guint32 encrypted_block_length;
2346 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
2348 encrypted_block_length = tvb_length (tvb);
2349 /* signature + seq + real payload */
2351 /* Setup a new tree for the NTLMSSP payload */
2354 tf = proto_tree_add_item (tree,
2356 tvb, offset, -1, FALSE);
2358 ntlmssp_tree = proto_item_add_subtree (tf,
2363 * Catch the ReportedBoundsError exception; the stuff we've been
2364 * handed doesn't necessarily run to the end of the packet, it's
2365 * an item inside a packet, so if it happens to be malformed (or
2366 * we, or a dissector we call, has a bug), so that an exception
2367 * is thrown, we want to report the error, but return and let
2368 * our caller dissect the rest of the packet.
2370 * If it gets a BoundsError, we can stop, as there's nothing more
2371 * in the packet after our blob to see, so we just re-throw the
2375 /* Version number */
2377 /* Try to decrypt */
2378 decrypt_data_payload (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
2379 /* let's try to hook ourselves here */
2381 } CATCH(BoundsError) {
2383 } CATCH(ReportedBoundsError) {
2384 show_reported_bounds_error(tvb, pinfo, tree);
2389 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious
2390 * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
2393 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2395 volatile int offset = 0;
2396 proto_tree *volatile ntlmssp_tree = NULL;
2397 proto_item *tf = NULL;
2398 guint32 verifier_length;
2399 guint32 encrypted_block_length;
2401 verifier_length = tvb_length (tvb);
2402 encrypted_block_length = verifier_length - 4;
2404 if (encrypted_block_length < 12) {
2405 /* Don't know why this would happen, but if it does, don't even bother
2406 attempting decryption/dissection */
2407 return offset + verifier_length;
2410 /* Setup a new tree for the NTLMSSP payload */
2412 tf = proto_tree_add_item (tree,
2414 tvb, offset, -1, FALSE);
2416 ntlmssp_tree = proto_item_add_subtree (tf,
2421 * Catch the ReportedBoundsError exception; the stuff we've been
2422 * handed doesn't necessarily run to the end of the packet, it's
2423 * an item inside a packet, so if it happens to be malformed (or
2424 * we, or a dissector we call, has a bug), so that an exception
2425 * is thrown, we want to report the error, but return and let
2426 * our caller dissect the rest of the packet.
2428 * If it gets a BoundsError, we can stop, as there's nothing more
2429 * in the packet after our blob to see, so we just re-throw the
2433 /* Version number */
2434 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2435 tvb, offset, 4, TRUE);
2438 /* Encrypted body */
2439 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2440 tvb, offset, encrypted_block_length, TRUE);
2442 /* Try to decrypt */
2443 decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
2444 /* let's try to hook ourselves here */
2447 offset += encrypted_block_length;
2448 } CATCH(BoundsError) {
2450 } CATCH(ReportedBoundsError) {
2451 show_reported_bounds_error(tvb, pinfo, tree);
2458 wrap_dissect_ntlmssp_payload_only(tvbuff_t *tvb,tvbuff_t *auth_tvb _U_,
2459 int offset, packet_info *pinfo,dcerpc_auth_info *auth_info _U_)
2463 data_tvb = tvb_new_subset(
2464 tvb, offset, tvb_length_remaining(tvb, offset),
2465 tvb_length_remaining(tvb, offset));
2466 dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL);
2467 return pinfo->gssapi_decrypted_tvb;
2472 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
2473 tvbuff_t *auth_tvb _U_,
2476 dcerpc_auth_info *auth_info _U_)
2478 /* gssapi_decrypted_tvb=NULL */
2479 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2481 conversation_t *conversation;
2482 guint32 encrypted_block_length;
2483 rc4_state_struct *rc4_state;
2484 rc4_state_struct *rc4_state_peer;
2485 ntlmssp_info *conv_ntlmssp_info = NULL;
2486 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2487 encrypted_block_length = tvb_length_remaining (data_tvb, offset);
2489 fprintf(stderr,"Called dissect_ntlmssp_encrypted_payload\n");
2490 /* Check to see if we already have state for this packet */
2491 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2492 if (packet_ntlmssp_info == NULL) {
2493 /* We don't have any packet state, so create one */
2494 packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
2495 p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
2498 if (!packet_ntlmssp_info->payload_decrypted) {
2499 /* Pull the challenge info from the conversation */
2500 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2501 pinfo->ptype, pinfo->srcport,
2502 pinfo->destport, 0);
2503 if (conversation == NULL) {
2504 /* There is no conversation, thus no encryption state */
2508 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2510 if (conv_ntlmssp_info == NULL) {
2511 /* There is no NTLMSSP state tied to the conversation */
2514 /* Get the pair of RC4 state structures. One is used for to decrypt the
2515 payload. The other is used to re-encrypt the payload to represent
2517 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2518 rc4_state = get_encrypted_state(pinfo, 1);
2519 rc4_state_peer = get_encrypted_state(pinfo, 0);
2521 rc4_state = get_encrypted_state(pinfo, 0);
2522 rc4_state_peer = get_encrypted_state(pinfo, 1);
2525 if (rc4_state == NULL || rc4_state_peer == NULL) {
2526 /* There is no encryption state, so we cannot decrypt */
2530 /* Store the decrypted contents in the packet state struct
2531 (of course at this point, they aren't decrypted yet) */
2532 packet_ntlmssp_info->decrypted_payload = tvb_memdup(data_tvb, offset,
2533 encrypted_block_length);
2534 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2535 packet_ntlmssp_info->decrypted_payload);
2537 /* Do the decryption of the payload */
2538 crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
2539 encrypted_block_length);
2541 /* We setup a temporary buffer so we can re-encrypt the payload after
2542 decryption. This is to update the opposite peer's RC4 state */
2543 peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2544 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2546 packet_ntlmssp_info->payload_decrypted = TRUE;
2549 /* Show the decrypted buffer in a new window */
2550 decr_tvb = tvb_new_child_real_data(data_tvb, packet_ntlmssp_info->decrypted_payload,
2551 encrypted_block_length,
2552 encrypted_block_length);
2554 offset += encrypted_block_length;
2561 free_payload(gpointer decrypted_payload, gpointer user_data _U_)
2563 g_free(decrypted_payload);
2566 guint g_header_hash(gconstpointer pointer) {
2567 guint32 crc = ~crc32c_calculate(pointer,NTLMSSP_KEY_LEN,CRC32C_PRELOAD);
2568 /* Mat TBD fprintf(stderr,"Val: %u\n",crc);*/
2572 gboolean g_header_equal(gconstpointer pointer1, gconstpointer pointer2) {
2573 if(!memcmp(pointer1,pointer2,16)) {
2582 ntlmssp_init_protocol(void)
2585 * Free the decrypted payloads, and then free the list of decrypted
2588 if (decrypted_payloads != NULL) {
2589 g_slist_foreach(decrypted_payloads, free_payload, NULL);
2590 g_slist_free(decrypted_payloads);
2591 decrypted_payloads = NULL;
2594 if(hash_packet == NULL) {
2595 hash_packet = g_hash_table_new(g_header_hash,g_header_equal);
2603 proto_register_ntlmssp(void)
2606 static hf_register_info hf[] = {
2608 { "NTLMSSP identifier", "ntlmssp.identifier", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2609 { &hf_ntlmssp_message_type,
2610 { "NTLM Message Type", "ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, NULL, HFILL }},
2611 { &hf_ntlmssp_negotiate_flags,
2612 { "Flags", "ntlmssp.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2613 { &hf_ntlmssp_negotiate_flags_01,
2614 { "Negotiate UNICODE", "ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_UNICODE, NULL, HFILL }},
2615 { &hf_ntlmssp_negotiate_flags_02,
2616 { "Negotiate OEM", "ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM, NULL, HFILL }},
2617 { &hf_ntlmssp_negotiate_flags_04,
2618 { "Request Target", "ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_TARGET, NULL, HFILL }},
2619 { &hf_ntlmssp_negotiate_flags_08,
2620 { "Request 0x00000008", "ntlmssp.negotiate00000008", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000008, NULL, HFILL }},
2621 { &hf_ntlmssp_negotiate_flags_10,
2622 { "Negotiate Sign", "ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SIGN, NULL, HFILL }},
2623 { &hf_ntlmssp_negotiate_flags_20,
2624 { "Negotiate Seal", "ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SEAL, NULL, HFILL }},
2625 { &hf_ntlmssp_negotiate_flags_40,
2626 { "Negotiate Datagram", "ntlmssp.negotiatedatagram", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_DATAGRAM, NULL, HFILL }},
2627 { &hf_ntlmssp_negotiate_flags_80,
2628 { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_LM_KEY, NULL, HFILL }},
2629 { &hf_ntlmssp_negotiate_flags_100,
2630 { "Negotiate 0x00000100", "ntlmssp.negotiate00000100", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000100, NULL, HFILL }},
2631 { &hf_ntlmssp_negotiate_flags_200,
2632 { "Negotiate NTLM key", "ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NTLM, NULL, HFILL }},
2633 { &hf_ntlmssp_negotiate_flags_400,
2634 { "Negotiate NT Only", "ntlmssp.negotiatentonly", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NT_ONLY, NULL, HFILL }},
2635 { &hf_ntlmssp_negotiate_flags_800,
2636 { "Negotiate 0x00000800", "ntlmssp.negotiate00000800", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000800, NULL, HFILL }},
2637 { &hf_ntlmssp_negotiate_flags_1000,
2638 { "Negotiate OEM Domain Supplied", "ntlmssp.negotiateoemdomainsupplied", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED, NULL, HFILL }},
2639 { &hf_ntlmssp_negotiate_flags_2000,
2640 { "Negotiate OEM Workstation Supplied", "ntlmssp.negotiateoemworkstationsupplied", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED, NULL, HFILL }},
2641 { &hf_ntlmssp_negotiate_flags_4000,
2642 { "Negotiate 0x00004000", "ntlmssp.negotiate00004000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00004000, NULL, HFILL }},
2643 { &hf_ntlmssp_negotiate_flags_8000,
2644 { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, NULL, HFILL }},
2645 { &hf_ntlmssp_negotiate_flags_10000,
2646 { "Target Type Domain", "ntlmssp.targettypedomain", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_DOMAIN, NULL, HFILL }},
2647 { &hf_ntlmssp_negotiate_flags_20000,
2648 { "Target Type Server", "ntlmssp.targettypeserver", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER, NULL, HFILL }},
2649 { &hf_ntlmssp_negotiate_flags_40000,
2650 { "Target Type Share", "ntlmssp.targettypeshare", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SHARE, NULL, HFILL }},
2652 /* Negotiate Flags */
2653 { &hf_ntlmssp_negotiate_flags_80000,
2654 { "Negotiate Extended Security", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SECURITY, NULL, HFILL }},
2655 { &hf_ntlmssp_negotiate_flags_100000,
2656 { "Negotiate Identify", "ntlmssp.negotiateidentify", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_IDENTIFY, NULL, HFILL }},
2657 { &hf_ntlmssp_negotiate_flags_200000,
2658 { "Negotiate 0x00200000", "ntlmssp.negotiatent00200000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00200000, NULL, HFILL }},
2659 { &hf_ntlmssp_negotiate_flags_400000,
2660 { "Request Non-NT Session", "ntlmssp.requestnonntsession", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_NON_NT_SESSION, NULL, HFILL }},
2661 { &hf_ntlmssp_negotiate_flags_800000,
2662 { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_TARGET_INFO, NULL, HFILL }},
2663 { &hf_ntlmssp_negotiate_flags_1000000,
2664 { "Negotiate 0x01000000", "ntlmssp.negotiatent01000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_01000000, NULL, HFILL }},
2665 { &hf_ntlmssp_negotiate_flags_2000000,
2666 { "Negotiate Version", "ntlmssp.negotiateversion", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_VERSION, NULL, HFILL }},
2667 { &hf_ntlmssp_negotiate_flags_4000000,
2668 { "Negotiate 0x04000000", "ntlmssp.negotiatent04000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_04000000, NULL, HFILL }},
2669 { &hf_ntlmssp_negotiate_flags_8000000,
2670 { "Negotiate 0x08000000", "ntlmssp.negotiatent08000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_08000000, NULL, HFILL }},
2671 { &hf_ntlmssp_negotiate_flags_10000000,
2672 { "Negotiate 0x10000000", "ntlmssp.negotiatent10000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_10000000, NULL, HFILL }},
2673 { &hf_ntlmssp_negotiate_flags_20000000,
2674 { "Negotiate 128", "ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_128, "128-bit encryption is supported", HFILL }},
2675 { &hf_ntlmssp_negotiate_flags_40000000,
2676 { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_KEY_EXCH, NULL, HFILL }},
2677 { &hf_ntlmssp_negotiate_flags_80000000,
2678 { "Negotiate 56", "ntlmssp.negotiate56", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_56, "56-bit encryption is supported", HFILL }},
2679 { &hf_ntlmssp_negotiate_workstation_strlen,
2680 { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2681 { &hf_ntlmssp_negotiate_workstation_maxlen,
2682 { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2683 { &hf_ntlmssp_negotiate_workstation_buffer,
2684 { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2685 { &hf_ntlmssp_negotiate_workstation,
2686 { "Calling workstation name", "ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2687 { &hf_ntlmssp_negotiate_domain_strlen,
2688 { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2689 { &hf_ntlmssp_negotiate_domain_maxlen,
2690 { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2691 { &hf_ntlmssp_negotiate_domain_buffer,
2692 { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2693 { &hf_ntlmssp_negotiate_domain,
2694 { "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2695 { &hf_ntlmssp_ntlm_client_challenge,
2696 { "NTLM Client Challenge", "ntlmssp.ntlmclientchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2697 { &hf_ntlmssp_ntlm_server_challenge,
2698 { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2699 { &hf_ntlmssp_reserved,
2700 { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2702 { &hf_ntlmssp_challenge_target_name,
2703 { "Target Name", "ntlmssp.challenge.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2704 { &hf_ntlmssp_auth_domain,
2705 { "Domain name", "ntlmssp.auth.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2706 { &hf_ntlmssp_auth_username,
2707 { "User name", "ntlmssp.auth.username", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2708 { &hf_ntlmssp_auth_hostname,
2709 { "Host name", "ntlmssp.auth.hostname", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2710 { &hf_ntlmssp_auth_lmresponse,
2711 { "Lan Manager Response", "ntlmssp.auth.lmresponse", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2712 { &hf_ntlmssp_auth_ntresponse,
2713 { "NTLM Response", "ntlmssp.auth.ntresponse", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2714 { &hf_ntlmssp_auth_sesskey,
2715 { "Session Key", "ntlmssp.auth.sesskey", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2716 { &hf_ntlmssp_string_len,
2717 { "Length", "ntlmssp.string.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2718 { &hf_ntlmssp_string_maxlen,
2719 { "Maxlen", "ntlmssp.string.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2720 { &hf_ntlmssp_string_offset,
2721 { "Offset", "ntlmssp.string.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2722 { &hf_ntlmssp_blob_len,
2723 { "Length", "ntlmssp.blob.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2724 { &hf_ntlmssp_blob_maxlen,
2725 { "Maxlen", "ntlmssp.blob.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2726 { &hf_ntlmssp_blob_offset,
2727 { "Offset", "ntlmssp.blob.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2728 { &hf_ntlmssp_version,
2729 { "Version", "ntlmssp.version", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2730 { &hf_ntlmssp_version_major,
2731 { "Major Version", "ntlmssp.version.major", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2732 { &hf_ntlmssp_version_minor,
2733 { "Minor Version", "ntlmssp.version.minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2734 { &hf_ntlmssp_version_build_number,
2735 { "Major Version", "ntlmssp.version.build_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2736 { &hf_ntlmssp_version_ntlm_current_revision,
2737 { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2740 { &hf_ntlmssp_challenge_target_info,
2741 { "Target Info", "ntlmssp.challenge.target_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2742 { &hf_ntlmssp_challenge_target_info_len,
2743 { "Length", "ntlmssp.challenge.target_info.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2744 { &hf_ntlmssp_challenge_target_info_maxlen,
2745 { "Maxlen", "ntlmssp.challenge.target_info.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2746 { &hf_ntlmssp_challenge_target_info_offset,
2747 { "Offset", "ntlmssp.challenge.target_info.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2749 { &hf_ntlmssp_challenge_target_info_item_type,
2750 { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
2751 { &hf_ntlmssp_challenge_target_info_item_len,
2752 { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2754 { &hf_ntlmssp_challenge_target_info_end,
2755 { "List End", "ntlmssp.challenge.target_info.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2756 { &hf_ntlmssp_challenge_target_info_nb_computer_name,
2757 { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
2758 { &hf_ntlmssp_challenge_target_info_nb_domain_name,
2759 { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
2760 { &hf_ntlmssp_challenge_target_info_dns_computer_name,
2761 { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2762 { &hf_ntlmssp_challenge_target_info_dns_domain_name,
2763 { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2764 { &hf_ntlmssp_challenge_target_info_dns_tree_name,
2765 { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2766 { &hf_ntlmssp_challenge_target_info_flags,
2767 { "Flags", "ntlmssp.challenge.target_info.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2768 { &hf_ntlmssp_challenge_target_info_timestamp,
2769 { "Timestamp", "ntlmssp.challenge.target_info.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2770 { &hf_ntlmssp_challenge_target_info_restrictions,
2771 { "Restrictions", "ntlmssp.challenge.target_info.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2772 { &hf_ntlmssp_challenge_target_info_target_name,
2773 { "Target Name", "ntlmssp.challenge.target_info.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2774 { &hf_ntlmssp_challenge_target_info_channel_bindings,
2775 { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2777 { &hf_ntlmssp_ntlmv2_response_item_type,
2778 { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
2779 { &hf_ntlmssp_ntlmv2_response_item_len,
2780 { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2782 { &hf_ntlmssp_ntlmv2_response_end,
2783 { "List End", "ntlmssp.ntlmv2_response.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2784 { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
2785 { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
2786 { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
2787 { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
2788 { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
2789 { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2790 { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
2791 { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2792 { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
2793 { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2794 { &hf_ntlmssp_ntlmv2_response_flags,
2795 { "Flags", "ntlmssp.ntlmv2_response.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2796 { &hf_ntlmssp_ntlmv2_response_timestamp,
2797 { "Timestamp", "ntlmssp.ntlmv2_response.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2798 { &hf_ntlmssp_ntlmv2_response_restrictions,
2799 { "Restrictions", "ntlmssp.ntlmv2_response.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2800 { &hf_ntlmssp_ntlmv2_response_target_name,
2801 { "Target Name", "ntlmssp.ntlmv2_response.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2802 { &hf_ntlmssp_ntlmv2_response_channel_bindings,
2803 { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2805 { &hf_ntlmssp_message_integrity_code,
2806 { "MIC", "ntlmssp.authenticate.mic", FT_BYTES, BASE_NONE, NULL, 0x0, "Message Integrity Code", HFILL}},
2808 { "NTLMSSP Verifier", "ntlmssp.verf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2809 { &hf_ntlmssp_verf_vers,
2810 { "Version Number", "ntlmssp.verf.vers", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2811 { &hf_ntlmssp_verf_body,
2812 { "Verifier Body", "ntlmssp.verf.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2813 { &hf_ntlmssp_decrypted_payload,
2814 { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2815 { &hf_ntlmssp_verf_randompad,
2816 { "Random Pad", "ntlmssp.verf.randompad", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2817 { &hf_ntlmssp_verf_crc32,
2818 { "Verifier CRC32", "ntlmssp.verf.crc32", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2819 { &hf_ntlmssp_verf_hmacmd5,
2820 { "HMAC MD5", "ntlmssp.verf.hmacmd5", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2821 { &hf_ntlmssp_verf_sequence,
2822 { "Sequence", "ntlmssp.verf.sequence", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2824 { &hf_ntlmssp_ntlmv2_response,
2825 { "NTLMv2 Response", "ntlmssp.ntlmv2_response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2826 { &hf_ntlmssp_ntlmv2_response_hmac,
2827 { "HMAC", "ntlmssp.ntlmv2_response.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2828 { &hf_ntlmssp_ntlmv2_response_header,
2829 { "Header", "ntlmssp.ntlmv2_response.header", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2830 { &hf_ntlmssp_ntlmv2_response_reserved,
2831 { "Reserved", "ntlmssp.ntlmv2_response.reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2832 { &hf_ntlmssp_ntlmv2_response_time,
2833 { "Time", "ntlmssp.ntlmv2_response.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2834 { &hf_ntlmssp_ntlmv2_response_chal,
2835 { "Client challenge", "ntlmssp.ntlmv2_response.chal", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2836 { &hf_ntlmssp_ntlmv2_response_unknown,
2837 { "Unknown", "ntlmssp.ntlmv2_response.unknown", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}
2841 static gint *ett[] = {
2843 &ett_ntlmssp_negotiate_flags,
2844 &ett_ntlmssp_string,
2846 &ett_ntlmssp_version,
2847 &ett_ntlmssp_challenge_target_info,
2848 &ett_ntlmssp_challenge_target_info_item,
2849 &ett_ntlmssp_ntlmv2_response,
2850 &ett_ntlmssp_ntlmv2_response_item,
2852 module_t *ntlmssp_module;
2854 proto_ntlmssp = proto_register_protocol (
2855 "NTLM Secure Service Provider", /* name */
2856 "NTLMSSP", /* short name */
2857 "ntlmssp" /* abbrev */
2859 proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
2860 proto_register_subtree_array (ett, array_length (ett));
2861 register_init_routine(&ntlmssp_init_protocol);
2863 ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
2865 prefs_register_string_preference(ntlmssp_module, "nt_password",
2867 "NT Password (used to decrypt payloads)",
2870 register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
2871 new_register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
2872 new_register_dissector("ntlmssp_data_only", dissect_ntlmssp_payload_only, proto_ntlmssp);
2873 new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
2876 static int wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
2877 proto_tree *tree, guint8 *drep _U_)
2881 auth_tvb = tvb_new_subset(
2882 tvb, offset, tvb_length_remaining(tvb, offset),
2883 tvb_length_remaining(tvb, offset));
2885 dissect_ntlmssp(auth_tvb, pinfo, tree);
2887 return tvb_length_remaining(tvb, offset);
2890 static int wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
2891 proto_tree *tree, guint8 *drep _U_)
2895 auth_tvb = tvb_new_subset(
2896 tvb, offset, tvb_length_remaining(tvb, offset),
2897 tvb_length_remaining(tvb, offset));
2898 return dissect_ntlmssp_verf(auth_tvb, pinfo, tree);
2901 static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
2902 wrap_dissect_ntlmssp, /* Bind */
2903 wrap_dissect_ntlmssp, /* Bind ACK */
2904 wrap_dissect_ntlmssp, /* AUTH3 */
2905 wrap_dissect_ntlmssp_verf, /* Request verifier */
2906 wrap_dissect_ntlmssp_verf, /* Response verifier */
2907 NULL, /* Request data */
2908 NULL /* Response data */
2911 static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
2912 wrap_dissect_ntlmssp, /* Bind */
2913 wrap_dissect_ntlmssp, /* Bind ACK */
2914 wrap_dissect_ntlmssp, /* AUTH3 */
2915 wrap_dissect_ntlmssp_verf, /* Request verifier */
2916 wrap_dissect_ntlmssp_verf, /* Response verifier */
2917 wrap_dissect_ntlmssp_payload_only, /* Request data */
2918 wrap_dissect_ntlmssp_payload_only /* Response data */
2922 proto_reg_handoff_ntlmssp(void)
2924 dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
2926 /* Register protocol with the GSS-API module */
2928 ntlmssp_handle = find_dissector("ntlmssp");
2929 ntlmssp_wrap_handle = find_dissector("ntlmssp_verf");
2930 gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
2931 ntlmssp_handle, ntlmssp_wrap_handle,
2932 "NTLMSSP - Microsoft NTLM Security Support Provider");
2934 /* Register authenticated pipe dissector */
2937 * XXX - the verifiers here seem to have a version of 1 and a body of all
2940 * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
2941 * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
2942 * any other levels here?
2944 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
2945 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2948 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
2949 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2952 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
2953 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2956 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
2957 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2959 ntlmssp_tap = register_tap("ntlmssp");
2963 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2968 * indent-tabs-mode: nil
2971 * vi: set shiftwidth=2 tabstop=8 expandtab
2972 * :indentSize=2:tabSize=8:noTabs=true: