forked from osmocom/wireshark
![Guy Harris](/assets/img/avatar_default.png)
call to "gssapi_init_oid()" supplies both dissectors for context-level tokens and GSS_Wrap header information; the latter dissector should return the number of bytes of header information, so that if the header information and the message for the protocol that's using GSSAPI are treated as a single blob of data (as is the case with LDAP, but not with DCE RPC, for example), the dissector for the protocol using GSSAPI knows where to start dissecting. We associate a pointer to the entire data structure for the OID, not the handle for context-level token dissector for the OID, with conversations and frames. Make the dissector for NTLMSSP verifiers be the handler for GSS_Wrap stuff for NTLMSSP, and add support for GSS_Wrap stuff for Kerberos. Support SASL GSS-SPNEGO wrapping of LDAP messages. (XXX - this should really check for GSS-SPNEGO.) svn path=/trunk/; revision=6692
1017 lines
40 KiB
C
1017 lines
40 KiB
C
/* packet-ntlmssp.c
|
|
* Routines for NTLM Secure Service Provider
|
|
* Devin Heitmueller <dheitmueller@netilla.com>
|
|
*
|
|
* $Id: packet-ntlmssp.c,v 1.32 2002/11/28 06:48:42 guy Exp $
|
|
*
|
|
* Ethereal - Network traffic analyzer
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <glib.h>
|
|
#include <epan/packet.h>
|
|
|
|
#include "packet-smb-common.h"
|
|
#include "asn1.h" /* XXX - needed for subid_t */
|
|
#include "packet-gssapi.h"
|
|
#include "packet-frame.h"
|
|
|
|
/* Message types */
|
|
|
|
#define NTLMSSP_NEGOTIATE 1
|
|
#define NTLMSSP_CHALLENGE 2
|
|
#define NTLMSSP_AUTH 3
|
|
#define NTLMSSP_UNKNOWN 4
|
|
|
|
static const value_string ntlmssp_message_types[] = {
|
|
{ NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
|
|
{ NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
|
|
{ NTLMSSP_AUTH, "NTLMSSP_AUTH" },
|
|
{ NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/*
|
|
* NTLMSSP negotiation flags
|
|
* Taken from Samba
|
|
*/
|
|
#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
|
|
#define NTLMSSP_NEGOTIATE_OEM 0x00000002
|
|
#define NTLMSSP_REQUEST_TARGET 0x00000004
|
|
#define NTLMSSP_NEGOTIATE_00000008 0x00000008
|
|
#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
|
|
#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
|
|
#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE 0x00000040
|
|
#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
|
|
#define NTLMSSP_NEGOTIATE_NETWARE 0x00000100
|
|
#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
|
|
#define NTLMSSP_NEGOTIATE_00000400 0x00000400
|
|
#define NTLMSSP_NEGOTIATE_00000800 0x00000800
|
|
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
|
|
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
|
|
#define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL 0x00004000
|
|
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
|
|
#define NTLMSSP_CHAL_INIT_RESPONSE 0x00010000
|
|
#define NTLMSSP_CHAL_ACCEPT_RESPONSE 0x00020000
|
|
#define NTLMSSP_CHAL_NON_NT_SESSION_KEY 0x00040000
|
|
#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
|
|
#define NTLMSSP_NEGOTIATE_00100000 0x00100000
|
|
#define NTLMSSP_NEGOTIATE_00200000 0x00200000
|
|
#define NTLMSSP_NEGOTIATE_00400000 0x00400000
|
|
#define NTLMSSP_CHAL_TARGET_INFO 0x00800000
|
|
#define NTLMSSP_NEGOTIATE_01000000 0x01000000
|
|
#define NTLMSSP_NEGOTIATE_02000000 0x02000000
|
|
#define NTLMSSP_NEGOTIATE_04000000 0x04000000
|
|
#define NTLMSSP_NEGOTIATE_08000000 0x08000000
|
|
#define NTLMSSP_NEGOTIATE_10000000 0x10000000
|
|
#define NTLMSSP_NEGOTIATE_128 0x20000000
|
|
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
|
|
#define NTLMSSP_NEGOTIATE_80000000 0x80000000
|
|
|
|
|
|
static int proto_ntlmssp = -1;
|
|
static int hf_ntlmssp = -1;
|
|
static int hf_ntlmssp_auth = -1;
|
|
static int hf_ntlmssp_message_type = -1;
|
|
static int hf_ntlmssp_negotiate_flags = -1;
|
|
static int hf_ntlmssp_negotiate_flags_01 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_02 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_04 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_08 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_10 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_20 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_40 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_80 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_100 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_200 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_400 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_800 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_1000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_2000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_4000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_8000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_10000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_20000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_40000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_80000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_100000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_200000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_400000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_800000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_1000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_2000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_4000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_8000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_10000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_20000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_40000000 = -1;
|
|
static int hf_ntlmssp_negotiate_flags_80000000 = -1;
|
|
static int hf_ntlmssp_negotiate_workstation_strlen = -1;
|
|
static int hf_ntlmssp_negotiate_workstation_maxlen = -1;
|
|
static int hf_ntlmssp_negotiate_workstation_buffer = -1;
|
|
static int hf_ntlmssp_negotiate_workstation = -1;
|
|
static int hf_ntlmssp_negotiate_domain_strlen = -1;
|
|
static int hf_ntlmssp_negotiate_domain_maxlen = -1;
|
|
static int hf_ntlmssp_negotiate_domain_buffer = -1;
|
|
static int hf_ntlmssp_negotiate_domain = -1;
|
|
static int hf_ntlmssp_ntlm_challenge = -1;
|
|
static int hf_ntlmssp_reserved = -1;
|
|
static int hf_ntlmssp_challenge_domain = -1;
|
|
static int hf_ntlmssp_auth_username = -1;
|
|
static int hf_ntlmssp_auth_domain = -1;
|
|
static int hf_ntlmssp_auth_hostname = -1;
|
|
static int hf_ntlmssp_auth_lmresponse = -1;
|
|
static int hf_ntlmssp_auth_ntresponse = -1;
|
|
static int hf_ntlmssp_auth_sesskey = -1;
|
|
static int hf_ntlmssp_string_len = -1;
|
|
static int hf_ntlmssp_string_maxlen = -1;
|
|
static int hf_ntlmssp_string_offset = -1;
|
|
static int hf_ntlmssp_blob_len = -1;
|
|
static int hf_ntlmssp_blob_maxlen = -1;
|
|
static int hf_ntlmssp_blob_offset = -1;
|
|
static int hf_ntlmssp_address_list = -1;
|
|
static int hf_ntlmssp_address_list_len = -1;
|
|
static int hf_ntlmssp_address_list_maxlen = -1;
|
|
static int hf_ntlmssp_address_list_offset = -1;
|
|
static int hf_ntlmssp_address_list_server_nb = -1;
|
|
static int hf_ntlmssp_address_list_domain_nb = -1;
|
|
static int hf_ntlmssp_address_list_server_dns = -1;
|
|
static int hf_ntlmssp_address_list_domain_dns = -1;
|
|
static int hf_ntlmssp_verf_vers = -1;
|
|
static int hf_ntlmssp_verf_body = -1;
|
|
|
|
static gint ett_ntlmssp = -1;
|
|
static gint ett_ntlmssp_negotiate_flags = -1;
|
|
static gint ett_ntlmssp_string = -1;
|
|
static gint ett_ntlmssp_blob = -1;
|
|
static gint ett_ntlmssp_address_list = -1;
|
|
|
|
static GMemChunk *flag_info_chunk;
|
|
static int flag_info_chunk_count = 100;
|
|
|
|
/* dissect a string - header area contains:
|
|
two byte len
|
|
two byte maxlen
|
|
four byte offset of string in data area
|
|
The function returns the offset at the end of the string header,
|
|
but the 'end' parameter returns the offset of the end of the string itself
|
|
The 'start' parameter returns the offset of the beginning of the string
|
|
*/
|
|
static int
|
|
dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
|
|
proto_tree *ntlmssp_tree,
|
|
gboolean unicode_strings,
|
|
int string_hf, int *start, int *end)
|
|
{
|
|
proto_tree *tree = NULL;
|
|
proto_item *tf = NULL;
|
|
gint16 string_length = tvb_get_letohs(tvb, offset);
|
|
gint16 string_maxlen = tvb_get_letohs(tvb, offset+2);
|
|
gint32 string_offset = tvb_get_letohl(tvb, offset+4);
|
|
const char *string_text = NULL;
|
|
int result_length;
|
|
guint16 bc;
|
|
|
|
*start = (string_offset > offset+8 ? string_offset : offset+8);
|
|
if (0 == string_length) {
|
|
*end = *start;
|
|
if (ntlmssp_tree)
|
|
proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
|
|
offset, 8, "NULL");
|
|
return offset+8;
|
|
}
|
|
|
|
bc = result_length = string_length;
|
|
string_text = get_unicode_or_ascii_string(tvb, &string_offset,
|
|
unicode_strings, &result_length,
|
|
FALSE, TRUE, &bc);
|
|
|
|
if (ntlmssp_tree) {
|
|
tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
|
|
string_offset, result_length, string_text);
|
|
tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
|
|
}
|
|
proto_tree_add_uint(tree, hf_ntlmssp_string_len,
|
|
tvb, offset, 2, string_length);
|
|
offset += 2;
|
|
proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
|
|
tvb, offset, 2, string_maxlen);
|
|
offset += 2;
|
|
proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
|
|
tvb, offset, 4, string_offset);
|
|
offset += 4;
|
|
|
|
*end = string_offset + string_length;
|
|
return offset;
|
|
}
|
|
|
|
/* dissect a generic blob - header area contains:
|
|
two byte len
|
|
two byte maxlen
|
|
four byte offset of blob in data area
|
|
The function returns the offset at the end of the blob header,
|
|
but the 'end' parameter returns the offset of the end of the blob itself
|
|
*/
|
|
static int
|
|
dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
|
|
proto_tree *ntlmssp_tree,
|
|
int blob_hf, int *end)
|
|
{
|
|
proto_item *tf = NULL;
|
|
proto_tree *tree = NULL;
|
|
guint16 blob_length = tvb_get_letohs(tvb, offset);
|
|
guint16 blob_maxlen = tvb_get_letohs(tvb, offset+2);
|
|
guint32 blob_offset = tvb_get_letohl(tvb, offset+4);
|
|
|
|
if (0 == blob_length) {
|
|
*end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
|
|
if (ntlmssp_tree)
|
|
proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
|
|
proto_registrar_get_name(blob_hf));
|
|
return offset+8;
|
|
}
|
|
|
|
if (ntlmssp_tree) {
|
|
tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
|
|
blob_offset, blob_length, FALSE);
|
|
tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
|
|
}
|
|
proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
|
|
tvb, offset, 2, blob_length);
|
|
offset += 2;
|
|
proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
|
|
tvb, offset, 2, blob_maxlen);
|
|
offset += 2;
|
|
proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
|
|
tvb, offset, 4, blob_offset);
|
|
offset += 4;
|
|
|
|
*end = blob_offset + blob_length;
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
|
|
proto_tree *ntlmssp_tree,
|
|
guint32 negotiate_flags)
|
|
{
|
|
proto_tree *negotiate_flags_tree = NULL;
|
|
proto_item *tf = NULL;
|
|
|
|
if (ntlmssp_tree) {
|
|
tf = proto_tree_add_uint (ntlmssp_tree,
|
|
hf_ntlmssp_negotiate_flags,
|
|
tvb, offset, 4, negotiate_flags);
|
|
negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
|
|
}
|
|
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_80000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_40000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_20000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_10000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_8000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_4000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_2000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_1000000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_800000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_400000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_200000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_100000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_80000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_40000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_20000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_10000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_8000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_4000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_2000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_1000,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_800,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_400,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_200,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_100,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_80,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_40,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_20,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_10,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_08,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_04,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_02,
|
|
tvb, offset, 4, negotiate_flags);
|
|
proto_tree_add_boolean (negotiate_flags_tree,
|
|
hf_ntlmssp_negotiate_flags_01,
|
|
tvb, offset, 4, negotiate_flags);
|
|
|
|
return (offset + 4);
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree)
|
|
{
|
|
guint32 negotiate_flags;
|
|
int start;
|
|
int workstation_end;
|
|
int domain_end;
|
|
|
|
/* NTLMSSP Negotiate Flags */
|
|
negotiate_flags = tvb_get_letohl (tvb, offset);
|
|
offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
|
|
negotiate_flags);
|
|
|
|
offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
|
|
hf_ntlmssp_negotiate_domain,
|
|
&start, &workstation_end);
|
|
offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
|
|
hf_ntlmssp_negotiate_workstation,
|
|
&start, &domain_end);
|
|
|
|
/* XXX - two blobs after this one, sometimes? */
|
|
|
|
return MAX(workstation_end, domain_end);
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_ntlmssp_address_list (tvbuff_t *tvb, int offset,
|
|
proto_tree *ntlmssp_tree,
|
|
int *end)
|
|
{
|
|
guint16 list_length = tvb_get_letohs(tvb, offset);
|
|
guint16 list_maxlen = tvb_get_letohs(tvb, offset+2);
|
|
guint32 list_offset = tvb_get_letohl(tvb, offset+4);
|
|
guint16 item_type, item_length;
|
|
int item_offset;
|
|
proto_item *tf = NULL;
|
|
proto_tree *tree = NULL;
|
|
|
|
/* the address list is just a blob */
|
|
if (0 == list_length) {
|
|
*end = (list_offset > ((guint)offset)+8 ? list_offset : ((guint)offset)+8);
|
|
if (ntlmssp_tree)
|
|
proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
|
|
"Address List: Empty");
|
|
return offset+8;
|
|
}
|
|
|
|
if (ntlmssp_tree) {
|
|
tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_address_list, tvb,
|
|
list_offset, list_length, FALSE);
|
|
tree = proto_item_add_subtree(tf, ett_ntlmssp_address_list);
|
|
}
|
|
proto_tree_add_uint(tree, hf_ntlmssp_address_list_len,
|
|
tvb, offset, 2, list_length);
|
|
offset += 2;
|
|
proto_tree_add_uint(tree, hf_ntlmssp_address_list_maxlen,
|
|
tvb, offset, 2, list_maxlen);
|
|
offset += 2;
|
|
proto_tree_add_uint(tree, hf_ntlmssp_address_list_offset,
|
|
tvb, offset, 4, list_offset);
|
|
offset += 4;
|
|
|
|
item_offset = list_offset;
|
|
item_type = tvb_get_letohs(tvb, item_offset);
|
|
item_offset += 2;
|
|
item_length = tvb_get_letohs(tvb, item_offset);
|
|
item_offset += 2;
|
|
while (item_type) {
|
|
guint16 bc;
|
|
int result_length;
|
|
const char *text;
|
|
bc = item_length;
|
|
|
|
/* Strings are always in unicode regardless of the negotiated
|
|
string type. */
|
|
|
|
text = get_unicode_or_ascii_string(tvb, &item_offset,
|
|
TRUE, &result_length,
|
|
FALSE, FALSE, &bc);
|
|
|
|
if (!text) text = ""; /* Make sure we don't blow up below */
|
|
|
|
switch(item_type) {
|
|
case 1:
|
|
proto_tree_add_string(tree, hf_ntlmssp_address_list_server_nb,
|
|
tvb, item_offset, item_length, text);
|
|
break;
|
|
case 2:
|
|
proto_tree_add_string(tree, hf_ntlmssp_address_list_domain_nb,
|
|
tvb, item_offset, item_length, text);
|
|
break;
|
|
case 3:
|
|
proto_tree_add_string(tree, hf_ntlmssp_address_list_server_dns,
|
|
tvb, item_offset, item_length, text);
|
|
break;
|
|
case 4:
|
|
proto_tree_add_string(tree, hf_ntlmssp_address_list_domain_dns,
|
|
tvb, item_offset, item_length, text);
|
|
}
|
|
|
|
item_offset += item_length;
|
|
item_type = tvb_get_letohs(tvb, item_offset);
|
|
item_offset += 2;
|
|
item_length = tvb_get_letohs(tvb, item_offset);
|
|
item_offset += 2;
|
|
}
|
|
|
|
*end = list_offset + list_length;
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
|
|
proto_tree *ntlmssp_tree)
|
|
{
|
|
guint32 negotiate_flags;
|
|
int item_start, item_end;
|
|
int data_start, data_end;
|
|
guint32 *flag_info;
|
|
conversation_t *conversation;
|
|
gboolean unicode_strings = FALSE;
|
|
|
|
/* need to find unicode flag */
|
|
negotiate_flags = tvb_get_letohl (tvb, offset+8);
|
|
if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
|
|
unicode_strings = TRUE;
|
|
|
|
/*
|
|
* Store the flags with the conversation, as they're needed in order
|
|
* to dissect subsequent messages.
|
|
*/
|
|
conversation = find_conversation(&pinfo->src, &pinfo->dst,
|
|
pinfo->ptype, pinfo->srcport,
|
|
pinfo->destport, 0);
|
|
if (!conversation) { /* Create one */
|
|
conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
|
|
pinfo->srcport, pinfo->destport, 0);
|
|
}
|
|
|
|
if (!conversation_get_proto_data(conversation, proto_ntlmssp)) {
|
|
flag_info = g_mem_chunk_alloc(flag_info_chunk);
|
|
*flag_info = negotiate_flags;
|
|
|
|
conversation_add_proto_data(conversation, proto_ntlmssp, flag_info);
|
|
}
|
|
|
|
/* Domain name */
|
|
offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
|
|
hf_ntlmssp_challenge_domain,
|
|
&item_start, &item_end);
|
|
data_start = item_start;
|
|
data_end = item_end;
|
|
|
|
/* NTLMSSP Negotiate Flags */
|
|
offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
|
|
negotiate_flags);
|
|
|
|
/* NTLMSSP NT Lan Manager Challenge */
|
|
proto_tree_add_item (ntlmssp_tree,
|
|
hf_ntlmssp_ntlm_challenge,
|
|
tvb, offset, 8, FALSE);
|
|
offset += 8;
|
|
|
|
/* Reserved (function not completely known) */
|
|
/* XXX - SSP key? */
|
|
proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
|
|
tvb, offset, 8, FALSE);
|
|
offset += 8;
|
|
|
|
/*
|
|
* The presence or absence of this field is not obviously correlated
|
|
* with any flags in the previous NEGOTIATE message or in this
|
|
* message (other than the "Workstation Supplied" and "Domain
|
|
* Supplied" flags in the NEGOTIATE message, at least in the capture
|
|
* I've seen - but those also correlate with the presence of workstation
|
|
* and domain name fields, so it doesn't seem to make sense that they
|
|
* actually *indicate* whether the subsequent CHALLENGE has an
|
|
* address list).
|
|
*/
|
|
if (offset < data_start) {
|
|
offset = dissect_ntlmssp_address_list(tvb, offset, ntlmssp_tree, &item_end);
|
|
data_end = MAX(data_end, item_end);
|
|
}
|
|
|
|
return MAX(offset, data_end);
|
|
}
|
|
|
|
static int
|
|
dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
|
|
proto_tree *ntlmssp_tree)
|
|
{
|
|
int item_start, item_end;
|
|
int data_start, data_end = 0;
|
|
guint32 negotiate_flags;
|
|
gboolean unicode_strings = FALSE;
|
|
guint32 *flag_info;
|
|
conversation_t *conversation;
|
|
|
|
/*
|
|
* Get flag info from the original negotiate message, if any.
|
|
* This is because the flag information is sometimes missing from
|
|
* the AUTHENTICATE message, so we can't figure out whether
|
|
* strings are Unicode or not by looking at *our* flags.
|
|
*/
|
|
flag_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
|
|
if (flag_info == NULL) {
|
|
/*
|
|
* There isn't any. Is there any from this conversation? If so,
|
|
* it means this is the first time we've dissected this frame, so
|
|
* we should give it flag info.
|
|
*/
|
|
conversation = find_conversation(&pinfo->src, &pinfo->dst,
|
|
pinfo->ptype, pinfo->srcport,
|
|
pinfo->destport, 0);
|
|
if (conversation != NULL) {
|
|
flag_info = conversation_get_proto_data(conversation, proto_ntlmssp);
|
|
if (flag_info != NULL) {
|
|
/*
|
|
* We have flag info; attach it to the frame.
|
|
*/
|
|
p_add_proto_data(pinfo->fd, proto_ntlmssp, flag_info);
|
|
}
|
|
}
|
|
}
|
|
if (flag_info != NULL) {
|
|
if (*flag_info & NTLMSSP_NEGOTIATE_UNICODE)
|
|
unicode_strings = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Sometimes the session key and flags are missing.
|
|
* Sometimes the session key is present but the flags are missing.
|
|
* Sometimes they're both present.
|
|
*
|
|
* This does not correlate with any flags in the previous CHALLENGE
|
|
* message, and only correlates with "Negotiate Unicode", "Workstation
|
|
* Supplied", and "Domain Supplied" in the NEGOTIATE message - but
|
|
* those don't make sense as flags to use to determine this.
|
|
*
|
|
* So we check all of the descriptors to figure out where the data
|
|
* area begins, and if the session key or the flags would be in the
|
|
* middle of the data area, we assume the field in question is
|
|
* missing.
|
|
*/
|
|
|
|
/* Lan Manager response */
|
|
data_start = tvb_get_letohl(tvb, offset+4);
|
|
offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
|
|
hf_ntlmssp_auth_lmresponse,
|
|
&item_end);
|
|
data_end = MAX(data_end, item_end);
|
|
|
|
/* NTLM response */
|
|
item_start = tvb_get_letohl(tvb, offset+4);
|
|
offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
|
|
hf_ntlmssp_auth_ntresponse,
|
|
&item_end);
|
|
data_start = MIN(data_start, item_start);
|
|
data_end = MAX(data_end, item_end);
|
|
|
|
/* domain name */
|
|
item_start = tvb_get_letohl(tvb, offset+4);
|
|
offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
|
|
unicode_strings,
|
|
hf_ntlmssp_auth_domain,
|
|
&item_start, &item_end);
|
|
data_start = MIN(data_start, item_start);
|
|
data_end = MAX(data_end, item_end);
|
|
|
|
/* user name */
|
|
item_start = tvb_get_letohl(tvb, offset+4);
|
|
offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
|
|
unicode_strings,
|
|
hf_ntlmssp_auth_username,
|
|
&item_start, &item_end);
|
|
data_start = MIN(data_start, item_start);
|
|
data_end = MAX(data_end, item_end);
|
|
|
|
/* hostname */
|
|
item_start = tvb_get_letohl(tvb, offset+4);
|
|
offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
|
|
unicode_strings,
|
|
hf_ntlmssp_auth_hostname,
|
|
&item_start, &item_end);
|
|
data_start = MIN(data_start, item_start);
|
|
data_end = MAX(data_end, item_end);
|
|
|
|
if (offset < data_start) {
|
|
/* Session Key */
|
|
offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
|
|
hf_ntlmssp_auth_sesskey,
|
|
&item_end);
|
|
data_end = MAX(data_end, item_end);
|
|
}
|
|
|
|
if (offset < data_start) {
|
|
/* NTLMSSP Negotiate Flags */
|
|
negotiate_flags = tvb_get_letohl (tvb, offset);
|
|
offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
|
|
negotiate_flags);
|
|
}
|
|
|
|
return MAX(offset, data_end);
|
|
}
|
|
|
|
static void
|
|
dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
guint32 ntlmssp_message_type;
|
|
volatile int offset = 0;
|
|
proto_tree *volatile ntlmssp_tree = NULL;
|
|
proto_item *tf = NULL;
|
|
|
|
/* Setup a new tree for the NTLMSSP payload */
|
|
if (tree) {
|
|
tf = proto_tree_add_item (tree,
|
|
hf_ntlmssp,
|
|
tvb, offset, -1, FALSE);
|
|
|
|
ntlmssp_tree = proto_item_add_subtree (tf,
|
|
ett_ntlmssp);
|
|
}
|
|
|
|
/*
|
|
* Catch the ReportedBoundsError exception; the stuff we've been
|
|
* handed doesn't necessarily run to the end of the packet, it's
|
|
* an item inside a packet, so if it happens to be malformed (or
|
|
* we, or a dissector we call, has a bug), so that an exception
|
|
* is thrown, we want to report the error, but return and let
|
|
* our caller dissect the rest of the packet.
|
|
*
|
|
* If it gets a BoundsError, we can stop, as there's nothing more
|
|
* in the packet after our blob to see, so we just re-throw the
|
|
* exception.
|
|
*/
|
|
TRY {
|
|
/* NTLMSSP constant */
|
|
proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
|
|
tvb, offset, 8, FALSE);
|
|
offset += 8;
|
|
|
|
/* NTLMSSP Message Type */
|
|
proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
|
|
tvb, offset, 4, TRUE);
|
|
ntlmssp_message_type = tvb_get_letohl (tvb, offset);
|
|
offset += 4;
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
|
val_to_str(ntlmssp_message_type,
|
|
ntlmssp_message_types,
|
|
"Unknown message type"));
|
|
|
|
/* Call the appropriate dissector based on the Message Type */
|
|
switch (ntlmssp_message_type) {
|
|
|
|
case NTLMSSP_NEGOTIATE:
|
|
offset = dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree);
|
|
break;
|
|
|
|
case NTLMSSP_CHALLENGE:
|
|
offset = dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree);
|
|
break;
|
|
|
|
case NTLMSSP_AUTH:
|
|
offset = dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree);
|
|
break;
|
|
|
|
default:
|
|
/* Unrecognized message type */
|
|
proto_tree_add_text (ntlmssp_tree, tvb, offset, -1,
|
|
"Unrecognized NTLMSSP Message");
|
|
break;
|
|
}
|
|
} CATCH(BoundsError) {
|
|
RETHROW;
|
|
} CATCH(ReportedBoundsError) {
|
|
show_reported_bounds_error(tvb, pinfo, tree);
|
|
} ENDTRY;
|
|
}
|
|
|
|
/*
|
|
* See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
|
|
*/
|
|
static int
|
|
dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
volatile int offset = 0;
|
|
proto_tree *volatile ntlmssp_tree = NULL;
|
|
proto_item *tf = NULL;
|
|
|
|
/* Setup a new tree for the NTLMSSP payload */
|
|
if (tree) {
|
|
tf = proto_tree_add_item (tree,
|
|
hf_ntlmssp,
|
|
tvb, offset, -1, FALSE);
|
|
|
|
ntlmssp_tree = proto_item_add_subtree (tf,
|
|
ett_ntlmssp);
|
|
}
|
|
|
|
/*
|
|
* Catch the ReportedBoundsError exception; the stuff we've been
|
|
* handed doesn't necessarily run to the end of the packet, it's
|
|
* an item inside a packet, so if it happens to be malformed (or
|
|
* we, or a dissector we call, has a bug), so that an exception
|
|
* is thrown, we want to report the error, but return and let
|
|
* our caller dissect the rest of the packet.
|
|
*
|
|
* If it gets a BoundsError, we can stop, as there's nothing more
|
|
* in the packet after our blob to see, so we just re-throw the
|
|
* exception.
|
|
*/
|
|
TRY {
|
|
/* Version number */
|
|
proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
|
|
tvb, offset, 4, TRUE);
|
|
offset += 4;
|
|
|
|
/* Encrypted body */
|
|
proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
|
|
tvb, offset, 12, TRUE);
|
|
offset += 12;
|
|
} CATCH(BoundsError) {
|
|
RETHROW;
|
|
} CATCH(ReportedBoundsError) {
|
|
show_reported_bounds_error(tvb, pinfo, tree);
|
|
} ENDTRY;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
ntlmssp_init_protocol(void)
|
|
{
|
|
if (flag_info_chunk)
|
|
g_mem_chunk_destroy(flag_info_chunk);
|
|
flag_info_chunk = g_mem_chunk_new("flag_info", sizeof(guint32 *),
|
|
flag_info_chunk_count * sizeof(guint32 *),
|
|
G_ALLOC_ONLY);
|
|
}
|
|
|
|
void
|
|
proto_register_ntlmssp(void)
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
|
{ &hf_ntlmssp,
|
|
{ "NTLMSSP", "ntlmssp", FT_NONE, BASE_NONE, NULL, 0x0, "NTLMSSP", HFILL }},
|
|
|
|
{ &hf_ntlmssp_auth,
|
|
{ "NTLMSSP identifier", "ntlmssp.identifier", FT_STRING, BASE_NONE, NULL, 0x0, "NTLMSSP Identifier", HFILL }},
|
|
|
|
{ &hf_ntlmssp_message_type,
|
|
{ "NTLM Message Type", "ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, "", HFILL }},
|
|
|
|
{ &hf_ntlmssp_negotiate_flags,
|
|
{ "Flags", "ntlmssp.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_01,
|
|
|
|
{ "Negotiate UNICODE", "ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_UNICODE, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_02,
|
|
{ "Negotiate OEM", "ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_OEM, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_04,
|
|
{ "Request Target", "ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_REQUEST_TARGET, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_08,
|
|
{ "Request 0x00000008", "ntlmssp.negotiate00000008", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000008, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_10,
|
|
{ "Negotiate Sign", "ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SIGN, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_20,
|
|
{ "Negotiate Seal", "ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SEAL, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_40,
|
|
{ "Negotiate Datagram Style", "ntlmssp.negotiatedatagramstyle", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_DATAGRAM_STYLE, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_80,
|
|
{ "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_LM_KEY, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_100,
|
|
{ "Negotiate Netware", "ntlmssp.negotiatenetware", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NETWARE, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_200,
|
|
{ "Negotiate NTLM key", "ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_400,
|
|
{ "Negotiate 0x00000400", "ntlmssp.negotiate00000400", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000400, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_800,
|
|
{ "Negotiate 0x00000800", "ntlmssp.negotiate00000800", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000800, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_1000,
|
|
{ "Negotiate Domain Supplied", "ntlmssp.negotiatedomainsupplied", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_2000,
|
|
{ "Negotiate Workstation Supplied", "ntlmssp.negotiateworkstationsupplied", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_4000,
|
|
{ "Negotiate This is Local Call", "ntlmssp.negotiatethisislocalcall", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_8000,
|
|
{ "Negotiate Always Sign", "ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_10000,
|
|
{ "Negotiate Challenge Init Response", "ntlmssp.negotiatechallengeinitresponse", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_INIT_RESPONSE, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_20000,
|
|
{ "Negotiate Challenge Accept Response", "ntlmssp.negotiatechallengeacceptresponse", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_ACCEPT_RESPONSE, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_40000,
|
|
{ "Negotiate Challenge Non NT Session Key", "ntlmssp.negotiatechallengenonntsessionkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_NON_NT_SESSION_KEY, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_80000,
|
|
{ "Negotiate NTLM2 key", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM2, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_100000,
|
|
{ "Negotiate 0x00100000", "ntlmssp.negotiatent00100000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00100000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_200000,
|
|
{ "Negotiate 0x00200000", "ntlmssp.negotiatent00200000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00200000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_400000,
|
|
{ "Negotiate 0x00400000", "ntlmssp.negotiatent00400000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00400000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_800000,
|
|
{ "Negotiate Target Info", "ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_TARGET_INFO, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_1000000,
|
|
{ "Negotiate 0x01000000", "ntlmssp.negotiatent01000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_01000000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_2000000,
|
|
{ "Negotiate 0x02000000", "ntlmssp.negotiatent02000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_02000000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_4000000,
|
|
{ "Negotiate 0x04000000", "ntlmssp.negotiatent04000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_04000000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_8000000,
|
|
{ "Negotiate 0x08000000", "ntlmssp.negotiatent08000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_08000000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_10000000,
|
|
{ "Negotiate 0x10000000", "ntlmssp.negotiatent10000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_10000000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_20000000,
|
|
{ "Negotiate 128", "ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_128, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_40000000,
|
|
{ "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_KEY_EXCH, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_flags_80000000,
|
|
{ "Negotiate 0x80000000", "ntlmssp.negotiatent80000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_80000000, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_workstation_strlen,
|
|
{ "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_workstation_maxlen,
|
|
{ "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_workstation_buffer,
|
|
{ "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_workstation,
|
|
{ "Calling workstation name", "ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_domain_strlen,
|
|
{ "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_domain_maxlen,
|
|
{ "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_domain_buffer,
|
|
{ "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_negotiate_domain,
|
|
{ "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_ntlm_challenge,
|
|
{ "NTLM Challenge", "ntlmssp.ntlmchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_reserved,
|
|
{ "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_challenge_domain,
|
|
{ "Domain", "ntlmssp.challenge.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_auth_domain,
|
|
{ "Domain name", "ntlmssp.auth.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_auth_username,
|
|
{ "User name", "ntlmssp.auth.username", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_auth_hostname,
|
|
{ "Host name", "ntlmssp.auth.hostname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_auth_lmresponse,
|
|
{ "Lan Manager Response", "ntlmssp.auth.lmresponse", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_auth_ntresponse,
|
|
{ "NTLM Response", "ntlmssp.auth.ntresponse", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_auth_sesskey,
|
|
{ "Session Key", "ntlmssp.auth.sesskey", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_string_len,
|
|
{ "Length", "ntlmssp.string.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_string_maxlen,
|
|
{ "Maxlen", "ntlmssp.string.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_string_offset,
|
|
{ "Offset", "ntlmssp.string.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_blob_len,
|
|
{ "Length", "ntlmssp.blob.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_blob_maxlen,
|
|
{ "Maxlen", "ntlmssp.blob.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_blob_offset,
|
|
{ "Offset", "ntlmssp.blob.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_address_list,
|
|
{ "Address List", "ntlmssp.challenge.addresslist", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_address_list_len,
|
|
{ "Length", "ntlmssp.challenge.addresslist.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_address_list_maxlen,
|
|
{ "Maxlen", "ntlmssp.challenge.addresslist.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_address_list_offset,
|
|
{ "Offset", "ntlmssp.challenge.addresslist.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
|
|
{ &hf_ntlmssp_address_list_server_nb,
|
|
{ "Server NetBIOS Name", "ntlmssp.challenge.addresslist.servernb", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_address_list_domain_nb,
|
|
{ "Domain NetBIOS Name", "ntlmssp.challenge.addresslist.domainnb", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_address_list_server_dns,
|
|
{ "Server DNS Name", "ntlmssp.challenge.addresslist.serverdns", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_address_list_domain_dns,
|
|
{ "Domain DNS Name", "ntlmssp.challenge.addresslist.domaindns", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_ntlmssp_verf_vers,
|
|
{ "Version Number", "ntlmssp.verf.vers", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_ntlmssp_verf_body,
|
|
{ "Verifier Body", "ntlmssp.verf.body", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }}
|
|
|
|
};
|
|
|
|
|
|
static gint *ett[] = {
|
|
&ett_ntlmssp,
|
|
&ett_ntlmssp_negotiate_flags,
|
|
&ett_ntlmssp_string,
|
|
&ett_ntlmssp_blob,
|
|
&ett_ntlmssp_address_list
|
|
};
|
|
|
|
proto_ntlmssp = proto_register_protocol (
|
|
"NTLM Secure Service Provider", /* name */
|
|
"NTLMSSP", /* short name */
|
|
"ntlmssp" /* abbrev */
|
|
);
|
|
proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
|
|
proto_register_subtree_array (ett, array_length (ett));
|
|
register_init_routine(&ntlmssp_init_protocol);
|
|
|
|
register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
|
|
new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
|
|
}
|
|
|
|
void
|
|
proto_reg_handoff_ntlmssp(void)
|
|
{
|
|
dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
|
|
|
|
/* Register protocol with the GSS-API module */
|
|
|
|
ntlmssp_handle = find_dissector("ntlmssp");
|
|
ntlmssp_wrap_handle = find_dissector("ntlmssp_verf");
|
|
gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
|
|
ntlmssp_handle, ntlmssp_wrap_handle,
|
|
"NTLMSSP - Microsoft NTLM Security Support Provider");
|
|
}
|