2003-03-25 09:41:42 +00:00
/* packet-smb-sidsnooping.c
* Routines for snooping SID to name mappings
* Copyright 2003 , Ronnie Sahlberg
*
2003-03-25 19:52:56 +00:00
* $ Id : packet - smb - sidsnooping . c , v 1.2 2003 / 03 / 25 19 : 52 : 56 guy Exp $
2003-03-25 09:41:42 +00:00
*
* Ethereal - Network traffic analyzer
* By Gerald Combs < gerald @ ethereal . com >
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <string.h>
# include "epan/packet_info.h"
# include "epan/epan_dissect.h"
# include "epan/proto.h"
# include "tap.h"
# include "packet-dcerpc.h"
# include "register.h"
# include "smb.h"
# include "packet-smb-sidsnooping.h"
static int hf_lsa = - 1 ;
static int hf_lsa_opnum = - 1 ;
static int hf_lsa_domain = - 1 ;
static int hf_smb_sid = - 1 ;
static GHashTable * sid_name_table = NULL ;
typedef struct _sid_name {
char * sid ;
char * name ;
} sid_name ;
static GMemChunk * sid_name_chunk = NULL ;
static int sid_name_init_count = 200 ;
static void * lsa_QueryInfoPolicy_l3_reply_flag = NULL ;
char *
find_sid_name ( char * sid )
{
sid_name * sn ;
sid_name old_sn ;
old_sn . sid = sid ;
sn = g_hash_table_lookup ( sid_name_table , & old_sn ) ;
if ( ! sn ) {
return NULL ;
}
return sn - > name ;
}
static void
add_sid_name_mapping ( char * sid , char * name )
{
sid_name * sn ;
sid_name old_sn ;
old_sn . sid = sid ;
sn = g_hash_table_lookup ( sid_name_table , & old_sn ) ;
if ( sn ) {
return ;
}
sn = g_mem_chunk_alloc ( sid_name_chunk ) ;
sn - > sid = g_strdup ( sid ) ;
sn - > name = g_strdup ( name ) ;
g_hash_table_insert ( sid_name_table , sn , sn ) ;
}
/*
* QueryInfoPolicy level 3 contains both a domain name and a sid
* which we can use to map a sid into a name .
*/
static int
lsa_QueryInfoPolicy_l3_reply ( void * dummy _U_ , packet_info * pinfo _U_ , epan_dissect_t * edt , void * pri _U_ )
{
/* dcerpc_info *ri=pri;*/
GPtrArray * gp_sid ;
GPtrArray * gp_domain ;
field_info * fi ;
char * domain ;
char * sid ;
gp_domain = proto_get_finfo_ptr_array ( edt - > tree , hf_lsa_domain ) ;
if ( ! gp_domain | | gp_domain - > len ! = 1 ) {
return 0 ;
}
fi = gp_domain - > pdata [ 0 ] ;
domain = fi - > value - > value . string ;
gp_sid = proto_get_finfo_ptr_array ( edt - > tree , hf_smb_sid ) ;
if ( ! gp_sid | | gp_sid - > len ! = 1 ) {
return 0 ;
}
fi = gp_sid - > pdata [ 0 ] ;
sid = fi - > value - > value . string ;
add_sid_name_mapping ( sid , domain ) ;
2003-03-25 19:52:56 +00:00
return 0 ;
2003-03-25 09:41:42 +00:00
}
static gboolean
free_all_sid_names ( gpointer key_arg , gpointer value _U_ , gpointer user_data _U_ )
{
sid_name * sn = ( sid_name * ) key_arg ;
if ( sn - > sid ) {
g_free ( ( gpointer ) sn - > sid ) ;
sn - > sid = NULL ;
}
if ( sn - > name ) {
g_free ( ( gpointer ) sn - > name ) ;
sn - > name = NULL ;
}
return TRUE ;
}
static gint
sid_name_equal ( gconstpointer k1 , gconstpointer k2 )
{
const sid_name * sn1 = ( const sid_name * ) k1 ;
const sid_name * sn2 = ( const sid_name * ) k2 ;
return ! strcmp ( sn1 - > sid , sn2 - > sid ) ;
}
static guint
sid_name_hash ( gconstpointer k )
{
const sid_name * sn = ( const sid_name * ) k ;
int i , sum ;
for ( sum = 0 , i = strlen ( sn - > sid ) - 1 ; i > = 0 ; i - - ) {
sum + = sn - > sid [ i ] ;
}
return sum ;
}
static void
sid_snooping_init ( void )
{
header_field_info * hfi ;
if ( lsa_QueryInfoPolicy_l3_reply_flag ) {
remove_tap_listener ( lsa_QueryInfoPolicy_l3_reply_flag ) ;
lsa_QueryInfoPolicy_l3_reply_flag = NULL ;
}
if ( sid_name_table ) {
g_hash_table_foreach_remove ( sid_name_table , free_all_sid_names , NULL ) ;
sid_name_table = NULL ;
}
if ( sid_name_chunk ) {
g_mem_chunk_destroy ( sid_name_chunk ) ;
sid_name_chunk = NULL ;
}
if ( ! sid_name_snooping ) {
return ;
}
sid_name_table = g_hash_table_new ( sid_name_hash , sid_name_equal ) ;
sid_name_chunk = g_mem_chunk_new ( " sid_name_chunk " ,
sizeof ( sid_name ) ,
sid_name_init_count * sizeof ( sid_name ) ,
G_ALLOC_ONLY ) ;
hf_lsa = proto_get_id_by_filter_name ( " lsa " ) ;
hfi = proto_registrar_get_byname ( " lsa.opnum " ) ;
if ( hfi ) {
hf_lsa_opnum = hfi - > id ;
}
hfi = proto_registrar_get_byname ( " smb.sid " ) ;
if ( hfi ) {
hf_smb_sid = hfi - > id ;
}
hfi = proto_registrar_get_byname ( " lsa.domain " ) ;
if ( hfi ) {
hf_lsa_domain = hfi - > id ;
}
if ( register_tap_listener ( " dcerpc " , lsa_QueryInfoPolicy_l3_reply , " dcerpc.pkt_type==2 and lsa.opnum==7 and lsa.info.level==3 and lsa.domain and smb.sid " , NULL , lsa_QueryInfoPolicy_l3_reply , NULL ) ) {
/* error, we failed to attach to the tap. clean up */
fprintf ( stderr , " tethereal: proto_reg_handoff_smb_sidsnooping()/lsa_QueryInfoPolicy_l3_reply failed to attach to tap. \n " ) ;
exit ( 1 ) ;
}
lsa_QueryInfoPolicy_l3_reply_flag = lsa_QueryInfoPolicy_l3_reply ;
}
void
proto_register_smb_sidsnooping ( void )
{
register_init_routine ( sid_snooping_init ) ;
}
void
proto_reg_handoff_smb_sidsnooping ( void )
{
}