diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-11-03 11:42:50 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-11-03 11:42:50 +0000 |
commit | f2676ba1c91c8b95427f3dfaa4176b20a486898d (patch) | |
tree | 7d3ab1ab40f4713a79924c9ceef4b60d7d91a1cb | |
parent | 80d72f8cf3c92156e9d8c1bab5f78bf812d3da87 (diff) |
Tvbuffification of Negotiate Protocol, from Ronnie Sahlberg.
Fix up Info column to put "Request" or "Response" *after* the name of
the request.
Give the Negotiate Protocol request its full name.
svn path=/trunk/; revision=4139
-rw-r--r-- | epan/proto.c | 18 | ||||
-rw-r--r-- | packet-smb.c | 1552 |
2 files changed, 987 insertions, 583 deletions
diff --git a/epan/proto.c b/epan/proto.c index b3906e9874..2955e54ee7 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -1,7 +1,7 @@ /* proto.c * Routines for protocol tree * - * $Id: proto.c,v 1.40 2001/11/03 01:19:59 guy Exp $ + * $Id: proto.c,v 1.41 2001/11/03 11:42:50 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -1547,9 +1547,15 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap) void proto_item_set_text(proto_item *pi, const char *format, ...) { - field_info *fi = (field_info*) (((GNode*)pi)->data); + field_info *fi = NULL; va_list ap; + if (pi==NULL) { + return; + } + + fi = (field_info *)(((GNode*)pi)->data); + if (fi->representation) g_mem_chunk_free(gmc_item_labels, fi->representation); @@ -1562,10 +1568,16 @@ proto_item_set_text(proto_item *pi, const char *format, ...) void proto_item_append_text(proto_item *pi, const char *format, ...) { - field_info *fi = (field_info*) (((GNode*)pi)->data); + field_info *fi = NULL; size_t curlen; va_list ap; + if (pi==NULL) { + return; + } + + fi = (field_info*) (((GNode*)pi)->data); + if (fi->visible) { va_start(ap, format); /* diff --git a/packet-smb.c b/packet-smb.c index 74e71c0fdf..047564f8da 100644 --- a/packet-smb.c +++ b/packet-smb.c @@ -2,7 +2,7 @@ * Routines for smb packet dissection * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com> * - * $Id: packet-smb.c,v 1.124 2001/11/03 06:56:55 guy Exp $ + * $Id: packet-smb.c,v 1.125 2001/11/03 11:42:47 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -79,6 +79,54 @@ static int hf_smb_flags2_dfs = -1; static int hf_smb_flags2_roe = -1; static int hf_smb_flags2_nt_error = -1; static int hf_smb_flags2_string = -1; +static int hf_smb_word_count = -1; +static int hf_smb_byte_count = -1; +static int hf_smb_buffer_format = -1; +static int hf_smb_dialect_name = -1; +static int hf_smb_dialect_index = -1; +static int hf_smb_max_trans_buf_size = -1; +static int hf_smb_max_mpx_count = -1; +static int hf_smb_max_vcs_num = -1; +static int hf_smb_session_key = -1; +static int hf_smb_server_timezone = -1; +static int hf_smb_encryption_key_length = -1; +static int hf_smb_encryption_key = -1; +static int hf_smb_primary_domain = -1; +static int hf_smb_max_raw_buf_size = -1; +static int hf_smb_server_guid = -1; +static int hf_smb_security_blob = -1; +static int hf_smb_sm_mode16 = -1; +static int hf_smb_sm_password16 = -1; +static int hf_smb_sm_mode = -1; +static int hf_smb_sm_password = -1; +static int hf_smb_sm_signatures = -1; +static int hf_smb_sm_sig_required = -1; +static int hf_smb_rm_read = -1; +static int hf_smb_rm_write = -1; +static int hf_smb_server_date_time = -1; +static int hf_smb_server_smb_date = -1; +static int hf_smb_server_smb_time = -1; +static int hf_smb_server_cap_raw_mode = -1; +static int hf_smb_server_cap_mpx_mode = -1; +static int hf_smb_server_cap_unicode = -1; +static int hf_smb_server_cap_large_files = -1; +static int hf_smb_server_cap_nt_smbs = -1; +static int hf_smb_server_cap_rpc_remote_apis = -1; +static int hf_smb_server_cap_nt_status = -1; +static int hf_smb_server_cap_level_ii_oplocks = -1; +static int hf_smb_server_cap_lock_and_read = -1; +static int hf_smb_server_cap_nt_find = -1; +static int hf_smb_server_cap_dfs = -1; +static int hf_smb_server_cap_infolevel_passthru = -1; +static int hf_smb_server_cap_large_readx = -1; +static int hf_smb_server_cap_large_writex = -1; +static int hf_smb_server_cap_unix = -1; +static int hf_smb_server_cap_reserved = -1; +static int hf_smb_server_cap_bulk_transfer = -1; +static int hf_smb_server_cap_compressed_data = -1; +static int hf_smb_server_cap_extended_security = -1; +static int hf_smb_system_time = -1; +static int hf_smb_unknown = -1; static gint ett_smb = -1; @@ -87,6 +135,7 @@ static gint ett_smb_command = -1; static gint ett_smb_fileattributes = -1; static gint ett_smb_capabilities = -1; static gint ett_smb_aflags = -1; +static gint ett_smb_dialect = -1; static gint ett_smb_dialects = -1; static gint ett_smb_mode = -1; static gint ett_smb_rawmode = -1; @@ -102,9 +151,34 @@ static gint ett_smb_writemode = -1; static gint ett_smb_lock_type = -1; static gint ett_smb_ssetupandxaction = -1; static gint ett_smb_optionsup = -1; +static gint ett_smb_time_date = -1; +static gint ett_smb_64bit_time = -1; + static char *decode_smb_name(unsigned char); static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree, guint8 cmd); +static const gchar *get_unicode_or_ascii_string_tvb(tvbuff_t *tvb, int *offsetp, packet_info *pinfo, int *len, gboolean nopad, gboolean exactlen); + + +#define WORD_COUNT \ + /* Word Count */ \ + wc = tvb_get_guint8(tvb, offset); \ + proto_tree_add_uint(tree, hf_smb_word_count, \ + tvb, offset, 1, wc); \ + offset += 1; \ + if(wc==0) goto bytecount; + +#define BYTE_COUNT \ + bytecount: \ + bc = tvb_get_letohs(tvb, offset); \ + proto_tree_add_uint(tree, hf_smb_byte_count, \ + tvb, offset, 2, bc); \ + offset += 2; \ + if(bc==0) goto endofcommand; + +#define END_OF_SMB \ + endofcommand: + /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX These variables and functions are used to match @@ -191,7 +265,601 @@ smb_info_init(void) End of request/response matching functions XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +static const value_string buffer_format_vals[] = { + {1, "Data Block"}, + {2, "Dialect"}, + {3, "Pathname"}, + {4, "ASCII"}, + {5, "Variable Block"}, + {0, NULL} +}; + +static int +dissect_smb_64bit_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, char *str, int hf_date) +{ + proto_item *item = NULL; + proto_tree *tree = NULL; + nstime_t tv; + + /* XXXX we need some way to represent this as a time + properly. For now we display everything as 8 bytes*/ + + if(parent_tree){ + item = proto_tree_add_text(parent_tree, tvb, offset, 8, + str); + tree = proto_item_add_subtree(item, ett_smb_64bit_time); + } + + proto_tree_add_bytes_format(tree, hf_smb_unknown, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8), "%s: can't decode this yet", str); + + offset += 8; + return offset; +} + +static int +dissect_smb_timedate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int hf_date, int hf_dos_date, int hf_dos_time) +{ + guint16 dos_time, dos_date; + proto_item *item = NULL; + proto_tree *tree = NULL; + struct tm tm; + time_t t; + nstime_t tv; + + dos_time = tvb_get_letohs(tvb, offset); + dos_date = tvb_get_letohs(tvb, offset+2); + + if((dos_time==0xffff)&&(dos_time==0xffff)){ + proto_tree_add_text(parent_tree, tvb, offset, 4, + "%s: No time specified (0xffffffff)", + proto_registrar_get_name(hf_date)); + offset += 4; + return offset; + } + + tm.tm_sec = (dos_time&0x1f)*2; + tm.tm_min = (dos_time>>5)&0x3f; + tm.tm_hour = (dos_time>>11)&0x1f; + tm.tm_mday = dos_date&0x1f; + tm.tm_mon = ((dos_date>>5)&0x0f) - 1; + tm.tm_year = ((dos_date>>9)&0x7f)+80; + tm.tm_isdst = -1; + + t = mktime(&tm); + + tv.secs = t; + tv.nsecs = 0; + + if(parent_tree){ + item = proto_tree_add_time(parent_tree, hf_date, tvb, offset, 4, &tv); + tree = proto_item_add_subtree(item, ett_smb_time_date); + proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time); + proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date); + } + + offset += 4; + + return offset; +} + +#define SERVER_CAP_RAW_MODE 0x00000001 +#define SERVER_CAP_MPX_MODE 0x00000002 +#define SERVER_CAP_UNICODE 0x00000004 +#define SERVER_CAP_LARGE_FILES 0x00000008 +#define SERVER_CAP_NT_SMBS 0x00000010 +#define SERVER_CAP_RPC_REMOTE_APIS 0x00000020 +#define SERVER_CAP_STATUS32 0x00000040 +#define SERVER_CAP_LEVEL_II_OPLOCKS 0x00000080 +#define SERVER_CAP_LOCK_AND_READ 0x00000100 +#define SERVER_CAP_NT_FIND 0x00000200 +#define SERVER_CAP_DFS 0x00001000 +#define SERVER_CAP_INFOLEVEL_PASSTHRU 0x00002000 +#define SERVER_CAP_LARGE_READX 0x00004000 +#define SERVER_CAP_LARGE_WRITEX 0x00008000 +#define SERVER_CAP_UNIX 0x00800000 +#define SERVER_CAP_RESERVED 0x02000000 +#define SERVER_CAP_BULK_TRANSFER 0x20000000 +#define SERVER_CAP_COMPRESSED_DATA 0x40000000 +#define SERVER_CAP_EXTENDED_SECURITY 0x80000000 +static const true_false_string tfs_server_cap_raw_mode = { + "Read Raw and Write Raw are supported", + "Read Raw and Write Raw are not supported" +}; +static const true_false_string tfs_server_cap_mpx_mode = { + "Read Mpx and Write Mpx are supported", + "Read Mpx and Write Mpx are not supported" +}; +static const true_false_string tfs_server_cap_unicode = { + "Unicode strings are supported", + "Unicode strings are not supported" +}; +static const true_false_string tfs_server_cap_large_files = { + "Large files are supported", + "Large files are not supported", +}; +static const true_false_string tfs_server_cap_nt_smbs = { + "NT SMBs are supported", + "NT SMBs are not supported" +}; +static const true_false_string tfs_server_cap_rpc_remote_apis = { + "RPC remote APIs are supported", + "RPC remote APIs are not supported" +}; +static const true_false_string tfs_server_cap_nt_status = { + "NT status codes are supported", + "NT status codes are not supported" +}; +static const true_false_string tfs_server_cap_level_ii_oplocks = { + "Level 2 oplocks are supported", + "Level 2 oplocks are not supported" +}; +static const true_false_string tfs_server_cap_lock_and_read = { + "Lock and Read is supported", + "Lock and Read is not supported" +}; +static const true_false_string tfs_server_cap_nt_find = { + "NT Find is supported", + "NT Find is not supported" +}; +static const true_false_string tfs_server_cap_dfs = { + "Dfs is supported", + "Dfs is not supported" +}; +static const true_false_string tfs_server_cap_infolevel_passthru = { + "NT information level request passthrough is supported", + "NT information level request passthrough is not supported" +}; +static const true_false_string tfs_server_cap_large_readx = { + "Large Read andX is supported", + "Large Read andX is not supported" +}; +static const true_false_string tfs_server_cap_large_writex = { + "Large Write andX is supported", + "Large Write andX is not supported" +}; +static const true_false_string tfs_server_cap_unix = { + "UNIX extensions are supported", + "UNIX extensions are not supported" +}; +static const true_false_string tfs_server_cap_reserved = { + "Reserved", + "Reserved" +}; +static const true_false_string tfs_server_cap_bulk_transfer = { + "Bulk Read and Bulk Write are supported", + "Bulk Read and Bulk Write are not supported" +}; +static const true_false_string tfs_server_cap_compressed_data = { + "Compressed data transfer is supported", + "Compressed data transfer is not supported" +}; +static const true_false_string tfs_server_cap_extended_security = { + "Extended security exchanges are supported", + "Extended security exchanges are not supported" +}; +static int +dissect_negprot_capabilities(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) +{ + guint32 mask; + proto_item *item = NULL; + proto_tree *tree = NULL; + + mask = tvb_get_letohl(tvb, offset); + + if(parent_tree){ + item = proto_tree_add_text(parent_tree, tvb, offset, 4, "Capabilities: 0x%08x", mask); + tree = proto_item_add_subtree(item, ett_smb_capabilities); + } + + proto_tree_add_boolean(tree, hf_smb_server_cap_raw_mode, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_mpx_mode, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_unicode, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_large_files, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_nt_smbs, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_rpc_remote_apis, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_nt_status, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_level_ii_oplocks, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_lock_and_read, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_nt_find, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_dfs, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_infolevel_passthru, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_large_readx, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_large_writex, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_unix, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_reserved, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_bulk_transfer, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_compressed_data, + tvb, offset, 4, mask); + proto_tree_add_boolean(tree, hf_smb_server_cap_extended_security, + tvb, offset, 4, mask); + + return mask; +} + +#define RAWMODE_READ 0x01 +#define RAWMODE_WRITE 0x02 +static const true_false_string tfs_rm_read = { + "Read Raw is supported", + "Read Raw is not supported" +}; +static const true_false_string tfs_rm_write = { + "Write Raw is supported", + "Write Raw is not supported" +}; + +static int +dissect_negprot_rawmode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) +{ + guint16 mask; + proto_item *item = NULL; + proto_tree *tree = NULL; + + mask = tvb_get_letohs(tvb, offset); + + if(parent_tree){ + item = proto_tree_add_text(parent_tree, tvb, offset, 2, "Raw Mode: 0x%04x", mask); + tree = proto_item_add_subtree(item, ett_smb_rawmode); + } + + proto_tree_add_boolean(tree, hf_smb_rm_read, tvb, offset, 2, mask); + proto_tree_add_boolean(tree, hf_smb_rm_write, tvb, offset, 2, mask); + + offset += 2; + + return offset; +} + +#define SECURITY_MODE_MODE 0x01 +#define SECURITY_MODE_PASSWORD 0x02 +#define SECURITY_MODE_SIGNATURES 0x04 +#define SECURITY_MODE_SIG_REQUIRED 0x08 +static const true_false_string tfs_sm_mode = { + "USER security mode", + "SHARE security mode" +}; +static const true_false_string tfs_sm_password = { + "ENCRYPTED password. Use challenge/response", + "PLAINTEXT password" +}; +static const true_false_string tfs_sm_signatures = { + "Security signatures ENABLED", + "Security signatures NOT enabled" +}; +static const true_false_string tfs_sm_sig_required = { + "Security signatures REQUIRED", + "Security signatures NOT required" +}; + +static int +dissect_negprot_security_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int wc) +{ + guint16 mask = 0; + proto_item *item = NULL; + proto_tree *tree = NULL; + + switch(wc){ + case 13: + mask = tvb_get_letohs(tvb, offset); + item = proto_tree_add_text(parent_tree, tvb, offset, 2, + "Security Mode: 0x%04x", mask); + tree = proto_item_add_subtree(item, ett_smb_mode); + proto_tree_add_boolean(tree, hf_smb_sm_mode16, tvb, offset, 2, mask); + proto_tree_add_boolean(tree, hf_smb_sm_password16, tvb, offset, 2, mask); + offset += 2; + break; + + case 17: + mask = tvb_get_guint8(tvb, offset); + item = proto_tree_add_text(parent_tree, tvb, offset, 1, + "Security Mode: 0x%02x", mask); + tree = proto_item_add_subtree(item, ett_smb_mode); + proto_tree_add_boolean(tree, hf_smb_sm_mode, tvb, offset, 1, mask); + proto_tree_add_boolean(tree, hf_smb_sm_password, tvb, offset, 1, mask); + proto_tree_add_boolean(tree, hf_smb_sm_signatures, tvb, offset, 1, mask); + proto_tree_add_boolean(tree, hf_smb_sm_sig_required, tvb, offset, 1, mask); + offset += 1; + break; + } + + return offset; +} + +static int +dissect_negprot_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) +{ + proto_item *it = NULL; + proto_tree *tr = NULL; + guint16 bc; + guint8 wc; + + WORD_COUNT; + + BYTE_COUNT; + + if(tree){ + it = proto_tree_add_text(tree, tvb, offset, bc, + "Requested Dialects"); + tr = proto_item_add_subtree(it, ett_smb_dialects); + } + + while(bc){ + int len; + int old_offset = offset; + const guint8 *str; + proto_item *dit = NULL; + proto_tree *dtr = NULL; + + len = tvb_strsize(tvb, offset+1); + str = tvb_get_ptr(tvb, offset+1, len); + + if(tr){ + dit = proto_tree_add_text(tr, tvb, offset, len+1, + "Dialect: %s", str); + dtr = proto_item_add_subtree(dit, ett_smb_dialect); + } + + /* Buffer Format */ + proto_tree_add_uint(dtr, hf_smb_buffer_format, tvb, offset, 1, + tvb_get_guint8(tvb, offset)); + offset += 1; + bc -= 1; + + /*Dialect Name */ + proto_tree_add_string(dtr, hf_smb_dialect_name, tvb, offset, + len, str); + offset += len; + bc -= len; + } + + END_OF_SMB + + return offset; +} + +static int +dissect_negprot_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) +{ + guint8 wc; + guint16 dialect; + const char *dn; + int dn_len; + guint16 bc; + guint16 ekl=0; + guint32 caps=0; + gint16 tz; + + + WORD_COUNT; + + /* Dialect Index */ + dialect = tvb_get_letohs(tvb, offset); + switch(wc){ + case 1: + if(dialect==0xffff){ + proto_tree_add_uint_format(tree, hf_smb_dialect_index, + tvb, offset, 2, dialect, + "Selected Index: -1, PC NETWORK PROGRAM 1.0 choosen"); + } else { + proto_tree_add_uint(tree, hf_smb_dialect_index, + tvb, offset, 2, dialect); + } + break; + case 13: + proto_tree_add_uint_format(tree, hf_smb_dialect_index, + tvb, offset, 2, dialect, + "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", dialect); + break; + case 17: + proto_tree_add_uint_format(tree, hf_smb_dialect_index, + tvb, offset, 2, dialect, + "Dialect Index: %u, greater than LANMAN2.1", dialect); + break; + default: + proto_tree_add_text(tree, tvb, offset, wc*2, + "Words for unknown response format"); + offset += wc*2; + goto bytecount; + } + offset += 2; + + switch(wc){ + case 13: + /* Security Mode */ + offset = dissect_negprot_security_mode(tvb, pinfo, tree, offset, + wc); + + /* Maximum Transmit Buffer Size */ + proto_tree_add_uint(tree, hf_smb_max_trans_buf_size, + tvb, offset, 2, tvb_get_letohs(tvb, offset)); + offset += 2; + + /* Maximum Multiplex Count */ + proto_tree_add_uint(tree, hf_smb_max_mpx_count, + tvb, offset, 2, tvb_get_letohs(tvb, offset)); + offset += 2; + + /* Maximum Vcs Number */ + proto_tree_add_uint(tree, hf_smb_max_vcs_num, + tvb, offset, 2, tvb_get_letohs(tvb, offset)); + offset += 2; + + /* raw mode */ + offset = dissect_negprot_rawmode(tvb, pinfo, tree, offset); + + /* session key */ + proto_tree_add_uint(tree, hf_smb_session_key, + tvb, offset, 4, tvb_get_letohl(tvb, offset)); + offset += 4; + + /* current time and date at server */ + offset = dissect_smb_timedate(tvb, pinfo, tree, offset, hf_smb_server_date_time, hf_smb_server_smb_date, hf_smb_server_smb_time); + + /* time zone */ + tz = tvb_get_letohs(tvb, offset); + proto_tree_add_int_format(tree, hf_smb_server_timezone, tvb, offset, 2, tz, "Server Time Zone: %d min from UTC", tz); + offset += 2; + + /* encryption key length */ + ekl = tvb_get_letohs(tvb, offset); + proto_tree_add_uint(tree, hf_smb_encryption_key_length, tvb, offset, 2, ekl); + offset += 2; + + /* 2 reserved bytes */ + proto_tree_add_bytes(tree, hf_smb_reserved, tvb, offset, 2, tvb_get_ptr(tvb, offset, 2)); + offset += 2; + + break; + + case 17: + /* Security Mode */ + offset = dissect_negprot_security_mode(tvb, pinfo, tree, offset, wc); + + /* Maximum Multiplex Count */ + proto_tree_add_uint(tree, hf_smb_max_mpx_count, + tvb, offset, 2, tvb_get_letohs(tvb, offset)); + offset += 2; + + /* Maximum Vcs Number */ + proto_tree_add_uint(tree, hf_smb_max_vcs_num, + tvb, offset, 2, tvb_get_letohs(tvb, offset)); + offset += 2; + + /* Maximum Transmit Buffer Size */ + proto_tree_add_uint(tree, hf_smb_max_trans_buf_size, + tvb, offset, 4, tvb_get_letohl(tvb, offset)); + offset += 4; + + /* maximum raw buffer size */ + proto_tree_add_uint(tree, hf_smb_max_raw_buf_size, + tvb, offset, 4, tvb_get_letohl(tvb, offset)); + offset += 4; + + /* session key */ + proto_tree_add_uint(tree, hf_smb_session_key, + tvb, offset, 4, tvb_get_letohl(tvb, offset)); + offset += 4; + + /* server capabilities */ + caps = dissect_negprot_capabilities(tvb, pinfo, tree, offset); + offset += 4; + + /* system time */ + offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset, + "System Time", hf_smb_system_time); + /* time zone */ + tz = tvb_get_letohs(tvb, offset); + proto_tree_add_int_format(tree, hf_smb_server_timezone, + tvb, offset, 2, tz, + "Server Time Zone: %d min from UTC", tz); + offset += 2; + + /* encryption key length */ + ekl = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(tree, hf_smb_encryption_key_length, + tvb, offset, 1, ekl); + offset += 1; + + break; + } + + BYTE_COUNT; + + switch(wc){ + case 13: + /* challange/ encryption key */ + if(ekl){ + proto_tree_add_bytes(tree, hf_smb_encryption_key, tvb, offset, ekl, tvb_get_ptr(tvb, offset, ekl)); + offset += ekl; + } + + /* is this string optional ? */ + if(tvb_reported_length_remaining(tvb, offset)>0){ + /* domain */ + dn = get_unicode_or_ascii_string_tvb(tvb, &offset, + pinfo, &dn_len, FALSE, FALSE); + proto_tree_add_string(tree, hf_smb_primary_domain, tvb, + offset, dn_len,dn); + offset += dn_len; + } + break; + + case 17: + if(!(caps&SERVER_CAP_EXTENDED_SECURITY)){ + smb_info_t *si; + + /* challange/ encryption key */ + if(ekl){ + proto_tree_add_bytes(tree, hf_smb_encryption_key, + tvb, offset, ekl, + tvb_get_ptr(tvb, offset, ekl)); + offset += ekl; + } + + if(tvb_reported_length_remaining(tvb, offset)){ + /* domain */ + /* this string is special, unicode is flagged in caps */ + /* This string is NOT padded to be 16bit aligned. (seen in actual capture) */ + si = pinfo->private_data; + si->unicode = (caps&SERVER_CAP_UNICODE); + dn = get_unicode_or_ascii_string_tvb(tvb, + &offset, pinfo, &dn_len, TRUE, FALSE); + proto_tree_add_string(tree, hf_smb_primary_domain, + tvb, offset, dn_len,dn); + offset += dn_len; + } + } else { + int len; + + /* guid */ + /* XXX - show it in the standard Microsoft format + for GUIDs? */ + proto_tree_add_bytes(tree, hf_smb_server_guid, + tvb, offset, 16, tvb_get_ptr(tvb, offset, 16)); + offset += 16; + + /* security blob */ + /* XXX - is this ASN.1-encoded? Is it a Kerberos + data structure, at least in NT 5.0-and-later + server replies? */ + len = tvb_reported_length_remaining(tvb, offset); + if(len){ + proto_tree_add_bytes(tree, hf_smb_security_blob, + tvb, offset, len, + tvb_get_ptr(tvb, offset, len)); + offset += len; + } + } + break; + + default: + proto_tree_add_text(tree, tvb, offset, bc, + "Bytes for unknown response format"); + offset += bc; + goto endofcommand; + } + + END_OF_SMB + + return offset; +} @@ -316,7 +984,7 @@ smb_function smb_dissector[256] = { /* 0x6f */ {NULL, NULL}, /* 0x70 */ {NULL, NULL}, /* 0x71 */ {NULL, NULL}, - /* 0x72 */ {NULL, NULL}, + /* 0x72 Negotiate Protocol*/ {dissect_negprot_request, dissect_negprot_response}, /* 0x73 */ {NULL, NULL}, /* 0x74 */ {NULL, NULL}, /* 0x75 */ {NULL, NULL}, @@ -474,8 +1142,9 @@ dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree, int int (*dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree); if (check_col(pinfo->fd, COL_INFO)) { - col_append_fstr(pinfo->fd, COL_INFO, "%s ", - decode_smb_name(cmd)); + col_add_fstr(pinfo->fd, COL_INFO, "%s %s ", + decode_smb_name(cmd), + (si->request)? "Request" : "Response"); } cmd_item = proto_tree_add_text(smb_tree, tvb, offset, @@ -621,7 +1290,7 @@ static const value_string smb_cmd_vals[] = { { 0x6F, "unknown-0x6F" }, { 0x70, "Tree Connect" }, { 0x71, "Tree Disconnect" }, - { 0x72, "Negotiate" }, + { 0x72, "Negotiate Protocol" }, { 0x73, "Session Setup AndX" }, { 0x74, "Logoff AndX" }, { 0x75, "Tree Connect AndX" }, @@ -1325,6 +1994,7 @@ unicode_to_str(const guint8 *us, int *us_lenp) { int us_len; int overflow = 0; + NullTVB; /* remove this function when we are fully tvbuffified */ if (cur == &str[0][0]) { cur = &str[1][0]; } else if (cur == &str[1][0]) { @@ -1354,6 +2024,60 @@ unicode_to_str(const guint8 *us, int *us_lenp) { *us_lenp = us_len; return cur; } +/* Turn a little-endian Unicode '\0'-terminated string into a string we + can display. + XXX - for now, we just handle the ISO 8859-1 characters. + If exactlen==TRUE then us_lenp contains the exact len of the string in + bytes. It might not be null terminated ! +*/ +static gchar * +unicode_to_str_tvb(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen) { + static gchar str[3][MAX_UNICODE_STR_LEN+3+1]; + static gchar *cur; + gchar *p; + guint16 uchar; + int len; + int us_len; + int overflow = 0; + + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + p = cur; + len = MAX_UNICODE_STR_LEN; + us_len = 0; + while ((uchar = tvb_get_letohs(tvb, offset)) != 0) { + if (len > 0) { + if ((uchar & 0xFF00) == 0) + *p++ = uchar; /* ISO 8859-1 */ + else + *p++ = '?'; /* not 8859-1 */ + len--; + } else + overflow = 1; + offset += 2; + us_len += 2; + if(exactlen){ + if(us_len>= *us_lenp){ + break; + } + } + } + if (overflow) { + /* Note that we're not showing the full string. */ + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + *p = '\0'; + *us_lenp = us_len; + return cur; +} + /* Get a null terminated string, which is Unicode if "is_unicode" is true and ASCII (OEM character set) otherwise. @@ -1366,6 +2090,7 @@ get_unicode_or_ascii_string(const u_char *pd, int *offsetp, int SMB_offset, const gchar *string; int string_len; + NullTVB; /* delete this function when we are fully tvbuffified */ if (is_unicode) { if ((offset - SMB_offset) % 2) { /* @@ -1387,14 +2112,48 @@ get_unicode_or_ascii_string(const u_char *pd, int *offsetp, int SMB_offset, return string; } -static const value_string buffer_format_vals[] = { - { 1, "Data block" }, - { 2, "Dialect" }, - { 3, "Pathname" }, - { 4, "ASCII" }, - { 5, "Variable block" }, - { 0, NULL } -}; +/* nopad == TRUE : Do not add any padding before this string + * exactlen == TRUE : len contains the exact len of the string in bytes. + */ +static const gchar * +get_unicode_or_ascii_string_tvb(tvbuff_t *tvb, int *offsetp, packet_info *pinfo, int *len, gboolean nopad, gboolean exactlen) +{ + int offset = *offsetp; + const gchar *string; + int string_len; + smb_info_t *si; + + si = pinfo->private_data; + if (si->unicode) { + if ((!nopad) && (*offsetp % 2)) { + /* + * XXX - this should be an offset relative to the beginning of the SMB, + * not an offset relative to the beginning of the frame; if the stuff + * before the SMB has an odd number of bytes, an offset relative to + * the beginning of the frame will give the wrong answer. + */ + (*offsetp)++; /* Looks like a pad byte there sometimes */ + } + if(exactlen){ + string_len = *len; + string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen); + } else { + string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen); + string_len += 2; + } + } else { + if(exactlen){ + string = tvb_get_ptr(tvb, *offsetp, *len); + string_len = *len; + } else { + string_len = tvb_strsize(tvb, *offsetp); + string = tvb_get_ptr(tvb, *offsetp, string_len); + } + } + *len = string_len; + return string; +} + /* * Each dissect routine is passed an offset to wct and works from there @@ -4040,563 +4799,6 @@ dissect_tcon_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree * } -void -dissect_negprot_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset) -{ - guint8 wct, enckeylen; - guint16 bcc, mode, rawmode, dialect; - guint32 caps; - proto_tree *dialects = NULL, *mode_tree, *caps_tree, *rawmode_tree; - proto_item *ti; - const char *str; - char *ustr; - int ustr_len; - - wct = pd[offset]; /* Should be 0, 1 or 13 or 17, I think */ - - if (!((wct == 0) && si.request) && !((wct == 1) && !si.request) && - !((wct == 13) && !si.request) && !((wct == 17) && !si.request)) { - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 1, "Invalid Negotiate Protocol format. WCT should be zero or 1 or 13 or 17 ..., not %u", wct); - - proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data"); - - return; - } - } - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %d", wct); - - } - - offset += 1; - - if (!si.request && wct == 0) { - - /* Build display for: Byte Count (BCC) */ - - bcc = GSHORT(pd, offset); - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc); - - } - - offset += 2; /* Skip Byte Count (BCC) */ - - return; - - } - - /* Now decode the various formats ... */ - - switch (wct) { - - case 0: /* A request */ - - bcc = GSHORT(pd, offset); - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc); - - } - - offset += 2; - - if (tree) { - - ti = proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Dialects"); - dialects = proto_item_add_subtree(ti, ett_smb_dialects); - - } - - while (IS_DATA_IN_FRAME(offset)) { - const char *str; - - if (tree) { - - proto_tree_add_text(dialects, NullTVB, offset, 1, "Dialect Marker: %d", pd[offset]); - - } - - offset += 1; - - str = pd + offset; - - if (tree) { - - proto_tree_add_text(dialects, NullTVB, offset, strlen(str)+1, "Dialect: %s", str); - - } - - offset += strlen(str) + 1; - - } - break; - - case 1: /* PC NETWORK PROGRAM 1.0 */ - - dialect = GSHORT(pd, offset); - - if (tree) { /* Hmmmm, what if none of the dialects is recognized */ - - if (dialect == 0xFFFF) { /* Server didn't like them dialects */ - - proto_tree_add_text(tree, NullTVB, offset, 2, "Supplied dialects not recognized"); - - } - else { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Dialect Index: %u, PC NETWORK PROTGRAM 1.0", dialect); - - } - - } - - offset += 2; - - bcc = GSHORT(pd, offset); - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc); - - } - - break; - - case 13: /* Greater than Core and up to and incl LANMAN2.1 */ - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", GSHORT(pd, offset)); - - } - - /* Much of this is similar to response 17 below */ - - offset += 2; - - mode = GSHORT(pd, offset); - - if (tree) { - - ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Security Mode: 0x%04x", mode); - mode_tree = proto_item_add_subtree(ti, ett_smb_mode); - proto_tree_add_text(mode_tree, NullTVB, offset, 2, "%s", - decode_boolean_bitfield(mode, 0x0001, 16, - "Security = User", - "Security = Share")); - proto_tree_add_text(mode_tree, NullTVB, offset, 2, "%s", - decode_boolean_bitfield(mode, 0x0002, 16, - "Passwords = Encrypted", - "Passwords = Plaintext")); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Max buffer size: %u", GSHORT(pd, offset)); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset)); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Max vcs: %u", GSHORT(pd, offset)); - - } - - offset += 2; - - rawmode = GSHORT(pd, offset); - - if (tree) { - - ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Raw Mode: 0x%04x", rawmode); - rawmode_tree = proto_item_add_subtree(ti, ett_smb_rawmode); - proto_tree_add_text(rawmode_tree, NullTVB, offset, 2, "%s", - decode_boolean_bitfield(rawmode, 0x01, 16, - "Read Raw supported", - "Read Raw not supported")); - proto_tree_add_text(rawmode_tree, NullTVB, offset, 2, "%s", - decode_boolean_bitfield(rawmode, 0x02, 16, - "Write Raw supported", - "Write Raw not supported")); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 4, "Session key: %08x", GWORD(pd, offset)); - - } - - offset += 4; - - /* Now the server time, two short parameters ... */ - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Server Time: %s", - dissect_dos_time(GSHORT(pd, offset))); - proto_tree_add_text(tree, NullTVB, offset + 2, 2, "Server Date: %s", - dissect_dos_date(GSHORT(pd, offset + 2))); - - } - - offset += 4; - - /* Server Time Zone, SHORT */ - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Server time zone: %i min from UTC", - (signed short)GSSHORT(pd, offset)); - - } - - offset += 2; - - /* Challenge Length */ - - enckeylen = GSHORT(pd, offset); - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Challenge Length: %u", enckeylen); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u (MBZ)", GSHORT(pd, offset)); - - } - - offset += 2; - - bcc = GSHORT(pd, offset); - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc); - - } - - offset += 2; - - if (enckeylen) { /* only if non-zero key len */ - - str = pd + offset; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, enckeylen, "Challenge: %s", - bytes_to_str(str, enckeylen)); - } - - offset += enckeylen; - - } - - /* Primary Domain ... */ - - str = pd + offset; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, strlen(str)+1, "Primary Domain: %s", str); - - } - - break; - - case 17: /* Greater than LANMAN2.1 */ - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Dialect Index: %u, Greater than LANMAN2.1", GSHORT(pd, offset)); - - } - - offset += 2; - - mode = GBYTE(pd, offset); - - if (tree) { - - ti = proto_tree_add_text(tree, NullTVB, offset, 1, "Security Mode: 0x%02x", mode); - mode_tree = proto_item_add_subtree(ti, ett_smb_mode); - proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s", - decode_boolean_bitfield(mode, 0x01, 8, - "Security = User", - "Security = Share")); - proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s", - decode_boolean_bitfield(mode, 0x02, 8, - "Passwords = Encrypted", - "Passwords = Plaintext")); - proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s", - decode_boolean_bitfield(mode, 0x04, 8, - "Security signatures enabled", - "Security signatures not enabled")); - proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s", - decode_boolean_bitfield(mode, 0x08, 8, - "Security signatures required", - "Security signatures not required")); - - } - - offset += 1; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset)); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Max vcs: %u", GSHORT(pd, offset)); - - } - - offset += 2; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Max buffer size: %u", GWORD(pd, offset)); - - } - - offset += 4; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 4, "Max raw size: %u", GWORD(pd, offset)); - - } - - offset += 4; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 4, "Session key: %08x", GWORD(pd, offset)); - - } - - offset += 4; - - caps = GWORD(pd, offset); - - if (tree) { - - ti = proto_tree_add_text(tree, NullTVB, offset, 4, "Capabilities: 0x%04x", caps); - caps_tree = proto_item_add_subtree(ti, ett_smb_capabilities); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0001, 32, - "Raw Mode supported", - "Raw Mode not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0002, 32, - "MPX Mode supported", - "MPX Mode not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0004, 32, - "Unicode supported", - "Unicode not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0008, 32, - "Large files supported", - "Large files not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0010, 32, - "NT LM 0.12 SMBs supported", - "NT LM 0.12 SMBs not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0020, 32, - "RPC remote APIs supported", - "RPC remote APIs not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0040, 32, - "NT status codes supported", - "NT status codes not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0080, 32, - "Level 2 OpLocks supported", - "Level 2 OpLocks not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0100, 32, - "Lock&Read supported", - "Lock&Read not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x0200, 32, - "NT Find supported", - "NT Find not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x1000, 32, - "DFS supported", - "DFS not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x4000, 32, - "Large READX supported", - "Large READX not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x8000, 32, - "Large WRITEX supported", - "Large WRITEX not supported")); - proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s", - decode_boolean_bitfield(caps, 0x80000000, 32, - "Extended security exchanges supported", - "Extended security exchanges not supported")); - } - - offset += 4; - - /* Server time, 2 WORDS */ - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 4, "System Time Low: 0x%08x", GWORD(pd, offset)); - proto_tree_add_text(tree, NullTVB, offset + 4, 4, "System Time High: 0x%08x", GWORD(pd, offset + 4)); - - } - - offset += 8; - - /* Server Time Zone, SHORT */ - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Server time zone: %i min from UTC", - (signed short)GSSHORT(pd, offset)); - - } - - offset += 2; - - /* Encryption key len */ - - enckeylen = pd[offset]; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 1, "Encryption key len: %u", enckeylen); - - } - - offset += 1; - - bcc = GSHORT(pd, offset); - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, 2, "Byte count (BCC): %u", bcc); - - } - - offset += 2; - - if (caps & 0x80000000) { - /* Extended security */ - - /* GUID */ - - if (tree) { - - /* XXX - show it in GUID form, with dashes or whatever */ - proto_tree_add_text(tree, NullTVB, offset, 16, "GUID: %s", - bytes_to_str(&pd[offset], 16)); - - } - - offset += 16; - - /* Security blob */ - /* XXX - is this ASN.1-encoded? Is it a Kerberos data structure, - at least in NT 5.0-and-later server replies? */ - - if (bcc > 16) { - bcc -= 16; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, bcc, "Security blob: %s", - bytes_to_str(&pd[offset], bcc)); - - } - } - } else { - /* Non-extended security */ - - if (enckeylen) { /* only if non-zero key len */ - - /* Encryption challenge key */ - - str = pd + offset; - - if (tree) { - - proto_tree_add_text(tree, NullTVB, offset, enckeylen, "Challenge encryption key: %s", - bytes_to_str(str, enckeylen)); - - } - - offset += enckeylen; - - } - - /* The domain, a null terminated string; Unicode if "caps" has - the 0x0004 bit set, ASCII (OEM character set) otherwise. - XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */ - - str = pd + offset; - - if (tree) { - - if (caps & 0x0004) { - ustr = unicode_to_str(str, &ustr_len); - proto_tree_add_text(tree, NullTVB, offset, ustr_len+2, "OEM domain name: %s", ustr); - } else { - proto_tree_add_text(tree, NullTVB, offset, strlen(str)+1, "OEM domain name: %s", str); - } - - } - } - - break; - - default: /* Baddd */ - - if (tree) - proto_tree_add_text(tree, NullTVB, offset, 1, "Bad format, should never get here"); - return; - - } - -} void dissect_deletedir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset) @@ -11601,7 +11803,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro dissect_unknown_smb, /* unknown SMB 0x6f */ dissect_treecon_smb, /* SMBtcon tree connect */ dissect_tdis_smb, /* SMBtdis tree disconnect */ - dissect_negprot_smb, /* SMBnegprot negotiate a protocol */ + dissect_unknown_smb, dissect_ssetup_andx_smb, /* SMBsesssetupX Session Set Up & X (including User Logon) */ dissect_logoff_andx_smb, /* SMBlogof Logoff & X */ dissect_tcon_andx_smb, /* SMBtconX tree connect and X */ @@ -12976,12 +13178,6 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) sip->mid); offset += 2; - - if (check_col(pinfo->fd, COL_INFO)) { - col_set_str(pinfo->fd, COL_INFO, - (sip->request)? "Request ":"Response "); - } - if(smb_dissector[sip->cmd].request){ /* call smb command dissector */ pinfo->private_data = sip; @@ -12992,8 +13188,9 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) tvb_compat(tvb, &pd, &SMB_offset); offset += SMB_offset; if (check_col(pinfo->fd, COL_INFO)) { - col_append_fstr(pinfo->fd, COL_INFO, "%s ", - decode_smb_name(sip->cmd)); + col_add_fstr(pinfo->fd, COL_INFO, "%s %s", + decode_smb_name(sip->cmd), + (sip->request)? "Request" : "Response"); } (dissect[sip->cmd])(pd, offset, pinfo->fd, parent_tree, tree, si, tvb_length(tvb), SMB_offset); @@ -13024,6 +13221,14 @@ proto_register_smb(void) { "SMB Command", "smb.cmd", FT_UINT8, BASE_HEX, VALS(smb_cmd_vals), 0x0, "SMB Command", HFILL }}, + { &hf_smb_word_count, + { "Word Count (WCT)", "smb.wct", FT_UINT8, BASE_DEC, + NULL, 0x0, "Word Count, count of parameter words", HFILL }}, + + { &hf_smb_byte_count, + { "Byte Count (BCC)", "smb.bcc", FT_UINT16, BASE_DEC, + NULL, 0x0, "Byte Count, count of data bytes", HFILL }}, + { &hf_smb_response_to, { "Response to", "smb.response_to", FT_UINT32, BASE_DEC, NULL, 0, "This packet is a response to the packet in this frame", HFILL }}, @@ -13118,12 +13323,196 @@ proto_register_smb(void) { &hf_smb_flags2_nt_error, { "", "smb.flags2.error", FT_BOOLEAN, 16, - TFS(&tfs_smb_flags2_nt_error), 0x4000, "Are errorcodes NT or DOS format?", HFILL }}, + TFS(&tfs_smb_flags2_nt_error), 0x4000, "Are error codes NT or DOS format?", HFILL }}, { &hf_smb_flags2_string, { "", "smb.flags2.string", FT_BOOLEAN, 16, TFS(&tfs_smb_flags2_string), 0x8000, "Are strings ASCII or UNICODE?", HFILL }}, + { &hf_smb_buffer_format, + { "Buffer Format", "smb.buffer_format", FT_UINT8, BASE_DEC, + VALS(buffer_format_vals), 0x0, "Buffer Format, type of buffer", HFILL }}, + + { &hf_smb_dialect_name, + { "Name", "smb.dialect.name", FT_STRING, BASE_NONE, + NULL, 0, "Name of dialect", HFILL }}, + + { &hf_smb_dialect_index, + { "Selected Index", "smb.dialect.index", FT_UINT16, BASE_DEC, + NULL, 0, "Index of selected dialect", HFILL }}, + + { &hf_smb_max_trans_buf_size, + { "Max Buffer Size", "smb.max_bufsize", FT_UINT32, BASE_DEC, + NULL, 0, "Maximum transmit buffer size", HFILL }}, + + { &hf_smb_max_mpx_count, + { "Max Mpx Count", "smb.max_mpx_count", FT_UINT16, BASE_DEC, + NULL, 0, "Maximum pending multiplexed requests", HFILL }}, + + { &hf_smb_max_vcs_num, + { "Max VCs", "smb.max_vcs", FT_UINT16, BASE_DEC, + NULL, 0, "Maximum VCs between client and server", HFILL }}, + + { &hf_smb_session_key, + { "Session Key", "smb.session_key", FT_UINT32, BASE_HEX, + NULL, 0, "Unique token identifying this session", HFILL }}, + + { &hf_smb_server_timezone, + { "Time Zone", "smb.server.timezone", FT_INT16, BASE_DEC, + NULL, 0, "Current timezone at server.", HFILL }}, + + { &hf_smb_encryption_key_length, + { "Key Length", "smb.encryption_key_length", FT_UINT16, BASE_DEC, + NULL, 0, "Encryption key length (must be 0 if not LM2.1 dialect)", HFILL }}, + + { &hf_smb_encryption_key, + { "Encryption Key", "smb.encryption_key", FT_BYTES, BASE_HEX, + NULL, 0, "Challenge/Response Encryption Key (for LM2.1 dialect)", HFILL }}, + + { &hf_smb_primary_domain, + { "Primary Domain", "smb.primary_domain", FT_STRING, BASE_NONE, + NULL, 0, "The server's primary domain", HFILL }}, + + { &hf_smb_max_raw_buf_size, + { "Max Raw Buffer", "smb.max_raw", FT_UINT32, BASE_DEC, + NULL, 0, "Maximum raw buffer size", HFILL }}, + + { &hf_smb_server_guid, + { "Server GUID", "smb.server.guid", FT_BYTES, BASE_HEX, + NULL, 0, "Globally unique identifier for this server", HFILL }}, + + { &hf_smb_security_blob, + { "Security Blob", "smb.security.blob", FT_BYTES, BASE_HEX, + NULL, 0, "Security blob", HFILL }}, + + { &hf_smb_sm_mode16, + { "Mode", "smb.sm.mode", FT_BOOLEAN, 16, + TFS(&tfs_sm_mode), SECURITY_MODE_MODE, "User or Share security mode?", HFILL }}, + + { &hf_smb_sm_password16, + { "Password", "smb.sm.password", FT_BOOLEAN, 16, + TFS(&tfs_sm_password), SECURITY_MODE_PASSWORD, "Encrypted or plaintext passwords?", HFILL }}, + + { &hf_smb_sm_mode, + { "Mode", "smb.sm.mode", FT_BOOLEAN, 8, + TFS(&tfs_sm_mode), SECURITY_MODE_MODE, "User or Share security mode?", HFILL }}, + + { &hf_smb_sm_password, + { "Password", "smb.sm.password", FT_BOOLEAN, 8, + TFS(&tfs_sm_password), SECURITY_MODE_PASSWORD, "Encrypted or plaintext passwords?", HFILL }}, + + { &hf_smb_sm_signatures, + { "Signatures", "smb.sm.signatures", FT_BOOLEAN, 8, + TFS(&tfs_sm_signatures), SECURITY_MODE_SIGNATURES, "Are security signatures enabled?", HFILL }}, + + { &hf_smb_sm_sig_required, + { "Sig Req", "smb.sm.sig_required", FT_BOOLEAN, 8, + TFS(&tfs_sm_sig_required), SECURITY_MODE_SIG_REQUIRED, "Are security signatures required?", HFILL }}, + + { &hf_smb_rm_read, + { "Read Raw", "smb.rm.read", FT_BOOLEAN, 16, + TFS(&tfs_rm_read), RAWMODE_READ, "Is Read Raw supported?", HFILL }}, + + { &hf_smb_rm_write, + { "Write Raw", "smb.rm.write", FT_BOOLEAN, 16, + TFS(&tfs_rm_write), RAWMODE_WRITE, "Is Write Raw supported?", HFILL }}, + + { &hf_smb_server_date_time, + { "Server Date and Time", "smb.server_date_time", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Current date and time at server", HFILL }}, + + { &hf_smb_server_smb_date, + { "Server Date", "smb.server_date_time.smb_date", FT_UINT16, BASE_HEX, + NULL, 0, "Current date at server, SMB_DATE format", HFILL }}, + + { &hf_smb_server_smb_time, + { "Server Time", "smb.server_date_time.smb_time", FT_UINT16, BASE_HEX, + NULL, 0, "Current time at server, SMB_TIME format", HFILL }}, + + { &hf_smb_server_cap_raw_mode, + { "Raw Mode", "smb.server.cap.raw_mode", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_raw_mode), SERVER_CAP_RAW_MODE, "Are Raw Read and Raw Write supported?", HFILL }}, + + { &hf_smb_server_cap_mpx_mode, + { "MPX Mode", "smb.server.cap.mpx_mode", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_mpx_mode), SERVER_CAP_MPX_MODE, "Are Read Mpx and Write Mpx supported?", HFILL }}, + + { &hf_smb_server_cap_unicode, + { "Unicode", "smb.server.cap.unicode", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_unicode), SERVER_CAP_UNICODE, "Are Unicode strings supported?", HFILL }}, + + { &hf_smb_server_cap_large_files, + { "Large Files", "smb.server.cap.large_files", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_large_files), SERVER_CAP_LARGE_FILES, "Are large files (>4GB) supported?", HFILL }}, + + { &hf_smb_server_cap_nt_smbs, + { "NT SMBs", "smb.server.cap.nt_smbs", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_nt_smbs), SERVER_CAP_NT_SMBS, "Are NT SMBs supported?", HFILL }}, + + { &hf_smb_server_cap_rpc_remote_apis, + { "RPC Remote APIs", "smb.server.cap.rpc_remote_apis", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_rpc_remote_apis), SERVER_CAP_RPC_REMOTE_APIS, "Are RPC Remote APIs supported?", HFILL }}, + + { &hf_smb_server_cap_nt_status, + { "NT Status Codes", "smb.server.cap.nt_status", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_nt_status), SERVER_CAP_STATUS32, "Are NT Status Codes supported?", HFILL }}, + + { &hf_smb_server_cap_level_ii_oplocks, + { "Level 2 Oplocks", "smb.server.cap.level_2_oplocks", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_level_ii_oplocks), SERVER_CAP_LEVEL_II_OPLOCKS, "Are Level 2 oplocks supported?", HFILL }}, + + { &hf_smb_server_cap_lock_and_read, + { "Lock and Read", "smb.server.cap.lock_and_read", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_lock_and_read), SERVER_CAP_LOCK_AND_READ, "Is Lock and Read supported?", HFILL }}, + + { &hf_smb_server_cap_nt_find, + { "NT Find", "smb.server.cap.nt_find", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_nt_find), SERVER_CAP_NT_FIND, "Is NT Find supported?", HFILL }}, + + { &hf_smb_server_cap_dfs, + { "Dfs", "smb.server.cap.dfs", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_dfs), SERVER_CAP_DFS, "Is Dfs supported?", HFILL }}, + + { &hf_smb_server_cap_infolevel_passthru, + { "Infolevel Passthru", "smb.server.cap.infolevel_passthru", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_infolevel_passthru), SERVER_CAP_INFOLEVEL_PASSTHRU, "Is NT information level request passthrough supported?", HFILL }}, + + { &hf_smb_server_cap_large_readx, + { "Large ReadX", "smb.server.cap.large_readx", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_large_readx), SERVER_CAP_LARGE_READX, "Is Large Read andX supported?", HFILL }}, + + { &hf_smb_server_cap_large_writex, + { "Large WriteX", "smb.server.cap.large_writex", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_large_writex), SERVER_CAP_LARGE_WRITEX, "Is Large Write andX supported?", HFILL }}, + + { &hf_smb_server_cap_unix, + { "UNIX", "smb.server.cap.unix", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_unix), SERVER_CAP_UNIX , "Are UNIX extensions supported?", HFILL }}, + + { &hf_smb_server_cap_reserved, + { "Reserved", "smb.server.cap.reserved", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_reserved), SERVER_CAP_RESERVED, "RESERVED", HFILL }}, + + { &hf_smb_server_cap_bulk_transfer, + { "Bulk Transfer", "smb.server.cap.bulk_transfer", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_bulk_transfer), SERVER_CAP_BULK_TRANSFER, "Are Bulk Read and Bulk Write supported?", HFILL }}, + + { &hf_smb_server_cap_compressed_data, + { "Compressed Data", "smb.server.cap.compressed_data", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_compressed_data), SERVER_CAP_COMPRESSED_DATA, "Is compressed data transfer supported?", HFILL }}, + + { &hf_smb_server_cap_extended_security, + { "Extended Security", "smb.server.cap.extended_security", FT_BOOLEAN, 32, + TFS(&tfs_server_cap_extended_security), SERVER_CAP_EXTENDED_SECURITY, "Are Extended security exchanges supported?", HFILL }}, + + { &hf_smb_system_time, + { "System Time", "smb.system.time", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "System Time", HFILL }}, + + { &hf_smb_unknown, + { "Unknown Data", "smb.unknown", FT_BYTES, BASE_HEX, + NULL, 0, "Unknown Data. Should be implemented by someone", HFILL }}, + }; static gint *ett[] = { @@ -13133,6 +13522,7 @@ proto_register_smb(void) &ett_smb_fileattributes, &ett_smb_capabilities, &ett_smb_aflags, + &ett_smb_dialect, &ett_smb_dialects, &ett_smb_mode, &ett_smb_rawmode, @@ -13148,6 +13538,8 @@ proto_register_smb(void) &ett_smb_lock_type, &ett_smb_ssetupandxaction, &ett_smb_optionsup, + &ett_smb_time_date, + &ett_smb_64bit_time, }; proto_smb = proto_register_protocol("SMB (Server Message Block Protocol)", |