epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-ntlmssp.c
blobc39b4d8076d423556371a08287bb9a304e2059a1
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_);
326 /* Debug function, log a hexdump of interesting memory */
327 static void printnbyte(wmem_allocator_t *scratch, const uint8_t* tab, int nb, const char* txt)
329 if (!ws_log_msg_is_active(WS_LOG_DOMAIN, LOG_LEVEL_DEBUG))
331 return;
334 char *hexdump = wmem_alloc0(scratch, nb*3 + 1);
335 int i;
337 for (i=0; i<nb; i++)
339 snprintf(hexdump+(i*3), 3, "%02X ", *(tab+i));
341 hexdump[nb*3] = '\0';
343 ws_debug("%s %s", txt, hexdump);
345 #if 0
346 static void printnchar(wmem_allocator_t *scratch, const uint8_t* tab, int nb, char* txt)
348 if (!ws_log_msg_is_active(WS_LOG_DOMAIN, LOG_LEVEL_DEBUG))
350 return;
353 ws_debug("%s %s", txt, wmem_strndup(scratch, tab, nb));
355 #endif
358 * GSlist of decrypted payloads.
360 static GSList *decrypted_payloads;
362 #if 0
363 static int
364 LEBE_Convert(int value)
366 char a, b, c, d;
367 /* Get each byte */
368 a = value&0x000000FF;
369 b = (value&0x0000FF00) >> 8;
370 c = (value&0x00FF0000) >> 16;
371 d = (value&0xFF000000) >> 24;
372 return (a << 24) | (b << 16) | (c << 8) | d;
374 #endif
376 static bool
377 ntlmssp_sessions_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_)
379 ntlmssp_info * conv_ntlmssp_info = (ntlmssp_info *) user_data;
380 if (conv_ntlmssp_info->rc4_state_initialized) {
381 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
382 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
384 /* unregister this callback */
385 return false;
389 Perform a DES encryption with a 16-byte key and 8-byte data item.
390 It's in fact 3 susbsequent call to crypt_des_ecb with a 7-byte key.
391 Missing bytes for the key are replaced by 0;
392 Returns output in response, which is expected to be 24 bytes.
394 static int
395 crypt_des_ecb_long(uint8_t *response,
396 const uint8_t *key,
397 const uint8_t *data)
399 uint8_t pw21[21] = { 0 }; /* 21 bytes place for the needed key */
401 memcpy(pw21, key, 16);
403 memset(response, 0, 24);
404 crypt_des_ecb(response, data, pw21);
405 crypt_des_ecb(response + 8, data, pw21 + 7);
406 crypt_des_ecb(response + 16, data, pw21 + 14);
408 return 1;
412 Generate a challenge response, given an eight byte challenge and
413 either the NT or the Lan Manager password hash (16 bytes).
414 Returns output in response, which is expected to be 24 bytes.
416 static int
417 ntlmssp_generate_challenge_response(uint8_t *response,
418 const uint8_t *passhash,
419 const uint8_t *challenge)
421 uint8_t pw21[21]; /* Password hash padded to 21 bytes */
423 memset(pw21, 0x0, sizeof(pw21));
424 memcpy(pw21, passhash, 16);
426 memset(response, 0, 24);
428 crypt_des_ecb(response, challenge, pw21);
429 crypt_des_ecb(response + 8, challenge, pw21 + 7);
430 crypt_des_ecb(response + 16, challenge, pw21 + 14);
432 return 1;
436 /* Ultra simple ANSI to unicode converter, will only work for ascii password...*/
437 static void
438 ansi_to_unicode(const char* ansi, char* unicode)
440 size_t input_len;
441 size_t i;
443 input_len = strlen(ansi);
444 if (unicode != NULL) {
445 for (i = 0; i < (input_len); i++) {
446 unicode[i * 2] = ansi[i];
447 unicode[i * 2 + 1] = 0;
449 unicode[2 * input_len] = '\0';
453 /* This function generate the Key Exchange Key (KXKEY)
454 * Depending on the flags this key will either be used to encrypt the exported session key
455 * or will be used directly as exported session key.
456 * Exported session key is the key that will be used for sealing and signing communication
457 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d86303b5-b29e-4fb9-b119-77579c761370
460 static void
461 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)
463 uint8_t basekey[NTLMSSP_KEY_LEN];
464 uint8_t zeros[24] = { 0 };
466 memset(keyexchangekey, 0, NTLMSSP_KEY_LEN);
467 memset(basekey, 0, NTLMSSP_KEY_LEN);
468 /* sessionbasekey is either derived from lm_hash or from nt_hash depending on the key type negotiated */
469 memcpy(basekey, sessionbasekey, 8);
470 memset(basekey+8, 0xBD, 8);
471 if (flags&NTLMSSP_NEGOTIATE_LM_KEY) {
472 /*data, key*/
473 crypt_des_ecb(keyexchangekey, lm_challenge_response, basekey);
474 crypt_des_ecb(keyexchangekey+8, lm_challenge_response, basekey+7);
476 else {
477 if (flags&NTLMSSP_REQUEST_NON_NT_SESSION_KEY) {
478 /*People from samba tends to use the same function in this case than in the previous one but with 0 data
479 * it's not clear that it produce the good result
480 * memcpy(keyexchangekey, lm_hash, 8);
481 * Let's trust samba implementation it mights seem weird but they are more often right than the spec!
483 crypt_des_ecb(keyexchangekey, zeros, basekey);
484 crypt_des_ecb(keyexchangekey+8, zeros, basekey+7);
486 else {
487 /* 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
488 * 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!
490 memcpy(keyexchangekey, sessionbasekey, NTLMSSP_KEY_LEN);
495 uint32_t
496 get_md4pass_list(wmem_allocator_t *pool, md4_pass** p_pass_list)
498 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
499 uint32_t nb_pass = 0;
500 enc_key_t *ek;
501 const char* password = ntlmssp_option_nt_password;
502 unsigned char nt_hash[NTLMSSP_KEY_LEN];
503 char password_unicode[256];
504 md4_pass* pass_list;
505 int i;
507 *p_pass_list = NULL;
508 read_keytab_file_from_preferences();
510 for (ek=enc_key_list; ek; ek=ek->next) {
511 if (NTLMSSP_EK_IS_NT4HASH(ek)) {
512 nb_pass++;
515 memset(password_unicode, 0, sizeof(password_unicode));
516 memset(nt_hash, 0, NTLMSSP_KEY_LEN);
517 /* Compute the NT hash of the provided password, even if empty */
518 if (strlen(password) < 129) {
519 int password_len;
520 nb_pass++;
521 password_len = (int)strlen(password);
522 ansi_to_unicode(password, password_unicode);
523 gcry_md_hash_buffer(GCRY_MD_MD4, nt_hash, password_unicode, password_len*2);
525 if (nb_pass == 0) {
526 /* Unable to calculate the session key without a valid password (128 chars or less) ......*/
527 return 0;
529 i = 0;
530 *p_pass_list = (md4_pass *)wmem_alloc0(pool, nb_pass*sizeof(md4_pass));
531 pass_list = *p_pass_list;
533 if (memcmp(nt_hash, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
534 memcpy(pass_list[i].md4, nt_hash, NTLMSSP_KEY_LEN);
535 snprintf(pass_list[i].key_origin, NTLMSSP_MAX_ORIG_LEN,
536 "<Global NT Password>");
537 i = 1;
539 for (ek=enc_key_list; ek; ek=ek->next) {
540 if (NTLMSSP_EK_IS_NT4HASH(ek)) {
541 memcpy(pass_list[i].md4, ek->keyvalue, NTLMSSP_KEY_LEN);
542 memcpy(pass_list[i].key_origin, ek->key_origin,
543 MIN(sizeof(pass_list[i].key_origin),sizeof(ek->key_origin)));
544 i++;
547 return nb_pass;
548 #else /* !(defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)) */
549 (void) pool;
550 *p_pass_list = NULL;
551 return 0;
552 #endif /* !(defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)) */
555 /* Create an NTLMSSP version 2 key
556 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
558 static void
559 create_ntlmssp_v2_key(const uint8_t *serverchallenge, const uint8_t *clientchallenge,
560 uint8_t *sessionkey , const uint8_t *encryptedsessionkey , int flags ,
561 const ntlmssp_blob *ntlm_response, const ntlmssp_blob *lm_response _U_, ntlmssp_header_t *ntlmssph,
562 packet_info *pinfo, proto_tree *ntlmssp_tree)
564 /* static const would be nicer, but -Werror=vla does not like it */
565 #define DOMAIN_NAME_BUF_SIZE 512
566 #define USER_BUF_SIZE 256
567 #define BUF_SIZE (DOMAIN_NAME_BUF_SIZE + USER_BUF_SIZE)
568 char domain_name_unicode[DOMAIN_NAME_BUF_SIZE];
569 char user_uppercase[USER_BUF_SIZE];
570 char buf[BUF_SIZE];
571 /*uint8_t md4[NTLMSSP_KEY_LEN];*/
572 unsigned char nt_hash[NTLMSSP_KEY_LEN];
573 unsigned char nt_proof[NTLMSSP_KEY_LEN];
574 unsigned char ntowfv2[NTLMSSP_KEY_LEN];
575 uint8_t sessionbasekey[NTLMSSP_KEY_LEN];
576 uint8_t keyexchangekey[NTLMSSP_KEY_LEN];
577 uint8_t lm_challenge_response[24];
578 uint32_t i;
579 uint32_t j;
580 gcry_cipher_hd_t rc4_handle;
581 size_t user_len;
582 size_t domain_len;
583 md4_pass *pass_list = NULL;
584 const md4_pass *used_md4 = NULL;
585 uint32_t nb_pass = 0;
586 bool found = false;
588 /* We are going to try password encrypted in keytab as well, it's an idea of Stefan Metzmacher <metze@samba.org>
589 * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
591 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
592 nb_pass = get_md4pass_list(pinfo->pool, &pass_list);
593 i = 0;
594 memset(user_uppercase, 0, USER_BUF_SIZE);
595 user_len = strlen(ntlmssph->acct_name);
596 if (user_len < USER_BUF_SIZE / 2) {
597 memset(buf, 0, BUF_SIZE);
598 ansi_to_unicode(ntlmssph->acct_name, buf);
599 for (j = 0; j < (2*user_len); j++) {
600 if (buf[j] != '\0') {
601 user_uppercase[j] = g_ascii_toupper(buf[j]);
605 else {
606 /* Unable to calculate the session not enough space in buffer, note this is unlikely to happen but ......*/
607 return;
609 domain_len = strlen(ntlmssph->domain_name);
610 if (domain_len < DOMAIN_NAME_BUF_SIZE / 2) {
611 ansi_to_unicode(ntlmssph->domain_name, domain_name_unicode);
613 else {
614 /* Unable to calculate the session not enough space in buffer, note this is unlikely to happen but ......*/
615 return;
617 while (i < nb_pass) {
618 ws_debug("Turn %d", i);
619 used_md4 = &pass_list[i];
620 memcpy(nt_hash, pass_list[i].md4, NTLMSSP_KEY_LEN);
621 printnbyte(pinfo->pool, nt_hash, NTLMSSP_KEY_LEN, "Current NT hash: ");
622 i++;
623 /* NTOWFv2 computation */
624 memset(buf, 0, BUF_SIZE);
625 memcpy(buf, user_uppercase, user_len*2);
626 memcpy(buf+user_len*2, domain_name_unicode, domain_len*2);
627 if (ws_hmac_buffer(GCRY_MD_MD5, ntowfv2, buf, domain_len*2+user_len*2, nt_hash, NTLMSSP_KEY_LEN)) {
628 return;
630 printnbyte(pinfo->pool, ntowfv2, NTLMSSP_KEY_LEN, "NTOWFv2: ");
632 /* LM response */
633 memset(buf, 0, BUF_SIZE);
634 memcpy(buf, serverchallenge, 8);
635 memcpy(buf+8, clientchallenge, 8);
636 if (ws_hmac_buffer(GCRY_MD_MD5, lm_challenge_response, buf, NTLMSSP_KEY_LEN, ntowfv2, NTLMSSP_KEY_LEN)) {
637 return;
639 memcpy(lm_challenge_response+NTLMSSP_KEY_LEN, clientchallenge, 8);
640 printnbyte(pinfo->pool, lm_challenge_response, 24, "LM Response: ");
642 /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
643 memset(buf, 0, BUF_SIZE);
644 memcpy(buf, serverchallenge, 8);
645 memcpy(buf+8, ntlm_response->contents+NTLMSSP_KEY_LEN, MIN(BUF_SIZE - 8, ntlm_response->length-NTLMSSP_KEY_LEN));
646 if (ws_hmac_buffer(GCRY_MD_MD5, nt_proof, buf, ntlm_response->length-8, ntowfv2, NTLMSSP_KEY_LEN)) {
647 return;
649 printnbyte(pinfo->pool, nt_proof, NTLMSSP_KEY_LEN, "NT proof: ");
650 if (!memcmp(nt_proof, ntlm_response->contents, NTLMSSP_KEY_LEN)) {
651 found = true;
652 break;
655 if (!found) {
656 return;
659 if (ws_hmac_buffer(GCRY_MD_MD5, sessionbasekey, nt_proof, NTLMSSP_KEY_LEN, ntowfv2, NTLMSSP_KEY_LEN)) {
660 return;
663 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
664 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
665 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
667 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
668 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
669 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
670 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
672 gcry_cipher_close(rc4_handle);
675 else
677 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
680 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
682 if (used_md4 == NULL) {
683 return;
685 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
686 &ei_ntlmssp_auth_nthash,
687 "NTLMv2 authenticated using %s (%02x%02x%02x%02x...)",
688 used_md4->key_origin,
689 used_md4->md4[0] & 0xFF, used_md4->md4[1] & 0xFF,
690 used_md4->md4[2] & 0xFF, used_md4->md4[3] & 0xFF);
691 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
692 &ei_ntlmssp_sessionbasekey,
693 "NTLMv2 BaseSessionKey ("
694 "%02x%02x%02x%02x"
695 "%02x%02x%02x%02x"
696 "%02x%02x%02x%02x"
697 "%02x%02x%02x%02x"
698 ")",
699 sessionbasekey[0] & 0xFF, sessionbasekey[1] & 0xFF,
700 sessionbasekey[2] & 0xFF, sessionbasekey[3] & 0xFF,
701 sessionbasekey[4] & 0xFF, sessionbasekey[5] & 0xFF,
702 sessionbasekey[6] & 0xFF, sessionbasekey[7] & 0xFF,
703 sessionbasekey[8] & 0xFF, sessionbasekey[9] & 0xFF,
704 sessionbasekey[10] & 0xFF, sessionbasekey[11] & 0xFF,
705 sessionbasekey[12] & 0xFF, sessionbasekey[13] & 0xFF,
706 sessionbasekey[14] & 0xFF, sessionbasekey[15] & 0xFF);
707 if (memcmp(sessionbasekey, sessionkey, NTLMSSP_KEY_LEN) == 0) {
708 return;
710 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
711 &ei_ntlmssp_sessionkey,
712 "NTLMSSP SessionKey ("
713 "%02x%02x%02x%02x"
714 "%02x%02x%02x%02x"
715 "%02x%02x%02x%02x"
716 "%02x%02x%02x%02x"
717 ")",
718 sessionkey[0] & 0xFF, sessionkey[1] & 0xFF,
719 sessionkey[2] & 0xFF, sessionkey[3] & 0xFF,
720 sessionkey[4] & 0xFF, sessionkey[5] & 0xFF,
721 sessionkey[6] & 0xFF, sessionkey[7] & 0xFF,
722 sessionkey[8] & 0xFF, sessionkey[9] & 0xFF,
723 sessionkey[10] & 0xFF, sessionkey[11] & 0xFF,
724 sessionkey[12] & 0xFF, sessionkey[13] & 0xFF,
725 sessionkey[14] & 0xFF, sessionkey[15] & 0xFF);
728 /* Create an NTLMSSP version 1 key
729 * That is more complicated logic and methods and user challenge as well.
730 * password points to the ANSI password to encrypt, challenge points to
731 * the 8 octet challenge string
732 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
734 static void
735 create_ntlmssp_v1_key(const uint8_t *serverchallenge, const uint8_t *clientchallenge,
736 uint8_t *sessionkey, const uint8_t *encryptedsessionkey, int flags,
737 const uint8_t *ref_nt_challenge_response, const uint8_t *ref_lm_challenge_response,
738 ntlmssp_header_t *ntlmssph,
739 packet_info *pinfo, proto_tree *ntlmssp_tree)
741 const char *password = ntlmssp_option_nt_password;
742 unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
743 unsigned char lm_hash[NTLMSSP_KEY_LEN];
744 unsigned char nt_hash[NTLMSSP_KEY_LEN];
745 unsigned char challenges_hash_first8[8];
746 unsigned char challenges[NTLMSSP_KEY_LEN];
747 uint8_t md4[NTLMSSP_KEY_LEN];
748 uint8_t nb_pass = 0;
749 uint8_t sessionbasekey[NTLMSSP_KEY_LEN];
750 uint8_t keyexchangekey[NTLMSSP_KEY_LEN];
751 uint8_t lm_challenge_response[24];
752 uint8_t nt_challenge_response[24];
753 gcry_cipher_hd_t rc4_handle;
754 gcry_md_hd_t md5_handle;
755 char password_unicode[256];
756 size_t password_len;
757 unsigned int i;
758 bool found = false;
759 md4_pass *pass_list = NULL;
760 const md4_pass *used_md4 = NULL;
762 // "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."
763 // "<35> Section 3.1.1.1: Windows NT Server 4.0 SP3 does not support providing NTLM instead of LM responses."
764 // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/f711d059-3983-4b9d-afbb-ff2f8c97ffbf
765 static const bool NoLMResponseNTLMv1 = true;
767 static const unsigned char lmhash_key[] =
768 {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; // "KGS!@#$%"
770 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
771 /* Create a NT hash of the input password, even if empty */
772 // NTOWFv1 as defined in https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
773 password_len = strlen(password);
774 /*Do not forget to free password*/
775 ansi_to_unicode(password, password_unicode);
776 gcry_md_hash_buffer(GCRY_MD_MD4, nt_hash, password_unicode, password_len*2);
778 if ((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NoLMResponseNTLMv1)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
779 /* Create a LM hash of the input password, even if empty */
780 // LMOWFv1 as defined in https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
781 /* Truncate password if too long */
782 if (password_len > NTLMSSP_KEY_LEN)
783 password_len = NTLMSSP_KEY_LEN;
785 memset(lm_password_upper, 0, sizeof(lm_password_upper));
786 for (i = 0; i < password_len; i++) {
787 lm_password_upper[i] = g_ascii_toupper(password[i]);
790 crypt_des_ecb(lm_hash, lmhash_key, lm_password_upper);
791 crypt_des_ecb(lm_hash+8, lmhash_key, lm_password_upper+7);
792 ntlmssp_generate_challenge_response(lm_challenge_response,
793 lm_hash, serverchallenge);
794 memcpy(sessionbasekey, lm_hash, NTLMSSP_KEY_LEN);
796 else {
798 memset(lm_challenge_response, 0, 24);
799 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
800 nb_pass = get_md4pass_list(pinfo->pool, &pass_list);
801 i = 0;
802 while (i < nb_pass) {
803 /*ws_debug("Turn %d", i);*/
804 used_md4 = &pass_list[i];
805 memcpy(nt_hash, pass_list[i].md4, NTLMSSP_KEY_LEN);
806 /*printnbyte(pinfo->pool, nt_hash, NTLMSSP_KEY_LEN, "Current NT hash: ");*/
807 i++;
808 if(clientchallenge){
809 memcpy(lm_challenge_response, clientchallenge, 8);
811 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
812 break;
814 gcry_md_write(md5_handle, serverchallenge, 8);
815 gcry_md_write(md5_handle, clientchallenge, 8);
816 memcpy(challenges_hash_first8, gcry_md_read(md5_handle, 0), 8);
817 gcry_md_close(md5_handle);
818 crypt_des_ecb_long(nt_challenge_response, nt_hash, challenges_hash_first8);
819 if (ref_nt_challenge_response && !memcmp(ref_nt_challenge_response, nt_challenge_response, 24)) {
820 found = true;
821 break;
825 else {
826 crypt_des_ecb_long(nt_challenge_response, nt_hash, serverchallenge);
827 if (NoLMResponseNTLMv1) {
828 memcpy(lm_challenge_response, nt_challenge_response, 24);
830 else {
831 crypt_des_ecb_long(lm_challenge_response, lm_hash, serverchallenge);
833 if (ref_nt_challenge_response &&
834 !memcmp(ref_nt_challenge_response, nt_challenge_response, 24) &&
835 ref_lm_challenge_response &&
836 !memcmp(ref_lm_challenge_response, lm_challenge_response, 24))
838 found = true;
841 /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
842 * that sessionbasekey should be based md4(nt_hash) only in the case of some NT auth
843 * Otherwise it should be lm_hash ...*/
844 gcry_md_hash_buffer(GCRY_MD_MD4, md4, nt_hash, NTLMSSP_KEY_LEN);
845 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
846 memcpy(challenges, serverchallenge, 8);
847 if(clientchallenge){
848 memcpy(challenges+8, clientchallenge, 8);
850 if (ws_hmac_buffer(GCRY_MD_MD5, sessionbasekey, challenges, NTLMSSP_KEY_LEN, md4, NTLMSSP_KEY_LEN)) {
851 return;
854 else {
855 memcpy(sessionbasekey, md4, NTLMSSP_KEY_LEN);
859 if (!found) {
860 return;
863 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
864 /*printnbyte(pinfo->pool, nt_challenge_response, 24, "NT challenge response");
865 printnbyte(pinfo->pool, lm_challenge_response, 24, "LM challenge response");*/
866 /* now decrypt session key if needed and setup sessionkey for decrypting further communications */
867 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
869 if(encryptedsessionkey){
870 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
872 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
873 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
874 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
876 gcry_cipher_close(rc4_handle);
879 else
881 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
883 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
885 if (used_md4 == NULL) {
886 return;
888 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
889 &ei_ntlmssp_auth_nthash,
890 "NTLMv1 authenticated using %s (%02x%02x%02x%02x...)",
891 used_md4->key_origin,
892 used_md4->md4[0] & 0xFF, used_md4->md4[1] & 0xFF,
893 used_md4->md4[2] & 0xFF, used_md4->md4[3] & 0xFF);
894 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
895 &ei_ntlmssp_sessionbasekey,
896 "NTLMv1 BaseSessionKey ("
897 "%02x%02x%02x%02x"
898 "%02x%02x%02x%02x"
899 "%02x%02x%02x%02x"
900 "%02x%02x%02x%02x"
901 ")",
902 sessionbasekey[0] & 0xFF, sessionbasekey[1] & 0xFF,
903 sessionbasekey[2] & 0xFF, sessionbasekey[3] & 0xFF,
904 sessionbasekey[4] & 0xFF, sessionbasekey[5] & 0xFF,
905 sessionbasekey[6] & 0xFF, sessionbasekey[7] & 0xFF,
906 sessionbasekey[8] & 0xFF, sessionbasekey[9] & 0xFF,
907 sessionbasekey[10] & 0xFF, sessionbasekey[11] & 0xFF,
908 sessionbasekey[12] & 0xFF, sessionbasekey[13] & 0xFF,
909 sessionbasekey[14] & 0xFF, sessionbasekey[15] & 0xFF);
910 if (memcmp(sessionbasekey, sessionkey, NTLMSSP_KEY_LEN) == 0) {
911 return;
913 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
914 &ei_ntlmssp_sessionkey,
915 "NTLMSSP SessionKey ("
916 "%02x%02x%02x%02x"
917 "%02x%02x%02x%02x"
918 "%02x%02x%02x%02x"
919 "%02x%02x%02x%02x"
920 ")",
921 sessionkey[0] & 0xFF, sessionkey[1] & 0xFF,
922 sessionkey[2] & 0xFF, sessionkey[3] & 0xFF,
923 sessionkey[4] & 0xFF, sessionkey[5] & 0xFF,
924 sessionkey[6] & 0xFF, sessionkey[7] & 0xFF,
925 sessionkey[8] & 0xFF, sessionkey[9] & 0xFF,
926 sessionkey[10] & 0xFF, sessionkey[11] & 0xFF,
927 sessionkey[12] & 0xFF, sessionkey[13] & 0xFF,
928 sessionkey[14] & 0xFF, sessionkey[15] & 0xFF);
932 * Create an NTLMSSP anonymous key
934 static void
935 create_ntlmssp_anon_key(uint8_t *sessionkey, const uint8_t *encryptedsessionkey, int flags,
936 ntlmssp_header_t *ntlmssph,
937 packet_info *pinfo, proto_tree *ntlmssp_tree)
939 uint8_t lm_challenge_response[24] = { 0, };
940 uint8_t sessionbasekey[NTLMSSP_KEY_LEN] = { 0, };
941 uint8_t keyexchangekey[NTLMSSP_KEY_LEN] = { 0, };
942 gcry_cipher_hd_t rc4_handle;
944 memset(sessionkey, 0, NTLMSSP_KEY_LEN);
946 get_keyexchange_key(keyexchangekey, sessionbasekey, lm_challenge_response, flags);
947 if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
949 if(encryptedsessionkey){
950 memcpy(sessionkey, encryptedsessionkey, NTLMSSP_KEY_LEN);
952 if (!gcry_cipher_open(&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
953 if (!gcry_cipher_setkey(rc4_handle, keyexchangekey, NTLMSSP_KEY_LEN)) {
954 gcry_cipher_decrypt(rc4_handle, sessionkey, NTLMSSP_KEY_LEN, NULL, 0);
956 gcry_cipher_close(rc4_handle);
959 else
961 memcpy(sessionkey, keyexchangekey, NTLMSSP_KEY_LEN);
963 memcpy(ntlmssph->session_key, sessionkey, NTLMSSP_KEY_LEN);
965 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
966 &ei_ntlmssp_auth_nthash,
967 "NTLM authenticated using ANONYMOUS ZERO NTHASH");
968 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
969 &ei_ntlmssp_sessionbasekey,
970 "NTLM Anonymous BaseSessionKey ("
971 "%02x%02x%02x%02x"
972 "%02x%02x%02x%02x"
973 "%02x%02x%02x%02x"
974 "%02x%02x%02x%02x"
975 ")",
976 sessionbasekey[0] & 0xFF, sessionbasekey[1] & 0xFF,
977 sessionbasekey[2] & 0xFF, sessionbasekey[3] & 0xFF,
978 sessionbasekey[4] & 0xFF, sessionbasekey[5] & 0xFF,
979 sessionbasekey[6] & 0xFF, sessionbasekey[7] & 0xFF,
980 sessionbasekey[8] & 0xFF, sessionbasekey[9] & 0xFF,
981 sessionbasekey[10] & 0xFF, sessionbasekey[11] & 0xFF,
982 sessionbasekey[12] & 0xFF, sessionbasekey[13] & 0xFF,
983 sessionbasekey[14] & 0xFF, sessionbasekey[15] & 0xFF);
984 if (memcmp(sessionbasekey, sessionkey, NTLMSSP_KEY_LEN) == 0) {
985 return;
987 expert_add_info_format(pinfo, proto_tree_get_parent(ntlmssp_tree),
988 &ei_ntlmssp_sessionkey,
989 "NTLMSSP SessionKey Anonymous ("
990 "%02x%02x%02x%02x"
991 "%02x%02x%02x%02x"
992 "%02x%02x%02x%02x"
993 "%02x%02x%02x%02x"
994 ")",
995 sessionkey[0] & 0xFF, sessionkey[1] & 0xFF,
996 sessionkey[2] & 0xFF, sessionkey[3] & 0xFF,
997 sessionkey[4] & 0xFF, sessionkey[5] & 0xFF,
998 sessionkey[6] & 0xFF, sessionkey[7] & 0xFF,
999 sessionkey[8] & 0xFF, sessionkey[9] & 0xFF,
1000 sessionkey[10] & 0xFF, sessionkey[11] & 0xFF,
1001 sessionkey[12] & 0xFF, sessionkey[13] & 0xFF,
1002 sessionkey[14] & 0xFF, sessionkey[15] & 0xFF);
1005 void
1006 ntlmssp_create_session_key(packet_info *pinfo,
1007 proto_tree *tree,
1008 ntlmssp_header_t *ntlmssph,
1009 int flags,
1010 const uint8_t *server_challenge,
1011 const uint8_t *encryptedsessionkey,
1012 const ntlmssp_blob *ntlm_response,
1013 const ntlmssp_blob *lm_response)
1015 uint8_t client_challenge[8] = {0, };
1016 uint8_t sessionkey[NTLMSSP_KEY_LEN] = {0, };
1018 if (ntlm_response->length > 24)
1021 * [MS-NLMP] 2.2.2.8 NTLM2 V2 Response: NTLMv2_RESPONSE has
1022 * the 2.2.2.7 "NTLM v2: NTLMv2_CLIENT_CHALLENGE" at offset 16.
1023 * Within that ChallengeFromClient is at offset 16, that means
1024 * it's at offset 32 in total.
1026 * Note that value is only used for the LM_response of NTLMv2.
1028 if (ntlm_response->length >= 40) {
1029 memcpy(client_challenge,
1030 ntlm_response->contents+32, 8);
1032 create_ntlmssp_v2_key(server_challenge,
1033 client_challenge,
1034 sessionkey,
1035 encryptedsessionkey,
1036 flags,
1037 ntlm_response,
1038 lm_response,
1039 ntlmssph,
1040 pinfo,
1041 tree);
1043 else if (ntlm_response->length == 24 && lm_response->length == 24)
1045 memcpy(client_challenge, lm_response->contents, 8);
1047 create_ntlmssp_v1_key(server_challenge,
1048 client_challenge,
1049 sessionkey,
1050 encryptedsessionkey,
1051 flags,
1052 ntlm_response->contents,
1053 lm_response->contents,
1054 ntlmssph,
1055 pinfo,
1056 tree);
1058 else if (ntlm_response->length == 0 && lm_response->length <= 1)
1060 create_ntlmssp_anon_key(sessionkey,
1061 encryptedsessionkey,
1062 flags,
1063 ntlmssph,
1064 pinfo,
1065 tree);
1069 static void
1070 get_signing_key(uint8_t *sign_key_server, uint8_t* sign_key_client, const uint8_t key[NTLMSSP_KEY_LEN], int keylen)
1072 gcry_md_hd_t md5_handle;
1074 memset(sign_key_client, 0, NTLMSSP_KEY_LEN);
1075 memset(sign_key_server, 0, NTLMSSP_KEY_LEN);
1076 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
1077 return;
1079 gcry_md_write(md5_handle, key, keylen);
1080 gcry_md_write(md5_handle, CLIENT_SIGN_TEXT, strlen(CLIENT_SIGN_TEXT)+1); // +1 to get the final null-byte
1081 memcpy(sign_key_client, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1082 gcry_md_reset(md5_handle);
1083 gcry_md_write(md5_handle, key, keylen);
1084 gcry_md_write(md5_handle, SERVER_SIGN_TEXT, strlen(SERVER_SIGN_TEXT)+1); // +1 to get the final null-byte
1085 memcpy(sign_key_server, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1086 gcry_md_close(md5_handle);
1089 /* We return either a 128 or 64 bit key
1091 static void
1092 get_sealing_rc4key(const uint8_t exportedsessionkey[NTLMSSP_KEY_LEN] , const int flags , int *keylen ,
1093 uint8_t *clientsealkey , uint8_t *serversealkey)
1095 gcry_md_hd_t md5_handle;
1097 memset(clientsealkey, 0, NTLMSSP_KEY_LEN);
1098 memset(serversealkey, 0, NTLMSSP_KEY_LEN);
1099 memcpy(clientsealkey, exportedsessionkey, NTLMSSP_KEY_LEN);
1100 if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)
1102 if (flags & NTLMSSP_NEGOTIATE_128)
1104 /* The exportedsessionkey has already the good length just update the length*/
1105 *keylen = 16;
1107 else
1109 if (flags & NTLMSSP_NEGOTIATE_56)
1111 memset(clientsealkey+7, 0, 9);
1112 *keylen = 7;
1114 else
1116 memset(clientsealkey+5, 0, 11);
1117 *keylen = 5;
1120 memcpy(serversealkey, clientsealkey, NTLMSSP_KEY_LEN);
1121 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
1122 return;
1124 gcry_md_write(md5_handle, clientsealkey, *keylen);
1125 gcry_md_write(md5_handle, CLIENT_SEAL_TEXT, strlen(CLIENT_SEAL_TEXT)+1); // +1 to get the final null-byte
1126 memcpy(clientsealkey, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1127 gcry_md_reset(md5_handle);
1128 gcry_md_write(md5_handle, serversealkey, *keylen);
1129 gcry_md_write(md5_handle, SERVER_SEAL_TEXT, strlen(SERVER_SEAL_TEXT)+1); // +1 to get the final null-byte
1130 memcpy(serversealkey, gcry_md_read(md5_handle, 0), NTLMSSP_KEY_LEN);
1131 gcry_md_close(md5_handle);
1133 else
1135 if (flags & NTLMSSP_NEGOTIATE_128)
1137 /* The exportedsessionkey has already the good length just update the length*/
1138 *keylen = 16;
1140 else
1142 *keylen = 8;
1143 if (flags & NTLMSSP_NEGOTIATE_56)
1145 memset(clientsealkey+7, 0, 9);
1147 else
1149 memset(clientsealkey+5, 0, 11);
1150 clientsealkey[5]=0xe5;
1151 clientsealkey[6]=0x38;
1152 clientsealkey[7]=0xb0;
1155 memcpy(serversealkey, clientsealkey,*keylen);
1158 /* Create an NTLMSSP version 1 key.
1159 * password points to the ANSI password to encrypt, challenge points to
1160 * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
1161 * otherwise it will do a 40 bit key. The result is stored in
1162 * sspkey (expected to be NTLMSSP_KEY_LEN octets)
1164 /* dissect a string - header area contains:
1165 two byte len
1166 two byte maxlen
1167 four byte offset of string in data area
1168 The function returns the offset at the end of the string header,
1169 but the 'end' parameter returns the offset of the end of the string itself
1170 The 'start' parameter returns the offset of the beginning of the string
1171 If there's no string, just use the offset of the end of the tvb as start/end.
1173 static int
1174 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
1175 proto_tree *ntlmssp_tree,
1176 bool unicode_strings,
1177 int string_hf, int *start, int *end,
1178 const uint8_t **stringp)
1180 proto_tree *tree = NULL;
1181 proto_item *tf = NULL;
1182 int16_t string_length = tvb_get_letohs(tvb, offset);
1183 int16_t string_maxlen = tvb_get_letohs(tvb, offset+2);
1184 int32_t string_offset = tvb_get_letohl(tvb, offset+4);
1186 *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
1187 if (0 == string_length) {
1188 *end = *start;
1189 if (ntlmssp_tree)
1190 proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
1191 offset, 8, "NULL");
1192 if (stringp != NULL)
1193 *stringp = "";
1194 return offset+8;
1197 if (unicode_strings) {
1198 /* UTF-16 string; must be 2-byte aligned */
1199 if ((string_offset & 1) != 0)
1200 string_offset++;
1202 tf = proto_tree_add_item_ret_string(ntlmssp_tree, string_hf, tvb,
1203 string_offset, string_length,
1204 unicode_strings ? ENC_UTF_16|ENC_LITTLE_ENDIAN : ENC_ASCII|ENC_NA,
1205 wmem_packet_scope(), stringp);
1206 tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
1207 proto_tree_add_uint(tree, hf_ntlmssp_string_len,
1208 tvb, offset, 2, string_length);
1209 offset += 2;
1210 proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
1211 tvb, offset, 2, string_maxlen);
1212 offset += 2;
1213 proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
1214 tvb, offset, 4, string_offset);
1215 offset += 4;
1217 *end = string_offset + string_length;
1218 return offset;
1221 /* dissect a generic blob - header area contains:
1222 two byte len
1223 two byte maxlen
1224 four byte offset of blob in data area
1225 The function returns the offset at the end of the blob header,
1226 but the 'end' parameter returns the offset of the end of the blob itself
1228 static int
1229 dissect_ntlmssp_blob (tvbuff_t *tvb, packet_info *pinfo,
1230 proto_tree *ntlmssp_tree, int offset,
1231 int blob_hf, int *end, ntlmssp_blob *result)
1233 proto_item *tf = NULL;
1234 proto_tree *tree = NULL;
1235 uint16_t blob_length = tvb_get_letohs(tvb, offset);
1236 uint16_t blob_maxlen = tvb_get_letohs(tvb, offset+2);
1237 uint32_t blob_offset = tvb_get_letohl(tvb, offset+4);
1239 if (0 == blob_length) {
1240 *end = (blob_offset > ((unsigned)offset)+8 ? blob_offset : ((unsigned)offset)+8);
1241 proto_tree_add_bytes_format_value(ntlmssp_tree, blob_hf, tvb, offset, 8, NULL, "Empty");
1242 result->length = 0;
1243 result->contents = NULL;
1244 return offset+8;
1247 if (ntlmssp_tree) {
1248 tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
1249 blob_offset, blob_length, ENC_NA);
1250 tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
1252 proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
1253 tvb, offset, 2, blob_length);
1254 offset += 2;
1255 proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
1256 tvb, offset, 2, blob_maxlen);
1257 offset += 2;
1258 proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
1259 tvb, offset, 4, blob_offset);
1260 offset += 4;
1262 *end = blob_offset + blob_length;
1264 if (blob_length < NTLMSSP_BLOB_MAX_SIZE) {
1265 result->length = blob_length;
1266 result->contents = (uint8_t *)tvb_memdup(wmem_file_scope(), tvb, blob_offset, blob_length);
1267 } else {
1268 expert_add_info_format(pinfo, tf, &ei_ntlmssp_v2_key_too_long,
1269 "NTLM v2 key is %d bytes long, too big for our %d buffer", blob_length, NTLMSSP_BLOB_MAX_SIZE);
1270 result->length = 0;
1271 result->contents = NULL;
1275 * XXX - for LmChallengeResponse (hf_ntlmssp_auth_lmresponse), should
1276 * we have a field for both Response (2.2.2.3 "LM_RESPONSE" and
1277 * 2.2.2.4 "LMv2_RESPONSE" in [MS-NLMP]) in addition to ClientChallenge
1278 * (only in 2.2.2.4 "LMv2_RESPONSE")?
1280 * XXX - should we also dissect the fields of an NtChallengeResponse
1281 * (hf_ntlmssp_auth_ntresponse)?
1283 * XXX - should we warn if the blob is too *small*?
1285 if (blob_hf == hf_ntlmssp_auth_lmresponse) {
1287 * LMChallengeResponse. It's either 2.2.2.3 "LM_RESPONSE" or
1288 * 2.2.2.4 "LMv2_RESPONSE", in [MS-NLMP].
1290 * XXX - should we have a field for Response as well as
1291 * ClientChallenge?
1293 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) {
1295 * LMv2_RESPONSE.
1297 * XXX - according to 2.2.2.4 "LMv2_RESPONSE", the ClientChallenge
1298 * is at an offset of 16 from the beginning of the blob; it's not
1299 * at the beginning of the blob.
1301 proto_tree_add_item (ntlmssp_tree,
1302 hf_ntlmssp_ntlm_client_challenge,
1303 tvb, blob_offset, 8, ENC_NA);
1305 } else if (blob_hf == hf_ntlmssp_auth_ntresponse) {
1307 * NTChallengeResponse. It's either 2.2.2.6 "NTLM v1 Response:
1308 * NTLM_RESPONSE" or 2.2.2.8 "NTLM v2 Response: NTLMv2_RESPONSE"
1309 * in [MS-NLMP].
1311 if (blob_length > 24) {
1313 * > 24 bytes, so it's "NTLM v2 Response: NTLMv2_RESPONSE".
1314 * An NTLMv2_RESPONSE has 16 bytes of Response followed
1315 * by an NTLMv2_CLIENT_CHALLENGE; an NTLMv2_CLIENT_CHALLENGE
1316 * is at least 32 bytes, so an NTLMv2_RESPONSE is at least
1317 * 48 bytes long.
1319 dissect_ntlmv2_response(tvb, pinfo, tree, blob_offset, blob_length);
1323 return offset;
1326 static int * const ntlmssp_negotiate_flags[] = {
1327 &hf_ntlmssp_negotiate_flags_80000000,
1328 &hf_ntlmssp_negotiate_flags_40000000,
1329 &hf_ntlmssp_negotiate_flags_20000000,
1330 &hf_ntlmssp_negotiate_flags_10000000,
1331 &hf_ntlmssp_negotiate_flags_8000000,
1332 &hf_ntlmssp_negotiate_flags_4000000,
1333 &hf_ntlmssp_negotiate_flags_2000000,
1334 &hf_ntlmssp_negotiate_flags_1000000,
1335 &hf_ntlmssp_negotiate_flags_800000,
1336 &hf_ntlmssp_negotiate_flags_400000,
1337 &hf_ntlmssp_negotiate_flags_200000,
1338 &hf_ntlmssp_negotiate_flags_100000,
1339 &hf_ntlmssp_negotiate_flags_80000,
1340 &hf_ntlmssp_negotiate_flags_40000,
1341 &hf_ntlmssp_negotiate_flags_20000,
1342 &hf_ntlmssp_negotiate_flags_10000,
1343 &hf_ntlmssp_negotiate_flags_8000,
1344 &hf_ntlmssp_negotiate_flags_4000,
1345 &hf_ntlmssp_negotiate_flags_2000,
1346 &hf_ntlmssp_negotiate_flags_1000,
1347 &hf_ntlmssp_negotiate_flags_800,
1348 &hf_ntlmssp_negotiate_flags_400,
1349 &hf_ntlmssp_negotiate_flags_200,
1350 &hf_ntlmssp_negotiate_flags_100,
1351 &hf_ntlmssp_negotiate_flags_80,
1352 &hf_ntlmssp_negotiate_flags_40,
1353 &hf_ntlmssp_negotiate_flags_20,
1354 &hf_ntlmssp_negotiate_flags_10,
1355 &hf_ntlmssp_negotiate_flags_08,
1356 &hf_ntlmssp_negotiate_flags_04,
1357 &hf_ntlmssp_negotiate_flags_02,
1358 &hf_ntlmssp_negotiate_flags_01,
1359 NULL
1362 /* Dissect "version" */
1364 /* From MS-NLMP:
1365 0 Major Version Number 1 byte
1366 1 Minor Version Number 1 byte
1367 2 Build Number short(LE)
1368 3 (Reserved) 3 bytes
1369 4 NTLM Current Revision 1 byte
1372 static int
1373 dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
1374 proto_tree *ntlmssp_tree)
1376 if (ntlmssp_tree) {
1377 proto_item *tf;
1378 proto_tree *version_tree;
1379 tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
1380 "Version %u.%u (Build %u); NTLM Current Revision %u",
1381 tvb_get_uint8(tvb, offset),
1382 tvb_get_uint8(tvb, offset+1),
1383 tvb_get_letohs(tvb, offset+2),
1384 tvb_get_uint8(tvb, offset+7));
1385 version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
1386 proto_tree_add_item(version_tree, hf_ntlmssp_version_major , tvb, offset , 1, ENC_LITTLE_ENDIAN);
1387 proto_tree_add_item(version_tree, hf_ntlmssp_version_minor , tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1388 proto_tree_add_item(version_tree, hf_ntlmssp_version_build_number , tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1389 proto_tree_add_item(version_tree, hf_ntlmssp_version_ntlm_current_revision, tvb, offset+7, 1, ENC_LITTLE_ENDIAN);
1391 return offset+8;
1394 /* Dissect a NTLM response. This is documented at
1395 http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
1397 /* Attribute types */
1399 * XXX - the davenport.sourceforge.net document cited above says that a
1400 * type of 5 has been seen, "apparently containing the 'parent' DNS
1401 * domain for servers in subdomains".
1402 * XXX: MS-NLMP info is newer than Davenport info;
1403 * The attribute type list and the attribute names below are
1404 * based upon MS-NLMP.
1407 #define NTLM_TARGET_INFO_END 0x0000
1408 #define NTLM_TARGET_INFO_NB_COMPUTER_NAME 0x0001
1409 #define NTLM_TARGET_INFO_NB_DOMAIN_NAME 0x0002
1410 #define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
1411 #define NTLM_TARGET_INFO_DNS_DOMAIN_NAME 0x0004
1412 #define NTLM_TARGET_INFO_DNS_TREE_NAME 0x0005
1413 #define NTLM_TARGET_INFO_FLAGS 0x0006
1414 #define NTLM_TARGET_INFO_TIMESTAMP 0x0007
1415 #define NTLM_TARGET_INFO_RESTRICTIONS 0x0008
1416 #define NTLM_TARGET_INFO_TARGET_NAME 0x0009
1417 #define NTLM_TARGET_INFO_CHANNEL_BINDINGS 0x000A
1419 static const value_string ntlm_name_types[] = {
1420 { NTLM_TARGET_INFO_END, "End of list" },
1421 { NTLM_TARGET_INFO_NB_COMPUTER_NAME, "NetBIOS computer name" },
1422 { NTLM_TARGET_INFO_NB_DOMAIN_NAME, "NetBIOS domain name" },
1423 { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
1424 { NTLM_TARGET_INFO_DNS_DOMAIN_NAME, "DNS domain name" },
1425 { NTLM_TARGET_INFO_DNS_TREE_NAME, "DNS tree name" },
1426 { NTLM_TARGET_INFO_FLAGS, "Flags" },
1427 { NTLM_TARGET_INFO_TIMESTAMP, "Timestamp" },
1428 { NTLM_TARGET_INFO_RESTRICTIONS, "Restrictions" },
1429 { NTLM_TARGET_INFO_TARGET_NAME, "Target Name"},
1430 { NTLM_TARGET_INFO_CHANNEL_BINDINGS, "Channel Bindings"},
1431 { 0, NULL }
1433 static value_string_ext ntlm_name_types_ext = VALUE_STRING_EXT_INIT(ntlm_name_types);
1435 /* The following *must* match the order of the list of attribute types */
1436 /* Assumption: values in the list are a sequence starting with 0 and */
1437 /* with no gaps allowing a direct access of the array by attribute type */
1438 static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
1439 &hf_ntlmssp_challenge_target_info_end,
1440 &hf_ntlmssp_challenge_target_info_nb_computer_name,
1441 &hf_ntlmssp_challenge_target_info_nb_domain_name,
1442 &hf_ntlmssp_challenge_target_info_dns_computer_name,
1443 &hf_ntlmssp_challenge_target_info_dns_domain_name,
1444 &hf_ntlmssp_challenge_target_info_dns_tree_name,
1445 &hf_ntlmssp_challenge_target_info_flags,
1446 &hf_ntlmssp_challenge_target_info_timestamp,
1447 &hf_ntlmssp_challenge_target_info_restrictions,
1448 &hf_ntlmssp_challenge_target_info_target_name,
1449 &hf_ntlmssp_challenge_target_info_channel_bindings
1452 static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
1453 &hf_ntlmssp_ntlmv2_response_end,
1454 &hf_ntlmssp_ntlmv2_response_nb_computer_name,
1455 &hf_ntlmssp_ntlmv2_response_nb_domain_name,
1456 &hf_ntlmssp_ntlmv2_response_dns_computer_name,
1457 &hf_ntlmssp_ntlmv2_response_dns_domain_name,
1458 &hf_ntlmssp_ntlmv2_response_dns_tree_name,
1459 &hf_ntlmssp_ntlmv2_response_flags,
1460 &hf_ntlmssp_ntlmv2_response_timestamp,
1461 &hf_ntlmssp_ntlmv2_response_restrictions,
1462 &hf_ntlmssp_ntlmv2_response_target_name,
1463 &hf_ntlmssp_ntlmv2_response_channel_bindings
1466 typedef struct _tif {
1467 int *ett;
1468 int *hf_item_type;
1469 int *hf_item_length;
1470 int **hf_attr_array_p;
1471 } tif_t;
1473 static tif_t ntlmssp_challenge_target_info_tif = {
1474 &ett_ntlmssp_challenge_target_info_item,
1475 &hf_ntlmssp_challenge_target_info_item_type,
1476 &hf_ntlmssp_challenge_target_info_item_len,
1477 ntlmssp_hf_challenge_target_info_hf_ptr_array
1480 static tif_t ntlmssp_ntlmv2_response_tif = {
1481 &ett_ntlmssp_ntlmv2_response_item,
1482 &hf_ntlmssp_ntlmv2_response_item_type,
1483 &hf_ntlmssp_ntlmv2_response_item_len,
1484 ntlmssp_hf_ntlmv2_response_hf_ptr_array
1487 /** See [MS-NLMP] 2.2.2.1 */
1488 static int
1489 dissect_ntlmssp_target_info_list(tvbuff_t *_tvb, packet_info *pinfo, proto_tree *tree,
1490 uint32_t target_info_offset, uint16_t target_info_length,
1491 tif_t *tif_p)
1493 tvbuff_t *tvb = tvb_new_subset_length(_tvb, target_info_offset, target_info_length);
1494 uint32_t item_offset = 0;
1495 uint16_t item_type = ~0;
1497 /* Now enumerate through the individual items in the list */
1499 while (tvb_bytes_exist(tvb, item_offset, 4) && (item_type != NTLM_TARGET_INFO_END)) {
1500 proto_item *target_info_tf;
1501 proto_tree *target_info_tree;
1502 uint32_t content_offset;
1503 uint16_t content_length;
1504 uint32_t type_offset;
1505 uint32_t len_offset;
1506 uint32_t item_length;
1507 const uint8_t *text = NULL;
1509 int **hf_array_p = tif_p->hf_attr_array_p;
1511 /* Content type */
1512 type_offset = item_offset;
1513 item_type = tvb_get_letohs(tvb, type_offset);
1515 /* Content length */
1516 len_offset = type_offset + 2;
1517 content_length = tvb_get_letohs(tvb, len_offset);
1519 /* Content value */
1520 content_offset = len_offset + 2;
1521 item_length = content_length + 4;
1523 if (!tvb_bytes_exist(tvb, item_offset, item_length)) {
1524 /* Mark the current item and all the rest as invalid */
1525 proto_tree_add_expert(tree, pinfo, &ei_ntlmssp_target_info_invalid,
1526 tvb, item_offset, target_info_length - item_offset);
1527 return target_info_offset + target_info_length;
1530 target_info_tree = proto_tree_add_subtree_format(tree, tvb, item_offset, item_length, *tif_p->ett, &target_info_tf,
1531 "Attribute: %s", val_to_str_ext(item_type, &ntlm_name_types_ext, "Unknown (%d)"));
1533 proto_tree_add_item (target_info_tree, *tif_p->hf_item_type, tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
1534 proto_tree_add_item (target_info_tree, *tif_p->hf_item_length, tvb, len_offset, 2, ENC_LITTLE_ENDIAN);
1536 if (content_length > 0) {
1537 switch (item_type) {
1538 case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
1539 case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
1540 case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
1541 case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
1542 case NTLM_TARGET_INFO_DNS_TREE_NAME:
1543 case NTLM_TARGET_INFO_TARGET_NAME:
1544 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);
1545 proto_item_append_text(target_info_tf, ": %s", text);
1546 break;
1548 case NTLM_TARGET_INFO_FLAGS:
1549 proto_tree_add_item(target_info_tree, *hf_array_p[item_type], tvb, content_offset, content_length, ENC_LITTLE_ENDIAN);
1550 break;
1552 case NTLM_TARGET_INFO_TIMESTAMP:
1553 dissect_nttime(tvb, target_info_tree, content_offset, *hf_array_p[item_type], ENC_LITTLE_ENDIAN);
1554 break;
1556 case NTLM_TARGET_INFO_RESTRICTIONS:
1557 case NTLM_TARGET_INFO_CHANNEL_BINDINGS:
1558 proto_tree_add_item(target_info_tree, *hf_array_p[item_type], tvb, content_offset, content_length, ENC_NA);
1559 break;
1561 default:
1562 proto_tree_add_expert(target_info_tree, pinfo, &ei_ntlmssp_target_info_attr,
1563 tvb, content_offset, content_length);
1564 break;
1568 item_offset += item_length;
1571 return target_info_offset + item_offset;
1574 /** See [MS-NLMP] 3.3.2 */
1576 dissect_ntlmv2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int len)
1578 proto_item *ntlmv2_item = NULL;
1579 proto_tree *ntlmv2_tree = NULL;
1580 const int orig_offset = offset;
1582 /* XXX - make sure we don't go past len? */
1583 if (tree) {
1584 ntlmv2_item = proto_tree_add_item(
1585 tree, hf_ntlmssp_ntlmv2_response, tvb,
1586 offset, len, ENC_NA);
1587 ntlmv2_tree = proto_item_add_subtree(
1588 ntlmv2_item, ett_ntlmssp_ntlmv2_response);
1591 proto_tree_add_item(
1592 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_ntproofstr, tvb,
1593 offset, 16, ENC_NA);
1594 offset += 16;
1596 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_rversion, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1597 offset += 1;
1599 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hirversion, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1600 offset += 1;
1602 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 6, ENC_NA);
1603 offset += 6;
1605 dissect_nttime(
1606 tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time, ENC_LITTLE_ENDIAN);
1607 offset += 8;
1608 proto_tree_add_item(
1609 ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
1610 offset, 8, ENC_NA);
1611 offset += 8;
1613 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 4, ENC_NA);
1614 offset += 4;
1616 offset = dissect_ntlmssp_target_info_list(tvb, pinfo, ntlmv2_tree, offset, len - (offset - orig_offset), &ntlmssp_ntlmv2_response_tif);
1618 if ((offset - orig_offset) < len) {
1619 proto_tree_add_item(ntlmv2_tree, hf_ntlmssp_ntlmv2_response_pad, tvb, offset, len - (offset - orig_offset), ENC_NA);
1622 return offset+len;
1625 /* tapping into ntlmssph not yet implemented */
1626 static int
1627 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1629 uint32_t negotiate_flags;
1630 int data_start;
1631 int data_end;
1632 int item_start;
1633 int item_end;
1635 /* NTLMSSP Negotiate Flags */
1636 negotiate_flags = tvb_get_letohl (tvb, offset);
1637 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1638 offset += 4;
1641 * XXX - the davenport document says that these might not be
1642 * sent at all, presumably meaning the length of the message
1643 * isn't enough to contain them.
1645 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, false,
1646 hf_ntlmssp_negotiate_domain,
1647 &data_start, &data_end, NULL);
1649 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, false,
1650 hf_ntlmssp_negotiate_workstation,
1651 &item_start, &item_end, NULL);
1652 data_start = MIN(data_start, item_start);
1653 data_end = MAX(data_end, item_end);
1655 /* If there are more bytes before the data block dissect a version field
1656 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1657 if (offset < data_start) {
1658 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1659 dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1661 return data_end;
1665 static int
1666 dissect_ntlmssp_challenge_target_info_blob (packet_info *pinfo, tvbuff_t *tvb, int offset,
1667 proto_tree *ntlmssp_tree,
1668 int *end)
1670 uint16_t challenge_target_info_length = tvb_get_letohs(tvb, offset);
1671 uint16_t challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
1672 uint32_t challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
1673 proto_item *tf = NULL;
1674 proto_tree *challenge_target_info_tree = NULL;
1676 /* the target info list is just a blob */
1677 if (0 == challenge_target_info_length) {
1678 *end = (challenge_target_info_offset > ((unsigned)offset)+8 ? challenge_target_info_offset : ((unsigned)offset)+8);
1679 proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb, offset, 8,
1680 "Target Info List: Empty");
1681 return offset+8;
1684 if (ntlmssp_tree) {
1685 tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
1686 challenge_target_info_offset, challenge_target_info_length, ENC_NA);
1687 challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
1689 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
1690 tvb, offset, 2, challenge_target_info_length);
1691 offset += 2;
1692 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
1693 tvb, offset, 2, challenge_target_info_maxlen);
1694 offset += 2;
1695 proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
1696 tvb, offset, 4, challenge_target_info_offset);
1697 offset += 4;
1699 dissect_ntlmssp_target_info_list(tvb, pinfo, challenge_target_info_tree,
1700 challenge_target_info_offset, challenge_target_info_length,
1701 &ntlmssp_challenge_target_info_tif);
1703 *end = challenge_target_info_offset + challenge_target_info_length;
1704 return offset;
1707 /* tapping into ntlmssph not yet implemented */
1708 static int
1709 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
1710 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
1712 uint32_t negotiate_flags = 0;
1713 int item_start, item_end;
1714 int data_start, data_end; /* MIN and MAX seen */
1715 uint8_t clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1716 uint8_t serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1717 ntlmssp_info *conv_ntlmssp_info = NULL;
1718 conversation_t *conversation;
1719 bool unicode_strings = false;
1720 uint8_t tmp[8];
1721 uint8_t sspkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key */
1722 int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
1725 * Use the negotiate flags in this message, if they're present
1726 * in the capture, to determine whether strings are Unicode or
1727 * not.
1729 * offset points at TargetNameFields; skip past it.
1731 if (tvb_bytes_exist(tvb, offset+8, 4)) {
1732 negotiate_flags = tvb_get_letohl (tvb, offset+8);
1733 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
1734 unicode_strings = true;
1737 /* Target name */
1739 * XXX - the davenport document (and MS-NLMP) calls this "Target Name",
1740 * presumably because non-domain targets are supported.
1741 * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
1743 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
1744 hf_ntlmssp_challenge_target_name,
1745 &item_start, &item_end, NULL);
1746 data_start = item_start;
1747 data_end = item_end;
1749 /* NTLMSSP Negotiate Flags */
1750 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
1751 offset += 4;
1753 /* NTLMSSP NT Lan Manager Challenge */
1754 proto_tree_add_item (ntlmssp_tree,
1755 hf_ntlmssp_ntlm_server_challenge,
1756 tvb, offset, 8, ENC_NA);
1759 * Store the flags and the RC4 state information with the conversation,
1760 * as they're needed in order to dissect subsequent messages.
1762 conversation = find_or_create_conversation(pinfo);
1764 tvb_memcpy(tvb, tmp, offset, 8); /* challenge */
1765 /* We can face more than one NTLM exchange over the same couple of IP and ports ...*/
1766 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation, proto_ntlmssp);
1767 /* XXX: The following code is (re)executed every time a particular frame is dissected
1768 * (in whatever order). Thus it seems to me that "multiple exchanges" might not be
1769 * handled well depending on the order that frames are visited after the initial dissection.
1771 if (!conv_ntlmssp_info || memcmp(tmp, conv_ntlmssp_info->server_challenge, 8) != 0) {
1772 conv_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_info);
1773 wmem_register_callback(wmem_file_scope(), ntlmssp_sessions_destroy_cb, conv_ntlmssp_info);
1774 /* Insert the flags into the conversation */
1775 conv_ntlmssp_info->flags = negotiate_flags;
1776 conv_ntlmssp_info->saw_challenge = true;
1777 /* Insert the RC4 state information into the conversation */
1778 tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
1779 /* Between the challenge and the user provided password, we can build the
1780 NTLMSSP key and initialize the cipher if we are not in EXTENDED SESSION SECURITY
1781 in this case we need the client challenge as well*/
1782 /* BTW this is true just if we are in LM Authentication if not the logic is a bit different.
1783 * Right now it's not very clear what is LM Authentication it __seems__ to be when
1784 * NEGOTIATE NT ONLY is not set and NEGOTIATE EXTENDED SESSION SECURITY is not set as well*/
1785 if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY))
1787 conv_ntlmssp_info->rc4_state_initialized = false;
1788 /* XXX - Make sure there is 24 bytes for the key */
1789 conv_ntlmssp_info->ntlm_response.contents = (uint8_t *)wmem_alloc0(wmem_file_scope(), 24);
1790 conv_ntlmssp_info->lm_response.contents = (uint8_t *)wmem_alloc0(wmem_file_scope(), 24);
1792 create_ntlmssp_v1_key(conv_ntlmssp_info->server_challenge,
1793 NULL, sspkey, NULL, conv_ntlmssp_info->flags,
1794 conv_ntlmssp_info->ntlm_response.contents,
1795 conv_ntlmssp_info->lm_response.contents,
1796 ntlmssph, pinfo, ntlmssp_tree);
1797 if (memcmp(sspkey, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
1798 get_sealing_rc4key(sspkey, conv_ntlmssp_info->flags, &ssp_key_len, clientkey, serverkey);
1799 if (!gcry_cipher_open(&conv_ntlmssp_info->rc4_handle_client, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1800 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_client, sspkey, ssp_key_len)) {
1801 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
1802 conv_ntlmssp_info->rc4_handle_client = NULL;
1805 if (!gcry_cipher_open(&conv_ntlmssp_info->rc4_handle_server, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
1806 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_server, sspkey, ssp_key_len)) {
1807 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
1808 conv_ntlmssp_info->rc4_handle_server = NULL;
1811 if (conv_ntlmssp_info->rc4_handle_client && conv_ntlmssp_info->rc4_handle_server) {
1812 conv_ntlmssp_info->server_dest_port = pinfo->destport;
1813 conv_ntlmssp_info->rc4_state_initialized = true;
1817 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1819 offset += 8;
1821 /* If no more bytes (ie: no "reserved", ...) before start of data block, then return */
1822 /* XXX: According to Davenport "This form is seen in older Win9x-based systems" */
1823 /* Also: I've seen a capture with an HTTP CONNECT proxy-authentication */
1824 /* message wherein the challenge from the proxy has this form. */
1825 if (offset >= data_start) {
1826 return data_end;
1829 /* Reserved (function not completely known) */
1831 * XXX - SSP key? The davenport document says
1833 * The context field is typically populated when Negotiate Local
1834 * Call is set. It contains an SSPI context handle, which allows
1835 * the client to "short-circuit" authentication and effectively
1836 * circumvent responding to the challenge. Physically, the context
1837 * is two long values. This is covered in greater detail later,
1838 * in the "Local Authentication" section.
1840 * It also says that that information may be omitted.
1842 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
1843 tvb, offset, 8, ENC_NA);
1844 offset += 8;
1847 * The presence or absence of this field is not obviously correlated
1848 * with any flags in the previous NEGOTIATE message or in this
1849 * message (other than the "Workstation Supplied" and "Domain
1850 * Supplied" flags in the NEGOTIATE message, at least in the capture
1851 * I've seen - but those also correlate with the presence of workstation
1852 * and domain name fields, so it doesn't seem to make sense that they
1853 * actually *indicate* whether the subsequent CHALLENGE has an
1854 * address list).
1856 if (offset < data_start) {
1857 offset = dissect_ntlmssp_challenge_target_info_blob(pinfo, tvb, offset, ntlmssp_tree, &item_end);
1858 /* XXX: This code assumes that the address list in the data block */
1859 /* is always after the target name. Is this OK ? */
1860 data_end = MAX(data_end, item_end);
1863 /* If there are more bytes before the data block dissect a version field
1864 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
1865 if (offset < data_start) {
1866 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
1867 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
1870 return MAX(offset, data_end);
1873 static int
1874 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
1875 proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
1877 int item_start, item_end;
1878 int data_start, data_end = 0;
1879 bool have_negotiate_flags = false;
1880 uint32_t negotiate_flags;
1881 uint8_t sspkey[NTLMSSP_KEY_LEN]; /* exported session key */
1882 uint8_t clientkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for client */
1883 uint8_t serverkey[NTLMSSP_KEY_LEN]; /* NTLMSSP cipher key for server*/
1884 uint8_t encryptedsessionkey[NTLMSSP_KEY_LEN] = {0};
1885 ntlmssp_blob sessionblob;
1886 bool unicode_strings = false;
1887 ntlmssp_info *conv_ntlmssp_info;
1888 conversation_t *conversation;
1889 int ssp_key_len;
1891 conv_ntlmssp_info = (ntlmssp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_CONV_INFO_KEY);
1892 if (conv_ntlmssp_info == NULL) {
1894 * There isn't any. Is there any from this conversation? If so,
1895 * it means this is the first time we've dissected this frame, so
1896 * we should give it flag info.
1898 /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
1899 /* so we'll have a place to store flags. */
1900 /* This is a bit brute-force but looks like it will be OK. */
1901 conversation = find_or_create_conversation(pinfo);
1902 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation, proto_ntlmssp);
1903 if (conv_ntlmssp_info == NULL) {
1904 conv_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_info);
1905 wmem_register_callback(wmem_file_scope(), ntlmssp_sessions_destroy_cb, conv_ntlmssp_info);
1906 conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
1908 /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
1909 same as the one attached to the conversation. That is: *both* point to
1910 the exact same struct in memory. Is this what is indended ? */
1911 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_CONV_INFO_KEY, conv_ntlmssp_info);
1915 * Get flag info from the original negotiate message, if any.
1916 * This is because the flag information is sometimes missing from
1917 * the AUTHENTICATE message, so we can't figure out whether
1918 * strings are Unicode or not by looking at *our* flags.
1920 * MS-NLMP says:
1922 * In 2.2.1.1 NEGOTIATE_MESSAGE:
1924 * NegotiateFlags (4 bytes): A NEGOTIATE structure that contains a set
1925 * of flags, as defined in section 2.2.2.5. The client sets flags to
1926 * indicate options it supports.
1928 * In 2.2.1.2 CHALLENGE_MESSAGE:
1930 * NegotiateFlags (4 bytes): A NEGOTIATE structure that contains a set
1931 * of flags, as defined by section 2.2.2.5. The server sets flags to
1932 * indicate options it supports or, if there has been a NEGOTIATE_MESSAGE
1933 * (section 2.2.1.1), the choices it has made from the options offered
1934 * by the client.
1936 * In 2.2.1.3 AUTHENTICATE_MESSAGE:
1938 * NegotiateFlags (4 bytes): In connectionless mode, a NEGOTIATE
1939 * structure that contains a set of flags (section 2.2.2.5) and
1940 * represents the conclusion of negotiation--the choices the client
1941 * has made from the options the server offered in the CHALLENGE_MESSAGE.
1942 * In connection-oriented mode, a NEGOTIATE structure that contains the
1943 * set of bit flags (section 2.2.2.5) negotiated in the previous messages.
1945 * As 1.3.1 NTLM Authentication Call Flow indicates, in connectionless
1946 * mode, there's no NEGOTIATE_MESSAGE, just a CHALLENGE_MESSAGE and
1947 * an AUTHENTICATE_MESSAGE.
1949 * So, for connectionless mode, with no NEGOTIATE_MESSAGE, the flags
1950 * that are the result of negotiation are in the AUTHENTICATE_MESSAGE;
1951 * only at the time the AUTHENTICATE_MESSAGE is sent does the client
1952 * know what the server is offering, so, at that point, it can indicate
1953 * to the server which of those it supports, with the final result
1954 * specifying the capabilities offered by the server that are also
1955 * supported by the client.
1957 * For connection-oriented mode, at the time of the CHALLENGE_MESSAGE,
1958 * the server knows what capabilities the client supports, as those
1959 * we specified in the NEGOTIATE_MESSAGE, so it returns the set of
1960 * capabilities, from the set that the client supports, that it also
1961 * supports, so the CHALLENGE_MESSAGE contains the final result. The
1962 * AUTHENTICATE_MESSAGE "contains the set of bit flags ... negotiated
1963 * in the previous messages", so it should contain the same set of
1964 * bit flags that were in the CHALLENGE_MESSAGE.
1966 * So we use the flags in this message, the AUTHENTICATE_MESSAGE, if
1967 * they're present; if this is connectionless mode, the flags in the
1968 * CHALLENGE_MESSAGE aren't sufficient, as they don't indicate what
1969 * the client supports, and if this is connection-oriented mode, the
1970 * flags here should match what's in the CHALLENGE_MESSAGE.
1972 * The flags might be missing from this message; the message could
1973 * have been cut short by the snapshot length, and even if it's not,
1974 * some older protocol implementations omit it. If they're missing,
1975 * we fall back on what's in the CHALLENGE_MESSAGE.
1977 * XXX: I've seen a capture which does an HTTP CONNECT which:
1978 * - has the NEGOTIATE & CHALLENGE messages in one TCP connection;
1979 * - has the AUTHENTICATE message in a second TCP connection;
1980 * (The authentication aparently succeeded).
1981 * For that case, in order to get the flags from the CHALLENGE_MESSAGE,
1982 * we'd somehow have to manage NTLMSSP exchanges that cross TCP
1983 * connection boundaries.
1985 * offset points at LmChallengeResponseFields; skip past
1986 * LmChallengeResponseFields, NtChallengeResponseFields,
1987 * DomainNameFields, UserNameFields, WorkstationFields,
1988 * and EncryptedRandomSessionKeyFields.
1990 if (tvb_bytes_exist(tvb, offset+8+8+8+8+8+8, 4)) {
1992 * See where the Lan Manager response's blob begins;
1993 * the data area starts at, or before, that location.
1995 data_start = tvb_get_letohl(tvb, offset+4);
1998 * See where the NTLM response's blob begins; the data area
1999 * starts at, or before, that location.
2001 item_start = tvb_get_letohl(tvb, offset+8+4);
2002 data_start = MIN(data_start, item_start);
2005 * See where the domain name's blob begins; the data area
2006 * starts at, or before, that location.
2008 item_start = tvb_get_letohl(tvb, offset+8+8+4);
2009 data_start = MIN(data_start, item_start);
2012 * See where the user name's blob begins; the data area
2013 * starts at, or before, that location.
2015 item_start = tvb_get_letohl(tvb, offset+8+8+8+4);
2016 data_start = MIN(data_start, item_start);
2019 * See where the host name's blob begins; the data area
2020 * starts at, or before, that location.
2022 item_start = tvb_get_letohl(tvb, offset+8+8+8+8+4);
2023 data_start = MIN(data_start, item_start);
2026 * See if we have a session key and flags.
2028 if (offset+8+8+8+8+8 < data_start) {
2030 * We have a session key and flags.
2032 negotiate_flags = tvb_get_letohl (tvb, offset+8+8+8+8+8+8);
2033 have_negotiate_flags = true;
2034 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
2035 unicode_strings = true;
2038 if (!have_negotiate_flags) {
2040 * The flags from this message aren't present; if we have the
2041 * flags from the CHALLENGE message, use them.
2043 if (conv_ntlmssp_info != NULL && conv_ntlmssp_info->saw_challenge) {
2044 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
2045 unicode_strings = true;
2050 * Sometimes the session key and flags are missing.
2051 * Sometimes the session key is present but the flags are missing.
2052 * XXX Who stay so ? Reading spec I would rather say the opposite: flags are
2053 * always present, session information are always there as well but sometime
2054 * session information could be null (in case of no session)
2055 * Sometimes they're both present.
2057 * This does not correlate with any flags in the previous CHALLENGE
2058 * message, and only correlates with "Negotiate Unicode", "Workstation
2059 * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
2060 * those don't make sense as flags to use to determine this.
2062 * So we check all of the descriptors to figure out where the data
2063 * area begins, and if the session key or the flags would be in the
2064 * middle of the data area, we assume the field in question is
2065 * missing.
2067 * XXX - Reading Davenport and MS-NLMP: as I see it the possibilities are:
2068 * a. No session-key; no flags; no version ("Win9x")
2069 * b. Session-key & flags.
2070 * c. Session-key, flags & version.
2071 * In cases b and c the session key may be "null".
2075 /* Lan Manager response */
2076 data_start = tvb_get_letohl(tvb, offset+4);
2077 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
2078 hf_ntlmssp_auth_lmresponse,
2079 &item_end,
2080 conv_ntlmssp_info == NULL ? NULL :
2081 &conv_ntlmssp_info->lm_response);
2082 data_end = MAX(data_end, item_end);
2084 /* NTLM response */
2085 item_start = tvb_get_letohl(tvb, offset+4);
2086 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
2087 hf_ntlmssp_auth_ntresponse,
2088 &item_end,
2089 conv_ntlmssp_info == NULL ? NULL :
2090 &conv_ntlmssp_info->ntlm_response);
2091 data_start = MIN(data_start, item_start);
2092 data_end = MAX(data_end, item_end);
2094 /* domain name */
2095 item_start = tvb_get_letohl(tvb, offset+4);
2096 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
2097 unicode_strings,
2098 hf_ntlmssp_auth_domain,
2099 &item_start, &item_end, &(ntlmssph->domain_name));
2100 /*ntlmssph->domain_name_len = item_end-item_start;*/
2101 data_start = MIN(data_start, item_start);
2102 data_end = MAX(data_end, item_end);
2104 /* user name */
2105 item_start = tvb_get_letohl(tvb, offset+4);
2106 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
2107 unicode_strings,
2108 hf_ntlmssp_auth_username,
2109 &item_start, &item_end, &(ntlmssph->acct_name));
2110 /*ntlmssph->acct_name_len = item_end-item_start;*/
2111 data_start = MIN(data_start, item_start);
2112 data_end = MAX(data_end, item_end);
2114 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "User: %s\\%s",
2115 ntlmssph->domain_name, ntlmssph->acct_name);
2117 /* hostname */
2118 item_start = tvb_get_letohl(tvb, offset+4);
2119 offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
2120 unicode_strings,
2121 hf_ntlmssp_auth_hostname,
2122 &item_start, &item_end, &(ntlmssph->host_name));
2123 data_start = MIN(data_start, item_start);
2124 data_end = MAX(data_end, item_end);
2126 sessionblob.length = 0;
2127 if (offset < data_start) {
2128 /* Session Key */
2129 offset = dissect_ntlmssp_blob(tvb, pinfo, ntlmssp_tree, offset,
2130 hf_ntlmssp_auth_sesskey,
2131 &item_end, &sessionblob);
2132 data_end = MAX(data_end, item_end);
2135 if (offset < data_start) {
2136 /* NTLMSSP Negotiate Flags */
2137 negotiate_flags = tvb_get_letohl (tvb, offset);
2138 proto_tree_add_bitmask(ntlmssp_tree, tvb, offset, hf_ntlmssp_negotiate_flags, ett_ntlmssp_negotiate_flags, ntlmssp_negotiate_flags, ENC_LITTLE_ENDIAN);
2139 offset += 4;
2141 /* If no previous flags seen (ie: no previous CHALLENGE) use flags
2142 from the AUTHENTICATE message).
2143 Assumption: (flags == 0) means flags not previously seen */
2144 if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
2145 conv_ntlmssp_info->flags = negotiate_flags;
2147 } else
2148 negotiate_flags = 0;
2150 /* If there are more bytes before the data block dissect a version field
2151 if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
2152 if (offset < data_start) {
2153 if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION) {
2154 offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
2155 } else {
2156 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_ntlmv2_response_z, tvb, offset, 8, ENC_NA);
2157 offset += 8;
2161 /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
2162 /* (See MS-NLMP) */
2163 if (offset < data_start) {
2164 proto_tree_add_item(ntlmssp_tree, hf_ntlmssp_message_integrity_code, tvb, offset, 16, ENC_NA);
2165 offset += 16;
2168 if (sessionblob.length > NTLMSSP_KEY_LEN) {
2169 expert_add_info_format(pinfo, NULL, &ei_ntlmssp_blob_len_too_long, "Session blob length too long: %u", sessionblob.length);
2170 } else if (sessionblob.length != 0) {
2171 /* XXX - Is it a problem if sessionblob.length < NTLMSSP_KEY_LEN ? */
2172 memcpy(encryptedsessionkey, sessionblob.contents, sessionblob.length);
2173 /* Try to attach to an existing conversation if not then it's useless to try to do so
2174 * because we are missing important information (ie. server challenge)
2176 if (conv_ntlmssp_info) {
2177 /* If we are in EXTENDED SESSION SECURITY then we can now initialize cipher */
2178 if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY))
2180 if (conv_ntlmssp_info->rc4_state_initialized) {
2181 /* XXX - Do we really need to reinitialize the cipher contexts? */
2182 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
2183 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
2185 conv_ntlmssp_info->rc4_state_initialized = false;
2186 ntlmssp_create_session_key(pinfo,
2187 ntlmssp_tree,
2188 ntlmssph,
2189 conv_ntlmssp_info->flags,
2190 conv_ntlmssp_info->server_challenge,
2191 encryptedsessionkey,
2192 &conv_ntlmssp_info->ntlm_response,
2193 &conv_ntlmssp_info->lm_response);
2194 /* ssp is the exported session key */
2195 memcpy(sspkey, ntlmssph->session_key, NTLMSSP_KEY_LEN);
2196 if (memcmp(sspkey, gbl_zeros, NTLMSSP_KEY_LEN) != 0) {
2197 get_sealing_rc4key(sspkey, conv_ntlmssp_info->flags, &ssp_key_len, clientkey, serverkey);
2198 get_signing_key((uint8_t*)&conv_ntlmssp_info->sign_key_server, (uint8_t*)&conv_ntlmssp_info->sign_key_client, sspkey, ssp_key_len);
2199 if (!gcry_cipher_open (&conv_ntlmssp_info->rc4_handle_server, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
2200 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_server, serverkey, ssp_key_len)) {
2201 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_server);
2202 conv_ntlmssp_info->rc4_handle_server = NULL;
2205 if (!gcry_cipher_open (&conv_ntlmssp_info->rc4_handle_client, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
2206 if (gcry_cipher_setkey(conv_ntlmssp_info->rc4_handle_client, clientkey, ssp_key_len)) {
2207 gcry_cipher_close(conv_ntlmssp_info->rc4_handle_client);
2208 conv_ntlmssp_info->rc4_handle_client = NULL;
2211 if (conv_ntlmssp_info->rc4_handle_server && conv_ntlmssp_info->rc4_handle_client) {
2212 conv_ntlmssp_info->server_dest_port = pinfo->destport;
2213 conv_ntlmssp_info->rc4_state_initialized = true;
2219 return MAX(offset, data_end);
2222 static uint8_t*
2223 get_sign_key(packet_info *pinfo, int cryptpeer)
2225 conversation_t *conversation;
2226 ntlmssp_info *conv_ntlmssp_info;
2228 conversation = find_conversation_pinfo(pinfo, 0);
2229 if (conversation == NULL) {
2230 /* We don't have a conversation. In this case, stop processing
2231 because we do not have enough info to decrypt the payload */
2232 return NULL;
2234 else {
2235 /* We have a conversation, check for encryption state */
2236 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2237 proto_ntlmssp);
2238 if (conv_ntlmssp_info == NULL) {
2239 /* No encryption state tied to the conversation. Therefore, we
2240 cannot decrypt the payload */
2241 return NULL;
2243 else {
2244 /* We have the encryption state in the conversation. So return the
2245 crypt state tied to the requested peer
2247 if (cryptpeer == 1) {
2248 return (uint8_t*)&conv_ntlmssp_info->sign_key_client;
2249 } else {
2250 return (uint8_t*)&conv_ntlmssp_info->sign_key_server;
2257 * Get the encryption state tied to this conversation. cryptpeer indicates
2258 * whether to retrieve the client key (1) or the server key (0)
2260 static gcry_cipher_hd_t
2261 get_encrypted_state(packet_info *pinfo, int cryptpeer)
2263 conversation_t *conversation;
2264 ntlmssp_info *conv_ntlmssp_info;
2266 conversation = find_conversation_pinfo(pinfo, 0);
2267 if (conversation == NULL) {
2268 /* We don't have a conversation. In this case, stop processing
2269 because we do not have enough info to decrypt the payload */
2270 return NULL;
2272 else {
2273 /* We have a conversation, check for encryption state */
2274 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2275 proto_ntlmssp);
2276 if (conv_ntlmssp_info == NULL) {
2277 /* No encryption state tied to the conversation. Therefore, we
2278 cannot decrypt the payload */
2279 return NULL;
2281 else {
2282 /* We have the encryption state in the conversation. So return the
2283 crypt state tied to the requested peer
2285 if (cryptpeer == 1) {
2286 return conv_ntlmssp_info->rc4_handle_client;
2287 } else {
2288 return conv_ntlmssp_info->rc4_handle_server;
2294 static tvbuff_t*
2295 decrypt_data_payload(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length,
2296 packet_info *pinfo, proto_tree *tree _U_, void *key);
2297 static void
2298 store_verifier(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length, packet_info *pinfo);
2300 static void
2301 decrypt_verifier(tvbuff_t *tvb, packet_info *pinfo);
2303 static int
2304 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2306 volatile int offset = 0;
2307 proto_tree *volatile ntlmssp_tree = NULL;
2308 proto_item *tf = NULL;
2309 uint32_t length;
2310 uint32_t encrypted_block_length;
2311 uint8_t key[NTLMSSP_KEY_LEN];
2312 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01 */
2313 uint32_t ntlm_magic_size = 4;
2314 uint32_t ntlm_signature_size = 8;
2315 uint32_t ntlm_seq_size = 4;
2317 length = tvb_captured_length (tvb);
2318 /* signature + seq + real payload */
2319 encrypted_block_length = length - ntlm_magic_size;
2321 if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
2322 /* Don't know why this would happen, but if it does, don't even bother
2323 attempting decryption/dissection */
2324 return offset + length;
2327 /* Setup a new tree for the NTLMSSP payload */
2328 if (tree) {
2329 tf = proto_tree_add_item (tree,
2330 hf_ntlmssp_verf,
2331 tvb, offset, -1, ENC_NA);
2333 ntlmssp_tree = proto_item_add_subtree (tf,
2334 ett_ntlmssp);
2338 * Catch the ReportedBoundsError exception; the stuff we've been
2339 * handed doesn't necessarily run to the end of the packet, it's
2340 * an item inside a packet, so if it happens to be malformed (or
2341 * we, or a dissector we call, has a bug), so that an exception
2342 * is thrown, we want to report the error, but return and let
2343 * our caller dissect the rest of the packet.
2345 * If it gets a BoundsError, we can stop, as there's nothing more
2346 * in the packet after our blob to see, so we just re-throw the
2347 * exception.
2349 TRY {
2350 /* Version number */
2351 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2352 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2353 offset += 4;
2355 /* Encrypted body */
2356 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2357 tvb, offset, ntlm_signature_size + ntlm_seq_size, ENC_NA);
2358 memset(key, 0, sizeof(key));
2359 tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
2360 /* Try to decrypt */
2361 decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree, key);
2362 store_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo);
2363 decrypt_verifier (tvb, pinfo);
2364 /* let's try to hook ourselves here */
2366 offset += 12;
2367 } CATCH_NONFATAL_ERRORS {
2368 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2369 } ENDTRY;
2371 return offset;
2374 static tvbuff_t*
2375 decrypt_data_payload(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length,
2376 packet_info *pinfo, proto_tree *tree _U_, void *key)
2378 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2379 ntlmssp_packet_info *packet_ntlmssp_info;
2380 ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
2382 /* Check to see if we already have state for this packet */
2383 packet_ntlmssp_info = (ntlmssp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2384 if (packet_ntlmssp_info == NULL) {
2385 /* We don't have any packet state, so create one */
2386 packet_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_packet_info);
2387 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY, packet_ntlmssp_info);
2389 if (!packet_ntlmssp_info->payload_decrypted) {
2390 conversation_t *conversation;
2391 ntlmssp_info *conv_ntlmssp_info;
2393 /* Pull the challenge info from the conversation */
2394 conversation = find_conversation_pinfo(pinfo, 0);
2395 if (conversation == NULL) {
2396 /* There is no conversation, thus no encryption state */
2397 return NULL;
2400 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2401 proto_ntlmssp);
2402 if (conv_ntlmssp_info == NULL) {
2403 /* There is no NTLMSSP state tied to the conversation */
2404 return NULL;
2406 if (!conv_ntlmssp_info->rc4_state_initialized) {
2407 /* The crypto sybsystem is not initialized. This means that either
2408 the conversation did not include a challenge, or that we do not have the right password */
2409 return NULL;
2411 if (key != NULL) {
2412 stored_packet_ntlmssp_info = (ntlmssp_packet_info *)g_hash_table_lookup(hash_packet, key);
2414 if (stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == true) {
2415 /* Mat TBD (stderr, "Found a already decrypted packet\n");*/
2416 memcpy(packet_ntlmssp_info, stored_packet_ntlmssp_info, sizeof(ntlmssp_packet_info));
2417 /* Mat TBD printnbyte(pinfo->pool, packet_ntlmssp_info->decrypted_payload, encrypted_block_length, "Data: ");*/
2419 else {
2420 gcry_cipher_hd_t rc4_handle;
2421 gcry_cipher_hd_t rc4_handle_peer;
2423 /* Get the pair of RC4 state structures. One is used for to decrypt the
2424 payload. The other is used to re-encrypt the payload to represent
2425 the peer */
2426 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2427 /* client */
2428 rc4_handle = get_encrypted_state(pinfo, 1);
2429 rc4_handle_peer = get_encrypted_state(pinfo, 0);
2430 } else {
2431 /* server */
2432 rc4_handle = get_encrypted_state(pinfo, 0);
2433 rc4_handle_peer = get_encrypted_state(pinfo, 1);
2436 if (rc4_handle == NULL) {
2437 /* There is no encryption state, so we cannot decrypt */
2438 return NULL;
2441 /* Store the decrypted contents in the packet state struct
2442 (of course at this point, they aren't decrypted yet) */
2443 packet_ntlmssp_info->decrypted_payload = (uint8_t *)tvb_memdup(wmem_file_scope(), tvb, offset,
2444 encrypted_block_length);
2445 packet_ntlmssp_info->payload_len = encrypted_block_length;
2446 decrypted_payloads = g_slist_prepend(decrypted_payloads,
2447 packet_ntlmssp_info->decrypted_payload);
2448 if (key != NULL) {
2449 uint8_t *perm_key = g_new(uint8_t, NTLMSSP_KEY_LEN);
2450 memcpy(perm_key, key, NTLMSSP_KEY_LEN);
2451 g_hash_table_insert(hash_packet, perm_key, packet_ntlmssp_info);
2454 /* Do the decryption of the payload */
2455 gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->decrypted_payload, encrypted_block_length, NULL, 0);
2457 /* decrypt the verifier */
2458 /*printnchar(pinfo->pool, packet_ntlmssp_info->decrypted_payload, encrypted_block_length, "data: ");*/
2459 /* We setup a temporary buffer so we can re-encrypt the payload after
2460 decryption. This is to update the opposite peer's RC4 state
2461 it's useful when we have only one key for both conversation
2462 in case of KEY_EXCH we have independent key so this is not needed*/
2463 if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2464 uint8_t *peer_block;
2465 peer_block = (uint8_t *)wmem_memdup(pinfo->pool, packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
2466 gcry_cipher_decrypt(rc4_handle_peer, peer_block, encrypted_block_length, NULL, 0);
2469 packet_ntlmssp_info->payload_decrypted = true;
2473 /* Show the decrypted buffer in a new window */
2474 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->decrypted_payload,
2475 encrypted_block_length,
2476 encrypted_block_length);
2478 add_new_data_source(pinfo, decr_tvb,
2479 "Decrypted data");
2480 return decr_tvb;
2483 static int
2484 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2486 volatile int offset = 0;
2487 proto_tree *volatile ntlmssp_tree = NULL;
2488 proto_item *tf, *type_item;
2489 ntlmssp_header_t *ntlmssph;
2491 /* Check if it is a signing signature */
2492 if (tvb_bytes_exist(tvb, offset, 16) &&
2493 tvb_reported_length_remaining(tvb, offset) == 16 &&
2494 tvb_get_uint8(tvb, offset) == 0x01)
2496 tvbuff_t *verf_tvb = tvb_new_subset_length(tvb, offset, 16);
2497 offset += dissect_ntlmssp_verf(verf_tvb, pinfo, tree, NULL);
2498 return offset;
2501 ntlmssph = wmem_new(pinfo->pool, ntlmssp_header_t);
2502 ntlmssph->type = 0;
2503 ntlmssph->domain_name = NULL;
2504 ntlmssph->acct_name = NULL;
2505 ntlmssph->host_name = NULL;
2506 memset(ntlmssph->session_key, 0, NTLMSSP_KEY_LEN);
2508 /* Setup a new tree for the NTLMSSP payload */
2509 tf = proto_tree_add_item (tree,
2510 proto_ntlmssp,
2511 tvb, offset, -1, ENC_NA);
2513 ntlmssp_tree = proto_item_add_subtree (tf, ett_ntlmssp);
2516 * Catch the ReportedBoundsError exception; the stuff we've been
2517 * handed doesn't necessarily run to the end of the packet, it's
2518 * an item inside a packet, so if it happens to be malformed (or
2519 * we, or a dissector we call, has a bug), so that an exception
2520 * is thrown, we want to report the error, but return and let
2521 * our caller dissect the rest of the packet.
2523 * If it gets a BoundsError, we can stop, as there's nothing more
2524 * in the packet after our blob to see, so we just re-throw the
2525 * exception.
2527 TRY {
2528 /* NTLMSSP constant */
2529 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
2530 tvb, offset, 8, ENC_ASCII);
2531 offset += 8;
2533 /* NTLMSSP Message Type */
2534 type_item = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
2535 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2536 ntlmssph->type = tvb_get_letohl (tvb, offset);
2537 offset += 4;
2539 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
2540 val_to_str_const(ntlmssph->type,
2541 ntlmssp_message_types,
2542 "Unknown NTLMSSP message type"));
2544 /* Call the appropriate dissector based on the Message Type */
2545 switch (ntlmssph->type) {
2547 case NTLMSSP_NEGOTIATE:
2548 dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree, ntlmssph);
2549 break;
2551 case NTLMSSP_CHALLENGE:
2552 dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2553 break;
2555 case NTLMSSP_AUTH:
2556 dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree, ntlmssph);
2557 break;
2559 default:
2560 /* Unrecognized message type */
2561 expert_add_info(pinfo, type_item, &ei_ntlmssp_message_type);
2562 break;
2564 } CATCH_NONFATAL_ERRORS {
2566 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2567 } ENDTRY;
2569 tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);
2570 return tvb_captured_length(tvb);
2573 static void
2574 store_verifier(tvbuff_t *tvb, int offset, uint32_t encrypted_block_length, packet_info *pinfo)
2576 ntlmssp_packet_info *packet_ntlmssp_info;
2578 packet_ntlmssp_info = (ntlmssp_packet_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2579 if (packet_ntlmssp_info == NULL) {
2580 /* We don't have any packet state, so create one */
2581 packet_ntlmssp_info = wmem_new0(wmem_file_scope(), ntlmssp_packet_info);
2582 p_add_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY, packet_ntlmssp_info);
2585 if (!packet_ntlmssp_info->verifier_decrypted) {
2586 /* Store all necessary info for later decryption */
2587 packet_ntlmssp_info->verifier_offset = offset;
2588 packet_ntlmssp_info->verifier_block_length = encrypted_block_length;
2589 /* Setup the buffer to decrypt to */
2590 tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
2591 offset, MIN(encrypted_block_length, sizeof(packet_ntlmssp_info->verifier)));
2596 * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
2598 static void
2599 decrypt_verifier(tvbuff_t *tvb, packet_info *pinfo)
2601 proto_tree *decr_tree;
2602 conversation_t *conversation;
2603 uint8_t* sign_key;
2604 gcry_cipher_hd_t rc4_handle;
2605 gcry_cipher_hd_t rc4_handle_peer;
2606 tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
2607 uint8_t *peer_block;
2608 uint8_t *check_buf;
2609 uint8_t calculated_md5[NTLMSSP_KEY_LEN];
2610 ntlmssp_info *conv_ntlmssp_info;
2611 ntlmssp_packet_info *packet_ntlmssp_info;
2612 int decrypted_offset = 0;
2613 int sequence = 0;
2615 packet_ntlmssp_info = (ntlmssp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ntlmssp, NTLMSSP_PACKET_INFO_KEY);
2616 if (packet_ntlmssp_info == NULL) {
2617 /* We don't have data for this packet */
2618 return;
2620 conversation = find_conversation_pinfo(pinfo, 0);
2621 if (conversation == NULL) {
2622 /* There is no conversation, thus no encryption state */
2623 return;
2625 conv_ntlmssp_info = (ntlmssp_info *)conversation_get_proto_data(conversation,
2626 proto_ntlmssp);
2627 if (conv_ntlmssp_info == NULL) {
2628 /* There is no NTLMSSP state tied to the conversation */
2629 return;
2632 if (!packet_ntlmssp_info->verifier_decrypted) {
2633 if (!conv_ntlmssp_info->rc4_state_initialized) {
2634 /* The crypto subsystem is not initialized. This means that either
2635 the conversation did not include a challenge, or we are doing
2636 something other than NTLMSSP v1 */
2637 return;
2639 if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
2640 /* client talk to server */
2641 rc4_handle = get_encrypted_state(pinfo, 1);
2642 sign_key = get_sign_key(pinfo, 1);
2643 rc4_handle_peer = get_encrypted_state(pinfo, 0);
2644 } else {
2645 rc4_handle = get_encrypted_state(pinfo, 0);
2646 sign_key = get_sign_key(pinfo, 0);
2647 rc4_handle_peer = get_encrypted_state(pinfo, 1);
2650 if (rc4_handle == NULL || rc4_handle_peer == NULL) {
2651 /* There is no encryption state, so we cannot decrypt */
2652 return;
2655 /*if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
2656 if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
2657 if ((NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
2658 /* The spec says that if we have a key exchange then we have the signature that is encrypted
2659 * otherwise it's just a hmac_md5(keysign, concat(message, sequence))[0..7]
2661 if (gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->verifier, 8, NULL, 0)) {
2662 return;
2666 * Trying to check the HMAC MD5 of the message against the calculated one works great with LDAP payload but
2667 * don't with DCE/RPC calls.
2668 * TODO Some analysis needs to be done ...
2670 if (sign_key != NULL) {
2671 check_buf = (uint8_t *)wmem_alloc(pinfo->pool, packet_ntlmssp_info->payload_len+4);
2672 tvb_memcpy(tvb, &sequence, packet_ntlmssp_info->verifier_offset+8, 4);
2673 memcpy(check_buf, &sequence, 4);
2674 memcpy(check_buf+4, packet_ntlmssp_info->decrypted_payload, packet_ntlmssp_info->payload_len);
2675 if (ws_hmac_buffer(GCRY_MD_MD5, calculated_md5, check_buf, (int)(packet_ntlmssp_info->payload_len+4), sign_key, NTLMSSP_KEY_LEN)) {
2676 return;
2679 printnbyte(pinfo->pool, packet_ntlmssp_info->verifier, 8, "HMAC from packet: ");
2680 printnbyte(pinfo->pool, calculated_md5, 8, "HMAC : ");
2684 else {
2685 /* 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 */
2686 /* Do the actual decryption of the verifier */
2687 if (gcry_cipher_decrypt(rc4_handle, packet_ntlmssp_info->verifier, packet_ntlmssp_info->verifier_block_length, NULL, 0)) {
2688 return;
2693 /* We setup a temporary buffer so we can re-encrypt the payload after
2694 decryption. This is to update the opposite peer's RC4 state
2695 This is not needed when we just have EXTENDED SESSION SECURITY because the signature is not encrypted
2696 and it's also not needed when we have key exchange because server and client have independent keys */
2697 if (!(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY & conv_ntlmssp_info->flags)) {
2698 peer_block = (uint8_t *)wmem_memdup(pinfo->pool, packet_ntlmssp_info->verifier, packet_ntlmssp_info->verifier_block_length);
2699 if (gcry_cipher_decrypt(rc4_handle_peer, peer_block, packet_ntlmssp_info->verifier_block_length, NULL, 0)) {
2700 return;
2704 /* Mark the packet as decrypted so that subsequent attempts to dissect
2705 the packet use the already decrypted payload instead of attempting
2706 to decrypt again */
2707 packet_ntlmssp_info->verifier_decrypted = true;
2710 /* Show the decrypted buffer in a new window */
2711 decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
2712 packet_ntlmssp_info->verifier_block_length,
2713 packet_ntlmssp_info->verifier_block_length);
2714 add_new_data_source(pinfo, decr_tvb,
2715 "Decrypted NTLMSSP Verifier");
2717 /* Show the decrypted payload in the tree */
2718 decr_tree = proto_tree_add_subtree_format(NULL, decr_tvb, 0, -1,
2719 ett_ntlmssp, NULL,
2720 "Decrypted Verifier (%d byte%s)",
2721 packet_ntlmssp_info->verifier_block_length,
2722 plurality(packet_ntlmssp_info->verifier_block_length, "", "s"));
2724 if (( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) {
2725 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
2726 decr_tvb, decrypted_offset, 8, ENC_NA);
2727 decrypted_offset += 8;
2729 /* Incrementing sequence number of DCE conversation */
2730 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2731 decr_tvb, decrypted_offset, 4, ENC_NA);
2733 else {
2734 /* RANDOM PAD usually it's 0 */
2735 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
2736 decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
2737 decrypted_offset += 4;
2739 /* CRC32 of the DCE fragment data */
2740 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
2741 decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
2742 decrypted_offset += 4;
2744 /* Incrementing sequence number of DCE conversation */
2745 proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
2746 decr_tvb, decrypted_offset, 4, ENC_NA);
2750 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contiguous*/
2751 static int
2752 dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *tree, void *data)
2754 volatile int offset = 0;
2755 proto_tree *volatile ntlmssp_tree = NULL;
2756 uint32_t encrypted_block_length;
2757 tvbuff_t *volatile decr_tvb;
2758 tvbuff_t** ret_decr_tvb = (tvbuff_t**)data;
2760 if (ret_decr_tvb)
2761 *ret_decr_tvb = NULL;
2762 /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
2764 encrypted_block_length = tvb_captured_length (tvb);
2765 /* signature + seq + real payload */
2767 /* Setup a new tree for the NTLMSSP payload */
2768 #if 0
2769 if (tree) {
2770 tf = proto_tree_add_item (tree,
2771 hf_ntlmssp_verf,
2772 tvb, offset, -1, ENC_NA);
2774 ntlmssp_tree = proto_item_add_subtree (tf,
2775 ett_ntlmssp);
2777 #endif
2779 * Catch the ReportedBoundsError exception; the stuff we've been
2780 * handed doesn't necessarily run to the end of the packet, it's
2781 * an item inside a packet, so if it happens to be malformed (or
2782 * we, or a dissector we call, has a bug), so that an exception
2783 * is thrown, we want to report the error, but return and let
2784 * our caller dissect the rest of the packet.
2786 * If it gets a BoundsError, we can stop, as there's nothing more
2787 * in the packet after our blob to see, so we just re-throw the
2788 * exception.
2790 TRY {
2791 /* Version number */
2793 /* Try to decrypt */
2794 decr_tvb = decrypt_data_payload (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree, NULL);
2795 if (ret_decr_tvb)
2796 *ret_decr_tvb = decr_tvb;
2797 /* let's try to hook ourselves here */
2799 } CATCH_NONFATAL_ERRORS {
2801 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2802 } ENDTRY;
2804 return offset;
2807 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contiguous
2808 * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
2810 static int
2811 dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2813 volatile int offset = 0;
2814 proto_tree *volatile ntlmssp_tree = NULL;
2815 proto_item *tf = NULL;
2816 uint32_t verifier_length;
2817 uint32_t encrypted_block_length;
2819 verifier_length = tvb_captured_length (tvb);
2820 encrypted_block_length = verifier_length - 4;
2822 if (encrypted_block_length < 12) {
2823 /* Don't know why this would happen, but if it does, don't even bother
2824 attempting decryption/dissection */
2825 return offset + verifier_length;
2828 /* Setup a new tree for the NTLMSSP payload */
2829 if (tree) {
2830 tf = proto_tree_add_item (tree,
2831 hf_ntlmssp_verf,
2832 tvb, offset, -1, ENC_NA);
2834 ntlmssp_tree = proto_item_add_subtree (tf,
2835 ett_ntlmssp);
2839 * Catch the ReportedBoundsError exception; the stuff we've been
2840 * handed doesn't necessarily run to the end of the packet, it's
2841 * an item inside a packet, so if it happens to be malformed (or
2842 * we, or a dissector we call, has a bug), so that an exception
2843 * is thrown, we want to report the error, but return and let
2844 * our caller dissect the rest of the packet.
2846 * If it gets a BoundsError, we can stop, as there's nothing more
2847 * in the packet after our blob to see, so we just re-throw the
2848 * exception.
2850 TRY {
2851 /* Version number */
2852 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
2853 tvb, offset, 4, ENC_LITTLE_ENDIAN);
2854 offset += 4;
2856 /* Encrypted body */
2857 proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
2858 tvb, offset, encrypted_block_length, ENC_NA);
2860 /* Extract and store the verifier for later decryption */
2861 store_verifier (tvb, offset, encrypted_block_length, pinfo);
2862 /* let's try to hook ourselves here */
2864 offset += 12;
2865 offset += encrypted_block_length;
2866 } CATCH_NONFATAL_ERRORS {
2868 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2869 } ENDTRY;
2871 return offset;
2874 static tvbuff_t *
2875 wrap_dissect_ntlmssp_payload_only(tvbuff_t *header_tvb _U_,
2876 tvbuff_t *payload_tvb,
2877 tvbuff_t *trailer_tvb _U_,
2878 tvbuff_t *auth_tvb _U_,
2879 packet_info *pinfo,
2880 dcerpc_auth_info *auth_info _U_)
2882 tvbuff_t *decrypted_tvb;
2884 dissect_ntlmssp_payload_only(payload_tvb, pinfo, NULL, &decrypted_tvb);
2885 /* Now the payload is decrypted, we can then decrypt the verifier which was stored earlier */
2886 decrypt_verifier(payload_tvb, pinfo);
2887 return decrypted_tvb;
2890 static unsigned
2891 header_hash(const void *pointer)
2893 uint32_t crc = ~crc32c_calculate(pointer, NTLMSSP_KEY_LEN, CRC32C_PRELOAD);
2894 /* Mat TBD ws_debug("Val: %u", crc);*/
2895 return crc;
2898 static gboolean
2899 header_equal(const void *pointer1, const void *pointer2)
2901 if (!memcmp(pointer1, pointer2, NTLMSSP_KEY_LEN)) {
2902 return TRUE;
2904 else {
2905 return FALSE;
2909 static void
2910 ntlmssp_init_protocol(void)
2912 hash_packet = g_hash_table_new_full(header_hash, header_equal, g_free, NULL);
2915 static void
2916 ntlmssp_cleanup_protocol(void)
2918 if (decrypted_payloads != NULL) {
2919 g_slist_free(decrypted_payloads);
2920 decrypted_payloads = NULL;
2922 g_hash_table_destroy(hash_packet);
2927 static int
2928 wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
2929 proto_tree *tree, dcerpc_info *di _U_, uint8_t *drep _U_)
2931 tvbuff_t *auth_tvb;
2933 auth_tvb = tvb_new_subset_remaining(tvb, offset);
2935 dissect_ntlmssp(auth_tvb, pinfo, tree, NULL);
2937 return tvb_captured_length_remaining(tvb, offset);
2940 static int
2941 wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
2942 proto_tree *tree, dcerpc_info *di _U_, uint8_t *drep _U_)
2944 tvbuff_t *auth_tvb;
2946 auth_tvb = tvb_new_subset_remaining(tvb, offset);
2947 return dissect_ntlmssp_verf(auth_tvb, pinfo, tree, NULL);
2950 static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
2951 wrap_dissect_ntlmssp, /* Bind */
2952 wrap_dissect_ntlmssp, /* Bind ACK */
2953 wrap_dissect_ntlmssp, /* AUTH3 */
2954 wrap_dissect_ntlmssp_verf, /* Request verifier */
2955 wrap_dissect_ntlmssp_verf, /* Response verifier */
2956 NULL, /* Request data */
2957 NULL /* Response data */
2960 static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
2961 wrap_dissect_ntlmssp, /* Bind */
2962 wrap_dissect_ntlmssp, /* Bind ACK */
2963 wrap_dissect_ntlmssp, /* AUTH3 */
2964 wrap_dissect_ntlmssp_verf, /* Request verifier */
2965 wrap_dissect_ntlmssp_verf, /* Response verifier */
2966 wrap_dissect_ntlmssp_payload_only, /* Request data */
2967 wrap_dissect_ntlmssp_payload_only /* Response data */
2970 static const value_string MSV1_0_CRED_VERSION[] = {
2971 { 0x00000000, "MSV1_0_CRED_VERSION" },
2972 { 0x00000002, "MSV1_0_CRED_VERSION_V2" },
2973 { 0x00000004, "MSV1_0_CRED_VERSION_V3" },
2974 { 0xffff0001, "MSV1_0_CRED_VERSION_IUM" },
2975 { 0xffff0002, "MSV1_0_CRED_VERSION_REMOTE" },
2976 { 0xfffffffe, "MSV1_0_CRED_VERSION_RESERVED_1" },
2977 { 0xffffffff, "MSV1_0_CRED_VERSION_INVALID" },
2978 { 0, NULL }
2981 #define MSV1_0_CRED_LM_PRESENT 0x00000001
2982 #define MSV1_0_CRED_NT_PRESENT 0x00000002
2983 #define MSV1_0_CRED_REMOVED 0x00000004
2984 #define MSV1_0_CRED_CREDKEY_PRESENT 0x00000008
2985 #define MSV1_0_CRED_SHA_PRESENT 0x00000010
2987 static int* const MSV1_0_CRED_FLAGS_bits[] = {
2988 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_LM_PRESENT,
2989 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_NT_PRESENT,
2990 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_REMOVED,
2991 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_CREDKEY_PRESENT,
2992 &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_SHA_PRESENT,
2993 NULL
2996 static const value_string MSV1_0_CREDENTIAL_KEY_TYPE[] = {
2997 { 0, "InvalidCredKey" },
2998 { 1, "IUMCredKey" },
2999 { 2, "DomainUserCredKey" },
3000 { 3, "LocalUserCredKey" },
3001 { 4, "ExternallySuppliedCredKey" },
3002 { 0, NULL }
3005 #define MSV1_0_CREDENTIAL_KEY_LENGTH 20
3008 dissect_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL(tvbuff_t *tvb, int offset, proto_tree *tree)
3010 proto_item *item;
3011 proto_tree *subtree;
3012 uint32_t EncryptedCredsSize;
3014 if (tvb_captured_length(tvb) < 36)
3015 return offset;
3017 item = proto_tree_add_item(tree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL, tvb,
3018 offset, -1, ENC_NA);
3019 subtree = proto_item_add_subtree(item, ett_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL);
3021 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Version, tvb,
3022 offset, 4, ENC_LITTLE_ENDIAN);
3023 offset+=4;
3025 proto_tree_add_bitmask(subtree, tvb, offset,
3026 hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Flags,
3027 ett_ntlmssp, MSV1_0_CRED_FLAGS_bits, ENC_LITTLE_ENDIAN);
3028 offset+=4;
3030 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKey,
3031 tvb, offset, MSV1_0_CREDENTIAL_KEY_LENGTH, ENC_NA);
3032 offset+=MSV1_0_CREDENTIAL_KEY_LENGTH;
3034 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKeyType,
3035 tvb, offset, 4, ENC_LITTLE_ENDIAN);
3036 offset+=4;
3038 EncryptedCredsSize = tvb_get_letohl(tvb, offset);
3039 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCredsSize,
3040 tvb, offset, 4, ENC_LITTLE_ENDIAN);
3041 offset+=4;
3043 if (EncryptedCredsSize == 0)
3044 return offset;
3046 if (tvb_captured_length(tvb) < (36 + EncryptedCredsSize))
3047 return offset;
3049 proto_tree_add_item(subtree, hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCreds,
3050 tvb, offset, EncryptedCredsSize, ENC_NA);
3051 offset+=EncryptedCredsSize;
3053 return offset;
3057 void
3058 proto_register_ntlmssp(void)
3061 static hf_register_info hf[] = {
3062 { &hf_ntlmssp_auth,
3063 { "NTLMSSP identifier", "ntlmssp.identifier",
3064 FT_STRING, BASE_NONE, NULL, 0x0,
3065 NULL, HFILL }
3067 { &hf_ntlmssp_message_type,
3068 { "NTLM Message Type", "ntlmssp.messagetype",
3069 FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0,
3070 NULL, HFILL }
3072 { &hf_ntlmssp_negotiate_flags,
3073 { "Negotiate Flags", "ntlmssp.negotiateflags",
3074 FT_UINT32, BASE_HEX, NULL, 0x0,
3075 NULL, HFILL }
3077 { &hf_ntlmssp_negotiate_flags_01,
3078 { "Negotiate UNICODE", "ntlmssp.negotiateunicode",
3079 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_UNICODE,
3080 NULL, HFILL }
3082 { &hf_ntlmssp_negotiate_flags_02,
3083 { "Negotiate OEM", "ntlmssp.negotiateoem",
3084 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM,
3085 NULL, HFILL }
3087 { &hf_ntlmssp_negotiate_flags_04,
3088 { "Request Target", "ntlmssp.requesttarget",
3089 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_TARGET,
3090 NULL, HFILL }
3092 { &hf_ntlmssp_negotiate_flags_08,
3093 { "Request 0x00000008", "ntlmssp.unused00000008",
3094 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00000008,
3095 NULL, HFILL }
3097 { &hf_ntlmssp_negotiate_flags_10,
3098 { "Negotiate Sign", "ntlmssp.negotiatesign",
3099 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SIGN,
3100 NULL, HFILL }
3102 { &hf_ntlmssp_negotiate_flags_20,
3103 { "Negotiate Seal", "ntlmssp.negotiateseal",
3104 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_SEAL,
3105 NULL, HFILL }
3107 { &hf_ntlmssp_negotiate_flags_40,
3108 { "Negotiate Datagram", "ntlmssp.negotiatedatagram",
3109 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_DATAGRAM,
3110 NULL, HFILL }
3112 { &hf_ntlmssp_negotiate_flags_80,
3113 { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey",
3114 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_LM_KEY,
3115 NULL, HFILL }
3117 { &hf_ntlmssp_negotiate_flags_100,
3118 { "Negotiate 0x00000100", "ntlmssp.unused00000100",
3119 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00000100,
3120 NULL, HFILL }
3122 { &hf_ntlmssp_negotiate_flags_200,
3123 { "Negotiate NTLM key", "ntlmssp.negotiatentlm",
3124 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_NTLM,
3125 NULL, HFILL }
3127 { &hf_ntlmssp_negotiate_flags_400,
3128 { "Negotiate 0x00000400", "ntlmssp.unused00000400",
3129 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00000400,
3130 NULL, HFILL }
3132 { &hf_ntlmssp_negotiate_flags_800,
3133 { "Negotiate Anonymous", "ntlmssp.negotiateanonymous",
3134 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ANONYMOUS,
3135 NULL, HFILL }
3137 { &hf_ntlmssp_negotiate_flags_1000,
3138 { "Negotiate OEM Domain Supplied", "ntlmssp.negotiateoemdomainsupplied",
3139 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED,
3140 NULL, HFILL }
3142 { &hf_ntlmssp_negotiate_flags_2000,
3143 { "Negotiate OEM Workstation Supplied", "ntlmssp.negotiateoemworkstationsupplied",
3144 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED,
3145 NULL, HFILL }
3147 { &hf_ntlmssp_negotiate_flags_4000,
3148 { "Negotiate 0x00004000", "ntlmssp.unused00004000",
3149 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00004000,
3150 NULL, HFILL }
3152 { &hf_ntlmssp_negotiate_flags_8000,
3153 { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign",
3154 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_ALWAYS_SIGN,
3155 NULL, HFILL }
3157 { &hf_ntlmssp_negotiate_flags_10000,
3158 { "Target Type Domain", "ntlmssp.targettypedomain",
3159 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_DOMAIN,
3160 NULL, HFILL }
3162 { &hf_ntlmssp_negotiate_flags_20000,
3163 { "Target Type Server", "ntlmssp.targettypeserver",
3164 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER,
3165 NULL, HFILL }
3167 { &hf_ntlmssp_negotiate_flags_40000,
3168 { "Negotiate 0x00040000", "ntlmssp.unused00040000",
3169 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00040000,
3170 NULL, HFILL }
3173 /* Negotiate Flags */
3174 { &hf_ntlmssp_negotiate_flags_80000,
3175 { "Negotiate Extended Session Security", "ntlmssp.negotiateextendedsessionsecurity",
3176 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY,
3177 NULL, HFILL }
3179 { &hf_ntlmssp_negotiate_flags_100000,
3180 { "Negotiate Identify", "ntlmssp.negotiateidentify",
3181 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_IDENTIFY,
3182 NULL, HFILL }
3184 { &hf_ntlmssp_negotiate_flags_200000,
3185 { "Negotiate 0x00200000", "ntlmssp.unused00200000",
3186 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_00200000,
3187 NULL, HFILL }
3189 { &hf_ntlmssp_negotiate_flags_400000,
3190 { "Request Non-NT Session Key", "ntlmssp.requestnonntsessionkey",
3191 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_REQUEST_NON_NT_SESSION_KEY,
3192 NULL, HFILL }
3194 { &hf_ntlmssp_negotiate_flags_800000,
3195 { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo",
3196 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_TARGET_INFO,
3197 NULL, HFILL }
3199 { &hf_ntlmssp_negotiate_flags_1000000,
3200 { "Negotiate 0x01000000", "ntlmssp.unused01000000",
3201 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_01000000,
3202 NULL, HFILL }
3204 { &hf_ntlmssp_negotiate_flags_2000000,
3205 { "Negotiate Version", "ntlmssp.negotiateversion",
3206 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_VERSION,
3207 NULL, HFILL }
3209 { &hf_ntlmssp_negotiate_flags_4000000,
3210 { "Negotiate 0x04000000", "ntlmssp.unused04000000",
3211 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_04000000,
3212 NULL, HFILL }
3214 { &hf_ntlmssp_negotiate_flags_8000000,
3215 { "Negotiate 0x08000000", "ntlmssp.unused08000000",
3216 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_08000000,
3217 NULL, HFILL }
3219 { &hf_ntlmssp_negotiate_flags_10000000,
3220 { "Negotiate 0x10000000", "ntlmssp.unused10000000",
3221 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_UNUSED_10000000,
3222 NULL, HFILL }
3224 { &hf_ntlmssp_negotiate_flags_20000000,
3225 { "Negotiate 128", "ntlmssp.negotiate128",
3226 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_128,
3227 "128-bit encryption is supported", HFILL }
3229 { &hf_ntlmssp_negotiate_flags_40000000,
3230 { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch",
3231 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_KEY_EXCH,
3232 NULL, HFILL }
3234 { &hf_ntlmssp_negotiate_flags_80000000,
3235 { "Negotiate 56", "ntlmssp.negotiate56",
3236 FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_56,
3237 "56-bit encryption is supported", HFILL }
3239 #if 0
3240 { &hf_ntlmssp_negotiate_workstation_strlen,
3241 { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen",
3242 FT_UINT16, BASE_DEC, NULL, 0x0,
3243 NULL, HFILL }
3245 #endif
3246 #if 0
3247 { &hf_ntlmssp_negotiate_workstation_maxlen,
3248 { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen",
3249 FT_UINT16, BASE_DEC, NULL, 0x0,
3250 NULL, HFILL }
3252 #endif
3253 #if 0
3254 { &hf_ntlmssp_negotiate_workstation_buffer,
3255 { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer",
3256 FT_UINT32, BASE_HEX, NULL, 0x0,
3257 NULL, HFILL }
3259 #endif
3260 { &hf_ntlmssp_negotiate_workstation,
3261 { "Calling workstation name", "ntlmssp.negotiate.callingworkstation",
3262 FT_STRING, BASE_NONE, NULL, 0x0,
3263 NULL, HFILL }
3265 #if 0
3266 { &hf_ntlmssp_negotiate_domain_strlen,
3267 { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen",
3268 FT_UINT16, BASE_DEC, NULL, 0x0,
3269 NULL, HFILL }
3271 #endif
3272 #if 0
3273 { &hf_ntlmssp_negotiate_domain_maxlen,
3274 { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen",
3275 FT_UINT16, BASE_DEC, NULL, 0x0,
3276 NULL, HFILL }
3278 #endif
3279 #if 0
3280 { &hf_ntlmssp_negotiate_domain_buffer,
3281 { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer",
3282 FT_UINT32, BASE_HEX, NULL, 0x0,
3283 NULL, HFILL }
3285 #endif
3286 { &hf_ntlmssp_negotiate_domain,
3287 { "Calling workstation domain", "ntlmssp.negotiate.domain",
3288 FT_STRING, BASE_NONE, NULL, 0x0,
3289 NULL, HFILL }
3291 { &hf_ntlmssp_ntlm_client_challenge,
3292 { "LMv2 Client Challenge", "ntlmssp.ntlmclientchallenge",
3293 FT_BYTES, BASE_NONE, NULL, 0x0,
3294 "The 8-byte LMv2 challenge message generated by the client", HFILL }
3296 { &hf_ntlmssp_ntlm_server_challenge,
3297 { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge",
3298 FT_BYTES, BASE_NONE, NULL, 0x0,
3299 NULL, HFILL }
3301 { &hf_ntlmssp_reserved,
3302 { "Reserved", "ntlmssp.reserved",
3303 FT_BYTES, BASE_NONE, NULL, 0x0,
3304 NULL, HFILL }
3307 { &hf_ntlmssp_challenge_target_name,
3308 { "Target Name", "ntlmssp.challenge.target_name",
3309 FT_STRING, BASE_NONE, NULL, 0x0,
3310 NULL, HFILL }
3312 { &hf_ntlmssp_auth_domain,
3313 { "Domain name", "ntlmssp.auth.domain",
3314 FT_STRING, BASE_NONE, NULL, 0x0,
3315 NULL, HFILL }
3317 { &hf_ntlmssp_auth_username,
3318 { "User name", "ntlmssp.auth.username",
3319 FT_STRING, BASE_NONE, NULL, 0x0,
3320 NULL, HFILL }
3322 { &hf_ntlmssp_auth_hostname,
3323 { "Host name", "ntlmssp.auth.hostname",
3324 FT_STRING, BASE_NONE, NULL, 0x0,
3325 NULL, HFILL }
3327 { &hf_ntlmssp_auth_lmresponse,
3328 { "Lan Manager Response", "ntlmssp.auth.lmresponse",
3329 FT_BYTES, BASE_NONE, NULL, 0x0,
3330 NULL, HFILL }
3332 { &hf_ntlmssp_auth_ntresponse,
3333 { "NTLM Response", "ntlmssp.auth.ntresponse",
3334 FT_BYTES, BASE_NONE, NULL, 0x0,
3335 NULL, HFILL }
3337 { &hf_ntlmssp_auth_sesskey,
3338 { "Session Key", "ntlmssp.auth.sesskey",
3339 FT_BYTES, BASE_NONE, NULL, 0x0,
3340 NULL, HFILL }
3342 { &hf_ntlmssp_string_len,
3343 { "Length", "ntlmssp.string.length",
3344 FT_UINT16, BASE_DEC, NULL, 0x0,
3345 NULL, HFILL}
3347 { &hf_ntlmssp_string_maxlen,
3348 { "Maxlen", "ntlmssp.string.maxlen",
3349 FT_UINT16, BASE_DEC, NULL, 0x0,
3350 NULL, HFILL}
3352 { &hf_ntlmssp_string_offset,
3353 { "Offset", "ntlmssp.string.offset",
3354 FT_UINT32, BASE_DEC, NULL, 0x0,
3355 NULL, HFILL}
3357 { &hf_ntlmssp_blob_len,
3358 { "Length", "ntlmssp.blob.length",
3359 FT_UINT16, BASE_DEC, NULL, 0x0,
3360 NULL, HFILL}
3362 { &hf_ntlmssp_blob_maxlen,
3363 { "Maxlen", "ntlmssp.blob.maxlen",
3364 FT_UINT16, BASE_DEC, NULL, 0x0,
3365 NULL, HFILL}
3367 { &hf_ntlmssp_blob_offset,
3368 { "Offset", "ntlmssp.blob.offset",
3369 FT_UINT32, BASE_DEC, NULL, 0x0,
3370 NULL, HFILL}
3372 { &hf_ntlmssp_version,
3373 { "Version", "ntlmssp.version",
3374 FT_NONE, BASE_NONE, NULL, 0x0,
3375 NULL, HFILL}
3377 { &hf_ntlmssp_version_major,
3378 { "Major Version", "ntlmssp.version.major",
3379 FT_UINT8, BASE_DEC, NULL, 0x0,
3380 NULL, HFILL}
3382 { &hf_ntlmssp_version_minor,
3383 { "Minor Version", "ntlmssp.version.minor",
3384 FT_UINT8, BASE_DEC, NULL, 0x0,
3385 NULL, HFILL}
3387 { &hf_ntlmssp_version_build_number,
3388 { "Build Number", "ntlmssp.version.build_number",
3389 FT_UINT16, BASE_DEC, NULL, 0x0,
3390 NULL, HFILL}
3392 { &hf_ntlmssp_version_ntlm_current_revision,
3393 { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision",
3394 FT_UINT8, BASE_DEC, NULL, 0x0,
3395 NULL, HFILL}
3398 /* Target Info */
3399 { &hf_ntlmssp_challenge_target_info,
3400 { "Target Info", "ntlmssp.challenge.target_info",
3401 FT_NONE, BASE_NONE, NULL, 0x0,
3402 NULL, HFILL}
3404 { &hf_ntlmssp_challenge_target_info_len,
3405 { "Length", "ntlmssp.challenge.target_info.length",
3406 FT_UINT16, BASE_DEC, NULL, 0x0,
3407 NULL, HFILL}
3409 { &hf_ntlmssp_challenge_target_info_maxlen,
3410 { "Maxlen", "ntlmssp.challenge.target_info.maxlen",
3411 FT_UINT16, BASE_DEC, NULL, 0x0,
3412 NULL, HFILL}
3414 { &hf_ntlmssp_challenge_target_info_offset,
3415 { "Offset", "ntlmssp.challenge.target_info.offset",
3416 FT_UINT32, BASE_DEC, NULL, 0x0,
3417 NULL, HFILL}
3420 { &hf_ntlmssp_challenge_target_info_item_type,
3421 { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type",
3422 FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ntlm_name_types_ext, 0x0,
3423 NULL, HFILL }
3425 { &hf_ntlmssp_challenge_target_info_item_len,
3426 { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length",
3427 FT_UINT16, BASE_DEC, NULL, 0x0,
3428 NULL, HFILL}
3431 { &hf_ntlmssp_challenge_target_info_end,
3432 { "List End", "ntlmssp.challenge.target_info.end",
3433 FT_NONE, BASE_NONE, NULL, 0x0,
3434 NULL, HFILL }
3436 { &hf_ntlmssp_challenge_target_info_nb_computer_name,
3437 { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name",
3438 FT_STRING, BASE_NONE, NULL, 0x0,
3439 "Server NetBIOS Computer Name", HFILL }
3441 { &hf_ntlmssp_challenge_target_info_nb_domain_name,
3442 { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name",
3443 FT_STRING, BASE_NONE, NULL, 0x0,
3444 "Server NetBIOS Domain Name", HFILL }
3446 { &hf_ntlmssp_challenge_target_info_dns_computer_name,
3447 { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name",
3448 FT_STRING, BASE_NONE, NULL, 0x0,
3449 NULL, HFILL }
3451 { &hf_ntlmssp_challenge_target_info_dns_domain_name,
3452 { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name",
3453 FT_STRING, BASE_NONE, NULL, 0x0,
3454 NULL, HFILL }
3456 { &hf_ntlmssp_challenge_target_info_dns_tree_name,
3457 { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name",
3458 FT_STRING, BASE_NONE, NULL, 0x0,
3459 NULL, HFILL }
3461 { &hf_ntlmssp_challenge_target_info_flags,
3462 { "Flags", "ntlmssp.challenge.target_info.flags",
3463 FT_UINT32, BASE_HEX, NULL, 0x0,
3464 NULL, HFILL }
3466 { &hf_ntlmssp_challenge_target_info_timestamp,
3467 { "Timestamp", "ntlmssp.challenge.target_info.timestamp",
3468 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
3469 NULL, HFILL }
3471 { &hf_ntlmssp_challenge_target_info_restrictions,
3472 { "Restrictions", "ntlmssp.challenge.target_info.restrictions",
3473 FT_BYTES, BASE_NONE, NULL, 0,
3474 NULL, HFILL }
3476 { &hf_ntlmssp_challenge_target_info_target_name,
3477 { "Target Name", "ntlmssp.challenge.target_info.target_name",
3478 FT_STRING, BASE_NONE, NULL, 0x0,
3479 NULL, HFILL }
3481 { &hf_ntlmssp_challenge_target_info_channel_bindings,
3482 { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings",
3483 FT_BYTES, BASE_NONE, NULL, 0x0,
3484 NULL, HFILL }
3487 { &hf_ntlmssp_ntlmv2_response_item_type,
3488 { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type",
3489 FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ntlm_name_types_ext, 0x0,
3490 NULL, HFILL }
3492 { &hf_ntlmssp_ntlmv2_response_item_len,
3493 { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length",
3494 FT_UINT16, BASE_DEC, NULL, 0x0,
3495 NULL, HFILL}
3498 { &hf_ntlmssp_ntlmv2_response_end,
3499 { "List End", "ntlmssp.ntlmv2_response.end",
3500 FT_NONE, BASE_NONE, NULL, 0x0,
3501 NULL, HFILL }
3503 { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
3504 { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name",
3505 FT_STRING, BASE_NONE, NULL, 0x0,
3506 "Server NetBIOS Computer Name", HFILL }
3508 { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
3509 { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name",
3510 FT_STRING, BASE_NONE, NULL, 0x0,
3511 "Server NetBIOS Domain Name", HFILL }
3513 { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
3514 { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name",
3515 FT_STRING, BASE_NONE, NULL, 0x0,
3516 NULL, HFILL }
3518 { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
3519 { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name",
3520 FT_STRING, BASE_NONE, NULL, 0x0,
3521 NULL, HFILL }
3523 { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
3524 { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name",
3525 FT_STRING, BASE_NONE, NULL, 0x0,
3526 NULL, HFILL }
3528 { &hf_ntlmssp_ntlmv2_response_flags,
3529 { "Flags", "ntlmssp.ntlmv2_response.flags",
3530 FT_UINT32, BASE_HEX, NULL, 0x0,
3531 NULL, HFILL }
3533 { &hf_ntlmssp_ntlmv2_response_timestamp,
3534 { "Timestamp", "ntlmssp.ntlmv2_response.timestamp",
3535 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
3536 NULL, HFILL }
3538 { &hf_ntlmssp_ntlmv2_response_restrictions,
3539 { "Restrictions", "ntlmssp.ntlmv2_response.restrictions",
3540 FT_BYTES, BASE_NONE, NULL, 0,
3541 NULL, HFILL }
3543 { &hf_ntlmssp_ntlmv2_response_target_name,
3544 { "Target Name", "ntlmssp.ntlmv2_response.target_name",
3545 FT_STRING, BASE_NONE, NULL, 0x0,
3546 NULL, HFILL }
3548 { &hf_ntlmssp_ntlmv2_response_channel_bindings,
3549 { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings",
3550 FT_BYTES, BASE_NONE, NULL, 0x0,
3551 NULL, HFILL }
3554 { &hf_ntlmssp_message_integrity_code,
3555 { "MIC", "ntlmssp.authenticate.mic",
3556 FT_BYTES, BASE_NONE, NULL, 0x0,
3557 "Message Integrity Code", HFILL}
3559 { &hf_ntlmssp_verf,
3560 { "NTLMSSP Verifier", "ntlmssp.verf",
3561 FT_NONE, BASE_NONE, NULL, 0x0,
3562 NULL, HFILL }
3564 { &hf_ntlmssp_verf_vers,
3565 { "Version Number", "ntlmssp.verf.vers",
3566 FT_UINT32, BASE_DEC, NULL, 0x0,
3567 NULL, HFILL }
3569 { &hf_ntlmssp_verf_body,
3570 { "Verifier Body", "ntlmssp.verf.body",
3571 FT_BYTES, BASE_NONE, NULL, 0x0,
3572 NULL, HFILL }
3574 #if 0
3575 { &hf_ntlmssp_decrypted_payload,
3576 { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload",
3577 FT_BYTES, BASE_NONE, NULL, 0x0,
3578 NULL, HFILL }
3580 #endif
3581 { &hf_ntlmssp_verf_randompad,
3582 { "Random Pad", "ntlmssp.verf.randompad",
3583 FT_UINT32, BASE_HEX, NULL, 0x0,
3584 NULL, HFILL }
3586 { &hf_ntlmssp_verf_crc32,
3587 { "Verifier CRC32", "ntlmssp.verf.crc32",
3588 FT_UINT32, BASE_HEX, NULL, 0x0,
3589 NULL, HFILL }
3591 { &hf_ntlmssp_verf_hmacmd5,
3592 { "HMAC MD5", "ntlmssp.verf.hmacmd5",
3593 FT_BYTES, BASE_NONE, NULL, 0x0,
3594 NULL, HFILL }
3596 { &hf_ntlmssp_verf_sequence,
3597 { "Sequence", "ntlmssp.verf.sequence",
3598 FT_BYTES, BASE_NONE, NULL, 0x0,
3599 NULL, HFILL }
3602 { &hf_ntlmssp_ntlmv2_response,
3603 { "NTLMv2 Response", "ntlmssp.ntlmv2_response",
3604 FT_BYTES, BASE_NONE, NULL, 0x0,
3605 NULL, HFILL }
3607 { &hf_ntlmssp_ntlmv2_response_ntproofstr,
3608 { "NTProofStr", "ntlmssp.ntlmv2_response.ntproofstr",
3609 FT_BYTES, BASE_NONE, NULL, 0x0,
3610 "The HMAC-MD5 of the challenge", HFILL }
3612 { &hf_ntlmssp_ntlmv2_response_rversion,
3613 { "Response Version", "ntlmssp.ntlmv2_response.rversion",
3614 FT_UINT8, BASE_DEC, NULL, 0x0,
3615 "The 1-byte response version, currently set to 1", HFILL }
3617 { &hf_ntlmssp_ntlmv2_response_hirversion,
3618 { "Hi Response Version", "ntlmssp.ntlmv2_response.hirversion",
3619 FT_UINT8, BASE_DEC, NULL, 0x0,
3620 "The 1-byte highest response version understood by the client, currently set to 1", HFILL }
3622 { &hf_ntlmssp_ntlmv2_response_z,
3623 { "Z", "ntlmssp.ntlmv2_response.z",
3624 FT_BYTES, BASE_NONE, NULL, 0x0,
3625 "byte array of zero bytes", HFILL }
3627 { &hf_ntlmssp_ntlmv2_response_pad,
3628 { "padding", "ntlmssp.ntlmv2_response.pad",
3629 FT_BYTES, BASE_NONE, NULL, 0x0,
3630 NULL, HFILL }
3632 { &hf_ntlmssp_ntlmv2_response_time,
3633 { "Time", "ntlmssp.ntlmv2_response.time",
3634 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
3635 "The 8-byte little-endian time in UTC", HFILL }
3637 { &hf_ntlmssp_ntlmv2_response_chal,
3638 { "NTLMv2 Client Challenge", "ntlmssp.ntlmv2_response.chal",
3639 FT_BYTES, BASE_NONE, NULL, 0x0,
3640 "The 8-byte NTLMv2 challenge message generated by the client", HFILL }
3642 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL,
3643 { "NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL",
3644 FT_NONE, BASE_NONE, NULL, 0,
3645 NULL, HFILL }},
3646 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Version,
3647 { "Version", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.Version",
3648 FT_UINT32, BASE_HEX, VALS(MSV1_0_CRED_VERSION), 0,
3649 NULL, HFILL }},
3650 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_Flags,
3651 { "Flags", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.Flags",
3652 FT_UINT32, BASE_HEX, NULL, 0,
3653 NULL, HFILL }},
3654 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_LM_PRESENT,
3655 { "lm_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.LM_PRESENT",
3656 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_LM_PRESENT,
3657 NULL, HFILL }},
3658 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_NT_PRESENT,
3659 { "nt_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.NT_PRESENT",
3660 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_NT_PRESENT,
3661 NULL, HFILL }},
3662 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_REMOVED,
3663 { "removed", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.REMOVED",
3664 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_REMOVED,
3665 NULL, HFILL }},
3666 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_CREDKEY_PRESENT,
3667 { "credkey_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.CREDKEY_PRESENT",
3668 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_CREDKEY_PRESENT,
3669 NULL, HFILL }},
3670 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_FLAG_SHA_PRESENT,
3671 { "sha_present", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.SHA_PRESENT",
3672 FT_BOOLEAN, 32, NULL, MSV1_0_CRED_SHA_PRESENT,
3673 NULL, HFILL }},
3674 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKey,
3675 { "CredentialKey", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.CredentialKey",
3676 FT_BYTES, BASE_NONE, NULL, 0,
3677 NULL, HFILL }},
3678 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_CredentialKeyType,
3679 { "CredentialKeyType", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.CredentialKeyType",
3680 FT_UINT32, BASE_DEC, VALS(MSV1_0_CREDENTIAL_KEY_TYPE), 0,
3681 NULL, HFILL }},
3682 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCredsSize,
3683 { "EncryptedCredsSize", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.EncryptedCredsSize",
3684 FT_UINT32, BASE_DEC, NULL, 0,
3685 NULL, HFILL }},
3686 { &hf_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL_EncryptedCreds,
3687 { "EncryptedCreds", "ntlmssp.NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL.EncryptedCreds",
3688 FT_BYTES, BASE_NONE, NULL, 0,
3689 NULL, HFILL }},
3693 static int *ett[] = {
3694 &ett_ntlmssp,
3695 &ett_ntlmssp_negotiate_flags,
3696 &ett_ntlmssp_string,
3697 &ett_ntlmssp_blob,
3698 &ett_ntlmssp_version,
3699 &ett_ntlmssp_challenge_target_info,
3700 &ett_ntlmssp_challenge_target_info_item,
3701 &ett_ntlmssp_ntlmv2_response,
3702 &ett_ntlmssp_ntlmv2_response_item,
3703 &ett_ntlmssp_NTLM_REMOTE_SUPPLEMENTAL_CREDENTIAL,
3705 static ei_register_info ei[] = {
3706 { &ei_ntlmssp_v2_key_too_long, { "ntlmssp.v2_key_too_long", PI_UNDECODED, PI_WARN, "NTLM v2 key is too long", EXPFILL }},
3707 { &ei_ntlmssp_blob_len_too_long, { "ntlmssp.blob.length.too_long", PI_UNDECODED, PI_WARN, "Session blob length too long", EXPFILL }},
3708 { &ei_ntlmssp_target_info_attr, { "ntlmssp.target_info_attr.unknown", PI_UNDECODED, PI_WARN, "Unknown NTLMSSP Target Info Attribute", EXPFILL }},
3709 { &ei_ntlmssp_target_info_invalid, { "ntlmssp.target_info_attr.invalid", PI_UNDECODED, PI_WARN, "Invalid NTLMSSP Target Info AvPairs", EXPFILL }},
3710 { &ei_ntlmssp_message_type, { "ntlmssp.messagetype.unknown", PI_PROTOCOL, PI_WARN, "Unrecognized NTLMSSP Message", EXPFILL }},
3711 { &ei_ntlmssp_auth_nthash, { "ntlmssp.authenticated", PI_SECURITY, PI_CHAT, "Authenticated NTHASH", EXPFILL }},
3712 { &ei_ntlmssp_sessionbasekey, { "ntlmssp.sessionbasekey", PI_SECURITY, PI_CHAT, "SessionBaseKey", EXPFILL }},
3713 { &ei_ntlmssp_sessionkey, { "ntlmssp.sessionkey", PI_SECURITY, PI_CHAT, "SessionKey", EXPFILL }},
3715 module_t *ntlmssp_module;
3716 expert_module_t* expert_ntlmssp;
3718 proto_ntlmssp = proto_register_protocol (
3719 "NTLM Secure Service Provider", /* name */
3720 "NTLMSSP", /* short name */
3721 "ntlmssp" /* abbrev */
3723 proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
3724 proto_register_subtree_array (ett, array_length (ett));
3725 expert_ntlmssp = expert_register_protocol(proto_ntlmssp);
3726 expert_register_field_array(expert_ntlmssp, ei, array_length(ei));
3727 register_init_routine(&ntlmssp_init_protocol);
3728 register_cleanup_routine(&ntlmssp_cleanup_protocol);
3730 ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
3732 prefs_register_string_preference(ntlmssp_module, "nt_password",
3733 "NT Password",
3734 "Cleartext NT Password (used to decrypt payloads, supports only ASCII passwords)",
3735 &ntlmssp_option_nt_password);
3737 ntlmssp_handle = register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
3738 ntlmssp_wrap_handle = register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
3739 register_dissector("ntlmssp_data_only", dissect_ntlmssp_payload_only, proto_ntlmssp);
3740 register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
3742 ntlmssp_tap = register_tap("ntlmssp");
3745 void
3746 proto_reg_handoff_ntlmssp(void)
3748 /* Register protocol with the GSS-API module */
3750 gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
3751 ntlmssp_handle, ntlmssp_wrap_handle,
3752 "NTLMSSP - Microsoft NTLM Security Support Provider");
3754 /* Register authenticated pipe dissector */
3757 * XXX - the verifiers here seem to have a version of 1 and a body of all
3758 * zeroes.
3760 * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
3761 * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
3762 * any other levels here?
3764 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
3765 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3766 &ntlmssp_sign_fns);
3768 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
3769 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3770 &ntlmssp_sign_fns);
3772 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
3773 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3774 &ntlmssp_sign_fns);
3776 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
3777 DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
3778 &ntlmssp_seal_fns);
3782 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3784 * Local variables:
3785 * c-basic-offset: 2
3786 * tab-width: 8
3787 * indent-tabs-mode: nil
3788 * End:
3790 * vi: set shiftwidth=2 tabstop=8 expandtab:
3791 * :indentSize=2:tabSize=8:noTabs=true: