wireshark/epan/dissectors/packet-smb-sidsnooping.c
Guy Harris 2c44a7f930 Clean up handling of enabled/disabled protocols/heuristic dissectors.
Add a "report a warning message" routine to the "report_err" code in
libwsutil, and rename files and routines appropriately, as they don't
only handle errors any more.

Have a routine read_enabled_and_disabled_protos() that reads all the
files that enable or disable protocols or heuristic dissectors, enables
and disables them based on the contents of those files, and reports
errors itself (as warnings) using the new "report a warning message"
routine.  Fix that error reporting to report separately on the disabled
protocols, enabled protocols, and heuristic dissectors files.

Have a routine to set up the enabled and disabled protocols and
heuristic dissectors from the command-line arguments, so it's done the
same way in all programs.

If we try to enable or disable an unknown heuristic dissector via a
command-line argument, report an error.

Update a bunch of comments.

Update the name of disabled_protos_cleanup(), as it cleans up
information for disabled *and* enabled protocols and for heuristic
dissectors.

Support the command-line flags to enable and disable protocols and
heuristic dissectors in tfshark.

Change-Id: I9b8bd29947cccdf6dc34a0540b5509ef941391df
Reviewed-on: https://code.wireshark.org/review/20966
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2017-04-08 20:40:08 +00:00

360 lines
8.6 KiB
C

/* packet-smb-sidsnooping.c
* Routines for snooping SID to name mappings
* Copyright 2003, Ronnie Sahlberg
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/epan_dissect.h>
#include <epan/tap.h>
#include <wsutil/report_message.h>
#include "packet-dcerpc.h"
#include "packet-dcerpc-nt.h"
#include "packet-smb.h"
#include "packet-smb-sidsnooping.h"
void proto_register_smb_sidsnooping(void);
#if 0
static int hf_lsa = -1;
static int hf_lsa_opnum = -1;
#endif
static int hf_lsa_info_level = -1;
static int hf_lsa_domain = -1;
static int hf_nt_domain_sid = -1;
static int hf_samr_hnd = -1;
static int hf_samr_rid = -1;
static int hf_samr_acct_name = -1;
static int hf_samr_level = -1;
GHashTable *sid_name_table = NULL;
static GHashTable *ctx_handle_table = NULL;
static gboolean lsa_policy_information_tap_installed = FALSE;
static gboolean samr_query_dispinfo_tap_installed = FALSE;
const char *
find_sid_name(const char *sid)
{
return (const char *)g_hash_table_lookup(sid_name_table, sid);
}
static void
add_sid_name_mapping(const char *sid, const char *name)
{
if (find_sid_name(sid)) {
return;
}
g_hash_table_insert(sid_name_table, g_strdup(sid), g_strdup(name));
}
/*
* QueryDispInfo :
* level 1 : user displayinfo 1
*/
static int
samr_query_dispinfo(void *dummy _U_, packet_info *pinfo, epan_dissect_t *edt, const void *pri)
{
const dcerpc_info *ri=(const dcerpc_info *)pri;
void *old_ctx=NULL;
char *pol_name;
char *sid;
int sid_len;
int num_rids;
int num_names;
GPtrArray *gp;
GPtrArray *gp_rids;
GPtrArray *gp_names;
field_info *fi;
field_info *fi_rid;
field_info *fi_name;
char sid_name_str[256];
int info_level;
gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_level);
if(!gp || gp->len!=1){
return 0;
}
fi=(field_info *)gp->pdata[0];
info_level=fi->value.value.sinteger;
if(info_level!=1){
return 0;
}
if(!ri){
return 0;
}
if(!ri->call_data){
return 0;
}
if(ri->ptype == PDU_REQ){
gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_hnd);
if(!gp || gp->len!=1){
return 0;
}
fi=(field_info *)gp->pdata[0];
old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(pinfo->num));
if(old_ctx){
g_hash_table_remove(ctx_handle_table, GINT_TO_POINTER(pinfo->num));
}
if(!old_ctx){
old_ctx=wmem_memdup(wmem_file_scope(), fi->value.value.bytes->data, 20);
}
g_hash_table_insert(ctx_handle_table, GINT_TO_POINTER(pinfo->num), old_ctx);
return 0;
}
if(!ri->call_data->req_frame){
return 0;
}
old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(ri->call_data->req_frame));
if(!old_ctx){
return 0;
}
if (!dcerpc_fetch_polhnd_data((e_ctx_hnd *)old_ctx, &pol_name, NULL, NULL, NULL, ri->call_data->req_frame)) {
return 0;
}
if (!pol_name)
return 0;
sid=strstr(pol_name,"S-1-5");
if(!sid){
return 0;
}
for(sid_len=4;1;sid_len++){
if((sid[sid_len]>='0') && (sid[sid_len]<='9')){
continue;
}
if(sid[sid_len]=='-'){
continue;
}
break;
}
gp_rids=proto_get_finfo_ptr_array(edt->tree, hf_samr_rid);
if(!gp_rids || gp_rids->len<1){
return 0;
}
num_rids=gp_rids->len;
gp_names=proto_get_finfo_ptr_array(edt->tree, hf_samr_acct_name);
if(!gp_names || gp_names->len<1){
return 0;
}
num_names=gp_names->len;
if(num_rids>num_names){
num_rids=num_names;
}
for(;num_rids;num_rids--){
int len=sid_len;
if (len > 247)
len = 247;
fi_rid=(field_info *)gp_rids->pdata[num_rids-1];
fi_name=(field_info *)gp_names->pdata[num_rids-1];
g_strlcpy(sid_name_str, sid, 256);
sid_name_str[len++]='-';
g_snprintf(sid_name_str+len, 256-len, "%d",fi_rid->value.value.sinteger);
add_sid_name_mapping(sid_name_str, fi_name->value.value.string);
}
return 1;
}
/*
* PolicyInformation :
* level 3 : PRIMARY_DOMAIN_INFO lsa.domain_sid -> lsa.domain
* level 5 : ACCOUNT_DOMAIN_INFO lsa.domain_sid -> lsa.domain
* level 12 : DNS_DOMAIN_INFO lsa.domain_sid -> lsa.domain
*/
static int
lsa_policy_information(void *dummy _U_, packet_info *pinfo _U_, epan_dissect_t *edt, const void *pri _U_)
{
GPtrArray *gp;
field_info *fi;
char *domain;
char *sid;
int info_level;
gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_info_level);
if(!gp || gp->len!=1){
return 0;
}
fi=(field_info *)gp->pdata[0];
info_level=fi->value.value.sinteger;
switch(info_level){
case 3:
case 5:
case 12:
gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_domain);
if(!gp || gp->len!=1){
return 0;
}
fi=(field_info *)gp->pdata[0];
domain=fi->value.value.string;
gp=proto_get_finfo_ptr_array(edt->tree, hf_nt_domain_sid);
if(!gp || gp->len!=1){
return 0;
}
fi=(field_info *)gp->pdata[0];
sid=fi->value.value.string;
add_sid_name_mapping(sid, domain);
break;
}
return 0;
}
static gint
ctx_handle_equal(gconstpointer k1, gconstpointer k2)
{
int sn1 = GPOINTER_TO_INT(k1);
int sn2 = GPOINTER_TO_INT(k2);
return sn1==sn2;
}
static guint
ctx_handle_hash(gconstpointer k)
{
int sn = GPOINTER_TO_INT(k);
return sn;
}
static void
sid_snooping_init(void)
{
GString *error_string;
if(lsa_policy_information_tap_installed){
remove_tap_listener(&lsa_policy_information_tap_installed);
lsa_policy_information_tap_installed=FALSE;
}
if(samr_query_dispinfo_tap_installed){
remove_tap_listener(&samr_query_dispinfo_tap_installed);
samr_query_dispinfo_tap_installed=FALSE;
}
sid_name_table = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
ctx_handle_table = g_hash_table_new(ctx_handle_hash, ctx_handle_equal);
/* TODO this code needs to be rewritten from scratch
disabling it now so that it won't cause wireshark to abort due to
unknown hf fields
*/
sid_name_snooping=FALSE;
if(!sid_name_snooping){
return;
}
#if 0
hf_lsa = proto_get_id_by_filter_name("lsa");
hf_lsa_opnum = proto_registrar_get_id_byname("lsa.opnum");
#endif
hf_nt_domain_sid = proto_registrar_get_id_byname("nt.domain_sid");
hf_lsa_domain = proto_registrar_get_id_byname("lsa.domain");
hf_lsa_info_level = proto_registrar_get_id_byname("lsa.info.level");
hf_samr_hnd = proto_registrar_get_id_byname("samr.handle");
hf_samr_rid = proto_registrar_get_id_byname("samr.rid");
hf_samr_acct_name = proto_registrar_get_id_byname("samr.acct_name");
hf_samr_level = proto_registrar_get_id_byname("samr.level");
error_string=register_tap_listener("dcerpc",
&lsa_policy_information_tap_installed,
"lsa.policy_information and ( lsa.info.level or lsa.domain or nt.domain_sid )",
TL_REQUIRES_PROTO_TREE, NULL, lsa_policy_information, NULL);
if(error_string){
/* error, we failed to attach to the tap. clean up */
report_failure( "Couldn't register proto_reg_handoff_smb_sidsnooping()/lsa_policy_information tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
return;
}
lsa_policy_information_tap_installed=TRUE;
error_string=register_tap_listener("dcerpc",
&samr_query_dispinfo_tap_installed,
"samr and samr.opnum==40 and ( samr.handle or samr.rid or samr.acct_name or samr.level )",
TL_REQUIRES_PROTO_TREE, NULL, samr_query_dispinfo, NULL);
if(error_string){
/* error, we failed to attach to the tap. clean up */
report_failure( "Couldn't register proto_reg_handoff_smb_sidsnooping()/samr_query_dispinfo tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
return;
}
samr_query_dispinfo_tap_installed=TRUE;
}
static void
sid_snooping_cleanup(void)
{
g_hash_table_destroy(sid_name_table);
g_hash_table_destroy(ctx_handle_table);
}
void
proto_register_smb_sidsnooping(void)
{
register_init_routine(sid_snooping_init);
register_cleanup_routine(sid_snooping_cleanup);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/