Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ntlmssp.c
blob147a31048eaaa9f0a6ae4655385f0c5a11a44267
1 /* packet-ntlmssp.c
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
15 #define WS_LOG_DOMAIN "packet-ntlmssp"
16 #include "config.h"
17 #include <wireshark.h>
18 #include <string.h>
20 #include <epan/packet.h>
21 #include <epan/exceptions.h>
22 #include <epan/asn1.h>
23 #include <epan/prefs.h>
24 #include <epan/tap.h>
25 #include <epan/expert.h>
26 #include <epan/show_exception.h>
27 #include <epan/proto_data.h>
28 #include <epan/tfs.h>
30 #include <wsutil/array.h>
31 #include <wsutil/wsgcrypt.h>
32 #include <wsutil/crc32.h>
33 #include <wsutil/str_util.h>
35 #include "packet-windows-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"
45 * See
47 * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/
49 * for Microsoft's MS-NLMP, NT LAN Manager (NTLM) Authentication Protocol
50 * Specification.
52 * See also
54 * http://davenport.sourceforge.net/ntlm.html
56 * which indicates that, in practice, some fields specified by MS-NLMP
57 * may be absent; this has been seen in some captures.
60 void proto_register_ntlmssp(void);
61 void proto_reg_handoff_ntlmssp(void);
63 static int ntlmssp_tap;
65 #define CLIENT_SIGN_TEXT "session key to client-to-server signing key magic constant"
66 #define CLIENT_SEAL_TEXT "session key to client-to-server sealing key magic constant"
67 #define SERVER_SIGN_TEXT "session key to server-to-client signing key magic constant"
68 #define SERVER_SEAL_TEXT "session key to server-to-client sealing key magic constant"
70 static const value_string ntlmssp_message_types[] = {
71 { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
72 { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
73 { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
74 { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
75 { 0, NULL }
78 #define NTLMSSP_EK_IS_NT4HASH(ek) \
79 (ek->fd_num == -1 && ek->keytype == 23 && ek->keylength == NTLMSSP_KEY_LEN)
81 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";
82 static GHashTable* hash_packet;
85 * NTLMSSP negotiation flags
86 * Taken from Samba
88 * See also the davenport.sourceforge.net document cited above,
89 * although that document says that:
91 * 0x00010000 is "Target Type Domain";
92 * 0x00020000 is "Target Type Server"
93 * 0x00040000 is "Target Type Share";
95 * and that 0x00100000, 0x00200000, and 0x00400000 are
96 * "Request Init Response", "Request Accept Response", and
97 * "Request Non-NT Session Key", rather than those values shifted
98 * right one having those interpretations.
100 * UPDATE: Further information obtained from [MS-NLMP] 2.2.2.5, added in comments
101 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832
103 #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001 // A
104 #define NTLMSSP_NEGOTIATE_OEM 0x00000002 // B
105 #define NTLMSSP_REQUEST_TARGET 0x00000004 // C
106 #define NTLMSSP_UNUSED_00000008 0x00000008 // r10
107 #define NTLMSSP_NEGOTIATE_SIGN 0x00000010 // D
108 #define NTLMSSP_NEGOTIATE_SEAL 0x00000020 // E
109 #define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040 // F
110 #define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080 // G, "requests LAN Manager (LM) session key computation", aka NTLMv1
111 #define NTLMSSP_UNUSED_00000100 0x00000100 // r9
112 #define NTLMSSP_NEGOTIATE_NTLM 0x00000200 // H, "requests usage of the NTLM v1 session security protocol"
113 #define NTLMSSP_UNUSED_00000400 0x00000400 // r8
114 #define NTLMSSP_NEGOTIATE_ANONYMOUS 0x00000800 // J
115 #define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000 // K
116 #define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000 // L
117 #define NTLMSSP_UNUSED_00004000 0x00004000 // r7
118 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000 // M
119 #define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000 // N
120 #define NTLMSSP_TARGET_TYPE_SERVER 0x00020000 // O
121 #define NTLMSSP_UNUSED_00040000 0x00040000 // r6
122 #define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000 // P, "requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2"
123 #define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000 // Q
124 #define NTLMSSP_UNUSED_00200000 0x00200000 // r5
125 #define NTLMSSP_REQUEST_NON_NT_SESSION_KEY 0x00400000 // R, "requests the usage of the LMOWF"
126 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000 // S
127 #define NTLMSSP_UNUSED_01000000 0x01000000 // r4
128 #define NTLMSSP_NEGOTIATE_VERSION 0x02000000 // T
129 #define NTLMSSP_UNUSED_04000000 0x04000000 // r3
130 #define NTLMSSP_UNUSED_08000000 0x08000000 // r2
131 #define NTLMSSP_UNUSED_10000000 0x10000000 // r1
132 #define NTLMSSP_NEGOTIATE_128 0x20000000 // U
133 #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000 // V
134 #define NTLMSSP_NEGOTIATE_56 0x80000000 // W
136 static int proto_ntlmssp;
137 static int hf_ntlmssp_auth;
138 static int hf_ntlmssp_message_type;
139 static int hf_ntlmssp_negotiate_flags;
140 static int hf_ntlmssp_negotiate_flags_01;
141 static int hf_ntlmssp_negotiate_flags_02;
142 static int hf_ntlmssp_negotiate_flags_04;
143 static int hf_ntlmssp_negotiate_flags_08;
144 static int hf_ntlmssp_negotiate_flags_10;
145 static int hf_ntlmssp_negotiate_flags_20;
146 static int hf_ntlmssp_negotiate_flags_40;
147 static int hf_ntlmssp_negotiate_flags_80;
148 static int hf_ntlmssp_negotiate_flags_100;
149 static int hf_ntlmssp_negotiate_flags_200;
150 static int hf_ntlmssp_negotiate_flags_400;
151 static int hf_ntlmssp_negotiate_flags_800;
152 static int hf_ntlmssp_negotiate_flags_1000;
153 static int hf_ntlmssp_negotiate_flags_2000;
154 static int hf_ntlmssp_negotiate_flags_4000;
155 static int hf_ntlmssp_negotiate_flags_8000;
156 static int hf_ntlmssp_negotiate_flags_10000;
157 static int hf_ntlmssp_negotiate_flags_20000;
158 static int hf_ntlmssp_negotiate_flags_40000;
159 static int hf_ntlmssp_negotiate_flags_80000;
160 static int hf_ntlmssp_negotiate_flags_100000;
161 static int hf_ntlmssp_negotiate_flags_200000;
162 static int hf_ntlmssp_negotiate_flags_400000;
163 static int hf_ntlmssp_negotiate_flags_800000;
164 static int hf_ntlmssp_negotiate_flags_1000000;
165 static int hf_ntlmssp_negotiate_flags_2000000;
166 static int hf_ntlmssp_negotiate_flags_4000000;
167 static int hf_ntlmssp_negotiate_flags_8000000;
168 static int hf_ntlmssp_negotiate_flags_10000000;
169 static int hf_ntlmssp_negotiate_flags_20000000;
170 static int hf_ntlmssp_negotiate_flags_40000000;
171 static int hf_ntlmssp_negotiate_flags_80000000;
172 /* static int hf_ntlmssp_negotiate_workstation_strlen; */
173 /* static int hf_ntlmssp_negotiate_workstation_maxlen; */
174 /* static int hf_ntlmssp_negotiate_workstation_buffer; */
175 static int hf_ntlmssp_negotiate_workstation;
176 /* static int hf_ntlmssp_negotiate_domain_strlen; */
177 /* static int hf_ntlmssp_negotiate_domain_maxlen; */
178 /* static int hf_ntlmssp_negotiate_domain_buffer; */
179 static int hf_ntlmssp_negotiate_domain;
180 static int hf_ntlmssp_ntlm_server_challenge;
181 static int hf_ntlmssp_ntlm_client_challenge;
182 static int hf_ntlmssp_reserved;
183 static int hf_ntlmssp_challenge_target_name;
184 static int hf_ntlmssp_auth_username;
185 static int hf_ntlmssp_auth_domain;
186 static int hf_ntlmssp_auth_hostname;
187 static int hf_ntlmssp_auth_lmresponse;
188 static int hf_ntlmssp_auth_ntresponse;
189 static int hf_ntlmssp_auth_sesskey;
190 static int hf_ntlmssp_string_len;
191 static int hf_ntlmssp_string_maxlen;
192 static int hf_ntlmssp_string_offset;
193 static int hf_ntlmssp_blob_len;
194 static int hf_ntlmssp_blob_maxlen;
195 static int hf_ntlmssp_blob_offset;
196 static int hf_ntlmssp_version;
197 static int hf_ntlmssp_version_major;
198 static int hf_ntlmssp_version_minor;
199 static int hf_ntlmssp_version_build_number;
200 static int hf_ntlmssp_version_ntlm_current_revision;
202 static int hf_ntlmssp_challenge_target_info;
203 static int hf_ntlmssp_challenge_target_info_len;
204 static int hf_ntlmssp_challenge_target_info_maxlen;
205 static int hf_ntlmssp_challenge_target_info_offset;
207 static int hf_ntlmssp_challenge_target_info_item_type;
208 static int hf_ntlmssp_challenge_target_info_item_len;
210 static int hf_ntlmssp_challenge_target_info_end;
211 static int hf_ntlmssp_challenge_target_info_nb_computer_name;
212 static int hf_ntlmssp_challenge_target_info_nb_domain_name;
213 static int hf_ntlmssp_challenge_target_info_dns_computer_name;
214 static int hf_ntlmssp_challenge_target_info_dns_domain_name;
215 static int hf_ntlmssp_challenge_target_info_dns_tree_name;
216 static int hf_ntlmssp_challenge_target_info_flags;
217 static int hf_ntlmssp_challenge_target_info_timestamp;
218 static int hf_ntlmssp_challenge_target_info_restrictions;
219 static int hf_ntlmssp_challenge_target_info_target_name;
220 static int hf_ntlmssp_challenge_target_info_channel_bindings;
222 static int hf_ntlmssp_ntlmv2_response_item_type;
223 static int hf_ntlmssp_ntlmv2_response_item_len;
225 static int hf_ntlmssp_ntlmv2_response_end;
226 static int hf_ntlmssp_ntlmv2_response_nb_computer_name;
227 static int hf_ntlmssp_ntlmv2_response_nb_domain_name;
228 static int hf_ntlmssp_ntlmv2_response_dns_computer_name;
229 static int hf_ntlmssp_ntlmv2_response_dns_domain_name;
230 static int hf_ntlmssp_ntlmv2_response_dns_tree_name;
231 static int hf_ntlmssp_ntlmv2_response_flags;
232 static int hf_ntlmssp_ntlmv2_response_timestamp;
233 static int hf_ntlmssp_ntlmv2_response_restrictions;
234 static int hf_ntlmssp_ntlmv2_response_target_name;
235 static int hf_ntlmssp_ntlmv2_response_channel_bindings;
237 static int hf_ntlmssp_message_integrity_code;
238 static int hf_ntlmssp_verf;
239 static int hf_ntlmssp_verf_vers;
240 static int hf_ntlmssp_verf_body;
241 static int hf_ntlmssp_verf_randompad;
242 static int hf_ntlmssp_verf_hmacmd5;
243 static int hf_ntlmssp_verf_crc32;
244 static int hf_ntlmssp_verf_sequence;
245 /* static int hf_ntlmssp_decrypted_payload; */
247 static int hf_ntlmssp_ntlmv2_response;
248 static int hf_ntlmssp_ntlmv2_response_ntproofstr;
249 static int hf_ntlmssp_ntlmv2_response_rversion;
250 static int hf_ntlmssp_ntlmv2_response_hirversion;
251 static int hf_ntlmssp_ntlmv2_response_z;
252 static int hf_ntlmssp_ntlmv2_response_pad;
253 static int hf_ntlmssp_ntlmv2_response_time;
254 static int hf_ntlmssp_ntlmv2_response_chal;
256 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL;
257 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Version;
258 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Flags;
259 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_LM_PRESENT;
260 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_NT_PRESENT;
261 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_REMOVED;
262 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_CREDKEY_PRESENT;
263 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_SHA_PRESENT;
264 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKey;
265 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKeyType;
266 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCredsSize;
267 static int hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCreds;
269 static int ett_ntlmssp;
270 static int ett_ntlmssp_negotiate_flags;
271 static int ett_ntlmssp_string;
272 static int ett_ntlmssp_blob;
273 static int ett_ntlmssp_version;
274 static int ett_ntlmssp_challenge_target_info;
275 static int ett_ntlmssp_challenge_target_info_item;
276 static int ett_ntlmssp_ntlmv2_response;
277 static int ett_ntlmssp_ntlmv2_response_item;
278 static int ett_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL;
280 static expert_field ei_ntlmssp_v2_key_too_long;
281 static expert_field ei_ntlmssp_blob_len_too_long;
282 static expert_field ei_ntlmssp_target_info_attr;
283 static expert_field ei_ntlmssp_target_info_invalid;
284 static expert_field ei_ntlmssp_message_type;
285 static expert_field ei_ntlmssp_auth_nthash;
286 static expert_field ei_ntlmssp_sessionbasekey;
287 static expert_field ei_ntlmssp_sessionkey;
289 static dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
291 /* Configuration variables */
292 static const char *ntlmssp_option_nt_password;
294 #define NTLMSSP_CONV_INFO_KEY 0
295 /* Used in the conversation function */
296 typedef struct _ntlmssp_info {
297 uint32_t flags;
298 bool saw_challenge;
299 gcry_cipher_hd_t rc4_handle_client;
300 gcry_cipher_hd_t rc4_handle_server;
301 uint8_t sign_key_client[NTLMSSP_KEY_LEN];
302 uint8_t sign_key_server[NTLMSSP_KEY_LEN];
303 uint32_t server_dest_port;
304 unsigned char server_challenge[8];
305 bool rc4_state_initialized;
306 ntlmssp_blob ntlm_response;
307 ntlmssp_blob lm_response;
308 } ntlmssp_info;
310 #define NTLMSSP_PACKET_INFO_KEY 1
311 /* If this struct exists in the payload_decrypt, then we have already
312 decrypted it once */
313 typedef struct _ntlmssp_packet_info {
314 uint8_t *decrypted_payload;
315 uint8_t payload_len;
316 uint8_t verifier[NTLMSSP_KEY_LEN];
317 bool payload_decrypted;
318 bool verifier_decrypted;
319 int verifier_offset;
320 uint32_t verifier_block_length;
321 } ntlmssp_packet_info;
323 static int
324 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
327 * GSlist of decrypted payloads.
329 static GSList *decrypted_payloads;
331 #if 0
332 static int
333 LEBE_Convert(int value)
335 char a, b, c, d;
336 /* Get each byte */
337 a = value&0x000000FF;
338 b = (value&0x0000FF00) >> 8;
339 c = (value&0x00FF0000) >> 16;
340 d = (value&0xFF000000) >> 24;
341 return (a << 24) | (b << 16) | (c << 8) | d;
343 #endif
345 static bool
346 ntlmssp_sessions_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_)
348 ntlmssp_info * conv_ntlmssp_info = (ntlmssp_info *) user_data;
349 if (conv_ntlmssp_info->rc4_state_initialized) {
350 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
351 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
353 /* unregister this callback */
354 return false;
358 Perform a DES encryption with a 16-byte key and 8-byte data item.
359 It's in fact 3 susbsequent call to crypt_des_ecb with a 7-byte key.
360 Missing bytes for the key are replaced by 0;
361 Returns output in response, which is expected to be 24 bytes.
363 static int
364 crypt_des_ecb_long(uint8_t *response,
365 const uint8_t *key,
366 const uint8_t *data)
368 uint8_t pw21[21] = { 0 }; /* 21 bytes place for the needed key */
370 memcpy(pw21, key, 16);
372 memset(response, 0, 24);
373 crypt_des_ecb(response, data, pw21);
374 crypt_des_ecb(response + 8, data, pw21 + 7);
375 crypt_des_ecb(response + 16, data, pw21 + 14);
377 return 1;
381 Generate a challenge response, given an eight byte challenge and
382 either the NT or the Lan Manager password hash (16 bytes).
383 Returns output in response, which is expected to be 24 bytes.
385 static int
386 ntlmssp_generate_challenge_response(uint8_t *response,
387 const uint8_t *passhash,
388 const uint8_t *challenge)
390 uint8_t pw21[21]; /* Password hash padded to 21 bytes */
392 memset(pw21, 0x0, sizeof(pw21));
393 memcpy(pw21, passhash, 16);
395 memset(response, 0, 24);
397 crypt_des_ecb(response, challenge, pw21);
398 crypt_des_ecb(response + 8, challenge, pw21 + 7);
399 crypt_des_ecb(response + 16, challenge, pw21 + 14);
401 return 1;
405 /* Ultra simple ANSI to unicode converter, will only work for ascii password...*/
406 static void
407 ansi_to_unicode(const char* ansi, char* unicode)
409 size_t input_len;
410 size_t i;
412 input_len = strlen(ansi);
413 if (unicode != NULL) {
414 for (i = 0; i < (input_len); i++) {
415 unicode[i * 2] = ansi[i];
416 unicode[i * 2 + 1] = 0;
418 unicode[2 * input_len] = '\0';
422 /* This function generate the Key Exchange Key (KXKEY)
423 * Depending on the flags this key will either be used to encrypt the exported session key
424 * or will be used directly as exported session key.
425 * Exported session key is the key that will be used for sealing and signing communication
426 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d86303b5-b29e-4fb9-b119-77579c761370
429 static void
430 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)
432 uint8_t basekey[NTLMSSP_KEY_LEN];
433 uint8_t zeros[24] = { 0 };
435 memset(keyexchangekey, 0, NTLMSSP_KEY_LEN);
436 memset(basekey, 0, NTLMSSP_KEY_LEN);
437 /* sessionbasekey is either derived from lm_hash or from nt_hash depending on the key type negotiated */
438 memcpy(basekey, sessionbasekey, 8);
439 memset(basekey+8, 0xBD, 8);
440 if (flags&NTLMSSP_NEGOTIATE_LM_KEY) {
441 /*data, key*/
442 crypt_des_ecb(keyexchangekey, lm_challenge_response, basekey);
443 crypt_des_ecb(keyexchangekey+8, lm_challenge_response, basekey+7);
445 else {
446 if (flags&NTLMSSP_REQUEST_NON_NT_SESSION_KEY) {
447 /*People from samba tends to use the same function in this case than in the previous one but with 0 data
448 * it's not clear that it produce the good result
449 * memcpy(keyexchangekey, lm_hash, 8);
450 * Let's trust samba implementation it mights seem weird but they are more often right than the spec!
452 crypt_des_ecb(keyexchangekey, zeros, basekey);
453 crypt_des_ecb(keyexchangekey+8, zeros, basekey+7);
455 else {
456 /* it is stated page 65 of NTLM SSP spec: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d86303b5-b29e-4fb9-b119-77579c761370
457 * that sessionbasekey should be encrypted with hmac_md5 using the concat of both challenge when it's NTLM v1 + extended session security but it turns out to be wrong!
459 memcpy(keyexchangekey, sessionbasekey, NTLMSSP_KEY_LEN);
464 uint32_t
465 get_md4pass_list(wmem_allocator_t *pool, md4_pass** p_pass_list)
467 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
468 uint32_t nb_pass = 0;
469 enc_key_t *ek;
470 const char* password = ntlmssp_option_nt_password;
471 unsigned char nt_hash[NTLMSSP_KEY_LEN];
472 char password_unicode[256];
473 md4_pass* pass_list;
474 int i;
476 *p_pass_list = NULL;
477 read_keytab_file_from_preferences();
479 for (ek=enc_key_list; ek; ek=ek->next) {
480 if (NTLMSSP_EK_IS_NT4HASH(ek)) {
481 nb_pass++;
484 memset(password_unicode, 0, sizeof(password_unicode));
485 memset(nt_hash, 0, NTLMSSP_KEY_LEN);
486 /* Compute the NT hash of the provided password, even if empty */
487 if (strlen(password) < 129) {
488 int password_len;
489 nb_pass++;
490 password_len = (int)strlen(password);
491 ansi_to_unicode(password, password_unicode);
492 gcry_md_hash_buffer(GCRY_MD_MD4, nt_hash, password_unicode, password_len*2);
494 if (nb_pass == 0) {
495 /* Unable to calculate the session key without a valid password (128 chars or less) ......*/
496 return 0;
498 i = 0;
499 *p_pass_list = (md4_pass *)wmem_alloc0(pool, nb_pass*sizeof(md4_pass));
500 pass_list = *p_pass_list;
502 if (memcmp(nt_hash, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
503 memcpy(pass_list[i].md4, nt_hash, NTLMSSP_KEY_LEN);
504 snprintf(pass_list[i].key_origin, NTLMSSP_MAX_ORIG_LEN,
505 "<Global NT Password>");
506 i = 1;
508 for (ek=enc_key_list; ek; ek=ek->next) {
509 if (NTLMSSP_EK_IS_NT4HASH(ek)) {
510 memcpy(pass_list[i].md4, ek->keyvalue, NTLMSSP_KEY_LEN);
511 memcpy(pass_list[i].key_origin, ek->key_origin,
512 MIN(sizeof(pass_list[i].key_origin),sizeof(ek->key_origin)));
513 i++;
516 return nb_pass;
517 #else /* !(defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)) */
518 (void) pool;
519 *p_pass_list = NULL;
520 return 0;
521 #endif /* !(defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)) */
524 /* Create an NTLMSSP version 2 key
525 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
527 static void
528 create_ntlmssp_v2_key(const uint8_t *serverchallenge, const uint8_t *clientchallenge,
529 uint8_t *sessionkey , const uint8_t *encryptedsessionkey , int flags ,
530 const ntlmssp_blob *ntlm_response, const ntlmssp_blob *lm_response _U_, ntlmssp_header_t *ntlmssph,
531 packet_info *pinfo, proto_tree *ntlmssp_tree)
533 /* static const would be nicer, but -Werror=vla does not like it */
534 #define DOMAIN_NAME_BUF_SIZE 512
535 #define USER_BUF_SIZE 256
536 #define BUF_SIZE (DOMAIN_NAME_BUF_SIZE + USER_BUF_SIZE)
537 char domain_name_unicode[DOMAIN_NAME_BUF_SIZE];
538 char user_uppercase[USER_BUF_SIZE];
539 char buf[BUF_SIZE];
540 /*uint8_t md4[NTLMSSP_KEY_LEN];*/
541 unsigned char nt_hash[NTLMSSP_KEY_LEN];
542 unsigned char nt_proof[NTLMSSP_KEY_LEN];
543 unsigned char ntowfv2[NTLMSSP_KEY_LEN];
544 uint8_t sessionbasekey[NTLMSSP_KEY_LEN];
545 uint8_t keyexchangekey[NTLMSSP_KEY_LEN];
546 uint8_t lm_challenge_response[24];
547 uint32_t i;
548 uint32_t j;
549 gcry_cipher_hd_t rc4_handle;
550 size_t user_len;
551 size_t domain_len;
552 md4_pass *pass_list = NULL;
553 const md4_pass *used_md4 = NULL;
554 uint32_t nb_pass = 0;
555 bool found = false;
557 /* We are going to try password encrypted in keytab as well, it's an idea of Stefan Metzmacher <metze@samba.org>
558 * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
560 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
561 nb_pass = get_md4pass_list(pinfo->pool, &pass_list);
562 i = 0;
563 memset(user_uppercase, 0, USER_BUF_SIZE);
564 user_len = strlen(ntlmssph->acct_name);
565 if (user_len < USER_BUF_SIZE / 2) {
566 memset(buf, 0, BUF_SIZE);
567 ansi_to_unicode(ntlmssph->acct_name, buf);
568 for (j = 0; j < (2*user_len); j++) {
569 if (buf[j] != '\0') {
570 user_uppercase[j] = g_ascii_toupper(buf[j]);
574 else {
575 /* Unable to calculate the session not enough space in buffer, note this is unlikely to happen but ......*/
576 return;
578 domain_len = strlen(ntlmssph->domain_name);
579 if (domain_len < DOMAIN_NAME_BUF_SIZE / 2) {
580 ansi_to_unicode(ntlmssph->domain_name, domain_name_unicode);
582 else {
583 /* Unable to calculate the session not enough space in buffer, note this is unlikely to happen but ......*/
584 return;
586 while (i < nb_pass) {
587 ws_debug("Turn %d", i);
588 used_md4 = &pass_list[i];
589 memcpy(nt_hash, pass_list[i].md4, NTLMSSP_KEY_LEN);
590 ws_log_buffer(nt_hash, NTLMSSP_KEY_LEN, "Current NT hash");
591 i++;
592 /* NTOWFv2 computation */
593 memset(buf, 0, BUF_SIZE);
594 memcpy(buf, user_uppercase, user_len*2);
595 memcpy(buf+user_len*2, domain_name_unicode, domain_len*2);
596 if (ws_hmac_buffer(GCRY_MD_MD5, ntowfv2, buf, domain_len*2+user_len*2, nt_hash, NTLMSSP_KEY_LEN)) {
597 return;
599 ws_log_buffer(ntowfv2, NTLMSSP_KEY_LEN, "NTOWFv2");
601 /* LM response */
602 memset(buf, 0, BUF_SIZE);
603 memcpy(buf, serverchallenge, 8);
604 memcpy(buf+8, clientchallenge, 8);
605 if (ws_hmac_buffer(GCRY_MD_MD5, lm_challenge_response, buf, NTLMSSP_KEY_LEN, ntowfv2, NTLMSSP_KEY_LEN)) {
606 return;
608 memcpy(lm_challenge_response+NTLMSSP_KEY_LEN, clientchallenge, 8);
609 ws_log_buffer(lm_challenge_response, 24, "LM Response");
611 /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
612 memset(buf, 0, BUF_SIZE);
613 memcpy(buf, serverchallenge, 8);
614 memcpy(buf+8, ntlm_response->contents+NTLMSSP_KEY_LEN, MIN(BUF_SIZE - 8, ntlm_response->length-NTLMSSP_KEY_LEN));
615 if (ws_hmac_buffer(GCRY_MD_MD5, nt_proof, buf, ntlm_response->length-8, ntowfv2, NTLMSSP_KEY_LEN)) {
616 return;
618 ws_log_buffer(nt_proof, NTLMSSP_KEY_LEN, "NT proof");
619 if (!memcmp(nt_proof, ntlm_response->contents, NTLMSSP_KEY_LEN)) {
620 found = true;
621 break;
624 if (!found) {
625 return;
628 if (ws_hmac_buffer(GCRY_MD_MD5, sessionbasekey, nt_proof, NTLMSSP_KEY_LEN, ntowfv2, NTLMSSP_KEY_LEN)) {
629 return;
632 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
633 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
634 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
636 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
637 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
638 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
639 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
641 gcry_cipher_close(rc4_handle);
644 else
646 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
649 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
651 if (used_md4 == NULL) {
652 return;
654 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
655 &ei_ntlmssp_auth_nthash,
656 "NTLMv2 authenticated using %s (%02x%02x%02x%02x...)",
657 used_md4->key_origin,
658 used_md4->md4[0] & 0xFF, used_md4->md4[1] & 0xFF,
659 used_md4->md4[2] & 0xFF, used_md4->md4[3] & 0xFF);
660 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
661 &ei_ntlmssp_sessionbasekey,
662 "NTLMv2 BaseSessionKey ("
663 "%02x%02x%02x%02x"
664 "%02x%02x%02x%02x"
665 "%02x%02x%02x%02x"
666 "%02x%02x%02x%02x"
667 ")",
668 sessionbasekey[0] & 0xFF, sessionbasekey[1] & 0xFF,
669 sessionbasekey[2] & 0xFF, sessionbasekey[3] & 0xFF,
670 sessionbasekey[4] & 0xFF, sessionbasekey[5] & 0xFF,
671 sessionbasekey[6] & 0xFF, sessionbasekey[7] & 0xFF,
672 sessionbasekey[8] & 0xFF, sessionbasekey[9] & 0xFF,
673 sessionbasekey[10] & 0xFF, sessionbasekey[11] & 0xFF,
674 sessionbasekey[12] & 0xFF, sessionbasekey[13] & 0xFF,
675 sessionbasekey[14] & 0xFF, sessionbasekey[15] & 0xFF);
676 if (memcmp(sessionbasekey, sessionkey, NTLMSSP_KEY_LEN) == 0) {
677 return;
679 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
680 &ei_ntlmssp_sessionkey,
681 "NTLMSSP SessionKey ("
682 "%02x%02x%02x%02x"
683 "%02x%02x%02x%02x"
684 "%02x%02x%02x%02x"
685 "%02x%02x%02x%02x"
686 ")",
687 sessionkey[0] & 0xFF, sessionkey[1] & 0xFF,
688 sessionkey[2] & 0xFF, sessionkey[3] & 0xFF,
689 sessionkey[4] & 0xFF, sessionkey[5] & 0xFF,
690 sessionkey[6] & 0xFF, sessionkey[7] & 0xFF,
691 sessionkey[8] & 0xFF, sessionkey[9] & 0xFF,
692 sessionkey[10] & 0xFF, sessionkey[11] & 0xFF,
693 sessionkey[12] & 0xFF, sessionkey[13] & 0xFF,
694 sessionkey[14] & 0xFF, sessionkey[15] & 0xFF);
697 /* Create an NTLMSSP version 1 key
698 * That is more complicated logic and methods and user challenge as well.
699 * password points to the ANSI password to encrypt, challenge points to
700 * the 8 octet challenge string
701 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
703 static void
704 create_ntlmssp_v1_key(const uint8_t *serverchallenge, const uint8_t *clientchallenge,
705 uint8_t *sessionkey, const uint8_t *encryptedsessionkey, int flags,
706 const uint8_t *ref_nt_challenge_response, const uint8_t *ref_lm_challenge_response,
707 ntlmssp_header_t *ntlmssph,
708 packet_info *pinfo, proto_tree *ntlmssp_tree)
710 const char *password = ntlmssp_option_nt_password;
711 unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
712 unsigned char lm_hash[NTLMSSP_KEY_LEN];
713 unsigned char nt_hash[NTLMSSP_KEY_LEN];
714 unsigned char challenges_hash_first8[8];
715 unsigned char challenges[NTLMSSP_KEY_LEN];
716 uint8_t md4[NTLMSSP_KEY_LEN];
717 uint8_t nb_pass = 0;
718 uint8_t sessionbasekey[NTLMSSP_KEY_LEN];
719 uint8_t keyexchangekey[NTLMSSP_KEY_LEN];
720 uint8_t lm_challenge_response[24];
721 uint8_t nt_challenge_response[24];
722 gcry_cipher_hd_t rc4_handle;
723 gcry_md_hd_t md5_handle;
724 char password_unicode[256];
725 size_t password_len;
726 unsigned int i;
727 bool found = false;
728 md4_pass *pass_list = NULL;
729 const md4_pass *used_md4 = NULL;
731 // "A Boolean setting that SHOULD<35> control using the NTLM response for the LM response to the server challenge when NTLMv1 authentication is used. The default value of this state variable is true."
732 // "<35> Section 3.1.1.1: Windows NT Server 4.0 SP3 does not support providing NTLM instead of LM responses."
733 // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/f711d059-3983-4b9d-afbb-ff2f8c97ffbf
734 static const bool NoLMResponseNTLMv1 = true;
736 static const unsigned char lmhash_key[] =
737 {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; // "KGS!@#$%"
739 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
740 /* Create a NT hash of the input password, even if empty */
741 // NTOWFv1 as defined in https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
742 password_len = strlen(password);
743 /*Do not forget to free password*/
744 ansi_to_unicode(password, password_unicode);
745 gcry_md_hash_buffer(GCRY_MD_MD4, nt_hash, password_unicode, password_len*2);
747 if ((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NoLMResponseNTLMv1)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
748 /* Create a LM hash of the input password, even if empty */
749 // LMOWFv1 as defined in https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
750 /* Truncate password if too long */
751 if (password_len > NTLMSSP_KEY_LEN)
752 password_len = NTLMSSP_KEY_LEN;
754 memset(lm_password_upper, 0, sizeof(lm_password_upper));
755 for (i = 0; i < password_len; i++) {
756 lm_password_upper[i] = g_ascii_toupper(password[i]);
759 crypt_des_ecb(lm_hash, lmhash_key, lm_password_upper);
760 crypt_des_ecb(lm_hash+8, lmhash_key, lm_password_upper+7);
761 ntlmssp_generate_challenge_response(lm_challenge_response,
762 lm_hash, serverchallenge);
763 memcpy(sessionbasekey, lm_hash, NTLMSSP_KEY_LEN);
765 else {
767 memset(lm_challenge_response, 0, 24);
768 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
769 nb_pass = get_md4pass_list(pinfo->pool, &pass_list);
770 i = 0;
771 while (i < nb_pass) {
772 /*ws_debug("Turn %d", i);*/
773 used_md4 = &pass_list[i];
774 memcpy(nt_hash, pass_list[i].md4, NTLMSSP_KEY_LEN);
775 /*ws_log_buffer(nt_hash, NTLMSSP_KEY_LEN, "Current NT hash");*/
776 i++;
777 if(clientchallenge){
778 memcpy(lm_challenge_response, clientchallenge, 8);
780 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
781 break;
783 gcry_md_write(md5_handle, serverchallenge, 8);
784 gcry_md_write(md5_handle, clientchallenge, 8);
785 memcpy(challenges_hash_first8, gcry_md_read(md5_handle, 0), 8);
786 gcry_md_close(md5_handle);
787 crypt_des_ecb_long(nt_challenge_response, nt_hash, challenges_hash_first8);
788 if (ref_nt_challenge_response && !memcmp(ref_nt_challenge_response, nt_challenge_response, 24)) {
789 found = true;
790 break;
794 else {
795 crypt_des_ecb_long(nt_challenge_response, nt_hash, serverchallenge);
796 if (NoLMResponseNTLMv1) {
797 memcpy(lm_challenge_response, nt_challenge_response, 24);
799 else {
800 crypt_des_ecb_long(lm_challenge_response, lm_hash, serverchallenge);
802 if (ref_nt_challenge_response &&
803 !memcmp(ref_nt_challenge_response, nt_challenge_response, 24) &&
804 ref_lm_challenge_response &&
805 !memcmp(ref_lm_challenge_response, lm_challenge_response, 24))
807 found = true;
810 /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
811 * that sessionbasekey should be based md4(nt_hash) only in the case of some NT auth
812 * Otherwise it should be lm_hash ...*/
813 gcry_md_hash_buffer(GCRY_MD_MD4, md4, nt_hash, NTLMSSP_KEY_LEN);
814 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
815 memcpy(challenges, serverchallenge, 8);
816 if(clientchallenge){
817 memcpy(challenges+8, clientchallenge, 8);
819 if (ws_hmac_buffer(GCRY_MD_MD5, sessionbasekey, challenges, NTLMSSP_KEY_LEN, md4, NTLMSSP_KEY_LEN)) {
820 return;
823 else {
824 memcpy(sessionbasekey, md4, NTLMSSP_KEY_LEN);
828 if (!found) {
829 return;
832 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
833 /*ws_log_buffer(nt_challenge_response, 24, "NT challenge response");
834 ws_log_buffer(lm_challenge_response, 24, "LM challenge response");*/
835 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
836 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
838 if(encryptedsessionkey){
839 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
841 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
842 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
843 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
845 gcry_cipher_close(rc4_handle);
848 else
850 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
852 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
854 if (used_md4 == NULL) {
855 return;
857 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
858 &ei_ntlmssp_auth_nthash,
859 "NTLMv1 authenticated using %s (%02x%02x%02x%02x...)",
860 used_md4->key_origin,
861 used_md4->md4[0] & 0xFF, used_md4->md4[1] & 0xFF,
862 used_md4->md4[2] & 0xFF, used_md4->md4[3] & 0xFF);
863 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
864 &ei_ntlmssp_sessionbasekey,
865 "NTLMv1 BaseSessionKey ("
866 "%02x%02x%02x%02x"
867 "%02x%02x%02x%02x"
868 "%02x%02x%02x%02x"
869 "%02x%02x%02x%02x"
870 ")",
871 sessionbasekey[0] & 0xFF, sessionbasekey[1] & 0xFF,
872 sessionbasekey[2] & 0xFF, sessionbasekey[3] & 0xFF,
873 sessionbasekey[4] & 0xFF, sessionbasekey[5] & 0xFF,
874 sessionbasekey[6] & 0xFF, sessionbasekey[7] & 0xFF,
875 sessionbasekey[8] & 0xFF, sessionbasekey[9] & 0xFF,
876 sessionbasekey[10] & 0xFF, sessionbasekey[11] & 0xFF,
877 sessionbasekey[12] & 0xFF, sessionbasekey[13] & 0xFF,
878 sessionbasekey[14] & 0xFF, sessionbasekey[15] & 0xFF);
879 if (memcmp(sessionbasekey, sessionkey, NTLMSSP_KEY_LEN) == 0) {
880 return;
882 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
883 &ei_ntlmssp_sessionkey,
884 "NTLMSSP SessionKey ("
885 "%02x%02x%02x%02x"
886 "%02x%02x%02x%02x"
887 "%02x%02x%02x%02x"
888 "%02x%02x%02x%02x"
889 ")",
890 sessionkey[0] & 0xFF, sessionkey[1] & 0xFF,
891 sessionkey[2] & 0xFF, sessionkey[3] & 0xFF,
892 sessionkey[4] & 0xFF, sessionkey[5] & 0xFF,
893 sessionkey[6] & 0xFF, sessionkey[7] & 0xFF,
894 sessionkey[8] & 0xFF, sessionkey[9] & 0xFF,
895 sessionkey[10] & 0xFF, sessionkey[11] & 0xFF,
896 sessionkey[12] & 0xFF, sessionkey[13] & 0xFF,
897 sessionkey[14] & 0xFF, sessionkey[15] & 0xFF);
901 * Create an NTLMSSP anonymous key
903 static void
904 create_ntlmssp_anon_key(uint8_t *sessionkey, const uint8_t *encryptedsessionkey, int flags,
905 ntlmssp_header_t *ntlmssph,
906 packet_info *pinfo, proto_tree *ntlmssp_tree)
908 uint8_t lm_challenge_response[24] = { 0, };
909 uint8_t sessionbasekey[NTLMSSP_KEY_LEN] = { 0, };
910 uint8_t keyexchangekey[NTLMSSP_KEY_LEN] = { 0, };
911 gcry_cipher_hd_t rc4_handle;
913 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
915 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
916 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
918 if(encryptedsessionkey){
919 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
921 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
922 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
923 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
925 gcry_cipher_close(rc4_handle);
928 else
930 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
932 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
934 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
935 &ei_ntlmssp_auth_nthash,
936 "NTLM authenticated using ANONYMOUS ZERO NTHASH");
937 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
938 &ei_ntlmssp_sessionbasekey,
939 "NTLM Anonymous BaseSessionKey ("
940 "%02x%02x%02x%02x"
941 "%02x%02x%02x%02x"
942 "%02x%02x%02x%02x"
943 "%02x%02x%02x%02x"
944 ")",
945 sessionbasekey[0] & 0xFF, sessionbasekey[1] & 0xFF,
946 sessionbasekey[2] & 0xFF, sessionbasekey[3] & 0xFF,
947 sessionbasekey[4] & 0xFF, sessionbasekey[5] & 0xFF,
948 sessionbasekey[6] & 0xFF, sessionbasekey[7] & 0xFF,
949 sessionbasekey[8] & 0xFF, sessionbasekey[9] & 0xFF,
950 sessionbasekey[10] & 0xFF, sessionbasekey[11] & 0xFF,
951 sessionbasekey[12] & 0xFF, sessionbasekey[13] & 0xFF,
952 sessionbasekey[14] & 0xFF, sessionbasekey[15] & 0xFF);
953 if (memcmp(sessionbasekey, sessionkey, NTLMSSP_KEY_LEN) == 0) {
954 return;
956 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
957 &ei_ntlmssp_sessionkey,
958 "NTLMSSP SessionKey Anonymous ("
959 "%02x%02x%02x%02x"
960 "%02x%02x%02x%02x"
961 "%02x%02x%02x%02x"
962 "%02x%02x%02x%02x"
963 ")",
964 sessionkey[0] & 0xFF, sessionkey[1] & 0xFF,
965 sessionkey[2] & 0xFF, sessionkey[3] & 0xFF,
966 sessionkey[4] & 0xFF, sessionkey[5] & 0xFF,
967 sessionkey[6] & 0xFF, sessionkey[7] & 0xFF,
968 sessionkey[8] & 0xFF, sessionkey[9] & 0xFF,
969 sessionkey[10] & 0xFF, sessionkey[11] & 0xFF,
970 sessionkey[12] & 0xFF, sessionkey[13] & 0xFF,
971 sessionkey[14] & 0xFF, sessionkey[15] & 0xFF);
974 void
975 ntlmssp_create_session_key(packet_info *pinfo,
976 proto_tree *tree,
977 ntlmssp_header_t *ntlmssph,
978 int flags,
979 const uint8_t *server_challenge,
980 const uint8_t *encryptedsessionkey,
981 const ntlmssp_blob *ntlm_response,
982 const ntlmssp_blob *lm_response)
984 uint8_t client_challenge[8] = {0, };
985 uint8_t sessionkey[NTLMSSP_KEY_LEN] = {0, };
987 if (ntlm_response->length > 24)
990 * [MS-NLMP] 2.2.2.8 NTLM2 V2 Response: NTLMv2_RESPONSE has
991 * the 2.2.2.7 "NTLM v2: NTLMv2_CLIENT_CHALLENGE" at offset 16.
992 * Within that ChallengeFromClient is at offset 16, that means
993 * it's at offset 32 in total.
995 * Note that value is only used for the LM_response of NTLMv2.
997 if (ntlm_response->length >= 40) {
998 memcpy(client_challenge,
999 ntlm_response->contents+32, 8);
1001 create_ntlmssp_v2_key(server_challenge,
1002 client_challenge,
1003 sessionkey,
1004 encryptedsessionkey,
1005 flags,
1006 ntlm_response,
1007 lm_response,
1008 ntlmssph,
1009 pinfo,
1010 tree);
1012 else if (ntlm_response->length == 24 && lm_response->length == 24)
1014 memcpy(client_challenge, lm_response->contents, 8);
1016 create_ntlmssp_v1_key(server_challenge,
1017 client_challenge,
1018 sessionkey,
1019 encryptedsessionkey,
1020 flags,
1021 ntlm_response->contents,
1022 lm_response->contents,
1023 ntlmssph,
1024 pinfo,
1025 tree);
1027 else if (ntlm_response->length == 0 && lm_response->length <= 1)
1029 create_ntlmssp_anon_key(sessionkey,
1030 encryptedsessionkey,
1031 flags,
1032 ntlmssph,
1033 pinfo,
1034 tree);
1038 static void
1039 get_signing_key(uint8_t *sign_key_server, uint8_t* sign_key_client, const uint8_t key[NTLMSSP_KEY_LEN], int keylen)
1041 gcry_md_hd_t md5_handle;
1043 memset(sign_key_client, 0, NTLMSSP_KEY_LEN);
1044 memset(sign_key_server, 0, NTLMSSP_KEY_LEN);
1045 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
1046 return;
1048 gcry_md_write(md5_handle, key, keylen);
1049 gcry_md_write(md5_handle, CLIENT_SIGN_TEXT, strlen(CLIENT_SIGN_TEXT)+1); // +1 to get the final null-byte
1050 memcpy(sign_key_client, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1051 gcry_md_reset(md5_handle);
1052 gcry_md_write(md5_handle, key, keylen);
1053 gcry_md_write(md5_handle, SERVER_SIGN_TEXT, strlen(SERVER_SIGN_TEXT)+1); // +1 to get the final null-byte
1054 memcpy(sign_key_server, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1055 gcry_md_close(md5_handle);
1058 /* We return either a 128 or 64 bit key
1060 static void
1061 get_sealing_rc4key(const uint8_t exportedsessionkey[NTLMSSP_KEY_LEN] , const int flags , int *keylen ,
1062 uint8_t *clientsealkey , uint8_t *serversealkey)
1064 gcry_md_hd_t md5_handle;
1066 memset(clientsealkey, 0, NTLMSSP_KEY_LEN);
1067 memset(serversealkey, 0, NTLMSSP_KEY_LEN);
1068 memcpy(clientsealkey, exportedsessionkey, NTLMSSP_KEY_LEN);
1069 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)
1071 if (flags & NTLMSSP_NEGOTIATE_128)
1073 /* The exportedsessionkey has already the good length just update the length*/
1074 *keylen = 16;
1076 else
1078 if (flags & NTLMSSP_NEGOTIATE_56)
1080 memset(clientsealkey+7, 0, 9);
1081 *keylen = 7;
1083 else
1085 memset(clientsealkey+5, 0, 11);
1086 *keylen = 5;
1089 memcpy(serversealkey, clientsealkey, NTLMSSP_KEY_LEN);
1090 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
1091 return;
1093 gcry_md_write(md5_handle, clientsealkey, *keylen);
1094 gcry_md_write(md5_handle, CLIENT_SEAL_TEXT, strlen(CLIENT_SEAL_TEXT)+1); // +1 to get the final null-byte
1095 memcpy(clientsealkey, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1096 gcry_md_reset(md5_handle);
1097 gcry_md_write(md5_handle, serversealkey, *keylen);
1098 gcry_md_write(md5_handle, SERVER_SEAL_TEXT, strlen(SERVER_SEAL_TEXT)+1); // +1 to get the final null-byte
1099 memcpy(serversealkey, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1100 gcry_md_close(md5_handle);
1102 else
1104 if (flags & NTLMSSP_NEGOTIATE_128)
1106 /* The exportedsessionkey has already the good length just update the length*/
1107 *keylen = 16;
1109 else
1111 *keylen = 8;
1112 if (flags & NTLMSSP_NEGOTIATE_56)
1114 memset(clientsealkey+7, 0, 9);
1116 else
1118 memset(clientsealkey+5, 0, 11);
1119 clientsealkey[5]=0xe5;
1120 clientsealkey[6]=0x38;
1121 clientsealkey[7]=0xb0;
1124 memcpy(serversealkey, clientsealkey,*keylen);
1127 /* Create an NTLMSSP version 1 key.
1128 * password points to the ANSI password to encrypt, challenge points to
1129 * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
1130 * otherwise it will do a 40 bit key. The result is stored in
1131 * sspkey (expected to be NTLMSSP_KEY_LEN octets)
1133 /* dissect a string - header area contains:
1134 two byte len
1135 two byte maxlen
1136 four byte offset of string in data area
1137 The function returns the offset at the end of the string header,
1138 but the 'end' parameter returns the offset of the end of the string itself
1139 The 'start' parameter returns the offset of the beginning of the string
1140 If there's no string, just use the offset of the end of the tvb as start/end.
1142 static int
1143 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
1144 proto_tree *ntlmssp_tree,
1145 bool unicode_strings,
1146 int string_hf, int *start, int *end,
1147 const uint8_t **stringp)
1149 proto_tree *tree = NULL;
1150 proto_item *tf = NULL;
1151 int16_t string_length = tvb_get_letohs(tvb, offset);
1152 int16_t string_maxlen = tvb_get_letohs(tvb, offset+2);
1153 int32_t string_offset = tvb_get_letohl(tvb, offset+4);
1155 *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
1156 if (0 == string_length) {
1157 *end = *start;
1158 if (ntlmssp_tree)
1159 proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
1160 offset, 8, "NULL");
1161 if (stringp != NULL)
1162 *stringp = "";
1163 return offset+8;
1166 if (unicode_strings) {
1167 /* UTF-16 string; must be 2-byte aligned */
1168 if ((string_offset & 1) != 0)
1169 string_offset++;
1171 tf = proto_tree_add_item_ret_string(ntlmssp_tree, string_hf, tvb,
1172 string_offset, string_length,
1173 unicode_strings ? ENC_UTF_16|ENC_LITTLE_ENDIAN : ENC_ASCII|ENC_NA,
1174 wmem_packet_scope(), stringp);
1175 tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
1176 proto_tree_add_uint(tree, hf_ntlmssp_string_len,
1177 tvb, offset, 2, string_length);
1178 offset += 2;
1179 proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
1180 tvb, offset, 2, string_maxlen);
1181 offset += 2;
1182 proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
1183 tvb, offset, 4, string_offset);
1184 offset += 4;
1186 *end = string_offset + string_length;
1187 return offset;
1190 /* dissect a generic blob - header area contains:
1191 two byte len
1192 two byte maxlen
1193 four byte offset of blob in data area
1194 The function returns the offset at the end of the blob header,
1195 but the 'end' parameter returns the offset of the end of the blob itself
1197 static int
1198 dissect_ntlmssp_blob (tvbuff_t *tvb, packet_info *pinfo,
1199 proto_tree *ntlmssp_tree, int offset,
1200 int blob_hf, int *end, ntlmssp_blob *result)
1202 proto_item *tf = NULL;
1203 proto_tree *tree = NULL;
1204 uint16_t blob_length = tvb_get_letohs(tvb, offset);
1205 uint16_t blob_maxlen = tvb_get_letohs(tvb, offset+2);
1206 uint32_t blob_offset = tvb_get_letohl(tvb, offset+4);
1208 if (0 == blob_length) {
1209 *end = (blob_offset > ((unsigned)offset)+8 ? blob_offset : ((unsigned)offset)+8);
1210 proto_tree_add_bytes_format_value(ntlmssp_tree, blob_hf, tvb, offset, 8, NULL, "Empty");
1211 result->length = 0;
1212 result->contents = NULL;
1213 return offset+8;
1216 if (ntlmssp_tree) {
1217 tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
1218 blob_offset, blob_length, ENC_NA);
1219 tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
1221 proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
1222 tvb, offset, 2, blob_length);
1223 offset += 2;
1224 proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
1225 tvb, offset, 2, blob_maxlen);
1226 offset += 2;
1227 proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
1228 tvb, offset, 4, blob_offset);
1229 offset += 4;
1231 *end = blob_offset + blob_length;
1233 if (blob_length < NTLMSSP_BLOB_MAX_SIZE) {
1234 result->length = blob_length;
1235 result->contents = (uint8_t *)tvb_memdup(wmem_file_scope(), tvb, blob_offset, blob_length);
1236 } else {
1237 expert_add_info_format(pinfo, tf, &ei_ntlmssp_v2_key_too_long,
1238 "NTLM v2 key is %d bytes long, too big for our %d buffer", blob_length, NTLMSSP_BLOB_MAX_SIZE);
1239 result->length = 0;
1240 result->contents = NULL;
1244 * XXX - for LmChallengeResponse (hf_ntlmssp_auth_lmresponse), should
1245 * we have a field for both Response (2.2.2.3 "LM_RESPONSE" and
1246 * 2.2.2.4 "LMv2_RESPONSE" in [MS-NLMP]) in addition to ClientChallenge
1247 * (only in 2.2.2.4 "LMv2_RESPONSE")?
1249 * XXX - should we also dissect the fields of an NtChallengeResponse
1250 * (hf_ntlmssp_auth_ntresponse)?
1252 * XXX - should we warn if the blob is too *small*?
1254 if (blob_hf == hf_ntlmssp_auth_lmresponse) {
1256 * LMChallengeResponse. It's either 2.2.2.3 "LM_RESPONSE" or
1257 * 2.2.2.4 "LMv2_RESPONSE", in [MS-NLMP].
1259 * XXX - should we have a field for Response as well as
1260 * ClientChallenge?
1262 if (tvb_memeql(tvb, blob_offset+8, (const uint8_t*)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NTLMSSP_KEY_LEN) == 0) {
1264 * LMv2_RESPONSE.
1266 * XXX - according to 2.2.2.4 "LMv2_RESPONSE", the ClientChallenge
1267 * is at an offset of 16 from the beginning of the blob; it's not
1268 * at the beginning of the blob.
1270 proto_tree_add_item (ntlmssp_tree,
1271 hf_ntlmssp_ntlm_client_challenge,
1272 tvb, blob_offset, 8, ENC_NA);
1274 } else if (blob_hf == hf_ntlmssp_auth_ntresponse) {
1276 * NTChallengeResponse. It's either 2.2.2.6 "NTLM v1 Response:
1277 * NTLM_RESPONSE" or 2.2.2.8 "NTLM v2 Response: NTLMv2_RESPONSE"
1278 * in [MS-NLMP].
1280 if (blob_length > 24) {
1282 * > 24 bytes, so it's "NTLM v2 Response: NTLMv2_RESPONSE".
1283 * An NTLMv2_RESPONSE has 16 bytes of Response followed
1284 * by an NTLMv2_CLIENT_CHALLENGE; an NTLMv2_CLIENT_CHALLENGE
1285 * is at least 32 bytes, so an NTLMv2_RESPONSE is at least
1286 * 48 bytes long.
1288 dissect_ntlmv2_response(tvb, pinfo, tree, blob_offset, blob_length);
1292 return offset;
1295 static int * const ntlmssp_negotiate_flags[] = {
1296 &hf_ntlmssp_negotiate_flags_80000000,
1297 &hf_ntlmssp_negotiate_flags_40000000,
1298 &hf_ntlmssp_negotiate_flags_20000000,
1299 &hf_ntlmssp_negotiate_flags_10000000,
1300 &hf_ntlmssp_negotiate_flags_8000000,
1301 &hf_ntlmssp_negotiate_flags_4000000,
1302 &hf_ntlmssp_negotiate_flags_2000000,
1303 &hf_ntlmssp_negotiate_flags_1000000,
1304 &hf_ntlmssp_negotiate_flags_800000,
1305 &hf_ntlmssp_negotiate_flags_400000,
1306 &hf_ntlmssp_negotiate_flags_200000,
1307 &hf_ntlmssp_negotiate_flags_100000,
1308 &hf_ntlmssp_negotiate_flags_80000,
1309 &hf_ntlmssp_negotiate_flags_40000,
1310 &hf_ntlmssp_negotiate_flags_20000,
1311 &hf_ntlmssp_negotiate_flags_10000,
1312 &hf_ntlmssp_negotiate_flags_8000,
1313 &hf_ntlmssp_negotiate_flags_4000,
1314 &hf_ntlmssp_negotiate_flags_2000,
1315 &hf_ntlmssp_negotiate_flags_1000,
1316 &hf_ntlmssp_negotiate_flags_800,
1317 &hf_ntlmssp_negotiate_flags_400,
1318 &hf_ntlmssp_negotiate_flags_200,
1319 &hf_ntlmssp_negotiate_flags_100,
1320 &hf_ntlmssp_negotiate_flags_80,
1321 &hf_ntlmssp_negotiate_flags_40,
1322 &hf_ntlmssp_negotiate_flags_20,
1323 &hf_ntlmssp_negotiate_flags_10,
1324 &hf_ntlmssp_negotiate_flags_08,
1325 &hf_ntlmssp_negotiate_flags_04,
1326 &hf_ntlmssp_negotiate_flags_02,
1327 &hf_ntlmssp_negotiate_flags_01,
1328 NULL
1331 /* Dissect "version" */
1333 /* From MS-NLMP:
1334 0 Major Version Number 1 byte
1335 1 Minor Version Number 1 byte
1336 2 Build Number short(LE)
1337 3 (Reserved) 3 bytes
1338 4 NTLM Current Revision 1 byte
1341 static int
1342 dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
1343 proto_tree *ntlmssp_tree)
1345 if (ntlmssp_tree) {
1346 proto_item *tf;
1347 proto_tree *version_tree;
1348 tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
1349 "Version %u.%u (Build %u); NTLM Current Revision %u",
1350 tvb_get_uint8(tvb, offset),
1351 tvb_get_uint8(tvb, offset+1),
1352 tvb_get_letohs(tvb, offset+2),
1353 tvb_get_uint8(tvb, offset+7));
1354 version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
1355 proto_tree_add_item(version_tree, hf_ntlmssp_version_major , tvb, offset , 1, ENC_LITTLE_ENDIAN);
1356 proto_tree_add_item(version_tree, hf_ntlmssp_version_minor , tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1357 proto_tree_add_item(version_tree, hf_ntlmssp_version_build_number , tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1358 proto_tree_add_item(version_tree, hf_ntlmssp_version_ntlm_current_revision, tvb, offset+7, 1, ENC_LITTLE_ENDIAN);
1360 return offset+8;
1363 /* Dissect a NTLM response. This is documented at
1364 http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
1366 /* Attribute types */
1368 * XXX - the davenport.sourceforge.net document cited above says that a
1369 * type of 5 has been seen, "apparently containing the 'parent' DNS
1370 * domain for servers in subdomains".
1371 * XXX: MS-NLMP info is newer than Davenport info;
1372 * The attribute type list and the attribute names below are
1373 * based upon MS-NLMP.
1376 #define NTLM_TARGET_INFO_END 0x0000
1377 #define NTLM_TARGET_INFO_NB_COMPUTER_NAME 0x0001
1378 #define NTLM_TARGET_INFO_NB_DOMAIN_NAME 0x0002
1379 #define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
1380 #define NTLM_TARGET_INFO_DNS_DOMAIN_NAME 0x0004
1381 #define NTLM_TARGET_INFO_DNS_TREE_NAME 0x0005
1382 #define NTLM_TARGET_INFO_FLAGS 0x0006
1383 #define NTLM_TARGET_INFO_TIMESTAMP 0x0007
1384 #define NTLM_TARGET_INFO_RESTRICTIONS 0x0008
1385 #define NTLM_TARGET_INFO_TARGET_NAME 0x0009
1386 #define NTLM_TARGET_INFO_CHANNEL_BINDINGS 0x000A
1388 static const value_string ntlm_name_types[] = {
1389 { NTLM_TARGET_INFO_END, "End of list" },
1390 { NTLM_TARGET_INFO_NB_COMPUTER_NAME, "NetBIOS computer name" },
1391 { NTLM_TARGET_INFO_NB_DOMAIN_NAME, "NetBIOS domain name" },
1392 { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
1393 { NTLM_TARGET_INFO_DNS_DOMAIN_NAME, "DNS domain name" },
1394 { NTLM_TARGET_INFO_DNS_TREE_NAME, "DNS tree name" },
1395 { NTLM_TARGET_INFO_FLAGS, "Flags" },
1396 { NTLM_TARGET_INFO_TIMESTAMP, "Timestamp" },
1397 { NTLM_TARGET_INFO_RESTRICTIONS, "Restrictions" },
1398 { NTLM_TARGET_INFO_TARGET_NAME, "Target Name"},
1399 { NTLM_TARGET_INFO_CHANNEL_BINDINGS, "Channel Bindings"},
1400 { 0, NULL }
1402 static value_string_ext ntlm_name_types_ext = VALUE_STRING_EXT_INIT(ntlm_name_types);
1404 /* The following *must* match the order of the list of attribute types */
1405 /* Assumption: values in the list are a sequence starting with 0 and */
1406 /* with no gaps allowing a direct access of the array by attribute type */
1407 static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
1408 &hf_ntlmssp_challenge_target_info_end,
1409 &hf_ntlmssp_challenge_target_info_nb_computer_name,
1410 &hf_ntlmssp_challenge_target_info_nb_domain_name,
1411 &hf_ntlmssp_challenge_target_info_dns_computer_name,
1412 &hf_ntlmssp_challenge_target_info_dns_domain_name,
1413 &hf_ntlmssp_challenge_target_info_dns_tree_name,
1414 &hf_ntlmssp_challenge_target_info_flags,
1415 &hf_ntlmssp_challenge_target_info_timestamp,
1416 &hf_ntlmssp_challenge_target_info_restrictions,
1417 &hf_ntlmssp_challenge_target_info_target_name,
1418 &hf_ntlmssp_challenge_target_info_channel_bindings
1421 static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
1422 &hf_ntlmssp_ntlmv2_response_end,
1423 &hf_ntlmssp_ntlmv2_response_nb_computer_name,
1424 &hf_ntlmssp_ntlmv2_response_nb_domain_name,
1425 &hf_ntlmssp_ntlmv2_response_dns_computer_name,
1426 &hf_ntlmssp_ntlmv2_response_dns_domain_name,
1427 &hf_ntlmssp_ntlmv2_response_dns_tree_name,
1428 &hf_ntlmssp_ntlmv2_response_flags,
1429 &hf_ntlmssp_ntlmv2_response_timestamp,
1430 &hf_ntlmssp_ntlmv2_response_restrictions,
1431 &hf_ntlmssp_ntlmv2_response_target_name,
1432 &hf_ntlmssp_ntlmv2_response_channel_bindings
1435 typedef struct _tif {
1436 int *ett;
1437 int *hf_item_type;
1438 int *hf_item_length;
1439 int **hf_attr_array_p;
1440 } tif_t;
1442 static tif_t ntlmssp_challenge_target_info_tif = {
1443 &ett_ntlmssp_challenge_target_info_item,
1444 &hf_ntlmssp_challenge_target_info_item_type,
1445 &hf_ntlmssp_challenge_target_info_item_len,
1446 ntlmssp_hf_challenge_target_info_hf_ptr_array
1449 static tif_t ntlmssp_ntlmv2_response_tif = {
1450 &ett_ntlmssp_ntlmv2_response_item,
1451 &hf_ntlmssp_ntlmv2_response_item_type,
1452 &hf_ntlmssp_ntlmv2_response_item_len,
1453 ntlmssp_hf_ntlmv2_response_hf_ptr_array
1456 /** See [MS-NLMP] 2.2.2.1 */
1457 static int
1458 dissect_ntlmssp_target_info_list(tvbuff_t *_tvb, packet_info *pinfo, proto_tree *tree,
1459 uint32_t target_info_offset, uint16_t target_info_length,
1460 tif_t *tif_p)
1462 tvbuff_t *tvb = tvb_new_subset_length(_tvb, target_info_offset, target_info_length);
1463 uint32_t item_offset = 0;
1464 uint16_t item_type = ~0;
1466 /* Now enumerate through the individual items in the list */
1468 while (tvb_bytes_exist(tvb, item_offset, 4) && (item_type != NTLM_TARGET_INFO_END)) {
1469 proto_item *target_info_tf;
1470 proto_tree *target_info_tree;
1471 uint32_t content_offset;
1472 uint16_t content_length;
1473 uint32_t type_offset;
1474 uint32_t len_offset;
1475 uint32_t item_length;
1476 const uint8_t *text = NULL;
1478 int **hf_array_p = tif_p->hf_attr_array_p;
1480 /* Content type */
1481 type_offset = item_offset;
1482 item_type = tvb_get_letohs(tvb, type_offset);
1484 /* Content length */
1485 len_offset = type_offset + 2;
1486 content_length = tvb_get_letohs(tvb, len_offset);
1488 /* Content value */
1489 content_offset = len_offset + 2;
1490 item_length = content_length + 4;
1492 if (!tvb_bytes_exist(tvb, item_offset, item_length)) {
1493 /* Mark the current item and all the rest as invalid */
1494 proto_tree_add_expert(tree, pinfo, &ei_ntlmssp_target_info_invalid,
1495 tvb, item_offset, target_info_length - item_offset);
1496 return target_info_offset + target_info_length;
1499 target_info_tree = proto_tree_add_subtree_format(tree, tvb, item_offset, item_length, *tif_p->ett, &target_info_tf,
1500 "Attribute: %s", val_to_str_ext(item_type, &ntlm_name_types_ext, "Unknown (%d)"));
1502 proto_tree_add_item (target_info_tree, *tif_p->hf_item_type, tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
1503 proto_tree_add_item (target_info_tree, *tif_p->hf_item_length, tvb, len_offset, 2, ENC_LITTLE_ENDIAN);
1505 if (content_length > 0) {
1506 switch (item_type) {
1507 case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
1508 case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
1509 case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
1510 case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
1511 case NTLM_TARGET_INFO_DNS_TREE_NAME:
1512 case NTLM_TARGET_INFO_TARGET_NAME:
1513 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, pinfo->pool, &text);
1514 proto_item_append_text(target_info_tf, ": %s", text);
1515 break;
1517 case NTLM_TARGET_INFO_FLAGS:
1518 proto_tree_add_item(target_info_tree, *hf_array_p[item_type], tvb, content_offset, content_length, ENC_LITTLE_ENDIAN);
1519 break;
1521 case NTLM_TARGET_INFO_TIMESTAMP:
1522 dissect_nttime(tvb, target_info_tree, content_offset, *hf_array_p[item_type], ENC_LITTLE_ENDIAN);
1523 break;
1525 case NTLM_TARGET_INFO_RESTRICTIONS:
1526 case NTLM_TARGET_INFO_CHANNEL_BINDINGS:
1527 proto_tree_add_item(target_info_tree, *hf_array_p[item_type], tvb, content_offset, content_length, ENC_NA);
1528 break;
1530 default:
1531 proto_tree_add_expert(target_info_tree, pinfo, &ei_ntlmssp_target_info_attr,
1532 tvb, content_offset, content_length);
1533 break;
1537 item_offset += item_length;
1540 return target_info_offset + item_offset;
1543 /** See [MS-NLMP] 3.3.2 */
1545 dissect_ntlmv2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int len)
1547 proto_item *ntlmv2_item = NULL;
1548 proto_tree *ntlmv2_tree = NULL;
1549 const int orig_offset = offset;
1551 /* XXX - make sure we don't go past len? */
1552 if (tree) {
1553 ntlmv2_item = proto_tree_add_item(
1554 tree, hf_ntlmssp_ntlmv2_response, tvb,
1555 offset, len, ENC_NA);
1556 ntlmv2_tree = proto_item_add_subtree(
1557 ntlmv2_item, ett_ntlmssp_ntlmv2_response);
1560 proto_tree_add_item(
1561 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_ntproofstr, tvb,
1562 offset, 16, ENC_NA);
1563 offset += 16;
1565 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_rversion, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1566 offset += 1;
1568 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hirversion, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1569 offset += 1;
1571 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 6, ENC_NA);
1572 offset += 6;
1574 dissect_nttime(
1575 tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time, ENC_LITTLE_ENDIAN);
1576 offset += 8;
1577 proto_tree_add_item(
1578 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
1579 offset, 8, ENC_NA);
1580 offset += 8;
1582 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 4, ENC_NA);
1583 offset += 4;
1585 offset = dissect_ntlmssp_target_info_list(tvb, pinfo, ntlmv2_tree, offset, len - (offset - orig_offset), &ntlmssp_ntlmv2_response_tif);
1587 if ((offset - orig_offset) < len) {
1588 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_pad, tvb, offset, len - (offset - orig_offset), ENC_NA);
1591 return offset+len;
1594 /* tapping into ntlmssph not yet implemented */
1595 static int
1596 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1598 uint32_t negotiate_flags;
1599 int data_start;
1600 int data_end;
1601 int item_start;
1602 int item_end;
1604 /* NTLMSSP Negotiate Flags */
1605 negotiate_flags = tvb_get_letohl (tvb, offset);
1606 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1607 offset += 4;
1610 * XXX - the davenport document says that these might not be
1611 * sent at all, presumably meaning the length of the message
1612 * isn't enough to contain them.
1614 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, false,
1615 hf_ntlmssp_negotiate_domain,
1616 &data_start, &data_end, NULL);
1618 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, false,
1619 hf_ntlmssp_negotiate_workstation,
1620 &item_start, &item_end, NULL);
1621 data_start = MIN(data_start, item_start);
1622 data_end = MAX(data_end, item_end);
1624 /* If there are more bytes before the data block dissect a version field
1625 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1626 if (offset < data_start) {
1627 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1628 dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1630 return data_end;
1634 static int
1635 dissect_ntlmssp_challenge_target_info_blob (packet_info *pinfo, tvbuff_t *tvb, int offset,
1636 proto_tree *ntlmssp_tree,
1637 int *end)
1639 uint16_t challenge_target_info_length = tvb_get_letohs(tvb, offset);
1640 uint16_t challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
1641 uint32_t challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
1642 proto_item *tf = NULL;
1643 proto_tree *challenge_target_info_tree = NULL;
1645 /* the target info list is just a blob */
1646 if (0 == challenge_target_info_length) {
1647 *end = (challenge_target_info_offset > ((unsigned)offset)+8 ? challenge_target_info_offset : ((unsigned)offset)+8);
1648 proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb, offset, 8,
1649 "Target Info List: Empty");
1650 return offset+8;
1653 if (ntlmssp_tree) {
1654 tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
1655 challenge_target_info_offset, challenge_target_info_length, ENC_NA);
1656 challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
1658 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
1659 tvb, offset, 2, challenge_target_info_length);
1660 offset += 2;
1661 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
1662 tvb, offset, 2, challenge_target_info_maxlen);
1663 offset += 2;
1664 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
1665 tvb, offset, 4, challenge_target_info_offset);
1666 offset += 4;
1668 dissect_ntlmssp_target_info_list(tvb, pinfo, challenge_target_info_tree,
1669 challenge_target_info_offset, challenge_target_info_length,
1670 &ntlmssp_challenge_target_info_tif);
1672 *end = challenge_target_info_offset + challenge_target_info_length;
1673 return offset;
1676 /* tapping into ntlmssph not yet implemented */
1677 static int
1678 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
1679 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1681 uint32_t negotiate_flags = 0;
1682 int item_start, item_end;
1683 int data_start, data_end; /* MIN and MAX seen */
1684 uint8_t clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1685 uint8_t serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1686 ntlmssp_info *conv_ntlmssp_info = NULL;
1687 conversation_t *conversation;
1688 bool unicode_strings = false;
1689 uint8_t tmp[8];
1690 uint8_t sspkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key */
1691 int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
1694 * Use the negotiate flags in this message, if they're present
1695 * in the capture, to determine whether strings are Unicode or
1696 * not.
1698 * offset points at TargetNameFields; skip past it.
1700 if (tvb_bytes_exist(tvb, offset+8, 4)) {
1701 negotiate_flags = tvb_get_letohl (tvb, offset+8);
1702 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
1703 unicode_strings = true;
1706 /* Target name */
1708 * XXX - the davenport document (and MS-NLMP) calls this "Target Name",
1709 * presumably because non-domain targets are supported.
1710 * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
1712 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
1713 hf_ntlmssp_challenge_target_name,
1714 &item_start, &item_end, NULL);
1715 data_start = item_start;
1716 data_end = item_end;
1718 /* NTLMSSP Negotiate Flags */
1719 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1720 offset += 4;
1722 /* NTLMSSP NT Lan Manager Challenge */
1723 proto_tree_add_item (ntlmssp_tree,
1724 hf_ntlmssp_ntlm_server_challenge,
1725 tvb, offset, 8, ENC_NA);
1728 * Store the flags and the RC4 state information with the conversation,
1729 * as they're needed in order to dissect subsequent messages.
1731 conversation = find_or_create_conversation(pinfo);
1733 tvb_memcpy(tvb, tmp, offset, 8); /* challenge */
1734 /* We can face more than one NTLM exchange over the same couple of IP and ports ...*/
1735 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation, proto_ntlmssp);
1736 /* XXX: The following code is (re)executed every time a particular frame is dissected
1737 * (in whatever order). Thus it seems to me that "multiple exchanges" might not be
1738 * handled well depending on the order that frames are visited after the initial dissection.
1740 if (!conv_ntlmssp_info || memcmp(tmp, conv_ntlmssp_info->server_challenge, 8) != 0) {
1741 conv_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_info);
1742 wmem_register_callback(wmem_file_scope(), ntlmssp_sessions_destroy_cb, conv_ntlmssp_info);
1743 /* Insert the flags into the conversation */
1744 conv_ntlmssp_info->flags = negotiate_flags;
1745 conv_ntlmssp_info->saw_challenge = true;
1746 /* Insert the RC4 state information into the conversation */
1747 tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
1748 /* Between the challenge and the user provided password, we can build the
1749 NTLMSSP key and initialize the cipher if we are not in EXTENDED SESSION SECURITY
1750 in this case we need the client challenge as well*/
1751 /* BTW this is true just if we are in LM Authentication if not the logic is a bit different.
1752 * Right now it's not very clear what is LM Authentication it __seems__ to be when
1753 * NEGOTIATE NT ONLY is not set and NEGOTIATE EXTENDED SESSION SECURITY is not set as well*/
1754 if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY))
1756 conv_ntlmssp_info->rc4_state_initialized = false;
1757 /* XXX - Make sure there is 24 bytes for the key */
1758 conv_ntlmssp_info->ntlm_response.contents = (uint8_t *)wmem_alloc0(wmem_file_scope(), 24);
1759 conv_ntlmssp_info->lm_response.contents = (uint8_t *)wmem_alloc0(wmem_file_scope(), 24);
1761 create_ntlmssp_v1_key(conv_ntlmssp_info->server_challenge,
1762 NULL, sspkey, NULL, conv_ntlmssp_info->flags,
1763 conv_ntlmssp_info->ntlm_response.contents,
1764 conv_ntlmssp_info->lm_response.contents,
1765 ntlmssph, pinfo, ntlmssp_tree);
1766 if (memcmp(sspkey, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
1767 get_sealing_rc4key(sspkey, conv_ntlmssp_info->flags, &ssp_key_len, clientkey, serverkey);
1768 if (!gcry_cipher_open(&conv_ntlmssp_info->rc4_handle_client, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1769 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_client, sspkey, ssp_key_len)) {
1770 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
1771 conv_ntlmssp_info->rc4_handle_client = NULL;
1774 if (!gcry_cipher_open(&conv_ntlmssp_info->rc4_handle_server, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1775 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_server, sspkey, ssp_key_len)) {
1776 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
1777 conv_ntlmssp_info->rc4_handle_server = NULL;
1780 if (conv_ntlmssp_info->rc4_handle_client && conv_ntlmssp_info->rc4_handle_server) {
1781 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1782 conv_ntlmssp_info->rc4_state_initialized = true;
1786 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1788 offset += 8;
1790 /* If no more bytes (ie: no "reserved", ...) before start of data block, then return */
1791 /* XXX: According to Davenport "This form is seen in older Win9x-based systems" */
1792 /* Also: I've seen a capture with an HTTP CONNECT proxy-authentication */
1793 /* message wherein the challenge from the proxy has this form. */
1794 if (offset >= data_start) {
1795 return data_end;
1798 /* Reserved (function not completely known) */
1800 * XXX - SSP key? The davenport document says
1802 * The context field is typically populated when Negotiate Local
1803 * Call is set. It contains an SSPI context handle, which allows
1804 * the client to "short-circuit" authentication and effectively
1805 * circumvent responding to the challenge. Physically, the context
1806 * is two long values. This is covered in greater detail later,
1807 * in the "Local Authentication" section.
1809 * It also says that that information may be omitted.
1811 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
1812 tvb, offset, 8, ENC_NA);
1813 offset += 8;
1816 * The presence or absence of this field is not obviously correlated
1817 * with any flags in the previous NEGOTIATE message or in this
1818 * message (other than the "Workstation Supplied" and "Domain
1819 * Supplied" flags in the NEGOTIATE message, at least in the capture
1820 * I've seen - but those also correlate with the presence of workstation
1821 * and domain name fields, so it doesn't seem to make sense that they
1822 * actually *indicate* whether the subsequent CHALLENGE has an
1823 * address list).
1825 if (offset < data_start) {
1826 offset = dissect_ntlmssp_challenge_target_info_blob(pinfo, tvb, offset, ntlmssp_tree, &item_end);
1827 /* XXX: This code assumes that the address list in the data block */
1828 /* is always after the target name. Is this OK ? */
1829 data_end = MAX(data_end, item_end);
1832 /* If there are more bytes before the data block dissect a version field
1833 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1834 if (offset < data_start) {
1835 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1836 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1839 return MAX(offset, data_end);
1842 static int
1843 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
1844 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
1846 int item_start, item_end;
1847 int data_start, data_end = 0;
1848 bool have_negotiate_flags = false;
1849 uint32_t negotiate_flags;
1850 uint8_t sspkey[NTLMSSP_KEY_LEN]; /* exported session key */
1851 uint8_t clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1852 uint8_t serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1853 uint8_t encryptedsessionkey[NTLMSSP_KEY_LEN] = {0};
1854 ntlmssp_blob sessionblob;
1855 bool unicode_strings = false;
1856 ntlmssp_info *conv_ntlmssp_info;
1857 conversation_t *conversation;
1858 int ssp_key_len;
1860 conv_ntlmssp_info = (ntlmssp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_CONV_INFO_KEY);
1861 if (conv_ntlmssp_info == NULL) {
1863 * There isn't any. Is there any from this conversation? If so,
1864 * it means this is the first time we've dissected this frame, so
1865 * we should give it flag info.
1867 /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
1868 /* so we'll have a place to store flags. */
1869 /* This is a bit brute-force but looks like it will be OK. */
1870 conversation = find_or_create_conversation(pinfo);
1871 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation, proto_ntlmssp);
1872 if (conv_ntlmssp_info == NULL) {
1873 conv_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_info);
1874 wmem_register_callback(wmem_file_scope(), ntlmssp_sessions_destroy_cb, conv_ntlmssp_info);
1875 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1877 /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
1878 same as the one attached to the conversation. That is: *both* point to
1879 the exact same struct in memory. Is this what is indended ? */
1880 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_CONV_INFO_KEY, conv_ntlmssp_info);
1884 * Get flag info from the original negotiate message, if any.
1885 * This is because the flag information is sometimes missing from
1886 * the AUTHENTICATE message, so we can't figure out whether
1887 * strings are Unicode or not by looking at *our* flags.
1889 * MS-NLMP says:
1891 * In 2.2.1.1 NEGOTIATE_MESSAGE:
1893 * NegotiateFlags (4 bytes): A NEGOTIATE structure that contains a set
1894 * of flags, as defined in section 2.2.2.5. The client sets flags to
1895 * indicate options it supports.
1897 * In 2.2.1.2 CHALLENGE_MESSAGE:
1899 * NegotiateFlags (4 bytes): A NEGOTIATE structure that contains a set
1900 * of flags, as defined by section 2.2.2.5. The server sets flags to
1901 * indicate options it supports or, if there has been a NEGOTIATE_MESSAGE
1902 * (section 2.2.1.1), the choices it has made from the options offered
1903 * by the client.
1905 * In 2.2.1.3 AUTHENTICATE_MESSAGE:
1907 * NegotiateFlags (4 bytes): In connectionless mode, a NEGOTIATE
1908 * structure that contains a set of flags (section 2.2.2.5) and
1909 * represents the conclusion of negotiation--the choices the client
1910 * has made from the options the server offered in the CHALLENGE_MESSAGE.
1911 * In connection-oriented mode, a NEGOTIATE structure that contains the
1912 * set of bit flags (section 2.2.2.5) negotiated in the previous messages.
1914 * As 1.3.1 NTLM Authentication Call Flow indicates, in connectionless
1915 * mode, there's no NEGOTIATE_MESSAGE, just a CHALLENGE_MESSAGE and
1916 * an AUTHENTICATE_MESSAGE.
1918 * So, for connectionless mode, with no NEGOTIATE_MESSAGE, the flags
1919 * that are the result of negotiation are in the AUTHENTICATE_MESSAGE;
1920 * only at the time the AUTHENTICATE_MESSAGE is sent does the client
1921 * know what the server is offering, so, at that point, it can indicate
1922 * to the server which of those it supports, with the final result
1923 * specifying the capabilities offered by the server that are also
1924 * supported by the client.
1926 * For connection-oriented mode, at the time of the CHALLENGE_MESSAGE,
1927 * the server knows what capabilities the client supports, as those
1928 * we specified in the NEGOTIATE_MESSAGE, so it returns the set of
1929 * capabilities, from the set that the client supports, that it also
1930 * supports, so the CHALLENGE_MESSAGE contains the final result. The
1931 * AUTHENTICATE_MESSAGE "contains the set of bit flags ... negotiated
1932 * in the previous messages", so it should contain the same set of
1933 * bit flags that were in the CHALLENGE_MESSAGE.
1935 * So we use the flags in this message, the AUTHENTICATE_MESSAGE, if
1936 * they're present; if this is connectionless mode, the flags in the
1937 * CHALLENGE_MESSAGE aren't sufficient, as they don't indicate what
1938 * the client supports, and if this is connection-oriented mode, the
1939 * flags here should match what's in the CHALLENGE_MESSAGE.
1941 * The flags might be missing from this message; the message could
1942 * have been cut short by the snapshot length, and even if it's not,
1943 * some older protocol implementations omit it. If they're missing,
1944 * we fall back on what's in the CHALLENGE_MESSAGE.
1946 * XXX: I've seen a capture which does an HTTP CONNECT which:
1947 * - has the NEGOTIATE & CHALLENGE messages in one TCP connection;
1948 * - has the AUTHENTICATE message in a second TCP connection;
1949 * (The authentication aparently succeeded).
1950 * For that case, in order to get the flags from the CHALLENGE_MESSAGE,
1951 * we'd somehow have to manage NTLMSSP exchanges that cross TCP
1952 * connection boundaries.
1954 * offset points at LmChallengeResponseFields; skip past
1955 * LmChallengeResponseFields, NtChallengeResponseFields,
1956 * DomainNameFields, UserNameFields, WorkstationFields,
1957 * and EncryptedRandomSessionKeyFields.
1959 if (tvb_bytes_exist(tvb, offset+8+8+8+8+8+8, 4)) {
1961 * See where the Lan Manager response's blob begins;
1962 * the data area starts at, or before, that location.
1964 data_start = tvb_get_letohl(tvb, offset+4);
1967 * See where the NTLM response's blob begins; the data area
1968 * starts at, or before, that location.
1970 item_start = tvb_get_letohl(tvb, offset+8+4);
1971 data_start = MIN(data_start, item_start);
1974 * See where the domain name's blob begins; the data area
1975 * starts at, or before, that location.
1977 item_start = tvb_get_letohl(tvb, offset+8+8+4);
1978 data_start = MIN(data_start, item_start);
1981 * See where the user name's blob begins; the data area
1982 * starts at, or before, that location.
1984 item_start = tvb_get_letohl(tvb, offset+8+8+8+4);
1985 data_start = MIN(data_start, item_start);
1988 * See where the host name's blob begins; the data area
1989 * starts at, or before, that location.
1991 item_start = tvb_get_letohl(tvb, offset+8+8+8+8+4);
1992 data_start = MIN(data_start, item_start);
1995 * See if we have a session key and flags.
1997 if (offset+8+8+8+8+8 < data_start) {
1999 * We have a session key and flags.
2001 negotiate_flags = tvb_get_letohl (tvb, offset+8+8+8+8+8+8);
2002 have_negotiate_flags = true;
2003 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
2004 unicode_strings = true;
2007 if (!have_negotiate_flags) {
2009 * The flags from this message aren't present; if we have the
2010 * flags from the CHALLENGE message, use them.
2012 if (conv_ntlmssp_info != NULL && conv_ntlmssp_info->saw_challenge) {
2013 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
2014 unicode_strings = true;
2019 * Sometimes the session key and flags are missing.
2020 * Sometimes the session key is present but the flags are missing.
2021 * XXX Who stay so ? Reading spec I would rather say the opposite: flags are
2022 * always present, session information are always there as well but sometime
2023 * session information could be null (in case of no session)
2024 * Sometimes they're both present.
2026 * This does not correlate with any flags in the previous CHALLENGE
2027 * message, and only correlates with "Negotiate Unicode", "Workstation
2028 * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
2029 * those don't make sense as flags to use to determine this.
2031 * So we check all of the descriptors to figure out where the data
2032 * area begins, and if the session key or the flags would be in the
2033 * middle of the data area, we assume the field in question is
2034 * missing.
2036 * XXX - Reading Davenport and MS-NLMP: as I see it the possibilities are:
2037 * a. No session-key; no flags; no version ("Win9x")
2038 * b. Session-key & flags.
2039 * c. Session-key, flags & version.
2040 * In cases b and c the session key may be "null".
2044 /* Lan Manager response */
2045 data_start = tvb_get_letohl(tvb, offset+4);
2046 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
2047 hf_ntlmssp_auth_lmresponse,
2048 &item_end,
2049 conv_ntlmssp_info == NULL ? NULL :
2050 &conv_ntlmssp_info->lm_response);
2051 data_end = MAX(data_end, item_end);
2053 /* NTLM response */
2054 item_start = tvb_get_letohl(tvb, offset+4);
2055 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
2056 hf_ntlmssp_auth_ntresponse,
2057 &item_end,
2058 conv_ntlmssp_info == NULL ? NULL :
2059 &conv_ntlmssp_info->ntlm_response);
2060 data_start = MIN(data_start, item_start);
2061 data_end = MAX(data_end, item_end);
2063 /* domain name */
2064 item_start = tvb_get_letohl(tvb, offset+4);
2065 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
2066 unicode_strings,
2067 hf_ntlmssp_auth_domain,
2068 &item_start, &item_end, &(ntlmssph->domain_name));
2069 /*ntlmssph->domain_name_len = item_end-item_start;*/
2070 data_start = MIN(data_start, item_start);
2071 data_end = MAX(data_end, item_end);
2073 /* user name */
2074 item_start = tvb_get_letohl(tvb, offset+4);
2075 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
2076 unicode_strings,
2077 hf_ntlmssp_auth_username,
2078 &item_start, &item_end, &(ntlmssph->acct_name));
2079 /*ntlmssph->acct_name_len = item_end-item_start;*/
2080 data_start = MIN(data_start, item_start);
2081 data_end = MAX(data_end, item_end);
2083 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "User: %s\\%s",
2084 ntlmssph->domain_name, ntlmssph->acct_name);
2086 /* hostname */
2087 item_start = tvb_get_letohl(tvb, offset+4);
2088 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
2089 unicode_strings,
2090 hf_ntlmssp_auth_hostname,
2091 &item_start, &item_end, &(ntlmssph->host_name));
2092 data_start = MIN(data_start, item_start);
2093 data_end = MAX(data_end, item_end);
2095 sessionblob.length = 0;
2096 if (offset < data_start) {
2097 /* Session Key */
2098 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
2099 hf_ntlmssp_auth_sesskey,
2100 &item_end, &sessionblob);
2101 data_end = MAX(data_end, item_end);
2104 if (offset < data_start) {
2105 /* NTLMSSP Negotiate Flags */
2106 negotiate_flags = tvb_get_letohl (tvb, offset);
2107 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
2108 offset += 4;
2110 /* If no previous flags seen (ie: no previous CHALLENGE) use flags
2111 from the AUTHENTICATE message).
2112 Assumption: (flags == 0) means flags not previously seen */
2113 if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
2114 conv_ntlmssp_info->flags = negotiate_flags;
2116 } else
2117 negotiate_flags = 0;
2119 /* If there are more bytes before the data block dissect a version field
2120 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
2121 if (offset < data_start) {
2122 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION) {
2123 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
2124 } else {
2125 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 8, ENC_NA);
2126 offset += 8;
2130 /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
2131 /* (See MS-NLMP) */
2132 if (offset < data_start) {
2133 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_message_integrity_code, tvb, offset, 16, ENC_NA);
2134 offset += 16;
2137 if (sessionblob.length > NTLMSSP_KEY_LEN) {
2138 expert_add_info_format(pinfo, NULL, &ei_ntlmssp_blob_len_too_long, "Session blob length too long: %u", sessionblob.length);
2139 } else if (sessionblob.length != 0) {
2140 /* XXX - Is it a problem if sessionblob.length < NTLMSSP_KEY_LEN ? */
2141 memcpy(encryptedsessionkey, sessionblob.contents, sessionblob.length);
2142 /* Try to attach to an existing conversation if not then it's useless to try to do so
2143 * because we are missing important information (ie. server challenge)
2145 if (conv_ntlmssp_info) {
2146 /* If we are in EXTENDED SESSION SECURITY then we can now initialize cipher */
2147 if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY))
2149 if (conv_ntlmssp_info->rc4_state_initialized) {
2150 /* XXX - Do we really need to reinitialize the cipher contexts? */
2151 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
2152 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
2154 conv_ntlmssp_info->rc4_state_initialized = false;
2155 ntlmssp_create_session_key(pinfo,
2156 ntlmssp_tree,
2157 ntlmssph,
2158 conv_ntlmssp_info->flags,
2159 conv_ntlmssp_info->server_challenge,
2160 encryptedsessionkey,
2161 &conv_ntlmssp_info->ntlm_response,
2162 &conv_ntlmssp_info->lm_response);
2163 /* ssp is the exported session key */
2164 memcpy(sspkey, ntlmssph->session_key, NTLMSSP_KEY_LEN);
2165 if (memcmp(sspkey, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
2166 get_sealing_rc4key(sspkey, conv_ntlmssp_info->flags, &ssp_key_len, clientkey, serverkey);
2167 get_signing_key((uint8_t*)&conv_ntlmssp_info->sign_key_server, (uint8_t*)&conv_ntlmssp_info->sign_key_client, sspkey, ssp_key_len);
2168 if (!gcry_cipher_open (&conv_ntlmssp_info->rc4_handle_server, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
2169 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_server, serverkey, ssp_key_len)) {
2170 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
2171 conv_ntlmssp_info->rc4_handle_server = NULL;
2174 if (!gcry_cipher_open (&conv_ntlmssp_info->rc4_handle_client, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
2175 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_client, clientkey, ssp_key_len)) {
2176 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
2177 conv_ntlmssp_info->rc4_handle_client = NULL;
2180 if (conv_ntlmssp_info->rc4_handle_server && conv_ntlmssp_info->rc4_handle_client) {
2181 conv_ntlmssp_info->server_dest_port = pinfo->destport;
2182 conv_ntlmssp_info->rc4_state_initialized = true;
2188 return MAX(offset, data_end);
2191 static uint8_t*
2192 get_sign_key(packet_info *pinfo, int cryptpeer)
2194 conversation_t *conversation;
2195 ntlmssp_info *conv_ntlmssp_info;
2197 conversation = find_conversation_pinfo(pinfo, 0);
2198 if (conversation == NULL) {
2199 /* We don't have a conversation. In this case, stop processing
2200 because we do not have enough info to decrypt the payload */
2201 return NULL;
2203 else {
2204 /* We have a conversation, check for encryption state */
2205 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2206 proto_ntlmssp);
2207 if (conv_ntlmssp_info == NULL) {
2208 /* No encryption state tied to the conversation. Therefore, we
2209 cannot decrypt the payload */
2210 return NULL;
2212 else {
2213 /* We have the encryption state in the conversation. So return the
2214 crypt state tied to the requested peer
2216 if (cryptpeer == 1) {
2217 return (uint8_t*)&conv_ntlmssp_info->sign_key_client;
2218 } else {
2219 return (uint8_t*)&conv_ntlmssp_info->sign_key_server;
2226 * Get the encryption state tied to this conversation. cryptpeer indicates
2227 * whether to retrieve the client key (1) or the server key (0)
2229 static gcry_cipher_hd_t
2230 get_encrypted_state(packet_info *pinfo, int cryptpeer)
2232 conversation_t *conversation;
2233 ntlmssp_info *conv_ntlmssp_info;
2235 conversation = find_conversation_pinfo(pinfo, 0);
2236 if (conversation == NULL) {
2237 /* We don't have a conversation. In this case, stop processing
2238 because we do not have enough info to decrypt the payload */
2239 return NULL;
2241 else {
2242 /* We have a conversation, check for encryption state */
2243 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2244 proto_ntlmssp);
2245 if (conv_ntlmssp_info == NULL) {
2246 /* No encryption state tied to the conversation. Therefore, we
2247 cannot decrypt the payload */
2248 return NULL;
2250 else {
2251 /* We have the encryption state in the conversation. So return the
2252 crypt state tied to the requested peer
2254 if (cryptpeer == 1) {
2255 return conv_ntlmssp_info->rc4_handle_client;
2256 } else {
2257 return conv_ntlmssp_info->rc4_handle_server;
2263 static tvbuff_t*
2264 decrypt_data_payload(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length,
2265 packet_info *pinfo, proto_tree *tree _U_, void *key);
2266 static void
2267 store_verifier(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length, packet_info *pinfo);
2269 static void
2270 decrypt_verifier(tvbuff_t *tvb, packet_info *pinfo);
2272 static int
2273 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2275 volatile int offset = 0;
2276 proto_tree *volatile ntlmssp_tree = NULL;
2277 proto_item *tf = NULL;
2278 uint32_t length;
2279 uint32_t encrypted_block_length;
2280 uint8_t key[NTLMSSP_KEY_LEN];
2281 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01 */
2282 uint32_t ntlm_magic_size = 4;
2283 uint32_t ntlm_signature_size = 8;
2284 uint32_t ntlm_seq_size = 4;
2286 length = tvb_captured_length (tvb);
2287 /* signature + seq + real payload */
2288 encrypted_block_length = length - ntlm_magic_size;
2290 if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
2291 /* Don't know why this would happen, but if it does, don't even bother
2292 attempting decryption/dissection */
2293 return offset + length;
2296 /* Setup a new tree for the NTLMSSP payload */
2297 if (tree) {
2298 tf = proto_tree_add_item (tree,
2299 hf_ntlmssp_verf,
2300 tvb, offset, -1, ENC_NA);
2302 ntlmssp_tree = proto_item_add_subtree (tf,
2303 ett_ntlmssp);
2307 * Catch the ReportedBoundsError exception; the stuff we've been
2308 * handed doesn't necessarily run to the end of the packet, it's
2309 * an item inside a packet, so if it happens to be malformed (or
2310 * we, or a dissector we call, has a bug), so that an exception
2311 * is thrown, we want to report the error, but return and let
2312 * our caller dissect the rest of the packet.
2314 * If it gets a BoundsError, we can stop, as there's nothing more
2315 * in the packet after our blob to see, so we just re-throw the
2316 * exception.
2318 TRY {
2319 /* Version number */
2320 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2321 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2322 offset += 4;
2324 /* Encrypted body */
2325 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2326 tvb, offset, ntlm_signature_size + ntlm_seq_size, ENC_NA);
2327 memset(key, 0, sizeof(key));
2328 tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
2329 /* Try to decrypt */
2330 decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree, key);
2331 store_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo);
2332 decrypt_verifier (tvb, pinfo);
2333 /* let's try to hook ourselves here */
2335 offset += 12;
2336 } CATCH_NONFATAL_ERRORS {
2337 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2338 } ENDTRY;
2340 return offset;
2343 static tvbuff_t*
2344 decrypt_data_payload(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length,
2345 packet_info *pinfo, proto_tree *tree _U_, void *key)
2347 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2348 ntlmssp_packet_info *packet_ntlmssp_info;
2349 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2351 /* Check to see if we already have state for this packet */
2352 packet_ntlmssp_info = (ntlmssp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2353 if (packet_ntlmssp_info == NULL) {
2354 /* We don't have any packet state, so create one */
2355 packet_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_packet_info);
2356 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY, packet_ntlmssp_info);
2358 if (!packet_ntlmssp_info->payload_decrypted) {
2359 conversation_t *conversation;
2360 ntlmssp_info *conv_ntlmssp_info;
2362 /* Pull the challenge info from the conversation */
2363 conversation = find_conversation_pinfo(pinfo, 0);
2364 if (conversation == NULL) {
2365 /* There is no conversation, thus no encryption state */
2366 return NULL;
2369 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2370 proto_ntlmssp);
2371 if (conv_ntlmssp_info == NULL) {
2372 /* There is no NTLMSSP state tied to the conversation */
2373 return NULL;
2375 if (!conv_ntlmssp_info->rc4_state_initialized) {
2376 /* The crypto sybsystem is not initialized. This means that either
2377 the conversation did not include a challenge, or that we do not have the right password */
2378 return NULL;
2380 if (key != NULL) {
2381 stored_packet_ntlmssp_info = (ntlmssp_packet_info *)g_hash_table_lookup(hash_packet, key);
2383 if (stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == true) {
2384 /* Mat TBD (stderr, "Found a already decrypted packet\n");*/
2385 memcpy(packet_ntlmssp_info, stored_packet_ntlmssp_info, sizeof(ntlmssp_packet_info));
2386 /* Mat TBD ws_log_buffer(packet_ntlmssp_info->decrypted_payload, encrypted_block_length, "Data");*/
2388 else {
2389 gcry_cipher_hd_t rc4_handle;
2390 gcry_cipher_hd_t rc4_handle_peer;
2392 /* Get the pair of RC4 state structures. One is used for to decrypt the
2393 payload. The other is used to re-encrypt the payload to represent
2394 the peer */
2395 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2396 /* client */
2397 rc4_handle = get_encrypted_state(pinfo, 1);
2398 rc4_handle_peer = get_encrypted_state(pinfo, 0);
2399 } else {
2400 /* server */
2401 rc4_handle = get_encrypted_state(pinfo, 0);
2402 rc4_handle_peer = get_encrypted_state(pinfo, 1);
2405 if (rc4_handle == NULL) {
2406 /* There is no encryption state, so we cannot decrypt */
2407 return NULL;
2410 /* Store the decrypted contents in the packet state struct
2411 (of course at this point, they aren't decrypted yet) */
2412 packet_ntlmssp_info->decrypted_payload = (uint8_t *)tvb_memdup(wmem_file_scope(), tvb, offset,
2413 encrypted_block_length);
2414 packet_ntlmssp_info->payload_len = encrypted_block_length;
2415 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2416 packet_ntlmssp_info->decrypted_payload);
2417 if (key != NULL) {
2418 uint8_t *perm_key = g_new(uint8_t, NTLMSSP_KEY_LEN);
2419 memcpy(perm_key, key, NTLMSSP_KEY_LEN);
2420 g_hash_table_insert(hash_packet, perm_key, packet_ntlmssp_info);
2423 /* Do the decryption of the payload */
2424 gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->decrypted_payload, encrypted_block_length, NULL, 0);
2426 /* decrypt the verifier */
2427 /*ws_log_buffer(packet_ntlmssp_info->decrypted_payload, encrypted_block_length, "data");*/
2428 /* We setup a temporary buffer so we can re-encrypt the payload after
2429 decryption. This is to update the opposite peer's RC4 state
2430 it's useful when we have only one key for both conversation
2431 in case of KEY_EXCH we have independent key so this is not needed*/
2432 if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2433 uint8_t *peer_block;
2434 peer_block = (uint8_t *)wmem_memdup(pinfo->pool, packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2435 gcry_cipher_decrypt(rc4_handle_peer, peer_block, encrypted_block_length, NULL, 0);
2438 packet_ntlmssp_info->payload_decrypted = true;
2442 /* Show the decrypted buffer in a new window */
2443 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->decrypted_payload,
2444 encrypted_block_length,
2445 encrypted_block_length);
2447 add_new_data_source(pinfo, decr_tvb,
2448 "Decrypted data");
2449 return decr_tvb;
2452 static int
2453 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2455 volatile int offset = 0;
2456 proto_tree *volatile ntlmssp_tree = NULL;
2457 proto_item *tf, *type_item;
2458 ntlmssp_header_t *ntlmssph;
2460 /* Check if it is a signing signature */
2461 if (tvb_bytes_exist(tvb, offset, 16) &&
2462 tvb_reported_length_remaining(tvb, offset) == 16 &&
2463 tvb_get_uint8(tvb, offset) == 0x01)
2465 tvbuff_t *verf_tvb = tvb_new_subset_length(tvb, offset, 16);
2466 offset += dissect_ntlmssp_verf(verf_tvb, pinfo, tree, NULL);
2467 return offset;
2470 ntlmssph = wmem_new(pinfo->pool, ntlmssp_header_t);
2471 ntlmssph->type = 0;
2472 ntlmssph->domain_name = NULL;
2473 ntlmssph->acct_name = NULL;
2474 ntlmssph->host_name = NULL;
2475 memset(ntlmssph->session_key, 0, NTLMSSP_KEY_LEN);
2477 /* Setup a new tree for the NTLMSSP payload */
2478 tf = proto_tree_add_item (tree,
2479 proto_ntlmssp,
2480 tvb, offset, -1, ENC_NA);
2482 ntlmssp_tree = proto_item_add_subtree (tf, ett_ntlmssp);
2485 * Catch the ReportedBoundsError exception; the stuff we've been
2486 * handed doesn't necessarily run to the end of the packet, it's
2487 * an item inside a packet, so if it happens to be malformed (or
2488 * we, or a dissector we call, has a bug), so that an exception
2489 * is thrown, we want to report the error, but return and let
2490 * our caller dissect the rest of the packet.
2492 * If it gets a BoundsError, we can stop, as there's nothing more
2493 * in the packet after our blob to see, so we just re-throw the
2494 * exception.
2496 TRY {
2497 /* NTLMSSP constant */
2498 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
2499 tvb, offset, 8, ENC_ASCII);
2500 offset += 8;
2502 /* NTLMSSP Message Type */
2503 type_item = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
2504 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2505 ntlmssph->type = tvb_get_letohl (tvb, offset);
2506 offset += 4;
2508 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
2509 val_to_str_const(ntlmssph->type,
2510 ntlmssp_message_types,
2511 "Unknown NTLMSSP message type"));
2513 /* Call the appropriate dissector based on the Message Type */
2514 switch (ntlmssph->type) {
2516 case NTLMSSP_NEGOTIATE:
2517 dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree, ntlmssph);
2518 break;
2520 case NTLMSSP_CHALLENGE:
2521 dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2522 break;
2524 case NTLMSSP_AUTH:
2525 dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2526 break;
2528 default:
2529 /* Unrecognized message type */
2530 expert_add_info(pinfo, type_item, &ei_ntlmssp_message_type);
2531 break;
2533 } CATCH_NONFATAL_ERRORS {
2535 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2536 } ENDTRY;
2538 tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);
2539 return tvb_captured_length(tvb);
2542 static void
2543 store_verifier(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length, packet_info *pinfo)
2545 ntlmssp_packet_info *packet_ntlmssp_info;
2547 packet_ntlmssp_info = (ntlmssp_packet_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2548 if (packet_ntlmssp_info == NULL) {
2549 /* We don't have any packet state, so create one */
2550 packet_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_packet_info);
2551 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY, packet_ntlmssp_info);
2554 if (!packet_ntlmssp_info->verifier_decrypted) {
2555 /* Store all necessary info for later decryption */
2556 packet_ntlmssp_info->verifier_offset = offset;
2557 packet_ntlmssp_info->verifier_block_length = encrypted_block_length;
2558 /* Setup the buffer to decrypt to */
2559 tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
2560 offset, MIN(encrypted_block_length, sizeof(packet_ntlmssp_info->verifier)));
2565 * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
2567 static void
2568 decrypt_verifier(tvbuff_t *tvb, packet_info *pinfo)
2570 proto_tree *decr_tree;
2571 conversation_t *conversation;
2572 uint8_t* sign_key;
2573 gcry_cipher_hd_t rc4_handle;
2574 gcry_cipher_hd_t rc4_handle_peer;
2575 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2576 uint8_t *peer_block;
2577 uint8_t *check_buf;
2578 uint8_t calculated_md5[NTLMSSP_KEY_LEN];
2579 ntlmssp_info *conv_ntlmssp_info;
2580 ntlmssp_packet_info *packet_ntlmssp_info;
2581 int decrypted_offset = 0;
2582 int sequence = 0;
2584 packet_ntlmssp_info = (ntlmssp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2585 if (packet_ntlmssp_info == NULL) {
2586 /* We don't have data for this packet */
2587 return;
2589 conversation = find_conversation_pinfo(pinfo, 0);
2590 if (conversation == NULL) {
2591 /* There is no conversation, thus no encryption state */
2592 return;
2594 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2595 proto_ntlmssp);
2596 if (conv_ntlmssp_info == NULL) {
2597 /* There is no NTLMSSP state tied to the conversation */
2598 return;
2601 if (!packet_ntlmssp_info->verifier_decrypted) {
2602 if (!conv_ntlmssp_info->rc4_state_initialized) {
2603 /* The crypto subsystem is not initialized. This means that either
2604 the conversation did not include a challenge, or we are doing
2605 something other than NTLMSSP v1 */
2606 return;
2608 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2609 /* client talk to server */
2610 rc4_handle = get_encrypted_state(pinfo, 1);
2611 sign_key = get_sign_key(pinfo, 1);
2612 rc4_handle_peer = get_encrypted_state(pinfo, 0);
2613 } else {
2614 rc4_handle = get_encrypted_state(pinfo, 0);
2615 sign_key = get_sign_key(pinfo, 0);
2616 rc4_handle_peer = get_encrypted_state(pinfo, 1);
2619 if (rc4_handle == NULL || rc4_handle_peer == NULL) {
2620 /* There is no encryption state, so we cannot decrypt */
2621 return;
2624 /*if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
2625 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
2626 if ((NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2627 /* The spec says that if we have a key exchange then we have the signature that is encrypted
2628 * otherwise it's just a hmac_md5(keysign, concat(message, sequence))[0..7]
2630 if (gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->verifier, 8, NULL, 0)) {
2631 return;
2635 * Trying to check the HMAC MD5 of the message against the calculated one works great with LDAP payload but
2636 * don't with DCE/RPC calls.
2637 * TODO Some analysis needs to be done ...
2639 if (sign_key != NULL) {
2640 check_buf = (uint8_t *)wmem_alloc(pinfo->pool, packet_ntlmssp_info->payload_len+4);
2641 tvb_memcpy(tvb, &sequence, packet_ntlmssp_info->verifier_offset+8, 4);
2642 memcpy(check_buf, &sequence, 4);
2643 memcpy(check_buf+4, packet_ntlmssp_info->decrypted_payload, packet_ntlmssp_info->payload_len);
2644 if (ws_hmac_buffer(GCRY_MD_MD5, calculated_md5, check_buf, (int)(packet_ntlmssp_info->payload_len+4), sign_key, NTLMSSP_KEY_LEN)) {
2645 return;
2648 ws_log_buffer(packet_ntlmssp_info->verifier, 8, "HMAC from packet");
2649 ws_log_buffer(calculated_md5, 8, "HMAC");
2653 else {
2654 /* 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 */
2655 /* Do the actual decryption of the verifier */
2656 if (gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->verifier, packet_ntlmssp_info->verifier_block_length, NULL, 0)) {
2657 return;
2662 /* We setup a temporary buffer so we can re-encrypt the payload after
2663 decryption. This is to update the opposite peer's RC4 state
2664 This is not needed when we just have EXTENDED SESSION SECURITY because the signature is not encrypted
2665 and it's also not needed when we have key exchange because server and client have independent keys */
2666 if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY & conv_ntlmssp_info->flags)) {
2667 peer_block = (uint8_t *)wmem_memdup(pinfo->pool, packet_ntlmssp_info->verifier, packet_ntlmssp_info->verifier_block_length);
2668 if (gcry_cipher_decrypt(rc4_handle_peer, peer_block, packet_ntlmssp_info->verifier_block_length, NULL, 0)) {
2669 return;
2673 /* Mark the packet as decrypted so that subsequent attempts to dissect
2674 the packet use the already decrypted payload instead of attempting
2675 to decrypt again */
2676 packet_ntlmssp_info->verifier_decrypted = true;
2679 /* Show the decrypted buffer in a new window */
2680 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
2681 packet_ntlmssp_info->verifier_block_length,
2682 packet_ntlmssp_info->verifier_block_length);
2683 add_new_data_source(pinfo, decr_tvb,
2684 "Decrypted NTLMSSP Verifier");
2686 /* Show the decrypted payload in the tree */
2687 decr_tree = proto_tree_add_subtree_format(NULL, decr_tvb, 0, -1,
2688 ett_ntlmssp, NULL,
2689 "Decrypted Verifier (%d byte%s)",
2690 packet_ntlmssp_info->verifier_block_length,
2691 plurality(packet_ntlmssp_info->verifier_block_length, "", "s"));
2693 if (( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) {
2694 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
2695 decr_tvb, decrypted_offset, 8, ENC_NA);
2696 decrypted_offset += 8;
2698 /* Incrementing sequence number of DCE conversation */
2699 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2700 decr_tvb, decrypted_offset, 4, ENC_NA);
2702 else {
2703 /* RANDOM PAD usually it's 0 */
2704 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
2705 decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
2706 decrypted_offset += 4;
2708 /* CRC32 of the DCE fragment data */
2709 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
2710 decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
2711 decrypted_offset += 4;
2713 /* Incrementing sequence number of DCE conversation */
2714 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2715 decr_tvb, decrypted_offset, 4, ENC_NA);
2719 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contiguous*/
2720 static int
2721 dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *tree, void *data)
2723 volatile int offset = 0;
2724 proto_tree *volatile ntlmssp_tree = NULL;
2725 uint32_t encrypted_block_length;
2726 tvbuff_t *volatile decr_tvb;
2727 tvbuff_t** ret_decr_tvb = (tvbuff_t**)data;
2729 if (ret_decr_tvb)
2730 *ret_decr_tvb = NULL;
2731 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
2733 encrypted_block_length = tvb_captured_length (tvb);
2734 /* signature + seq + real payload */
2736 /* Setup a new tree for the NTLMSSP payload */
2737 #if 0
2738 if (tree) {
2739 tf = proto_tree_add_item (tree,
2740 hf_ntlmssp_verf,
2741 tvb, offset, -1, ENC_NA);
2743 ntlmssp_tree = proto_item_add_subtree (tf,
2744 ett_ntlmssp);
2746 #endif
2748 * Catch the ReportedBoundsError exception; the stuff we've been
2749 * handed doesn't necessarily run to the end of the packet, it's
2750 * an item inside a packet, so if it happens to be malformed (or
2751 * we, or a dissector we call, has a bug), so that an exception
2752 * is thrown, we want to report the error, but return and let
2753 * our caller dissect the rest of the packet.
2755 * If it gets a BoundsError, we can stop, as there's nothing more
2756 * in the packet after our blob to see, so we just re-throw the
2757 * exception.
2759 TRY {
2760 /* Version number */
2762 /* Try to decrypt */
2763 decr_tvb = decrypt_data_payload (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree, NULL);
2764 if (ret_decr_tvb)
2765 *ret_decr_tvb = decr_tvb;
2766 /* let's try to hook ourselves here */
2768 } CATCH_NONFATAL_ERRORS {
2770 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2771 } ENDTRY;
2773 return offset;
2776 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contiguous
2777 * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
2779 static int
2780 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2782 volatile int offset = 0;
2783 proto_tree *volatile ntlmssp_tree = NULL;
2784 proto_item *tf = NULL;
2785 uint32_t verifier_length;
2786 uint32_t encrypted_block_length;
2788 verifier_length = tvb_captured_length (tvb);
2789 encrypted_block_length = verifier_length - 4;
2791 if (encrypted_block_length < 12) {
2792 /* Don't know why this would happen, but if it does, don't even bother
2793 attempting decryption/dissection */
2794 return offset + verifier_length;
2797 /* Setup a new tree for the NTLMSSP payload */
2798 if (tree) {
2799 tf = proto_tree_add_item (tree,
2800 hf_ntlmssp_verf,
2801 tvb, offset, -1, ENC_NA);
2803 ntlmssp_tree = proto_item_add_subtree (tf,
2804 ett_ntlmssp);
2808 * Catch the ReportedBoundsError exception; the stuff we've been
2809 * handed doesn't necessarily run to the end of the packet, it's
2810 * an item inside a packet, so if it happens to be malformed (or
2811 * we, or a dissector we call, has a bug), so that an exception
2812 * is thrown, we want to report the error, but return and let
2813 * our caller dissect the rest of the packet.
2815 * If it gets a BoundsError, we can stop, as there's nothing more
2816 * in the packet after our blob to see, so we just re-throw the
2817 * exception.
2819 TRY {
2820 /* Version number */
2821 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2822 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2823 offset += 4;
2825 /* Encrypted body */
2826 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2827 tvb, offset, encrypted_block_length, ENC_NA);
2829 /* Extract and store the verifier for later decryption */
2830 store_verifier (tvb, offset, encrypted_block_length, pinfo);
2831 /* let's try to hook ourselves here */
2833 offset += 12;
2834 offset += encrypted_block_length;
2835 } CATCH_NONFATAL_ERRORS {
2837 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2838 } ENDTRY;
2840 return offset;
2843 static tvbuff_t *
2844 wrap_dissect_ntlmssp_payload_only(tvbuff_t *header_tvb _U_,
2845 tvbuff_t *payload_tvb,
2846 tvbuff_t *trailer_tvb _U_,
2847 tvbuff_t *auth_tvb _U_,
2848 packet_info *pinfo,
2849 dcerpc_auth_info *auth_info _U_)
2851 tvbuff_t *decrypted_tvb;
2853 dissect_ntlmssp_payload_only(payload_tvb, pinfo, NULL, &decrypted_tvb);
2854 /* Now the payload is decrypted, we can then decrypt the verifier which was stored earlier */
2855 decrypt_verifier(payload_tvb, pinfo);
2856 // TODO auth_info->session_key
2857 return decrypted_tvb;
2860 static unsigned
2861 header_hash(const void *pointer)
2863 uint32_t crc = ~crc32c_calculate(pointer, NTLMSSP_KEY_LEN, CRC32C_PRELOAD);
2864 /* Mat TBD ws_debug("Val: %u", crc);*/
2865 return crc;
2868 static gboolean
2869 header_equal(const void *pointer1, const void *pointer2)
2871 if (!memcmp(pointer1, pointer2, NTLMSSP_KEY_LEN)) {
2872 return TRUE;
2874 else {
2875 return FALSE;
2879 static void
2880 ntlmssp_init_protocol(void)
2882 hash_packet = g_hash_table_new_full(header_hash, header_equal, g_free, NULL);
2885 static void
2886 ntlmssp_cleanup_protocol(void)
2888 if (decrypted_payloads != NULL) {
2889 g_slist_free(decrypted_payloads);
2890 decrypted_payloads = NULL;
2892 g_hash_table_destroy(hash_packet);
2897 static int
2898 wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
2899 proto_tree *tree, dcerpc_info *di _U_, uint8_t *drep _U_)
2901 tvbuff_t *auth_tvb;
2903 auth_tvb = tvb_new_subset_remaining(tvb, offset);
2905 dissect_ntlmssp(auth_tvb, pinfo, tree, NULL);
2907 return tvb_captured_length_remaining(tvb, offset);
2910 static int
2911 wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
2912 proto_tree *tree, dcerpc_info *di _U_, uint8_t *drep _U_)
2914 tvbuff_t *auth_tvb;
2916 auth_tvb = tvb_new_subset_remaining(tvb, offset);
2917 return dissect_ntlmssp_verf(auth_tvb, pinfo, tree, NULL);
2920 static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
2921 wrap_dissect_ntlmssp, /* Bind */
2922 wrap_dissect_ntlmssp, /* Bind ACK */
2923 wrap_dissect_ntlmssp, /* AUTH3 */
2924 wrap_dissect_ntlmssp_verf, /* Request verifier */
2925 wrap_dissect_ntlmssp_verf, /* Response verifier */
2926 NULL, /* Request data */
2927 NULL /* Response data */
2930 static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
2931 wrap_dissect_ntlmssp, /* Bind */
2932 wrap_dissect_ntlmssp, /* Bind ACK */
2933 wrap_dissect_ntlmssp, /* AUTH3 */
2934 wrap_dissect_ntlmssp_verf, /* Request verifier */
2935 wrap_dissect_ntlmssp_verf, /* Response verifier */
2936 wrap_dissect_ntlmssp_payload_only, /* Request data */
2937 wrap_dissect_ntlmssp_payload_only /* Response data */
2940 static const value_string MSV1_0_CRED_VERSION[] = {
2941 { 0x00000000, "MSV1_0_CRED_VERSION" },
2942 { 0x00000002, "MSV1_0_CRED_VERSION_V2" },
2943 { 0x00000004, "MSV1_0_CRED_VERSION_V3" },
2944 { 0xffff0001, "MSV1_0_CRED_VERSION_IUM" },
2945 { 0xffff0002, "MSV1_0_CRED_VERSION_REMOTE" },
2946 { 0xfffffffe, "MSV1_0_CRED_VERSION_RESERVED_1" },
2947 { 0xffffffff, "MSV1_0_CRED_VERSION_INVALID" },
2948 { 0, NULL }
2951 #define MSV1_0_CRED_LM_PRESENT 0x00000001
2952 #define MSV1_0_CRED_NT_PRESENT 0x00000002
2953 #define MSV1_0_CRED_REMOVED 0x00000004
2954 #define MSV1_0_CRED_CREDKEY_PRESENT 0x00000008
2955 #define MSV1_0_CRED_SHA_PRESENT 0x00000010
2957 static int* const MSV1_0_CRED_FLAGS_bits[] = {
2958 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_LM_PRESENT,
2959 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_NT_PRESENT,
2960 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_REMOVED,
2961 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_CREDKEY_PRESENT,
2962 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_SHA_PRESENT,
2963 NULL
2966 static const value_string MSV1_0_CREDENTIAL_KEY_TYPE[] = {
2967 { 0, "InvalidCredKey" },
2968 { 1, "IUMCredKey" },
2969 { 2, "DomainUserCredKey" },
2970 { 3, "LocalUserCredKey" },
2971 { 4, "ExternallySuppliedCredKey" },
2972 { 0, NULL }
2975 #define MSV1_0_CREDENTIAL_KEY_LENGTH 20
2978 dissect_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL(tvbuff_t *tvb, int offset, proto_tree *tree)
2980 proto_item *item;
2981 proto_tree *subtree;
2982 uint32_t EncryptedCredsSize;
2984 if (tvb_captured_length(tvb) < 36)
2985 return offset;
2987 item = proto_tree_add_item(tree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL, tvb,
2988 offset, -1, ENC_NA);
2989 subtree = proto_item_add_subtree(item, ett_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL);
2991 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Version, tvb,
2992 offset, 4, ENC_LITTLE_ENDIAN);
2993 offset+=4;
2995 proto_tree_add_bitmask(subtree, tvb, offset,
2996 hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Flags,
2997 ett_ntlmssp, MSV1_0_CRED_FLAGS_bits, ENC_LITTLE_ENDIAN);
2998 offset+=4;
3000 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKey,
3001 tvb, offset, MSV1_0_CREDENTIAL_KEY_LENGTH, ENC_NA);
3002 offset+=MSV1_0_CREDENTIAL_KEY_LENGTH;
3004 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKeyType,
3005 tvb, offset, 4, ENC_LITTLE_ENDIAN);
3006 offset+=4;
3008 EncryptedCredsSize = tvb_get_letohl(tvb, offset);
3009 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCredsSize,
3010 tvb, offset, 4, ENC_LITTLE_ENDIAN);
3011 offset+=4;
3013 if (EncryptedCredsSize == 0)
3014 return offset;
3016 if (tvb_captured_length(tvb) < (36 + EncryptedCredsSize))
3017 return offset;
3019 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCreds,
3020 tvb, offset, EncryptedCredsSize, ENC_NA);
3021 offset+=EncryptedCredsSize;
3023 return offset;
3027 void
3028 proto_register_ntlmssp(void)
3031 static hf_register_info hf[] = {
3032 { &hf_ntlmssp_auth,
3033 { "NTLMSSP identifier", "ntlmssp.identifier",
3034 FT_STRING, BASE_NONE, NULL, 0x0,
3035 NULL, HFILL }
3037 { &hf_ntlmssp_message_type,
3038 { "NTLM Message Type", "ntlmssp.messagetype",
3039 FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0,
3040 NULL, HFILL }
3042 { &hf_ntlmssp_negotiate_flags,
3043 { "Negotiate Flags", "ntlmssp.negotiateflags",
3044 FT_UINT32, BASE_HEX, NULL, 0x0,
3045 NULL, HFILL }
3047 { &hf_ntlmssp_negotiate_flags_01,
3048 { "Negotiate UNICODE", "ntlmssp.negotiateunicode",
3049 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_UNICODE,
3050 NULL, HFILL }
3052 { &hf_ntlmssp_negotiate_flags_02,
3053 { "Negotiate OEM", "ntlmssp.negotiateoem",
3054 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM,
3055 NULL, HFILL }
3057 { &hf_ntlmssp_negotiate_flags_04,
3058 { "Request Target", "ntlmssp.requesttarget",
3059 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_TARGET,
3060 NULL, HFILL }
3062 { &hf_ntlmssp_negotiate_flags_08,
3063 { "Request 0x00000008", "ntlmssp.unused00000008",
3064 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00000008,
3065 NULL, HFILL }
3067 { &hf_ntlmssp_negotiate_flags_10,
3068 { "Negotiate Sign", "ntlmssp.negotiatesign",
3069 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SIGN,
3070 NULL, HFILL }
3072 { &hf_ntlmssp_negotiate_flags_20,
3073 { "Negotiate Seal", "ntlmssp.negotiateseal",
3074 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SEAL,
3075 NULL, HFILL }
3077 { &hf_ntlmssp_negotiate_flags_40,
3078 { "Negotiate Datagram", "ntlmssp.negotiatedatagram",
3079 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_DATAGRAM,
3080 NULL, HFILL }
3082 { &hf_ntlmssp_negotiate_flags_80,
3083 { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey",
3084 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_LM_KEY,
3085 NULL, HFILL }
3087 { &hf_ntlmssp_negotiate_flags_100,
3088 { "Negotiate 0x00000100", "ntlmssp.unused00000100",
3089 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00000100,
3090 NULL, HFILL }
3092 { &hf_ntlmssp_negotiate_flags_200,
3093 { "Negotiate NTLM key", "ntlmssp.negotiatentlm",
3094 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NTLM,
3095 NULL, HFILL }
3097 { &hf_ntlmssp_negotiate_flags_400,
3098 { "Negotiate 0x00000400", "ntlmssp.unused00000400",
3099 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00000400,
3100 NULL, HFILL }
3102 { &hf_ntlmssp_negotiate_flags_800,
3103 { "Negotiate Anonymous", "ntlmssp.negotiateanonymous",
3104 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ANONYMOUS,
3105 NULL, HFILL }
3107 { &hf_ntlmssp_negotiate_flags_1000,
3108 { "Negotiate OEM Domain Supplied", "ntlmssp.negotiateoemdomainsupplied",
3109 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED,
3110 NULL, HFILL }
3112 { &hf_ntlmssp_negotiate_flags_2000,
3113 { "Negotiate OEM Workstation Supplied", "ntlmssp.negotiateoemworkstationsupplied",
3114 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED,
3115 NULL, HFILL }
3117 { &hf_ntlmssp_negotiate_flags_4000,
3118 { "Negotiate 0x00004000", "ntlmssp.unused00004000",
3119 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00004000,
3120 NULL, HFILL }
3122 { &hf_ntlmssp_negotiate_flags_8000,
3123 { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign",
3124 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ALWAYS_SIGN,
3125 NULL, HFILL }
3127 { &hf_ntlmssp_negotiate_flags_10000,
3128 { "Target Type Domain", "ntlmssp.targettypedomain",
3129 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_DOMAIN,
3130 NULL, HFILL }
3132 { &hf_ntlmssp_negotiate_flags_20000,
3133 { "Target Type Server", "ntlmssp.targettypeserver",
3134 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER,
3135 NULL, HFILL }
3137 { &hf_ntlmssp_negotiate_flags_40000,
3138 { "Negotiate 0x00040000", "ntlmssp.unused00040000",
3139 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00040000,
3140 NULL, HFILL }
3143 /* Negotiate Flags */
3144 { &hf_ntlmssp_negotiate_flags_80000,
3145 { "Negotiate Extended Session Security", "ntlmssp.negotiateextendedsessionsecurity",
3146 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY,
3147 NULL, HFILL }
3149 { &hf_ntlmssp_negotiate_flags_100000,
3150 { "Negotiate Identify", "ntlmssp.negotiateidentify",
3151 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_IDENTIFY,
3152 NULL, HFILL }
3154 { &hf_ntlmssp_negotiate_flags_200000,
3155 { "Negotiate 0x00200000", "ntlmssp.unused00200000",
3156 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00200000,
3157 NULL, HFILL }
3159 { &hf_ntlmssp_negotiate_flags_400000,
3160 { "Request Non-NT Session Key", "ntlmssp.requestnonntsessionkey",
3161 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_NON_NT_SESSION_KEY,
3162 NULL, HFILL }
3164 { &hf_ntlmssp_negotiate_flags_800000,
3165 { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo",
3166 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_TARGET_INFO,
3167 NULL, HFILL }
3169 { &hf_ntlmssp_negotiate_flags_1000000,
3170 { "Negotiate 0x01000000", "ntlmssp.unused01000000",
3171 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_01000000,
3172 NULL, HFILL }
3174 { &hf_ntlmssp_negotiate_flags_2000000,
3175 { "Negotiate Version", "ntlmssp.negotiateversion",
3176 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_VERSION,
3177 NULL, HFILL }
3179 { &hf_ntlmssp_negotiate_flags_4000000,
3180 { "Negotiate 0x04000000", "ntlmssp.unused04000000",
3181 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_04000000,
3182 NULL, HFILL }
3184 { &hf_ntlmssp_negotiate_flags_8000000,
3185 { "Negotiate 0x08000000", "ntlmssp.unused08000000",
3186 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_08000000,
3187 NULL, HFILL }
3189 { &hf_ntlmssp_negotiate_flags_10000000,
3190 { "Negotiate 0x10000000", "ntlmssp.unused10000000",
3191 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_10000000,
3192 NULL, HFILL }
3194 { &hf_ntlmssp_negotiate_flags_20000000,
3195 { "Negotiate 128", "ntlmssp.negotiate128",
3196 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_128,
3197 "128-bit encryption is supported", HFILL }
3199 { &hf_ntlmssp_negotiate_flags_40000000,
3200 { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch",
3201 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_KEY_EXCH,
3202 NULL, HFILL }
3204 { &hf_ntlmssp_negotiate_flags_80000000,
3205 { "Negotiate 56", "ntlmssp.negotiate56",
3206 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_56,
3207 "56-bit encryption is supported", HFILL }
3209 #if 0
3210 { &hf_ntlmssp_negotiate_workstation_strlen,
3211 { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen",
3212 FT_UINT16, BASE_DEC, NULL, 0x0,
3213 NULL, HFILL }
3215 #endif
3216 #if 0
3217 { &hf_ntlmssp_negotiate_workstation_maxlen,
3218 { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen",
3219 FT_UINT16, BASE_DEC, NULL, 0x0,
3220 NULL, HFILL }
3222 #endif
3223 #if 0
3224 { &hf_ntlmssp_negotiate_workstation_buffer,
3225 { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer",
3226 FT_UINT32, BASE_HEX, NULL, 0x0,
3227 NULL, HFILL }
3229 #endif
3230 { &hf_ntlmssp_negotiate_workstation,
3231 { "Calling workstation name", "ntlmssp.negotiate.callingworkstation",
3232 FT_STRING, BASE_NONE, NULL, 0x0,
3233 NULL, HFILL }
3235 #if 0
3236 { &hf_ntlmssp_negotiate_domain_strlen,
3237 { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen",
3238 FT_UINT16, BASE_DEC, NULL, 0x0,
3239 NULL, HFILL }
3241 #endif
3242 #if 0
3243 { &hf_ntlmssp_negotiate_domain_maxlen,
3244 { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen",
3245 FT_UINT16, BASE_DEC, NULL, 0x0,
3246 NULL, HFILL }
3248 #endif
3249 #if 0
3250 { &hf_ntlmssp_negotiate_domain_buffer,
3251 { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer",
3252 FT_UINT32, BASE_HEX, NULL, 0x0,
3253 NULL, HFILL }
3255 #endif
3256 { &hf_ntlmssp_negotiate_domain,
3257 { "Calling workstation domain", "ntlmssp.negotiate.domain",
3258 FT_STRING, BASE_NONE, NULL, 0x0,
3259 NULL, HFILL }
3261 { &hf_ntlmssp_ntlm_client_challenge,
3262 { "LMv2 Client Challenge", "ntlmssp.ntlmclientchallenge",
3263 FT_BYTES, BASE_NONE, NULL, 0x0,
3264 "The 8-byte LMv2 challenge message generated by the client", HFILL }
3266 { &hf_ntlmssp_ntlm_server_challenge,
3267 { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge",
3268 FT_BYTES, BASE_NONE, NULL, 0x0,
3269 NULL, HFILL }
3271 { &hf_ntlmssp_reserved,
3272 { "Reserved", "ntlmssp.reserved",
3273 FT_BYTES, BASE_NONE, NULL, 0x0,
3274 NULL, HFILL }
3277 { &hf_ntlmssp_challenge_target_name,
3278 { "Target Name", "ntlmssp.challenge.target_name",
3279 FT_STRING, BASE_NONE, NULL, 0x0,
3280 NULL, HFILL }
3282 { &hf_ntlmssp_auth_domain,
3283 { "Domain name", "ntlmssp.auth.domain",
3284 FT_STRING, BASE_NONE, NULL, 0x0,
3285 NULL, HFILL }
3287 { &hf_ntlmssp_auth_username,
3288 { "User name", "ntlmssp.auth.username",
3289 FT_STRING, BASE_NONE, NULL, 0x0,
3290 NULL, HFILL }
3292 { &hf_ntlmssp_auth_hostname,
3293 { "Host name", "ntlmssp.auth.hostname",
3294 FT_STRING, BASE_NONE, NULL, 0x0,
3295 NULL, HFILL }
3297 { &hf_ntlmssp_auth_lmresponse,
3298 { "Lan Manager Response", "ntlmssp.auth.lmresponse",
3299 FT_BYTES, BASE_NONE, NULL, 0x0,
3300 NULL, HFILL }
3302 { &hf_ntlmssp_auth_ntresponse,
3303 { "NTLM Response", "ntlmssp.auth.ntresponse",
3304 FT_BYTES, BASE_NONE, NULL, 0x0,
3305 NULL, HFILL }
3307 { &hf_ntlmssp_auth_sesskey,
3308 { "Session Key", "ntlmssp.auth.sesskey",
3309 FT_BYTES, BASE_NONE, NULL, 0x0,
3310 NULL, HFILL }
3312 { &hf_ntlmssp_string_len,
3313 { "Length", "ntlmssp.string.length",
3314 FT_UINT16, BASE_DEC, NULL, 0x0,
3315 NULL, HFILL}
3317 { &hf_ntlmssp_string_maxlen,
3318 { "Maxlen", "ntlmssp.string.maxlen",
3319 FT_UINT16, BASE_DEC, NULL, 0x0,
3320 NULL, HFILL}
3322 { &hf_ntlmssp_string_offset,
3323 { "Offset", "ntlmssp.string.offset",
3324 FT_UINT32, BASE_DEC, NULL, 0x0,
3325 NULL, HFILL}
3327 { &hf_ntlmssp_blob_len,
3328 { "Length", "ntlmssp.blob.length",
3329 FT_UINT16, BASE_DEC, NULL, 0x0,
3330 NULL, HFILL}
3332 { &hf_ntlmssp_blob_maxlen,
3333 { "Maxlen", "ntlmssp.blob.maxlen",
3334 FT_UINT16, BASE_DEC, NULL, 0x0,
3335 NULL, HFILL}
3337 { &hf_ntlmssp_blob_offset,
3338 { "Offset", "ntlmssp.blob.offset",
3339 FT_UINT32, BASE_DEC, NULL, 0x0,
3340 NULL, HFILL}
3342 { &hf_ntlmssp_version,
3343 { "Version", "ntlmssp.version",
3344 FT_NONE, BASE_NONE, NULL, 0x0,
3345 NULL, HFILL}
3347 { &hf_ntlmssp_version_major,
3348 { "Major Version", "ntlmssp.version.major",
3349 FT_UINT8, BASE_DEC, NULL, 0x0,
3350 NULL, HFILL}
3352 { &hf_ntlmssp_version_minor,
3353 { "Minor Version", "ntlmssp.version.minor",
3354 FT_UINT8, BASE_DEC, NULL, 0x0,
3355 NULL, HFILL}
3357 { &hf_ntlmssp_version_build_number,
3358 { "Build Number", "ntlmssp.version.build_number",
3359 FT_UINT16, BASE_DEC, NULL, 0x0,
3360 NULL, HFILL}
3362 { &hf_ntlmssp_version_ntlm_current_revision,
3363 { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision",
3364 FT_UINT8, BASE_DEC, NULL, 0x0,
3365 NULL, HFILL}
3368 /* Target Info */
3369 { &hf_ntlmssp_challenge_target_info,
3370 { "Target Info", "ntlmssp.challenge.target_info",
3371 FT_NONE, BASE_NONE, NULL, 0x0,
3372 NULL, HFILL}
3374 { &hf_ntlmssp_challenge_target_info_len,
3375 { "Length", "ntlmssp.challenge.target_info.length",
3376 FT_UINT16, BASE_DEC, NULL, 0x0,
3377 NULL, HFILL}
3379 { &hf_ntlmssp_challenge_target_info_maxlen,
3380 { "Maxlen", "ntlmssp.challenge.target_info.maxlen",
3381 FT_UINT16, BASE_DEC, NULL, 0x0,
3382 NULL, HFILL}
3384 { &hf_ntlmssp_challenge_target_info_offset,
3385 { "Offset", "ntlmssp.challenge.target_info.offset",
3386 FT_UINT32, BASE_DEC, NULL, 0x0,
3387 NULL, HFILL}
3390 { &hf_ntlmssp_challenge_target_info_item_type,
3391 { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type",
3392 FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ntlm_name_types_ext, 0x0,
3393 NULL, HFILL }
3395 { &hf_ntlmssp_challenge_target_info_item_len,
3396 { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length",
3397 FT_UINT16, BASE_DEC, NULL, 0x0,
3398 NULL, HFILL}
3401 { &hf_ntlmssp_challenge_target_info_end,
3402 { "List End", "ntlmssp.challenge.target_info.end",
3403 FT_NONE, BASE_NONE, NULL, 0x0,
3404 NULL, HFILL }
3406 { &hf_ntlmssp_challenge_target_info_nb_computer_name,
3407 { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name",
3408 FT_STRING, BASE_NONE, NULL, 0x0,
3409 "Server NetBIOS Computer Name", HFILL }
3411 { &hf_ntlmssp_challenge_target_info_nb_domain_name,
3412 { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name",
3413 FT_STRING, BASE_NONE, NULL, 0x0,
3414 "Server NetBIOS Domain Name", HFILL }
3416 { &hf_ntlmssp_challenge_target_info_dns_computer_name,
3417 { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name",
3418 FT_STRING, BASE_NONE, NULL, 0x0,
3419 NULL, HFILL }
3421 { &hf_ntlmssp_challenge_target_info_dns_domain_name,
3422 { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name",
3423 FT_STRING, BASE_NONE, NULL, 0x0,
3424 NULL, HFILL }
3426 { &hf_ntlmssp_challenge_target_info_dns_tree_name,
3427 { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name",
3428 FT_STRING, BASE_NONE, NULL, 0x0,
3429 NULL, HFILL }
3431 { &hf_ntlmssp_challenge_target_info_flags,
3432 { "Flags", "ntlmssp.challenge.target_info.flags",
3433 FT_UINT32, BASE_HEX, NULL, 0x0,
3434 NULL, HFILL }
3436 { &hf_ntlmssp_challenge_target_info_timestamp,
3437 { "Timestamp", "ntlmssp.challenge.target_info.timestamp",
3438 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
3439 NULL, HFILL }
3441 { &hf_ntlmssp_challenge_target_info_restrictions,
3442 { "Restrictions", "ntlmssp.challenge.target_info.restrictions",
3443 FT_BYTES, BASE_NONE, NULL, 0,
3444 NULL, HFILL }
3446 { &hf_ntlmssp_challenge_target_info_target_name,
3447 { "Target Name", "ntlmssp.challenge.target_info.target_name",
3448 FT_STRING, BASE_NONE, NULL, 0x0,
3449 NULL, HFILL }
3451 { &hf_ntlmssp_challenge_target_info_channel_bindings,
3452 { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings",
3453 FT_BYTES, BASE_NONE, NULL, 0x0,
3454 NULL, HFILL }
3457 { &hf_ntlmssp_ntlmv2_response_item_type,
3458 { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type",
3459 FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ntlm_name_types_ext, 0x0,
3460 NULL, HFILL }
3462 { &hf_ntlmssp_ntlmv2_response_item_len,
3463 { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length",
3464 FT_UINT16, BASE_DEC, NULL, 0x0,
3465 NULL, HFILL}
3468 { &hf_ntlmssp_ntlmv2_response_end,
3469 { "List End", "ntlmssp.ntlmv2_response.end",
3470 FT_NONE, BASE_NONE, NULL, 0x0,
3471 NULL, HFILL }
3473 { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
3474 { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name",
3475 FT_STRING, BASE_NONE, NULL, 0x0,
3476 "Server NetBIOS Computer Name", HFILL }
3478 { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
3479 { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name",
3480 FT_STRING, BASE_NONE, NULL, 0x0,
3481 "Server NetBIOS Domain Name", HFILL }
3483 { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
3484 { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name",
3485 FT_STRING, BASE_NONE, NULL, 0x0,
3486 NULL, HFILL }
3488 { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
3489 { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name",
3490 FT_STRING, BASE_NONE, NULL, 0x0,
3491 NULL, HFILL }
3493 { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
3494 { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name",
3495 FT_STRING, BASE_NONE, NULL, 0x0,
3496 NULL, HFILL }
3498 { &hf_ntlmssp_ntlmv2_response_flags,
3499 { "Flags", "ntlmssp.ntlmv2_response.flags",
3500 FT_UINT32, BASE_HEX, NULL, 0x0,
3501 NULL, HFILL }
3503 { &hf_ntlmssp_ntlmv2_response_timestamp,
3504 { "Timestamp", "ntlmssp.ntlmv2_response.timestamp",
3505 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
3506 NULL, HFILL }
3508 { &hf_ntlmssp_ntlmv2_response_restrictions,
3509 { "Restrictions", "ntlmssp.ntlmv2_response.restrictions",
3510 FT_BYTES, BASE_NONE, NULL, 0,
3511 NULL, HFILL }
3513 { &hf_ntlmssp_ntlmv2_response_target_name,
3514 { "Target Name", "ntlmssp.ntlmv2_response.target_name",
3515 FT_STRING, BASE_NONE, NULL, 0x0,
3516 NULL, HFILL }
3518 { &hf_ntlmssp_ntlmv2_response_channel_bindings,
3519 { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings",
3520 FT_BYTES, BASE_NONE, NULL, 0x0,
3521 NULL, HFILL }
3524 { &hf_ntlmssp_message_integrity_code,
3525 { "MIC", "ntlmssp.authenticate.mic",
3526 FT_BYTES, BASE_NONE, NULL, 0x0,
3527 "Message Integrity Code", HFILL}
3529 { &hf_ntlmssp_verf,
3530 { "NTLMSSP Verifier", "ntlmssp.verf",
3531 FT_NONE, BASE_NONE, NULL, 0x0,
3532 NULL, HFILL }
3534 { &hf_ntlmssp_verf_vers,
3535 { "Version Number", "ntlmssp.verf.vers",
3536 FT_UINT32, BASE_DEC, NULL, 0x0,
3537 NULL, HFILL }
3539 { &hf_ntlmssp_verf_body,
3540 { "Verifier Body", "ntlmssp.verf.body",
3541 FT_BYTES, BASE_NONE, NULL, 0x0,
3542 NULL, HFILL }
3544 #if 0
3545 { &hf_ntlmssp_decrypted_payload,
3546 { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload",
3547 FT_BYTES, BASE_NONE, NULL, 0x0,
3548 NULL, HFILL }
3550 #endif
3551 { &hf_ntlmssp_verf_randompad,
3552 { "Random Pad", "ntlmssp.verf.randompad",
3553 FT_UINT32, BASE_HEX, NULL, 0x0,
3554 NULL, HFILL }
3556 { &hf_ntlmssp_verf_crc32,
3557 { "Verifier CRC32", "ntlmssp.verf.crc32",
3558 FT_UINT32, BASE_HEX, NULL, 0x0,
3559 NULL, HFILL }
3561 { &hf_ntlmssp_verf_hmacmd5,
3562 { "HMAC MD5", "ntlmssp.verf.hmacmd5",
3563 FT_BYTES, BASE_NONE, NULL, 0x0,
3564 NULL, HFILL }
3566 { &hf_ntlmssp_verf_sequence,
3567 { "Sequence", "ntlmssp.verf.sequence",
3568 FT_BYTES, BASE_NONE, NULL, 0x0,
3569 NULL, HFILL }
3572 { &hf_ntlmssp_ntlmv2_response,
3573 { "NTLMv2 Response", "ntlmssp.ntlmv2_response",
3574 FT_BYTES, BASE_NONE, NULL, 0x0,
3575 NULL, HFILL }
3577 { &hf_ntlmssp_ntlmv2_response_ntproofstr,
3578 { "NTProofStr", "ntlmssp.ntlmv2_response.ntproofstr",
3579 FT_BYTES, BASE_NONE, NULL, 0x0,
3580 "The HMAC-MD5 of the challenge", HFILL }
3582 { &hf_ntlmssp_ntlmv2_response_rversion,
3583 { "Response Version", "ntlmssp.ntlmv2_response.rversion",
3584 FT_UINT8, BASE_DEC, NULL, 0x0,
3585 "The 1-byte response version, currently set to 1", HFILL }
3587 { &hf_ntlmssp_ntlmv2_response_hirversion,
3588 { "Hi Response Version", "ntlmssp.ntlmv2_response.hirversion",
3589 FT_UINT8, BASE_DEC, NULL, 0x0,
3590 "The 1-byte highest response version understood by the client, currently set to 1", HFILL }
3592 { &hf_ntlmssp_ntlmv2_response_z,
3593 { "Z", "ntlmssp.ntlmv2_response.z",
3594 FT_BYTES, BASE_NONE, NULL, 0x0,
3595 "byte array of zero bytes", HFILL }
3597 { &hf_ntlmssp_ntlmv2_response_pad,
3598 { "padding", "ntlmssp.ntlmv2_response.pad",
3599 FT_BYTES, BASE_NONE, NULL, 0x0,
3600 NULL, HFILL }
3602 { &hf_ntlmssp_ntlmv2_response_time,
3603 { "Time", "ntlmssp.ntlmv2_response.time",
3604 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
3605 "The 8-byte little-endian time in UTC", HFILL }
3607 { &hf_ntlmssp_ntlmv2_response_chal,
3608 { "NTLMv2 Client Challenge", "ntlmssp.ntlmv2_response.chal",
3609 FT_BYTES, BASE_NONE, NULL, 0x0,
3610 "The 8-byte NTLMv2 challenge message generated by the client", HFILL }
3612 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL,
3613 { "NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL",
3614 FT_NONE, BASE_NONE, NULL, 0,
3615 NULL, HFILL }},
3616 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Version,
3617 { "Version", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.Version",
3618 FT_UINT32, BASE_HEX, VALS(MSV1_0_CRED_VERSION), 0,
3619 NULL, HFILL }},
3620 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Flags,
3621 { "Flags", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.Flags",
3622 FT_UINT32, BASE_HEX, NULL, 0,
3623 NULL, HFILL }},
3624 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_LM_PRESENT,
3625 { "lm_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.LM_PRESENT",
3626 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_LM_PRESENT,
3627 NULL, HFILL }},
3628 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_NT_PRESENT,
3629 { "nt_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.NT_PRESENT",
3630 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_NT_PRESENT,
3631 NULL, HFILL }},
3632 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_REMOVED,
3633 { "removed", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.REMOVED",
3634 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_REMOVED,
3635 NULL, HFILL }},
3636 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_CREDKEY_PRESENT,
3637 { "credkey_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.CREDKEY_PRESENT",
3638 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_CREDKEY_PRESENT,
3639 NULL, HFILL }},
3640 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_SHA_PRESENT,
3641 { "sha_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.SHA_PRESENT",
3642 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_SHA_PRESENT,
3643 NULL, HFILL }},
3644 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKey,
3645 { "CredentialKey", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.CredentialKey",
3646 FT_BYTES, BASE_NONE, NULL, 0,
3647 NULL, HFILL }},
3648 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKeyType,
3649 { "CredentialKeyType", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.CredentialKeyType",
3650 FT_UINT32, BASE_DEC, VALS(MSV1_0_CREDENTIAL_KEY_TYPE), 0,
3651 NULL, HFILL }},
3652 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCredsSize,
3653 { "EncryptedCredsSize", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.EncryptedCredsSize",
3654 FT_UINT32, BASE_DEC, NULL, 0,
3655 NULL, HFILL }},
3656 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCreds,
3657 { "EncryptedCreds", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.EncryptedCreds",
3658 FT_BYTES, BASE_NONE, NULL, 0,
3659 NULL, HFILL }},
3663 static int *ett[] = {
3664 &ett_ntlmssp,
3665 &ett_ntlmssp_negotiate_flags,
3666 &ett_ntlmssp_string,
3667 &ett_ntlmssp_blob,
3668 &ett_ntlmssp_version,
3669 &ett_ntlmssp_challenge_target_info,
3670 &ett_ntlmssp_challenge_target_info_item,
3671 &ett_ntlmssp_ntlmv2_response,
3672 &ett_ntlmssp_ntlmv2_response_item,
3673 &ett_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL,
3675 static ei_register_info ei[] = {
3676 { &ei_ntlmssp_v2_key_too_long, { "ntlmssp.v2_key_too_long", PI_UNDECODED, PI_WARN, "NTLM v2 key is too long", EXPFILL }},
3677 { &ei_ntlmssp_blob_len_too_long, { "ntlmssp.blob.length.too_long", PI_UNDECODED, PI_WARN, "Session blob length too long", EXPFILL }},
3678 { &ei_ntlmssp_target_info_attr, { "ntlmssp.target_info_attr.unknown", PI_UNDECODED, PI_WARN, "Unknown NTLMSSP Target Info Attribute", EXPFILL }},
3679 { &ei_ntlmssp_target_info_invalid, { "ntlmssp.target_info_attr.invalid", PI_UNDECODED, PI_WARN, "Invalid NTLMSSP Target Info AvPairs", EXPFILL }},
3680 { &ei_ntlmssp_message_type, { "ntlmssp.messagetype.unknown", PI_PROTOCOL, PI_WARN, "Unrecognized NTLMSSP Message", EXPFILL }},
3681 { &ei_ntlmssp_auth_nthash, { "ntlmssp.authenticated", PI_SECURITY, PI_CHAT, "Authenticated NTHASH", EXPFILL }},
3682 { &ei_ntlmssp_sessionbasekey, { "ntlmssp.sessionbasekey", PI_SECURITY, PI_CHAT, "SessionBaseKey", EXPFILL }},
3683 { &ei_ntlmssp_sessionkey, { "ntlmssp.sessionkey", PI_SECURITY, PI_CHAT, "SessionKey", EXPFILL }},
3685 module_t *ntlmssp_module;
3686 expert_module_t* expert_ntlmssp;
3688 proto_ntlmssp = proto_register_protocol (
3689 "NTLM Secure Service Provider", /* name */
3690 "NTLMSSP", /* short name */
3691 "ntlmssp" /* abbrev */
3693 proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
3694 proto_register_subtree_array (ett, array_length (ett));
3695 expert_ntlmssp = expert_register_protocol(proto_ntlmssp);
3696 expert_register_field_array(expert_ntlmssp, ei, array_length(ei));
3697 register_init_routine(&ntlmssp_init_protocol);
3698 register_cleanup_routine(&ntlmssp_cleanup_protocol);
3700 ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
3702 prefs_register_string_preference(ntlmssp_module, "nt_password",
3703 "NT Password",
3704 "Cleartext NT Password (used to decrypt payloads, supports only ASCII passwords)",
3705 &ntlmssp_option_nt_password);
3707 ntlmssp_handle = register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
3708 ntlmssp_wrap_handle = register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
3709 register_dissector("ntlmssp_data_only", dissect_ntlmssp_payload_only, proto_ntlmssp);
3710 register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
3712 ntlmssp_tap = register_tap("ntlmssp");
3715 void
3716 proto_reg_handoff_ntlmssp(void)
3718 /* Register protocol with the GSS-API module */
3720 gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
3721 ntlmssp_handle, ntlmssp_wrap_handle,
3722 "NTLMSSP - Microsoft NTLM Security Support Provider");
3724 /* Register authenticated pipe dissector */
3727 * XXX - the verifiers here seem to have a version of 1 and a body of all
3728 * zeroes.
3730 * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
3731 * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
3732 * any other levels here?
3734 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
3735 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3736 &ntlmssp_sign_fns);
3738 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
3739 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3740 &ntlmssp_sign_fns);
3742 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
3743 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3744 &ntlmssp_sign_fns);
3746 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
3747 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3748 &ntlmssp_seal_fns);
3752 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3754 * Local variables:
3755 * c-basic-offset: 2
3756 * tab-width: 8
3757 * indent-tabs-mode: nil
3758 * End:
3760 * vi: set shiftwidth=2 tabstop=8 expandtab:
3761 * :indentSize=2:tabSize=8:noTabs=true: