2 * Add-on for better NTLM v1/v2 handling
3 * Copyright 2009 Matthieu Patou <matthieu.patou@matws.net>
4 * Routines for NTLM Secure Service Provider
5 * Devin Heitmueller <dheitmueller@netilla.com>
6 * Copyright 2003, Tim Potter <tpot@samba.org>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
41 #include "packet-windows-common.h"
42 #include "packet-smb-common.h"
43 #include "packet-frame.h"
44 #include <epan/asn1.h>
45 #include "packet-kerberos.h"
46 #include <epan/prefs.h>
47 #include <epan/emem.h>
49 #include <epan/expert.h>
50 #include <epan/crypt/crypt-rc4.h>
51 #include <epan/crypt/crypt-md4.h>
52 #include <epan/crypt/crypt-md5.h>
53 #include <epan/crypt/crypt-des.h>
54 #include "packet-dcerpc.h"
55 #include "packet-gssapi.h"
56 #include <epan/crc32.h>
58 #include "packet-ntlmssp.h"
60 static int ntlmssp_tap = -1;
64 #define NTLMSSP_NEGOTIATE 1
65 #define NTLMSSP_CHALLENGE 2
66 #define NTLMSSP_AUTH 3
67 #define NTLMSSP_UNKNOWN 4
68 #define CLIENT_SIGN_TEXT "session key to client-to-server signing key magic constant"
69 #define CLIENT_SEAL_TEXT "session key to client-to-server sealing key magic constant"
70 #define SERVER_SIGN_TEXT "session key to server-to-client signing key magic constant"
71 #define SERVER_SEAL_TEXT "session key to server-to-client sealing key magic constant"
73 #define NTLMSSP_KEY_LEN 16
75 static const value_string ntlmssp_message_types[] = {
76 { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
77 { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
78 { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
79 { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
83 typedef struct _md4_pass {
84 guint8 md4[NTLMSSP_KEY_LEN];
87 static unsigned char gbl_zeros[24] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
88 static GHashTable* hash_packet = NULL;
91 * NTLMSSP negotiation flags
96 * http://davenport.sourceforge.net/ntlm.html
98 * although that document says that:
100 * 0x00010000 is "Target Type Domain";
101 * 0x00020000 is "Target Type Server"
102 * 0x00040000 is "Target Type Share";
104 * and that 0x00100000, 0x00200000, and 0x00400000 are
105 * "Request Init Response", "Request Accept Response", and
106 * "Request Non-NT Session Key", rather than those values shifted
107 * right one having those interpretations.
109 * UPDATE: Further information obtained from [MS-NLMP]:
110 * NT LAN Manager (NTLM) Authentication Protocol Specification
111 * http://msdn2.microsoft.com/en-us/library/cc236621.aspx
114 #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
115 #define NTLMSSP_NEGOTIATE_OEM 0x00000002
116 #define NTLMSSP_REQUEST_TARGET 0x00000004
117 #define NTLMSSP_NEGOTIATE_00000008 0x00000008
118 #define NTLMSSP_NEGOTIATE_SIGN 0x00000010
119 #define NTLMSSP_NEGOTIATE_SEAL 0x00000020
120 #define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040
121 #define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
122 #define NTLMSSP_NEGOTIATE_00000100 0x00000100
123 #define NTLMSSP_NEGOTIATE_NTLM 0x00000200
124 #define NTLMSSP_NEGOTIATE_NT_ONLY 0x00000400
125 #define NTLMSSP_NEGOTIATE_00000800 0x00000800
126 #define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000
127 #define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000
128 #define NTLMSSP_NEGOTIATE_00004000 0x00004000
129 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
130 #define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000
131 #define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
132 #define NTLMSSP_TARGET_TYPE_SHARE 0x00040000
133 #define NTLMSSP_NEGOTIATE_EXTENDED_SECURITY 0x00080000
134 #define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000
135 #define NTLMSSP_NEGOTIATE_00200000 0x00200000
136 #define NTLMSSP_REQUEST_NON_NT_SESSION 0x00400000
137 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
138 #define NTLMSSP_NEGOTIATE_01000000 0x01000000
139 #define NTLMSSP_NEGOTIATE_VERSION 0x02000000
140 #define NTLMSSP_NEGOTIATE_04000000 0x04000000
141 #define NTLMSSP_NEGOTIATE_08000000 0x08000000
142 #define NTLMSSP_NEGOTIATE_10000000 0x10000000
143 #define NTLMSSP_NEGOTIATE_128 0x20000000
144 #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
145 #define NTLMSSP_NEGOTIATE_56 0x80000000
147 static int proto_ntlmssp = -1;
148 static int hf_ntlmssp_auth = -1;
149 static int hf_ntlmssp_message_type = -1;
150 static int hf_ntlmssp_negotiate_flags = -1;
151 static int hf_ntlmssp_negotiate_flags_01 = -1;
152 static int hf_ntlmssp_negotiate_flags_02 = -1;
153 static int hf_ntlmssp_negotiate_flags_04 = -1;
154 static int hf_ntlmssp_negotiate_flags_08 = -1;
155 static int hf_ntlmssp_negotiate_flags_10 = -1;
156 static int hf_ntlmssp_negotiate_flags_20 = -1;
157 static int hf_ntlmssp_negotiate_flags_40 = -1;
158 static int hf_ntlmssp_negotiate_flags_80 = -1;
159 static int hf_ntlmssp_negotiate_flags_100 = -1;
160 static int hf_ntlmssp_negotiate_flags_200 = -1;
161 static int hf_ntlmssp_negotiate_flags_400 = -1;
162 static int hf_ntlmssp_negotiate_flags_800 = -1;
163 static int hf_ntlmssp_negotiate_flags_1000 = -1;
164 static int hf_ntlmssp_negotiate_flags_2000 = -1;
165 static int hf_ntlmssp_negotiate_flags_4000 = -1;
166 static int hf_ntlmssp_negotiate_flags_8000 = -1;
167 static int hf_ntlmssp_negotiate_flags_10000 = -1;
168 static int hf_ntlmssp_negotiate_flags_20000 = -1;
169 static int hf_ntlmssp_negotiate_flags_40000 = -1;
170 static int hf_ntlmssp_negotiate_flags_80000 = -1;
171 static int hf_ntlmssp_negotiate_flags_100000 = -1;
172 static int hf_ntlmssp_negotiate_flags_200000 = -1;
173 static int hf_ntlmssp_negotiate_flags_400000 = -1;
174 static int hf_ntlmssp_negotiate_flags_800000 = -1;
175 static int hf_ntlmssp_negotiate_flags_1000000 = -1;
176 static int hf_ntlmssp_negotiate_flags_2000000 = -1;
177 static int hf_ntlmssp_negotiate_flags_4000000 = -1;
178 static int hf_ntlmssp_negotiate_flags_8000000 = -1;
179 static int hf_ntlmssp_negotiate_flags_10000000 = -1;
180 static int hf_ntlmssp_negotiate_flags_20000000 = -1;
181 static int hf_ntlmssp_negotiate_flags_40000000 = -1;
182 static int hf_ntlmssp_negotiate_flags_80000000 = -1;
183 static int hf_ntlmssp_negotiate_workstation_strlen = -1;
184 static int hf_ntlmssp_negotiate_workstation_maxlen = -1;
185 static int hf_ntlmssp_negotiate_workstation_buffer = -1;
186 static int hf_ntlmssp_negotiate_workstation = -1;
187 static int hf_ntlmssp_negotiate_domain_strlen = -1;
188 static int hf_ntlmssp_negotiate_domain_maxlen = -1;
189 static int hf_ntlmssp_negotiate_domain_buffer = -1;
190 static int hf_ntlmssp_negotiate_domain = -1;
191 static int hf_ntlmssp_ntlm_server_challenge = -1;
192 static int hf_ntlmssp_ntlm_client_challenge = -1;
193 static int hf_ntlmssp_reserved = -1;
194 static int hf_ntlmssp_challenge_target_name = -1;
195 static int hf_ntlmssp_auth_username = -1;
196 static int hf_ntlmssp_auth_domain = -1;
197 static int hf_ntlmssp_auth_hostname = -1;
198 static int hf_ntlmssp_auth_lmresponse = -1;
199 static int hf_ntlmssp_auth_ntresponse = -1;
200 static int hf_ntlmssp_auth_sesskey = -1;
201 static int hf_ntlmssp_string_len = -1;
202 static int hf_ntlmssp_string_maxlen = -1;
203 static int hf_ntlmssp_string_offset = -1;
204 static int hf_ntlmssp_blob_len = -1;
205 static int hf_ntlmssp_blob_maxlen = -1;
206 static int hf_ntlmssp_blob_offset = -1;
207 static int hf_ntlmssp_version = -1;
208 static int hf_ntlmssp_version_major = -1;
209 static int hf_ntlmssp_version_minor = -1;
210 static int hf_ntlmssp_version_build_number = -1;
211 static int hf_ntlmssp_version_ntlm_current_revision = -1;
213 static int hf_ntlmssp_challenge_target_info = -1;
214 static int hf_ntlmssp_challenge_target_info_len = -1;
215 static int hf_ntlmssp_challenge_target_info_maxlen = -1;
216 static int hf_ntlmssp_challenge_target_info_offset = -1;
218 static int hf_ntlmssp_challenge_target_info_item_type = -1;
219 static int hf_ntlmssp_challenge_target_info_item_len = -1;
221 static int hf_ntlmssp_challenge_target_info_end = -1;
222 static int hf_ntlmssp_challenge_target_info_nb_computer_name = -1;
223 static int hf_ntlmssp_challenge_target_info_nb_domain_name = -1;
224 static int hf_ntlmssp_challenge_target_info_dns_computer_name = -1;
225 static int hf_ntlmssp_challenge_target_info_dns_domain_name = -1;
226 static int hf_ntlmssp_challenge_target_info_dns_tree_name = -1;
227 static int hf_ntlmssp_challenge_target_info_flags = -1;
228 static int hf_ntlmssp_challenge_target_info_timestamp = -1;
229 static int hf_ntlmssp_challenge_target_info_restrictions = -1;
230 static int hf_ntlmssp_challenge_target_info_target_name =-1;
231 static int hf_ntlmssp_challenge_target_info_channel_bindings =-1;
233 static int hf_ntlmssp_ntlmv2_response_item_type = -1;
234 static int hf_ntlmssp_ntlmv2_response_item_len = -1;
236 static int hf_ntlmssp_ntlmv2_response_end = -1;
237 static int hf_ntlmssp_ntlmv2_response_nb_computer_name = -1;
238 static int hf_ntlmssp_ntlmv2_response_nb_domain_name = -1;
239 static int hf_ntlmssp_ntlmv2_response_dns_computer_name = -1;
240 static int hf_ntlmssp_ntlmv2_response_dns_domain_name = -1;
241 static int hf_ntlmssp_ntlmv2_response_dns_tree_name = -1;
242 static int hf_ntlmssp_ntlmv2_response_flags = -1;
243 static int hf_ntlmssp_ntlmv2_response_timestamp = -1;
244 static int hf_ntlmssp_ntlmv2_response_restrictions = -1;
245 static int hf_ntlmssp_ntlmv2_response_target_name =-1;
246 static int hf_ntlmssp_ntlmv2_response_channel_bindings =-1;
248 static int hf_ntlmssp_message_integrity_code = -1;
249 static int hf_ntlmssp_verf = -1;
250 static int hf_ntlmssp_verf_vers = -1;
251 static int hf_ntlmssp_verf_body = -1;
252 static int hf_ntlmssp_verf_randompad = -1;
253 static int hf_ntlmssp_verf_hmacmd5 = -1;
254 static int hf_ntlmssp_verf_crc32 = -1;
255 static int hf_ntlmssp_verf_sequence = -1;
256 static int hf_ntlmssp_decrypted_payload = -1;
258 static int hf_ntlmssp_ntlmv2_response = -1;
259 static int hf_ntlmssp_ntlmv2_response_hmac = -1;
260 static int hf_ntlmssp_ntlmv2_response_header = -1;
261 static int hf_ntlmssp_ntlmv2_response_reserved = -1;
262 static int hf_ntlmssp_ntlmv2_response_time = -1;
263 static int hf_ntlmssp_ntlmv2_response_chal = -1;
264 static int hf_ntlmssp_ntlmv2_response_unknown = -1;
266 static gint ett_ntlmssp = -1;
267 static gint ett_ntlmssp_negotiate_flags = -1;
268 static gint ett_ntlmssp_string = -1;
269 static gint ett_ntlmssp_blob = -1;
270 static gint ett_ntlmssp_version = -1;
271 static gint ett_ntlmssp_challenge_target_info = -1;
272 static gint ett_ntlmssp_challenge_target_info_item = -1;
273 static gint ett_ntlmssp_ntlmv2_response = -1;
274 static gint ett_ntlmssp_ntlmv2_response_item = -1;
276 /* Configuration variables */
277 const char *gbl_nt_password = NULL;
279 #define MAX_BLOB_SIZE 256
280 typedef struct _ntlmssp_blob {
282 guint8 contents[MAX_BLOB_SIZE];
285 /* Used in the conversation function */
286 typedef struct _ntlmssp_info {
289 rc4_state_struct rc4_state_client;
290 rc4_state_struct rc4_state_server;
291 guint8 sign_key_client[NTLMSSP_KEY_LEN];
292 guint8 sign_key_server[NTLMSSP_KEY_LEN];
293 guint32 server_dest_port;
294 unsigned char server_challenge[8];
295 unsigned char client_challenge[8];
296 int rc4_state_initialized;
297 ntlmssp_blob ntlm_response;
298 ntlmssp_blob lm_response;
301 /* If this struct exists in the payload_decrypt, then we have already
303 typedef struct _ntlmssp_packet_info {
304 guint8 *decrypted_payload;
306 guint8 verifier[NTLMSSP_KEY_LEN];
307 gboolean payload_decrypted;
308 gboolean verifier_decrypted;
309 } ntlmssp_packet_info;
312 static void printnbyte(const guint8* tab,int nb,const char* txt,const char* txt2)
315 fprintf(stderr,"%s ",txt);
318 fprintf(stderr,"%02hhX ",*(tab+i));
320 fprintf(stderr,"%s",txt2);
323 static void printnchar(const guint8* tab,int nb,char* txt,char* txt2)
326 fprintf(stderr,"%s ",txt);
329 fprintf(stderr,"%c",*(tab+i));
331 fprintf(stderr,"%s",txt2);
335 static void printnbyte(const guint8* tab _U_,int nb _U_, const char* txt _U_,const char* txt2 _U_)
340 * GSlist of decrypted payloads.
342 static GSList *decrypted_payloads;
344 int LEBE_Convert(int value)
349 b=(value&0x0000FF00) >> 8;
350 c=(value&0x00FF0000) >> 16;
351 d=(value&0xFF000000) >> 24;
352 return (a << 24) | (b << 16) | (c << 8) | d;
355 Perform a DES encryption with a 16 bit key and 8bit data item.
356 It's in fact 3 susbsequent call to crypt_des_ecb with a 7 bit key.
357 Missing bits for the key are replaced by 0;
358 Returns output in response, which is expected to be 24 bytes.
360 static int crypt_des_ecb_long(guint8 *response,
364 guint8 pw21[21]; /* 21 bytes place for the needed key */
366 memset(pw21, 0, sizeof(pw21));
367 memcpy(pw21, key, 16);
369 memset(response, 0, 24);
370 /* crypt_des_ecb(data,key)*/
371 crypt_des_ecb(response, data, pw21, 1);
372 crypt_des_ecb(response + 8, data, pw21 + 7, 1);
373 crypt_des_ecb(response + 16, data, pw21 + 14, 1);
378 Generate a challenge response, given an eight byte challenge and
379 either the NT or the Lan Manager password hash (16 bytes).
380 Returns output in response, which is expected to be 24 bytes.
382 static int ntlmssp_generate_challenge_response(guint8 *response,
383 const guint8 *passhash,
384 const guint8 *challenge)
386 guint8 pw21[21]; /* Password hash padded to 21 bytes */
388 memset(pw21, 0x0, sizeof(pw21));
389 memcpy(pw21, passhash, 16);
391 memset(response, 0, 24);
393 crypt_des_ecb(response, challenge, pw21, 1);
394 crypt_des_ecb(response + 8, challenge, pw21 + 7, 1);
395 crypt_des_ecb(response + 16, challenge, pw21 + 14, 1);
401 /* Ultra simple ainsi to unicode converter, will only work for ascii password ...*/
402 static void str_to_unicode(const char *nt_password, char *nt_password_unicode)
404 size_t password_len = 0;
407 password_len = strlen(nt_password);
408 if(nt_password_unicode != NULL)
410 for(i=0;i<(password_len);i++)
412 nt_password_unicode[i*2]=nt_password[i];
413 nt_password_unicode[i*2+1]=0;
415 nt_password_unicode[2*password_len]='\0';
419 /* This function generate the Key Exchange Key
420 * Depending on the flags this key will either be used to crypt the exported session key
421 * or will be used directly as exported session key.
422 * Exported session key is the key that will be used for sealing and signing communication*/
425 get_keyexchange_key(unsigned char keyexchangekey[NTLMSSP_KEY_LEN],const unsigned char sessionbasekey[NTLMSSP_KEY_LEN],const unsigned char lm_challenge_response[24],int flags)
427 guint8 basekey[NTLMSSP_KEY_LEN];
430 memset(keyexchangekey,0,NTLMSSP_KEY_LEN);
431 memset(basekey,0,NTLMSSP_KEY_LEN);
432 /* sessionbasekey is either derived from lm_password_hash or from nt_password_hash depending on the key type negotiated */
433 memcpy(basekey,sessionbasekey,8);
434 memset(basekey,0xBD,8);
435 if(flags&NTLMSSP_NEGOTIATE_LM_KEY)
438 crypt_des_ecb(keyexchangekey,lm_challenge_response,basekey,1);
439 crypt_des_ecb(keyexchangekey+8,lm_challenge_response,basekey+7,1);
443 if(flags&NTLMSSP_REQUEST_NON_NT_SESSION)
445 /*People from samba tends to use the same function in this case than in the previous one but with 0 data
446 * it's not clear that it produce the good result
447 * memcpy(keyexchangekey,lm_hash,8);
448 * Let's trust samba implementation it mights seem weird but they are more often rights than the spec !
451 crypt_des_ecb(keyexchangekey,zeros,basekey,3);
452 crypt_des_ecb(keyexchangekey+8,zeros,basekey+7,1);
456 /* it is stated page 65 of NTLM SSP spec that sessionbasekey should be encrypted with hmac_md5 using the concact of both challenge
457 * when it's NTLM v1 + extended security but it turns out to be wrong !
459 memcpy(keyexchangekey,sessionbasekey,NTLMSSP_KEY_LEN);
463 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
465 get_md4pass_list(md4_pass** p_pass_list,const char* nt_password)
470 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
471 int password_len = 0;
472 char nt_password_unicode[256];
479 read_keytab_file_from_preferences();
481 for(ek=enc_key_list;ek;ek=ek->next){
482 if( ek->keylength == NTLMSSP_KEY_LEN ) {
486 memset(nt_password_hash,0,NTLMSSP_KEY_LEN);
487 if (nt_password[0] != '\0' && ( strlen(nt_password) < 129 )) {
489 password_len = strlen(nt_password);
490 str_to_unicode(nt_password,nt_password_unicode);
491 crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
494 /* Unable to calculate the session key without a password or if password is more than 128 char ......*/
498 *p_pass_list = ep_alloc(nb_pass*sizeof(md4_pass));
499 pass_list=*p_pass_list;
501 if( memcmp(nt_password_hash,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
502 memcpy(pass_list[i].md4,nt_password_hash,NTLMSSP_KEY_LEN);
505 for(ek=enc_key_list;ek;ek=ek->next){
506 if( ek->keylength == NTLMSSP_KEY_LEN ) {
507 memcpy(pass_list[i].md4,ek->keyvalue,NTLMSSP_KEY_LEN);
514 /* Create an NTLMSSP version 2 key
517 create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge , const guint8 *clientchallenge ,
518 guint8 *sessionkey ,const guint8 *encryptedsessionkey , int flags ,
519 ntlmssp_blob ntlm_response, ntlmssp_blob lm_response _U_, ntlmssp_header_t *ntlmssph ) {
520 char domain_name_unicode[256];
521 char user_uppercase[256];
523 /*guint8 md4[NTLMSSP_KEY_LEN];*/
524 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
525 unsigned char nt_proof[NTLMSSP_KEY_LEN];
526 unsigned char ntowf[NTLMSSP_KEY_LEN];
527 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
528 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
529 guint8 lm_challenge_response[24];
532 rc4_state_struct rc4state;
535 md4_pass *pass_list = NULL;
539 /* We are going to try password encrypted in keytab as well, it's an idean of Stefan Metzmacher <metze@samba.org>
540 * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
542 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
543 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
544 nb_pass = get_md4pass_list(&pass_list,nt_password);
547 memset(user_uppercase,0,256);
548 user_len = strlen(ntlmssph->acct_name);
549 if( user_len < 129 ) {
551 str_to_unicode(ntlmssph->acct_name,buf);
552 for (j = 0; j < (2*user_len); j++) {
553 if( buf[j] != '\0' ) {
554 user_uppercase[j] = toupper(buf[j]);
559 /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
562 domain_len = strlen(ntlmssph->domain_name);
563 if( domain_len < 129 ) {
564 str_to_unicode(ntlmssph->domain_name,domain_name_unicode);
567 /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
570 while (i < nb_pass ) {
571 /*fprintf(stderr,"Turn %d, ",i);*/
572 memcpy(nt_password_hash,pass_list[i].md4,NTLMSSP_KEY_LEN);
573 /*printnbyte(nt_password_hash,NTLMSSP_KEY_LEN,"Current NT password hash: ","\n");*/
575 /* ntowf computation */
577 memcpy(buf,user_uppercase,user_len*2);
578 memcpy(buf+user_len*2,domain_name_unicode,domain_len*2);
579 md5_hmac(buf,domain_len*2+user_len*2,nt_password_hash,NTLMSSP_KEY_LEN,ntowf);
582 memcpy(buf,serverchallenge,8);
583 memcpy(buf+8,clientchallenge,8);
584 md5_hmac(buf,NTLMSSP_KEY_LEN,ntowf,NTLMSSP_KEY_LEN,lm_challenge_response);
585 memcpy(lm_challenge_response+NTLMSSP_KEY_LEN,clientchallenge,8);
586 printnbyte(lm_challenge_response,24,"LM Response: ","\n");
588 /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
590 memcpy(buf,serverchallenge,8);
591 memcpy(buf+8,ntlm_response.contents+NTLMSSP_KEY_LEN,ntlm_response.length-NTLMSSP_KEY_LEN);
592 md5_hmac(buf,ntlm_response.length-8,ntowf,NTLMSSP_KEY_LEN,nt_proof);
593 printnbyte(nt_proof,NTLMSSP_KEY_LEN,"NT proof: ","\n");
594 if( !memcmp(nt_proof,ntlm_response.contents,NTLMSSP_KEY_LEN) ) {
605 md5_hmac(nt_proof,NTLMSSP_KEY_LEN,ntowf,NTLMSSP_KEY_LEN,sessionbasekey);
606 get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
607 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
608 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
610 memcpy(sessionkey,encryptedsessionkey,NTLMSSP_KEY_LEN);
611 crypt_rc4_init(&rc4state,keyexchangekey,NTLMSSP_KEY_LEN);
612 crypt_rc4(&rc4state,sessionkey,NTLMSSP_KEY_LEN);
616 memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
620 /* Create an NTLMSSP version 1 key
621 * That is more complicated logic and methods and user challenge as well.
622 * password points to the ANSI password to encrypt, challenge points to
623 * the 8 octet challenge string
626 create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, const guint8 *clientchallenge,
627 guint8 *sessionkey,const guint8 *encryptedsessionkey, int flags,
628 const guint8 *ref_nt_challenge_response,const guint8 *ref_lm_challenge_response)
630 unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
631 unsigned char lm_password_hash[NTLMSSP_KEY_LEN];
632 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
633 unsigned char challenges_hash[NTLMSSP_KEY_LEN];
634 unsigned char challenges_hash_first8[8];
635 unsigned char challenges[NTLMSSP_KEY_LEN];
636 guint8 md4[NTLMSSP_KEY_LEN];
638 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
639 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
640 guint8 lm_challenge_response[24];
641 guint8 nt_challenge_response[24];
642 rc4_state_struct rc4state;
643 md5_state_t md5state;
644 char nt_password_unicode[256];
648 md4_pass *pass_list = NULL;
649 unsigned char lmhash_key[] =
650 {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
652 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
653 memset(lm_password_upper, 0, sizeof(lm_password_upper));
654 /* lm auth/lm session == (!NTLM_NEGOTIATE_NT_ONLY && NTLMSSP_NEGOTIATE_LM_KEY) || ! (EXTENDED_SECURITY) || ! NTLMSSP_NEGOTIATE_NTLM*/
655 /* Create a Lan Manager hash of the input password */
656 if (nt_password[0] != '\0') {
657 password_len = strlen(nt_password);
658 /*Do not forget to free nt_password_nt*/
659 str_to_unicode(nt_password,nt_password_unicode);
660 crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
661 /* Truncate password if too long */
662 if (password_len > NTLMSSP_KEY_LEN)
663 password_len = NTLMSSP_KEY_LEN;
664 for (i = 0; i < password_len; i++) {
665 lm_password_upper[i] = toupper(nt_password[i]);
670 /* Unable to calculate the session key without a password ... and we will not use one for a keytab*/
671 if( !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
675 if((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NTLMSSP_NEGOTIATE_NT_ONLY)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
676 crypt_des_ecb(lm_password_hash, lmhash_key, lm_password_upper, 1);
677 crypt_des_ecb(lm_password_hash+8, lmhash_key, lm_password_upper+7, 1);
678 ntlmssp_generate_challenge_response(lm_challenge_response,
679 lm_password_hash, serverchallenge);
680 memcpy(sessionbasekey,lm_password_hash,NTLMSSP_KEY_LEN);
684 memset(lm_challenge_response,0,24);
685 if( flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
686 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
687 nb_pass = get_md4pass_list(&pass_list,nt_password);
690 while (i < nb_pass ) {
691 /*fprintf(stderr,"Turn %d, ",i);*/
692 memcpy(nt_password_hash,pass_list[i].md4,NTLMSSP_KEY_LEN);
693 /*printnbyte(nt_password_hash,NTLMSSP_KEY_LEN,"Current NT password hash: ","\n");*/
695 memcpy(lm_challenge_response,clientchallenge,8);
697 md5_append(&md5state,serverchallenge,8);
698 md5_append(&md5state,clientchallenge,8);
699 md5_finish(&md5state,challenges_hash);
700 memcpy(challenges_hash_first8,challenges_hash,8);
701 crypt_des_ecb_long(nt_challenge_response,nt_password_hash,challenges_hash_first8);
702 if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) ) {
709 crypt_des_ecb_long(nt_challenge_response,nt_password_hash,serverchallenge);
710 if( flags & NTLMSSP_NEGOTIATE_NT_ONLY ) {
711 memcpy(lm_challenge_response,nt_challenge_response,24);
714 crypt_des_ecb_long(lm_challenge_response,lm_password_hash,serverchallenge);
716 if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) && !memcmp(ref_lm_challenge_response,lm_challenge_response,24) ) {
720 /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
721 * that sessionbasekey should be based md4(nt_password_hash) only in the case of some NT auth
722 * Otherwise it should be lm_password_hash ...*/
723 crypt_md4(md4,nt_password_hash,NTLMSSP_KEY_LEN);
724 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
725 memcpy(challenges,serverchallenge,8);
726 memcpy(challenges+8,clientchallenge,8);
727 /*md5_hmac(text,text_len,key,key_len,digest);*/
728 md5_hmac(challenges,NTLMSSP_KEY_LEN,md4,NTLMSSP_KEY_LEN,sessionbasekey);
731 memcpy(sessionbasekey,md4,NTLMSSP_KEY_LEN);
740 get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
741 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
742 /*printnbyte(nt_challenge_response,24,"NT challenge response","\n");
743 printnbyte(lm_challenge_response,24,"LM challenge response","\n");*/
744 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
745 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
747 memcpy(sessionkey,encryptedsessionkey,NTLMSSP_KEY_LEN);
748 crypt_rc4_init(&rc4state,keyexchangekey,NTLMSSP_KEY_LEN);
749 crypt_rc4(&rc4state,sessionkey,NTLMSSP_KEY_LEN);
753 memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
757 get_siging_key(guint8 *sign_key_server,guint8* sign_key_client,const guint8 key[NTLMSSP_KEY_LEN], int keylen)
759 md5_state_t md5state;
760 md5_state_t md5state2;
761 memset(sign_key_client,0,NTLMSSP_KEY_LEN);
762 memset(sign_key_server,0,NTLMSSP_KEY_LEN);
764 md5_append(&md5state,key,keylen);
765 md5_append(&md5state,CLIENT_SIGN_TEXT,strlen(CLIENT_SIGN_TEXT)+1);
766 md5_finish(&md5state,sign_key_client);
767 md5_init(&md5state2);
768 md5_append(&md5state2,key,keylen);
769 md5_append(&md5state2,SERVER_SIGN_TEXT,strlen(SERVER_SIGN_TEXT)+1);
770 md5_finish(&md5state2,sign_key_server);
774 /* We return either a 128 or 64 bit key
777 get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int flags ,int *keylen ,guint8 *clientsealkey ,guint8 *serversealkey)
779 md5_state_t md5state;
780 md5_state_t md5state2;
781 memset(clientsealkey,0,NTLMSSP_KEY_LEN);
782 memset(serversealkey,0,NTLMSSP_KEY_LEN);
783 memcpy(clientsealkey,exportedsessionkey,NTLMSSP_KEY_LEN);
784 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)
786 if (flags & NTLMSSP_NEGOTIATE_128)
788 /* The exportedsessionkey has already the good length just update the length*/
793 if (flags & NTLMSSP_NEGOTIATE_56)
795 memset(clientsealkey+7,0,9);
800 memset(clientsealkey+5,0,11);
804 memcpy(serversealkey,clientsealkey,NTLMSSP_KEY_LEN);
806 md5_append(&md5state,clientsealkey,*keylen);
807 md5_append(&md5state,CLIENT_SEAL_TEXT,strlen(CLIENT_SEAL_TEXT)+1);
808 md5_finish(&md5state,clientsealkey);
809 md5_init(&md5state2);
810 md5_append(&md5state2,serversealkey,*keylen);
811 md5_append(&md5state2,SERVER_SEAL_TEXT,strlen(SERVER_SEAL_TEXT)+1);
812 md5_finish(&md5state2,serversealkey);
816 if (flags & NTLMSSP_NEGOTIATE_128)
818 /* The exportedsessionkey has already the good length just update the length*/
824 if (flags & NTLMSSP_NEGOTIATE_56)
826 memset(clientsealkey+7,0,9);
830 memset(clientsealkey+5,0,11);
831 clientsealkey[5]=0xe5;
832 clientsealkey[6]=0x38;
833 clientsealkey[7]=0xb0;
836 serversealkey = memcpy(serversealkey,clientsealkey,*keylen);
839 /* Create an NTLMSSP version 1 key.
840 * password points to the ANSI password to encrypt, challenge points to
841 * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
842 * otherwise it will do a 40 bit key. The result is stored in
843 * sspkey (expected to be NTLMSSP_KEY_LEN octets)
845 /* dissect a string - header area contains:
848 four byte offset of string in data area
849 The function returns the offset at the end of the string header,
850 but the 'end' parameter returns the offset of the end of the string itself
851 The 'start' parameter returns the offset of the beginning of the string
852 If there's no string, just use the offset of the end of the tvb as start/end.
855 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
856 proto_tree *ntlmssp_tree,
857 gboolean unicode_strings,
858 int string_hf, int *start, int *end,
859 const char **stringp)
861 proto_tree *tree = NULL;
862 proto_item *tf = NULL;
863 gint16 string_length = tvb_get_letohs(tvb, offset);
864 gint16 string_maxlen = tvb_get_letohs(tvb, offset+2);
865 gint32 string_offset = tvb_get_letohl(tvb, offset+4);
866 const char *string_text = NULL;
870 *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
871 if (0 == string_length) {
874 proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
881 bc = result_length = string_length;
882 string_text = get_unicode_or_ascii_string(tvb, &string_offset,
883 unicode_strings, &result_length,
886 if (stringp != NULL) {
887 if (!string_text) string_text = ""; /* Make sure we don't blow up later */
889 *stringp = string_text;
893 tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
894 string_offset, result_length, string_text);
895 tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
897 proto_tree_add_uint(tree, hf_ntlmssp_string_len,
898 tvb, offset, 2, string_length);
900 proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
901 tvb, offset, 2, string_maxlen);
903 proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
904 tvb, offset, 4, string_offset);
907 *end = string_offset + string_length;
911 /* dissect a generic blob - header area contains:
914 four byte offset of blob in data area
915 The function returns the offset at the end of the blob header,
916 but the 'end' parameter returns the offset of the end of the blob itself
919 dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
920 proto_tree *ntlmssp_tree,
921 int blob_hf, int *end, ntlmssp_blob *result)
923 proto_item *tf = NULL;
924 proto_tree *tree = NULL;
925 guint16 blob_length = tvb_get_letohs(tvb, offset);
926 guint16 blob_maxlen = tvb_get_letohs(tvb, offset+2);
927 guint32 blob_offset = tvb_get_letohl(tvb, offset+4);
928 if (0 == blob_length) {
929 *end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
931 proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
932 proto_registrar_get_name(blob_hf));
937 tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
938 blob_offset, blob_length, FALSE);
939 tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
941 proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
942 tvb, offset, 2, blob_length);
944 proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
945 tvb, offset, 2, blob_maxlen);
947 proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
948 tvb, offset, 4, blob_offset);
951 *end = blob_offset + blob_length;
953 if (result != NULL) {
954 result->length = blob_length;
955 memset(result->contents, 0, MAX_BLOB_SIZE);
956 if (blob_length < MAX_BLOB_SIZE)
958 tvb_memcpy(tvb, result->contents, blob_offset, blob_length);
959 if (blob_hf == hf_ntlmssp_auth_lmresponse && !(memcmp(tvb->real_data+blob_offset+8,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",NTLMSSP_KEY_LEN)))
961 proto_tree_add_item (ntlmssp_tree,
962 hf_ntlmssp_ntlm_client_challenge,
963 tvb, blob_offset, 8, FALSE);
968 /* If we are dissecting the NTLM response and it is a NTLMv2
969 response call the appropriate dissector. */
971 if (blob_hf == hf_ntlmssp_auth_ntresponse && blob_length > 24)
973 proto_tree_add_item (ntlmssp_tree,
974 hf_ntlmssp_ntlm_client_challenge,
975 tvb, blob_offset+32, 8, FALSE);
976 dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
983 dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
984 proto_tree *ntlmssp_tree,
985 guint32 negotiate_flags)
987 proto_tree *negotiate_flags_tree = NULL;
988 proto_item *tf = NULL;
991 tf = proto_tree_add_uint (ntlmssp_tree,
992 hf_ntlmssp_negotiate_flags,
993 tvb, offset, 4, negotiate_flags);
994 negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
997 proto_tree_add_boolean (negotiate_flags_tree,
998 hf_ntlmssp_negotiate_flags_80000000,
999 tvb, offset, 4, negotiate_flags);
1000 proto_tree_add_boolean (negotiate_flags_tree,
1001 hf_ntlmssp_negotiate_flags_40000000,
1002 tvb, offset, 4, negotiate_flags);
1003 proto_tree_add_boolean (negotiate_flags_tree,
1004 hf_ntlmssp_negotiate_flags_20000000,
1005 tvb, offset, 4, negotiate_flags);
1006 proto_tree_add_boolean (negotiate_flags_tree,
1007 hf_ntlmssp_negotiate_flags_10000000,
1008 tvb, offset, 4, negotiate_flags);
1009 proto_tree_add_boolean (negotiate_flags_tree,
1010 hf_ntlmssp_negotiate_flags_8000000,
1011 tvb, offset, 4, negotiate_flags);
1012 proto_tree_add_boolean (negotiate_flags_tree,
1013 hf_ntlmssp_negotiate_flags_4000000,
1014 tvb, offset, 4, negotiate_flags);
1015 proto_tree_add_boolean (negotiate_flags_tree,
1016 hf_ntlmssp_negotiate_flags_2000000,
1017 tvb, offset, 4, negotiate_flags);
1018 proto_tree_add_boolean (negotiate_flags_tree,
1019 hf_ntlmssp_negotiate_flags_1000000,
1020 tvb, offset, 4, negotiate_flags);
1021 proto_tree_add_boolean (negotiate_flags_tree,
1022 hf_ntlmssp_negotiate_flags_800000,
1023 tvb, offset, 4, negotiate_flags);
1024 proto_tree_add_boolean (negotiate_flags_tree,
1025 hf_ntlmssp_negotiate_flags_400000,
1026 tvb, offset, 4, negotiate_flags);
1027 proto_tree_add_boolean (negotiate_flags_tree,
1028 hf_ntlmssp_negotiate_flags_200000,
1029 tvb, offset, 4, negotiate_flags);
1030 proto_tree_add_boolean (negotiate_flags_tree,
1031 hf_ntlmssp_negotiate_flags_100000,
1032 tvb, offset, 4, negotiate_flags);
1033 proto_tree_add_boolean (negotiate_flags_tree,
1034 hf_ntlmssp_negotiate_flags_80000,
1035 tvb, offset, 4, negotiate_flags);
1036 proto_tree_add_boolean (negotiate_flags_tree,
1037 hf_ntlmssp_negotiate_flags_40000,
1038 tvb, offset, 4, negotiate_flags);
1039 proto_tree_add_boolean (negotiate_flags_tree,
1040 hf_ntlmssp_negotiate_flags_20000,
1041 tvb, offset, 4, negotiate_flags);
1042 proto_tree_add_boolean (negotiate_flags_tree,
1043 hf_ntlmssp_negotiate_flags_10000,
1044 tvb, offset, 4, negotiate_flags);
1045 proto_tree_add_boolean (negotiate_flags_tree,
1046 hf_ntlmssp_negotiate_flags_8000,
1047 tvb, offset, 4, negotiate_flags);
1048 proto_tree_add_boolean (negotiate_flags_tree,
1049 hf_ntlmssp_negotiate_flags_4000,
1050 tvb, offset, 4, negotiate_flags);
1051 proto_tree_add_boolean (negotiate_flags_tree,
1052 hf_ntlmssp_negotiate_flags_2000,
1053 tvb, offset, 4, negotiate_flags);
1054 proto_tree_add_boolean (negotiate_flags_tree,
1055 hf_ntlmssp_negotiate_flags_1000,
1056 tvb, offset, 4, negotiate_flags);
1057 proto_tree_add_boolean (negotiate_flags_tree,
1058 hf_ntlmssp_negotiate_flags_800,
1059 tvb, offset, 4, negotiate_flags);
1060 proto_tree_add_boolean (negotiate_flags_tree,
1061 hf_ntlmssp_negotiate_flags_400,
1062 tvb, offset, 4, negotiate_flags);
1063 proto_tree_add_boolean (negotiate_flags_tree,
1064 hf_ntlmssp_negotiate_flags_200,
1065 tvb, offset, 4, negotiate_flags);
1066 proto_tree_add_boolean (negotiate_flags_tree,
1067 hf_ntlmssp_negotiate_flags_100,
1068 tvb, offset, 4, negotiate_flags);
1069 proto_tree_add_boolean (negotiate_flags_tree,
1070 hf_ntlmssp_negotiate_flags_80,
1071 tvb, offset, 4, negotiate_flags);
1072 proto_tree_add_boolean (negotiate_flags_tree,
1073 hf_ntlmssp_negotiate_flags_40,
1074 tvb, offset, 4, negotiate_flags);
1075 proto_tree_add_boolean (negotiate_flags_tree,
1076 hf_ntlmssp_negotiate_flags_20,
1077 tvb, offset, 4, negotiate_flags);
1078 proto_tree_add_boolean (negotiate_flags_tree,
1079 hf_ntlmssp_negotiate_flags_10,
1080 tvb, offset, 4, negotiate_flags);
1081 proto_tree_add_boolean (negotiate_flags_tree,
1082 hf_ntlmssp_negotiate_flags_08,
1083 tvb, offset, 4, negotiate_flags);
1084 proto_tree_add_boolean (negotiate_flags_tree,
1085 hf_ntlmssp_negotiate_flags_04,
1086 tvb, offset, 4, negotiate_flags);
1087 proto_tree_add_boolean (negotiate_flags_tree,
1088 hf_ntlmssp_negotiate_flags_02,
1089 tvb, offset, 4, negotiate_flags);
1090 proto_tree_add_boolean (negotiate_flags_tree,
1091 hf_ntlmssp_negotiate_flags_01,
1092 tvb, offset, 4, negotiate_flags);
1094 return (offset + 4);
1097 /* Dissect "version" */
1100 0 Major Version Number 1 byte
1101 1 Minor Version Number 1 byte
1102 2 Build Number short(LE)
1103 3 (Reserved) 3 bytes
1104 4 NTLM Current Revision 1 byte
1108 dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
1109 proto_tree *ntlmssp_tree)
1113 proto_tree *version_tree;
1114 tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
1115 "Version %u.%u (Build %u); NTLM Current Revision %u",
1116 tvb_get_guint8(tvb, offset),
1117 tvb_get_guint8(tvb, offset+1),
1118 tvb_get_letohs(tvb, offset+2),
1119 tvb_get_guint8(tvb, offset+7));
1120 version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
1121 proto_tree_add_item(version_tree, hf_ntlmssp_version_major , tvb, offset , 1, ENC_NA);
1122 proto_tree_add_item(version_tree, hf_ntlmssp_version_minor , tvb, offset+1, 1, ENC_NA);
1123 proto_tree_add_item(version_tree, hf_ntlmssp_version_build_number , tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1124 proto_tree_add_item(version_tree, hf_ntlmssp_version_ntlm_current_revision, tvb, offset+7, 1, ENC_NA);
1129 /* Dissect a NTLM response. This is documented at
1130 http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
1132 /* Attribute types */
1134 * XXX - the davenport document says that a type of 5 has been seen,
1135 * "apparently containing the 'parent' DNS domain for servers in
1137 * XXX: MS-NLMP info is newer than Davenport info;
1138 * The attribute type list and the attribute names below are
1139 * based upon MS-NLMP.
1142 #define NTLM_TARGET_INFO_END 0x0000
1143 #define NTLM_TARGET_INFO_NB_COMPUTER_NAME 0x0001
1144 #define NTLM_TARGET_INFO_NB_DOMAIN_NAME 0x0002
1145 #define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
1146 #define NTLM_TARGET_INFO_DNS_DOMAIN_NAME 0x0004
1147 #define NTLM_TARGET_INFO_DNS_TREE_NAME 0x0005
1148 #define NTLM_TARGET_INFO_FLAGS 0x0006
1149 #define NTLM_TARGET_INFO_TIMESTAMP 0x0007
1150 #define NTLM_TARGET_INFO_RESTRICTIONS 0x0008
1151 #define NTLM_TARGET_INFO_TARGET_NAME 0x0009
1152 #define NTLM_TARGET_INFO_CHANNEL_BINDINGS 0x000A
1154 static const value_string ntlm_name_types[] = {
1155 { NTLM_TARGET_INFO_END, "End of list" },
1156 { NTLM_TARGET_INFO_NB_COMPUTER_NAME, "NetBIOS computer name" },
1157 { NTLM_TARGET_INFO_NB_DOMAIN_NAME, "NetBIOS domain name" },
1158 { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
1159 { NTLM_TARGET_INFO_DNS_DOMAIN_NAME, "DNS domain name" },
1160 { NTLM_TARGET_INFO_DNS_TREE_NAME, "DNS tree name" },
1161 { NTLM_TARGET_INFO_FLAGS, "Flags" },
1162 { NTLM_TARGET_INFO_TIMESTAMP, "Timestamp" },
1163 { NTLM_TARGET_INFO_RESTRICTIONS, "Restrictions" },
1164 { NTLM_TARGET_INFO_TARGET_NAME, "Target Name"},
1165 { NTLM_TARGET_INFO_CHANNEL_BINDINGS, "Channel Bindings"},
1169 /* The following *must* match the order of the list of attribute types */
1170 /* Assumption: values in the list are a sequence starting with 0 and */
1171 /* with no gaps allowing a direct access of the array by attribute type */
1172 static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
1173 &hf_ntlmssp_challenge_target_info_end,
1174 &hf_ntlmssp_challenge_target_info_nb_computer_name,
1175 &hf_ntlmssp_challenge_target_info_nb_domain_name,
1176 &hf_ntlmssp_challenge_target_info_dns_computer_name,
1177 &hf_ntlmssp_challenge_target_info_dns_domain_name,
1178 &hf_ntlmssp_challenge_target_info_dns_tree_name,
1179 &hf_ntlmssp_challenge_target_info_flags,
1180 &hf_ntlmssp_challenge_target_info_timestamp,
1181 &hf_ntlmssp_challenge_target_info_restrictions,
1182 &hf_ntlmssp_challenge_target_info_target_name,
1183 &hf_ntlmssp_challenge_target_info_channel_bindings
1186 static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
1187 &hf_ntlmssp_ntlmv2_response_end,
1188 &hf_ntlmssp_ntlmv2_response_nb_computer_name,
1189 &hf_ntlmssp_ntlmv2_response_nb_domain_name,
1190 &hf_ntlmssp_ntlmv2_response_dns_computer_name,
1191 &hf_ntlmssp_ntlmv2_response_dns_domain_name,
1192 &hf_ntlmssp_ntlmv2_response_dns_tree_name,
1193 &hf_ntlmssp_ntlmv2_response_flags,
1194 &hf_ntlmssp_ntlmv2_response_timestamp,
1195 &hf_ntlmssp_ntlmv2_response_restrictions,
1196 &hf_ntlmssp_ntlmv2_response_target_name,
1197 &hf_ntlmssp_ntlmv2_response_channel_bindings
1200 typedef struct _tif {
1203 int *hf_item_length;
1204 int **hf_attr_array_p;
1207 static tif_t ntlmssp_challenge_target_info_tif = {
1208 &ett_ntlmssp_challenge_target_info_item,
1209 &hf_ntlmssp_challenge_target_info_item_type,
1210 &hf_ntlmssp_challenge_target_info_item_len,
1211 ntlmssp_hf_challenge_target_info_hf_ptr_array
1214 static tif_t ntlmssp_ntlmv2_response_tif = {
1215 &ett_ntlmssp_ntlmv2_response_item,
1216 &hf_ntlmssp_ntlmv2_response_item_type,
1217 &hf_ntlmssp_ntlmv2_response_item_len,
1218 ntlmssp_hf_ntlmv2_response_hf_ptr_array
1222 dissect_ntlmssp_target_info_list(tvbuff_t *tvb, proto_tree *tree,
1223 guint32 target_info_offset, guint16 target_info_length,
1226 guint32 item_offset;
1228 guint16 item_length;
1231 /* Now enumerate through the individual items in the list */
1232 item_offset = target_info_offset;
1234 while (item_offset < (target_info_offset + target_info_length)) {
1235 proto_item *target_info_tf;
1236 proto_tree *target_info_tree;
1237 guint32 content_offset;
1238 guint16 content_length;
1239 guint32 type_offset;
1242 int **hf_array_p = tif_p->hf_attr_array_p;
1245 type_offset = item_offset;
1246 item_type = tvb_get_letohs(tvb, type_offset);
1248 /* Content length */
1249 len_offset = type_offset + 2;
1250 content_length = tvb_get_letohs(tvb, len_offset);
1253 content_offset = len_offset + 2;
1254 item_length = content_length + 4;
1256 target_info_tf = proto_tree_add_text(tree, tvb, item_offset, item_length, "Attribute: %s",
1257 val_to_str(item_type, ntlm_name_types, "Unknown (%d)"));
1259 target_info_tree = proto_item_add_subtree (target_info_tf, *tif_p->ett);
1260 proto_tree_add_item (target_info_tree, *tif_p->hf_item_type, tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
1261 proto_tree_add_item (target_info_tree, *tif_p->hf_item_length, tvb, len_offset, 2, ENC_LITTLE_ENDIAN);
1263 switch (item_type) {
1264 case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
1265 case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
1266 case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
1267 case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
1268 case NTLM_TARGET_INFO_DNS_TREE_NAME:
1269 case NTLM_TARGET_INFO_TARGET_NAME:
1270 if (content_length > 0) {
1273 text = tvb_get_ephemeral_faked_unicode(tvb, content_offset, content_length / 2, TRUE);
1274 proto_tree_add_string(target_info_tree, *hf_array_p[item_type],
1275 tvb, content_offset, content_length, text);
1276 proto_item_append_text(target_info_tf, ": %s", text);
1280 case NTLM_TARGET_INFO_FLAGS:
1281 proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
1282 tvb, content_offset, content_length, ENC_LITTLE_ENDIAN);
1285 case NTLM_TARGET_INFO_TIMESTAMP:
1286 dissect_nt_64bit_time(tvb, target_info_tree, content_offset, *hf_array_p[item_type]);
1289 case NTLM_TARGET_INFO_RESTRICTIONS:
1290 case NTLM_TARGET_INFO_CHANNEL_BINDINGS:
1291 proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
1292 tvb, content_offset, content_length, ENC_NA);
1299 item_offset += item_length;
1304 dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
1306 proto_item *ntlmv2_item = NULL;
1307 proto_tree *ntlmv2_tree = NULL;
1310 /* Dissect NTLMv2 bits&pieces */
1311 orig_offset = offset;
1314 ntlmv2_item = proto_tree_add_item(
1315 tree, hf_ntlmssp_ntlmv2_response, tvb,
1317 ntlmv2_tree = proto_item_add_subtree(
1318 ntlmv2_item, ett_ntlmssp_ntlmv2_response);
1321 proto_tree_add_item(
1322 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hmac, tvb,
1327 proto_tree_add_item(
1328 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_header, tvb,
1333 proto_tree_add_item(
1334 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_reserved, tvb,
1339 offset = dissect_nt_64bit_time(
1340 tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time);
1342 proto_tree_add_item(
1343 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
1348 proto_tree_add_item(
1349 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_unknown, tvb,
1354 /* Variable length list of attributes */
1356 * XXX - Windows puts one or more sets of 4 bytes of additional stuff (all zeros ?)
1357 * at the end of the attributes.
1358 * Samba's smbclient doesn't.
1359 * Both of them appear to be able to connect to W2K SMB
1361 * The additional stuff will be dissected as extra "end" attributes.
1364 dissect_ntlmssp_target_info_list(tvb, ntlmv2_tree,
1365 offset, len - (offset - orig_offset),
1366 &ntlmssp_ntlmv2_response_tif);
1371 /* tapping into ntlmssph not yet implemented */
1373 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1375 guint32 negotiate_flags;
1381 /* NTLMSSP Negotiate Flags */
1382 negotiate_flags = tvb_get_letohl (tvb, offset);
1383 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1387 * XXX - the davenport document says that these might not be
1388 * sent at all, presumably meaning the length of the message
1389 * isn't enough to contain them.
1391 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1392 hf_ntlmssp_negotiate_domain,
1393 &data_start, &data_end, NULL);
1395 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1396 hf_ntlmssp_negotiate_workstation,
1397 &item_start, &item_end, NULL);
1398 data_start = MIN(data_start, item_start);
1399 data_end = MAX(data_end, item_end);
1401 /* If there are more bytes before the data block dissect a version field */
1402 if (offset < data_start) {
1403 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1410 dissect_ntlmssp_challenge_target_info_blob (tvbuff_t *tvb, int offset,
1411 proto_tree *ntlmssp_tree,
1414 guint16 challenge_target_info_length = tvb_get_letohs(tvb, offset);
1415 guint16 challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
1416 guint32 challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
1417 proto_item *tf = NULL;
1418 proto_tree *challenge_target_info_tree = NULL;
1420 /* the target info list is just a blob */
1421 if (0 == challenge_target_info_length) {
1422 *end = (challenge_target_info_offset > ((guint)offset)+8 ? challenge_target_info_offset : ((guint)offset)+8);
1424 proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
1425 "Target Info List: Empty");
1430 tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
1431 challenge_target_info_offset, challenge_target_info_length, FALSE);
1432 challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
1434 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
1435 tvb, offset, 2, challenge_target_info_length);
1437 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
1438 tvb, offset, 2, challenge_target_info_maxlen);
1440 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
1441 tvb, offset, 4, challenge_target_info_offset);
1444 dissect_ntlmssp_target_info_list(tvb, challenge_target_info_tree,
1445 challenge_target_info_offset, challenge_target_info_length,
1446 &ntlmssp_challenge_target_info_tif);
1448 *end = challenge_target_info_offset + challenge_target_info_length;
1452 /* tapping into ntlmssph not yet implemented */
1454 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
1455 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1457 guint32 negotiate_flags;
1458 int item_start, item_end;
1459 int data_start, data_end; /* MIN and MAX seen */
1460 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1461 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1462 ntlmssp_info *conv_ntlmssp_info = NULL;
1463 conversation_t *conversation;
1464 gboolean unicode_strings = FALSE;
1465 guint8 challenge[8];
1467 guint8 sspkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key */
1468 int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
1470 /* need to find unicode flag */
1471 negotiate_flags = tvb_get_letohl (tvb, offset+8);
1472 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
1473 unicode_strings = TRUE;
1477 * XXX - the davenport document (and MS-NLMP) calls this "Target Name",
1478 * presumably because non-domain targets are supported.
1479 * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
1481 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
1482 hf_ntlmssp_challenge_target_name,
1483 &item_start, &item_end, NULL);
1484 data_start = item_start;
1485 data_end = item_end;
1487 /* NTLMSSP Negotiate Flags */
1488 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1491 /* NTLMSSP NT Lan Manager Challenge */
1492 proto_tree_add_item (ntlmssp_tree,
1493 hf_ntlmssp_ntlm_server_challenge,
1494 tvb, offset, 8, FALSE);
1497 * Store the flags and the RC4 state information with the conversation,
1498 * as they're needed in order to dissect subsequent messages.
1500 conversation = find_or_create_conversation(pinfo);
1502 tvb_memcpy(tvb, tmp, offset, 8); /* challenge */
1503 /* We can face more than one NTLM exchange over the same couple of IP and ports ...*/
1504 conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
1505 /* XXX: The following code is (re)executed every time a particular frame is dissected
1506 * (in whatever order). Thus it seems to me that "multiple exchanges" might not be
1507 * handled well depending on the order that frames are visited after the initial dissection.
1509 if (!conv_ntlmssp_info || memcmp(tmp,conv_ntlmssp_info->server_challenge,8) != 0) {
1510 conv_ntlmssp_info = se_alloc(sizeof(ntlmssp_info));
1511 /* Insert the flags into the conversation */
1512 conv_ntlmssp_info->flags = negotiate_flags;
1513 /* Insert the RC4 state information into the conversation */
1514 tvb_memcpy(tvb, challenge, offset, 8);
1515 tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
1516 conv_ntlmssp_info->is_auth_ntlm_v2=0;
1517 /* Between the challenge and the user provided password, we can build the
1518 NTLMSSP key and initialize the cipher if we are not in EXTENDED SECURITY
1519 in this case we need the client challenge as well*/
1520 /* BTW this is true just if we are in LM Authentification if not the logic is a bit different.
1521 * Right now it's not very clear what is LM Authentification it __seems__ to be when
1522 * NEGOTIATE NT ONLY is not set and NEGOSIATE EXTENDED SECURITY is not set as well*/
1523 if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1525 conv_ntlmssp_info->rc4_state_initialized = 0;
1526 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);
1527 if( memcmp(sspkey,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
1528 get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
1529 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, sspkey, ssp_key_len);
1530 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, sspkey, ssp_key_len);
1531 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1532 conv_ntlmssp_info->rc4_state_initialized = 1;
1536 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1540 /* If no more bytes (ie: no "reserved", ...) before start of data block, then return */
1541 /* XXX: According to Davenport "This form is seen in older Win9x-based systems" */
1542 /* Also: I've seen a capture with an HTTP CONNECT proxy-authentication */
1543 /* message wherein the challenge from the proxy has this form. */
1544 if (offset >= data_start) {
1548 /* Reserved (function not completely known) */
1550 * XXX - SSP key? The davenport document says
1552 * The context field is typically populated when Negotiate Local
1553 * Call is set. It contains an SSPI context handle, which allows
1554 * the client to "short-circuit" authentication and effectively
1555 * circumvent responding to the challenge. Physically, the context
1556 * is two long values. This is covered in greater detail later,
1557 * in the "Local Authentication" section.
1559 * It also says that that information may be omitted.
1561 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
1562 tvb, offset, 8, FALSE);
1566 * The presence or absence of this field is not obviously correlated
1567 * with any flags in the previous NEGOTIATE message or in this
1568 * message (other than the "Workstation Supplied" and "Domain
1569 * Supplied" flags in the NEGOTIATE message, at least in the capture
1570 * I've seen - but those also correlate with the presence of workstation
1571 * and domain name fields, so it doesn't seem to make sense that they
1572 * actually *indicate* whether the subsequent CHALLENGE has an
1575 if (offset < data_start) {
1576 offset = dissect_ntlmssp_challenge_target_info_blob(tvb, offset, ntlmssp_tree, &item_end);
1577 /* XXX: This code assumes that the address list in the data block */
1578 /* is always after the target name. Is this OK ? */
1579 data_end = MAX(data_end, item_end);
1582 /* If there are more bytes before the data block dissect a version field */
1583 if (offset < data_start) {
1584 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1587 return MAX(offset, data_end);
1591 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
1592 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
1594 int item_start, item_end;
1595 int data_start, data_end = 0;
1596 guint32 negotiate_flags;
1597 guint8 sspkey[NTLMSSP_KEY_LEN]; /* exported session key */
1598 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1599 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1600 guint8 encryptedsessionkey[NTLMSSP_KEY_LEN];
1601 ntlmssp_blob sessionblob;
1602 gboolean unicode_strings = FALSE;
1603 ntlmssp_info *conv_ntlmssp_info = NULL;
1604 conversation_t *conversation;
1607 * Get flag info from the original negotiate message, if any.
1608 * This is because the flag information is sometimes missing from
1609 * the AUTHENTICATE message, so we can't figure out whether
1610 * strings are Unicode or not by looking at *our* flags.
1611 * XXX it seems it's more from the CHALLENGE message, which is more clever in fact
1612 * because the server can change some flags.
1613 * But according to MS NTLMSSP doc it's not that simple.
1614 * In case of Conection less mode AUTHENTICATE flags should be used because they
1615 * reprensent the choice of the client after having been informed of options of the
1616 * server in the CHALLENGE message.
1617 * In Connection mode then the CHALLENGE flags should (must ?) be used
1618 * XXX: MS-NLMP says the flag field in the AUTHENTICATE message "contains the set of bit
1619 * flags (section 2.2.2.5) negotiated in the previous messages."
1620 * I read that to mean that the flags for in connection-mode AUTHENTICATE also represent
1621 * the choice of the client (for the flags which are negotiated).
1622 * XXX: In the absence of CHALLENGE flags, as a last resort we'll use the flags
1623 * (if available) from this AUTHENTICATE message.
1624 * I've seen a capture which does an HTTP CONNECT which:
1625 * - has the NEGOTIATE & CHALLENGE messages in one TCP connection;
1626 * - has the AUTHENTICATE message in a second TCP connection;
1627 * (The authentication aparently succeeded).
1629 conv_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
1630 if (conv_ntlmssp_info == NULL) {
1632 * There isn't any. Is there any from this conversation? If so,
1633 * it means this is the first time we've dissected this frame, so
1634 * we should give it flag info.
1636 /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
1637 /* so we'll have a place to store flags. */
1638 /* This is a bit brute-force but looks like it will be OK. */
1639 conversation = find_or_create_conversation(pinfo);
1640 conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
1641 if (conv_ntlmssp_info == NULL) {
1642 conv_ntlmssp_info = se_alloc0(sizeof(ntlmssp_info));
1643 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1645 /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
1646 same as the one attached to the conversation. That is: *both* point to
1647 the exact same struct in memory. Is this what is indended ? */
1648 p_add_proto_data(pinfo->fd, proto_ntlmssp, conv_ntlmssp_info);
1651 if (conv_ntlmssp_info != NULL) {
1652 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
1653 unicode_strings = TRUE;
1657 * Sometimes the session key and flags are missing.
1658 * Sometimes the session key is present but the flags are missing.
1659 * XXX Who stay so ? Reading spec I would rather say the opposite: flags are
1660 * always present, session information are always there as well but sometime
1661 * session information could be null (in case of no session)
1662 * Sometimes they're both present.
1664 * This does not correlate with any flags in the previous CHALLENGE
1665 * message, and only correlates with "Negotiate Unicode", "Workstation
1666 * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
1667 * those don't make sense as flags to use to determine this.
1669 * So we check all of the descriptors to figure out where the data
1670 * area begins, and if the session key or the flags would be in the
1671 * middle of the data area, we assume the field in question is
1674 * XXX - Reading Davenport and MS-NLMP: as I see it the possibilities are:
1675 * a. No session-key; no flags; no version ("Win9x")
1676 * b. Session-key & flags.
1677 * c. Session-key, flags & version.
1678 * In cases b and c the session key may be "null".
1682 /* Lan Manager response */
1683 data_start = tvb_get_letohl(tvb, offset+4);
1684 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1685 hf_ntlmssp_auth_lmresponse,
1687 conv_ntlmssp_info == NULL ? NULL :
1688 &conv_ntlmssp_info->lm_response);
1689 data_end = MAX(data_end, item_end);
1692 item_start = tvb_get_letohl(tvb, offset+4);
1693 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1694 hf_ntlmssp_auth_ntresponse,
1696 conv_ntlmssp_info == NULL ? NULL :
1697 &conv_ntlmssp_info->ntlm_response);
1698 if( conv_ntlmssp_info != NULL && conv_ntlmssp_info->ntlm_response.length > 24 ) {
1699 memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->ntlm_response.contents+32,8);
1701 data_start = MIN(data_start, item_start);
1702 data_end = MAX(data_end, item_end);
1703 if( conv_ntlmssp_info != NULL )
1705 if( conv_ntlmssp_info->ntlm_response.length > 24 )
1707 conv_ntlmssp_info->is_auth_ntlm_v2=1;
1711 conv_ntlmssp_info->is_auth_ntlm_v2=0;
1716 item_start = tvb_get_letohl(tvb, offset+4);
1717 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1719 hf_ntlmssp_auth_domain,
1720 &item_start, &item_end, &(ntlmssph->domain_name));
1721 /*ntlmssph->domain_name_len=item_end-item_start;*/
1722 data_start = MIN(data_start, item_start);
1723 data_end = MAX(data_end, item_end);
1726 item_start = tvb_get_letohl(tvb, offset+4);
1727 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1729 hf_ntlmssp_auth_username,
1730 &item_start, &item_end, &(ntlmssph->acct_name));
1731 /*ntlmssph->acct_name_len=item_end-item_start;*/
1732 data_start = MIN(data_start, item_start);
1733 data_end = MAX(data_end, item_end);
1735 if (check_col(pinfo->cinfo, COL_INFO))
1736 col_append_fstr(pinfo->cinfo, COL_INFO, ", User: %s\\%s",
1737 ntlmssph->domain_name, ntlmssph->acct_name);
1740 item_start = tvb_get_letohl(tvb, offset+4);
1741 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1743 hf_ntlmssp_auth_hostname,
1744 &item_start, &item_end, &(ntlmssph->host_name));
1745 data_start = MIN(data_start, item_start);
1746 data_end = MAX(data_end, item_end);
1748 memset(sessionblob.contents, 0, MAX_BLOB_SIZE);
1749 sessionblob.length = 0;
1750 if (offset < data_start) {
1752 offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
1753 hf_ntlmssp_auth_sesskey,
1754 &item_end, &sessionblob);
1755 data_end = MAX(data_end, item_end);
1758 if (offset < data_start) {
1759 /* NTLMSSP Negotiate Flags */
1760 negotiate_flags = tvb_get_letohl (tvb, offset);
1761 offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
1763 /* If no previous flags seen (ie: no previous CHALLENGE) use flags
1764 from the AUTHENTICATE message).
1765 Assumption: (flags == 0) means flags not previously seen */
1766 if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
1767 conv_ntlmssp_info->flags = negotiate_flags;
1771 /* If there are more bytes before the data block dissect a version field */
1772 if (offset < data_start) {
1773 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1776 /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
1778 if (offset < data_start) {
1779 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_message_integrity_code, tvb, offset, 16, ENC_NA);
1783 if ( sessionblob.length > NTLMSSP_KEY_LEN ) {
1784 expert_add_info_format(pinfo, NULL, PI_WARN, PI_UNDECODED, "Session blob length too long: %u", sessionblob.length);
1785 } else if( sessionblob.length != 0 ) {
1786 memcpy(encryptedsessionkey,sessionblob.contents,sessionblob.length);
1787 /* Try to attach to an existing conversation if not then it's useless to try to do so
1788 * because we are missing important information (ie. server challenge)
1790 if (conv_ntlmssp_info) {
1791 /* If we are in EXTENDED SECURITY then we can now initialize cipher */
1792 if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1794 conv_ntlmssp_info->rc4_state_initialized = 0;
1795 if( conv_ntlmssp_info->is_auth_ntlm_v2 ) {
1796 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);
1800 memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->lm_response.contents,8);
1801 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);
1803 /* ssp is the exported session key */
1804 if( memcmp(sspkey,gbl_zeros,NTLMSSP_KEY_LEN) != 0) {
1805 get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
1806 get_siging_key((guint8*)&conv_ntlmssp_info->sign_key_server,(guint8*)&conv_ntlmssp_info->sign_key_client,sspkey,ssp_key_len);
1807 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, serverkey, ssp_key_len);
1808 crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, clientkey, ssp_key_len);
1809 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1810 conv_ntlmssp_info->rc4_state_initialized = 1;
1815 return MAX(offset, data_end);
1818 get_sign_key(packet_info *pinfo, int cryptpeer)
1820 conversation_t *conversation;
1821 ntlmssp_info *conv_ntlmssp_info;
1823 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1824 pinfo->ptype, pinfo->srcport,
1825 pinfo->destport, 0);
1826 if (conversation == NULL) {
1827 /* We don't have a conversation. In this case, stop processing
1828 because we do not have enough info to decrypt the payload */
1832 /* We have a conversation, check for encryption state */
1833 conv_ntlmssp_info = conversation_get_proto_data(conversation,
1835 if (conv_ntlmssp_info == NULL) {
1836 /* No encryption state tied to the conversation. Therefore, we
1837 cannot decrypt the payload */
1841 /* We have the encryption state in the conversation. So return the
1842 crypt state tied to the requested peer
1844 if (cryptpeer == 1) {
1845 return (guint8*)&conv_ntlmssp_info->sign_key_client;
1847 return (guint8*)&conv_ntlmssp_info->sign_key_server;
1853 * Get the encryption state tied to this conversation. cryptpeer indicates
1854 * whether to retrieve the client key (1) or the server key (0)
1856 static rc4_state_struct *
1857 get_encrypted_state(packet_info *pinfo, int cryptpeer)
1859 conversation_t *conversation;
1860 ntlmssp_info *conv_ntlmssp_info;
1862 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1863 pinfo->ptype, pinfo->srcport,
1864 pinfo->destport, 0);
1865 if (conversation == NULL) {
1866 /* We don't have a conversation. In this case, stop processing
1867 because we do not have enough info to decrypt the payload */
1871 /* We have a conversation, check for encryption state */
1872 conv_ntlmssp_info = conversation_get_proto_data(conversation,
1874 if (conv_ntlmssp_info == NULL) {
1875 /* No encryption state tied to the conversation. Therefore, we
1876 cannot decrypt the payload */
1880 /* We have the encryption state in the conversation. So return the
1881 crypt state tied to the requested peer
1883 if (cryptpeer == 1) {
1884 return &conv_ntlmssp_info->rc4_state_client;
1886 return &conv_ntlmssp_info->rc4_state_server;
1892 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1893 packet_info *pinfo, proto_tree *tree _U_,gpointer key);
1895 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1896 packet_info *pinfo, proto_tree *tree,gpointer key);
1899 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
1900 tvbuff_t *auth_tvb _U_,
1903 dcerpc_auth_info *auth_info _U_)
1907 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1909 volatile int offset = 0;
1910 proto_tree *volatile ntlmssp_tree = NULL;
1911 proto_item *tf = NULL;
1913 guint32 encrypted_block_length;
1914 guint8 key[NTLMSSP_KEY_LEN];
1915 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
1917 guint32 ntlm_magic_size = 4;
1918 guint32 ntlm_signature_size = 8;
1919 guint32 ntlm_seq_size = 4;
1920 length = tvb_length (tvb);
1921 /* signature + seq + real payload */
1922 encrypted_block_length = length - ntlm_magic_size;
1924 if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
1925 /* Don't know why this would happen, but if it does, don't even bother
1926 attempting decryption/dissection */
1927 return offset + length;
1930 /* Setup a new tree for the NTLMSSP payload */
1932 tf = proto_tree_add_item (tree,
1934 tvb, offset, -1, FALSE);
1936 ntlmssp_tree = proto_item_add_subtree (tf,
1941 * Catch the ReportedBoundsError exception; the stuff we've been
1942 * handed doesn't necessarily run to the end of the packet, it's
1943 * an item inside a packet, so if it happens to be malformed (or
1944 * we, or a dissector we call, has a bug), so that an exception
1945 * is thrown, we want to report the error, but return and let
1946 * our caller dissect the rest of the packet.
1948 * If it gets a BoundsError, we can stop, as there's nothing more
1949 * in the packet after our blob to see, so we just re-throw the
1953 /* Version number */
1954 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
1955 tvb, offset, 4, TRUE);
1958 /* Encrypted body */
1959 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
1960 tvb, offset, ntlm_signature_size + ntlm_seq_size, TRUE);
1961 tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
1962 /* Try to decrypt */
1963 decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree,key);
1964 decrypt_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo, ntlmssp_tree,key);
1965 /* let's try to hook ourselves here */
1968 } CATCH(BoundsError) {
1970 } CATCH(ReportedBoundsError) {
1971 show_reported_bounds_error(tvb, pinfo, tree);
1977 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1978 packet_info *pinfo, proto_tree *tree _U_,gpointer key)
1980 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
1982 conversation_t *conversation;
1983 rc4_state_struct *rc4_state;
1984 rc4_state_struct *rc4_state_peer;
1985 ntlmssp_info *conv_ntlmssp_info = NULL;
1986 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
1987 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
1989 /* Check to see if we already have state for this packet */
1990 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
1991 if (packet_ntlmssp_info == NULL) {
1992 /* We don't have any packet state, so create one */
1993 packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
1994 p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
1996 if (!packet_ntlmssp_info->payload_decrypted) {
1997 /* Pull the challenge info from the conversation */
1998 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1999 pinfo->ptype, pinfo->srcport,
2000 pinfo->destport, 0);
2001 if (conversation == NULL) {
2002 /* There is no conversation, thus no encryption state */
2006 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2008 if (conv_ntlmssp_info == NULL) {
2009 /* There is no NTLMSSP state tied to the conversation */
2012 if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
2013 /* The crypto sybsystem is not initialized. This means that either
2014 the conversation did not include a challenge, or that we do not have the right password */
2018 stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
2020 if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == TRUE)
2022 /* Mat TBD (stderr,"Found a already decrypted packet\n");*/
2023 memcpy(packet_ntlmssp_info,stored_packet_ntlmssp_info,sizeof(ntlmssp_packet_info));
2024 /* Mat TBD printnbyte(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"Data: ","\n");*/
2028 /* Get the pair of RC4 state structures. One is used for to decrypt the
2029 payload. The other is used to re-encrypt the payload to represent
2031 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2033 rc4_state = get_encrypted_state(pinfo, 1);
2034 rc4_state_peer = get_encrypted_state(pinfo, 0);
2037 rc4_state = get_encrypted_state(pinfo, 0);
2038 rc4_state_peer = get_encrypted_state(pinfo, 1);
2041 if (rc4_state == NULL ) {
2042 /* There is no encryption state, so we cannot decrypt */
2046 /* Store the decrypted contents in the packet state struct
2047 (of course at this point, they aren't decrypted yet) */
2048 packet_ntlmssp_info->decrypted_payload = tvb_memdup(tvb, offset,
2049 encrypted_block_length);
2050 packet_ntlmssp_info->payload_len = encrypted_block_length;
2051 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2052 packet_ntlmssp_info->decrypted_payload);
2054 g_hash_table_insert(hash_packet,key,packet_ntlmssp_info);
2057 /* Do the decryption of the payload */
2058 crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
2059 encrypted_block_length);
2060 /* decrypt the verifier */
2061 /*printnchar(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"data: ","\n");*/
2062 /* We setup a temporary buffer so we can re-encrypt the payload after
2063 decryption. This is to update the opposite peer's RC4 state
2064 it's usefull when we have only one key for both conversation
2065 in case of KEY_EXCH we have independant key so this is not needed*/
2066 if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2067 peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2068 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2071 packet_ntlmssp_info->payload_decrypted = TRUE;
2075 /* Show the decrypted buffer in a new window */
2076 decr_tvb = tvb_new_real_data(packet_ntlmssp_info->decrypted_payload,
2077 encrypted_block_length,
2078 encrypted_block_length);
2080 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2081 pinfo->gssapi_decrypted_tvb = decr_tvb;
2084 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2086 volatile int offset = 0;
2087 proto_tree *volatile ntlmssp_tree = NULL;
2088 proto_item *tf = NULL;
2089 ntlmssp_header_t *ntlmssph;
2091 ntlmssph=ep_alloc(sizeof(ntlmssp_header_t));
2093 ntlmssph->domain_name=NULL;
2094 ntlmssph->acct_name=NULL;
2095 ntlmssph->host_name=NULL;
2097 /* Setup a new tree for the NTLMSSP payload */
2099 tf = proto_tree_add_item (tree,
2101 tvb, offset, -1, FALSE);
2103 ntlmssp_tree = proto_item_add_subtree (tf,
2108 * Catch the ReportedBoundsError exception; the stuff we've been
2109 * handed doesn't necessarily run to the end of the packet, it's
2110 * an item inside a packet, so if it happens to be malformed (or
2111 * we, or a dissector we call, has a bug), so that an exception
2112 * is thrown, we want to report the error, but return and let
2113 * our caller dissect the rest of the packet.
2115 * If it gets a BoundsError, we can stop, as there's nothing more
2116 * in the packet after our blob to see, so we just re-throw the
2120 /* NTLMSSP constant */
2121 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
2122 tvb, offset, 8, FALSE);
2125 /* NTLMSSP Message Type */
2126 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
2127 tvb, offset, 4, TRUE);
2128 ntlmssph->type = tvb_get_letohl (tvb, offset);
2131 if (check_col(pinfo->cinfo, COL_INFO))
2132 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2133 val_to_str(ntlmssph->type,
2134 ntlmssp_message_types,
2135 "Unknown message type"));
2137 /* Call the appropriate dissector based on the Message Type */
2138 switch (ntlmssph->type) {
2140 case NTLMSSP_NEGOTIATE:
2141 offset = dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree, ntlmssph);
2144 case NTLMSSP_CHALLENGE:
2145 offset = dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2149 offset = dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2153 /* Unrecognized message type */
2154 proto_tree_add_text (ntlmssp_tree, tvb, offset, -1,
2155 "Unrecognized NTLMSSP Message");
2158 } CATCH(BoundsError) {
2160 } CATCH(ReportedBoundsError) {
2161 show_reported_bounds_error(tvb, pinfo, tree);
2164 /*tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);*/
2170 * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
2173 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
2174 packet_info *pinfo, proto_tree *tree,gpointer key)
2176 proto_tree *decr_tree = NULL;
2177 proto_item *tf = NULL;
2178 conversation_t *conversation;
2180 rc4_state_struct *rc4_state;
2181 rc4_state_struct *rc4_state_peer;
2182 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2185 guint8 calculated_md5[NTLMSSP_KEY_LEN];
2186 ntlmssp_info *conv_ntlmssp_info = NULL;
2187 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2188 int decrypted_offset = 0;
2191 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2192 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2193 if (packet_ntlmssp_info == NULL) {
2194 /* We don't have data for this packet */
2197 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2198 pinfo->ptype, pinfo->srcport,
2199 pinfo->destport, 0);
2200 if (conversation == NULL) {
2201 /* There is no conversation, thus no encryption state */
2204 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2206 if (conv_ntlmssp_info == NULL) {
2207 /* There is no NTLMSSP state tied to the conversation */
2212 stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
2214 if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->verifier_decrypted == TRUE) {
2215 /* Mat TBD fprintf(stderr,"Found a already decrypted packet\n");*/
2216 /* In Theory it's aleady the case, and we should be more clever ... like just copying buffers ...*/
2217 packet_ntlmssp_info = stored_packet_ntlmssp_info;
2220 if (!packet_ntlmssp_info->verifier_decrypted) {
2221 if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
2222 /* The crypto sybsystem is not initialized. This means that either
2223 the conversation did not include a challenge, or we are doing
2224 something other than NTLMSSP v1 */
2227 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2228 /* client talk to server */
2229 rc4_state = get_encrypted_state(pinfo, 1);
2230 sign_key = get_sign_key(pinfo,1);
2231 rc4_state_peer = get_encrypted_state(pinfo, 0);
2233 rc4_state = get_encrypted_state(pinfo, 0);
2234 sign_key = get_sign_key(pinfo,0);
2235 rc4_state_peer = get_encrypted_state(pinfo, 1);
2238 if (rc4_state == NULL || rc4_state_peer == NULL) {
2239 /* There is no encryption state, so we cannot decrypt */
2243 /* Setup the buffer to decrypt to */
2244 tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
2245 offset, encrypted_block_length);
2247 /*if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
2248 if( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
2249 if( (NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2250 /* The spec says that if we have have a key exchange then we have a the signature that is crypted
2251 * otherwise it's just a hmac_md5(keysign,concat(message,sequence))[0..7]
2253 crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
2257 * Try to check the HMAC MD5 of the message against those calculated works great with LDAP payload but
2258 * don't with DCE/RPC calls.
2259 * Some analysis need to be done ...
2261 if( sign_key != NULL ) {
2262 check_buf = ep_alloc(packet_ntlmssp_info->payload_len+4);
2263 tvb_memcpy(tvb, &sequence,offset+8,4);
2264 memcpy(check_buf,&sequence,4);
2265 memcpy(check_buf+4,packet_ntlmssp_info->decrypted_payload,packet_ntlmssp_info->payload_len);
2266 md5_hmac(check_buf,(int)(packet_ntlmssp_info->payload_len+4),sign_key,NTLMSSP_KEY_LEN,calculated_md5);
2268 printnbyte(packet_ntlmssp_info->verifier,8,"HMAC from packet: ","\n");
2269 printnbyte(calculated_md5,8,"HMAC : ","\n");
2274 /* 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 */
2275 /* Do the actual decryption of the verifier */
2276 crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
2277 encrypted_block_length);
2282 /* We setup a temporary buffer so we can re-encrypt the payload after
2283 decryption. This is to update the opposite peer's RC4 state
2284 This is not needed when we just have EXTENDED SECURITY because the signature is not crypted
2285 and it's also not needed when we have key exchange because server and client have independant keys */
2286 if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SECURITY & conv_ntlmssp_info->flags)) {
2287 peer_block = ep_memdup(packet_ntlmssp_info->verifier, encrypted_block_length);
2288 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2291 /* Mark the packet as decrypted so that subsequent attempts to dissect
2292 the packet use the already decrypted payload instead of attempting
2294 packet_ntlmssp_info->verifier_decrypted = TRUE;
2297 /* Show the decrypted buffer in a new window */
2298 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
2299 encrypted_block_length,
2300 encrypted_block_length);
2301 add_new_data_source(pinfo, decr_tvb,
2302 "Decrypted NTLMSSP Verifier");
2304 /* Show the decrypted payload in the tree */
2305 tf = proto_tree_add_text(tree, decr_tvb, 0, -1,
2306 "Decrypted Verifier (%d byte%s)",
2307 encrypted_block_length,
2308 plurality(encrypted_block_length, "", "s"));
2309 decr_tree = proto_item_add_subtree (tf, ett_ntlmssp);
2311 if(( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
2312 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
2313 decr_tvb, decrypted_offset, 8,TRUE);
2314 decrypted_offset += 8;
2318 /* Incrementing sequence number of DCE conversation */
2319 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2320 decr_tvb, decrypted_offset, 4, TRUE);
2321 decrypted_offset += 4;
2325 /* RANDOM PAD usually it's 0 */
2326 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
2327 decr_tvb, decrypted_offset, 4, TRUE);
2328 decrypted_offset += 4;
2330 /* CRC32 of the DCE fragment data */
2331 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
2332 decr_tvb, decrypted_offset, 4, TRUE);
2333 decrypted_offset += 4;
2335 /* Incrementing sequence number of DCE conversation */
2336 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2337 decr_tvb, decrypted_offset, 4, TRUE);
2338 decrypted_offset += 4;
2342 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious*/
2344 dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *tree)
2346 volatile int offset = 0;
2347 proto_tree *volatile ntlmssp_tree = NULL;
2348 guint32 encrypted_block_length;
2349 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
2351 encrypted_block_length = tvb_length (tvb);
2352 /* signature + seq + real payload */
2354 /* Setup a new tree for the NTLMSSP payload */
2357 tf = proto_tree_add_item (tree,
2359 tvb, offset, -1, FALSE);
2361 ntlmssp_tree = proto_item_add_subtree (tf,
2366 * Catch the ReportedBoundsError exception; the stuff we've been
2367 * handed doesn't necessarily run to the end of the packet, it's
2368 * an item inside a packet, so if it happens to be malformed (or
2369 * we, or a dissector we call, has a bug), so that an exception
2370 * is thrown, we want to report the error, but return and let
2371 * our caller dissect the rest of the packet.
2373 * If it gets a BoundsError, we can stop, as there's nothing more
2374 * in the packet after our blob to see, so we just re-throw the
2378 /* Version number */
2380 /* Try to decrypt */
2381 decrypt_data_payload (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
2382 /* let's try to hook ourselves here */
2384 } CATCH(BoundsError) {
2386 } CATCH(ReportedBoundsError) {
2387 show_reported_bounds_error(tvb, pinfo, tree);
2392 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious
2393 * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
2396 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2398 volatile int offset = 0;
2399 proto_tree *volatile ntlmssp_tree = NULL;
2400 proto_item *tf = NULL;
2401 guint32 verifier_length;
2402 guint32 encrypted_block_length;
2404 verifier_length = tvb_length (tvb);
2405 encrypted_block_length = verifier_length - 4;
2407 if (encrypted_block_length < 12) {
2408 /* Don't know why this would happen, but if it does, don't even bother
2409 attempting decryption/dissection */
2410 return offset + verifier_length;
2413 /* Setup a new tree for the NTLMSSP payload */
2415 tf = proto_tree_add_item (tree,
2417 tvb, offset, -1, FALSE);
2419 ntlmssp_tree = proto_item_add_subtree (tf,
2424 * Catch the ReportedBoundsError exception; the stuff we've been
2425 * handed doesn't necessarily run to the end of the packet, it's
2426 * an item inside a packet, so if it happens to be malformed (or
2427 * we, or a dissector we call, has a bug), so that an exception
2428 * is thrown, we want to report the error, but return and let
2429 * our caller dissect the rest of the packet.
2431 * If it gets a BoundsError, we can stop, as there's nothing more
2432 * in the packet after our blob to see, so we just re-throw the
2436 /* Version number */
2437 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2438 tvb, offset, 4, TRUE);
2441 /* Encrypted body */
2442 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2443 tvb, offset, encrypted_block_length, TRUE);
2445 /* Try to decrypt */
2446 decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
2447 /* let's try to hook ourselves here */
2450 offset += encrypted_block_length;
2451 } CATCH(BoundsError) {
2453 } CATCH(ReportedBoundsError) {
2454 show_reported_bounds_error(tvb, pinfo, tree);
2461 wrap_dissect_ntlmssp_payload_only(tvbuff_t *tvb,tvbuff_t *auth_tvb _U_,
2462 int offset, packet_info *pinfo,dcerpc_auth_info *auth_info _U_)
2466 data_tvb = tvb_new_subset(
2467 tvb, offset, tvb_length_remaining(tvb, offset),
2468 tvb_length_remaining(tvb, offset));
2469 dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL);
2470 return pinfo->gssapi_decrypted_tvb;
2475 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
2476 tvbuff_t *auth_tvb _U_,
2479 dcerpc_auth_info *auth_info _U_)
2481 /* gssapi_decrypted_tvb=NULL */
2482 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2484 conversation_t *conversation;
2485 guint32 encrypted_block_length;
2486 rc4_state_struct *rc4_state;
2487 rc4_state_struct *rc4_state_peer;
2488 ntlmssp_info *conv_ntlmssp_info = NULL;
2489 ntlmssp_packet_info *packet_ntlmssp_info = NULL;
2490 encrypted_block_length = tvb_length_remaining (data_tvb, offset);
2492 fprintf(stderr,"Called dissect_ntlmssp_encrypted_payload\n");
2493 /* Check to see if we already have state for this packet */
2494 packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
2495 if (packet_ntlmssp_info == NULL) {
2496 /* We don't have any packet state, so create one */
2497 packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
2498 p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
2501 if (!packet_ntlmssp_info->payload_decrypted) {
2502 /* Pull the challenge info from the conversation */
2503 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2504 pinfo->ptype, pinfo->srcport,
2505 pinfo->destport, 0);
2506 if (conversation == NULL) {
2507 /* There is no conversation, thus no encryption state */
2511 conv_ntlmssp_info = conversation_get_proto_data(conversation,
2513 if (conv_ntlmssp_info == NULL) {
2514 /* There is no NTLMSSP state tied to the conversation */
2517 /* Get the pair of RC4 state structures. One is used for to decrypt the
2518 payload. The other is used to re-encrypt the payload to represent
2520 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2521 rc4_state = get_encrypted_state(pinfo, 1);
2522 rc4_state_peer = get_encrypted_state(pinfo, 0);
2524 rc4_state = get_encrypted_state(pinfo, 0);
2525 rc4_state_peer = get_encrypted_state(pinfo, 1);
2528 if (rc4_state == NULL || rc4_state_peer == NULL) {
2529 /* There is no encryption state, so we cannot decrypt */
2533 /* Store the decrypted contents in the packet state struct
2534 (of course at this point, they aren't decrypted yet) */
2535 packet_ntlmssp_info->decrypted_payload = tvb_memdup(data_tvb, offset,
2536 encrypted_block_length);
2537 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2538 packet_ntlmssp_info->decrypted_payload);
2540 /* Do the decryption of the payload */
2541 crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
2542 encrypted_block_length);
2544 /* We setup a temporary buffer so we can re-encrypt the payload after
2545 decryption. This is to update the opposite peer's RC4 state */
2546 peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2547 crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
2549 packet_ntlmssp_info->payload_decrypted = TRUE;
2552 /* Show the decrypted buffer in a new window */
2553 decr_tvb = tvb_new_child_real_data(data_tvb, packet_ntlmssp_info->decrypted_payload,
2554 encrypted_block_length,
2555 encrypted_block_length);
2557 offset += encrypted_block_length;
2564 free_payload(gpointer decrypted_payload, gpointer user_data _U_)
2566 g_free(decrypted_payload);
2569 guint g_header_hash(gconstpointer pointer) {
2570 guint32 crc = ~crc32c_calculate(pointer,NTLMSSP_KEY_LEN,CRC32C_PRELOAD);
2571 /* Mat TBD fprintf(stderr,"Val: %u\n",crc);*/
2575 gboolean g_header_equal(gconstpointer pointer1, gconstpointer pointer2) {
2576 if(!memcmp(pointer1,pointer2,16)) {
2585 ntlmssp_init_protocol(void)
2588 * Free the decrypted payloads, and then free the list of decrypted
2591 if (decrypted_payloads != NULL) {
2592 g_slist_foreach(decrypted_payloads, free_payload, NULL);
2593 g_slist_free(decrypted_payloads);
2594 decrypted_payloads = NULL;
2597 if(hash_packet == NULL) {
2598 hash_packet = g_hash_table_new(g_header_hash,g_header_equal);
2606 proto_register_ntlmssp(void)
2609 static hf_register_info hf[] = {
2611 { "NTLMSSP identifier", "ntlmssp.identifier", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2612 { &hf_ntlmssp_message_type,
2613 { "NTLM Message Type", "ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, NULL, HFILL }},
2614 { &hf_ntlmssp_negotiate_flags,
2615 { "Flags", "ntlmssp.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2616 { &hf_ntlmssp_negotiate_flags_01,
2617 { "Negotiate UNICODE", "ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_UNICODE, NULL, HFILL }},
2618 { &hf_ntlmssp_negotiate_flags_02,
2619 { "Negotiate OEM", "ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM, NULL, HFILL }},
2620 { &hf_ntlmssp_negotiate_flags_04,
2621 { "Request Target", "ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_TARGET, NULL, HFILL }},
2622 { &hf_ntlmssp_negotiate_flags_08,
2623 { "Request 0x00000008", "ntlmssp.negotiate00000008", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000008, NULL, HFILL }},
2624 { &hf_ntlmssp_negotiate_flags_10,
2625 { "Negotiate Sign", "ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SIGN, NULL, HFILL }},
2626 { &hf_ntlmssp_negotiate_flags_20,
2627 { "Negotiate Seal", "ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SEAL, NULL, HFILL }},
2628 { &hf_ntlmssp_negotiate_flags_40,
2629 { "Negotiate Datagram", "ntlmssp.negotiatedatagram", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_DATAGRAM, NULL, HFILL }},
2630 { &hf_ntlmssp_negotiate_flags_80,
2631 { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_LM_KEY, NULL, HFILL }},
2632 { &hf_ntlmssp_negotiate_flags_100,
2633 { "Negotiate 0x00000100", "ntlmssp.negotiate00000100", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000100, NULL, HFILL }},
2634 { &hf_ntlmssp_negotiate_flags_200,
2635 { "Negotiate NTLM key", "ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NTLM, NULL, HFILL }},
2636 { &hf_ntlmssp_negotiate_flags_400,
2637 { "Negotiate NT Only", "ntlmssp.negotiatentonly", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NT_ONLY, NULL, HFILL }},
2638 { &hf_ntlmssp_negotiate_flags_800,
2639 { "Negotiate 0x00000800", "ntlmssp.negotiate00000800", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000800, NULL, HFILL }},
2640 { &hf_ntlmssp_negotiate_flags_1000,
2641 { "Negotiate OEM Domain Supplied", "ntlmssp.negotiateoemdomainsupplied", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED, NULL, HFILL }},
2642 { &hf_ntlmssp_negotiate_flags_2000,
2643 { "Negotiate OEM Workstation Supplied", "ntlmssp.negotiateoemworkstationsupplied", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED, NULL, HFILL }},
2644 { &hf_ntlmssp_negotiate_flags_4000,
2645 { "Negotiate 0x00004000", "ntlmssp.negotiate00004000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00004000, NULL, HFILL }},
2646 { &hf_ntlmssp_negotiate_flags_8000,
2647 { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, NULL, HFILL }},
2648 { &hf_ntlmssp_negotiate_flags_10000,
2649 { "Target Type Domain", "ntlmssp.targettypedomain", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_DOMAIN, NULL, HFILL }},
2650 { &hf_ntlmssp_negotiate_flags_20000,
2651 { "Target Type Server", "ntlmssp.targettypeserver", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER, NULL, HFILL }},
2652 { &hf_ntlmssp_negotiate_flags_40000,
2653 { "Target Type Share", "ntlmssp.targettypeshare", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SHARE, NULL, HFILL }},
2655 /* Negotiate Flags */
2656 { &hf_ntlmssp_negotiate_flags_80000,
2657 { "Negotiate Extended Security", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SECURITY, NULL, HFILL }},
2658 { &hf_ntlmssp_negotiate_flags_100000,
2659 { "Negotiate Identify", "ntlmssp.negotiateidentify", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_IDENTIFY, NULL, HFILL }},
2660 { &hf_ntlmssp_negotiate_flags_200000,
2661 { "Negotiate 0x00200000", "ntlmssp.negotiatent00200000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00200000, NULL, HFILL }},
2662 { &hf_ntlmssp_negotiate_flags_400000,
2663 { "Request Non-NT Session", "ntlmssp.requestnonntsession", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_NON_NT_SESSION, NULL, HFILL }},
2664 { &hf_ntlmssp_negotiate_flags_800000,
2665 { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_TARGET_INFO, NULL, HFILL }},
2666 { &hf_ntlmssp_negotiate_flags_1000000,
2667 { "Negotiate 0x01000000", "ntlmssp.negotiatent01000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_01000000, NULL, HFILL }},
2668 { &hf_ntlmssp_negotiate_flags_2000000,
2669 { "Negotiate Version", "ntlmssp.negotiateversion", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_VERSION, NULL, HFILL }},
2670 { &hf_ntlmssp_negotiate_flags_4000000,
2671 { "Negotiate 0x04000000", "ntlmssp.negotiatent04000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_04000000, NULL, HFILL }},
2672 { &hf_ntlmssp_negotiate_flags_8000000,
2673 { "Negotiate 0x08000000", "ntlmssp.negotiatent08000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_08000000, NULL, HFILL }},
2674 { &hf_ntlmssp_negotiate_flags_10000000,
2675 { "Negotiate 0x10000000", "ntlmssp.negotiatent10000000", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_10000000, NULL, HFILL }},
2676 { &hf_ntlmssp_negotiate_flags_20000000,
2677 { "Negotiate 128", "ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_128, "128-bit encryption is supported", HFILL }},
2678 { &hf_ntlmssp_negotiate_flags_40000000,
2679 { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_KEY_EXCH, NULL, HFILL }},
2680 { &hf_ntlmssp_negotiate_flags_80000000,
2681 { "Negotiate 56", "ntlmssp.negotiate56", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_56, "56-bit encryption is supported", HFILL }},
2682 { &hf_ntlmssp_negotiate_workstation_strlen,
2683 { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2684 { &hf_ntlmssp_negotiate_workstation_maxlen,
2685 { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2686 { &hf_ntlmssp_negotiate_workstation_buffer,
2687 { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2688 { &hf_ntlmssp_negotiate_workstation,
2689 { "Calling workstation name", "ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2690 { &hf_ntlmssp_negotiate_domain_strlen,
2691 { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2692 { &hf_ntlmssp_negotiate_domain_maxlen,
2693 { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2694 { &hf_ntlmssp_negotiate_domain_buffer,
2695 { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2696 { &hf_ntlmssp_negotiate_domain,
2697 { "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2698 { &hf_ntlmssp_ntlm_client_challenge,
2699 { "NTLM Client Challenge", "ntlmssp.ntlmclientchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2700 { &hf_ntlmssp_ntlm_server_challenge,
2701 { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2702 { &hf_ntlmssp_reserved,
2703 { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2705 { &hf_ntlmssp_challenge_target_name,
2706 { "Target Name", "ntlmssp.challenge.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2707 { &hf_ntlmssp_auth_domain,
2708 { "Domain name", "ntlmssp.auth.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2709 { &hf_ntlmssp_auth_username,
2710 { "User name", "ntlmssp.auth.username", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2711 { &hf_ntlmssp_auth_hostname,
2712 { "Host name", "ntlmssp.auth.hostname", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2713 { &hf_ntlmssp_auth_lmresponse,
2714 { "Lan Manager Response", "ntlmssp.auth.lmresponse", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2715 { &hf_ntlmssp_auth_ntresponse,
2716 { "NTLM Response", "ntlmssp.auth.ntresponse", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2717 { &hf_ntlmssp_auth_sesskey,
2718 { "Session Key", "ntlmssp.auth.sesskey", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2719 { &hf_ntlmssp_string_len,
2720 { "Length", "ntlmssp.string.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2721 { &hf_ntlmssp_string_maxlen,
2722 { "Maxlen", "ntlmssp.string.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2723 { &hf_ntlmssp_string_offset,
2724 { "Offset", "ntlmssp.string.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2725 { &hf_ntlmssp_blob_len,
2726 { "Length", "ntlmssp.blob.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2727 { &hf_ntlmssp_blob_maxlen,
2728 { "Maxlen", "ntlmssp.blob.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2729 { &hf_ntlmssp_blob_offset,
2730 { "Offset", "ntlmssp.blob.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2731 { &hf_ntlmssp_version,
2732 { "Version", "ntlmssp.version", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2733 { &hf_ntlmssp_version_major,
2734 { "Major Version", "ntlmssp.version.major", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2735 { &hf_ntlmssp_version_minor,
2736 { "Minor Version", "ntlmssp.version.minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2737 { &hf_ntlmssp_version_build_number,
2738 { "Major Version", "ntlmssp.version.build_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2739 { &hf_ntlmssp_version_ntlm_current_revision,
2740 { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2743 { &hf_ntlmssp_challenge_target_info,
2744 { "Target Info", "ntlmssp.challenge.target_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2745 { &hf_ntlmssp_challenge_target_info_len,
2746 { "Length", "ntlmssp.challenge.target_info.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2747 { &hf_ntlmssp_challenge_target_info_maxlen,
2748 { "Maxlen", "ntlmssp.challenge.target_info.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2749 { &hf_ntlmssp_challenge_target_info_offset,
2750 { "Offset", "ntlmssp.challenge.target_info.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2752 { &hf_ntlmssp_challenge_target_info_item_type,
2753 { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
2754 { &hf_ntlmssp_challenge_target_info_item_len,
2755 { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2757 { &hf_ntlmssp_challenge_target_info_end,
2758 { "List End", "ntlmssp.challenge.target_info.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2759 { &hf_ntlmssp_challenge_target_info_nb_computer_name,
2760 { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
2761 { &hf_ntlmssp_challenge_target_info_nb_domain_name,
2762 { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
2763 { &hf_ntlmssp_challenge_target_info_dns_computer_name,
2764 { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2765 { &hf_ntlmssp_challenge_target_info_dns_domain_name,
2766 { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2767 { &hf_ntlmssp_challenge_target_info_dns_tree_name,
2768 { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2769 { &hf_ntlmssp_challenge_target_info_flags,
2770 { "Flags", "ntlmssp.challenge.target_info.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2771 { &hf_ntlmssp_challenge_target_info_timestamp,
2772 { "Timestamp", "ntlmssp.challenge.target_info.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2773 { &hf_ntlmssp_challenge_target_info_restrictions,
2774 { "Restrictions", "ntlmssp.challenge.target_info.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2775 { &hf_ntlmssp_challenge_target_info_target_name,
2776 { "Target Name", "ntlmssp.challenge.target_info.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2777 { &hf_ntlmssp_challenge_target_info_channel_bindings,
2778 { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2780 { &hf_ntlmssp_ntlmv2_response_item_type,
2781 { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
2782 { &hf_ntlmssp_ntlmv2_response_item_len,
2783 { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2785 { &hf_ntlmssp_ntlmv2_response_end,
2786 { "List End", "ntlmssp.ntlmv2_response.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2787 { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
2788 { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
2789 { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
2790 { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
2791 { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
2792 { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2793 { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
2794 { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2795 { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
2796 { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2797 { &hf_ntlmssp_ntlmv2_response_flags,
2798 { "Flags", "ntlmssp.ntlmv2_response.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2799 { &hf_ntlmssp_ntlmv2_response_timestamp,
2800 { "Timestamp", "ntlmssp.ntlmv2_response.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2801 { &hf_ntlmssp_ntlmv2_response_restrictions,
2802 { "Restrictions", "ntlmssp.ntlmv2_response.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2803 { &hf_ntlmssp_ntlmv2_response_target_name,
2804 { "Target Name", "ntlmssp.ntlmv2_response.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2805 { &hf_ntlmssp_ntlmv2_response_channel_bindings,
2806 { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2808 { &hf_ntlmssp_message_integrity_code,
2809 { "MIC", "ntlmssp.authenticate.mic", FT_BYTES, BASE_NONE, NULL, 0x0, "Message Integrity Code", HFILL}},
2811 { "NTLMSSP Verifier", "ntlmssp.verf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2812 { &hf_ntlmssp_verf_vers,
2813 { "Version Number", "ntlmssp.verf.vers", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2814 { &hf_ntlmssp_verf_body,
2815 { "Verifier Body", "ntlmssp.verf.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2816 { &hf_ntlmssp_decrypted_payload,
2817 { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2818 { &hf_ntlmssp_verf_randompad,
2819 { "Random Pad", "ntlmssp.verf.randompad", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2820 { &hf_ntlmssp_verf_crc32,
2821 { "Verifier CRC32", "ntlmssp.verf.crc32", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2822 { &hf_ntlmssp_verf_hmacmd5,
2823 { "HMAC MD5", "ntlmssp.verf.hmacmd5", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2824 { &hf_ntlmssp_verf_sequence,
2825 { "Sequence", "ntlmssp.verf.sequence", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2827 { &hf_ntlmssp_ntlmv2_response,
2828 { "NTLMv2 Response", "ntlmssp.ntlmv2_response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2829 { &hf_ntlmssp_ntlmv2_response_hmac,
2830 { "HMAC", "ntlmssp.ntlmv2_response.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2831 { &hf_ntlmssp_ntlmv2_response_header,
2832 { "Header", "ntlmssp.ntlmv2_response.header", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2833 { &hf_ntlmssp_ntlmv2_response_reserved,
2834 { "Reserved", "ntlmssp.ntlmv2_response.reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2835 { &hf_ntlmssp_ntlmv2_response_time,
2836 { "Time", "ntlmssp.ntlmv2_response.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
2837 { &hf_ntlmssp_ntlmv2_response_chal,
2838 { "Client challenge", "ntlmssp.ntlmv2_response.chal", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2839 { &hf_ntlmssp_ntlmv2_response_unknown,
2840 { "Unknown", "ntlmssp.ntlmv2_response.unknown", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}
2844 static gint *ett[] = {
2846 &ett_ntlmssp_negotiate_flags,
2847 &ett_ntlmssp_string,
2849 &ett_ntlmssp_version,
2850 &ett_ntlmssp_challenge_target_info,
2851 &ett_ntlmssp_challenge_target_info_item,
2852 &ett_ntlmssp_ntlmv2_response,
2853 &ett_ntlmssp_ntlmv2_response_item,
2855 module_t *ntlmssp_module;
2857 proto_ntlmssp = proto_register_protocol (
2858 "NTLM Secure Service Provider", /* name */
2859 "NTLMSSP", /* short name */
2860 "ntlmssp" /* abbrev */
2862 proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
2863 proto_register_subtree_array (ett, array_length (ett));
2864 register_init_routine(&ntlmssp_init_protocol);
2866 ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
2868 prefs_register_string_preference(ntlmssp_module, "nt_password",
2870 "NT Password (used to decrypt payloads)",
2873 register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
2874 new_register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
2875 new_register_dissector("ntlmssp_data_only", dissect_ntlmssp_payload_only, proto_ntlmssp);
2876 new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
2879 static int wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
2880 proto_tree *tree, guint8 *drep _U_)
2884 auth_tvb = tvb_new_subset(
2885 tvb, offset, tvb_length_remaining(tvb, offset),
2886 tvb_length_remaining(tvb, offset));
2888 dissect_ntlmssp(auth_tvb, pinfo, tree);
2890 return tvb_length_remaining(tvb, offset);
2893 static int wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
2894 proto_tree *tree, guint8 *drep _U_)
2898 auth_tvb = tvb_new_subset(
2899 tvb, offset, tvb_length_remaining(tvb, offset),
2900 tvb_length_remaining(tvb, offset));
2901 return dissect_ntlmssp_verf(auth_tvb, pinfo, tree);
2904 static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
2905 wrap_dissect_ntlmssp, /* Bind */
2906 wrap_dissect_ntlmssp, /* Bind ACK */
2907 wrap_dissect_ntlmssp, /* AUTH3 */
2908 wrap_dissect_ntlmssp_verf, /* Request verifier */
2909 wrap_dissect_ntlmssp_verf, /* Response verifier */
2910 NULL, /* Request data */
2911 NULL /* Response data */
2914 static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
2915 wrap_dissect_ntlmssp, /* Bind */
2916 wrap_dissect_ntlmssp, /* Bind ACK */
2917 wrap_dissect_ntlmssp, /* AUTH3 */
2918 wrap_dissect_ntlmssp_verf, /* Request verifier */
2919 wrap_dissect_ntlmssp_verf, /* Response verifier */
2920 wrap_dissect_ntlmssp_payload_only, /* Request data */
2921 wrap_dissect_ntlmssp_payload_only /* Response data */
2925 proto_reg_handoff_ntlmssp(void)
2927 dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
2929 /* Register protocol with the GSS-API module */
2931 ntlmssp_handle = find_dissector("ntlmssp");
2932 ntlmssp_wrap_handle = find_dissector("ntlmssp_verf");
2933 gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
2934 ntlmssp_handle, ntlmssp_wrap_handle,
2935 "NTLMSSP - Microsoft NTLM Security Support Provider");
2937 /* Register authenticated pipe dissector */
2940 * XXX - the verifiers here seem to have a version of 1 and a body of all
2943 * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
2944 * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
2945 * any other levels here?
2947 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
2948 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2951 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
2952 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2955 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
2956 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2959 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
2960 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
2962 ntlmssp_tap = register_tap("ntlmssp");
2966 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2971 * indent-tabs-mode: nil
2974 * vi: set shiftwidth=2 tabstop=8 expandtab
2975 * :indentSize=2:tabSize=8:noTabs=true: