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 <wsutil/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_)
341 * GSlist of decrypted payloads.
343 static GSList *decrypted_payloads;
347 LEBE_Convert(int value)
352 b=(value&0x0000FF00) >> 8;
353 c=(value&0x00FF0000) >> 16;
354 d=(value&0xFF000000) >> 24;
355 return (a << 24) | (b << 16) | (c << 8) | d;
360 Perform a DES encryption with a 16 bit key and 8bit data item.
361 It's in fact 3 susbsequent call to crypt_des_ecb with a 7 bit key.
362 Missing bits for the key are replaced by 0;
363 Returns output in response, which is expected to be 24 bytes.
366 crypt_des_ecb_long(guint8 *response,
370 guint8 pw21[21]; /* 21 bytes place for the needed key */
372 memset(pw21, 0, sizeof(pw21));
373 memcpy(pw21, key, 16);
375 memset(response, 0, 24);
376 /* crypt_des_ecb(data,key)*/
377 crypt_des_ecb(response, data, pw21, 1);
378 crypt_des_ecb(response + 8, data, pw21 + 7, 1);
379 crypt_des_ecb(response + 16, data, pw21 + 14, 1);
385 Generate a challenge response, given an eight byte challenge and
386 either the NT or the Lan Manager password hash (16 bytes).
387 Returns output in response, which is expected to be 24 bytes.
390 ntlmssp_generate_challenge_response(guint8 *response,
391 const guint8 *passhash,
392 const guint8 *challenge)
394 guint8 pw21[21]; /* Password hash padded to 21 bytes */
396 memset(pw21, 0x0, sizeof(pw21));
397 memcpy(pw21, passhash, 16);
399 memset(response, 0, 24);
401 crypt_des_ecb(response, challenge, pw21, 1);
402 crypt_des_ecb(response + 8, challenge, pw21 + 7, 1);
403 crypt_des_ecb(response + 16, challenge, pw21 + 14, 1);
409 /* Ultra simple ainsi to unicode converter, will only work for ascii password ...*/
411 str_to_unicode(const char *nt_password, char *nt_password_unicode)
413 size_t password_len = 0;
416 password_len = strlen(nt_password);
417 if(nt_password_unicode != NULL)
419 for(i=0;i<(password_len);i++)
421 nt_password_unicode[i*2]=nt_password[i];
422 nt_password_unicode[i*2+1]=0;
424 nt_password_unicode[2*password_len]='\0';
428 /* This function generate the Key Exchange Key
429 * Depending on the flags this key will either be used to crypt the exported session key
430 * or will be used directly as exported session key.
431 * Exported session key is the key that will be used for sealing and signing communication*/
434 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)
436 guint8 basekey[NTLMSSP_KEY_LEN];
439 memset(keyexchangekey,0,NTLMSSP_KEY_LEN);
440 memset(basekey,0,NTLMSSP_KEY_LEN);
441 /* sessionbasekey is either derived from lm_password_hash or from nt_password_hash depending on the key type negotiated */
442 memcpy(basekey,sessionbasekey,8);
443 memset(basekey,0xBD,8);
444 if(flags&NTLMSSP_NEGOTIATE_LM_KEY)
447 crypt_des_ecb(keyexchangekey,lm_challenge_response,basekey,1);
448 crypt_des_ecb(keyexchangekey+8,lm_challenge_response,basekey+7,1);
452 if(flags&NTLMSSP_REQUEST_NON_NT_SESSION)
454 /*People from samba tends to use the same function in this case than in the previous one but with 0 data
455 * it's not clear that it produce the good result
456 * memcpy(keyexchangekey,lm_hash,8);
457 * Let's trust samba implementation it mights seem weird but they are more often rights than the spec !
460 crypt_des_ecb(keyexchangekey,zeros,basekey,3);
461 crypt_des_ecb(keyexchangekey+8,zeros,basekey+7,1);
465 /* it is stated page 65 of NTLM SSP spec that sessionbasekey should be encrypted with hmac_md5 using the concact of both challenge
466 * when it's NTLM v1 + extended security but it turns out to be wrong !
468 memcpy(keyexchangekey,sessionbasekey,NTLMSSP_KEY_LEN);
473 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
475 get_md4pass_list(md4_pass** p_pass_list,const char* nt_password)
480 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
481 int password_len = 0;
482 char nt_password_unicode[256];
489 read_keytab_file_from_preferences();
491 for(ek=enc_key_list;ek;ek=ek->next){
492 if( ek->keylength == NTLMSSP_KEY_LEN ) {
496 memset(nt_password_hash,0,NTLMSSP_KEY_LEN);
497 if (nt_password[0] != '\0' && ( strlen(nt_password) < 129 )) {
499 password_len = strlen(nt_password);
500 str_to_unicode(nt_password,nt_password_unicode);
501 crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
504 /* Unable to calculate the session key without a password or if password is more than 128 char ......*/
508 *p_pass_list = ep_alloc(nb_pass*sizeof(md4_pass));
509 pass_list=*p_pass_list;
511 if( memcmp(nt_password_hash,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
512 memcpy(pass_list[i].md4,nt_password_hash,NTLMSSP_KEY_LEN);
515 for(ek=enc_key_list;ek;ek=ek->next){
516 if( ek->keylength == NTLMSSP_KEY_LEN ) {
517 memcpy(pass_list[i].md4,ek->keyvalue,NTLMSSP_KEY_LEN);
525 /* Create an NTLMSSP version 2 key
528 create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge , const guint8 *clientchallenge ,
529 guint8 *sessionkey ,const guint8 *encryptedsessionkey , int flags ,
530 const ntlmssp_blob *ntlm_response, const ntlmssp_blob *lm_response _U_, ntlmssp_header_t *ntlmssph )
532 char domain_name_unicode[256];
533 char user_uppercase[256];
535 /*guint8 md4[NTLMSSP_KEY_LEN];*/
536 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
537 unsigned char nt_proof[NTLMSSP_KEY_LEN];
538 unsigned char ntowf[NTLMSSP_KEY_LEN];
539 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
540 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
541 guint8 lm_challenge_response[24];
544 rc4_state_struct rc4state;
547 md4_pass *pass_list = NULL;
551 /* We are going to try password encrypted in keytab as well, it's an idean of Stefan Metzmacher <metze@samba.org>
552 * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
554 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
555 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
556 nb_pass = get_md4pass_list(&pass_list,nt_password);
559 memset(user_uppercase,0,256);
560 user_len = strlen(ntlmssph->acct_name);
561 if( user_len < 129 ) {
563 str_to_unicode(ntlmssph->acct_name,buf);
564 for (j = 0; j < (2*user_len); j++) {
565 if( buf[j] != '\0' ) {
566 user_uppercase[j] = toupper(buf[j]);
571 /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
574 domain_len = strlen(ntlmssph->domain_name);
575 if( domain_len < 129 ) {
576 str_to_unicode(ntlmssph->domain_name,domain_name_unicode);
579 /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
582 while (i < nb_pass ) {
583 /*fprintf(stderr,"Turn %d, ",i);*/
584 memcpy(nt_password_hash,pass_list[i].md4,NTLMSSP_KEY_LEN);
585 /*printnbyte(nt_password_hash,NTLMSSP_KEY_LEN,"Current NT password hash: ","\n");*/
587 /* ntowf computation */
589 memcpy(buf,user_uppercase,user_len*2);
590 memcpy(buf+user_len*2,domain_name_unicode,domain_len*2);
591 md5_hmac(buf,domain_len*2+user_len*2,nt_password_hash,NTLMSSP_KEY_LEN,ntowf);
594 memcpy(buf,serverchallenge,8);
595 memcpy(buf+8,clientchallenge,8);
596 md5_hmac(buf,NTLMSSP_KEY_LEN,ntowf,NTLMSSP_KEY_LEN,lm_challenge_response);
597 memcpy(lm_challenge_response+NTLMSSP_KEY_LEN,clientchallenge,8);
598 printnbyte(lm_challenge_response,24,"LM Response: ","\n");
600 /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
602 memcpy(buf,serverchallenge,8);
603 memcpy(buf+8,ntlm_response->contents+NTLMSSP_KEY_LEN,ntlm_response->length-NTLMSSP_KEY_LEN);
604 md5_hmac(buf,ntlm_response->length-8,ntowf,NTLMSSP_KEY_LEN,nt_proof);
605 printnbyte(nt_proof,NTLMSSP_KEY_LEN,"NT proof: ","\n");
606 if( !memcmp(nt_proof,ntlm_response->contents,NTLMSSP_KEY_LEN) ) {
617 md5_hmac(nt_proof,NTLMSSP_KEY_LEN,ntowf,NTLMSSP_KEY_LEN,sessionbasekey);
618 get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
619 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
620 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
622 memcpy(sessionkey,encryptedsessionkey,NTLMSSP_KEY_LEN);
623 crypt_rc4_init(&rc4state,keyexchangekey,NTLMSSP_KEY_LEN);
624 crypt_rc4(&rc4state,sessionkey,NTLMSSP_KEY_LEN);
628 memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
632 /* Create an NTLMSSP version 1 key
633 * That is more complicated logic and methods and user challenge as well.
634 * password points to the ANSI password to encrypt, challenge points to
635 * the 8 octet challenge string
638 create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, const guint8 *clientchallenge,
639 guint8 *sessionkey,const guint8 *encryptedsessionkey, int flags,
640 const guint8 *ref_nt_challenge_response,const guint8 *ref_lm_challenge_response)
642 unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
643 unsigned char lm_password_hash[NTLMSSP_KEY_LEN];
644 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
645 unsigned char challenges_hash[NTLMSSP_KEY_LEN];
646 unsigned char challenges_hash_first8[8];
647 unsigned char challenges[NTLMSSP_KEY_LEN];
648 guint8 md4[NTLMSSP_KEY_LEN];
650 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
651 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
652 guint8 lm_challenge_response[24];
653 guint8 nt_challenge_response[24];
654 rc4_state_struct rc4state;
655 md5_state_t md5state;
656 char nt_password_unicode[256];
660 md4_pass *pass_list = NULL;
661 unsigned char lmhash_key[] =
662 {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
664 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
665 memset(lm_password_upper, 0, sizeof(lm_password_upper));
666 /* lm auth/lm session == (!NTLM_NEGOTIATE_NT_ONLY && NTLMSSP_NEGOTIATE_LM_KEY) || ! (EXTENDED_SECURITY) || ! NTLMSSP_NEGOTIATE_NTLM*/
667 /* Create a Lan Manager hash of the input password */
668 if (nt_password[0] != '\0') {
669 password_len = strlen(nt_password);
670 /*Do not forget to free nt_password_nt*/
671 str_to_unicode(nt_password,nt_password_unicode);
672 crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
673 /* Truncate password if too long */
674 if (password_len > NTLMSSP_KEY_LEN)
675 password_len = NTLMSSP_KEY_LEN;
676 for (i = 0; i < password_len; i++) {
677 lm_password_upper[i] = toupper(nt_password[i]);
682 /* Unable to calculate the session key without a password ... and we will not use one for a keytab*/
683 if( !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
687 if((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NTLMSSP_NEGOTIATE_NT_ONLY)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
688 crypt_des_ecb(lm_password_hash, lmhash_key, lm_password_upper, 1);
689 crypt_des_ecb(lm_password_hash+8, lmhash_key, lm_password_upper+7, 1);
690 ntlmssp_generate_challenge_response(lm_challenge_response,
691 lm_password_hash, serverchallenge);
692 memcpy(sessionbasekey,lm_password_hash,NTLMSSP_KEY_LEN);
696 memset(lm_challenge_response,0,24);
697 if( flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
698 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
699 nb_pass = get_md4pass_list(&pass_list,nt_password);
702 while (i < nb_pass ) {
703 /*fprintf(stderr,"Turn %d, ",i);*/
704 memcpy(nt_password_hash,pass_list[i].md4,NTLMSSP_KEY_LEN);
705 /*printnbyte(nt_password_hash,NTLMSSP_KEY_LEN,"Current NT password hash: ","\n");*/
707 memcpy(lm_challenge_response,clientchallenge,8);
709 md5_append(&md5state,serverchallenge,8);
710 md5_append(&md5state,clientchallenge,8);
711 md5_finish(&md5state,challenges_hash);
712 memcpy(challenges_hash_first8,challenges_hash,8);
713 crypt_des_ecb_long(nt_challenge_response,nt_password_hash,challenges_hash_first8);
714 if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) ) {
721 crypt_des_ecb_long(nt_challenge_response,nt_password_hash,serverchallenge);
722 if( flags & NTLMSSP_NEGOTIATE_NT_ONLY ) {
723 memcpy(lm_challenge_response,nt_challenge_response,24);
726 crypt_des_ecb_long(lm_challenge_response,lm_password_hash,serverchallenge);
728 if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) && !memcmp(ref_lm_challenge_response,lm_challenge_response,24) ) {
732 /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
733 * that sessionbasekey should be based md4(nt_password_hash) only in the case of some NT auth
734 * Otherwise it should be lm_password_hash ...*/
735 crypt_md4(md4,nt_password_hash,NTLMSSP_KEY_LEN);
736 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
737 memcpy(challenges,serverchallenge,8);
738 memcpy(challenges+8,clientchallenge,8);
739 /*md5_hmac(text,text_len,key,key_len,digest);*/
740 md5_hmac(challenges,NTLMSSP_KEY_LEN,md4,NTLMSSP_KEY_LEN,sessionbasekey);
743 memcpy(sessionbasekey,md4,NTLMSSP_KEY_LEN);
752 get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
753 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
754 /*printnbyte(nt_challenge_response,24,"NT challenge response","\n");
755 printnbyte(lm_challenge_response,24,"LM challenge response","\n");*/
756 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
757 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
759 memcpy(sessionkey,encryptedsessionkey,NTLMSSP_KEY_LEN);
760 crypt_rc4_init(&rc4state,keyexchangekey,NTLMSSP_KEY_LEN);
761 crypt_rc4(&rc4state,sessionkey,NTLMSSP_KEY_LEN);
765 memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
770 get_siging_key(guint8 *sign_key_server,guint8* sign_key_client,const guint8 key[NTLMSSP_KEY_LEN], int keylen)
772 md5_state_t md5state;
773 md5_state_t md5state2;
774 memset(sign_key_client,0,NTLMSSP_KEY_LEN);
775 memset(sign_key_server,0,NTLMSSP_KEY_LEN);
777 md5_append(&md5state,key,keylen);
778 md5_append(&md5state,CLIENT_SIGN_TEXT,strlen(CLIENT_SIGN_TEXT)+1);
779 md5_finish(&md5state,sign_key_client);
780 md5_init(&md5state2);
781 md5_append(&md5state2,key,keylen);
782 md5_append(&md5state2,SERVER_SIGN_TEXT,strlen(SERVER_SIGN_TEXT)+1);
783 md5_finish(&md5state2,sign_key_server);
787 /* We return either a 128 or 64 bit key
790 get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int flags ,int *keylen ,
791 guint8 *clientsealkey ,guint8 *serversealkey)
793 md5_state_t md5state;
794 md5_state_t md5state2;
795 memset(clientsealkey,0,NTLMSSP_KEY_LEN);
796 memset(serversealkey,0,NTLMSSP_KEY_LEN);
797 memcpy(clientsealkey,exportedsessionkey,NTLMSSP_KEY_LEN);
798 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)
800 if (flags & NTLMSSP_NEGOTIATE_128)
802 /* The exportedsessionkey has already the good length just update the length*/
807 if (flags & NTLMSSP_NEGOTIATE_56)
809 memset(clientsealkey+7,0,9);
814 memset(clientsealkey+5,0,11);
818 memcpy(serversealkey,clientsealkey,NTLMSSP_KEY_LEN);
820 md5_append(&md5state,clientsealkey,*keylen);
821 md5_append(&md5state,CLIENT_SEAL_TEXT,strlen(CLIENT_SEAL_TEXT)+1);
822 md5_finish(&md5state,clientsealkey);
823 md5_init(&md5state2);
824 md5_append(&md5state2,serversealkey,*keylen);
825 md5_append(&md5state2,SERVER_SEAL_TEXT,strlen(SERVER_SEAL_TEXT)+1);
826 md5_finish(&md5state2,serversealkey);
830 if (flags & NTLMSSP_NEGOTIATE_128)
832 /* The exportedsessionkey has already the good length just update the length*/
838 if (flags & NTLMSSP_NEGOTIATE_56)
840 memset(clientsealkey+7,0,9);
844 memset(clientsealkey+5,0,11);
845 clientsealkey[5]=0xe5;
846 clientsealkey[6]=0x38;
847 clientsealkey[7]=0xb0;
850 memcpy(serversealkey,clientsealkey,*keylen);
853 /* Create an NTLMSSP version 1 key.
854 * password points to the ANSI password to encrypt, challenge points to
855 * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
856 * otherwise it will do a 40 bit key. The result is stored in
857 * sspkey (expected to be NTLMSSP_KEY_LEN octets)
859 /* dissect a string - header area contains:
862 four byte offset of string in data area
863 The function returns the offset at the end of the string header,
864 but the 'end' parameter returns the offset of the end of the string itself
865 The 'start' parameter returns the offset of the beginning of the string
866 If there's no string, just use the offset of the end of the tvb as start/end.
869 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
870 proto_tree *ntlmssp_tree,
871 gboolean unicode_strings,
872 int string_hf, int *start, int *end,
873 const char **stringp)
875 proto_tree *tree = NULL;
876 proto_item *tf = NULL;
877 gint16 string_length = tvb_get_letohs(tvb, offset);
878 gint16 string_maxlen = tvb_get_letohs(tvb, offset+2);
879 gint32 string_offset = tvb_get_letohl(tvb, offset+4);
880 const char *string_text = NULL;
884 *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
885 if (0 == string_length) {
888 proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
895 bc = result_length = string_length;
896 string_text = get_unicode_or_ascii_string(tvb, &string_offset,
897 unicode_strings, &result_length,
900 if (stringp != NULL) {
901 if (!string_text) string_text = ""; /* Make sure we don't blow up later */
903 *stringp = string_text;
907 tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
908 string_offset, result_length, string_text);
909 tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
911 proto_tree_add_uint(tree, hf_ntlmssp_string_len,
912 tvb, offset, 2, string_length);
914 proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
915 tvb, offset, 2, string_maxlen);
917 proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
918 tvb, offset, 4, string_offset);
921 *end = string_offset + string_length;
925 /* dissect a generic blob - header area contains:
928 four byte offset of blob in data area
929 The function returns the offset at the end of the blob header,
930 but the 'end' parameter returns the offset of the end of the blob itself
933 dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
934 proto_tree *ntlmssp_tree,
935 int blob_hf, int *end, ntlmssp_blob *result)
937 proto_item *tf = NULL;
938 proto_tree *tree = NULL;
939 guint16 blob_length = tvb_get_letohs(tvb, offset);
940 guint16 blob_maxlen = tvb_get_letohs(tvb, offset+2);
941 guint32 blob_offset = tvb_get_letohl(tvb, offset+4);
942 if (0 == blob_length) {
943 *end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
945 proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
946 proto_registrar_get_name(blob_hf));
951 tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
952 blob_offset, blob_length, FALSE);
953 tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
955 proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
956 tvb, offset, 2, blob_length);
958 proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
959 tvb, offset, 2, blob_maxlen);
961 proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
962 tvb, offset, 4, blob_offset);
965 *end = blob_offset + blob_length;
967 if (result != NULL) {
968 result->length = blob_length;
969 memset(result->contents, 0, MAX_BLOB_SIZE);
970 if (blob_length < MAX_BLOB_SIZE)
972 tvb_memcpy(tvb, result->contents, blob_offset, blob_length);
973 if (blob_hf == hf_ntlmssp_auth_lmresponse && !(tvb_memeql(tvb, blob_offset+8, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NTLMSSP_KEY_LEN)))
975 proto_tree_add_item (ntlmssp_tree,
976 hf_ntlmssp_ntlm_client_challenge,
977 tvb, blob_offset, 8, FALSE);
982 /* If we are dissecting the NTLM response and it is a NTLMv2
983 response call the appropriate dissector. */
985 if (blob_hf == hf_ntlmssp_auth_ntresponse && blob_length > 24)
987 proto_tree_add_item (ntlmssp_tree,
988 hf_ntlmssp_ntlm_client_challenge,
989 tvb, blob_offset+32, 8, FALSE);
990 dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
997 dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
998 proto_tree *ntlmssp_tree,
999 guint32 negotiate_flags)
1001 proto_tree *negotiate_flags_tree = NULL;
1002 proto_item *tf = NULL;
1005 tf = proto_tree_add_uint (ntlmssp_tree,
1006 hf_ntlmssp_negotiate_flags,
1007 tvb, offset, 4, negotiate_flags);
1008 negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
1011 proto_tree_add_boolean (negotiate_flags_tree,
1012 hf_ntlmssp_negotiate_flags_80000000,
1013 tvb, offset, 4, negotiate_flags);
1014 proto_tree_add_boolean (negotiate_flags_tree,
1015 hf_ntlmssp_negotiate_flags_40000000,
1016 tvb, offset, 4, negotiate_flags);
1017 proto_tree_add_boolean (negotiate_flags_tree,
1018 hf_ntlmssp_negotiate_flags_20000000,
1019 tvb, offset, 4, negotiate_flags);
1020 proto_tree_add_boolean (negotiate_flags_tree,
1021 hf_ntlmssp_negotiate_flags_10000000,
1022 tvb, offset, 4, negotiate_flags);
1023 proto_tree_add_boolean (negotiate_flags_tree,
1024 hf_ntlmssp_negotiate_flags_8000000,
1025 tvb, offset, 4, negotiate_flags);
1026 proto_tree_add_boolean (negotiate_flags_tree,
1027 hf_ntlmssp_negotiate_flags_4000000,
1028 tvb, offset, 4, negotiate_flags);
1029 proto_tree_add_boolean (negotiate_flags_tree,
1030 hf_ntlmssp_negotiate_flags_2000000,
1031 tvb, offset, 4, negotiate_flags);
1032 proto_tree_add_boolean (negotiate_flags_tree,
1033 hf_ntlmssp_negotiate_flags_1000000,
1034 tvb, offset, 4, negotiate_flags);
1035 proto_tree_add_boolean (negotiate_flags_tree,
1036 hf_ntlmssp_negotiate_flags_800000,
1037 tvb, offset, 4, negotiate_flags);
1038 proto_tree_add_boolean (negotiate_flags_tree,
1039 hf_ntlmssp_negotiate_flags_400000,
1040 tvb, offset, 4, negotiate_flags);
1041 proto_tree_add_boolean (negotiate_flags_tree,
1042 hf_ntlmssp_negotiate_flags_200000,
1043 tvb, offset, 4, negotiate_flags);
1044 proto_tree_add_boolean (negotiate_flags_tree,
1045 hf_ntlmssp_negotiate_flags_100000,
1046 tvb, offset, 4, negotiate_flags);
1047 proto_tree_add_boolean (negotiate_flags_tree,
1048 hf_ntlmssp_negotiate_flags_80000,
1049 tvb, offset, 4, negotiate_flags);
1050 proto_tree_add_boolean (negotiate_flags_tree,
1051 hf_ntlmssp_negotiate_flags_40000,
1052 tvb, offset, 4, negotiate_flags);
1053 proto_tree_add_boolean (negotiate_flags_tree,
1054 hf_ntlmssp_negotiate_flags_20000,
1055 tvb, offset, 4, negotiate_flags);
1056 proto_tree_add_boolean (negotiate_flags_tree,
1057 hf_ntlmssp_negotiate_flags_10000,
1058 tvb, offset, 4, negotiate_flags);
1059 proto_tree_add_boolean (negotiate_flags_tree,
1060 hf_ntlmssp_negotiate_flags_8000,
1061 tvb, offset, 4, negotiate_flags);
1062 proto_tree_add_boolean (negotiate_flags_tree,
1063 hf_ntlmssp_negotiate_flags_4000,
1064 tvb, offset, 4, negotiate_flags);
1065 proto_tree_add_boolean (negotiate_flags_tree,
1066 hf_ntlmssp_negotiate_flags_2000,
1067 tvb, offset, 4, negotiate_flags);
1068 proto_tree_add_boolean (negotiate_flags_tree,
1069 hf_ntlmssp_negotiate_flags_1000,
1070 tvb, offset, 4, negotiate_flags);
1071 proto_tree_add_boolean (negotiate_flags_tree,
1072 hf_ntlmssp_negotiate_flags_800,
1073 tvb, offset, 4, negotiate_flags);
1074 proto_tree_add_boolean (negotiate_flags_tree,
1075 hf_ntlmssp_negotiate_flags_400,
1076 tvb, offset, 4, negotiate_flags);
1077 proto_tree_add_boolean (negotiate_flags_tree,
1078 hf_ntlmssp_negotiate_flags_200,
1079 tvb, offset, 4, negotiate_flags);
1080 proto_tree_add_boolean (negotiate_flags_tree,
1081 hf_ntlmssp_negotiate_flags_100,
1082 tvb, offset, 4, negotiate_flags);
1083 proto_tree_add_boolean (negotiate_flags_tree,
1084 hf_ntlmssp_negotiate_flags_80,
1085 tvb, offset, 4, negotiate_flags);
1086 proto_tree_add_boolean (negotiate_flags_tree,
1087 hf_ntlmssp_negotiate_flags_40,
1088 tvb, offset, 4, negotiate_flags);
1089 proto_tree_add_boolean (negotiate_flags_tree,
1090 hf_ntlmssp_negotiate_flags_20,
1091 tvb, offset, 4, negotiate_flags);
1092 proto_tree_add_boolean (negotiate_flags_tree,
1093 hf_ntlmssp_negotiate_flags_10,
1094 tvb, offset, 4, negotiate_flags);
1095 proto_tree_add_boolean (negotiate_flags_tree,
1096 hf_ntlmssp_negotiate_flags_08,
1097 tvb, offset, 4, negotiate_flags);
1098 proto_tree_add_boolean (negotiate_flags_tree,
1099 hf_ntlmssp_negotiate_flags_04,
1100 tvb, offset, 4, negotiate_flags);
1101 proto_tree_add_boolean (negotiate_flags_tree,
1102 hf_ntlmssp_negotiate_flags_02,
1103 tvb, offset, 4, negotiate_flags);
1104 proto_tree_add_boolean (negotiate_flags_tree,
1105 hf_ntlmssp_negotiate_flags_01,
1106 tvb, offset, 4, negotiate_flags);
1108 return (offset + 4);
1111 /* Dissect "version" */
1114 0 Major Version Number 1 byte
1115 1 Minor Version Number 1 byte
1116 2 Build Number short(LE)
1117 3 (Reserved) 3 bytes
1118 4 NTLM Current Revision 1 byte
1122 dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
1123 proto_tree *ntlmssp_tree)
1127 proto_tree *version_tree;
1128 tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
1129 "Version %u.%u (Build %u); NTLM Current Revision %u",
1130 tvb_get_guint8(tvb, offset),
1131 tvb_get_guint8(tvb, offset+1),
1132 tvb_get_letohs(tvb, offset+2),
1133 tvb_get_guint8(tvb, offset+7));
1134 version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
1135 proto_tree_add_item(version_tree, hf_ntlmssp_version_major , tvb, offset , 1, ENC_NA);
1136 proto_tree_add_item(version_tree, hf_ntlmssp_version_minor , tvb, offset+1, 1, ENC_NA);
1137 proto_tree_add_item(version_tree, hf_ntlmssp_version_build_number , tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1138 proto_tree_add_item(version_tree, hf_ntlmssp_version_ntlm_current_revision, tvb, offset+7, 1, ENC_NA);
1143 /* Dissect a NTLM response. This is documented at
1144 http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
1146 /* Attribute types */
1148 * XXX - the davenport document says that a type of 5 has been seen,
1149 * "apparently containing the 'parent' DNS domain for servers in
1151 * XXX: MS-NLMP info is newer than Davenport info;
1152 * The attribute type list and the attribute names below are
1153 * based upon MS-NLMP.
1156 #define NTLM_TARGET_INFO_END 0x0000
1157 #define NTLM_TARGET_INFO_NB_COMPUTER_NAME 0x0001
1158 #define NTLM_TARGET_INFO_NB_DOMAIN_NAME 0x0002
1159 #define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
1160 #define NTLM_TARGET_INFO_DNS_DOMAIN_NAME 0x0004
1161 #define NTLM_TARGET_INFO_DNS_TREE_NAME 0x0005
1162 #define NTLM_TARGET_INFO_FLAGS 0x0006
1163 #define NTLM_TARGET_INFO_TIMESTAMP 0x0007
1164 #define NTLM_TARGET_INFO_RESTRICTIONS 0x0008
1165 #define NTLM_TARGET_INFO_TARGET_NAME 0x0009
1166 #define NTLM_TARGET_INFO_CHANNEL_BINDINGS 0x000A
1168 static const value_string ntlm_name_types[] = {
1169 { NTLM_TARGET_INFO_END, "End of list" },
1170 { NTLM_TARGET_INFO_NB_COMPUTER_NAME, "NetBIOS computer name" },
1171 { NTLM_TARGET_INFO_NB_DOMAIN_NAME, "NetBIOS domain name" },
1172 { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
1173 { NTLM_TARGET_INFO_DNS_DOMAIN_NAME, "DNS domain name" },
1174 { NTLM_TARGET_INFO_DNS_TREE_NAME, "DNS tree name" },
1175 { NTLM_TARGET_INFO_FLAGS, "Flags" },
1176 { NTLM_TARGET_INFO_TIMESTAMP, "Timestamp" },
1177 { NTLM_TARGET_INFO_RESTRICTIONS, "Restrictions" },
1178 { NTLM_TARGET_INFO_TARGET_NAME, "Target Name"},
1179 { NTLM_TARGET_INFO_CHANNEL_BINDINGS, "Channel Bindings"},
1183 /* The following *must* match the order of the list of attribute types */
1184 /* Assumption: values in the list are a sequence starting with 0 and */
1185 /* with no gaps allowing a direct access of the array by attribute type */
1186 static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
1187 &hf_ntlmssp_challenge_target_info_end,
1188 &hf_ntlmssp_challenge_target_info_nb_computer_name,
1189 &hf_ntlmssp_challenge_target_info_nb_domain_name,
1190 &hf_ntlmssp_challenge_target_info_dns_computer_name,
1191 &hf_ntlmssp_challenge_target_info_dns_domain_name,
1192 &hf_ntlmssp_challenge_target_info_dns_tree_name,
1193 &hf_ntlmssp_challenge_target_info_flags,
1194 &hf_ntlmssp_challenge_target_info_timestamp,
1195 &hf_ntlmssp_challenge_target_info_restrictions,
1196 &hf_ntlmssp_challenge_target_info_target_name,
1197 &hf_ntlmssp_challenge_target_info_channel_bindings
1200 static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
1201 &hf_ntlmssp_ntlmv2_response_end,
1202 &hf_ntlmssp_ntlmv2_response_nb_computer_name,
1203 &hf_ntlmssp_ntlmv2_response_nb_domain_name,
1204 &hf_ntlmssp_ntlmv2_response_dns_computer_name,
1205 &hf_ntlmssp_ntlmv2_response_dns_domain_name,
1206 &hf_ntlmssp_ntlmv2_response_dns_tree_name,
1207 &hf_ntlmssp_ntlmv2_response_flags,
1208 &hf_ntlmssp_ntlmv2_response_timestamp,
1209 &hf_ntlmssp_ntlmv2_response_restrictions,
1210 &hf_ntlmssp_ntlmv2_response_target_name,
1211 &hf_ntlmssp_ntlmv2_response_channel_bindings
1214 typedef struct _tif {
1217 int *hf_item_length;
1218 int **hf_attr_array_p;
1221 static tif_t ntlmssp_challenge_target_info_tif = {
1222 &ett_ntlmssp_challenge_target_info_item,
1223 &hf_ntlmssp_challenge_target_info_item_type,
1224 &hf_ntlmssp_challenge_target_info_item_len,
1225 ntlmssp_hf_challenge_target_info_hf_ptr_array
1228 static tif_t ntlmssp_ntlmv2_response_tif = {
1229 &ett_ntlmssp_ntlmv2_response_item,
1230 &hf_ntlmssp_ntlmv2_response_item_type,
1231 &hf_ntlmssp_ntlmv2_response_item_len,
1232 ntlmssp_hf_ntlmv2_response_hf_ptr_array
1236 dissect_ntlmssp_target_info_list(tvbuff_t *tvb, proto_tree *tree,
1237 guint32 target_info_offset, guint16 target_info_length,
1240 guint32 item_offset;
1242 guint16 item_length;
1245 /* Now enumerate through the individual items in the list */
1246 item_offset = target_info_offset;
1248 while (item_offset < (target_info_offset + target_info_length)) {
1249 proto_item *target_info_tf;
1250 proto_tree *target_info_tree;
1251 guint32 content_offset;
1252 guint16 content_length;
1253 guint32 type_offset;
1256 int **hf_array_p = tif_p->hf_attr_array_p;
1259 type_offset = item_offset;
1260 item_type = tvb_get_letohs(tvb, type_offset);
1262 /* Content length */
1263 len_offset = type_offset + 2;
1264 content_length = tvb_get_letohs(tvb, len_offset);
1267 content_offset = len_offset + 2;
1268 item_length = content_length + 4;
1270 target_info_tf = proto_tree_add_text(tree, tvb, item_offset, item_length, "Attribute: %s",
1271 val_to_str(item_type, ntlm_name_types, "Unknown (%d)"));
1273 target_info_tree = proto_item_add_subtree (target_info_tf, *tif_p->ett);
1274 proto_tree_add_item (target_info_tree, *tif_p->hf_item_type, tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
1275 proto_tree_add_item (target_info_tree, *tif_p->hf_item_length, tvb, len_offset, 2, ENC_LITTLE_ENDIAN);
1277 switch (item_type) {
1278 case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
1279 case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
1280 case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
1281 case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
1282 case NTLM_TARGET_INFO_DNS_TREE_NAME:
1283 case NTLM_TARGET_INFO_TARGET_NAME:
1284 if (content_length > 0) {
1287 text = tvb_get_ephemeral_faked_unicode(tvb, content_offset, content_length / 2, TRUE);
1288 proto_tree_add_string(target_info_tree, *hf_array_p[item_type],
1289 tvb, content_offset, content_length, text);
1290 proto_item_append_text(target_info_tf, ": %s", text);
1294 case NTLM_TARGET_INFO_FLAGS:
1295 proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
1296 tvb, content_offset, content_length, ENC_LITTLE_ENDIAN);
1299 case NTLM_TARGET_INFO_TIMESTAMP:
1300 dissect_nt_64bit_time(tvb, target_info_tree, content_offset, *hf_array_p[item_type]);
1303 case NTLM_TARGET_INFO_RESTRICTIONS:
1304 case NTLM_TARGET_INFO_CHANNEL_BINDINGS:
1305 proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
1306 tvb, content_offset, content_length, ENC_NA);
1313 item_offset += item_length;
1318 dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
1320 proto_item *ntlmv2_item = NULL;
1321 proto_tree *ntlmv2_tree = NULL;
1324 /* Dissect NTLMv2 bits&pieces */
1325 orig_offset = offset;
1328 ntlmv2_item = proto_tree_add_item(
1329 tree, hf_ntlmssp_ntlmv2_response, tvb,
1331 ntlmv2_tree = proto_item_add_subtree(
1332 ntlmv2_item, ett_ntlmssp_ntlmv2_response);
1335 proto_tree_add_item(
1336 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hmac, tvb,
1341 proto_tree_add_item(
1342 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_header, tvb,
1347 proto_tree_add_item(
1348 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_reserved, tvb,
1353 offset = dissect_nt_64bit_time(
1354 tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time);
1356 proto_tree_add_item(
1357 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
1362 proto_tree_add_item(
1363 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_unknown, tvb,
1368 /* Variable length list of attributes */
1370 * XXX - Windows puts one or more sets of 4 bytes of additional stuff (all zeros ?)
1371 * at the end of the attributes.
1372 * Samba's smbclient doesn't.
1373 * Both of them appear to be able to connect to W2K SMB
1375 * The additional stuff will be dissected as extra "end" attributes.
1378 dissect_ntlmssp_target_info_list(tvb, ntlmv2_tree,
1379 offset, len - (offset - orig_offset),
1380 &ntlmssp_ntlmv2_response_tif);
1385 /* tapping into ntlmssph not yet implemented */
1387 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1389 guint32 negotiate_flags;
1395 /* NTLMSSP Negotiate Flags */
1396 negotiate_flags = tvb_get_letohl (tvb, offset);
1397 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1401 * XXX - the davenport document says that these might not be
1402 * sent at all, presumably meaning the length of the message
1403 * isn't enough to contain them.
1405 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1406 hf_ntlmssp_negotiate_domain,
1407 &data_start, &data_end, NULL);
1409 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1410 hf_ntlmssp_negotiate_workstation,
1411 &item_start, &item_end, NULL);
1412 data_start = MIN(data_start, item_start);
1413 data_end = MAX(data_end, item_end);
1415 /* If there are more bytes before the data block dissect a version field
1416 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1417 if (offset < data_start) {
1418 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1419 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1426 dissect_ntlmssp_challenge_target_info_blob (tvbuff_t *tvb, int offset,
1427 proto_tree *ntlmssp_tree,
1430 guint16 challenge_target_info_length = tvb_get_letohs(tvb, offset);
1431 guint16 challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
1432 guint32 challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
1433 proto_item *tf = NULL;
1434 proto_tree *challenge_target_info_tree = NULL;
1436 /* the target info list is just a blob */
1437 if (0 == challenge_target_info_length) {
1438 *end = (challenge_target_info_offset > ((guint)offset)+8 ? challenge_target_info_offset : ((guint)offset)+8);
1440 proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
1441 "Target Info List: Empty");
1446 tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
1447 challenge_target_info_offset, challenge_target_info_length, FALSE);
1448 challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
1450 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
1451 tvb, offset, 2, challenge_target_info_length);
1453 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
1454 tvb, offset, 2, challenge_target_info_maxlen);
1456 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
1457 tvb, offset, 4, challenge_target_info_offset);
1460 dissect_ntlmssp_target_info_list(tvb, challenge_target_info_tree,
1461 challenge_target_info_offset, challenge_target_info_length,
1462 &ntlmssp_challenge_target_info_tif);
1464 *end = challenge_target_info_offset + challenge_target_info_length;
1468 /* tapping into ntlmssph not yet implemented */
1470 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
1471 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1473 guint32 negotiate_flags;
1474 int item_start, item_end;
1475 int data_start, data_end; /* MIN and MAX seen */
1476 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1477 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1478 ntlmssp_info *conv_ntlmssp_info = NULL;
1479 conversation_t *conversation;
1480 gboolean unicode_strings = FALSE;
1481 guint8 challenge[8];
1483 guint8 sspkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key */
1484 int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
1486 /* need to find unicode flag */
1487 negotiate_flags = tvb_get_letohl (tvb, offset+8);
1488 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
1489 unicode_strings = TRUE;
1493 * XXX - the davenport document (and MS-NLMP) calls this "Target Name",
1494 * presumably because non-domain targets are supported.
1495 * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
1497 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
1498 hf_ntlmssp_challenge_target_name,
1499 &item_start, &item_end, NULL);
1500 data_start = item_start;
1501 data_end = item_end;
1503 /* NTLMSSP Negotiate Flags */
1504 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1507 /* NTLMSSP NT Lan Manager Challenge */
1508 proto_tree_add_item (ntlmssp_tree,
1509 hf_ntlmssp_ntlm_server_challenge,
1510 tvb, offset, 8, FALSE);
1513 * Store the flags and the RC4 state information with the conversation,
1514 * as they're needed in order to dissect subsequent messages.
1516 conversation = find_or_create_conversation(pinfo);
1518 tvb_memcpy(tvb, tmp, offset, 8); /* challenge */
1519 /* We can face more than one NTLM exchange over the same couple of IP and ports ...*/
1520 conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
1521 /* XXX: The following code is (re)executed every time a particular frame is dissected
1522 * (in whatever order). Thus it seems to me that "multiple exchanges" might not be
1523 * handled well depending on the order that frames are visited after the initial dissection.
1525 if (!conv_ntlmssp_info || memcmp(tmp,conv_ntlmssp_info->server_challenge,8) != 0) {
1526 conv_ntlmssp_info = se_alloc(sizeof(ntlmssp_info));
1527 /* Insert the flags into the conversation */
1528 conv_ntlmssp_info->flags = negotiate_flags;
1529 /* Insert the RC4 state information into the conversation */
1530 tvb_memcpy(tvb, challenge, offset, 8);
1531 tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
1532 conv_ntlmssp_info->is_auth_ntlm_v2=0;
1533 /* Between the challenge and the user provided password, we can build the
1534 NTLMSSP key and initialize the cipher if we are not in EXTENDED SECURITY
1535 in this case we need the client challenge as well*/
1536 /* BTW this is true just if we are in LM Authentification if not the logic is a bit different.
1537 * Right now it's not very clear what is LM Authentification it __seems__ to be when
1538 * NEGOTIATE NT ONLY is not set and NEGOSIATE EXTENDED SECURITY is not set as well*/
1539 if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1541 conv_ntlmssp_info->rc4_state_initialized = 0;
1542 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);
1543 if( memcmp(sspkey,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
1544 get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
1545 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, sspkey, ssp_key_len);
1546 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, sspkey, ssp_key_len);
1547 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1548 conv_ntlmssp_info->rc4_state_initialized = 1;
1552 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1556 /* If no more bytes (ie: no "reserved", ...) before start of data block, then return */
1557 /* XXX: According to Davenport "This form is seen in older Win9x-based systems" */
1558 /* Also: I've seen a capture with an HTTP CONNECT proxy-authentication */
1559 /* message wherein the challenge from the proxy has this form. */
1560 if (offset >= data_start) {
1564 /* Reserved (function not completely known) */
1566 * XXX - SSP key? The davenport document says
1568 * The context field is typically populated when Negotiate Local
1569 * Call is set. It contains an SSPI context handle, which allows
1570 * the client to "short-circuit" authentication and effectively
1571 * circumvent responding to the challenge. Physically, the context
1572 * is two long values. This is covered in greater detail later,
1573 * in the "Local Authentication" section.
1575 * It also says that that information may be omitted.
1577 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
1578 tvb, offset, 8, FALSE);
1582 * The presence or absence of this field is not obviously correlated
1583 * with any flags in the previous NEGOTIATE message or in this
1584 * message (other than the "Workstation Supplied" and "Domain
1585 * Supplied" flags in the NEGOTIATE message, at least in the capture
1586 * I've seen - but those also correlate with the presence of workstation
1587 * and domain name fields, so it doesn't seem to make sense that they
1588 * actually *indicate* whether the subsequent CHALLENGE has an
1591 if (offset < data_start) {
1592 offset = dissect_ntlmssp_challenge_target_info_blob(tvb, offset, ntlmssp_tree, &item_end);
1593 /* XXX: This code assumes that the address list in the data block */
1594 /* is always after the target name. Is this OK ? */
1595 data_end = MAX(data_end, item_end);
1598 /* If there are more bytes before the data block dissect a version field
1599 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1600 if (offset < data_start) {
1601 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1602 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1605 return MAX(offset, data_end);
1609 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
1610 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
1612 int item_start, item_end;
1613 int data_start, data_end = 0;
1614 guint32 negotiate_flags;
1615 guint8 sspkey[NTLMSSP_KEY_LEN]; /* exported session key */
1616 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1617 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1618 guint8 encryptedsessionkey[NTLMSSP_KEY_LEN];
1619 ntlmssp_blob sessionblob;
1620 gboolean unicode_strings = FALSE;
1621 ntlmssp_info *conv_ntlmssp_info = NULL;
1622 conversation_t *conversation;
1625 * Get flag info from the original negotiate message, if any.
1626 * This is because the flag information is sometimes missing from
1627 * the AUTHENTICATE message, so we can't figure out whether
1628 * strings are Unicode or not by looking at *our* flags.
1629 * XXX it seems it's more from the CHALLENGE message, which is more clever in fact
1630 * because the server can change some flags.
1631 * But according to MS NTLMSSP doc it's not that simple.
1632 * In case of Conection less mode AUTHENTICATE flags should be used because they
1633 * reprensent the choice of the client after having been informed of options of the
1634 * server in the CHALLENGE message.
1635 * In Connection mode then the CHALLENGE flags should (must ?) be used
1636 * XXX: MS-NLMP says the flag field in the AUTHENTICATE message "contains the set of bit
1637 * flags (section 2.2.2.5) negotiated in the previous messages."
1638 * I read that to mean that the flags for in connection-mode AUTHENTICATE also represent
1639 * the choice of the client (for the flags which are negotiated).
1640 * XXX: In the absence of CHALLENGE flags, as a last resort we'll use the flags
1641 * (if available) from this AUTHENTICATE message.
1642 * I've seen a capture which does an HTTP CONNECT which:
1643 * - has the NEGOTIATE & CHALLENGE messages in one TCP connection;
1644 * - has the AUTHENTICATE message in a second TCP connection;
1645 * (The authentication aparently succeeded).
1647 conv_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
1648 if (conv_ntlmssp_info == NULL) {
1650 * There isn't any. Is there any from this conversation? If so,
1651 * it means this is the first time we've dissected this frame, so
1652 * we should give it flag info.
1654 /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
1655 /* so we'll have a place to store flags. */
1656 /* This is a bit brute-force but looks like it will be OK. */
1657 conversation = find_or_create_conversation(pinfo);
1658 conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
1659 if (conv_ntlmssp_info == NULL) {
1660 conv_ntlmssp_info = se_alloc0(sizeof(ntlmssp_info));
1661 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1663 /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
1664 same as the one attached to the conversation. That is: *both* point to
1665 the exact same struct in memory. Is this what is indended ? */
1666 p_add_proto_data(pinfo->fd, proto_ntlmssp, conv_ntlmssp_info);
1669 if (conv_ntlmssp_info != NULL) {
1670 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
1671 unicode_strings = TRUE;
1675 * Sometimes the session key and flags are missing.
1676 * Sometimes the session key is present but the flags are missing.
1677 * XXX Who stay so ? Reading spec I would rather say the opposite: flags are
1678 * always present, session information are always there as well but sometime
1679 * session information could be null (in case of no session)
1680 * Sometimes they're both present.
1682 * This does not correlate with any flags in the previous CHALLENGE
1683 * message, and only correlates with "Negotiate Unicode", "Workstation
1684 * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
1685 * those don't make sense as flags to use to determine this.
1687 * So we check all of the descriptors to figure out where the data
1688 * area begins, and if the session key or the flags would be in the
1689 * middle of the data area, we assume the field in question is
1692 * XXX - Reading Davenport and MS-NLMP: as I see it the possibilities are:
1693 * a. No session-key; no flags; no version ("Win9x")
1694 * b. Session-key & flags.
1695 * c. Session-key, flags & version.
1696 * In cases b and c the session key may be "null".
1700 /* Lan Manager response */
1701 data_start = tvb_get_letohl(tvb, offset+4);
1702 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1703 hf_ntlmssp_auth_lmresponse,
1705 conv_ntlmssp_info == NULL ? NULL :
1706 &conv_ntlmssp_info->lm_response);
1707 data_end = MAX(data_end, item_end);
1710 item_start = tvb_get_letohl(tvb, offset+4);
1711 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1712 hf_ntlmssp_auth_ntresponse,
1714 conv_ntlmssp_info == NULL ? NULL :
1715 &conv_ntlmssp_info->ntlm_response);
1716 if( conv_ntlmssp_info != NULL && conv_ntlmssp_info->ntlm_response.length > 24 ) {
1717 memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->ntlm_response.contents+32,8);
1719 data_start = MIN(data_start, item_start);
1720 data_end = MAX(data_end, item_end);
1721 if( conv_ntlmssp_info != NULL )
1723 if( conv_ntlmssp_info->ntlm_response.length > 24 )
1725 conv_ntlmssp_info->is_auth_ntlm_v2=1;
1729 conv_ntlmssp_info->is_auth_ntlm_v2=0;
1734 item_start = tvb_get_letohl(tvb, offset+4);
1735 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1737 hf_ntlmssp_auth_domain,
1738 &item_start, &item_end, &(ntlmssph->domain_name));
1739 /*ntlmssph->domain_name_len=item_end-item_start;*/
1740 data_start = MIN(data_start, item_start);
1741 data_end = MAX(data_end, item_end);
1744 item_start = tvb_get_letohl(tvb, offset+4);
1745 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1747 hf_ntlmssp_auth_username,
1748 &item_start, &item_end, &(ntlmssph->acct_name));
1749 /*ntlmssph->acct_name_len=item_end-item_start;*/
1750 data_start = MIN(data_start, item_start);
1751 data_end = MAX(data_end, item_end);
1753 col_append_fstr(pinfo->cinfo, COL_INFO, ", User: %s\\%s",
1754 ntlmssph->domain_name, ntlmssph->acct_name);
1757 item_start = tvb_get_letohl(tvb, offset+4);
1758 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1760 hf_ntlmssp_auth_hostname,
1761 &item_start, &item_end, &(ntlmssph->host_name));
1762 data_start = MIN(data_start, item_start);
1763 data_end = MAX(data_end, item_end);
1765 memset(sessionblob.contents, 0, MAX_BLOB_SIZE);
1766 sessionblob.length = 0;
1767 if (offset < data_start) {
1769 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1770 hf_ntlmssp_auth_sesskey,
1771 &item_end, &sessionblob);
1772 data_end = MAX(data_end, item_end);
1775 if (offset < data_start) {
1776 /* NTLMSSP Negotiate Flags */
1777 negotiate_flags = tvb_get_letohl (tvb, offset);
1778 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1780 /* If no previous flags seen (ie: no previous CHALLENGE) use flags
1781 from the AUTHENTICATE message).
1782 Assumption: (flags == 0) means flags not previously seen */
1783 if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
1784 conv_ntlmssp_info->flags = negotiate_flags;
1787 negotiate_flags = 0;
1789 /* If there are more bytes before the data block dissect a version field
1790 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1791 if (offset < data_start) {
1792 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1793 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1796 /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
1798 if (offset < data_start) {
1799 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_message_integrity_code, tvb, offset, 16, ENC_NA);
1803 if ( sessionblob.length > NTLMSSP_KEY_LEN ) {
1804 expert_add_info_format(pinfo, NULL, PI_WARN, PI_UNDECODED, "Session blob length too long: %u", sessionblob.length);
1805 } else if( sessionblob.length != 0 ) {
1806 memcpy(encryptedsessionkey,sessionblob.contents,sessionblob.length);
1807 /* Try to attach to an existing conversation if not then it's useless to try to do so
1808 * because we are missing important information (ie. server challenge)
1810 if (conv_ntlmssp_info) {
1811 /* If we are in EXTENDED SECURITY then we can now initialize cipher */
1812 if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1814 conv_ntlmssp_info->rc4_state_initialized = 0;
1815 if( conv_ntlmssp_info->is_auth_ntlm_v2 ) {
1816 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);
1820 memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->lm_response.contents,8);
1821 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);
1823 /* ssp is the exported session key */
1824 if( memcmp(sspkey,gbl_zeros,NTLMSSP_KEY_LEN) != 0) {
1825 get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
1826 get_siging_key((guint8*)&conv_ntlmssp_info->sign_key_server,(guint8*)&conv_ntlmssp_info->sign_key_client,sspkey,ssp_key_len);
1827 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, serverkey, ssp_key_len);
1828 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, clientkey, ssp_key_len);
1829 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1830 conv_ntlmssp_info->rc4_state_initialized = 1;
1835 return MAX(offset, data_end);
1839 get_sign_key(packet_info *pinfo, int cryptpeer)
1841 conversation_t *conversation;
1842 ntlmssp_info *conv_ntlmssp_info;
1844 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1845 pinfo->ptype, pinfo->srcport,
1846 pinfo->destport, 0);
1847 if (conversation == NULL) {
1848 /* We don't have a conversation. In this case, stop processing
1849 because we do not have enough info to decrypt the payload */
1853 /* We have a conversation, check for encryption state */
1854 conv_ntlmssp_info = conversation_get_proto_data(conversation,
1856 if (conv_ntlmssp_info == NULL) {
1857 /* No encryption state tied to the conversation. Therefore, we
1858 cannot decrypt the payload */
1862 /* We have the encryption state in the conversation. So return the
1863 crypt state tied to the requested peer
1865 if (cryptpeer == 1) {
1866 return (guint8*)&conv_ntlmssp_info->sign_key_client;
1868 return (guint8*)&conv_ntlmssp_info->sign_key_server;
1875 * Get the encryption state tied to this conversation. cryptpeer indicates
1876 * whether to retrieve the client key (1) or the server key (0)
1878 static rc4_state_struct *
1879 get_encrypted_state(packet_info *pinfo, int cryptpeer)
1881 conversation_t *conversation;
1882 ntlmssp_info *conv_ntlmssp_info;
1884 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1885 pinfo->ptype, pinfo->srcport,
1886 pinfo->destport, 0);
1887 if (conversation == NULL) {
1888 /* We don't have a conversation. In this case, stop processing
1889 because we do not have enough info to decrypt the payload */
1893 /* We have a conversation, check for encryption state */
1894 conv_ntlmssp_info = conversation_get_proto_data(conversation,
1896 if (conv_ntlmssp_info == NULL) {
1897 /* No encryption state tied to the conversation. Therefore, we
1898 cannot decrypt the payload */
1902 /* We have the encryption state in the conversation. So return the
1903 crypt state tied to the requested peer
1905 if (cryptpeer == 1) {
1906 return &conv_ntlmssp_info->rc4_state_client;
1908 return &conv_ntlmssp_info->rc4_state_server;
1915 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1916 packet_info *pinfo, proto_tree *tree _U_,gpointer key);
1918 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1919 packet_info *pinfo, proto_tree *tree,gpointer key);
1923 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
1924 tvbuff_t *auth_tvb _U_,
1927 dcerpc_auth_info *auth_info _U_)
1931 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1933 volatile int offset = 0;
1934 proto_tree *volatile ntlmssp_tree = NULL;
1935 proto_item *tf = NULL;
1937 guint32 encrypted_block_length;
1938 guint8 key[NTLMSSP_KEY_LEN];
1939 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
1941 guint32 ntlm_magic_size = 4;
1942 guint32 ntlm_signature_size = 8;
1943 guint32 ntlm_seq_size = 4;
1946 length = tvb_length (tvb);
1947 /* signature + seq + real payload */
1948 encrypted_block_length = length - ntlm_magic_size;
1950 if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
1951 /* Don't know why this would happen, but if it does, don't even bother
1952 attempting decryption/dissection */
1953 return offset + length;
1956 /* Setup a new tree for the NTLMSSP payload */
1958 tf = proto_tree_add_item (tree,
1960 tvb, offset, -1, FALSE);
1962 ntlmssp_tree = proto_item_add_subtree (tf,
1967 * Catch the ReportedBoundsError exception; the stuff we've been
1968 * handed doesn't necessarily run to the end of the packet, it's
1969 * an item inside a packet, so if it happens to be malformed (or
1970 * we, or a dissector we call, has a bug), so that an exception
1971 * is thrown, we want to report the error, but return and let
1972 * our caller dissect the rest of the packet.
1974 * If it gets a BoundsError, we can stop, as there's nothing more
1975 * in the packet after our blob to see, so we just re-throw the
1978 pd_save = pinfo->private_data;
1980 /* Version number */
1981 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
1982 tvb, offset, 4, TRUE);
1985 /* Encrypted body */
1986 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
1987 tvb, offset, ntlm_signature_size + ntlm_seq_size, TRUE);
1988 tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
1989 /* Try to decrypt */
1990 decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree,key);
1991 decrypt_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo, ntlmssp_tree,key);
1992 /* let's try to hook ourselves here */
1995 } CATCH(BoundsError) {
1997 } CATCH(ReportedBoundsError) {
1998 /* Restore the private_data structure in case one of the
1999 * called dissectors modified it (and, due to the exception,
2000 * was unable to restore it).
2002 pinfo->private_data = pd_save;
2003 show_reported_bounds_error(tvb, pinfo, tree);
2010 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
2011 packet_info *pinfo, proto_tree *tree _U_,gpointer key)
2013 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2015 conversation_t *conversation;
2016 rc4_state_struct *rc4_state;
2017 rc4_state_struct *rc4_state_peer;
2018 ntlmssp_info *conv_ntlmssp_info = NULL;
2019 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2020 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2022 /* Check to see if we already have state for this packet */
2023 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2024 if (packet_ntlmssp_info == NULL) {
2025 /* We don't have any packet state, so create one */
2026 packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
2027 p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
2029 if (!packet_ntlmssp_info->payload_decrypted) {
2030 /* Pull the challenge info from the conversation */
2031 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2032 pinfo->ptype, pinfo->srcport,
2033 pinfo->destport, 0);
2034 if (conversation == NULL) {
2035 /* There is no conversation, thus no encryption state */
2039 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2041 if (conv_ntlmssp_info == NULL) {
2042 /* There is no NTLMSSP state tied to the conversation */
2045 if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
2046 /* The crypto sybsystem is not initialized. This means that either
2047 the conversation did not include a challenge, or that we do not have the right password */
2051 stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
2053 if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == TRUE)
2055 /* Mat TBD (stderr,"Found a already decrypted packet\n");*/
2056 memcpy(packet_ntlmssp_info,stored_packet_ntlmssp_info,sizeof(ntlmssp_packet_info));
2057 /* Mat TBD printnbyte(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"Data: ","\n");*/
2061 /* Get the pair of RC4 state structures. One is used for to decrypt the
2062 payload. The other is used to re-encrypt the payload to represent
2064 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2066 rc4_state = get_encrypted_state(pinfo, 1);
2067 rc4_state_peer = get_encrypted_state(pinfo, 0);
2070 rc4_state = get_encrypted_state(pinfo, 0);
2071 rc4_state_peer = get_encrypted_state(pinfo, 1);
2074 if (rc4_state == NULL ) {
2075 /* There is no encryption state, so we cannot decrypt */
2079 /* Store the decrypted contents in the packet state struct
2080 (of course at this point, they aren't decrypted yet) */
2081 packet_ntlmssp_info->decrypted_payload = tvb_memdup(tvb, offset,
2082 encrypted_block_length);
2083 packet_ntlmssp_info->payload_len = encrypted_block_length;
2084 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2085 packet_ntlmssp_info->decrypted_payload);
2087 g_hash_table_insert(hash_packet,key,packet_ntlmssp_info);
2090 /* Do the decryption of the payload */
2091 crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
2092 encrypted_block_length);
2093 /* decrypt the verifier */
2094 /*printnchar(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"data: ","\n");*/
2095 /* We setup a temporary buffer so we can re-encrypt the payload after
2096 decryption. This is to update the opposite peer's RC4 state
2097 it's usefull when we have only one key for both conversation
2098 in case of KEY_EXCH we have independant key so this is not needed*/
2099 if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2100 peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2101 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2104 packet_ntlmssp_info->payload_decrypted = TRUE;
2108 /* Show the decrypted buffer in a new window */
2109 decr_tvb = tvb_new_real_data(packet_ntlmssp_info->decrypted_payload,
2110 encrypted_block_length,
2111 encrypted_block_length);
2113 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2114 pinfo->gssapi_decrypted_tvb = decr_tvb;
2118 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2120 volatile int offset = 0;
2121 proto_tree *volatile ntlmssp_tree = NULL;
2122 proto_item *tf = NULL;
2123 ntlmssp_header_t *ntlmssph;
2126 ntlmssph=ep_alloc(sizeof(ntlmssp_header_t));
2128 ntlmssph->domain_name=NULL;
2129 ntlmssph->acct_name=NULL;
2130 ntlmssph->host_name=NULL;
2132 /* Setup a new tree for the NTLMSSP payload */
2134 tf = proto_tree_add_item (tree,
2136 tvb, offset, -1, FALSE);
2138 ntlmssp_tree = proto_item_add_subtree (tf,
2143 * Catch the ReportedBoundsError exception; the stuff we've been
2144 * handed doesn't necessarily run to the end of the packet, it's
2145 * an item inside a packet, so if it happens to be malformed (or
2146 * we, or a dissector we call, has a bug), so that an exception
2147 * is thrown, we want to report the error, but return and let
2148 * our caller dissect the rest of the packet.
2150 * If it gets a BoundsError, we can stop, as there's nothing more
2151 * in the packet after our blob to see, so we just re-throw the
2154 pd_save = pinfo->private_data;
2156 /* NTLMSSP constant */
2157 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
2158 tvb, offset, 8, FALSE);
2161 /* NTLMSSP Message Type */
2162 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
2163 tvb, offset, 4, TRUE);
2164 ntlmssph->type = tvb_get_letohl (tvb, offset);
2167 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2168 val_to_str(ntlmssph->type,
2169 ntlmssp_message_types,
2170 "Unknown message type"));
2172 /* Call the appropriate dissector based on the Message Type */
2173 switch (ntlmssph->type) {
2175 case NTLMSSP_NEGOTIATE:
2176 offset = dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree, ntlmssph);
2179 case NTLMSSP_CHALLENGE:
2180 offset = dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2184 offset = dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2188 /* Unrecognized message type */
2189 proto_tree_add_text (ntlmssp_tree, tvb, offset, -1,
2190 "Unrecognized NTLMSSP Message");
2193 } CATCH(BoundsError) {
2195 } CATCH(ReportedBoundsError) {
2196 /* Restore the private_data structure in case one of the
2197 * called dissectors modified it (and, due to the exception,
2198 * was unable to restore it).
2200 pinfo->private_data = pd_save;
2201 show_reported_bounds_error(tvb, pinfo, tree);
2204 /*tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);*/
2210 * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
2213 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
2214 packet_info *pinfo, proto_tree *tree,gpointer key)
2216 proto_tree *decr_tree = NULL;
2217 proto_item *tf = NULL;
2218 conversation_t *conversation;
2220 rc4_state_struct *rc4_state;
2221 rc4_state_struct *rc4_state_peer;
2222 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2225 guint8 calculated_md5[NTLMSSP_KEY_LEN];
2226 ntlmssp_info *conv_ntlmssp_info = NULL;
2227 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2228 int decrypted_offset = 0;
2231 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2232 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2233 if (packet_ntlmssp_info == NULL) {
2234 /* We don't have data for this packet */
2237 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2238 pinfo->ptype, pinfo->srcport,
2239 pinfo->destport, 0);
2240 if (conversation == NULL) {
2241 /* There is no conversation, thus no encryption state */
2244 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2246 if (conv_ntlmssp_info == NULL) {
2247 /* There is no NTLMSSP state tied to the conversation */
2252 stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
2254 if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->verifier_decrypted == TRUE) {
2255 /* Mat TBD fprintf(stderr,"Found a already decrypted packet\n");*/
2256 /* In Theory it's aleady the case, and we should be more clever ... like just copying buffers ...*/
2257 packet_ntlmssp_info = stored_packet_ntlmssp_info;
2260 if (!packet_ntlmssp_info->verifier_decrypted) {
2261 if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
2262 /* The crypto sybsystem is not initialized. This means that either
2263 the conversation did not include a challenge, or we are doing
2264 something other than NTLMSSP v1 */
2267 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2268 /* client talk to server */
2269 rc4_state = get_encrypted_state(pinfo, 1);
2270 sign_key = get_sign_key(pinfo,1);
2271 rc4_state_peer = get_encrypted_state(pinfo, 0);
2273 rc4_state = get_encrypted_state(pinfo, 0);
2274 sign_key = get_sign_key(pinfo,0);
2275 rc4_state_peer = get_encrypted_state(pinfo, 1);
2278 if (rc4_state == NULL || rc4_state_peer == NULL) {
2279 /* There is no encryption state, so we cannot decrypt */
2283 /* Setup the buffer to decrypt to */
2284 tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
2285 offset, encrypted_block_length);
2287 /*if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
2288 if( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
2289 if( (NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2290 /* The spec says that if we have have a key exchange then we have a the signature that is crypted
2291 * otherwise it's just a hmac_md5(keysign,concat(message,sequence))[0..7]
2293 crypt_rc4(rc4_state, packet_ntlmssp_info->verifier, 8);
2296 * Try to check the HMAC MD5 of the message against those calculated works great with LDAP payload but
2297 * don't with DCE/RPC calls.
2298 * Some analysis need to be done ...
2300 if( sign_key != NULL ) {
2301 check_buf = ep_alloc(packet_ntlmssp_info->payload_len+4);
2302 tvb_memcpy(tvb, &sequence,offset+8,4);
2303 memcpy(check_buf,&sequence,4);
2304 memcpy(check_buf+4,packet_ntlmssp_info->decrypted_payload,packet_ntlmssp_info->payload_len);
2305 md5_hmac(check_buf,(int)(packet_ntlmssp_info->payload_len+4),sign_key,NTLMSSP_KEY_LEN,calculated_md5);
2307 printnbyte(packet_ntlmssp_info->verifier,8,"HMAC from packet: ","\n");
2308 printnbyte(calculated_md5,8,"HMAC : ","\n");
2313 /* 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 */
2314 /* Do the actual decryption of the verifier */
2315 crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
2316 encrypted_block_length);
2321 /* We setup a temporary buffer so we can re-encrypt the payload after
2322 decryption. This is to update the opposite peer's RC4 state
2323 This is not needed when we just have EXTENDED SECURITY because the signature is not crypted
2324 and it's also not needed when we have key exchange because server and client have independant keys */
2325 if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SECURITY & conv_ntlmssp_info->flags)) {
2326 peer_block = ep_memdup(packet_ntlmssp_info->verifier, encrypted_block_length);
2327 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2330 /* Mark the packet as decrypted so that subsequent attempts to dissect
2331 the packet use the already decrypted payload instead of attempting
2333 packet_ntlmssp_info->verifier_decrypted = TRUE;
2336 /* Show the decrypted buffer in a new window */
2337 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
2338 encrypted_block_length,
2339 encrypted_block_length);
2340 add_new_data_source(pinfo, decr_tvb,
2341 "Decrypted NTLMSSP Verifier");
2343 /* Show the decrypted payload in the tree */
2344 tf = proto_tree_add_text(tree, decr_tvb, 0, -1,
2345 "Decrypted Verifier (%d byte%s)",
2346 encrypted_block_length,
2347 plurality(encrypted_block_length, "", "s"));
2348 decr_tree = proto_item_add_subtree (tf, ett_ntlmssp);
2350 if(( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
2351 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
2352 decr_tvb, decrypted_offset, 8,TRUE);
2353 decrypted_offset += 8;
2357 /* Incrementing sequence number of DCE conversation */
2358 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2359 decr_tvb, decrypted_offset, 4, TRUE);
2360 decrypted_offset += 4;
2364 /* RANDOM PAD usually it's 0 */
2365 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
2366 decr_tvb, decrypted_offset, 4, TRUE);
2367 decrypted_offset += 4;
2369 /* CRC32 of the DCE fragment data */
2370 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
2371 decr_tvb, decrypted_offset, 4, TRUE);
2372 decrypted_offset += 4;
2374 /* Incrementing sequence number of DCE conversation */
2375 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2376 decr_tvb, decrypted_offset, 4, TRUE);
2377 decrypted_offset += 4;
2381 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious*/
2383 dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *tree)
2385 volatile int offset = 0;
2386 proto_tree *volatile ntlmssp_tree = NULL;
2387 guint32 encrypted_block_length;
2390 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
2392 encrypted_block_length = tvb_length (tvb);
2393 /* signature + seq + real payload */
2395 /* Setup a new tree for the NTLMSSP payload */
2398 tf = proto_tree_add_item (tree,
2400 tvb, offset, -1, FALSE);
2402 ntlmssp_tree = proto_item_add_subtree (tf,
2407 * Catch the ReportedBoundsError exception; the stuff we've been
2408 * handed doesn't necessarily run to the end of the packet, it's
2409 * an item inside a packet, so if it happens to be malformed (or
2410 * we, or a dissector we call, has a bug), so that an exception
2411 * is thrown, we want to report the error, but return and let
2412 * our caller dissect the rest of the packet.
2414 * If it gets a BoundsError, we can stop, as there's nothing more
2415 * in the packet after our blob to see, so we just re-throw the
2418 pd_save = pinfo->private_data;
2420 /* Version number */
2422 /* Try to decrypt */
2423 decrypt_data_payload (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
2424 /* let's try to hook ourselves here */
2426 } CATCH(BoundsError) {
2428 } CATCH(ReportedBoundsError) {
2429 /* Restore the private_data structure in case one of the
2430 * called dissectors modified it (and, due to the exception,
2431 * was unable to restore it).
2433 pinfo->private_data = pd_save;
2434 show_reported_bounds_error(tvb, pinfo, tree);
2440 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious
2441 * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
2444 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2446 volatile int offset = 0;
2447 proto_tree *volatile ntlmssp_tree = NULL;
2448 proto_item *tf = NULL;
2449 guint32 verifier_length;
2450 guint32 encrypted_block_length;
2453 verifier_length = tvb_length (tvb);
2454 encrypted_block_length = verifier_length - 4;
2456 if (encrypted_block_length < 12) {
2457 /* Don't know why this would happen, but if it does, don't even bother
2458 attempting decryption/dissection */
2459 return offset + verifier_length;
2462 /* Setup a new tree for the NTLMSSP payload */
2464 tf = proto_tree_add_item (tree,
2466 tvb, offset, -1, FALSE);
2468 ntlmssp_tree = proto_item_add_subtree (tf,
2473 * Catch the ReportedBoundsError exception; the stuff we've been
2474 * handed doesn't necessarily run to the end of the packet, it's
2475 * an item inside a packet, so if it happens to be malformed (or
2476 * we, or a dissector we call, has a bug), so that an exception
2477 * is thrown, we want to report the error, but return and let
2478 * our caller dissect the rest of the packet.
2480 * If it gets a BoundsError, we can stop, as there's nothing more
2481 * in the packet after our blob to see, so we just re-throw the
2484 pd_save = pinfo->private_data;
2486 /* Version number */
2487 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2488 tvb, offset, 4, TRUE);
2491 /* Encrypted body */
2492 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2493 tvb, offset, encrypted_block_length, TRUE);
2495 /* Try to decrypt */
2496 decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
2497 /* let's try to hook ourselves here */
2500 offset += encrypted_block_length;
2501 } CATCH(BoundsError) {
2503 } CATCH(ReportedBoundsError) {
2504 /* Restore the private_data structure in case one of the
2505 * called dissectors modified it (and, due to the exception,
2506 * was unable to restore it).
2508 pinfo->private_data = pd_save;
2509 show_reported_bounds_error(tvb, pinfo, tree);
2516 wrap_dissect_ntlmssp_payload_only(tvbuff_t *tvb,tvbuff_t *auth_tvb _U_,
2517 int offset, packet_info *pinfo,dcerpc_auth_info *auth_info _U_)
2521 data_tvb = tvb_new_subset(
2522 tvb, offset, tvb_length_remaining(tvb, offset),
2523 tvb_length_remaining(tvb, offset));
2524 dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL);
2525 return pinfo->gssapi_decrypted_tvb;
2530 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
2531 tvbuff_t *auth_tvb _U_,
2534 dcerpc_auth_info *auth_info _U_)
2536 /* gssapi_decrypted_tvb=NULL */
2537 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2539 conversation_t *conversation;
2540 guint32 encrypted_block_length;
2541 rc4_state_struct *rc4_state;
2542 rc4_state_struct *rc4_state_peer;
2543 ntlmssp_info *conv_ntlmssp_info = NULL;
2544 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2545 encrypted_block_length = tvb_length_remaining (data_tvb, offset);
2547 fprintf(stderr,"Called dissect_ntlmssp_encrypted_payload\n");
2548 /* Check to see if we already have state for this packet */
2549 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2550 if (packet_ntlmssp_info == NULL) {
2551 /* We don't have any packet state, so create one */
2552 packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
2553 p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
2556 if (!packet_ntlmssp_info->payload_decrypted) {
2557 /* Pull the challenge info from the conversation */
2558 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2559 pinfo->ptype, pinfo->srcport,
2560 pinfo->destport, 0);
2561 if (conversation == NULL) {
2562 /* There is no conversation, thus no encryption state */
2566 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2568 if (conv_ntlmssp_info == NULL) {
2569 /* There is no NTLMSSP state tied to the conversation */
2572 /* Get the pair of RC4 state structures. One is used for to decrypt the
2573 payload. The other is used to re-encrypt the payload to represent
2575 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2576 rc4_state = get_encrypted_state(pinfo, 1);
2577 rc4_state_peer = get_encrypted_state(pinfo, 0);
2579 rc4_state = get_encrypted_state(pinfo, 0);
2580 rc4_state_peer = get_encrypted_state(pinfo, 1);
2583 if (rc4_state == NULL || rc4_state_peer == NULL) {
2584 /* There is no encryption state, so we cannot decrypt */
2588 /* Store the decrypted contents in the packet state struct
2589 (of course at this point, they aren't decrypted yet) */
2590 packet_ntlmssp_info->decrypted_payload = tvb_memdup(data_tvb, offset,
2591 encrypted_block_length);
2592 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2593 packet_ntlmssp_info->decrypted_payload);
2595 /* Do the decryption of the payload */
2596 crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
2597 encrypted_block_length);
2599 /* We setup a temporary buffer so we can re-encrypt the payload after
2600 decryption. This is to update the opposite peer's RC4 state */
2601 peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2602 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2604 packet_ntlmssp_info->payload_decrypted = TRUE;
2607 /* Show the decrypted buffer in a new window */
2608 decr_tvb = tvb_new_child_real_data(data_tvb, packet_ntlmssp_info->decrypted_payload,
2609 encrypted_block_length,
2610 encrypted_block_length);
2612 offset += encrypted_block_length;
2619 free_payload(gpointer decrypted_payload, gpointer user_data _U_)
2621 g_free(decrypted_payload);
2625 header_hash(gconstpointer pointer)
2627 guint32 crc = ~crc32c_calculate(pointer,NTLMSSP_KEY_LEN,CRC32C_PRELOAD);
2628 /* Mat TBD fprintf(stderr,"Val: %u\n",crc);*/
2633 header_equal(gconstpointer pointer1, gconstpointer pointer2)
2635 if(!memcmp(pointer1,pointer2,16)) {
2644 ntlmssp_init_protocol(void)
2647 * Free the decrypted payloads, and then free the list of decrypted
2650 if (decrypted_payloads != NULL) {
2651 g_slist_foreach(decrypted_payloads, free_payload, NULL);
2652 g_slist_free(decrypted_payloads);
2653 decrypted_payloads = NULL;
2656 if(hash_packet == NULL) {
2657 hash_packet = g_hash_table_new(header_hash, header_equal);
2665 wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
2666 proto_tree *tree, guint8 *drep _U_)
2670 auth_tvb = tvb_new_subset(
2671 tvb, offset, tvb_length_remaining(tvb, offset),
2672 tvb_length_remaining(tvb, offset));
2674 dissect_ntlmssp(auth_tvb, pinfo, tree);
2676 return tvb_length_remaining(tvb, offset);
2680 wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
2681 proto_tree *tree, guint8 *drep _U_)
2685 auth_tvb = tvb_new_subset(
2686 tvb, offset, tvb_length_remaining(tvb, offset),
2687 tvb_length_remaining(tvb, offset));
2688 return dissect_ntlmssp_verf(auth_tvb, pinfo, tree);
2691 static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
2692 wrap_dissect_ntlmssp, /* Bind */
2693 wrap_dissect_ntlmssp, /* Bind ACK */
2694 wrap_dissect_ntlmssp, /* AUTH3 */
2695 wrap_dissect_ntlmssp_verf, /* Request verifier */
2696 wrap_dissect_ntlmssp_verf, /* Response verifier */
2697 NULL, /* Request data */
2698 NULL /* Response data */
2701 static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
2702 wrap_dissect_ntlmssp, /* Bind */
2703 wrap_dissect_ntlmssp, /* Bind ACK */
2704 wrap_dissect_ntlmssp, /* AUTH3 */
2705 wrap_dissect_ntlmssp_verf, /* Request verifier */
2706 wrap_dissect_ntlmssp_verf, /* Response verifier */
2707 wrap_dissect_ntlmssp_payload_only, /* Request data */
2708 wrap_dissect_ntlmssp_payload_only /* Response data */
2712 proto_register_ntlmssp(void)
2715 static hf_register_info hf[] = {
2717 { "NTLMSSP identifier", "ntlmssp.identifier", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2718 { &hf_ntlmssp_message_type,
2719 { "NTLM Message Type", "ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, NULL, HFILL }},
2720 { &hf_ntlmssp_negotiate_flags,
2721 { "Flags", "ntlmssp.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2722 { &hf_ntlmssp_negotiate_flags_01,
2723 { "Negotiate UNICODE", "ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_UNICODE, NULL, HFILL }},
2724 { &hf_ntlmssp_negotiate_flags_02,
2725 { "Negotiate OEM", "ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM, NULL, HFILL }},
2726 { &hf_ntlmssp_negotiate_flags_04,
2727 { "Request Target", "ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_TARGET, NULL, HFILL }},
2728 { &hf_ntlmssp_negotiate_flags_08,
2729 { "Request 0x00000008", "ntlmssp.negotiate00000008", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000008, NULL, HFILL }},
2730 { &hf_ntlmssp_negotiate_flags_10,
2731 { "Negotiate Sign", "ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SIGN, NULL, HFILL }},
2732 { &hf_ntlmssp_negotiate_flags_20,
2733 { "Negotiate Seal", "ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SEAL, NULL, HFILL }},
2734 { &hf_ntlmssp_negotiate_flags_40,
2735 { "Negotiate Datagram", "ntlmssp.negotiatedatagram", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_DATAGRAM, NULL, HFILL }},
2736 { &hf_ntlmssp_negotiate_flags_80,
2737 { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_LM_KEY, NULL, HFILL }},
2738 { &hf_ntlmssp_negotiate_flags_100,
2739 { "Negotiate 0x00000100", "ntlmssp.negotiate00000100", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000100, NULL, HFILL }},
2740 { &hf_ntlmssp_negotiate_flags_200,
2741 { "Negotiate NTLM key", "ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NTLM, NULL, HFILL }},
2742 { &hf_ntlmssp_negotiate_flags_400,
2743 { "Negotiate NT Only", "ntlmssp.negotiatentonly", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NT_ONLY, NULL, HFILL }},
2744 { &hf_ntlmssp_negotiate_flags_800,
2745 { "Negotiate 0x00000800", "ntlmssp.negotiate00000800", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000800, NULL, HFILL }},
2746 { &hf_ntlmssp_negotiate_flags_1000,
2747 { "Negotiate OEM Domain Supplied", "ntlmssp.negotiateoemdomainsupplied", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED, NULL, HFILL }},
2748 { &hf_ntlmssp_negotiate_flags_2000,
2749 { "Negotiate OEM Workstation Supplied", "ntlmssp.negotiateoemworkstationsupplied", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED, NULL, HFILL }},
2750 { &hf_ntlmssp_negotiate_flags_4000,
2751 { "Negotiate 0x00004000", "ntlmssp.negotiate00004000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00004000, NULL, HFILL }},
2752 { &hf_ntlmssp_negotiate_flags_8000,
2753 { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, NULL, HFILL }},
2754 { &hf_ntlmssp_negotiate_flags_10000,
2755 { "Target Type Domain", "ntlmssp.targettypedomain", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_DOMAIN, NULL, HFILL }},
2756 { &hf_ntlmssp_negotiate_flags_20000,
2757 { "Target Type Server", "ntlmssp.targettypeserver", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER, NULL, HFILL }},
2758 { &hf_ntlmssp_negotiate_flags_40000,
2759 { "Target Type Share", "ntlmssp.targettypeshare", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SHARE, NULL, HFILL }},
2761 /* Negotiate Flags */
2762 { &hf_ntlmssp_negotiate_flags_80000,
2763 { "Negotiate Extended Security", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SECURITY, NULL, HFILL }},
2764 { &hf_ntlmssp_negotiate_flags_100000,
2765 { "Negotiate Identify", "ntlmssp.negotiateidentify", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_IDENTIFY, NULL, HFILL }},
2766 { &hf_ntlmssp_negotiate_flags_200000,
2767 { "Negotiate 0x00200000", "ntlmssp.negotiatent00200000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00200000, NULL, HFILL }},
2768 { &hf_ntlmssp_negotiate_flags_400000,
2769 { "Request Non-NT Session", "ntlmssp.requestnonntsession", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_NON_NT_SESSION, NULL, HFILL }},
2770 { &hf_ntlmssp_negotiate_flags_800000,
2771 { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_TARGET_INFO, NULL, HFILL }},
2772 { &hf_ntlmssp_negotiate_flags_1000000,
2773 { "Negotiate 0x01000000", "ntlmssp.negotiatent01000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_01000000, NULL, HFILL }},
2774 { &hf_ntlmssp_negotiate_flags_2000000,
2775 { "Negotiate Version", "ntlmssp.negotiateversion", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_VERSION, NULL, HFILL }},
2776 { &hf_ntlmssp_negotiate_flags_4000000,
2777 { "Negotiate 0x04000000", "ntlmssp.negotiatent04000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_04000000, NULL, HFILL }},
2778 { &hf_ntlmssp_negotiate_flags_8000000,
2779 { "Negotiate 0x08000000", "ntlmssp.negotiatent08000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_08000000, NULL, HFILL }},
2780 { &hf_ntlmssp_negotiate_flags_10000000,
2781 { "Negotiate 0x10000000", "ntlmssp.negotiatent10000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_10000000, NULL, HFILL }},
2782 { &hf_ntlmssp_negotiate_flags_20000000,
2783 { "Negotiate 128", "ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_128, "128-bit encryption is supported", HFILL }},
2784 { &hf_ntlmssp_negotiate_flags_40000000,
2785 { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_KEY_EXCH, NULL, HFILL }},
2786 { &hf_ntlmssp_negotiate_flags_80000000,
2787 { "Negotiate 56", "ntlmssp.negotiate56", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_56, "56-bit encryption is supported", HFILL }},
2788 { &hf_ntlmssp_negotiate_workstation_strlen,
2789 { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2790 { &hf_ntlmssp_negotiate_workstation_maxlen,
2791 { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2792 { &hf_ntlmssp_negotiate_workstation_buffer,
2793 { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2794 { &hf_ntlmssp_negotiate_workstation,
2795 { "Calling workstation name", "ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2796 { &hf_ntlmssp_negotiate_domain_strlen,
2797 { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2798 { &hf_ntlmssp_negotiate_domain_maxlen,
2799 { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2800 { &hf_ntlmssp_negotiate_domain_buffer,
2801 { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2802 { &hf_ntlmssp_negotiate_domain,
2803 { "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2804 { &hf_ntlmssp_ntlm_client_challenge,
2805 { "NTLM Client Challenge", "ntlmssp.ntlmclientchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2806 { &hf_ntlmssp_ntlm_server_challenge,
2807 { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2808 { &hf_ntlmssp_reserved,
2809 { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2811 { &hf_ntlmssp_challenge_target_name,
2812 { "Target Name", "ntlmssp.challenge.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2813 { &hf_ntlmssp_auth_domain,
2814 { "Domain name", "ntlmssp.auth.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2815 { &hf_ntlmssp_auth_username,
2816 { "User name", "ntlmssp.auth.username", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2817 { &hf_ntlmssp_auth_hostname,
2818 { "Host name", "ntlmssp.auth.hostname", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2819 { &hf_ntlmssp_auth_lmresponse,
2820 { "Lan Manager Response", "ntlmssp.auth.lmresponse", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2821 { &hf_ntlmssp_auth_ntresponse,
2822 { "NTLM Response", "ntlmssp.auth.ntresponse", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2823 { &hf_ntlmssp_auth_sesskey,
2824 { "Session Key", "ntlmssp.auth.sesskey", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2825 { &hf_ntlmssp_string_len,
2826 { "Length", "ntlmssp.string.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2827 { &hf_ntlmssp_string_maxlen,
2828 { "Maxlen", "ntlmssp.string.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2829 { &hf_ntlmssp_string_offset,
2830 { "Offset", "ntlmssp.string.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2831 { &hf_ntlmssp_blob_len,
2832 { "Length", "ntlmssp.blob.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2833 { &hf_ntlmssp_blob_maxlen,
2834 { "Maxlen", "ntlmssp.blob.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2835 { &hf_ntlmssp_blob_offset,
2836 { "Offset", "ntlmssp.blob.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2837 { &hf_ntlmssp_version,
2838 { "Version", "ntlmssp.version", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2839 { &hf_ntlmssp_version_major,
2840 { "Major Version", "ntlmssp.version.major", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2841 { &hf_ntlmssp_version_minor,
2842 { "Minor Version", "ntlmssp.version.minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2843 { &hf_ntlmssp_version_build_number,
2844 { "Build Number", "ntlmssp.version.build_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2845 { &hf_ntlmssp_version_ntlm_current_revision,
2846 { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2849 { &hf_ntlmssp_challenge_target_info,
2850 { "Target Info", "ntlmssp.challenge.target_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2851 { &hf_ntlmssp_challenge_target_info_len,
2852 { "Length", "ntlmssp.challenge.target_info.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2853 { &hf_ntlmssp_challenge_target_info_maxlen,
2854 { "Maxlen", "ntlmssp.challenge.target_info.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2855 { &hf_ntlmssp_challenge_target_info_offset,
2856 { "Offset", "ntlmssp.challenge.target_info.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2858 { &hf_ntlmssp_challenge_target_info_item_type,
2859 { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
2860 { &hf_ntlmssp_challenge_target_info_item_len,
2861 { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2863 { &hf_ntlmssp_challenge_target_info_end,
2864 { "List End", "ntlmssp.challenge.target_info.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2865 { &hf_ntlmssp_challenge_target_info_nb_computer_name,
2866 { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
2867 { &hf_ntlmssp_challenge_target_info_nb_domain_name,
2868 { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
2869 { &hf_ntlmssp_challenge_target_info_dns_computer_name,
2870 { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2871 { &hf_ntlmssp_challenge_target_info_dns_domain_name,
2872 { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2873 { &hf_ntlmssp_challenge_target_info_dns_tree_name,
2874 { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2875 { &hf_ntlmssp_challenge_target_info_flags,
2876 { "Flags", "ntlmssp.challenge.target_info.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2877 { &hf_ntlmssp_challenge_target_info_timestamp,
2878 { "Timestamp", "ntlmssp.challenge.target_info.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2879 { &hf_ntlmssp_challenge_target_info_restrictions,
2880 { "Restrictions", "ntlmssp.challenge.target_info.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2881 { &hf_ntlmssp_challenge_target_info_target_name,
2882 { "Target Name", "ntlmssp.challenge.target_info.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2883 { &hf_ntlmssp_challenge_target_info_channel_bindings,
2884 { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2886 { &hf_ntlmssp_ntlmv2_response_item_type,
2887 { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
2888 { &hf_ntlmssp_ntlmv2_response_item_len,
2889 { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2891 { &hf_ntlmssp_ntlmv2_response_end,
2892 { "List End", "ntlmssp.ntlmv2_response.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2893 { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
2894 { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
2895 { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
2896 { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
2897 { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
2898 { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2899 { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
2900 { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2901 { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
2902 { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2903 { &hf_ntlmssp_ntlmv2_response_flags,
2904 { "Flags", "ntlmssp.ntlmv2_response.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2905 { &hf_ntlmssp_ntlmv2_response_timestamp,
2906 { "Timestamp", "ntlmssp.ntlmv2_response.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2907 { &hf_ntlmssp_ntlmv2_response_restrictions,
2908 { "Restrictions", "ntlmssp.ntlmv2_response.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2909 { &hf_ntlmssp_ntlmv2_response_target_name,
2910 { "Target Name", "ntlmssp.ntlmv2_response.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2911 { &hf_ntlmssp_ntlmv2_response_channel_bindings,
2912 { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2914 { &hf_ntlmssp_message_integrity_code,
2915 { "MIC", "ntlmssp.authenticate.mic", FT_BYTES, BASE_NONE, NULL, 0x0, "Message Integrity Code", HFILL}},
2917 { "NTLMSSP Verifier", "ntlmssp.verf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2918 { &hf_ntlmssp_verf_vers,
2919 { "Version Number", "ntlmssp.verf.vers", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2920 { &hf_ntlmssp_verf_body,
2921 { "Verifier Body", "ntlmssp.verf.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2922 { &hf_ntlmssp_decrypted_payload,
2923 { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2924 { &hf_ntlmssp_verf_randompad,
2925 { "Random Pad", "ntlmssp.verf.randompad", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2926 { &hf_ntlmssp_verf_crc32,
2927 { "Verifier CRC32", "ntlmssp.verf.crc32", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2928 { &hf_ntlmssp_verf_hmacmd5,
2929 { "HMAC MD5", "ntlmssp.verf.hmacmd5", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2930 { &hf_ntlmssp_verf_sequence,
2931 { "Sequence", "ntlmssp.verf.sequence", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2933 { &hf_ntlmssp_ntlmv2_response,
2934 { "NTLMv2 Response", "ntlmssp.ntlmv2_response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2935 { &hf_ntlmssp_ntlmv2_response_hmac,
2936 { "HMAC", "ntlmssp.ntlmv2_response.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2937 { &hf_ntlmssp_ntlmv2_response_header,
2938 { "Header", "ntlmssp.ntlmv2_response.header", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2939 { &hf_ntlmssp_ntlmv2_response_reserved,
2940 { "Reserved", "ntlmssp.ntlmv2_response.reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2941 { &hf_ntlmssp_ntlmv2_response_time,
2942 { "Time", "ntlmssp.ntlmv2_response.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2943 { &hf_ntlmssp_ntlmv2_response_chal,
2944 { "Client challenge", "ntlmssp.ntlmv2_response.chal", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2945 { &hf_ntlmssp_ntlmv2_response_unknown,
2946 { "Unknown", "ntlmssp.ntlmv2_response.unknown", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}
2950 static gint *ett[] = {
2952 &ett_ntlmssp_negotiate_flags,
2953 &ett_ntlmssp_string,
2955 &ett_ntlmssp_version,
2956 &ett_ntlmssp_challenge_target_info,
2957 &ett_ntlmssp_challenge_target_info_item,
2958 &ett_ntlmssp_ntlmv2_response,
2959 &ett_ntlmssp_ntlmv2_response_item,
2961 module_t *ntlmssp_module;
2963 proto_ntlmssp = proto_register_protocol (
2964 "NTLM Secure Service Provider", /* name */
2965 "NTLMSSP", /* short name */
2966 "ntlmssp" /* abbrev */
2968 proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
2969 proto_register_subtree_array (ett, array_length (ett));
2970 register_init_routine(&ntlmssp_init_protocol);
2972 ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
2974 prefs_register_string_preference(ntlmssp_module, "nt_password",
2976 "NT Password (used to decrypt payloads)",
2979 register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
2980 new_register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
2981 new_register_dissector("ntlmssp_data_only", dissect_ntlmssp_payload_only, proto_ntlmssp);
2982 new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
2986 proto_reg_handoff_ntlmssp(void)
2988 dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
2990 /* Register protocol with the GSS-API module */
2992 ntlmssp_handle = find_dissector("ntlmssp");
2993 ntlmssp_wrap_handle = find_dissector("ntlmssp_verf");
2994 gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
2995 ntlmssp_handle, ntlmssp_wrap_handle,
2996 "NTLMSSP - Microsoft NTLM Security Support Provider");
2998 /* Register authenticated pipe dissector */
3001 * XXX - the verifiers here seem to have a version of 1 and a body of all
3004 * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
3005 * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
3006 * any other levels here?
3008 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
3009 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3012 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
3013 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3016 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
3017 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3020 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
3021 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3023 ntlmssp_tap = register_tap("ntlmssp");
3027 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3032 * indent-tabs-mode: nil
3035 * vi: set shiftwidth=2 tabstop=8 expandtab
3036 * :indentSize=2:tabSize=8:noTabs=true: