2 * Add-on for better NTLM v1/v2 handling
3 * Copyright 2009, 2012 Matthieu Patou <mat@matws.net>
4 * Routines for NTLM Secure Service Provider
5 * Devin Heitmueller <dheitmueller@netilla.com>
6 * Copyright 2003, Tim Potter <tpot@samba.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
14 /* Just set me to activate debug #define DEBUG_NTLMSSP */
21 #include <epan/packet.h>
22 #include <epan/exceptions.h>
23 #include <epan/asn1.h>
24 #include <epan/prefs.h>
26 #include <epan/expert.h>
27 #include <epan/show_exception.h>
28 #include <epan/proto_data.h>
30 #include <wsutil/wsgcrypt.h>
31 #include <wsutil/crc32.h>
32 #include <wsutil/str_util.h>
34 #include "packet-windows-common.h"
35 #include "packet-smb-common.h"
36 #include "packet-kerberos.h"
37 #include "packet-dcerpc.h"
38 #include "packet-gssapi.h"
40 #include "read_keytab_file.h"
42 #include "packet-ntlmssp.h"
44 void proto_register_ntlmssp(void);
45 void proto_reg_handoff_ntlmssp(void);
47 static int ntlmssp_tap = -1;
49 #define CLIENT_SIGN_TEXT "session key to client-to-server signing key magic constant"
50 #define CLIENT_SEAL_TEXT "session key to client-to-server sealing key magic constant"
51 #define SERVER_SIGN_TEXT "session key to server-to-client signing key magic constant"
52 #define SERVER_SEAL_TEXT "session key to server-to-client sealing key magic constant"
54 static const value_string ntlmssp_message_types[] = {
55 { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
56 { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
57 { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
58 { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
62 typedef struct _md4_pass {
63 guint8 md4[NTLMSSP_KEY_LEN];
66 static const 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";
67 static GHashTable* hash_packet = NULL;
70 * NTLMSSP negotiation flags
75 * http://davenport.sourceforge.net/ntlm.html
77 * although that document says that:
79 * 0x00010000 is "Target Type Domain";
80 * 0x00020000 is "Target Type Server"
81 * 0x00040000 is "Target Type Share";
83 * and that 0x00100000, 0x00200000, and 0x00400000 are
84 * "Request Init Response", "Request Accept Response", and
85 * "Request Non-NT Session Key", rather than those values shifted
86 * right one having those interpretations.
88 * UPDATE: Further information obtained from [MS-NLMP] 2.2.2.5:
89 * NT LAN Manager (NTLM) Authentication Protocol Specification
90 * http://msdn2.microsoft.com/en-us/library/cc236621.aspx
93 #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
94 #define NTLMSSP_NEGOTIATE_OEM 0x00000002
95 #define NTLMSSP_REQUEST_TARGET 0x00000004
96 #define NTLMSSP_NEGOTIATE_00000008 0x00000008
97 #define NTLMSSP_NEGOTIATE_SIGN 0x00000010
98 #define NTLMSSP_NEGOTIATE_SEAL 0x00000020
99 #define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040
100 #define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
101 #define NTLMSSP_NEGOTIATE_00000100 0x00000100
102 #define NTLMSSP_NEGOTIATE_NTLM 0x00000200
103 #define NTLMSSP_NEGOTIATE_NT_ONLY 0x00000400
104 #define NTLMSSP_NEGOTIATE_ANONYMOUS 0x00000800
105 #define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000
106 #define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000
107 #define NTLMSSP_NEGOTIATE_00004000 0x00004000
108 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
109 #define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000
110 #define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
111 #define NTLMSSP_TARGET_TYPE_SHARE 0x00040000
112 #define NTLMSSP_NEGOTIATE_EXTENDED_SECURITY 0x00080000
113 #define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000
114 #define NTLMSSP_NEGOTIATE_00200000 0x00200000
115 #define NTLMSSP_REQUEST_NON_NT_SESSION 0x00400000
116 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
117 #define NTLMSSP_NEGOTIATE_01000000 0x01000000
118 #define NTLMSSP_NEGOTIATE_VERSION 0x02000000
119 #define NTLMSSP_NEGOTIATE_04000000 0x04000000
120 #define NTLMSSP_NEGOTIATE_08000000 0x08000000
121 #define NTLMSSP_NEGOTIATE_10000000 0x10000000
122 #define NTLMSSP_NEGOTIATE_128 0x20000000
123 #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
124 #define NTLMSSP_NEGOTIATE_56 0x80000000
126 static int proto_ntlmssp = -1;
127 static int hf_ntlmssp_auth = -1;
128 static int hf_ntlmssp_message_type = -1;
129 static int hf_ntlmssp_negotiate_flags = -1;
130 static int hf_ntlmssp_negotiate_flags_01 = -1;
131 static int hf_ntlmssp_negotiate_flags_02 = -1;
132 static int hf_ntlmssp_negotiate_flags_04 = -1;
133 static int hf_ntlmssp_negotiate_flags_08 = -1;
134 static int hf_ntlmssp_negotiate_flags_10 = -1;
135 static int hf_ntlmssp_negotiate_flags_20 = -1;
136 static int hf_ntlmssp_negotiate_flags_40 = -1;
137 static int hf_ntlmssp_negotiate_flags_80 = -1;
138 static int hf_ntlmssp_negotiate_flags_100 = -1;
139 static int hf_ntlmssp_negotiate_flags_200 = -1;
140 static int hf_ntlmssp_negotiate_flags_400 = -1;
141 static int hf_ntlmssp_negotiate_flags_800 = -1;
142 static int hf_ntlmssp_negotiate_flags_1000 = -1;
143 static int hf_ntlmssp_negotiate_flags_2000 = -1;
144 static int hf_ntlmssp_negotiate_flags_4000 = -1;
145 static int hf_ntlmssp_negotiate_flags_8000 = -1;
146 static int hf_ntlmssp_negotiate_flags_10000 = -1;
147 static int hf_ntlmssp_negotiate_flags_20000 = -1;
148 static int hf_ntlmssp_negotiate_flags_40000 = -1;
149 static int hf_ntlmssp_negotiate_flags_80000 = -1;
150 static int hf_ntlmssp_negotiate_flags_100000 = -1;
151 static int hf_ntlmssp_negotiate_flags_200000 = -1;
152 static int hf_ntlmssp_negotiate_flags_400000 = -1;
153 static int hf_ntlmssp_negotiate_flags_800000 = -1;
154 static int hf_ntlmssp_negotiate_flags_1000000 = -1;
155 static int hf_ntlmssp_negotiate_flags_2000000 = -1;
156 static int hf_ntlmssp_negotiate_flags_4000000 = -1;
157 static int hf_ntlmssp_negotiate_flags_8000000 = -1;
158 static int hf_ntlmssp_negotiate_flags_10000000 = -1;
159 static int hf_ntlmssp_negotiate_flags_20000000 = -1;
160 static int hf_ntlmssp_negotiate_flags_40000000 = -1;
161 static int hf_ntlmssp_negotiate_flags_80000000 = -1;
162 /* static int hf_ntlmssp_negotiate_workstation_strlen = -1; */
163 /* static int hf_ntlmssp_negotiate_workstation_maxlen = -1; */
164 /* static int hf_ntlmssp_negotiate_workstation_buffer = -1; */
165 static int hf_ntlmssp_negotiate_workstation = -1;
166 /* static int hf_ntlmssp_negotiate_domain_strlen = -1; */
167 /* static int hf_ntlmssp_negotiate_domain_maxlen = -1; */
168 /* static int hf_ntlmssp_negotiate_domain_buffer = -1; */
169 static int hf_ntlmssp_negotiate_domain = -1;
170 static int hf_ntlmssp_ntlm_server_challenge = -1;
171 static int hf_ntlmssp_ntlm_client_challenge = -1;
172 static int hf_ntlmssp_reserved = -1;
173 static int hf_ntlmssp_challenge_target_name = -1;
174 static int hf_ntlmssp_auth_username = -1;
175 static int hf_ntlmssp_auth_domain = -1;
176 static int hf_ntlmssp_auth_hostname = -1;
177 static int hf_ntlmssp_auth_lmresponse = -1;
178 static int hf_ntlmssp_auth_ntresponse = -1;
179 static int hf_ntlmssp_auth_sesskey = -1;
180 static int hf_ntlmssp_string_len = -1;
181 static int hf_ntlmssp_string_maxlen = -1;
182 static int hf_ntlmssp_string_offset = -1;
183 static int hf_ntlmssp_blob_len = -1;
184 static int hf_ntlmssp_blob_maxlen = -1;
185 static int hf_ntlmssp_blob_offset = -1;
186 static int hf_ntlmssp_version = -1;
187 static int hf_ntlmssp_version_major = -1;
188 static int hf_ntlmssp_version_minor = -1;
189 static int hf_ntlmssp_version_build_number = -1;
190 static int hf_ntlmssp_version_ntlm_current_revision = -1;
192 static int hf_ntlmssp_challenge_target_info = -1;
193 static int hf_ntlmssp_challenge_target_info_len = -1;
194 static int hf_ntlmssp_challenge_target_info_maxlen = -1;
195 static int hf_ntlmssp_challenge_target_info_offset = -1;
197 static int hf_ntlmssp_challenge_target_info_item_type = -1;
198 static int hf_ntlmssp_challenge_target_info_item_len = -1;
200 static int hf_ntlmssp_challenge_target_info_end = -1;
201 static int hf_ntlmssp_challenge_target_info_nb_computer_name = -1;
202 static int hf_ntlmssp_challenge_target_info_nb_domain_name = -1;
203 static int hf_ntlmssp_challenge_target_info_dns_computer_name = -1;
204 static int hf_ntlmssp_challenge_target_info_dns_domain_name = -1;
205 static int hf_ntlmssp_challenge_target_info_dns_tree_name = -1;
206 static int hf_ntlmssp_challenge_target_info_flags = -1;
207 static int hf_ntlmssp_challenge_target_info_timestamp = -1;
208 static int hf_ntlmssp_challenge_target_info_restrictions = -1;
209 static int hf_ntlmssp_challenge_target_info_target_name =-1;
210 static int hf_ntlmssp_challenge_target_info_channel_bindings =-1;
212 static int hf_ntlmssp_ntlmv2_response_item_type = -1;
213 static int hf_ntlmssp_ntlmv2_response_item_len = -1;
215 static int hf_ntlmssp_ntlmv2_response_end = -1;
216 static int hf_ntlmssp_ntlmv2_response_nb_computer_name = -1;
217 static int hf_ntlmssp_ntlmv2_response_nb_domain_name = -1;
218 static int hf_ntlmssp_ntlmv2_response_dns_computer_name = -1;
219 static int hf_ntlmssp_ntlmv2_response_dns_domain_name = -1;
220 static int hf_ntlmssp_ntlmv2_response_dns_tree_name = -1;
221 static int hf_ntlmssp_ntlmv2_response_flags = -1;
222 static int hf_ntlmssp_ntlmv2_response_timestamp = -1;
223 static int hf_ntlmssp_ntlmv2_response_restrictions = -1;
224 static int hf_ntlmssp_ntlmv2_response_target_name =-1;
225 static int hf_ntlmssp_ntlmv2_response_channel_bindings =-1;
227 static int hf_ntlmssp_message_integrity_code = -1;
228 static int hf_ntlmssp_verf = -1;
229 static int hf_ntlmssp_verf_vers = -1;
230 static int hf_ntlmssp_verf_body = -1;
231 static int hf_ntlmssp_verf_randompad = -1;
232 static int hf_ntlmssp_verf_hmacmd5 = -1;
233 static int hf_ntlmssp_verf_crc32 = -1;
234 static int hf_ntlmssp_verf_sequence = -1;
235 /* static int hf_ntlmssp_decrypted_payload = -1; */
237 static int hf_ntlmssp_ntlmv2_response = -1;
238 static int hf_ntlmssp_ntlmv2_response_ntproofstr = -1;
239 static int hf_ntlmssp_ntlmv2_response_rversion = -1;
240 static int hf_ntlmssp_ntlmv2_response_hirversion = -1;
241 static int hf_ntlmssp_ntlmv2_response_z = -1;
242 static int hf_ntlmssp_ntlmv2_response_pad = -1;
243 static int hf_ntlmssp_ntlmv2_response_time = -1;
244 static int hf_ntlmssp_ntlmv2_response_chal = -1;
246 static gint ett_ntlmssp = -1;
247 static gint ett_ntlmssp_negotiate_flags = -1;
248 static gint ett_ntlmssp_string = -1;
249 static gint ett_ntlmssp_blob = -1;
250 static gint ett_ntlmssp_version = -1;
251 static gint ett_ntlmssp_challenge_target_info = -1;
252 static gint ett_ntlmssp_challenge_target_info_item = -1;
253 static gint ett_ntlmssp_ntlmv2_response = -1;
254 static gint ett_ntlmssp_ntlmv2_response_item = -1;
256 static expert_field ei_ntlmssp_v2_key_too_long = EI_INIT;
257 static expert_field ei_ntlmssp_blob_len_too_long = EI_INIT;
258 static expert_field ei_ntlmssp_target_info_attr = EI_INIT;
259 static expert_field ei_ntlmssp_message_type = EI_INIT;
261 static dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
263 /* Configuration variables */
264 const char *gbl_nt_password = NULL;
266 #define MAX_BLOB_SIZE 10240
267 typedef struct _ntlmssp_blob {
272 #define NTLMSSP_CONV_INFO_KEY 0
273 /* Used in the conversation function */
274 typedef struct _ntlmssp_info {
277 gcry_cipher_hd_t rc4_handle_client;
278 gcry_cipher_hd_t rc4_handle_server;
279 guint8 sign_key_client[NTLMSSP_KEY_LEN];
280 guint8 sign_key_server[NTLMSSP_KEY_LEN];
281 guint32 server_dest_port;
282 unsigned char server_challenge[8];
283 unsigned char client_challenge[8];
284 int rc4_state_initialized;
285 ntlmssp_blob ntlm_response;
286 ntlmssp_blob lm_response;
289 #define NTLMSSP_PACKET_INFO_KEY 1
290 /* If this struct exists in the payload_decrypt, then we have already
292 typedef struct _ntlmssp_packet_info {
293 guint8 *decrypted_payload;
295 guint8 verifier[NTLMSSP_KEY_LEN];
296 gboolean payload_decrypted;
297 gboolean verifier_decrypted;
298 } ntlmssp_packet_info;
301 static void printnbyte(const guint8* tab, int nb, const char* txt, const char* txt2)
304 fprintf(stderr, "%s ", txt);
307 fprintf(stderr, "%02X ", *(tab+i));
309 fprintf(stderr, "%s", txt2);
312 static void printnchar(const guint8* tab, int nb, char* txt, char* txt2)
315 fprintf(stderr, "%s ", txt);
318 fprintf(stderr, "%c", *(tab+i));
320 fprintf(stderr, "%s", txt2);
324 static void printnbyte(const guint8* tab _U_, int nb _U_, const char* txt _U_, const char* txt2 _U_)
330 * GSlist of decrypted payloads.
332 static GSList *decrypted_payloads;
336 LEBE_Convert(int value)
340 a = value&0x000000FF;
341 b = (value&0x0000FF00) >> 8;
342 c = (value&0x00FF0000) >> 16;
343 d = (value&0xFF000000) >> 24;
344 return (a << 24) | (b << 16) | (c << 8) | d;
349 ntlmssp_sessions_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_)
351 ntlmssp_info * conv_ntlmssp_info = (ntlmssp_info *) user_data;
352 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
353 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
354 /* unregister this callback */
359 Perform a DES encryption with a 16-byte key and 8-byte data item.
360 It's in fact 3 susbsequent call to crypt_des_ecb with a 7-byte key.
361 Missing bytes for the key are replaced by 0;
362 Returns output in response, which is expected to be 24 bytes.
365 crypt_des_ecb_long(guint8 *response,
369 guint8 pw21[21] = { 0 }; /* 21 bytes place for the needed key */
371 memcpy(pw21, key, 16);
373 memset(response, 0, 24);
374 crypt_des_ecb(response, data, pw21);
375 crypt_des_ecb(response + 8, data, pw21 + 7);
376 crypt_des_ecb(response + 16, data, pw21 + 14);
382 Generate a challenge response, given an eight byte challenge and
383 either the NT or the Lan Manager password hash (16 bytes).
384 Returns output in response, which is expected to be 24 bytes.
387 ntlmssp_generate_challenge_response(guint8 *response,
388 const guint8 *passhash,
389 const guint8 *challenge)
391 guint8 pw21[21]; /* Password hash padded to 21 bytes */
393 memset(pw21, 0x0, sizeof(pw21));
394 memcpy(pw21, passhash, 16);
396 memset(response, 0, 24);
398 crypt_des_ecb(response, challenge, pw21);
399 crypt_des_ecb(response + 8, challenge, pw21 + 7);
400 crypt_des_ecb(response + 16, challenge, pw21 + 14);
406 /* Ultra simple ainsi to unicode converter, will only work for ascii password ...*/
408 str_to_unicode(const char *nt_password, char *nt_password_unicode)
413 password_len = strlen(nt_password);
414 if (nt_password_unicode != NULL) {
415 for (i=0; i<(password_len); i++) {
416 nt_password_unicode[i*2]=nt_password[i];
417 nt_password_unicode[i*2+1]=0;
419 nt_password_unicode[2*password_len]='\0';
423 /* This function generate the Key Exchange Key
424 * Depending on the flags this key will either be used to crypt the exported session key
425 * or will be used directly as exported session key.
426 * Exported session key is the key that will be used for sealing and signing communication*/
429 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)
431 guint8 basekey[NTLMSSP_KEY_LEN];
432 guint8 zeros[24] = { 0 };
434 memset(keyexchangekey, 0, NTLMSSP_KEY_LEN);
435 memset(basekey, 0, NTLMSSP_KEY_LEN);
436 /* sessionbasekey is either derived from lm_password_hash or from nt_password_hash depending on the key type negotiated */
437 memcpy(basekey, sessionbasekey, 8);
438 memset(basekey, 0xBD, 8);
439 if (flags&NTLMSSP_NEGOTIATE_LM_KEY) {
441 crypt_des_ecb(keyexchangekey, lm_challenge_response, basekey);
442 crypt_des_ecb(keyexchangekey+8, lm_challenge_response, basekey+7);
445 if (flags&NTLMSSP_REQUEST_NON_NT_SESSION) {
446 /*People from samba tends to use the same function in this case than in the previous one but with 0 data
447 * it's not clear that it produce the good result
448 * memcpy(keyexchangekey, lm_hash, 8);
449 * 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);
452 crypt_des_ecb(keyexchangekey+8, zeros, basekey+7);
455 /* it is stated page 65 of NTLM SSP spec that sessionbasekey should be encrypted with hmac_md5 using the concact of both challenge
456 * when it's NTLM v1 + extended security but it turns out to be wrong !
458 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 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_unicode, 0, sizeof(nt_password_unicode));
487 memset(nt_password_hash, 0, NTLMSSP_KEY_LEN);
488 if ((nt_password[0] != '\0') && (strlen(nt_password) < 129)) {
491 password_len = (int)strlen(nt_password);
492 str_to_unicode(nt_password, nt_password_unicode);
493 gcry_md_hash_buffer(GCRY_MD_MD4, nt_password_hash, nt_password_unicode, password_len*2);
496 /* Unable to calculate the session key without a password or if password is more than 128 char ......*/
500 *p_pass_list = (md4_pass *)wmem_alloc(wmem_packet_scope(), nb_pass*sizeof(md4_pass));
501 pass_list = *p_pass_list;
503 if (memcmp(nt_password_hash, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
504 memcpy(pass_list[i].md4, nt_password_hash, NTLMSSP_KEY_LEN);
507 for (ek=enc_key_list; ek; ek=ek->next) {
508 if (ek->keylength == NTLMSSP_KEY_LEN) {
509 memcpy(pass_list[i].md4, ek->keyvalue, NTLMSSP_KEY_LEN);
517 /* Create an NTLMSSP version 2 key
520 create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge , const guint8 *clientchallenge ,
521 guint8 *sessionkey , const guint8 *encryptedsessionkey , int flags ,
522 const ntlmssp_blob *ntlm_response, const ntlmssp_blob *lm_response _U_, ntlmssp_header_t *ntlmssph)
524 /* static const would be nicer, but -Werror=vla does not like it */
525 #define DOMAIN_NAME_BUF_SIZE 512
526 #define USER_BUF_SIZE 256
527 #define BUF_SIZE (DOMAIN_NAME_BUF_SIZE + USER_BUF_SIZE)
528 char domain_name_unicode[DOMAIN_NAME_BUF_SIZE];
529 char user_uppercase[USER_BUF_SIZE];
531 /*guint8 md4[NTLMSSP_KEY_LEN];*/
532 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
533 unsigned char nt_proof[NTLMSSP_KEY_LEN];
534 unsigned char ntowf[NTLMSSP_KEY_LEN];
535 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
536 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
537 guint8 lm_challenge_response[24];
540 gcry_cipher_hd_t rc4_handle;
543 md4_pass *pass_list = NULL;
545 gboolean found = FALSE;
547 /* We are going to try password encrypted in keytab as well, it's an idea of Stefan Metzmacher <metze@samba.org>
548 * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
550 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
551 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
552 nb_pass = get_md4pass_list(&pass_list, nt_password);
555 memset(user_uppercase, 0, USER_BUF_SIZE);
556 user_len = strlen(ntlmssph->acct_name);
557 if (user_len < USER_BUF_SIZE / 2) {
558 memset(buf, 0, BUF_SIZE);
559 str_to_unicode(ntlmssph->acct_name, buf);
560 for (j = 0; j < (2*user_len); j++) {
561 if (buf[j] != '\0') {
562 user_uppercase[j] = g_ascii_toupper(buf[j]);
567 /* Unable to calculate the session not enough space in buffer, note this is unlikely to happen but ......*/
570 domain_len = strlen(ntlmssph->domain_name);
571 if (domain_len < DOMAIN_NAME_BUF_SIZE / 2) {
572 str_to_unicode(ntlmssph->domain_name, domain_name_unicode);
575 /* Unable to calculate the session not enough space in buffer, note this is unlikely to happen but ......*/
578 while (i < nb_pass) {
580 fprintf(stderr, "Turn %d, ", i);
582 memcpy(nt_password_hash, pass_list[i].md4, NTLMSSP_KEY_LEN);
583 printnbyte(nt_password_hash, NTLMSSP_KEY_LEN, "Current NT password hash: ", "\n");
585 /* ntowf computation */
586 memset(buf, 0, BUF_SIZE);
587 memcpy(buf, user_uppercase, user_len*2);
588 memcpy(buf+user_len*2, domain_name_unicode, domain_len*2);
589 if (ws_hmac_buffer(GCRY_MD_MD5, ntowf, buf, domain_len*2+user_len*2, nt_password_hash, NTLMSSP_KEY_LEN)) {
592 printnbyte(ntowf, NTLMSSP_KEY_LEN, "NTOWF: ", "\n");
595 memset(buf, 0, BUF_SIZE);
596 memcpy(buf, serverchallenge, 8);
597 memcpy(buf+8, clientchallenge, 8);
598 if (ws_hmac_buffer(GCRY_MD_MD5, lm_challenge_response, buf, NTLMSSP_KEY_LEN, ntowf, NTLMSSP_KEY_LEN)) {
601 memcpy(lm_challenge_response+NTLMSSP_KEY_LEN, clientchallenge, 8);
602 printnbyte(lm_challenge_response, 24, "LM Response: ", "\n");
604 /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
605 memset(buf, 0, BUF_SIZE);
606 memcpy(buf, serverchallenge, 8);
607 memcpy(buf+8, ntlm_response->contents+NTLMSSP_KEY_LEN, MIN(BUF_SIZE - 8, ntlm_response->length-NTLMSSP_KEY_LEN));
608 if (ws_hmac_buffer(GCRY_MD_MD5, nt_proof, buf, ntlm_response->length-8, ntowf, NTLMSSP_KEY_LEN)) {
611 printnbyte(nt_proof, NTLMSSP_KEY_LEN, "NT proof: ", "\n");
612 if (!memcmp(nt_proof, ntlm_response->contents, NTLMSSP_KEY_LEN)) {
621 if (ws_hmac_buffer(GCRY_MD_MD5, sessionbasekey, nt_proof, NTLMSSP_KEY_LEN, ntowf, NTLMSSP_KEY_LEN)) {
625 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
626 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
627 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
629 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
630 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
631 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
632 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
634 gcry_cipher_close(rc4_handle);
639 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
642 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
645 /* Create an NTLMSSP version 1 key
646 * That is more complicated logic and methods and user challenge as well.
647 * password points to the ANSI password to encrypt, challenge points to
648 * the 8 octet challenge string
651 create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, const guint8 *clientchallenge,
652 guint8 *sessionkey, const guint8 *encryptedsessionkey, int flags,
653 const guint8 *ref_nt_challenge_response, const guint8 *ref_lm_challenge_response,
654 ntlmssp_header_t *ntlmssph)
656 unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
657 unsigned char lm_password_hash[NTLMSSP_KEY_LEN];
658 unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
659 unsigned char challenges_hash_first8[8];
660 unsigned char challenges[NTLMSSP_KEY_LEN];
661 guint8 md4[NTLMSSP_KEY_LEN];
663 guint8 sessionbasekey[NTLMSSP_KEY_LEN];
664 guint8 keyexchangekey[NTLMSSP_KEY_LEN];
665 guint8 lm_challenge_response[24];
666 guint8 nt_challenge_response[24];
667 gcry_cipher_hd_t rc4_handle;
668 gcry_md_hd_t md5_handle;
669 char nt_password_unicode[256];
672 gboolean found = FALSE;
673 md4_pass *pass_list = NULL;
675 static const unsigned char lmhash_key[] =
676 {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
678 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
679 memset(lm_password_upper, 0, sizeof(lm_password_upper));
680 /* lm auth/lm session == (!NTLM_NEGOTIATE_NT_ONLY && NTLMSSP_NEGOTIATE_LM_KEY) || ! (EXTENDED_SECURITY) || ! NTLMSSP_NEGOTIATE_NTLM*/
681 /* Create a Lan Manager hash of the input password */
682 if (nt_password[0] != '\0') {
683 password_len = strlen(nt_password);
684 /*Do not forget to free nt_password_nt*/
685 str_to_unicode(nt_password, nt_password_unicode);
686 gcry_md_hash_buffer(GCRY_MD_MD4, nt_password_hash, nt_password_unicode, password_len*2);
687 /* Truncate password if too long */
688 if (password_len > NTLMSSP_KEY_LEN)
689 password_len = NTLMSSP_KEY_LEN;
690 for (i = 0; i < password_len; i++) {
691 lm_password_upper[i] = g_ascii_toupper(nt_password[i]);
696 /* Unable to calculate the session key without a password ... and we will not use one for a keytab*/
697 if (!(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)) {
701 if ((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NTLMSSP_NEGOTIATE_NT_ONLY)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
702 crypt_des_ecb(lm_password_hash, lmhash_key, lm_password_upper);
703 crypt_des_ecb(lm_password_hash+8, lmhash_key, lm_password_upper+7);
704 ntlmssp_generate_challenge_response(lm_challenge_response,
705 lm_password_hash, serverchallenge);
706 memcpy(sessionbasekey, lm_password_hash, NTLMSSP_KEY_LEN);
710 memset(lm_challenge_response, 0, 24);
711 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
712 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
713 nb_pass = get_md4pass_list(&pass_list, nt_password);
716 while (i < nb_pass) {
717 /*fprintf(stderr, "Turn %d, ", i);*/
718 memcpy(nt_password_hash, pass_list[i].md4, NTLMSSP_KEY_LEN);
719 /*printnbyte(nt_password_hash, NTLMSSP_KEY_LEN, "Current NT password hash: ", "\n");*/
722 memcpy(lm_challenge_response, clientchallenge, 8);
724 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
727 gcry_md_write(md5_handle, serverchallenge, 8);
728 gcry_md_write(md5_handle, clientchallenge, 8);
729 memcpy(challenges_hash_first8, gcry_md_read(md5_handle, 0), 8);
730 gcry_md_close(md5_handle);
731 crypt_des_ecb_long(nt_challenge_response, nt_password_hash, challenges_hash_first8);
732 if (ref_nt_challenge_response && !memcmp(ref_nt_challenge_response, nt_challenge_response, 24)) {
739 crypt_des_ecb_long(nt_challenge_response, nt_password_hash, serverchallenge);
740 if (flags & NTLMSSP_NEGOTIATE_NT_ONLY) {
741 memcpy(lm_challenge_response, nt_challenge_response, 24);
744 crypt_des_ecb_long(lm_challenge_response, lm_password_hash, serverchallenge);
746 if (ref_nt_challenge_response &&
747 !memcmp(ref_nt_challenge_response, nt_challenge_response, 24) &&
748 ref_lm_challenge_response &&
749 !memcmp(ref_lm_challenge_response, lm_challenge_response, 24))
754 /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
755 * that sessionbasekey should be based md4(nt_password_hash) only in the case of some NT auth
756 * Otherwise it should be lm_password_hash ...*/
757 gcry_md_hash_buffer(GCRY_MD_MD4, md4, nt_password_hash, NTLMSSP_KEY_LEN);
758 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
759 memcpy(challenges, serverchallenge, 8);
761 memcpy(challenges+8, clientchallenge, 8);
763 if (ws_hmac_buffer(GCRY_MD_MD5, sessionbasekey, challenges, NTLMSSP_KEY_LEN, md4, NTLMSSP_KEY_LEN)) {
768 memcpy(sessionbasekey, md4, NTLMSSP_KEY_LEN);
776 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
777 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
778 /*printnbyte(nt_challenge_response, 24, "NT challenge response", "\n");
779 printnbyte(lm_challenge_response, 24, "LM challenge response", "\n");*/
780 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
781 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
783 if(encryptedsessionkey){
784 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
786 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
787 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
788 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
790 gcry_cipher_close(rc4_handle);
795 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
797 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
801 get_siging_key(guint8 *sign_key_server, guint8* sign_key_client, const guint8 key[NTLMSSP_KEY_LEN], int keylen)
803 gcry_md_hd_t md5_handle;
805 memset(sign_key_client, 0, NTLMSSP_KEY_LEN);
806 memset(sign_key_server, 0, NTLMSSP_KEY_LEN);
807 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
810 gcry_md_write(md5_handle, key, keylen);
811 gcry_md_write(md5_handle, CLIENT_SIGN_TEXT, strlen(CLIENT_SIGN_TEXT)+1);
812 memcpy(sign_key_client, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
813 gcry_md_reset(md5_handle);
814 gcry_md_write(md5_handle, key, keylen);
815 gcry_md_write(md5_handle, SERVER_SIGN_TEXT, strlen(SERVER_SIGN_TEXT)+1);
816 memcpy(sign_key_server, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
817 gcry_md_close(md5_handle);
820 /* We return either a 128 or 64 bit key
823 get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] , const int flags , int *keylen ,
824 guint8 *clientsealkey , guint8 *serversealkey)
826 gcry_md_hd_t md5_handle;
828 memset(clientsealkey, 0, NTLMSSP_KEY_LEN);
829 memset(serversealkey, 0, NTLMSSP_KEY_LEN);
830 memcpy(clientsealkey, exportedsessionkey, NTLMSSP_KEY_LEN);
831 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)
833 if (flags & NTLMSSP_NEGOTIATE_128)
835 /* The exportedsessionkey has already the good length just update the length*/
840 if (flags & NTLMSSP_NEGOTIATE_56)
842 memset(clientsealkey+7, 0, 9);
847 memset(clientsealkey+5, 0, 11);
851 memcpy(serversealkey, clientsealkey, NTLMSSP_KEY_LEN);
852 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
855 gcry_md_write(md5_handle, clientsealkey, *keylen);
856 gcry_md_write(md5_handle, CLIENT_SEAL_TEXT, strlen(CLIENT_SEAL_TEXT)+1);
857 memcpy(clientsealkey, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
858 gcry_md_reset(md5_handle);
859 gcry_md_write(md5_handle, serversealkey, *keylen);
860 gcry_md_write(md5_handle, SERVER_SEAL_TEXT, strlen(SERVER_SEAL_TEXT)+1);
861 memcpy(serversealkey, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
862 gcry_md_close(md5_handle);
866 if (flags & NTLMSSP_NEGOTIATE_128)
868 /* The exportedsessionkey has already the good length just update the length*/
874 if (flags & NTLMSSP_NEGOTIATE_56)
876 memset(clientsealkey+7, 0, 9);
880 memset(clientsealkey+5, 0, 11);
881 clientsealkey[5]=0xe5;
882 clientsealkey[6]=0x38;
883 clientsealkey[7]=0xb0;
886 memcpy(serversealkey, clientsealkey,*keylen);
889 /* Create an NTLMSSP version 1 key.
890 * password points to the ANSI password to encrypt, challenge points to
891 * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
892 * otherwise it will do a 40 bit key. The result is stored in
893 * sspkey (expected to be NTLMSSP_KEY_LEN octets)
895 /* dissect a string - header area contains:
898 four byte offset of string in data area
899 The function returns the offset at the end of the string header,
900 but the 'end' parameter returns the offset of the end of the string itself
901 The 'start' parameter returns the offset of the beginning of the string
902 If there's no string, just use the offset of the end of the tvb as start/end.
905 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
906 proto_tree *ntlmssp_tree,
907 gboolean unicode_strings,
908 int string_hf, int *start, int *end,
909 const char **stringp)
911 proto_tree *tree = NULL;
912 proto_item *tf = NULL;
913 gint16 string_length = tvb_get_letohs(tvb, offset);
914 gint16 string_maxlen = tvb_get_letohs(tvb, offset+2);
915 gint32 string_offset = tvb_get_letohl(tvb, offset+4);
916 const char *string_text = NULL;
920 *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
921 if (0 == string_length) {
924 proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
931 bc = result_length = string_length;
932 string_text = get_unicode_or_ascii_string(tvb, &string_offset,
933 unicode_strings, &result_length,
936 if (stringp != NULL) {
937 if (!string_text) string_text = ""; /* Make sure we don't blow up later */
939 *stringp = string_text;
943 tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
944 string_offset, result_length, string_text);
945 tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
947 proto_tree_add_uint(tree, hf_ntlmssp_string_len,
948 tvb, offset, 2, string_length);
950 proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
951 tvb, offset, 2, string_maxlen);
953 proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
954 tvb, offset, 4, string_offset);
957 *end = string_offset + string_length;
961 /* dissect a generic blob - header area contains:
964 four byte offset of blob in data area
965 The function returns the offset at the end of the blob header,
966 but the 'end' parameter returns the offset of the end of the blob itself
969 dissect_ntlmssp_blob (tvbuff_t *tvb, packet_info *pinfo,
970 proto_tree *ntlmssp_tree, int offset,
971 int blob_hf, int *end, ntlmssp_blob *result)
973 proto_item *tf = NULL;
974 proto_tree *tree = NULL;
975 guint16 blob_length = tvb_get_letohs(tvb, offset);
976 guint16 blob_maxlen = tvb_get_letohs(tvb, offset+2);
977 guint32 blob_offset = tvb_get_letohl(tvb, offset+4);
979 if (0 == blob_length) {
980 *end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
981 proto_tree_add_bytes_format_value(ntlmssp_tree, blob_hf, tvb, offset, 8, NULL, "Empty");
983 result->contents = NULL;
988 tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
989 blob_offset, blob_length, ENC_NA);
990 tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
992 proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
993 tvb, offset, 2, blob_length);
995 proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
996 tvb, offset, 2, blob_maxlen);
998 proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
999 tvb, offset, 4, blob_offset);
1002 *end = blob_offset + blob_length;
1004 if (blob_length < MAX_BLOB_SIZE) {
1005 result->length = blob_length;
1006 result->contents = (guint8 *)tvb_memdup(wmem_file_scope(), tvb, blob_offset, blob_length);
1008 expert_add_info_format(pinfo, tf, &ei_ntlmssp_v2_key_too_long,
1009 "NTLM v2 key is %d bytes long, too big for our %d buffer", blob_length, MAX_BLOB_SIZE);
1011 result->contents = NULL;
1015 * XXX - for LmChallengeResponse (hf_ntlmssp_auth_lmresponse), should
1016 * we have a field for both Response (2.2.2.3 "LM_RESPONSE" and
1017 * 2.2.2.4 "LMv2_RESPONSE" in [MS-NLMP]) in addition to ClientChallenge
1018 * (only in 2.2.2.4 "LMv2_RESPONSE")?
1020 * XXX - should we also dissect the fields of an NtChallengeResponse
1021 * (hf_ntlmssp_auth_ntresponse)?
1023 * XXX - should we warn if the blob is too *small*?
1025 if (blob_hf == hf_ntlmssp_auth_lmresponse) {
1027 * LMChallengeResponse. It's either 2.2.2.3 "LM_RESPONSE" or
1028 * 2.2.2.4 "LMv2_RESPONSE", in [MS-NLMP].
1030 * XXX - should we have a field for Response as well as
1033 if (tvb_memeql(tvb, blob_offset+8, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NTLMSSP_KEY_LEN) == 0) {
1037 * XXX - according to 2.2.2.4 "LMv2_RESPONSE", the ClientChallenge
1038 * is at an offset of 16 from the beginning of the blob; it's not
1039 * at the beginning of the blob.
1041 proto_tree_add_item (ntlmssp_tree,
1042 hf_ntlmssp_ntlm_client_challenge,
1043 tvb, blob_offset, 8, ENC_NA);
1045 } else if (blob_hf == hf_ntlmssp_auth_ntresponse) {
1047 * NTChallengeResponse. It's either 2.2.2.6 "NTLM v1 Response:
1048 * NTLM_RESPONSE" or 2.2.2.8 "NTLM v2 Response: NTLMv2_RESPONSE"
1051 if (blob_length > 24) {
1053 * > 24 bytes, so it's "NTLM v2 Response: NTLMv2_RESPONSE".
1054 * An NTLMv2_RESPONSE has 16 bytes of Response followed
1055 * by an NTLMv2_CLIENT_CHALLENGE; an NTLMv2_CLIENT_CHALLENGE
1056 * is at least 32 bytes, so an NTLMv2_RESPONSE is at least
1059 dissect_ntlmv2_response(tvb, pinfo, tree, blob_offset, blob_length);
1066 static const int * ntlmssp_negotiate_flags[] = {
1067 &hf_ntlmssp_negotiate_flags_80000000,
1068 &hf_ntlmssp_negotiate_flags_40000000,
1069 &hf_ntlmssp_negotiate_flags_20000000,
1070 &hf_ntlmssp_negotiate_flags_10000000,
1071 &hf_ntlmssp_negotiate_flags_8000000,
1072 &hf_ntlmssp_negotiate_flags_4000000,
1073 &hf_ntlmssp_negotiate_flags_2000000,
1074 &hf_ntlmssp_negotiate_flags_1000000,
1075 &hf_ntlmssp_negotiate_flags_800000,
1076 &hf_ntlmssp_negotiate_flags_400000,
1077 &hf_ntlmssp_negotiate_flags_200000,
1078 &hf_ntlmssp_negotiate_flags_100000,
1079 &hf_ntlmssp_negotiate_flags_80000,
1080 &hf_ntlmssp_negotiate_flags_40000,
1081 &hf_ntlmssp_negotiate_flags_20000,
1082 &hf_ntlmssp_negotiate_flags_10000,
1083 &hf_ntlmssp_negotiate_flags_8000,
1084 &hf_ntlmssp_negotiate_flags_4000,
1085 &hf_ntlmssp_negotiate_flags_2000,
1086 &hf_ntlmssp_negotiate_flags_1000,
1087 &hf_ntlmssp_negotiate_flags_800,
1088 &hf_ntlmssp_negotiate_flags_400,
1089 &hf_ntlmssp_negotiate_flags_200,
1090 &hf_ntlmssp_negotiate_flags_100,
1091 &hf_ntlmssp_negotiate_flags_80,
1092 &hf_ntlmssp_negotiate_flags_40,
1093 &hf_ntlmssp_negotiate_flags_20,
1094 &hf_ntlmssp_negotiate_flags_10,
1095 &hf_ntlmssp_negotiate_flags_08,
1096 &hf_ntlmssp_negotiate_flags_04,
1097 &hf_ntlmssp_negotiate_flags_02,
1098 &hf_ntlmssp_negotiate_flags_01,
1102 /* Dissect "version" */
1105 0 Major Version Number 1 byte
1106 1 Minor Version Number 1 byte
1107 2 Build Number short(LE)
1108 3 (Reserved) 3 bytes
1109 4 NTLM Current Revision 1 byte
1113 dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
1114 proto_tree *ntlmssp_tree)
1118 proto_tree *version_tree;
1119 tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
1120 "Version %u.%u (Build %u); NTLM Current Revision %u",
1121 tvb_get_guint8(tvb, offset),
1122 tvb_get_guint8(tvb, offset+1),
1123 tvb_get_letohs(tvb, offset+2),
1124 tvb_get_guint8(tvb, offset+7));
1125 version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
1126 proto_tree_add_item(version_tree, hf_ntlmssp_version_major , tvb, offset , 1, ENC_LITTLE_ENDIAN);
1127 proto_tree_add_item(version_tree, hf_ntlmssp_version_minor , tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1128 proto_tree_add_item(version_tree, hf_ntlmssp_version_build_number , tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1129 proto_tree_add_item(version_tree, hf_ntlmssp_version_ntlm_current_revision, tvb, offset+7, 1, ENC_LITTLE_ENDIAN);
1134 /* Dissect a NTLM response. This is documented at
1135 http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
1137 /* Attribute types */
1139 * XXX - the davenport document says that a type of 5 has been seen,
1140 * "apparently containing the 'parent' DNS domain for servers in
1142 * XXX: MS-NLMP info is newer than Davenport info;
1143 * The attribute type list and the attribute names below are
1144 * based upon MS-NLMP.
1147 #define NTLM_TARGET_INFO_END 0x0000
1148 #define NTLM_TARGET_INFO_NB_COMPUTER_NAME 0x0001
1149 #define NTLM_TARGET_INFO_NB_DOMAIN_NAME 0x0002
1150 #define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
1151 #define NTLM_TARGET_INFO_DNS_DOMAIN_NAME 0x0004
1152 #define NTLM_TARGET_INFO_DNS_TREE_NAME 0x0005
1153 #define NTLM_TARGET_INFO_FLAGS 0x0006
1154 #define NTLM_TARGET_INFO_TIMESTAMP 0x0007
1155 #define NTLM_TARGET_INFO_RESTRICTIONS 0x0008
1156 #define NTLM_TARGET_INFO_TARGET_NAME 0x0009
1157 #define NTLM_TARGET_INFO_CHANNEL_BINDINGS 0x000A
1159 static const value_string ntlm_name_types[] = {
1160 { NTLM_TARGET_INFO_END, "End of list" },
1161 { NTLM_TARGET_INFO_NB_COMPUTER_NAME, "NetBIOS computer name" },
1162 { NTLM_TARGET_INFO_NB_DOMAIN_NAME, "NetBIOS domain name" },
1163 { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
1164 { NTLM_TARGET_INFO_DNS_DOMAIN_NAME, "DNS domain name" },
1165 { NTLM_TARGET_INFO_DNS_TREE_NAME, "DNS tree name" },
1166 { NTLM_TARGET_INFO_FLAGS, "Flags" },
1167 { NTLM_TARGET_INFO_TIMESTAMP, "Timestamp" },
1168 { NTLM_TARGET_INFO_RESTRICTIONS, "Restrictions" },
1169 { NTLM_TARGET_INFO_TARGET_NAME, "Target Name"},
1170 { NTLM_TARGET_INFO_CHANNEL_BINDINGS, "Channel Bindings"},
1173 static value_string_ext ntlm_name_types_ext = VALUE_STRING_EXT_INIT(ntlm_name_types);
1175 /* The following *must* match the order of the list of attribute types */
1176 /* Assumption: values in the list are a sequence starting with 0 and */
1177 /* with no gaps allowing a direct access of the array by attribute type */
1178 static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
1179 &hf_ntlmssp_challenge_target_info_end,
1180 &hf_ntlmssp_challenge_target_info_nb_computer_name,
1181 &hf_ntlmssp_challenge_target_info_nb_domain_name,
1182 &hf_ntlmssp_challenge_target_info_dns_computer_name,
1183 &hf_ntlmssp_challenge_target_info_dns_domain_name,
1184 &hf_ntlmssp_challenge_target_info_dns_tree_name,
1185 &hf_ntlmssp_challenge_target_info_flags,
1186 &hf_ntlmssp_challenge_target_info_timestamp,
1187 &hf_ntlmssp_challenge_target_info_restrictions,
1188 &hf_ntlmssp_challenge_target_info_target_name,
1189 &hf_ntlmssp_challenge_target_info_channel_bindings
1192 static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
1193 &hf_ntlmssp_ntlmv2_response_end,
1194 &hf_ntlmssp_ntlmv2_response_nb_computer_name,
1195 &hf_ntlmssp_ntlmv2_response_nb_domain_name,
1196 &hf_ntlmssp_ntlmv2_response_dns_computer_name,
1197 &hf_ntlmssp_ntlmv2_response_dns_domain_name,
1198 &hf_ntlmssp_ntlmv2_response_dns_tree_name,
1199 &hf_ntlmssp_ntlmv2_response_flags,
1200 &hf_ntlmssp_ntlmv2_response_timestamp,
1201 &hf_ntlmssp_ntlmv2_response_restrictions,
1202 &hf_ntlmssp_ntlmv2_response_target_name,
1203 &hf_ntlmssp_ntlmv2_response_channel_bindings
1206 typedef struct _tif {
1209 int *hf_item_length;
1210 int **hf_attr_array_p;
1213 static tif_t ntlmssp_challenge_target_info_tif = {
1214 &ett_ntlmssp_challenge_target_info_item,
1215 &hf_ntlmssp_challenge_target_info_item_type,
1216 &hf_ntlmssp_challenge_target_info_item_len,
1217 ntlmssp_hf_challenge_target_info_hf_ptr_array
1220 static tif_t ntlmssp_ntlmv2_response_tif = {
1221 &ett_ntlmssp_ntlmv2_response_item,
1222 &hf_ntlmssp_ntlmv2_response_item_type,
1223 &hf_ntlmssp_ntlmv2_response_item_len,
1224 ntlmssp_hf_ntlmv2_response_hf_ptr_array
1227 /** See [MS-NLMP] 2.2.2.1 */
1229 dissect_ntlmssp_target_info_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1230 guint32 target_info_offset, guint16 target_info_length,
1233 guint32 item_offset;
1234 guint16 item_type = ~0;
1235 guint16 item_length;
1237 /* Now enumerate through the individual items in the list */
1238 item_offset = target_info_offset;
1240 while (item_offset < (target_info_offset + target_info_length) && (item_type != NTLM_TARGET_INFO_END)) {
1241 proto_item *target_info_tf;
1242 proto_tree *target_info_tree;
1243 guint32 content_offset;
1244 guint16 content_length;
1245 guint32 type_offset;
1247 const guint8 *text = NULL;
1249 int **hf_array_p = tif_p->hf_attr_array_p;
1252 type_offset = item_offset;
1253 item_type = tvb_get_letohs(tvb, type_offset);
1255 /* Content length */
1256 len_offset = type_offset + 2;
1257 content_length = tvb_get_letohs(tvb, len_offset);
1260 content_offset = len_offset + 2;
1261 item_length = content_length + 4;
1263 target_info_tree = proto_tree_add_subtree_format(tree, tvb, item_offset, item_length, *tif_p->ett, &target_info_tf,
1264 "Attribute: %s", val_to_str_ext(item_type, &ntlm_name_types_ext, "Unknown (%d)"));
1266 proto_tree_add_item (target_info_tree, *tif_p->hf_item_type, tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
1267 proto_tree_add_item (target_info_tree, *tif_p->hf_item_length, tvb, len_offset, 2, ENC_LITTLE_ENDIAN);
1269 if (content_length > 0) {
1270 switch (item_type) {
1271 case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
1272 case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
1273 case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
1274 case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
1275 case NTLM_TARGET_INFO_DNS_TREE_NAME:
1276 case NTLM_TARGET_INFO_TARGET_NAME:
1277 proto_tree_add_item_ret_string(target_info_tree, *hf_array_p[item_type], tvb, content_offset, content_length, ENC_UTF_16|ENC_LITTLE_ENDIAN, wmem_packet_scope(), &text);
1278 proto_item_append_text(target_info_tf, ": %s", text);
1281 case NTLM_TARGET_INFO_FLAGS:
1282 proto_tree_add_item(target_info_tree, *hf_array_p[item_type], 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], tvb, content_offset, content_length, ENC_NA);
1295 proto_tree_add_expert(target_info_tree, pinfo, &ei_ntlmssp_target_info_attr,
1296 tvb, content_offset, content_length);
1301 item_offset += item_length;
1307 /** See [MS-NLMP] 3.3.2 */
1309 dissect_ntlmv2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int len)
1311 proto_item *ntlmv2_item = NULL;
1312 proto_tree *ntlmv2_tree = NULL;
1313 const int orig_offset = offset;
1315 /* XXX - make sure we don't go past len? */
1317 ntlmv2_item = proto_tree_add_item(
1318 tree, hf_ntlmssp_ntlmv2_response, tvb,
1319 offset, len, ENC_NA);
1320 ntlmv2_tree = proto_item_add_subtree(
1321 ntlmv2_item, ett_ntlmssp_ntlmv2_response);
1324 proto_tree_add_item(
1325 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_ntproofstr, tvb,
1326 offset, 16, ENC_NA);
1329 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_rversion, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1332 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hirversion, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1335 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 6, ENC_NA);
1338 offset = dissect_nt_64bit_time(
1339 tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time);
1340 proto_tree_add_item(
1341 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
1345 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 4, ENC_NA);
1348 offset = dissect_ntlmssp_target_info_list(tvb, pinfo, ntlmv2_tree, offset, len - (offset - orig_offset), &ntlmssp_ntlmv2_response_tif);
1350 if ((offset - orig_offset) < len) {
1351 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 4, ENC_NA);
1355 if ((offset - orig_offset) < len) {
1356 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_pad, tvb, offset, len - (offset - orig_offset), ENC_NA);
1362 /* tapping into ntlmssph not yet implemented */
1364 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1366 guint32 negotiate_flags;
1372 /* NTLMSSP Negotiate Flags */
1373 negotiate_flags = tvb_get_letohl (tvb, offset);
1374 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1378 * XXX - the davenport document says that these might not be
1379 * sent at all, presumably meaning the length of the message
1380 * isn't enough to contain them.
1382 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1383 hf_ntlmssp_negotiate_domain,
1384 &data_start, &data_end, NULL);
1386 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
1387 hf_ntlmssp_negotiate_workstation,
1388 &item_start, &item_end, NULL);
1389 data_start = MIN(data_start, item_start);
1390 data_end = MAX(data_end, item_end);
1392 /* If there are more bytes before the data block dissect a version field
1393 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1394 if (offset < data_start) {
1395 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1396 dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1403 dissect_ntlmssp_challenge_target_info_blob (packet_info *pinfo, tvbuff_t *tvb, int offset,
1404 proto_tree *ntlmssp_tree,
1407 guint16 challenge_target_info_length = tvb_get_letohs(tvb, offset);
1408 guint16 challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
1409 guint32 challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
1410 proto_item *tf = NULL;
1411 proto_tree *challenge_target_info_tree = NULL;
1413 /* the target info list is just a blob */
1414 if (0 == challenge_target_info_length) {
1415 *end = (challenge_target_info_offset > ((guint)offset)+8 ? challenge_target_info_offset : ((guint)offset)+8);
1416 proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb, offset, 8,
1417 "Target Info List: Empty");
1422 tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
1423 challenge_target_info_offset, challenge_target_info_length, ENC_NA);
1424 challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
1426 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
1427 tvb, offset, 2, challenge_target_info_length);
1429 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
1430 tvb, offset, 2, challenge_target_info_maxlen);
1432 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
1433 tvb, offset, 4, challenge_target_info_offset);
1436 dissect_ntlmssp_target_info_list(tvb, pinfo, challenge_target_info_tree,
1437 challenge_target_info_offset, challenge_target_info_length,
1438 &ntlmssp_challenge_target_info_tif);
1440 *end = challenge_target_info_offset + challenge_target_info_length;
1444 /* tapping into ntlmssph not yet implemented */
1446 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
1447 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1449 guint32 negotiate_flags;
1450 int item_start, item_end;
1451 int data_start, data_end; /* MIN and MAX seen */
1452 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1453 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1454 ntlmssp_info *conv_ntlmssp_info = NULL;
1455 conversation_t *conversation;
1456 gboolean unicode_strings = FALSE;
1458 guint8 sspkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key */
1459 int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
1461 /* need to find unicode flag */
1462 negotiate_flags = tvb_get_letohl (tvb, offset+8);
1463 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
1464 unicode_strings = TRUE;
1468 * XXX - the davenport document (and MS-NLMP) calls this "Target Name",
1469 * presumably because non-domain targets are supported.
1470 * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
1472 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
1473 hf_ntlmssp_challenge_target_name,
1474 &item_start, &item_end, NULL);
1475 data_start = item_start;
1476 data_end = item_end;
1478 /* NTLMSSP Negotiate Flags */
1479 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1482 /* NTLMSSP NT Lan Manager Challenge */
1483 proto_tree_add_item (ntlmssp_tree,
1484 hf_ntlmssp_ntlm_server_challenge,
1485 tvb, offset, 8, ENC_NA);
1488 * Store the flags and the RC4 state information with the conversation,
1489 * as they're needed in order to dissect subsequent messages.
1491 conversation = find_or_create_conversation(pinfo);
1493 tvb_memcpy(tvb, tmp, offset, 8); /* challenge */
1494 /* We can face more than one NTLM exchange over the same couple of IP and ports ...*/
1495 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation, proto_ntlmssp);
1496 /* XXX: The following code is (re)executed every time a particular frame is dissected
1497 * (in whatever order). Thus it seems to me that "multiple exchanges" might not be
1498 * handled well depending on the order that frames are visited after the initial dissection.
1500 if (!conv_ntlmssp_info || memcmp(tmp, conv_ntlmssp_info->server_challenge, 8) != 0) {
1501 conv_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_info);
1502 wmem_register_callback(wmem_file_scope(), ntlmssp_sessions_destroy_cb, conv_ntlmssp_info);
1503 /* Insert the flags into the conversation */
1504 conv_ntlmssp_info->flags = negotiate_flags;
1505 /* Insert the RC4 state information into the conversation */
1506 tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
1507 conv_ntlmssp_info->is_auth_ntlm_v2 = 0;
1508 /* Between the challenge and the user provided password, we can build the
1509 NTLMSSP key and initialize the cipher if we are not in EXTENDED SECURITY
1510 in this case we need the client challenge as well*/
1511 /* BTW this is true just if we are in LM Authentication if not the logic is a bit different.
1512 * Right now it's not very clear what is LM Authentication it __seems__ to be when
1513 * NEGOTIATE NT ONLY is not set and NEGOSIATE EXTENDED SECURITY is not set as well*/
1514 if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1516 conv_ntlmssp_info->rc4_state_initialized = 0;
1517 /* XXX - Make sure there is 24 bytes for the key */
1518 conv_ntlmssp_info->ntlm_response.contents = (guint8 *)wmem_alloc0(wmem_file_scope(), 24);
1519 conv_ntlmssp_info->lm_response.contents = (guint8 *)wmem_alloc0(wmem_file_scope(), 24);
1521 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, ntlmssph);
1522 if (memcmp(sspkey, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
1523 get_sealing_rc4key(sspkey, conv_ntlmssp_info->flags, &ssp_key_len, clientkey, serverkey);
1524 if (!gcry_cipher_open(&conv_ntlmssp_info->rc4_handle_client, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1525 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_client, sspkey, ssp_key_len)) {
1526 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
1527 conv_ntlmssp_info->rc4_handle_client = NULL;
1530 if (!gcry_cipher_open(&conv_ntlmssp_info->rc4_handle_server, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1531 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_server, sspkey, ssp_key_len)) {
1532 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
1533 conv_ntlmssp_info->rc4_handle_server = NULL;
1536 if (conv_ntlmssp_info->rc4_handle_client && conv_ntlmssp_info->rc4_handle_server) {
1537 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1538 conv_ntlmssp_info->rc4_state_initialized = 1;
1542 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1546 /* If no more bytes (ie: no "reserved", ...) before start of data block, then return */
1547 /* XXX: According to Davenport "This form is seen in older Win9x-based systems" */
1548 /* Also: I've seen a capture with an HTTP CONNECT proxy-authentication */
1549 /* message wherein the challenge from the proxy has this form. */
1550 if (offset >= data_start) {
1554 /* Reserved (function not completely known) */
1556 * XXX - SSP key? The davenport document says
1558 * The context field is typically populated when Negotiate Local
1559 * Call is set. It contains an SSPI context handle, which allows
1560 * the client to "short-circuit" authentication and effectively
1561 * circumvent responding to the challenge. Physically, the context
1562 * is two long values. This is covered in greater detail later,
1563 * in the "Local Authentication" section.
1565 * It also says that that information may be omitted.
1567 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
1568 tvb, offset, 8, ENC_NA);
1572 * The presence or absence of this field is not obviously correlated
1573 * with any flags in the previous NEGOTIATE message or in this
1574 * message (other than the "Workstation Supplied" and "Domain
1575 * Supplied" flags in the NEGOTIATE message, at least in the capture
1576 * I've seen - but those also correlate with the presence of workstation
1577 * and domain name fields, so it doesn't seem to make sense that they
1578 * actually *indicate* whether the subsequent CHALLENGE has an
1581 if (offset < data_start) {
1582 offset = dissect_ntlmssp_challenge_target_info_blob(pinfo, tvb, offset, ntlmssp_tree, &item_end);
1583 /* XXX: This code assumes that the address list in the data block */
1584 /* is always after the target name. Is this OK ? */
1585 data_end = MAX(data_end, item_end);
1588 /* If there are more bytes before the data block dissect a version field
1589 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1590 if (offset < data_start) {
1591 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1592 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1595 return MAX(offset, data_end);
1599 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
1600 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
1602 int item_start, item_end;
1603 int data_start, data_end = 0;
1604 guint32 negotiate_flags;
1605 guint8 sspkey[NTLMSSP_KEY_LEN]; /* exported session key */
1606 guint8 clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1607 guint8 serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1608 guint8 encryptedsessionkey[NTLMSSP_KEY_LEN];
1609 ntlmssp_blob sessionblob;
1610 gboolean unicode_strings = FALSE;
1611 ntlmssp_info *conv_ntlmssp_info;
1612 conversation_t *conversation;
1616 * Get flag info from the original negotiate message, if any.
1617 * This is because the flag information is sometimes missing from
1618 * the AUTHENTICATE message, so we can't figure out whether
1619 * strings are Unicode or not by looking at *our* flags.
1620 * XXX it seems it's more from the CHALLENGE message, which is more clever in fact
1621 * because the server can change some flags.
1622 * But according to MS NTLMSSP doc it's not that simple.
1623 * In case of Conection less mode AUTHENTICATE flags should be used because they
1624 * reprensent the choice of the client after having been informed of options of the
1625 * server in the CHALLENGE message.
1626 * In Connection mode then the CHALLENGE flags should (must ?) be used
1627 * XXX: MS-NLMP says the flag field in the AUTHENTICATE message "contains the set of bit
1628 * flags (section 2.2.2.5) negotiated in the previous messages."
1629 * I read that to mean that the flags for in connection-mode AUTHENTICATE also represent
1630 * the choice of the client (for the flags which are negotiated).
1631 * XXX: In the absence of CHALLENGE flags, as a last resort we'll use the flags
1632 * (if available) from this AUTHENTICATE message.
1633 * I've seen a capture which does an HTTP CONNECT which:
1634 * - has the NEGOTIATE & CHALLENGE messages in one TCP connection;
1635 * - has the AUTHENTICATE message in a second TCP connection;
1636 * (The authentication aparently succeeded).
1638 conv_ntlmssp_info = (ntlmssp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_CONV_INFO_KEY);
1639 if (conv_ntlmssp_info == NULL) {
1641 * There isn't any. Is there any from this conversation? If so,
1642 * it means this is the first time we've dissected this frame, so
1643 * we should give it flag info.
1645 /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
1646 /* so we'll have a place to store flags. */
1647 /* This is a bit brute-force but looks like it will be OK. */
1648 conversation = find_or_create_conversation(pinfo);
1649 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation, proto_ntlmssp);
1650 if (conv_ntlmssp_info == NULL) {
1651 conv_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_info);
1652 wmem_register_callback(wmem_file_scope(), ntlmssp_sessions_destroy_cb, conv_ntlmssp_info);
1653 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1655 /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
1656 same as the one attached to the conversation. That is: *both* point to
1657 the exact same struct in memory. Is this what is indended ? */
1658 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_CONV_INFO_KEY, conv_ntlmssp_info);
1661 if (conv_ntlmssp_info != NULL) {
1662 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
1663 unicode_strings = TRUE;
1667 * Sometimes the session key and flags are missing.
1668 * Sometimes the session key is present but the flags are missing.
1669 * XXX Who stay so ? Reading spec I would rather say the opposite: flags are
1670 * always present, session information are always there as well but sometime
1671 * session information could be null (in case of no session)
1672 * Sometimes they're both present.
1674 * This does not correlate with any flags in the previous CHALLENGE
1675 * message, and only correlates with "Negotiate Unicode", "Workstation
1676 * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
1677 * those don't make sense as flags to use to determine this.
1679 * So we check all of the descriptors to figure out where the data
1680 * area begins, and if the session key or the flags would be in the
1681 * middle of the data area, we assume the field in question is
1684 * XXX - Reading Davenport and MS-NLMP: as I see it the possibilities are:
1685 * a. No session-key; no flags; no version ("Win9x")
1686 * b. Session-key & flags.
1687 * c. Session-key, flags & version.
1688 * In cases b and c the session key may be "null".
1692 /* Lan Manager response */
1693 data_start = tvb_get_letohl(tvb, offset+4);
1694 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
1695 hf_ntlmssp_auth_lmresponse,
1697 conv_ntlmssp_info == NULL ? NULL :
1698 &conv_ntlmssp_info->lm_response);
1699 data_end = MAX(data_end, item_end);
1702 item_start = tvb_get_letohl(tvb, offset+4);
1703 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
1704 hf_ntlmssp_auth_ntresponse,
1706 conv_ntlmssp_info == NULL ? NULL :
1707 &conv_ntlmssp_info->ntlm_response);
1708 data_start = MIN(data_start, item_start);
1709 data_end = MAX(data_end, item_end);
1710 if (conv_ntlmssp_info != NULL)
1712 if (conv_ntlmssp_info->ntlm_response.length > 24)
1714 conv_ntlmssp_info->is_auth_ntlm_v2 = 1;
1716 * XXX - at least according to 2.2.2.7 "NTLM v2: NTLMv2_CLIENT_CHALLENGE"
1717 * in [MS-NLMP], the client challenge is at an offset of 16 bytes,
1718 * not 24 bytes, from the beginning of the blob.
1720 * If so, that not only means that the "+24" should be "+16", it also
1721 * means that the length check should be ">= 24", and would thus be
1724 * If not, then we should handle a bad blob in which the client
1725 * challenge is missing, and not try to use whatever random junk
1726 * is in conv_ntlmssp_info->client_challenge.
1728 if (conv_ntlmssp_info->ntlm_response.length >= 32) {
1729 memcpy(conv_ntlmssp_info->client_challenge, conv_ntlmssp_info->ntlm_response.contents+24, 8);
1734 conv_ntlmssp_info->is_auth_ntlm_v2 = 0;
1739 item_start = tvb_get_letohl(tvb, offset+4);
1740 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1742 hf_ntlmssp_auth_domain,
1743 &item_start, &item_end, &(ntlmssph->domain_name));
1744 /*ntlmssph->domain_name_len = item_end-item_start;*/
1745 data_start = MIN(data_start, item_start);
1746 data_end = MAX(data_end, item_end);
1749 item_start = tvb_get_letohl(tvb, offset+4);
1750 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1752 hf_ntlmssp_auth_username,
1753 &item_start, &item_end, &(ntlmssph->acct_name));
1754 /*ntlmssph->acct_name_len = item_end-item_start;*/
1755 data_start = MIN(data_start, item_start);
1756 data_end = MAX(data_end, item_end);
1758 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "User: %s\\%s",
1759 ntlmssph->domain_name, ntlmssph->acct_name);
1762 item_start = tvb_get_letohl(tvb, offset+4);
1763 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
1765 hf_ntlmssp_auth_hostname,
1766 &item_start, &item_end, &(ntlmssph->host_name));
1767 data_start = MIN(data_start, item_start);
1768 data_end = MAX(data_end, item_end);
1770 sessionblob.length = 0;
1771 if (offset < data_start) {
1773 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
1774 hf_ntlmssp_auth_sesskey,
1775 &item_end, &sessionblob);
1776 data_end = MAX(data_end, item_end);
1779 if (offset < data_start) {
1780 /* NTLMSSP Negotiate Flags */
1781 negotiate_flags = tvb_get_letohl (tvb, offset);
1782 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1785 /* If no previous flags seen (ie: no previous CHALLENGE) use flags
1786 from the AUTHENTICATE message).
1787 Assumption: (flags == 0) means flags not previously seen */
1788 if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
1789 conv_ntlmssp_info->flags = negotiate_flags;
1792 negotiate_flags = 0;
1794 /* If there are more bytes before the data block dissect a version field
1795 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1796 if (offset < data_start) {
1797 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1798 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1801 /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
1803 if (offset < data_start) {
1804 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_message_integrity_code, tvb, offset, 16, ENC_NA);
1808 if (sessionblob.length > NTLMSSP_KEY_LEN) {
1809 expert_add_info_format(pinfo, NULL, &ei_ntlmssp_blob_len_too_long, "Session blob length too long: %u", sessionblob.length);
1810 } else if (sessionblob.length != 0) {
1811 memcpy(encryptedsessionkey, sessionblob.contents, sessionblob.length);
1812 /* Try to attach to an existing conversation if not then it's useless to try to do so
1813 * because we are missing important information (ie. server challenge)
1815 if (conv_ntlmssp_info) {
1816 /* If we are in EXTENDED SECURITY then we can now initialize cipher */
1817 if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
1819 conv_ntlmssp_info->rc4_state_initialized = 0;
1820 if (conv_ntlmssp_info->is_auth_ntlm_v2) {
1821 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);
1825 if (conv_ntlmssp_info->lm_response.contents == NULL || conv_ntlmssp_info->lm_response.length < 8) {
1826 memset(conv_ntlmssp_info->client_challenge, 0, 8);
1828 memcpy(conv_ntlmssp_info->client_challenge, conv_ntlmssp_info->lm_response.contents, 8);
1830 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, ntlmssph);
1832 /* ssp is the exported session key */
1833 if (memcmp(sspkey, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
1834 get_sealing_rc4key(sspkey, conv_ntlmssp_info->flags, &ssp_key_len, clientkey, serverkey);
1835 get_siging_key((guint8*)&conv_ntlmssp_info->sign_key_server, (guint8*)&conv_ntlmssp_info->sign_key_client, sspkey, ssp_key_len);
1836 if (!gcry_cipher_open (&conv_ntlmssp_info->rc4_handle_server, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1837 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_server, serverkey, ssp_key_len)) {
1838 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
1839 conv_ntlmssp_info->rc4_handle_server = NULL;
1842 if (!gcry_cipher_open (&conv_ntlmssp_info->rc4_handle_client, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1843 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_client, clientkey, ssp_key_len)) {
1844 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
1845 conv_ntlmssp_info->rc4_handle_client = NULL;
1848 if (conv_ntlmssp_info->rc4_handle_server && conv_ntlmssp_info->rc4_handle_client) {
1849 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1850 conv_ntlmssp_info->rc4_state_initialized = 1;
1856 return MAX(offset, data_end);
1860 get_sign_key(packet_info *pinfo, int cryptpeer)
1862 conversation_t *conversation;
1863 ntlmssp_info *conv_ntlmssp_info;
1865 conversation = find_conversation_pinfo(pinfo, 0);
1866 if (conversation == NULL) {
1867 /* We don't have a conversation. In this case, stop processing
1868 because we do not have enough info to decrypt the payload */
1872 /* We have a conversation, check for encryption state */
1873 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
1875 if (conv_ntlmssp_info == NULL) {
1876 /* No encryption state tied to the conversation. Therefore, we
1877 cannot decrypt the payload */
1881 /* We have the encryption state in the conversation. So return the
1882 crypt state tied to the requested peer
1884 if (cryptpeer == 1) {
1885 return (guint8*)&conv_ntlmssp_info->sign_key_client;
1887 return (guint8*)&conv_ntlmssp_info->sign_key_server;
1894 * Get the encryption state tied to this conversation. cryptpeer indicates
1895 * whether to retrieve the client key (1) or the server key (0)
1897 static gcry_cipher_hd_t
1898 get_encrypted_state(packet_info *pinfo, int cryptpeer)
1900 conversation_t *conversation;
1901 ntlmssp_info *conv_ntlmssp_info;
1903 conversation = find_conversation_pinfo(pinfo, 0);
1904 if (conversation == NULL) {
1905 /* We don't have a conversation. In this case, stop processing
1906 because we do not have enough info to decrypt the payload */
1910 /* We have a conversation, check for encryption state */
1911 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
1913 if (conv_ntlmssp_info == NULL) {
1914 /* No encryption state tied to the conversation. Therefore, we
1915 cannot decrypt the payload */
1919 /* We have the encryption state in the conversation. So return the
1920 crypt state tied to the requested peer
1922 if (cryptpeer == 1) {
1923 return conv_ntlmssp_info->rc4_handle_client;
1925 return conv_ntlmssp_info->rc4_handle_server;
1932 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1933 packet_info *pinfo, proto_tree *tree _U_, gpointer key);
1935 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
1936 packet_info *pinfo, proto_tree *tree, gpointer key);
1939 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1941 volatile int offset = 0;
1942 proto_tree *volatile ntlmssp_tree = NULL;
1943 proto_item *tf = NULL;
1945 guint32 encrypted_block_length;
1946 guint8 key[NTLMSSP_KEY_LEN];
1947 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01 */
1948 guint32 ntlm_magic_size = 4;
1949 guint32 ntlm_signature_size = 8;
1950 guint32 ntlm_seq_size = 4;
1952 length = tvb_captured_length (tvb);
1953 /* signature + seq + real payload */
1954 encrypted_block_length = length - ntlm_magic_size;
1956 if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
1957 /* Don't know why this would happen, but if it does, don't even bother
1958 attempting decryption/dissection */
1959 return offset + length;
1962 /* Setup a new tree for the NTLMSSP payload */
1964 tf = proto_tree_add_item (tree,
1966 tvb, offset, -1, ENC_NA);
1968 ntlmssp_tree = proto_item_add_subtree (tf,
1973 * Catch the ReportedBoundsError exception; the stuff we've been
1974 * handed doesn't necessarily run to the end of the packet, it's
1975 * an item inside a packet, so if it happens to be malformed (or
1976 * we, or a dissector we call, has a bug), so that an exception
1977 * is thrown, we want to report the error, but return and let
1978 * our caller dissect the rest of the packet.
1980 * If it gets a BoundsError, we can stop, as there's nothing more
1981 * in the packet after our blob to see, so we just re-throw the
1985 /* Version number */
1986 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
1987 tvb, offset, 4, ENC_LITTLE_ENDIAN);
1990 /* Encrypted body */
1991 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
1992 tvb, offset, ntlm_signature_size + ntlm_seq_size, ENC_NA);
1993 memset(key, 0, sizeof(key));
1994 tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
1995 /* Try to decrypt */
1996 decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree, key);
1997 decrypt_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo, ntlmssp_tree, key);
1998 /* let's try to hook ourselves here */
2001 } CATCH_NONFATAL_ERRORS {
2002 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2009 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
2010 packet_info *pinfo, proto_tree *tree _U_, gpointer key)
2012 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2013 ntlmssp_packet_info *packet_ntlmssp_info;
2014 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2016 /* Check to see if we already have state for this packet */
2017 packet_ntlmssp_info = (ntlmssp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2018 if (packet_ntlmssp_info == NULL) {
2019 /* We don't have any packet state, so create one */
2020 packet_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_packet_info);
2021 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY, packet_ntlmssp_info);
2023 if (!packet_ntlmssp_info->payload_decrypted) {
2024 conversation_t *conversation;
2025 ntlmssp_info *conv_ntlmssp_info;
2027 /* Pull the challenge info from the conversation */
2028 conversation = find_conversation_pinfo(pinfo, 0);
2029 if (conversation == NULL) {
2030 /* There is no conversation, thus no encryption state */
2034 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2036 if (conv_ntlmssp_info == NULL) {
2037 /* There is no NTLMSSP state tied to the conversation */
2040 if (conv_ntlmssp_info->rc4_state_initialized != 1) {
2041 /* The crypto sybsystem is not initialized. This means that either
2042 the conversation did not include a challenge, or that we do not have the right password */
2046 stored_packet_ntlmssp_info = (ntlmssp_packet_info *)g_hash_table_lookup(hash_packet, key);
2048 if (stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == TRUE) {
2049 /* Mat TBD (stderr, "Found a already decrypted packet\n");*/
2050 memcpy(packet_ntlmssp_info, stored_packet_ntlmssp_info, sizeof(ntlmssp_packet_info));
2051 /* Mat TBD printnbyte(packet_ntlmssp_info->decrypted_payload, encrypted_block_length, "Data: ", "\n");*/
2054 gcry_cipher_hd_t rc4_handle;
2055 gcry_cipher_hd_t rc4_handle_peer;
2057 /* Get the pair of RC4 state structures. One is used for to decrypt the
2058 payload. The other is used to re-encrypt the payload to represent
2060 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2062 rc4_handle = get_encrypted_state(pinfo, 1);
2063 rc4_handle_peer = get_encrypted_state(pinfo, 0);
2066 rc4_handle = get_encrypted_state(pinfo, 0);
2067 rc4_handle_peer = get_encrypted_state(pinfo, 1);
2070 if (rc4_handle == NULL) {
2071 /* There is no encryption state, so we cannot decrypt */
2075 /* Store the decrypted contents in the packet state struct
2076 (of course at this point, they aren't decrypted yet) */
2077 packet_ntlmssp_info->decrypted_payload = (guint8 *)tvb_memdup(wmem_file_scope(), tvb, offset,
2078 encrypted_block_length);
2079 packet_ntlmssp_info->payload_len = encrypted_block_length;
2080 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2081 packet_ntlmssp_info->decrypted_payload);
2083 g_hash_table_insert(hash_packet, key, packet_ntlmssp_info);
2086 /* Do the decryption of the payload */
2087 gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->decrypted_payload, encrypted_block_length, NULL, 0);
2089 /* decrypt the verifier */
2090 /*printnchar(packet_ntlmssp_info->decrypted_payload, encrypted_block_length, "data: ", "\n");*/
2091 /* We setup a temporary buffer so we can re-encrypt the payload after
2092 decryption. This is to update the opposite peer's RC4 state
2093 it's useful when we have only one key for both conversation
2094 in case of KEY_EXCH we have independent key so this is not needed*/
2095 if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2097 peer_block = (guint8 *)wmem_memdup(wmem_packet_scope(), packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2098 gcry_cipher_decrypt(rc4_handle_peer, peer_block, encrypted_block_length, NULL, 0);
2101 packet_ntlmssp_info->payload_decrypted = TRUE;
2105 /* Show the decrypted buffer in a new window */
2106 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->decrypted_payload,
2107 encrypted_block_length,
2108 encrypted_block_length);
2110 add_new_data_source(pinfo, decr_tvb,
2116 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2118 volatile int offset = 0;
2119 proto_tree *volatile ntlmssp_tree = NULL;
2120 proto_item *tf, *type_item;
2121 ntlmssp_header_t *ntlmssph;
2123 ntlmssph = wmem_new(wmem_packet_scope(), ntlmssp_header_t);
2125 ntlmssph->domain_name = NULL;
2126 ntlmssph->acct_name = NULL;
2127 ntlmssph->host_name = NULL;
2128 memset(ntlmssph->session_key, 0, NTLMSSP_KEY_LEN);
2130 /* Setup a new tree for the NTLMSSP payload */
2131 tf = proto_tree_add_item (tree,
2133 tvb, offset, -1, ENC_NA);
2135 ntlmssp_tree = proto_item_add_subtree (tf, ett_ntlmssp);
2138 * Catch the ReportedBoundsError exception; the stuff we've been
2139 * handed doesn't necessarily run to the end of the packet, it's
2140 * an item inside a packet, so if it happens to be malformed (or
2141 * we, or a dissector we call, has a bug), so that an exception
2142 * is thrown, we want to report the error, but return and let
2143 * our caller dissect the rest of the packet.
2145 * If it gets a BoundsError, we can stop, as there's nothing more
2146 * in the packet after our blob to see, so we just re-throw the
2150 /* NTLMSSP constant */
2151 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
2152 tvb, offset, 8, ENC_ASCII|ENC_NA);
2155 /* NTLMSSP Message Type */
2156 type_item = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
2157 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2158 ntlmssph->type = tvb_get_letohl (tvb, offset);
2161 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
2162 val_to_str_const(ntlmssph->type,
2163 ntlmssp_message_types,
2164 "Unknown NTLMSSP message type"));
2166 /* Call the appropriate dissector based on the Message Type */
2167 switch (ntlmssph->type) {
2169 case NTLMSSP_NEGOTIATE:
2170 dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree, ntlmssph);
2173 case NTLMSSP_CHALLENGE:
2174 dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2178 dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2182 /* Unrecognized message type */
2183 expert_add_info(pinfo, type_item, &ei_ntlmssp_message_type);
2186 } CATCH_NONFATAL_ERRORS {
2188 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2191 tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);
2192 return tvb_captured_length(tvb);
2196 dissect_ntlmssp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
2198 if (tvb_memeql(tvb, 0, "NTLMSSP", 8) == 0) {
2199 dissect_ntlmssp(tvb, pinfo, parent_tree, data);
2208 * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
2211 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
2212 packet_info *pinfo, proto_tree *tree, gpointer key)
2214 proto_tree *decr_tree;
2215 conversation_t *conversation;
2217 gcry_cipher_hd_t rc4_handle;
2218 gcry_cipher_hd_t rc4_handle_peer;
2219 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2222 guint8 calculated_md5[NTLMSSP_KEY_LEN];
2223 ntlmssp_info *conv_ntlmssp_info;
2224 ntlmssp_packet_info *packet_ntlmssp_info;
2225 int decrypted_offset = 0;
2227 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2229 packet_ntlmssp_info = (ntlmssp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2230 if (packet_ntlmssp_info == NULL) {
2231 /* We don't have data for this packet */
2234 conversation = find_conversation_pinfo(pinfo, 0);
2235 if (conversation == NULL) {
2236 /* There is no conversation, thus no encryption state */
2239 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2241 if (conv_ntlmssp_info == NULL) {
2242 /* There is no NTLMSSP state tied to the conversation */
2247 stored_packet_ntlmssp_info = (ntlmssp_packet_info *)g_hash_table_lookup(hash_packet, key);
2249 if (stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->verifier_decrypted == TRUE) {
2250 /* Mat TBD fprintf(stderr, "Found a already decrypted packet\n");*/
2251 /* In Theory it's aleady the case, and we should be more clever ... like just copying buffers ...*/
2252 packet_ntlmssp_info = stored_packet_ntlmssp_info;
2255 if (!packet_ntlmssp_info->verifier_decrypted) {
2256 if (conv_ntlmssp_info->rc4_state_initialized != 1) {
2257 /* The crypto sybsystem is not initialized. This means that either
2258 the conversation did not include a challenge, or we are doing
2259 something other than NTLMSSP v1 */
2262 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2263 /* client talk to server */
2264 rc4_handle = get_encrypted_state(pinfo, 1);
2265 sign_key = get_sign_key(pinfo, 1);
2266 rc4_handle_peer = get_encrypted_state(pinfo, 0);
2268 rc4_handle = get_encrypted_state(pinfo, 0);
2269 sign_key = get_sign_key(pinfo, 0);
2270 rc4_handle_peer = get_encrypted_state(pinfo, 1);
2273 if (rc4_handle == NULL || rc4_handle_peer == NULL) {
2274 /* There is no encryption state, so we cannot decrypt */
2278 /* Setup the buffer to decrypt to */
2279 tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
2280 offset, MIN(encrypted_block_length, sizeof(packet_ntlmssp_info->verifier)));
2282 /*if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
2283 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
2284 if ((NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2285 /* The spec says that if we have have a key exchange then we have a the signature that is crypted
2286 * otherwise it's just a hmac_md5(keysign, concat(message, sequence))[0..7]
2288 if (gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->verifier, 8, NULL, 0)) {
2293 * Try to check the HMAC MD5 of the message against those calculated works great with LDAP payload but
2294 * don't with DCE/RPC calls.
2295 * Some analysis need to be done ...
2297 if (sign_key != NULL) {
2298 check_buf = (guint8 *)wmem_alloc(wmem_packet_scope(), packet_ntlmssp_info->payload_len+4);
2299 tvb_memcpy(tvb, &sequence, offset+8, 4);
2300 memcpy(check_buf, &sequence, 4);
2301 memcpy(check_buf+4, packet_ntlmssp_info->decrypted_payload, packet_ntlmssp_info->payload_len);
2302 if (ws_hmac_buffer(GCRY_MD_MD5, calculated_md5, check_buf, (int)(packet_ntlmssp_info->payload_len+4), sign_key, NTLMSSP_KEY_LEN)) {
2306 printnbyte(packet_ntlmssp_info->verifier, 8, "HMAC from packet: ", "\n");
2307 printnbyte(calculated_md5, 8, "HMAC : ", "\n");
2312 /* 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 */
2313 /* Do the actual decryption of the verifier */
2314 if (gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->verifier, encrypted_block_length, NULL, 0)) {
2321 /* We setup a temporary buffer so we can re-encrypt the payload after
2322 decryption. This is to update the opposite peer's RC4 state
2323 This is not needed when we just have EXTENDED SECURITY because the signature is not crypted
2324 and it's also not needed when we have key exchange because server and client have independent keys */
2325 if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SECURITY & conv_ntlmssp_info->flags)) {
2326 peer_block = (guint8 *)wmem_memdup(wmem_packet_scope(), packet_ntlmssp_info->verifier, encrypted_block_length);
2327 if (gcry_cipher_decrypt(rc4_handle_peer, peer_block, encrypted_block_length, NULL, 0)) {
2332 /* Mark the packet as decrypted so that subsequent attempts to dissect
2333 the packet use the already decrypted payload instead of attempting
2335 packet_ntlmssp_info->verifier_decrypted = TRUE;
2338 /* Show the decrypted buffer in a new window */
2339 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
2340 encrypted_block_length,
2341 encrypted_block_length);
2342 add_new_data_source(pinfo, decr_tvb,
2343 "Decrypted NTLMSSP Verifier");
2345 /* Show the decrypted payload in the tree */
2346 decr_tree = proto_tree_add_subtree_format(tree, decr_tvb, 0, -1,
2348 "Decrypted Verifier (%d byte%s)",
2349 encrypted_block_length,
2350 plurality(encrypted_block_length, "", "s"));
2352 if (( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)) {
2353 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
2354 decr_tvb, decrypted_offset, 8, ENC_NA);
2355 decrypted_offset += 8;
2357 /* Incrementing sequence number of DCE conversation */
2358 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2359 decr_tvb, decrypted_offset, 4, ENC_NA);
2362 /* RANDOM PAD usually it's 0 */
2363 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
2364 decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
2365 decrypted_offset += 4;
2367 /* CRC32 of the DCE fragment data */
2368 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
2369 decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
2370 decrypted_offset += 4;
2372 /* Incrementing sequence number of DCE conversation */
2373 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2374 decr_tvb, decrypted_offset, 4, ENC_NA);
2378 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious*/
2380 dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *tree, void *data)
2382 volatile int offset = 0;
2383 proto_tree *volatile ntlmssp_tree = NULL;
2384 guint32 encrypted_block_length;
2385 tvbuff_t *volatile decr_tvb;
2386 tvbuff_t** ret_decr_tvb = (tvbuff_t**)data;
2389 *ret_decr_tvb = NULL;
2390 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
2392 encrypted_block_length = tvb_captured_length (tvb);
2393 /* signature + seq + real payload */
2395 /* Setup a new tree for the NTLMSSP payload */
2398 tf = proto_tree_add_item (tree,
2400 tvb, offset, -1, ENC_NA);
2402 ntlmssp_tree = proto_item_add_subtree (tf,
2407 * Catch the ReportedBoundsError exception; the stuff we've been
2408 * handed doesn't necessarily run to the end of the packet, it's
2409 * an item inside a packet, so if it happens to be malformed (or
2410 * we, or a dissector we call, has a bug), so that an exception
2411 * is thrown, we want to report the error, but return and let
2412 * our caller dissect the rest of the packet.
2414 * If it gets a BoundsError, we can stop, as there's nothing more
2415 * in the packet after our blob to see, so we just re-throw the
2419 /* Version number */
2421 /* Try to decrypt */
2422 decr_tvb = decrypt_data_payload (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree, NULL);
2424 *ret_decr_tvb = decr_tvb;
2425 /* let's try to hook ourselves here */
2427 } CATCH_NONFATAL_ERRORS {
2429 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2435 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious
2436 * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
2439 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2441 volatile int offset = 0;
2442 proto_tree *volatile ntlmssp_tree = NULL;
2443 proto_item *tf = NULL;
2444 guint32 verifier_length;
2445 guint32 encrypted_block_length;
2447 verifier_length = tvb_captured_length (tvb);
2448 encrypted_block_length = verifier_length - 4;
2450 if (encrypted_block_length < 12) {
2451 /* Don't know why this would happen, but if it does, don't even bother
2452 attempting decryption/dissection */
2453 return offset + verifier_length;
2456 /* Setup a new tree for the NTLMSSP payload */
2458 tf = proto_tree_add_item (tree,
2460 tvb, offset, -1, ENC_NA);
2462 ntlmssp_tree = proto_item_add_subtree (tf,
2467 * Catch the ReportedBoundsError exception; the stuff we've been
2468 * handed doesn't necessarily run to the end of the packet, it's
2469 * an item inside a packet, so if it happens to be malformed (or
2470 * we, or a dissector we call, has a bug), so that an exception
2471 * is thrown, we want to report the error, but return and let
2472 * our caller dissect the rest of the packet.
2474 * If it gets a BoundsError, we can stop, as there's nothing more
2475 * in the packet after our blob to see, so we just re-throw the
2479 /* Version number */
2480 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2481 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2484 /* Encrypted body */
2485 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2486 tvb, offset, encrypted_block_length, ENC_NA);
2488 /* Try to decrypt */
2489 decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree, NULL);
2490 /* let's try to hook ourselves here */
2493 offset += encrypted_block_length;
2494 } CATCH_NONFATAL_ERRORS {
2496 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2503 wrap_dissect_ntlmssp_payload_only(tvbuff_t *tvb, tvbuff_t *auth_tvb _U_,
2504 int offset, packet_info *pinfo, dcerpc_auth_info *auth_info _U_)
2506 tvbuff_t *data_tvb, *decrypted_tvb;
2508 data_tvb = tvb_new_subset_remaining(tvb, offset);
2509 dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL, &decrypted_tvb);
2510 return decrypted_tvb;
2514 header_hash(gconstpointer pointer)
2516 guint32 crc = ~crc32c_calculate(pointer, NTLMSSP_KEY_LEN, CRC32C_PRELOAD);
2517 /* Mat TBD fprintf(stderr, "Val: %u\n", crc);*/
2522 header_equal(gconstpointer pointer1, gconstpointer pointer2)
2524 if (!memcmp(pointer1, pointer2, 16)) {
2533 ntlmssp_init_protocol(void)
2535 hash_packet = g_hash_table_new(header_hash, header_equal);
2539 ntlmssp_cleanup_protocol(void)
2541 if (decrypted_payloads != NULL) {
2542 g_slist_free(decrypted_payloads);
2543 decrypted_payloads = NULL;
2545 g_hash_table_destroy(hash_packet);
2551 wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
2552 proto_tree *tree, dcerpc_info *di _U_, guint8 *drep _U_)
2556 auth_tvb = tvb_new_subset_remaining(tvb, offset);
2558 dissect_ntlmssp(auth_tvb, pinfo, tree, NULL);
2560 return tvb_captured_length_remaining(tvb, offset);
2564 wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
2565 proto_tree *tree, dcerpc_info *di _U_, guint8 *drep _U_)
2569 auth_tvb = tvb_new_subset_remaining(tvb, offset);
2570 return dissect_ntlmssp_verf(auth_tvb, pinfo, tree, NULL);
2573 static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
2574 wrap_dissect_ntlmssp, /* Bind */
2575 wrap_dissect_ntlmssp, /* Bind ACK */
2576 wrap_dissect_ntlmssp, /* AUTH3 */
2577 wrap_dissect_ntlmssp_verf, /* Request verifier */
2578 wrap_dissect_ntlmssp_verf, /* Response verifier */
2579 NULL, /* Request data */
2580 NULL /* Response data */
2583 static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
2584 wrap_dissect_ntlmssp, /* Bind */
2585 wrap_dissect_ntlmssp, /* Bind ACK */
2586 wrap_dissect_ntlmssp, /* AUTH3 */
2587 wrap_dissect_ntlmssp_verf, /* Request verifier */
2588 wrap_dissect_ntlmssp_verf, /* Response verifier */
2589 wrap_dissect_ntlmssp_payload_only, /* Request data */
2590 wrap_dissect_ntlmssp_payload_only /* Response data */
2594 proto_register_ntlmssp(void)
2597 static hf_register_info hf[] = {
2599 { "NTLMSSP identifier", "ntlmssp.identifier",
2600 FT_STRING, BASE_NONE, NULL, 0x0,
2603 { &hf_ntlmssp_message_type,
2604 { "NTLM Message Type", "ntlmssp.messagetype",
2605 FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0,
2608 { &hf_ntlmssp_negotiate_flags,
2609 { "Negotiate Flags", "ntlmssp.negotiateflags",
2610 FT_UINT32, BASE_HEX, NULL, 0x0,
2613 { &hf_ntlmssp_negotiate_flags_01,
2614 { "Negotiate UNICODE", "ntlmssp.negotiateunicode",
2615 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_UNICODE,
2618 { &hf_ntlmssp_negotiate_flags_02,
2619 { "Negotiate OEM", "ntlmssp.negotiateoem",
2620 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM,
2623 { &hf_ntlmssp_negotiate_flags_04,
2624 { "Request Target", "ntlmssp.requesttarget",
2625 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_TARGET,
2628 { &hf_ntlmssp_negotiate_flags_08,
2629 { "Request 0x00000008", "ntlmssp.negotiate00000008",
2630 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000008,
2633 { &hf_ntlmssp_negotiate_flags_10,
2634 { "Negotiate Sign", "ntlmssp.negotiatesign",
2635 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SIGN,
2638 { &hf_ntlmssp_negotiate_flags_20,
2639 { "Negotiate Seal", "ntlmssp.negotiateseal",
2640 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SEAL,
2643 { &hf_ntlmssp_negotiate_flags_40,
2644 { "Negotiate Datagram", "ntlmssp.negotiatedatagram",
2645 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_DATAGRAM,
2648 { &hf_ntlmssp_negotiate_flags_80,
2649 { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey",
2650 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_LM_KEY,
2653 { &hf_ntlmssp_negotiate_flags_100,
2654 { "Negotiate 0x00000100", "ntlmssp.negotiate00000100",
2655 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00000100,
2658 { &hf_ntlmssp_negotiate_flags_200,
2659 { "Negotiate NTLM key", "ntlmssp.negotiatentlm",
2660 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NTLM,
2663 { &hf_ntlmssp_negotiate_flags_400,
2664 { "Negotiate NT Only", "ntlmssp.negotiatentonly",
2665 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NT_ONLY,
2668 { &hf_ntlmssp_negotiate_flags_800,
2669 { "Negotiate Anonymous", "ntlmssp.negotiateanonymous",
2670 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ANONYMOUS,
2673 { &hf_ntlmssp_negotiate_flags_1000,
2674 { "Negotiate OEM Domain Supplied", "ntlmssp.negotiateoemdomainsupplied",
2675 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED,
2678 { &hf_ntlmssp_negotiate_flags_2000,
2679 { "Negotiate OEM Workstation Supplied", "ntlmssp.negotiateoemworkstationsupplied",
2680 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED,
2683 { &hf_ntlmssp_negotiate_flags_4000,
2684 { "Negotiate 0x00004000", "ntlmssp.negotiate00004000",
2685 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00004000,
2688 { &hf_ntlmssp_negotiate_flags_8000,
2689 { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign",
2690 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ALWAYS_SIGN,
2693 { &hf_ntlmssp_negotiate_flags_10000,
2694 { "Target Type Domain", "ntlmssp.targettypedomain",
2695 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_DOMAIN,
2698 { &hf_ntlmssp_negotiate_flags_20000,
2699 { "Target Type Server", "ntlmssp.targettypeserver",
2700 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER,
2703 { &hf_ntlmssp_negotiate_flags_40000,
2704 { "Target Type Share", "ntlmssp.targettypeshare",
2705 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SHARE,
2709 /* Negotiate Flags */
2710 { &hf_ntlmssp_negotiate_flags_80000,
2711 { "Negotiate Extended Security", "ntlmssp.negotiatentlm2",
2712 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SECURITY,
2715 { &hf_ntlmssp_negotiate_flags_100000,
2716 { "Negotiate Identify", "ntlmssp.negotiateidentify",
2717 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_IDENTIFY,
2720 { &hf_ntlmssp_negotiate_flags_200000,
2721 { "Negotiate 0x00200000", "ntlmssp.negotiatent00200000",
2722 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_00200000,
2725 { &hf_ntlmssp_negotiate_flags_400000,
2726 { "Request Non-NT Session", "ntlmssp.requestnonntsession",
2727 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_NON_NT_SESSION,
2730 { &hf_ntlmssp_negotiate_flags_800000,
2731 { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo",
2732 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_TARGET_INFO,
2735 { &hf_ntlmssp_negotiate_flags_1000000,
2736 { "Negotiate 0x01000000", "ntlmssp.negotiatent01000000",
2737 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_01000000,
2740 { &hf_ntlmssp_negotiate_flags_2000000,
2741 { "Negotiate Version", "ntlmssp.negotiateversion",
2742 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_VERSION,
2745 { &hf_ntlmssp_negotiate_flags_4000000,
2746 { "Negotiate 0x04000000", "ntlmssp.negotiatent04000000",
2747 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_04000000,
2750 { &hf_ntlmssp_negotiate_flags_8000000,
2751 { "Negotiate 0x08000000", "ntlmssp.negotiatent08000000",
2752 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_08000000,
2755 { &hf_ntlmssp_negotiate_flags_10000000,
2756 { "Negotiate 0x10000000", "ntlmssp.negotiatent10000000",
2757 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_10000000,
2760 { &hf_ntlmssp_negotiate_flags_20000000,
2761 { "Negotiate 128", "ntlmssp.negotiate128",
2762 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_128,
2763 "128-bit encryption is supported", HFILL }
2765 { &hf_ntlmssp_negotiate_flags_40000000,
2766 { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch",
2767 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_KEY_EXCH,
2770 { &hf_ntlmssp_negotiate_flags_80000000,
2771 { "Negotiate 56", "ntlmssp.negotiate56",
2772 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_56,
2773 "56-bit encryption is supported", HFILL }
2776 { &hf_ntlmssp_negotiate_workstation_strlen,
2777 { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen",
2778 FT_UINT16, BASE_DEC, NULL, 0x0,
2783 { &hf_ntlmssp_negotiate_workstation_maxlen,
2784 { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen",
2785 FT_UINT16, BASE_DEC, NULL, 0x0,
2790 { &hf_ntlmssp_negotiate_workstation_buffer,
2791 { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer",
2792 FT_UINT32, BASE_HEX, NULL, 0x0,
2796 { &hf_ntlmssp_negotiate_workstation,
2797 { "Calling workstation name", "ntlmssp.negotiate.callingworkstation",
2798 FT_STRING, BASE_NONE, NULL, 0x0,
2802 { &hf_ntlmssp_negotiate_domain_strlen,
2803 { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen",
2804 FT_UINT16, BASE_DEC, NULL, 0x0,
2809 { &hf_ntlmssp_negotiate_domain_maxlen,
2810 { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen",
2811 FT_UINT16, BASE_DEC, NULL, 0x0,
2816 { &hf_ntlmssp_negotiate_domain_buffer,
2817 { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer",
2818 FT_UINT32, BASE_HEX, NULL, 0x0,
2822 { &hf_ntlmssp_negotiate_domain,
2823 { "Calling workstation domain", "ntlmssp.negotiate.domain",
2824 FT_STRING, BASE_NONE, NULL, 0x0,
2827 { &hf_ntlmssp_ntlm_client_challenge,
2828 { "LMv2 Client Challenge", "ntlmssp.ntlmclientchallenge",
2829 FT_BYTES, BASE_NONE, NULL, 0x0,
2830 "The 8-byte LMv2 challenge message generated by the client", HFILL }
2832 { &hf_ntlmssp_ntlm_server_challenge,
2833 { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge",
2834 FT_BYTES, BASE_NONE, NULL, 0x0,
2837 { &hf_ntlmssp_reserved,
2838 { "Reserved", "ntlmssp.reserved",
2839 FT_BYTES, BASE_NONE, NULL, 0x0,
2843 { &hf_ntlmssp_challenge_target_name,
2844 { "Target Name", "ntlmssp.challenge.target_name",
2845 FT_STRING, BASE_NONE, NULL, 0x0,
2848 { &hf_ntlmssp_auth_domain,
2849 { "Domain name", "ntlmssp.auth.domain",
2850 FT_STRING, BASE_NONE, NULL, 0x0,
2853 { &hf_ntlmssp_auth_username,
2854 { "User name", "ntlmssp.auth.username",
2855 FT_STRING, BASE_NONE, NULL, 0x0,
2858 { &hf_ntlmssp_auth_hostname,
2859 { "Host name", "ntlmssp.auth.hostname",
2860 FT_STRING, BASE_NONE, NULL, 0x0,
2863 { &hf_ntlmssp_auth_lmresponse,
2864 { "Lan Manager Response", "ntlmssp.auth.lmresponse",
2865 FT_BYTES, BASE_NONE, NULL, 0x0,
2868 { &hf_ntlmssp_auth_ntresponse,
2869 { "NTLM Response", "ntlmssp.auth.ntresponse",
2870 FT_BYTES, BASE_NONE, NULL, 0x0,
2873 { &hf_ntlmssp_auth_sesskey,
2874 { "Session Key", "ntlmssp.auth.sesskey",
2875 FT_BYTES, BASE_NONE, NULL, 0x0,
2878 { &hf_ntlmssp_string_len,
2879 { "Length", "ntlmssp.string.length",
2880 FT_UINT16, BASE_DEC, NULL, 0x0,
2883 { &hf_ntlmssp_string_maxlen,
2884 { "Maxlen", "ntlmssp.string.maxlen",
2885 FT_UINT16, BASE_DEC, NULL, 0x0,
2888 { &hf_ntlmssp_string_offset,
2889 { "Offset", "ntlmssp.string.offset",
2890 FT_UINT32, BASE_DEC, NULL, 0x0,
2893 { &hf_ntlmssp_blob_len,
2894 { "Length", "ntlmssp.blob.length",
2895 FT_UINT16, BASE_DEC, NULL, 0x0,
2898 { &hf_ntlmssp_blob_maxlen,
2899 { "Maxlen", "ntlmssp.blob.maxlen",
2900 FT_UINT16, BASE_DEC, NULL, 0x0,
2903 { &hf_ntlmssp_blob_offset,
2904 { "Offset", "ntlmssp.blob.offset",
2905 FT_UINT32, BASE_DEC, NULL, 0x0,
2908 { &hf_ntlmssp_version,
2909 { "Version", "ntlmssp.version",
2910 FT_NONE, BASE_NONE, NULL, 0x0,
2913 { &hf_ntlmssp_version_major,
2914 { "Major Version", "ntlmssp.version.major",
2915 FT_UINT8, BASE_DEC, NULL, 0x0,
2918 { &hf_ntlmssp_version_minor,
2919 { "Minor Version", "ntlmssp.version.minor",
2920 FT_UINT8, BASE_DEC, NULL, 0x0,
2923 { &hf_ntlmssp_version_build_number,
2924 { "Build Number", "ntlmssp.version.build_number",
2925 FT_UINT16, BASE_DEC, NULL, 0x0,
2928 { &hf_ntlmssp_version_ntlm_current_revision,
2929 { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision",
2930 FT_UINT8, BASE_DEC, NULL, 0x0,
2935 { &hf_ntlmssp_challenge_target_info,
2936 { "Target Info", "ntlmssp.challenge.target_info",
2937 FT_NONE, BASE_NONE, NULL, 0x0,
2940 { &hf_ntlmssp_challenge_target_info_len,
2941 { "Length", "ntlmssp.challenge.target_info.length",
2942 FT_UINT16, BASE_DEC, NULL, 0x0,
2945 { &hf_ntlmssp_challenge_target_info_maxlen,
2946 { "Maxlen", "ntlmssp.challenge.target_info.maxlen",
2947 FT_UINT16, BASE_DEC, NULL, 0x0,
2950 { &hf_ntlmssp_challenge_target_info_offset,
2951 { "Offset", "ntlmssp.challenge.target_info.offset",
2952 FT_UINT32, BASE_DEC, NULL, 0x0,
2956 { &hf_ntlmssp_challenge_target_info_item_type,
2957 { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type",
2958 FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ntlm_name_types_ext, 0x0,
2961 { &hf_ntlmssp_challenge_target_info_item_len,
2962 { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length",
2963 FT_UINT16, BASE_DEC, NULL, 0x0,
2967 { &hf_ntlmssp_challenge_target_info_end,
2968 { "List End", "ntlmssp.challenge.target_info.end",
2969 FT_NONE, BASE_NONE, NULL, 0x0,
2972 { &hf_ntlmssp_challenge_target_info_nb_computer_name,
2973 { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name",
2974 FT_STRING, BASE_NONE, NULL, 0x0,
2975 "Server NetBIOS Computer Name", HFILL }
2977 { &hf_ntlmssp_challenge_target_info_nb_domain_name,
2978 { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name",
2979 FT_STRING, BASE_NONE, NULL, 0x0,
2980 "Server NetBIOS Domain Name", HFILL }
2982 { &hf_ntlmssp_challenge_target_info_dns_computer_name,
2983 { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name",
2984 FT_STRING, BASE_NONE, NULL, 0x0,
2987 { &hf_ntlmssp_challenge_target_info_dns_domain_name,
2988 { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name",
2989 FT_STRING, BASE_NONE, NULL, 0x0,
2992 { &hf_ntlmssp_challenge_target_info_dns_tree_name,
2993 { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name",
2994 FT_STRING, BASE_NONE, NULL, 0x0,
2997 { &hf_ntlmssp_challenge_target_info_flags,
2998 { "Flags", "ntlmssp.challenge.target_info.flags",
2999 FT_UINT32, BASE_HEX, NULL, 0x0,
3002 { &hf_ntlmssp_challenge_target_info_timestamp,
3003 { "Timestamp", "ntlmssp.challenge.target_info.timestamp",
3004 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
3007 { &hf_ntlmssp_challenge_target_info_restrictions,
3008 { "Restrictions", "ntlmssp.challenge.target_info.restrictions",
3009 FT_BYTES, BASE_NONE, NULL, 0,
3012 { &hf_ntlmssp_challenge_target_info_target_name,
3013 { "Target Name", "ntlmssp.challenge.target_info.target_name",
3014 FT_STRING, BASE_NONE, NULL, 0x0,
3017 { &hf_ntlmssp_challenge_target_info_channel_bindings,
3018 { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings",
3019 FT_BYTES, BASE_NONE, NULL, 0x0,
3023 { &hf_ntlmssp_ntlmv2_response_item_type,
3024 { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type",
3025 FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ntlm_name_types_ext, 0x0,
3028 { &hf_ntlmssp_ntlmv2_response_item_len,
3029 { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length",
3030 FT_UINT16, BASE_DEC, NULL, 0x0,
3034 { &hf_ntlmssp_ntlmv2_response_end,
3035 { "List End", "ntlmssp.ntlmv2_response.end",
3036 FT_NONE, BASE_NONE, NULL, 0x0,
3039 { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
3040 { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name",
3041 FT_STRING, BASE_NONE, NULL, 0x0,
3042 "Server NetBIOS Computer Name", HFILL }
3044 { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
3045 { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name",
3046 FT_STRING, BASE_NONE, NULL, 0x0,
3047 "Server NetBIOS Domain Name", HFILL }
3049 { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
3050 { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name",
3051 FT_STRING, BASE_NONE, NULL, 0x0,
3054 { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
3055 { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name",
3056 FT_STRING, BASE_NONE, NULL, 0x0,
3059 { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
3060 { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name",
3061 FT_STRING, BASE_NONE, NULL, 0x0,
3064 { &hf_ntlmssp_ntlmv2_response_flags,
3065 { "Flags", "ntlmssp.ntlmv2_response.flags",
3066 FT_UINT32, BASE_HEX, NULL, 0x0,
3069 { &hf_ntlmssp_ntlmv2_response_timestamp,
3070 { "Timestamp", "ntlmssp.ntlmv2_response.timestamp",
3071 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
3074 { &hf_ntlmssp_ntlmv2_response_restrictions,
3075 { "Restrictions", "ntlmssp.ntlmv2_response.restrictions",
3076 FT_BYTES, BASE_NONE, NULL, 0,
3079 { &hf_ntlmssp_ntlmv2_response_target_name,
3080 { "Target Name", "ntlmssp.ntlmv2_response.target_name",
3081 FT_STRING, BASE_NONE, NULL, 0x0,
3084 { &hf_ntlmssp_ntlmv2_response_channel_bindings,
3085 { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings",
3086 FT_BYTES, BASE_NONE, NULL, 0x0,
3090 { &hf_ntlmssp_message_integrity_code,
3091 { "MIC", "ntlmssp.authenticate.mic",
3092 FT_BYTES, BASE_NONE, NULL, 0x0,
3093 "Message Integrity Code", HFILL}
3096 { "NTLMSSP Verifier", "ntlmssp.verf",
3097 FT_NONE, BASE_NONE, NULL, 0x0,
3100 { &hf_ntlmssp_verf_vers,
3101 { "Version Number", "ntlmssp.verf.vers",
3102 FT_UINT32, BASE_DEC, NULL, 0x0,
3105 { &hf_ntlmssp_verf_body,
3106 { "Verifier Body", "ntlmssp.verf.body",
3107 FT_BYTES, BASE_NONE, NULL, 0x0,
3111 { &hf_ntlmssp_decrypted_payload,
3112 { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload",
3113 FT_BYTES, BASE_NONE, NULL, 0x0,
3117 { &hf_ntlmssp_verf_randompad,
3118 { "Random Pad", "ntlmssp.verf.randompad",
3119 FT_UINT32, BASE_HEX, NULL, 0x0,
3122 { &hf_ntlmssp_verf_crc32,
3123 { "Verifier CRC32", "ntlmssp.verf.crc32",
3124 FT_UINT32, BASE_HEX, NULL, 0x0,
3127 { &hf_ntlmssp_verf_hmacmd5,
3128 { "HMAC MD5", "ntlmssp.verf.hmacmd5",
3129 FT_BYTES, BASE_NONE, NULL, 0x0,
3132 { &hf_ntlmssp_verf_sequence,
3133 { "Sequence", "ntlmssp.verf.sequence",
3134 FT_BYTES, BASE_NONE, NULL, 0x0,
3138 { &hf_ntlmssp_ntlmv2_response,
3139 { "NTLMv2 Response", "ntlmssp.ntlmv2_response",
3140 FT_BYTES, BASE_NONE, NULL, 0x0,
3143 { &hf_ntlmssp_ntlmv2_response_ntproofstr,
3144 { "NTProofStr", "ntlmssp.ntlmv2_response.ntproofstr",
3145 FT_BYTES, BASE_NONE, NULL, 0x0,
3146 "The HMAC-MD5 of the challenge", HFILL }
3148 { &hf_ntlmssp_ntlmv2_response_rversion,
3149 { "Response Version", "ntlmssp.ntlmv2_response.rversion",
3150 FT_UINT8, BASE_DEC, NULL, 0x0,
3151 "The 1-byte response version, currently set to 1", HFILL }
3153 { &hf_ntlmssp_ntlmv2_response_hirversion,
3154 { "Hi Response Version", "ntlmssp.ntlmv2_response.hirversion",
3155 FT_UINT8, BASE_DEC, NULL, 0x0,
3156 "The 1-byte highest response version understood by the client, currently set to 1", HFILL }
3158 { &hf_ntlmssp_ntlmv2_response_z,
3159 { "Z", "ntlmssp.ntlmv2_response.z",
3160 FT_BYTES, BASE_NONE, NULL, 0x0,
3161 "byte array of zero bytes", HFILL }
3163 { &hf_ntlmssp_ntlmv2_response_pad,
3164 { "padding", "ntlmssp.ntlmv2_response.pad",
3165 FT_BYTES, BASE_NONE, NULL, 0x0,
3168 { &hf_ntlmssp_ntlmv2_response_time,
3169 { "Time", "ntlmssp.ntlmv2_response.time",
3170 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
3171 "The 8-byte little-endian time in UTC", HFILL }
3173 { &hf_ntlmssp_ntlmv2_response_chal,
3174 { "NTLMv2 Client Challenge", "ntlmssp.ntlmv2_response.chal",
3175 FT_BYTES, BASE_NONE, NULL, 0x0,
3176 "The 8-byte NTLMv2 challenge message generated by the client", HFILL }
3181 static gint *ett[] = {
3183 &ett_ntlmssp_negotiate_flags,
3184 &ett_ntlmssp_string,
3186 &ett_ntlmssp_version,
3187 &ett_ntlmssp_challenge_target_info,
3188 &ett_ntlmssp_challenge_target_info_item,
3189 &ett_ntlmssp_ntlmv2_response,
3190 &ett_ntlmssp_ntlmv2_response_item,
3192 static ei_register_info ei[] = {
3193 { &ei_ntlmssp_v2_key_too_long, { "ntlmssp.v2_key_too_long", PI_UNDECODED, PI_WARN, "NTLM v2 key is too long", EXPFILL }},
3194 { &ei_ntlmssp_blob_len_too_long, { "ntlmssp.blob.length.too_long", PI_UNDECODED, PI_WARN, "Session blob length too long", EXPFILL }},
3195 { &ei_ntlmssp_target_info_attr, { "ntlmssp.target_info_attr.unknown", PI_UNDECODED, PI_WARN, "unknown NTLMSSP Target Info Attribute", EXPFILL }},
3196 { &ei_ntlmssp_message_type, { "ntlmssp.messagetype.unknown", PI_PROTOCOL, PI_WARN, "Unrecognized NTLMSSP Message", EXPFILL }},
3198 module_t *ntlmssp_module;
3199 expert_module_t* expert_ntlmssp;
3201 proto_ntlmssp = proto_register_protocol (
3202 "NTLM Secure Service Provider", /* name */
3203 "NTLMSSP", /* short name */
3204 "ntlmssp" /* abbrev */
3206 proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
3207 proto_register_subtree_array (ett, array_length (ett));
3208 expert_ntlmssp = expert_register_protocol(proto_ntlmssp);
3209 expert_register_field_array(expert_ntlmssp, ei, array_length(ei));
3210 register_init_routine(&ntlmssp_init_protocol);
3211 register_cleanup_routine(&ntlmssp_cleanup_protocol);
3213 ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
3215 prefs_register_string_preference(ntlmssp_module, "nt_password",
3217 "NT Password (used to decrypt payloads)",
3220 ntlmssp_handle = register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
3221 ntlmssp_wrap_handle = register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
3222 register_dissector("ntlmssp_data_only", dissect_ntlmssp_payload_only, proto_ntlmssp);
3223 register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
3227 proto_reg_handoff_ntlmssp(void)
3229 /* Register protocol with the GSS-API module */
3231 gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
3232 ntlmssp_handle, ntlmssp_wrap_handle,
3233 "NTLMSSP - Microsoft NTLM Security Support Provider");
3235 /* Register authenticated pipe dissector */
3238 * XXX - the verifiers here seem to have a version of 1 and a body of all
3241 * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
3242 * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
3243 * any other levels here?
3245 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
3246 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3249 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
3250 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3253 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
3254 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3257 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
3258 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3260 ntlmssp_tap = register_tap("ntlmssp");
3262 heur_dissector_add("credssp", dissect_ntlmssp_heur, "NTLMSSP over CredSSP", "ntlmssp_credssp", proto_ntlmssp, HEURISTIC_ENABLE);
3267 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3272 * indent-tabs-mode: nil
3275 * vi: set shiftwidth=2 tabstop=8 expandtab:
3276 * :indentSize=2:tabSize=8:noTabs=true: