aboutsummaryrefslogtreecommitdiffstats
path: root/packet-smb-pipe.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-08-05 01:15:27 +0000
committerGuy Harris <guy@alum.mit.edu>2001-08-05 01:15:27 +0000
commitd2b01e812b82b4640389ddb31fe5176abe92f19a (patch)
treefd8cfcd25f6e04dde725229fee4cbd78dfa52d29 /packet-smb-pipe.c
parentd271509c7e5c18fce2f700cf52b570717046126d (diff)
Remote API protocol (that seems to be what it's called in a number of
places) dissector tvbuffified, from Ronnie Sahlberg and me. Additional "are we past the end of the buffer" checks added, so that we don't hand random junk to the transaction and transact2 dissectors. svn path=/trunk/; revision=3824
Diffstat (limited to 'packet-smb-pipe.c')
-rw-r--r--packet-smb-pipe.c2383
1 files changed, 1514 insertions, 869 deletions
diff --git a/packet-smb-pipe.c b/packet-smb-pipe.c
index 73cda9f84b..542d9b8a8d 100644
--- a/packet-smb-pipe.c
+++ b/packet-smb-pipe.c
@@ -1,11 +1,18 @@
+/*
+XXX Fixme : continuation stuff removed, should be solved by smb reassembly
+XXX Fixme : shouldnt show [malformed frame] for long packets
+*/
+
/* packet-smb-pipe.c
* Routines for SMB named pipe packet dissection
* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ * significant rewrite to tvbuffify the dissector, Ronnie Sahlberg and
+ * Guy Harris 2001
*
- * $Id: packet-smb-pipe.c,v 1.23 2001/08/05 00:16:36 guy Exp $
+ * $Id: packet-smb-pipe.c,v 1.24 2001/08/05 01:15:26 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from packet-pop.c
@@ -46,18 +53,88 @@
#include "packet.h"
#include "conversation.h"
#include "smb.h"
-#include "alignment.h"
-#include "strutil.h"
#include "packet-smb-pipe.h"
+#include "packet-smb-browse.h"
static int proto_smb_lanman = -1;
+static int hf_function_code = -1;
+static int hf_param_desc = -1;
+static int hf_return_desc = -1;
+static int hf_not_implemented = -1;
+static int hf_detail_level = -1;
+static int hf_recv_buf_len = -1;
+static int hf_response_to = -1;
+static int hf_status = -1;
+static int hf_convert = -1;
+static int hf_ecount = -1;
+static int hf_acount = -1;
+static int hf_share_name = -1;
+static int hf_share_type = -1;
+static int hf_share_comment = -1;
+static int hf_share_permissions = -1;
+static int hf_share_max_uses = -1;
+static int hf_share_current_uses = -1;
+static int hf_server_name = -1;
+static int hf_server_major = -1;
+static int hf_server_minor = -1;
+static int hf_server_comment = -1;
+static int hf_abytes = -1;
+static int hf_current_time = -1;
+static int hf_msecs = -1;
+static int hf_hour = -1;
+static int hf_minute = -1;
+static int hf_second = -1;
+static int hf_hundredths = -1;
+static int hf_tzoffset = -1;
+static int hf_timeinterval = -1;
+static int hf_day = -1;
+static int hf_month = -1;
+static int hf_year = -1;
+static int hf_weekday = -1;
+static int hf_computer_name = -1;
+static int hf_user_name = -1;
+static int hf_workstation_domain = -1;
+static int hf_workstation_major = -1;
+static int hf_workstation_minor = -1;
+static int hf_logon_domain = -1;
+static int hf_other_domains = -1;
+static int hf_password = -1;
+static int hf_workstation_name = -1;
+static int hf_ustruct_size = -1;
+static int hf_logon_code = -1;
+static int hf_privilege_level = -1;
+static int hf_operator_privileges = -1;
+static int hf_num_logons = -1;
+static int hf_bad_pw_count = -1;
+static int hf_last_logon = -1;
+static int hf_last_logoff = -1;
+static int hf_logoff_time = -1;
+static int hf_kickoff_time = -1;
+static int hf_password_age = -1;
+static int hf_password_can_change = -1;
+static int hf_password_must_change = -1;
+static int hf_script_path = -1;
+static int hf_logoff_code = -1;
+static int hf_duration = -1;
+static int hf_user_comment = -1;
+static int hf_full_name = -1;
+static int hf_homedir = -1;
+static int hf_parameters = -1;
+static int hf_logon_server = -1;
+static int hf_country_code = -1;
+static int hf_workstations = -1;
+static int hf_max_storage = -1;
+static int hf_units_per_week = -1;
+static int hf_logon_hours = -1;
+static int hf_code_page = -1;
+static int hf_new_password = -1;
+static int hf_old_password = -1;
static gint ett_lanman = -1;
static gint ett_lanman_servers = -1;
static gint ett_lanman_server = -1;
static gint ett_lanman_shares = -1;
static gint ett_lanman_share = -1;
-static gint ett_lanman_flags = -1;
/*
* See
@@ -67,1120 +144,1689 @@ static gint ett_lanman_flags = -1;
* among other documents.
*/
-/*
- * The following data structure describes the LANMAN requests we understand
- *
- * Simply fill in the number, name, and parameter names if you know them
- * Try to keep them in order
- *
- * We will extend this data structure as we try to decode more ...
- */
-
-struct lanman_desc {
- int lanman_num;
- char *lanman_name;
- char **req;
- char **req_data; /* Hmmm, not flexible enough */
- char **resp;
- char **resp_data;
+static const value_string status_vals[] = {
+ {0, "Success"},
+ {5, "User has insufficient privilege"},
+ {65, "Network access is denied"},
+ {86, "The specified password is invalid"},
+ {SMBE_moredata, "Additional data is available"},
+ {2114, "Service is not running on the remote computer"},
+ {2123, "Supplied buffer is too small"},
+ {2141, "Server is not configured for transactions (IPC$ not shared)"},
+ {2212, "An error occurred while loading or running the logon script"},
+ {2214, "The logon was not validated by any server"},
+ {2217, "The logon server is running an older software version"},
+ {2221, "The user name was not found"},
+ {2240, "The user is not allowed to logon from this computer"},
+ {2241, "The user is not allowed to logon at this time"},
+ {2242, "The user password has expired"},
+ {2243, "The password cannot be changed"},
+ {2246, "The password is too short"},
+ {0, NULL}
};
-static char *lm_params_req_0[] = {"Detail Level", "Return Buffer Size", NULL};
-static char *lm_params_req_1[] = {"Share Name", "Detail Level", "Receive Buffer Size", NULL};
-static char *lm_params_resp_1[] = {"Returned Data Len", NULL};
-static char *lm_params_req_13[] = {"Detail Level", "Receive Buffer Size", NULL};
-static char *lm_params_req_56[] = {"User Name", "Detail Level", "Receive Buffer Size", NULL};
-static char *lm_params_req_104[] = {"Detail Level", "Return Buffer Size", "Server Type", "Domain", NULL};
-static char *lm_params_req_132[] = {"Reserved1", "Reserved2", "Detail Level", "UserInfoStruct?", "Length of UStruct", "Receive Buffer Size", NULL};
-static char *lm_params_req_133[] = {"Reserved1", "Reserved2", "Detail Level", "UserInfoStruct?", "Length of UStruct", "Receive Buffer Size", NULL};
-
-static char *lm_null_params[] = {NULL};
-
-struct lanman_desc lmd[] = {
- {0, "NetShareEnum", lm_params_req_0, lm_null_params, lm_null_params, lm_null_params},
- {1, "NetShareGetInfo", lm_params_req_1, lm_null_params, lm_params_resp_1, lm_null_params},
- {13, "NetServerGetInfo", lm_params_req_13, lm_null_params, lm_null_params, lm_null_params},
- {52, "NetGroupGetUsers", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {56, "NetUserGetInfo", lm_params_req_56, lm_null_params, lm_null_params, lm_null_params},
- {59, "NetUserGetGroups", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {63, "NetWkstaGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {69, "DOSPrintQEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {70, "DOSPrintQGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {74, "WPrintQueuePause", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {75, "WPrintQueueResume", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {76, "WPrintJobEnumerate", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {77, "WPrintJobGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {81, "RDOSPrintJobDel", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {82, "RDOSPrintJobPause", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {83, "RDOSPrintJobResume", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {84, "WPrintDestEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {85, "WPrintDestGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {91, "NetRemoteTOD", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {103, "WPrintQueuePurge", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {104, "NetServerEnum2", lm_params_req_104, lm_null_params, lm_null_params, lm_null_params},
- {105, "WAccessGetUserPerms", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {115, "SetUserPassword", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {132, "NetWkstaUserLogon", lm_params_req_132, lm_null_params, lm_null_params, lm_null_params},
- {133, "NetWkstaUserLogoff", lm_params_req_133, lm_null_params, lm_null_params, lm_null_params},
- {147, "PrintJobInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {205, "WPrintDriverEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {206, "WPrintQProcEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {207, "WPrintPortEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {214, "SamOEMChangePassword", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {-1, NULL, NULL,NULL, NULL, NULL}
+static const value_string share_type_vals[] = {
+ {0, "Directory tree"},
+ {1, "Printer queue"},
+ {2, "Communications device"},
+ {3, "IPC"},
+ {0, NULL}
};
-static struct lanman_desc *
-find_lanman(int lanman_num)
-{
- int i = 0;
-
- /* FIXME, This could be more efficient */
-
- while (lmd[i].lanman_num != -1) {
-
- if (lmd[i].lanman_num == lanman_num) {
-
- return &lmd[i];
-
- }
-
- i++;
-
- }
-
- return NULL;
-
-}
+static const value_string privilege_vals[] = {
+ {0, "Guest"},
+ {1, "User"},
+ {2, "Administrator"},
+ {0, NULL}
+};
+static const value_string op_privilege_vals[] = {
+ {0, "Print operator"},
+ {1, "Communications operator"},
+ {2, "Server operator"},
+ {3, "Accounts operator"},
+ {0, NULL}
+};
-#define NETSHAREENUM 0x00 /* 00 */
-#define NETSERVERENUM2 0x68 /* 104 */
+static const value_string weekday_vals[] = {
+ {0, "Sunday"},
+ {1, "Monday"},
+ {2, "Tuesday"},
+ {3, "Wednesday"},
+ {4, "Thursday"},
+ {5, "Friday"},
+ {6, "Saturday"},
+ {0, NULL}
+};
-static void
-dissect_server_flags(proto_tree *tree, int offset, int length, int flags)
+static int
+not_implemented(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
{
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0001, length*8, "Workstation", "Not Workstation"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0002, length*8, "Server", "Not Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0004, length*8, "SQL Server", "Not SQL Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0008, length*8, "Domain Controller", "Not Domain Controller"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0010, length*8, "Backup Controller", "Not Backup Controller"));
- proto_tree_add_text(tree, NullTVB, offset, 4, "%s",
- decode_boolean_bitfield(flags, 0x0020, length*8, "Time Source", "Not Time Source"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0040, length*8, "Apple Server", "Not Apple Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0080, length*8, "Novell Server", "Not Novell Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0100, length*8, "Domain Member Server", "Not Domain Member Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0200, length*8, "Print Queue Server", "Not Print Queue Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0400, length*8, "Dialin Server", "Not Dialin Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0800, length*8, "Xenix Server", "Not Xenix Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x1000, length*8, "NT Workstation", "Not NT Workstation"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x2000, length*8, "Windows for Workgroups", "Not Windows for Workgroups"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x8000, length*8, "NT Server", "Not NT Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x10000, length*8, "Potential Browser", "Not Potential Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x20000, length*8, "Backup Browser", "Not Backup Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x40000, length*8, "Master Browser", "Not Master Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x80000, length*8, "Domain Master Browser", "Not Domain Master Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x100000, length*8, "OSF", "Not OSF"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x200000, length*8, "VMS", "Not VMS"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x400000, length*8, "Windows 95 or above", "Not Windows 95 or above"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x40000000, length*8, "Local List Only", "Not Local List Only"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x80000000, length*8, "Domain Enum", "Not Domain Enum"));
+ proto_tree_add_item(tree, hf_not_implemented, tvb, offset, tvb_length_remaining(tvb, offset), TRUE);
+ return offset+tvb_length_remaining(tvb,offset);
}
-
-
-static char *p_desc = NULL, *d_desc = NULL, *data = NULL, *params = NULL;
-static int p_count, d_count, p_offset, d_offset, d_current = 0, p_current = 0;
-static int pd_p_current = 0, pd_d_current = 0, in_params = 0, need_data = 0;
-static int lm_ent_count = 0, lm_act_count = 0;
-
-/* Initialize the various data structure */
-static void
-dissect_transact_engine_init(const u_char *pd, const char *param_desc,
- const char *data_desc, int SMB_offset, int ParameterOffset,
- int ParameterCount, int DataOffset, int DataCount)
+static int
+add_string_pointer(tvbuff_t *tvb, proto_tree *tree, int offset, int convert,
+ int hf_index)
{
+ int cptr;
+ gint string_len;
+
+ /* pointer to string */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+
+ /* string */
+ if (tvb_offset_exists(tvb, cptr) &&
+ (string_len = tvb_strnlen(tvb, cptr, -1)) != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, cptr,
+ string_len + 1, TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <String goes past end of frame>",
+ proto_registrar_get_name(hf_index));
+ }
- d_count = DataCount;
- p_count = ParameterCount;
- d_offset = 0;
- p_offset = 0;
- d_current = 0;
- p_current = 0;
- lm_ent_count = lm_act_count = 0;
- pd_d_current = DataOffset;
- pd_p_current = ParameterOffset;
- in_params = need_data = 0;
-
- if (p_desc) g_free(p_desc);
- p_desc = g_malloc(strlen(param_desc) + 1);
- strcpy(p_desc, param_desc);
-
- if (d_desc) g_free(d_desc);
- d_desc= g_malloc(strlen(data_desc) + 1);
- strcpy(d_desc, data_desc);
-
- if (params) g_free(params);
- params = g_malloc(p_count);
- memcpy(params, pd + ParameterOffset, ParameterCount);
-
- if (data) g_free(data);
- data = g_malloc(d_count);
- memcpy(data, pd + DataOffset, DataCount);
-
+ return offset;
}
-int get_ent_count()
+static int
+add_byte_array_pointer(tvbuff_t *tvb, proto_tree *tree, int offset, int len,
+ int convert, int hf_index)
{
+ int cptr;
- return lm_ent_count;
+ /* pointer to string */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+ /* string */
+ proto_tree_add_item(tree, hf_index, tvb, cptr, len, TRUE);
+
+ return offset;
}
-int get_act_count()
+/*
+ * Sigh. This is for handling Microsoft's annoying almost-UNIX-time-but-
+ * it's-local-time-not-UTC time.
+ */
+static time_t
+localtime_to_utc(time_t local)
{
-
- return lm_act_count;
-
+ struct tm *tmp;
+
+ /*
+ * Run it through "gmtime()" to break it down, and then run it
+ * through "mktime()" to put it back together as UTC.
+ */
+ tmp = gmtime(&local);
+ tmp->tm_isdst = -1; /* we don't know if it's DST or not */
+ return mktime(tmp);
}
-static int get_byte_count(const u_char *p_data)
-
+static int
+netshareenum_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
{
- int count = 0, off = 0;
-
- while (p_data[off] && isdigit(p_data[off])) {
-
- count = (count * 10) + (int)p_data[off++] - (int)'0';
+ /* detail level */
+ proto_tree_add_item(tree, hf_detail_level, tvb, offset, 2, TRUE);
+ offset += 2;
- }
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- return count;
+ return offset;
}
-
-/* Dissect the next item, if Name is null, call it by its data type */
-/* We pull out the next item in the appropriate place and display it */
-/* We display the parameters first, then the data, then any auxilliary data */
-
static int
-dissect_transact_next(const u_char *pd, char *Name, gboolean request, proto_tree *tree)
+netshareenum_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
{
- /* guint8 BParam; */
- guint16 WParam = 0;
- guint32 LParam = 0;
- const char /**Bytes,*/ *AsciiZ = NULL;
- int bc;
-
- while (1) {
-
- if (p_desc[p_offset] == 0) return 0; /* No more ... */
-
- switch (in_params) {
-
- case 0: /* We are in the params area ... */
-
- switch (p_desc[p_offset++]) {
-
- case 'r':
-
- if (!request) { /* We need to process the data ... */
-
- need_data = 1;
-
- }
-
- break;
-
- case 'h': /* A WORD parameter received */
-
- if (!request) {
+ struct smb_info *smb_info = pinfo->private;
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ guint16 acount, ecount;
+ int i;
- WParam = GSHORT(pd, pd_p_current);
+ /* entry count */
+ ecount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2, ecount);
+ offset += 2;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (%04X)", (Name) ? Name : "Returned Word", WParam, WParam);
+ /* available count */
+ acount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_acount, tvb, offset, 2, acount);
+ offset += 2;
- pd_p_current += 2;
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
- lm_act_count = WParam;
-
- return 1;
-
- }
-
- break;
-
- case 'e': /* An ent count .. */
-
- if (!request) { /* Only relevant in a response */
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: (%04X)", (Name) ? Name : "Entry Count", WParam);
-
- pd_p_current += 2;
-
- lm_ent_count = WParam; /* Save this for later retrieval */
-
- return 1;
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
+ /* create a subtree for all available shares */
+ if (tree) {
+ it = proto_tree_add_text(tree, tvb, offset,
+ tvb_length_remaining(tvb, offset),
+ "Available Shares");
+ tr = proto_item_add_subtree(it, ett_lanman_shares);
}
- break;
+ for (i = 0; i < ecount; i++){
+ proto_item *si = NULL;
+ proto_tree *st = NULL;
+ char *share;
+ int start_offset = offset;
- case 'W': /* Word Parameter */
+ share = (char *)tvb_get_ptr(tvb, offset, 13);
- if (request) { /* A request ... */
-
- /* Insert a word param */
+ if (tree) {
+ si = proto_tree_add_text(tr, tvb, offset,
+ tvb_length_remaining(tvb, offset),
+ "Share %s", share);
+ st = proto_item_add_subtree(si, ett_lanman_shares);
+ }
- WParam = GSHORT(pd, pd_p_current);
+ /* share name */
+ proto_tree_add_item(st, hf_share_name, tvb, offset, 13, TRUE);
+ offset += 13;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (%04X)", (Name) ? Name : "Word Param", WParam, WParam);
+ /* pad byte */
+ offset += 1;
- pd_p_current += 2;
+ /* share type */
+ proto_tree_add_item(st, hf_share_type, tvb, offset, 2, TRUE);
+ offset += 2;
- return 1; /* That's it here ... we have dissected a param */
+ /* share comment */
+ offset = add_string_pointer(tvb, st, offset, convert,
+ hf_share_comment);
+ proto_item_set_len(si, offset-start_offset);
}
- break;
-
- case 'i': /* A long word is returned */
-
- if (!request) {
-
- LParam = GWORD(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u (0x%08X)", (Name) ? Name : "Returned Long Word", LParam, LParam);
-
- pd_p_current += 2;
+ return offset;
+}
- return 1;
+static int
+netsharegetinfo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ guint share_name_len;
+ guint16 level;
+
+ /* share name */
+ share_name_len = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_share_name, tvb, offset, share_name_len,
+ TRUE);
+ offset += share_name_len;
+
+ /* detail level */
+ level = tvb_get_letohs(tvb, offset);
+ request_val->last_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, level);
+ offset += 2;
+
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ return offset;
+}
+static int
+netsharegetinfo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 abytes;
+ guint16 permissions;
+ guint16 max_uses;
+
+ /* available bytes */
+ abytes = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_abytes, tvb, offset, 2, abytes);
+ offset += 2;
+
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
+
+ /* XXX - what is this field? */
+ proto_tree_add_text(tree, tvb, offset, 2, "Mysterious field: %04x",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
+
+ /* share name */
+ proto_tree_add_item(tree, hf_share_name, tvb, offset, 13, TRUE);
+ offset += 13;
+
+ if (request_val->last_level == 0)
+ return offset; /* that's it, at level 0 */
+
+ /* pad byte */
+ offset += 1;
+
+ /* share type */
+ proto_tree_add_item(tree, hf_share_type, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* share comment */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_share_comment);
+
+ if (request_val->last_level == 1)
+ return offset; /* that's it, at level 1 */
+
+ /* share permissions */
+ /* XXX - do as bit fields */
+ permissions = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_share_permissions, tvb, offset, 2,
+ permissions);
+ offset += 2;
+
+ /* max uses */
+ max_uses = tvb_get_letohs(tvb, offset);
+ if (max_uses == 0xffff) { /* -1 */
+ proto_tree_add_uint_format(tree, hf_share_max_uses, tvb,
+ offset, 2, max_uses, "Share Max Uses: No limit");
+ } else {
+ proto_tree_add_uint(tree, hf_share_max_uses, tvb, offset, 2,
+ max_uses);
}
+ offset += 2;
- break;
-
- case 'D': /* Double Word parameter */
+ /* current uses */
+ max_uses = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_share_current_uses, tvb, offset, 2, TRUE);
+ offset += 2;
- if (request) {
-
- LParam = GWORD(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u (0x%08X)", (Name) ? Name : "DWord Param", LParam, LParam);
-
- pd_p_current += 4;
-
- return 1; /* That's it here */
+ return offset;
+}
+static int
+add_server_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int convert, guint16 level)
+{
+ /* server name */
+ proto_tree_add_item(tree, hf_server_name, tvb, offset, 16, TRUE);
+ offset += 16;
+
+ if (level) {
+ /* major version */
+ proto_tree_add_item(tree, hf_server_major, tvb, offset, 1,
+ TRUE);
+ offset += 1;
+
+ /* minor version */
+ proto_tree_add_item(tree, hf_server_minor, tvb, offset, 1,
+ TRUE);
+ offset += 1;
+
+ /* server type flags */
+ dissect_smb_server_type_flags(tvb, pinfo, tree, offset, FALSE);
+ offset += 4;
+
+ /* server comment */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_server_comment);
}
- break;
-
- case 'g': /* A byte or series of bytes is returned */
-
- if (!request) {
-
- bc = get_byte_count(p_desc + p_offset);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : "B", (bc) ? bc : 1, format_text( pd + pd_p_current, (bc) ? bc : 1));
-
- pd_p_current += (bc) ? bc : 1;
-
- return 1;
+ return offset;
+}
- }
+static int
+netservergetinfo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ guint16 level;
- break;
+ /* detail level */
+ level = tvb_get_letohs(tvb, offset);
+ request_val->last_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, level);
+ offset += 2;
- case 'b': /* A byte or series of bytes */
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- if (request) {
+ return offset;
+}
- bc = get_byte_count(p_desc + p_offset); /* This is not clean */
+static int
+netservergetinfo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 abytes;
- /*Bytes = g_malloc(bc + 1); / * Is this needed ? */
+ /* available bytes */
+ abytes = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_abytes, tvb, offset, 2, abytes);
+ offset += 2;
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : "B", (bc) ? bc : 1, format_text(pd + pd_p_current, (bc) ? bc : 1));
+ /* XXX - what is this field? */
+ proto_tree_add_text(tree, tvb, offset, 2, "Mysterious field: %04x",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
- pd_p_current += (bc) ? bc : 1;
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
- return 1; /* That's it here ... */
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
- }
+ offset = add_server_info(tvb, pinfo, tree, offset, convert,
+ request_val->last_level);
- break;
+ return offset;
+}
- case 'O': /* A null pointer */
+static int
+netusergetinfo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ guint16 level;
- if (request) {
+ /* detail level */
+ level = tvb_get_letohs(tvb, offset);
+ request_val->last_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, level);
+ offset += 2;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 0, "%s: Null Pointer", (Name) ? Name : "Unknown");
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- return 1; /* That's it here */
+ return offset;
+}
+static int
+netusergetinfo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 abytes;
+ struct timeval timeval;
+ guint16 nlogons;
+ guint32 max_storage;
+
+ /* available bytes */
+ abytes = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_abytes, tvb, offset, 2, abytes);
+ offset += 2;
+
+ /* XXX - what is this field? */
+ proto_tree_add_text(tree, tvb, offset, 2, "Mysterious field: %04x",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
+
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
+
+ /* user name */
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
+ offset += 21;
+
+ /* pad1 */
+ offset += 1;
+
+ /* user comment */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_user_comment);
+
+ /* full name */
+ offset = add_string_pointer(tvb, tree, offset, convert, hf_full_name);
+
+ /* privilege level */
+ proto_tree_add_item(tree, hf_privilege_level, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* operator privileges */
+ proto_tree_add_item(tree, hf_operator_privileges, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* password age */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ proto_tree_add_time_format(tree, hf_password_age, tvb, offset, 4,
+ &timeval, "Password Age: %s", time_secs_to_str(timeval.tv_sec));
+ offset += 4;
+
+ /* home directory */
+ offset = add_string_pointer(tvb, tree, offset, convert, hf_homedir);
+
+ /* parameters */
+ offset = add_string_pointer(tvb, tree, offset, convert, hf_parameters);
+
+ timeval.tv_usec = 0;
+
+ /* last logon time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_last_logon, tvb, offset, 4,
+ &timeval, "Last Logon Date/Time: Unknown");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_last_logon, tvb, offset, 4,
+ &timeval);
}
-
- break;
-
- case 'z': /* An AsciiZ string */
-
- if (request) {
-
- AsciiZ = pd + pd_p_current;
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, strlen(AsciiZ) + 1, "%s: %s", (Name) ? Name : "AsciiZ", AsciiZ);
-
- pd_p_current += strlen(AsciiZ) + 1;
-
- return 1; /* That's it here ... */
-
+ offset += 4;
+
+ /* last logoff time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_last_logoff, tvb, offset, 4,
+ &timeval, "Last Logoff Date/Time: Unknown");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_last_logoff, tvb, offset, 4,
+ &timeval);
}
+ offset += 4;
- break;
+ /* bad password count */
+ proto_tree_add_item(tree, hf_bad_pw_count, tvb, offset, 2, TRUE);
+ offset += 2;
- case 'F': /* One or more pad bytes */
-
- if (request) {
-
- bc = get_byte_count(pd);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : "Pad", bc, format_text(pd + pd_p_current, bc));
+ /* number of logons */
+ nlogons = tvb_get_letohs(tvb, offset);
+ if (nlogons == 0xffff) /* -1 */
+ proto_tree_add_uint_format(tree, hf_num_logons, tvb, offset, 2,
+ nlogons, "Number of Logons: Unknown");
+ else
+ proto_tree_add_uint(tree, hf_num_logons, tvb, offset, 2,
+ nlogons);
+ offset += 2;
+
+ /* logon server */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_logon_server);
+
+ /* country code */
+ /* XXX - we should have a value_string table for these */
+ proto_tree_add_item(tree, hf_country_code, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* workstations */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_workstations);
+
+ /* max storage */
+ max_storage = tvb_get_letohl(tvb, offset);
+ if (nlogons == 0xffffffff)
+ proto_tree_add_uint_format(tree, hf_max_storage, tvb, offset, 4,
+ max_storage, "Max Storage: No limit");
+ else
+ proto_tree_add_uint(tree, hf_max_storage, tvb, offset, 4,
+ max_storage);
+ offset += 4;
+
+ /* units per week */
+ proto_tree_add_item(tree, hf_units_per_week, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* logon hours */
+ /* XXX - should actually carve up the bits */
+ /* XXX - how do we recognize a null pointer? */
+ offset = add_byte_array_pointer(tvb, tree, offset, 21, convert,
+ hf_logon_hours);
+
+ /* code page */
+ /* XXX - we should have a value_string table for these */
+ proto_tree_add_item(tree, hf_code_page, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ return offset;
+}
- pd_p_current += bc;
+static int
+netremotetod_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- return 1; /* That's it here */
+ return offset;
+}
+static int
+netremotetod_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct timeval timeval;
+ gint16 tzoffset;
+ guint16 timeinterval;
+
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
+
+ /* current time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ timeval.tv_usec = 0;
+ proto_tree_add_time(tree, hf_current_time, tvb, offset, 4, &timeval);
+ offset += 4;
+
+ /* msecs since arbitrary point in the past */
+ timeval.tv_usec = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ /* hour */
+ proto_tree_add_item(tree, hf_hour, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* minute */
+ proto_tree_add_item(tree, hf_minute, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* second */
+ proto_tree_add_item(tree, hf_second, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* hundredths-of-second */
+ proto_tree_add_item(tree, hf_hundredths, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* time zone offset, in minutes */
+ tzoffset = tvb_get_letohs(tvb, offset);
+ if (tzoffset < 0) {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "Time Zone Offset: %s east of UTC",
+ time_secs_to_str(-tzoffset*60));
+ } else if (tzoffset > 0) {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "Time Zone Offset: %s west of UTC",
+ time_secs_to_str(tzoffset*60));
+ } else {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "Time Zone Offset: at UTC");
}
+ offset += 2;
- break;
+ /* timer resolution */
+ timeinterval = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_timeinterval, tvb, offset, 2,
+ timeinterval, "Time Interval: %f seconds", timeinterval*.0001);
+ offset += 2;
- case 'L': /* Receive buffer len: Short */
+ /* day */
+ proto_tree_add_item(tree, hf_day, tvb, offset, 1, TRUE);
+ offset += 1;
- if (request) {
+ /* month */
+ proto_tree_add_item(tree, hf_month, tvb, offset, 1, TRUE);
+ offset += 1;
- WParam = GSHORT(pd, pd_p_current);
+ /* year */
+ proto_tree_add_item(tree, hf_year, tvb, offset, 2, TRUE);
+ offset += 2;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (0x%04X)", (Name) ? Name : "Receive Buffer Len", WParam, WParam);
+ /* day of week */
+ proto_tree_add_item(tree, hf_weekday, tvb, offset, 1, TRUE);
+ offset += 1;
- pd_p_current += 2;
+ return offset;
+}
- return 1; /* That's it here ... */
+static int
+netserverenum2_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ guint16 level;
- }
+ /* detail level */
+ level = tvb_get_letohs(tvb, offset);
+ request_val->last_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, level);
+ offset += 2;
- break;
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- case 's': /* Send buf ... */
+ /* server type flags */
+ dissect_smb_server_type_flags(tvb, pinfo, tree, offset, TRUE);
+ offset += 4;
- if (request) {
+ return offset;
+}
- need_data = 1;
+static int
+netserverenum2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 ecount, acount;
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ int i;
- LParam = GWORD(pd, pd_p_current);
+ /* entry count */
+ ecount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2, ecount);
+ offset += 2;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u", (Name) ? Name : "Send Buffer Ptr", LParam);
+ /* available count */
+ acount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_acount, tvb, offset, 2, acount);
+ offset += 2;
- pd_p_current += 4;
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
- return 1; /* That's it here ... */
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
+ if (tree) {
+ it = proto_tree_add_text(tree, tvb, offset,
+ tvb_length_remaining(tvb, offset), "Servers");
+ tr = proto_item_add_subtree(it, ett_lanman_servers);
}
- break;
+ for (i = 0; i < ecount; i++) {
+ proto_item *si = NULL;
+ proto_tree *st = NULL;
+ char *server;
+ int old_offset = offset;
- case 'T':
+ server = (char *)tvb_get_ptr(tvb, offset, 16);
+ if (tree) {
+ si = proto_tree_add_text(tr, tvb, offset,
+ request_val->last_level ? 26 : 16,
+ "Server %.16s", server);
+ st = proto_item_add_subtree(si, ett_lanman_server);
+ }
- if (request) {
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u", (Name) ? Name : "Send Buffer Len", WParam);
-
- pd_p_current += 2;
-
- return 1;
+ offset = add_server_info(tvb, pinfo, st, offset, convert,
+ request_val->last_level);
+ proto_item_set_len(si, offset-old_offset);
}
- break;
-
- default:
-
- break;
-
- }
-
- break;
-
- case 1: /* We are in the data area ... */
-
-
- break;
-
- }
- }
-
- return 0;
-
+ return offset;
}
-static const value_string share_type_vals[] = {
- {0, "Directory tree"},
- {1, "Printer queue"},
- {2, "Communications device"},
- {3, "IPC"},
- {0, NULL}
-};
-
-/*
- * Per-frame data needed to dissect replies.
- */
-typedef struct {
- guint16 FunctionCode;
- gboolean is_continuation;
-} response_data;
-
-static GMemChunk *lanman_proto_data;
-
-static gboolean
-dissect_pipe_lanman(const u_char *pd, int offset, frame_data *fd,
- proto_tree *parent, proto_tree *tree,
- int max_data, int SMB_offset, int errcode,
- const u_char *command, int DataOffset, int DataCount,
- int ParameterOffset, int ParameterCount)
+static int
+netwkstagetinfo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
{
- struct smb_info *smb_info = pi.private;
- gboolean is_interim_response;
- guint32 loc_offset;
- guint16 FunctionCode;
- guint16 Level;
- guint16 RecvBufLen;
- guint32 Flags;
- const char *ParameterDescriptor;
- const char *ReturnDescriptor;
- proto_tree *lanman_tree = NULL, *flags_tree = NULL;
- proto_item *ti;
- struct lanman_desc *lanman;
- guint32 string_offset;
-
- if (DataOffset < 0) {
-
- /* Interim response; we weren't given any data. */
-
- is_interim_response = TRUE;
- loc_offset = SMB_offset;
-
- }
- else {
-
- /* Offset of the data we should dissect. */
-
- is_interim_response = FALSE;
- loc_offset = SMB_offset + ParameterOffset;
-
- }
-
- if (check_col(fd, COL_PROTOCOL))
- col_set_str(fd, COL_PROTOCOL, "LANMAN");
-
- if (smb_info->request) { /* The request side */
-
- FunctionCode = GSHORT(pd, loc_offset);
-
- smb_info->request_val -> last_lanman_cmd = FunctionCode;
-
- lanman = find_lanman(FunctionCode);
-
- if (check_col(fd, COL_INFO)) {
-
- if (lanman) {
- col_add_fstr(fd, COL_INFO, "%s Request", lanman -> lanman_name);
- }
- else {
- col_add_fstr(fd, COL_INFO, "Unknown LANMAN Request: %u", FunctionCode);
- }
- }
-
- if (tree) {
-
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, ParameterCount, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
-
- if (lanman) {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: %s", lanman -> lanman_name);
- }
- else {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: Unknown LANMAN Request: %u", FunctionCode);
- }
-
- }
-
- loc_offset += 2;
-
- ParameterDescriptor = pd + loc_offset;
-
- /* Now, save these for later */
-
- smb_info->request_val -> trans_response_seen = 0;
-
- if (smb_info->request_val -> last_param_descrip)
- g_free(smb_info->request_val -> last_param_descrip);
- smb_info->request_val -> last_param_descrip = g_malloc(strlen(ParameterDescriptor) + 1);
- if (smb_info->request_val -> last_param_descrip)
- strcpy(smb_info->request_val -> last_param_descrip, ParameterDescriptor);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ParameterDescriptor) + 1, "Parameter Descriptor: %s", ParameterDescriptor);
-
- }
-
- loc_offset += strlen(ParameterDescriptor) + 1;
-
- ReturnDescriptor = pd + loc_offset;
-
- if (smb_info->request_val -> last_data_descrip)
- g_free(smb_info->request_val -> last_data_descrip);
- smb_info->request_val -> last_data_descrip = g_malloc(strlen(ReturnDescriptor) + 1);
- if (smb_info->request_val -> last_data_descrip)
- strcpy(smb_info->request_val -> last_data_descrip, ReturnDescriptor);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ReturnDescriptor) + 1, "Return Descriptor: %s", ReturnDescriptor);
-
- }
+ guint16 level;
- loc_offset += strlen(ReturnDescriptor) + 1;
+ /* detail level */
+ level = tvb_get_letohs(tvb, offset);
+ request_val->last_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, level);
+ offset += 2;
- switch (FunctionCode) {
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- case NETSHAREENUM: /* Never decode this at the moment ... */
-
- Level = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Detail Level: %u", Level);
-
- }
-
- loc_offset += 2;
-
- RecvBufLen = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Receive Buffer Length: %u", RecvBufLen);
-
- }
-
- loc_offset += 2;
-
- break;
-
- case NETSERVERENUM2: /* Process a NetServerEnum2 */
-
- Level = GSHORT(pd, loc_offset);
- smb_info->request_val -> last_level = Level;
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Info Detail Level: %u", Level);
-
- }
-
- loc_offset += 2;
-
- RecvBufLen = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Receive Buffer Length: %u", RecvBufLen);
-
- }
-
- loc_offset += 2;
-
- Flags = GWORD(pd, loc_offset);
-
- if (tree) {
-
- ti = proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 4, "Server Types Required: 0x%08X", Flags);
- flags_tree = proto_item_add_subtree(ti, ett_lanman_flags);
- dissect_server_flags(flags_tree, loc_offset, 4, Flags);
-
- }
-
- loc_offset += 4;
-
- return TRUE;
- break;
-
- default: /* Just try to handle what is there ... */
-
- if (tree) {
-
- int i = 0; /* Counter for names below */
- char *name = NULL;
+ return offset;
+}
- dissect_transact_engine_init(pd, ParameterDescriptor, ReturnDescriptor,SMB_offset, loc_offset, ParameterCount, DataOffset, DataCount);
+static int
+netwkstagetinfo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 abytes;
- if (lanman) name = lanman -> req[i]; /* Must be OK ... */
+ /* available bytes */
+ abytes = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_abytes, tvb, offset, 2, abytes);
+ offset += 2;
- while (dissect_transact_next(pd, name, smb_info->request, lanman_tree))
- if (name) name = lanman -> req[++i];
- }
+ /* XXX - what is this field? */
+ proto_tree_add_text(tree, tvb, offset, 2, "Mysterious field: %04x",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
- break;
-
- }
- }
- else { /* response */
- response_data *proto_data;
- guint16 Status;
- guint16 Convert;
- guint16 EntCount;
- guint16 AvailCount;
- int i;
- proto_tree *server_tree = NULL, *flags_tree = NULL, *share_tree = NULL;
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
- /* Is there any per-frame LANMAN data for this frame? */
- proto_data = p_get_proto_data(fd, proto_smb_lanman);
- if (proto_data == NULL) {
- /* No. Allocate some, and set it up. */
- proto_data = g_mem_chunk_alloc(lanman_proto_data);
- proto_data->FunctionCode = smb_info->request_val -> last_lanman_cmd;
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
- /*
- * If we've already seen a response to the request, this must
- * be a continuation of that response.
- */
- proto_data->is_continuation = smb_info->request_val -> trans_response_seen;
+ /* computer name */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_computer_name);
- /*
- * Attach it to the frame.
- */
- p_add_proto_data(fd, proto_smb_lanman, proto_data);
- }
+ /* user name */
+ offset = add_string_pointer(tvb, tree, offset, convert, hf_user_name);
- FunctionCode = proto_data->FunctionCode;
+ /* workstation domain */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_workstation_domain);
- /*
- * If we have already seen the response to this transact, simply
- * record it as a continuation ...
- */
- if (proto_data->is_continuation) {
+ /* major version */
+ proto_tree_add_item(tree, hf_workstation_major, tvb, offset, 1, TRUE);
+ offset += 1;
- if (check_col(fd, COL_INFO)) {
- col_set_str(fd, COL_INFO, "Transact Continuation");
- }
-
- if (tree) {
+ /* minor version */
+ proto_tree_add_item(tree, hf_workstation_minor, tvb, offset, 1, TRUE);
+ offset += 1;
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, END_OF_FRAME, FALSE);
+ /* logon domain */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_logon_domain);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
+ /* other domains */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_other_domains);
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, END_OF_FRAME, "Payload: %s", format_text(pd + loc_offset, END_OF_FRAME));
+ return offset;
+}
- }
+static int
+netwkstauserlogon_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ guint16 level;
- return TRUE;
+ /* detail level */
+ level = tvb_get_letohs(tvb, offset);
+ request_val->last_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, level);
+ offset += 2;
- }
+ /* user name */
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
+ offset += 21;
- smb_info->request_val -> trans_response_seen = 1;
+ /* pad1 */
+ offset += 1;
- lanman = find_lanman(FunctionCode);
+ /* password */
+ proto_tree_add_item(tree, hf_password, tvb, offset, 15, TRUE);
+ offset += 15;
- if (check_col(fd, COL_INFO)) {
+ /* pad2 */
+ offset += 1;
- if (lanman) {
- col_add_fstr(fd, COL_INFO, "%s %sResponse", lanman -> lanman_name,
- is_interim_response ? "Interim " : "");
- }
- else {
- col_add_fstr(fd, COL_INFO, "Unknown LANMAN %sResponse: %u",
- is_interim_response ? "Interim " : "", FunctionCode);
- }
- }
+ /* workstation name */
+ proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
+ offset += 16;
- if (tree) {
+ /* size of the above */
+ proto_tree_add_item(tree, hf_ustruct_size, tvb, offset, 2, TRUE);
+ offset += 2;
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, END_OF_FRAME, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
- if (lanman) {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 0, "Function Code: %s", lanman -> lanman_name);
- }
- else {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 0, "Function Code: Unknown LANMAN Response: %u", FunctionCode);
- }
- }
+ /* receiver buffer length */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb, offset, 2, TRUE);
+ offset += 2;
- if (is_interim_response) {
+ return offset;
+}
- return TRUE; /* no data to dissect */
+static int
+netwkstauserlogon_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 abytes;
+ guint16 nlogons;
+ struct timeval timeval;
+
+ /* available bytes */
+ abytes = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_abytes, tvb, offset, 2, abytes);
+ offset += 2;
+
+ /* XXX - what is this field? */
+ proto_tree_add_text(tree, tvb, offset, 2, "Mysterious field: %04x",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
+
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
+
+ /* logon code */
+ proto_tree_add_item(tree, hf_logon_code, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* user name */
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
+ offset += 21;
+
+ /* pad1 */
+ offset += 1;
+
+ /* privilege level */
+ proto_tree_add_item(tree, hf_privilege_level, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* operator privileges */
+ proto_tree_add_item(tree, hf_operator_privileges, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* number of logons */
+ nlogons = tvb_get_letohs(tvb, offset);
+ if (nlogons == 0xffff) /* -1 */
+ proto_tree_add_uint_format(tree, hf_num_logons, tvb, offset, 2,
+ nlogons, "Number of Logons: Unknown");
+ else
+ proto_tree_add_uint(tree, hf_num_logons, tvb, offset, 2,
+ nlogons);
+ offset += 2;
+
+ /* bad password count */
+ proto_tree_add_item(tree, hf_bad_pw_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ timeval.tv_usec = 0;
+
+ /* last logon time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_last_logon, tvb, offset, 4,
+ &timeval, "Last Logon Date/Time: Unknown");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_last_logon, tvb, offset, 4,
+ &timeval);
+ }
+ offset += 4;
+
+ /* last logoff time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_last_logoff, tvb, offset, 4,
+ &timeval, "Last Logoff Date/Time: Unknown");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_last_logoff, tvb, offset, 4,
+ &timeval);
+ }
+ offset += 4;
+
+ /* logoff time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_logoff_time, tvb, offset, 4,
+ &timeval, "Logoff Date/Time: None");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_logoff_time, tvb, offset, 4,
+ &timeval);
+ }
+ offset += 4;
+
+ /* kickoff time */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_kickoff_time, tvb, offset, 4,
+ &timeval, "Kickoff Date/Time: None");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_kickoff_time, tvb, offset, 4,
+ &timeval);
+ }
+ offset += 4;
+
+ /* password age */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ proto_tree_add_time_format(tree, hf_password_age, tvb, offset, 4,
+ &timeval, "Password Age: %s", time_secs_to_str(timeval.tv_sec));
+ offset += 4;
+
+ /* date/time when password can change */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_password_can_change, tvb, offset, 4,
+ &timeval, "Password Can Change: Never");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_password_can_change, tvb, offset, 4,
+ &timeval);
+ }
+ offset += 4;
+
+ /* date/time when password must change */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ if (timeval.tv_sec == -1) {
+ proto_tree_add_time_format(tree, hf_password_must_change, tvb, offset, 4,
+ &timeval, "Password Must Change: Never");
+ } else {
+ timeval.tv_sec = localtime_to_utc(timeval.tv_sec);
+ proto_tree_add_time(tree, hf_password_must_change, tvb, offset, 4,
+ &timeval);
+ }
+ offset += 4;
- }
+ /* computer where user is logged on */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_server_name);
- switch (FunctionCode) {
+ /* domain in which user is logged on */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_logon_domain);
- case NETSHAREENUM:
+ /* pathname of user's login script */
+ offset = add_string_pointer(tvb, tree, offset, convert,
+ hf_script_path);
- Status = GSHORT(pd, loc_offset);
+ /* reserved */
+ proto_tree_add_text(tree, tvb, offset, 4, "Reserved: %08x",
+ tvb_get_letohl(tvb, offset));
+ offset += 4;
- if (tree) {
+ return offset;
+}
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Status: %u", Status);
+static int
+netwkstauserlogoff_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ /* user name */
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
+ offset += 21;
- }
+ /* pad1 */
+ offset += 1;
- loc_offset += 2;
+ /* workstation name */
+ proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
+ offset += 16;
- Convert = GSHORT(pd, loc_offset);
+ return offset;
+}
- if (tree) {
+static int
+netwkstauserlogoff_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint16 abytes;
+ guint16 nlogons;
+ struct timeval timeval;
+
+ /* available bytes */
+ abytes = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_abytes, tvb, offset, 2, abytes);
+ offset += 2;
+
+ /* XXX - what is this field? */
+ proto_tree_add_text(tree, tvb, offset, 2, "Mysterious field: %04x",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ if (status != 0 && status != SMBE_moredata)
+ return offset;
+
+ /* The rest is in the data section. */
+ offset = smb_info->data_offset;
+
+ /* logoff code */
+ proto_tree_add_item(tree, hf_logoff_code, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* duration */
+ timeval.tv_sec = tvb_get_letohl(tvb, offset);
+ timeval.tv_usec = 0;
+ proto_tree_add_time_format(tree, hf_duration, tvb, offset, 4,
+ &timeval, "Duration of Session: %s", time_secs_to_str(timeval.tv_sec));
+ offset += 4;
+
+ /* number of logons */
+ nlogons = tvb_get_letohs(tvb, offset);
+ if (nlogons == 0xffff) /* -1 */
+ proto_tree_add_uint_format(tree, hf_num_logons, tvb, offset, 2,
+ nlogons, "Number of Logons: Unknown");
+ else
+ proto_tree_add_uint(tree, hf_num_logons, tvb, offset, 2,
+ nlogons);
+ offset += 2;
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
+ return offset;
+}
- }
+static int
+samoemchangepassword_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset)
+{
+ struct smb_info *smb_info = pinfo->private;
+ guint user_name_len;
- loc_offset += 2;
+ /* user name */
+ user_name_len = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, user_name_len,
+ TRUE);
+ offset += user_name_len;
- EntCount = GSHORT(pd, loc_offset);
+ /* new password */
+ proto_tree_add_item(tree, hf_new_password, tvb,
+ smb_info->data_offset, 516, TRUE);
- if (tree) {
+ /* old password */
+ proto_tree_add_item(tree, hf_old_password, tvb,
+ smb_info->data_offset + 516, 16, TRUE);
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Entry Count: %u", EntCount);
+ return offset;
+}
- }
+static int
+samoemchangepassword_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val, int offset, guint16 status,
+ int convert)
+{
+ /* nothing in this reply */
+ return offset;
+}
- loc_offset += 2;
+#define LANMAN_NETSHAREENUM 0
+#define LANMAN_NETSHAREGETINFO 1
+#define LANMAN_NETSERVERGETINFO 13
+#define LANMAN_NETGROUPGETUSERS 52
+#define LANMAN_NETUSERGETINFO 56
+#define LANMAN_NETUSERGETGROUPS 59
+#define LANMAN_NETWKSTAGETINFO 63
+#define LANMAN_DOSPRINTQENUM 69
+#define LANMAN_DOSPRINTQGETINFO 70
+#define LANMAN_WPRINTQUEUEPAUSE 74
+#define LANMAN_WPRINTQUEUERESUME 75
+#define LANMAN_WPRINTJOBENUMERATE 76
+#define LANMAN_WPRINTJOBGETINFO 77
+#define LANMAN_RDOSPRINTJOBDEL 81
+#define LANMAN_RDOSPRINTJOBPAUSE 82
+#define LANMAN_RDOSPRINTJOBRESUME 83
+#define LANMAN_WPRINTDESTENUM 84
+#define LANMAN_WPRINTDESTGETINFO 85
+#define LANMAN_NETREMOTETOD 91
+#define LANMAN_WPRINTQUEUEPURGE 103
+#define LANMAN_NETSERVERENUM2 104
+#define LANMAN_WACCESSGETUSERPERMS 105
+#define LANMAN_SETUSERPASSWORD 115
+#define LANMAN_NETWKSTAUSERLOGON 132
+#define LANMAN_NETWKSTAUSERLOGOFF 133
+#define LANMAN_PRINTJOBINFO 147
+#define LANMAN_WPRINTDRIVERENUM 205
+#define LANMAN_WPRINTQPROCENUM 206
+#define LANMAN_WPRINTPORTENUM 207
+#define LANMAN_SAMOEMCHANGEPASSWORD 214
+
+static const value_string commands[] = {
+ {LANMAN_NETSHAREENUM, "NetShareEnum"},
+ {LANMAN_NETSHAREGETINFO, "NetShareGetInfo"},
+ {LANMAN_NETSERVERGETINFO, "NetServerGetInfo"},
+ {LANMAN_NETGROUPGETUSERS, "NetGroupGetUsers"},
+ {LANMAN_NETUSERGETINFO, "NetUserGetInfo"},
+ {LANMAN_NETUSERGETGROUPS, "NetUserGetGroups"},
+ {LANMAN_NETWKSTAGETINFO, "NetWkstaGetInfo"},
+ {LANMAN_DOSPRINTQENUM, "DOSPrintQEnum"},
+ {LANMAN_DOSPRINTQGETINFO, "DOSPrintQGetInfo"},
+ {LANMAN_WPRINTQUEUEPAUSE, "WPrintQueuePause"},
+ {LANMAN_WPRINTQUEUERESUME, "WPrintQueueResume"},
+ {LANMAN_WPRINTJOBENUMERATE, "WPrintJobEnumerate"},
+ {LANMAN_WPRINTJOBGETINFO, "WPrintJobGetInfo"},
+ {LANMAN_RDOSPRINTJOBDEL, "RDOSPrintJobDel"},
+ {LANMAN_RDOSPRINTJOBPAUSE, "RDOSPrintJobPause"},
+ {LANMAN_RDOSPRINTJOBRESUME, "RDOSPrintJobResume"},
+ {LANMAN_WPRINTDESTENUM, "WPrintDestEnum"},
+ {LANMAN_WPRINTDESTGETINFO, "WPrintDestGetInfo"},
+ {LANMAN_NETREMOTETOD, "NetRemoteTOD"},
+ {LANMAN_WPRINTQUEUEPURGE, "WPrintQueuePurge"},
+ {LANMAN_NETSERVERENUM2, "NetServerEnum2"},
+ {LANMAN_WACCESSGETUSERPERMS, "WAccessGetUserPerms"},
+ {LANMAN_SETUSERPASSWORD, "SetUserPassword"},
+ {LANMAN_NETWKSTAUSERLOGON, "NetWkstaUserLogon"},
+ {LANMAN_NETWKSTAUSERLOGOFF, "NetWkstaUserLogoff"},
+ {LANMAN_PRINTJOBINFO, "PrintJobInfo"},
+ {LANMAN_WPRINTDRIVERENUM, "WPrintDriverEnum"},
+ {LANMAN_WPRINTQPROCENUM, "WPrintQProcEnum"},
+ {LANMAN_WPRINTPORTENUM, "WPrintPortEnum"},
+ {LANMAN_SAMOEMCHANGEPASSWORD, "SamOEMChangePassword"},
+ {0, NULL}
+};
- AvailCount = GSHORT(pd, loc_offset);
+struct lanman_dissector {
+ int command;
+ int (*request)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val,
+ int offset);
+ int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct smb_request_val *request_val,
+ int offset, guint16 status, int convert);
+};
- if (tree) {
+struct lanman_dissector lmd[] = {
+ { LANMAN_NETSHAREENUM,
+ netshareenum_request,
+ netshareenum_response },
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Available Entries: %u", AvailCount);
+ { LANMAN_NETSHAREGETINFO,
+ netsharegetinfo_request,
+ netsharegetinfo_response },
- }
+ { LANMAN_NETSERVERGETINFO,
+ netservergetinfo_request,
+ netservergetinfo_response },
- loc_offset += 2;
+ { LANMAN_NETUSERGETINFO,
+ netusergetinfo_request,
+ netusergetinfo_response },
- if (tree) {
+ { LANMAN_NETREMOTETOD,
+ netremotetod_request,
+ netremotetod_response },
- ti = proto_tree_add_text(lanman_tree, NullTVB, loc_offset, AvailCount * 20, "Available Shares");
+ { LANMAN_NETSERVERENUM2,
+ netserverenum2_request,
+ netserverenum2_response },
- share_tree = proto_item_add_subtree(ti, ett_lanman_shares);
+ { LANMAN_NETWKSTAGETINFO,
+ netwkstagetinfo_request,
+ netwkstagetinfo_response },
- }
+ { LANMAN_NETWKSTAUSERLOGON,
+ netwkstauserlogon_request,
+ netwkstauserlogon_response },
- for (i = 1; i <= EntCount; i++) {
- const gchar *Share = pd + loc_offset;
- guint32 Flags;
- const gchar *Comment;
- proto_tree *share = NULL;
- proto_item *ti = NULL;
+ { LANMAN_NETWKSTAUSERLOGOFF,
+ netwkstauserlogoff_request,
+ netwkstauserlogoff_response },
- if (tree) {
+ { LANMAN_SAMOEMCHANGEPASSWORD,
+ samoemchangepassword_request,
+ samoemchangepassword_response },
- ti = proto_tree_add_text(share_tree, NullTVB, loc_offset, 20, "Share %s", Share);
- share = proto_item_add_subtree(ti, ett_lanman_share);
+ { -1, NULL, NULL }
+};
+struct lanman_dissector *find_lanman_dissector(int cmd)
+{
+ int i;
+ for (i = 0; lmd[i].command != -1; i++) {
+ if (lmd[i].command == cmd)
+ return &lmd[i];
}
+ return NULL;
+}
- if (tree) {
-
- proto_tree_add_text(share, NullTVB, loc_offset, 13, "Share Name: %s", Share);
-
+static gboolean
+dissect_pipe_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ struct smb_info *smb_info = pinfo->private;
+ struct smb_request_val *request_val = smb_info->request_val;
+ int offset = 0;
+ guint16 cmd;
+ guint16 status;
+ int convert;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ struct lanman_dissector *dis;
+ guint param_descriptor_len, return_descriptor_len;
+
+ if (check_col(pinfo->fd, COL_PROTOCOL)) {
+ col_set_str(pinfo->fd, COL_PROTOCOL, "LANMAN");
}
- loc_offset += 13;
-
- loc_offset += 1; /* Pad byte ... */
-
- Flags = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(share, NullTVB, loc_offset, 2, "Share Type: %s",
- val_to_str(Flags, share_type_vals, "Unknown (%u)"));
-
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_lanman,
+ tvb, 0, tvb_length(tvb), FALSE);
+ tree = proto_item_add_subtree(item, ett_lanman);
}
- loc_offset += 2;
-
- /* XXX - should check whether all of the string is within the
- frame. */
- string_offset = SMB_offset + DataOffset + (GWORD(pd, loc_offset) & 0xFFFF) - Convert;
- if (IS_DATA_IN_FRAME(string_offset))
- Comment = pd + string_offset;
- else
- Comment = "<String goes past end of frame>";
-
- if (tree) {
-
- proto_tree_add_text(share, NullTVB, loc_offset, 4, "Share Comment: %s", Comment);
-
+ /* continuation messages, dont try to decode them */
+ if (smb_info->ddisp) {
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_set_str(pinfo->fd, COL_INFO, "Transact Continuation");
+ }
+ return TRUE;
}
- loc_offset += 4;
-
- }
-
- break;
-
- case NETSERVERENUM2:
-
- Status = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Status: %u", Status);
-
- }
-
- loc_offset += 2;
-
- Convert = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
-
- }
-
- loc_offset += 2;
+ if (smb_info->request) { /* this is a request */
+ /* function code */
+ cmd = tvb_get_letohs(tvb, offset);
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_add_fstr(pinfo->fd, COL_INFO, "%s Request", val_to_str(cmd, commands, "Unknown Command:0x%02x"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, tvb, offset, 2,
+ cmd);
+ offset += 2;
+
+ /*
+ * If we haven't already done so, save the function code in
+ * the structure we were handed, so that it's available to
+ * the code parsing the reply.
+ */
+ if (!pinfo->fd->flags.visited)
+ request_val->last_lanman_cmd = cmd;
+
+ /* parameter descriptor */
+ param_descriptor_len = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_param_desc, tvb, offset,
+ param_descriptor_len, TRUE);
+ if (pinfo->fd->flags.visited) {
+ /*
+ * Save the parameter descriptor for future use.
+ */
+ g_assert(request_val->last_param_descrip == NULL);
+ request_val->last_param_descrip =
+ g_malloc(param_descriptor_len);
+ strcpy(request_val->last_param_descrip,
+ tvb_get_ptr(tvb, offset, param_descriptor_len));
+ }
+ offset += param_descriptor_len;
+
+ /* return descriptor */
+ return_descriptor_len = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_return_desc, tvb, offset,
+ return_descriptor_len, TRUE);
+ if (pinfo->fd->flags.visited) {
+ /*
+ * Save the return descriptor for future use.
+ */
+ g_assert(request_val->last_data_descrip == NULL);
+ request_val->last_data_descrip =
+ g_malloc(return_descriptor_len);
+ strcpy(request_val->last_data_descrip,
+ tvb_get_ptr(tvb, offset, return_descriptor_len));
+ }
+ offset += return_descriptor_len;
+
+ /* command parameters */
+ dis = find_lanman_dissector(cmd);
+ if (dis == NULL) {
+ offset = not_implemented(tvb, pinfo, tree, offset);
+ return FALSE;
+ }
+ offset = (*(dis->request))(tvb, pinfo, tree, request_val,
+ offset);
+ } else {
+ /*
+ * This is a response.
+ * Have we seen the request to which it's a response?
+ */
+ if (request_val == NULL)
+ return FALSE; /* no - can't dissect it */
+
+ /* ok we have seen this one before */
+
+ /* response to the request in frame xx */
+ proto_tree_add_uint(tree, hf_response_to, tvb, 0, 0,
+ request_val->frame);
+ /* command */
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_add_fstr(pinfo->fd, COL_INFO, "%s %sResponse",
+ val_to_str(request_val->last_lanman_cmd, commands, "Unknown Command (0x%02x)"),
+ smb_info->is_interim_response ? "Interim " : "");
+ }
+ proto_tree_add_uint(tree, hf_function_code, tvb, 0, 0,
+ request_val->last_lanman_cmd);
+
+ if (smb_info->is_interim_response)
+ return TRUE; /* no data to dissect */
+
+ /* command parameters */
+
+ /* status */
+ status = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_status, tvb, offset, 2, status);
+ offset += 2;
+
+ /* convert */
+ convert = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_convert, tvb, offset, 2, convert);
+ offset += 2;
+
+ /*
+ * "convert" is relative to the beginning of the data
+ * area, but we're handed a tvbuff that starts at the
+ * beginning of the parameter area, so we need to
+ * add "smb_info->data_offset" to offsets after
+ * subtracting "convert"; subtract it from "convert"
+ * so that it gets added in for free.
+ */
+ convert -= smb_info->data_offset;
+
+ dis = find_lanman_dissector(request_val->last_lanman_cmd);
+ if (dis == NULL) {
+ offset = not_implemented(tvb, pinfo, tree, offset);
+ return FALSE;
+ }
+ offset = (*(dis->response))(tvb, pinfo, tree, request_val,
+ offset, status, convert);
+ }
- EntCount = GSHORT(pd, loc_offset);
+ return TRUE;
+}
- if (tree) {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Entry Count: %u", EntCount);
- }
+gboolean
+dissect_pipe_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ char *command)
+{
+ if (!proto_is_protocol_enabled(proto_smb_lanman))
+ return FALSE;
+ pinfo->current_proto = "LANMAN";
- loc_offset += 2;
+ if (command != NULL && strcmp(command, "LANMAN") == 0) {
+ /* Try to decode a LANMAN */
- AvailCount = GSHORT(pd, loc_offset);
+ return dissect_pipe_lanman(tvb, pinfo, tree);
+ }
- if (tree) {
+ return FALSE;
+}
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Available Entries: %u", AvailCount);
+void
+register_proto_smb_pipe(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_function_code,
+ { "Function Code", "lanman.function_code", FT_UINT16, BASE_DEC,
+ VALS(commands), 0, "LANMAN Function Code/Command", HFILL }},
- }
+ { &hf_param_desc,
+ { "Parameter Descriptor", "lanman.param_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameter Descriptor", HFILL }},
- loc_offset += 2;
+ { &hf_return_desc,
+ { "Return Descriptor", "lanman.ret_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Return Descriptor", HFILL }},
- if (tree) {
+ { &hf_not_implemented,
+ { "Unknown Data", "lanman.not_implemented", FT_BYTES, BASE_HEX,
+ NULL, 0, "Decoding of this data is not implemented yet", HFILL }},
- ti = proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 26 * AvailCount, "Servers");
- if (ti == NULL) {
+ { &hf_detail_level,
+ { "Detail Level", "lanman.level", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Detail Level", HFILL }},
- printf("Null value returned from proto_tree_add_text\n");
- exit(1);
+ { &hf_recv_buf_len,
+ { "Receive Buffer Length", "lanman.recv_buf_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Receive Buffer Length", HFILL }},
- }
+ { &hf_response_to,
+ { "Response to request in frame", "lanman.response_to", FT_UINT32, BASE_DEC,
+ NULL, 0, "This is a LANMAN response to the request in frame", HFILL }},
- server_tree = proto_item_add_subtree(ti, ett_lanman_servers);
+ { &hf_status,
+ { "Status", "lanman.status", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Return status", HFILL }},
- }
+ { &hf_convert,
+ { "Convert", "lanman.convert", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Convert", HFILL }},
- /* Make sure we don't go past the end of the capture buffer */
+ { &hf_ecount,
+ { "Entry Count", "lanman.entry_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Entries", HFILL }},
- for (i = 1; (i <= EntCount) && ((pi.captured_len - loc_offset) >= 16); i++) {
- const gchar *Server = pd + loc_offset;
- gint8 ServerMajor;
- guint ServerMinor;
- guint32 ServerFlags;
- const gchar *Comment;
- proto_tree *server = NULL;
- proto_item *ti;
+ { &hf_acount,
+ { "Available Entries", "lanman.available_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Entries", HFILL }},
- if (tree) {
+ { &hf_share_name,
+ { "Share Name", "lanman.share.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Share", HFILL }},
- ti = proto_tree_add_text(server_tree, NullTVB, loc_offset,
- (smb_info->request_val -> last_level) ? 26 : 16,
- "Server %s", Server);
- server = proto_item_add_subtree(ti, ett_lanman_server);
+ { &hf_share_type,
+ { "Share Type", "lanman.share.type", FT_UINT16, BASE_DEC,
+ VALS(share_type_vals), 0, "LANMAN Type of Share", HFILL }},
+ { &hf_share_comment,
+ { "Share Comment", "lanman.share.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Comment", HFILL }},
- }
+ { &hf_share_permissions,
+ { "Share Permissions", "lanman.share.permissions", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Permissions on share", HFILL }},
- if (tree) {
-
- proto_tree_add_text(server, NullTVB, loc_offset, 16, "Server Name: %s", Server);
+ { &hf_share_max_uses,
+ { "Share Max Uses", "lanman.share.max_uses", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Max connections allowed to share", HFILL }},
- }
+ { &hf_share_current_uses,
+ { "Share Current Uses", "lanman.share.current_uses", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Current connections to share", HFILL }},
- loc_offset += 16;
+ { &hf_server_name,
+ { "Server Name", "lanman.server.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Server", HFILL }},
- if (smb_info->request_val -> last_level) { /* Print out the rest of the info */
+ { &hf_server_major,
+ { "Major Version", "lanman.server.major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Major Version", HFILL }},
- ServerMajor = GBYTE(pd, loc_offset);
+ { &hf_server_minor,
+ { "Minor Version", "lanman.server.minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Minor Version", HFILL }},
- if (tree) {
+ { &hf_server_comment,
+ { "Server Comment", "lanman.server.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Server Comment", HFILL }},
- proto_tree_add_text(server, NullTVB, loc_offset, 1, "Major Version: %u", ServerMajor);
+ { &hf_abytes,
+ { "Available Bytes", "lanman.available_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Bytes", HFILL }},
- }
+ { &hf_current_time,
+ { "Current Date/Time", "lanman.current_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Current date and time, in seconds since 00:00:00, January 1, 1970", HFILL }},
- loc_offset += 1;
+ { &hf_msecs,
+ { "Milliseconds", "lanman.msecs", FT_UINT32, BASE_DEC,
+ NULL, 0, "LANMAN Milliseconds since arbitrary time in the past (typically boot time)", HFILL }},
- ServerMinor = GBYTE(pd, loc_offset);
+ { &hf_hour,
+ { "Hour", "lanman.hour", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current hour", HFILL }},
- if (tree) {
+ { &hf_minute,
+ { "Minute", "lanman.minute", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current minute", HFILL }},
- proto_tree_add_text(server, NullTVB, loc_offset, 1, "Minor Version: %u", ServerMinor);
+ { &hf_second,
+ { "Second", "lanman.second", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current second", HFILL }},
- }
+ { &hf_hundredths,
+ { "Hundredths of a second", "lanman.hundredths", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current hundredths of a second", HFILL }},
- loc_offset += 1;
+ { &hf_tzoffset,
+ { "Time Zone Offset", "lanman.tzoffset", FT_INT16, BASE_DEC,
+ NULL, 0, "LANMAN Offset of time zone from GMT, in minutes", HFILL }},
- ServerFlags = GWORD(pd, loc_offset);
+ { &hf_timeinterval,
+ { "Time Interval", "lanman.timeinterval", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN .0001 second units per clock tick", HFILL }},
- if (tree) {
+ { &hf_day,
+ { "Day", "lanman.day", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current day", HFILL }},
- ti = proto_tree_add_text(server, NullTVB, loc_offset, 4, "Server Type: 0x%08X", ServerFlags);
- flags_tree = proto_item_add_subtree(ti, ett_lanman_flags);
- dissect_server_flags(flags_tree, loc_offset, 4, ServerFlags);
+ { &hf_month,
+ { "Month", "lanman.month", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current month", HFILL }},
- }
+ { &hf_year,
+ { "Year", "lanman.year", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Current year", HFILL }},
- loc_offset += 4;
+ { &hf_weekday,
+ { "Weekday", "lanman.weekday", FT_UINT8, BASE_DEC,
+ VALS(weekday_vals), 0, "LANMAN Current day of the week", HFILL }},
- /* XXX - should check whether all of the string is within the
- frame. */
- string_offset = SMB_offset + DataOffset + (GWORD(pd, loc_offset) & 0xFFFF) - Convert;
- if (IS_DATA_IN_FRAME(string_offset))
- Comment = pd + string_offset;
- else
- Comment = "<String goes past end of frame>";
+ { &hf_computer_name,
+ { "Computer Name", "lanman.computer_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Computer Name", HFILL }},
- if (tree) {
+ { &hf_user_name,
+ { "User Name", "lanman.user_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN User Name", HFILL }},
- proto_tree_add_text(server, NullTVB, loc_offset, 4, "Server Comment: %s", Comment);
+ { &hf_workstation_domain,
+ { "Workstation Domain", "lanman.workstation_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstation Domain", HFILL }},
- }
+ { &hf_workstation_major,
+ { "Workstation Major Version", "lanman.workstation_major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Workstation Major Version", HFILL }},
- loc_offset += 4;
+ { &hf_workstation_minor,
+ { "Workstation Minor Version", "lanman.workstation_minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Workstation Minor Version", HFILL }},
- }
+ { &hf_logon_domain,
+ { "Logon Domain", "lanman.logon_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Logon Domain", HFILL }},
- }
+ { &hf_other_domains,
+ { "Other Domains", "lanman.other_domains", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Other Domains", HFILL }},
- break;
+ { &hf_password,
+ { "Password", "lanman.password", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Password", HFILL }},
- default:
+ { &hf_workstation_name,
+ { "Workstation Name", "lanman.workstation_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstation Name", HFILL }},
- Status = GSHORT(pd, loc_offset);
+ { &hf_ustruct_size,
+ { "Length of UStruct", "lanman.ustruct_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN UStruct Length", HFILL }},
- if (tree) {
+ { &hf_logon_code,
+ { "Logon Code", "lanman.logon_code", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Logon Code", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Status: %u", Status);
+ { &hf_privilege_level,
+ { "Privilege Level", "lanman.privilege_level", FT_UINT16, BASE_DEC,
+ VALS(privilege_vals), 0, "LANMAN Privilege Level", HFILL }},
- }
+ { &hf_operator_privileges,
+ { "Operator Privileges", "lanman.operator_privileges", FT_UINT32, BASE_DEC,
+ VALS(op_privilege_vals), 0, "LANMAN Operator Privileges", HFILL }},
- loc_offset += 2;
+ { &hf_num_logons,
+ { "Number of Logons", "lanman.num_logons", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Logons", HFILL }},
- Convert = GSHORT(pd, loc_offset);
+ { &hf_bad_pw_count,
+ { "Bad Password Count", "lanman.bad_pw_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of incorrect passwords entered since last successful login", HFILL }},
- if (tree) {
+ { &hf_last_logon,
+ { "Last Logon Date/Time", "lanman.last_logon", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time of last logon", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
+ { &hf_last_logoff,
+ { "Last Logoff Date/Time", "lanman.last_logoff", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time of last logoff", HFILL }},
- }
+ { &hf_logoff_time,
+ { "Logoff Date/Time", "lanman.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user should log off", HFILL }},
- loc_offset += 2;
+ { &hf_kickoff_time,
+ { "Kickoff Date/Time", "lanman.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user will be logged off", HFILL }},
- if (tree) {
+ { &hf_password_age,
+ { "Password Age", "lanman.password_age", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Time since user last changed his/her password", HFILL }},
- int i = 0;
- char *name = NULL;
+ { &hf_password_can_change,
+ { "Password Can Change", "lanman.password_can_change", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user can change their password", HFILL }},
- dissect_transact_engine_init(pd, smb_info->request_val -> last_param_descrip, smb_info->request_val -> last_data_descrip, SMB_offset, loc_offset, ParameterCount, DataOffset, DataCount);
+ { &hf_password_must_change,
+ { "Password Must Change", "lanman.password_must_change", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user must change their password", HFILL }},
- if (lanman) name = lanman -> resp[i];
-
- while (dissect_transact_next(pd, name, smb_info->request, lanman_tree))
- if (name) name = lanman -> resp[++i];
-
- }
+ { &hf_script_path,
+ { "Script Path", "lanman.script_path", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Pathname of user's logon script", HFILL }},
- return TRUE;
- break;
+ { &hf_logoff_code,
+ { "Logoff Code", "lanman.logoff_code", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Logoff Code", HFILL }},
- }
+ { &hf_duration,
+ { "Duration of Session", "lanman.duration", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Number of seconds the user was logged on", HFILL }},
- }
+ { &hf_user_comment,
+ { "User Comment", "lanman.user_comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN User Comment", HFILL }},
- return FALSE;
+ { &hf_full_name,
+ { "Full Name", "lanman.full_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Full Name", HFILL }},
-}
+ { &hf_homedir,
+ { "Home Directory", "lanman.homedir", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Home Directory", HFILL }},
-gboolean
-dissect_pipe_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, int max_data, int SMB_offset, int errcode, const u_char *command, int DataOffset, int DataCount, int ParameterOffset, int ParameterCount)
-{
+ { &hf_parameters,
+ { "Parameters", "lanman.parameters", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameters", HFILL }},
- if (!proto_is_protocol_enabled(proto_smb_lanman))
- return FALSE;
+ { &hf_logon_server,
+ { "Logon Server", "lanman.logon_server", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Logon Server", HFILL }},
- if (command != NULL && strcmp(command, "LANMAN") == 0) {
- /* Try to decode a LANMAN */
+ { &hf_country_code,
+ { "Country Code", "lanman.country_code", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Country Code", HFILL }},
- return dissect_pipe_lanman(pd, offset, fd, parent, tree, max_data,
- SMB_offset, errcode, command, DataOffset,
- DataCount, ParameterOffset, ParameterCount);
+ { &hf_workstations,
+ { "Workstations", "lanman.workstations", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstations", HFILL }},
- }
+ { &hf_max_storage,
+ { "Max Storage", "lanman.max_storage", FT_UINT32, BASE_DEC,
+ NULL, 0, "LANMAN Max Storage", HFILL }},
- return FALSE;
+ { &hf_units_per_week,
+ { "Units Per Week", "lanman.units_per_week", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Units Per Week", HFILL }},
-}
+ { &hf_logon_hours,
+ { "Logon Hours", "lanman.logon_hours", FT_BYTES, BASE_NONE,
+ NULL, 0, "LANMAN Logon Hours", HFILL }},
-static void
-pipe_lanman_init_protocol(void)
-{
- if (lanman_proto_data != NULL)
- g_mem_chunk_destroy(lanman_proto_data);
+ { &hf_code_page,
+ { "Code Page", "lanman.code_page", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Code Page", HFILL }},
- lanman_proto_data = g_mem_chunk_new("lanman_proto_data",
- sizeof(response_data),
- 100 * sizeof(response_data),
- G_ALLOC_AND_FREE);
-}
+ { &hf_new_password,
+ { "New Password", "lanman.new_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "LANMAN New Password (encrypted)", HFILL }},
-void
-register_proto_smb_pipe( void){
+ { &hf_old_password,
+ { "Old Password", "lanman.old_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "LANMAN Old Password (encrypted)", HFILL }},
+ };
static gint *ett[] = {
@@ -1189,13 +1835,12 @@ register_proto_smb_pipe( void){
&ett_lanman_server,
&ett_lanman_shares,
&ett_lanman_share,
- &ett_lanman_flags
};
proto_smb_lanman = proto_register_protocol(
"Microsoft Windows Lanman Protocol", "LANMAN", "lanman");
+ proto_register_field_array(proto_smb_lanman, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- register_init_routine(&pipe_lanman_init_protocol);
}