From bb68761a500fc5d426c75e53700fa793e016135f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 14 Oct 2005 16:07:00 +0000 Subject: r11060: merging new eventlog code from trunk (This used to be commit 1bcf7e82ede63a851a244162a3b939373787b693) --- source3/rpc_server/srv_eventlog_lib.c | 348 ++++++++++++------- source3/rpc_server/srv_eventlog_nt.c | 628 +++++++++++++--------------------- 2 files changed, 469 insertions(+), 507 deletions(-) (limited to 'source3/rpc_server') diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/rpc_server/srv_eventlog_lib.c index 3b7a32dac2..495ad8e58c 100644 --- a/source3/rpc_server/srv_eventlog_lib.c +++ b/source3/rpc_server/srv_eventlog_lib.c @@ -1,8 +1,8 @@ - /* * Unix SMB/CIFS implementation. * Eventlog utility routines * Copyright (C) Marcin Krzysztof Porwit 2005, + * Copyright (C) Brian Moran 2005. * Copyright (C) Gerald (Jerry) Carter 2005. * * This program is free software; you can redistribute it and/or modify @@ -22,117 +22,132 @@ #include "includes.h" +/* maintain a list of open eventlog tdbs with reference counts */ -/**************************************************************** -Init an Eventlog TDB, and return it. If null, something bad happened. -****************************************************************/ -TDB_CONTEXT *init_eventlog_tdb( char *tdbfilename ) -{ - TDB_CONTEXT *the_tdb; - - unlink( tdbfilename ); +struct elog_open_tdb { + struct elog_open_tdb *prev, *next; + char *name; + TDB_CONTEXT *tdb; + int ref_count; +}; - the_tdb = - tdb_open_log( tdbfilename, 0, TDB_DEFAULT, O_RDWR | O_CREAT, - 0664 ); - if ( the_tdb == NULL ) { - DEBUG( 1, ( "Can't open tdb for [%s]\n", tdbfilename ) ); - return NULL; - } - tdb_store_int32( the_tdb, VN_oldest_entry, 1 ); - tdb_store_int32( the_tdb, VN_next_record, 1 ); +static struct elog_open_tdb *open_elog_list; - /* initialize with defaults, copy real values in here from registry */ - - tdb_store_int32( the_tdb, VN_maxsize, 0x80000 ); - tdb_store_int32( the_tdb, VN_retention, 0x93A80 ); - - tdb_store_int32( the_tdb, VN_version, EVENTLOG_DATABASE_VERSION_V1 ); - return the_tdb; -} +/******************************************************************** + Init an Eventlog TDB, and return it. If null, something bad + happened. +********************************************************************/ -/* make the tdb file name for an event log, given destination buffer and size */ -char *mk_tdbfilename( char *dest_buffer, char *eventlog_name, int size_dest ) +TDB_CONTEXT *elog_init_tdb( char *tdbfilename ) { - pstring ondisk_name; - - if ( !dest_buffer ) - return NULL; + TDB_CONTEXT *tdb; - pstrcpy( ondisk_name, "EV" ); - pstrcat( ondisk_name, eventlog_name ); - pstrcat( ondisk_name, ".tdb" ); + DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n", + tdbfilename)); - memset( dest_buffer, 0, size_dest ); + tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT, + O_RDWR|O_CREAT|O_TRUNC, 0600 ); - /* BAD things could happen if the dest_buffer is not large enough... */ - if ( strlen( ondisk_name ) > size_dest ) { - DEBUG( 3, ( "Buffer not big enough for filename\n" ) ); + if ( !tdb ) { + DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) ); return NULL; } - strncpy( dest_buffer, ondisk_name, size_dest ); + /* initialize with defaults, copy real values in here from registry */ + + tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 ); + tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 ); + tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 ); + tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 ); + + tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 ); - return dest_buffer; + return tdb; } +/******************************************************************** + make the tdb file name for an event log, given destination buffer + and size. Caller must free memory. +********************************************************************/ -/* count the number of bytes in the TDB */ +char *elog_tdbname( const char *name ) +{ + fstring path; + char *tdb_fullpath; + char *eventlogdir = lock_path( "eventlog" ); + + pstr_sprintf( path, "%s/%s.tdb", eventlogdir, name ); + strlower_m( path ); + tdb_fullpath = SMB_STRDUP( path ); + + return tdb_fullpath; +} -/* Arg! Static Globals! */ -static int eventlog_tdbcount; -static int eventlog_tdbsize; +/******************************************************************** + this function is used to count up the number of bytes in a + particular TDB +********************************************************************/ + +struct trav_size_struct { + int size; + int rec_count; +}; -/* this function is used to count up the number of bytes in a particular TDB */ -int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, +static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, void *state ) { - eventlog_tdbsize += data.dsize; - eventlog_tdbcount++; + struct trav_size_struct *tsize = state; + + tsize->size += data.dsize; + tsize->rec_count++; + return 0; } -/* returns the size of the eventlog, and if MaxSize is a non-null ptr, puts - the MaxSize there. This is purely a way not to have yet another function that solely - reads the maxsize of the eventlog. Yeah, that's it. */ +/******************************************************************** + returns the size of the eventlog, and if MaxSize is a non-null + ptr, puts the MaxSize there. This is purely a way not to have yet + another function that solely reads the maxsize of the eventlog. + Yeah, that's it. +********************************************************************/ -int eventlog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention ) +int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention ) { + struct trav_size_struct tsize; + if ( !tdb ) return 0; - eventlog_tdbcount = 0; - eventlog_tdbsize = 0; + + ZERO_STRUCT( tsize ); - tdb_traverse( tdb, eventlog_tdb_size_fn, NULL ); + tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize ); if ( MaxSize != NULL ) { - *MaxSize = tdb_fetch_int32( tdb, VN_maxsize ); + *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE ); } if ( Retention != NULL ) { - *Retention = tdb_fetch_int32( tdb, VN_retention ); + *Retention = tdb_fetch_int32( tdb, EVT_RETENTION ); } DEBUG( 1, - ( "eventlog size: [%d] for [%d] records\n", eventlog_tdbsize, - eventlog_tdbcount ) ); - return eventlog_tdbsize; + ( "eventlog size: [%d] for [%d] records\n", tsize.size, + tsize.rec_count ) ); + return tsize.size; } - -/* - Discard early event logs until we have enough for 'needed' bytes... - NO checking done beforehand to see that we actually need to do this, and - it's going to pluck records one-by-one. So, it's best to determine that this - needs to be done before doing it. - - Setting whack_by_date to True indicates that eventlogs falling outside of the - retention range need to go... - -*/ - -/* return True if we made enough room to accommodate needed bytes */ +/******************************************************************** + Discard early event logs until we have enough for 'needed' bytes... + NO checking done beforehand to see that we actually need to do + this, and it's going to pluck records one-by-one. So, it's best + to determine that this needs to be done before doing it. + + Setting whack_by_date to True indicates that eventlogs falling + outside of the retention range need to go... + + return True if we made enough room to accommodate needed bytes +********************************************************************/ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed, BOOL whack_by_date ) @@ -140,12 +155,9 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed, int start_record, i, new_start; int end_record; int nbytes, reclen, len, Retention, MaxSize; - int tresv1, trecnum, timegen, timewr; - TDB_DATA key, ret; TALLOC_CTX *mem_ctx = NULL; - time_t current_time, exp_time; /* discard some eventlogs */ @@ -158,12 +170,12 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed, if ( mem_ctx == NULL ) return False; /* can't allocate memory indicates bigger problems */ /* lock */ - tdb_lock_bystring( the_tdb, VN_next_record, 1 ); + tdb_lock_bystring( the_tdb, EVT_NEXT_RECORD, 1 ); /* read */ - end_record = tdb_fetch_int32( the_tdb, VN_next_record ); - start_record = tdb_fetch_int32( the_tdb, VN_oldest_entry ); - Retention = tdb_fetch_int32( the_tdb, VN_retention ); - MaxSize = tdb_fetch_int32( the_tdb, VN_maxsize ); + end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD ); + start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY ); + Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION ); + MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE ); time( ¤t_time ); @@ -189,7 +201,7 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed, DEBUG( 8, ( "Can't find a record for the key, record [%d]\n", i ) ); - tdb_unlock_bystring( the_tdb, VN_next_record ); + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); return False; } nbytes += ret.dsize; /* note this includes overhead */ @@ -226,16 +238,16 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed, tdb_delete( the_tdb, key ); } - tdb_store_int32( the_tdb, VN_oldest_entry, new_start ); + tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start ); } - tdb_unlock_bystring( the_tdb, VN_next_record ); + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); return True; } -/* +/******************************************************************** some hygiene for an eventlog - see how big it is, and then calculate how many bytes we need to remove -*/ +********************************************************************/ BOOL prune_eventlog( TDB_CONTEXT * tdb ) { @@ -246,7 +258,7 @@ BOOL prune_eventlog( TDB_CONTEXT * tdb ) return False; } - CalcdSize = eventlog_tdb_size( tdb, &MaxSize, &Retention ); + CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention ); DEBUG( 3, ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize, MaxSize ) ); @@ -259,6 +271,9 @@ BOOL prune_eventlog( TDB_CONTEXT * tdb ) return make_way_for_eventlogs( tdb, 0, True ); } +/******************************************************************** +********************************************************************/ + BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed ) { int calcd_size; @@ -274,7 +289,7 @@ BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed ) MaxSize = 0; Retention = 0; - calcd_size = eventlog_tdb_size( tdb, &MaxSize, &Retention ); + calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention ); if ( calcd_size <= MaxSize ) return True; /* you betcha */ @@ -299,28 +314,128 @@ BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed ) return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False ); } -TDB_CONTEXT *open_eventlog_tdb( char *tdbfilename ) +/******************************************************************* +*******************************************************************/ + +TDB_CONTEXT *elog_open_tdb( char *logname ) { - TDB_CONTEXT *the_tdb; + TDB_CONTEXT *tdb; + uint32 vers_id; + struct elog_open_tdb *ptr; + char *tdbfilename; + pstring tdbpath; + struct elog_open_tdb *tdb_node; + char *eventlogdir; + + /* first see if we have an open context */ + + for ( ptr=open_elog_list; ptr; ptr=ptr->next ) { + if ( strequal( ptr->name, logname ) ) { + ptr->ref_count++; + return ptr->tdb; + } + } + + /* make sure that the eventlog dir exists */ + + eventlogdir = lock_path( "eventlog" ); + if ( !directory_exist( eventlogdir, NULL ) ) + mkdir( eventlogdir, 0755 ); + + /* get the path on disk */ + + tdbfilename = elog_tdbname( logname ); + pstrcpy( tdbpath, tdbfilename ); + SAFE_FREE( tdbfilename ); + + DEBUG(7,("elog_open_tdb: Opening %s...\n", tdbpath )); + + tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 ); + if ( tdb ) { + vers_id = tdb_fetch_int32( tdb, EVT_VERSION ); + + if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) { + DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n", + vers_id, tdbpath)); + tdb_close( tdb ); + tdb = elog_init_tdb( tdbpath ); + } + } + else { + tdb = elog_init_tdb( tdbpath ); + } + + /* if we got a valid context, then add it to the list */ + + if ( tdb ) { + if ( !(tdb_node = TALLOC_ZERO_P( NULL, struct elog_open_tdb )) ) { + DEBUG(0,("elog_open_tdb: talloc() failure!\n")); + tdb_close( tdb ); + return NULL; + } + + tdb_node->name = talloc_strdup( tdb_node, logname ); + tdb_node->tdb = tdb; + tdb_node->ref_count = 1; + + DLIST_ADD( open_elog_list, tdb_node ); + } + + return tdb; +} + +/******************************************************************* + Wrapper to handle reference counts to the tdb +*******************************************************************/ - the_tdb = - tdb_open_log( tdbfilename, 0, TDB_DEFAULT, O_RDONLY,0664 ); - if ( the_tdb == NULL ) { - return init_eventlog_tdb( tdbfilename ); +int elog_close_tdb( TDB_CONTEXT *tdb ) +{ + struct elog_open_tdb *ptr; + + if ( !tdb ) + return 0; + + /* See if we can just decrement the ref_count. + Just compare pointer values (not names ) */ + + for ( ptr=open_elog_list; ptr; ptr=ptr->next ) { + if ( tdb == ptr->tdb ) { + ptr->ref_count--; + break; + } } - if ( EVENTLOG_DATABASE_VERSION_V1 != - tdb_fetch_int32( the_tdb, VN_version ) ) { - tdb_close( the_tdb ); - return init_eventlog_tdb( tdbfilename ); + + /* if we have a NULL pointer; it means we are trying to + close a tdb not in the list of open eventlogs */ + + SMB_ASSERT( ptr != NULL ); + if ( !ptr ) + return tdb_close( tdb ); + + SMB_ASSERT( ptr->ref_count >= 0 ); + + if ( ptr->ref_count == 0 ) { + DLIST_REMOVE( open_elog_list, ptr ); + TALLOC_FREE( ptr ); + return tdb_close( tdb ); } - return the_tdb; + + return 0; } -/* write an eventlog entry. Note that we have to lock, read next eventlog, increment, write, write the record, unlock */ -/* coming into this, ee has the eventlog record, and the auxilliary date (computer name, etc.) - filled into the other structure. Before packing into a record, this routine will calc the - appropriate padding, etc., and then blast out the record in a form that can be read back in */ +/******************************************************************* + write an eventlog entry. Note that we have to lock, read next + eventlog, increment, write, write the record, unlock + + coming into this, ee has the eventlog record, and the auxilliary date + (computer name, etc.) filled into the other structure. Before packing + into a record, this routine will calc the appropriate padding, etc., + and then blast out the record in a form that can be read back in +*******************************************************************/ + +#define MARGIN 512 + int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ) { int32 next_record; @@ -343,8 +458,6 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ) if ( ee->record.time_generated == 0 ) return 0; -#define MARGIN 512 - /* todo - check for sanity in next_record */ fixup_eventlog_entry( ee ); @@ -365,9 +478,9 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ) /* need to read the record number and insert it into the entry here */ /* lock */ - tdb_lock_bystring( the_tdb, VN_next_record, 1 ); + tdb_lock_bystring( the_tdb, EVT_NEXT_RECORD, 1 ); /* read */ - next_record = tdb_fetch_int32( the_tdb, VN_next_record ); + next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD ); n_packed = tdb_pack( packed_ee, ee->record.length + MARGIN, @@ -406,18 +519,20 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ) if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) { /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */ - tdb_unlock_bystring( the_tdb, VN_next_record ); + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); talloc_destroy( mem_ctx ); return 0; } next_record++; - tdb_store_int32( the_tdb, VN_next_record, next_record ); - tdb_unlock_bystring( the_tdb, VN_next_record ); + tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record ); + tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); talloc_destroy( mem_ctx ); return ( next_record - 1 ); } -/* calculate the correct fields etc for an eventlog entry */ +/******************************************************************* + calculate the correct fields etc for an eventlog entry +*******************************************************************/ void fixup_eventlog_entry( Eventlog_entry * ee ) { @@ -453,10 +568,11 @@ void fixup_eventlog_entry( Eventlog_entry * ee ) } /******************************************************************** -Note that it's a pretty good idea to initialize the Eventlog_entry structure to zero's before -calling parse_logentry on an batch of lines that may resolve to a record. -ALSO, it's a good idea to remove any linefeeds (that's EOL to you and me) on the lines going in. - + Note that it's a pretty good idea to initialize the Eventlog_entry + structure to zero's before calling parse_logentry on an batch of + lines that may resolve to a record. ALSO, it's a good idea to + remove any linefeeds (that's EOL to you and me) on the lines + going in. ********************************************************************/ BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor ) diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c index d3b350f233..577ec48482 100644 --- a/source3/rpc_server/srv_eventlog_nt.c +++ b/source3/rpc_server/srv_eventlog_nt.c @@ -25,192 +25,201 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV - -typedef struct { - pstring logname; /* rather than alloc on the fly what we need... (memory is cheap now) */ - pstring tdbfname; - TDB_CONTEXT *log_tdb; /* the pointer to the TDB_CONTEXT */ -} EventlogTDBInfo; - -static int nlogs; -static EventlogTDBInfo *ttdb = NULL; -static TALLOC_CTX *mem_ctx = NULL; - typedef struct { char *logname; - char *servername; + TDB_CONTEXT *tdb; uint32 num_records; uint32 oldest_entry; uint32 flags; -} EventlogInfo; + uint32 access_granted; +} EVENTLOG_INFO; +/******************************************************************** + ********************************************************************/ +static void free_eventlog_info( void *ptr ) +{ + EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr; + + if ( elog->tdb ) + elog_close_tdb( elog->tdb ); + + TALLOC_FREE( elog ); +} -#if 0 /* UNUSED */ /******************************************************************** ********************************************************************/ - -void test_eventlog_tdb( TDB_CONTEXT * the_tdb ) + +static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p, + POLICY_HND * handle ) { - Eventlog_entry ee; - - int i = 0; - - memset( &ee, 0, sizeof( Eventlog_entry ) ); - - if ( !the_tdb ) - return; - - for ( i = 0; i < 100; i++ ) { - ee.record.length = sizeof( ee.record ); - memset( &ee.data_record, 0, sizeof( ee.data_record ) ); - ee.record.reserved1 = 0xBEEFDEAD; - ee.record.record_number = 1000 - i; /* should get substituted */ - ee.record.time_generated = 0; - ee.record.time_written = 0; - ee.record.event_id = 500; - ee.record.event_type = 300; - ee.record.num_strings = 0; - ee.record.event_category = 0; - ee.record.reserved2 = ( i << 8 ) | i; - ee.record.closing_record_number = -1; - ee.record.string_offset = 0; - ee.record.user_sid_length = 0; - ee.record.user_sid_offset = 0; - ee.record.data_length = 0; - ee.record.data_offset = 0; - - rpcstr_push( ( void * ) ( ee.data_record.source_name ), - "SystemLog", - sizeof( ee.data_record.source_name ), - STR_TERMINATE ); - ee.data_record.source_name_len = - ( strlen_w( ee.data_record.source_name ) * 2 ) + 2; - - rpcstr_push( ( void * ) ( ee.data_record.computer_name ), - "DMLINUX", - sizeof( ee.data_record.computer_name ), - STR_TERMINATE ); - - ee.data_record.computer_name_len = - ( strlen_w( ee.data_record.computer_name ) * 2 ) + 2; - - write_eventlog_tdb( the_tdb, &ee ); + EVENTLOG_INFO *info; + + if ( !find_policy_by_hnd( p, handle, ( void ** ) &info ) ) { + DEBUG( 2, + ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) ); + return NULL; } + + return info; } -#endif /* UNUSED */ /******************************************************************** - ********************************************************************/ +********************************************************************/ -static void refresh_eventlog_tdb_table( void ) +static BOOL elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token ) { - const char **elogs = lp_eventlog_list( ); - int i, j; + char *tdbname = elog_tdbname( info->logname ); + SEC_DESC *sec_desc; + BOOL ret; + NTSTATUS ntstatus; + + if ( !tdbname ) + return False; + + /* get the security descriptor for the file */ + + sec_desc = get_nt_acl_no_snum( info, tdbname ); + SAFE_FREE( tdbname ); + + if ( !sec_desc ) { + DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n", + tdbname)); + return False; + } + + /* run the check, try for the max allowed */ + + ret = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS, + &info->access_granted, &ntstatus ); + + if ( sec_desc ) + TALLOC_FREE( sec_desc ); + + if ( !ret ) { + DEBUG(8,("elog_check_access: se_access_check() return %s\n", + nt_errstr( ntstatus))); + return False; + } + + /* we have to have READ permission for a successful open */ + + return ( info->access_granted & SA_RIGHT_FILE_READ_DATA ); +} - if ( !elogs ) - return; +/******************************************************************** + ********************************************************************/ - if ( !mem_ctx ) { - mem_ctx = talloc_init( "refresh_eventlog_tdb_table" ); +static BOOL elog_validate_logname( const char *name ) +{ + int i; + const char **elogs = lp_eventlog_list(); + + for ( i=0; elogs[i]; i++ ) { + if ( strequal( name, elogs[i] ) ) + return True; } + + return False; +} - if ( !mem_ctx ) { - DEBUG( 1, ( "Can't allocate memory\n" ) ); - return; - } +/******************************************************************** + ********************************************************************/ - /* count them */ - for ( i = 0; elogs[i]; i++ ) { - } - /* number of logs in i */ - DEBUG( 10, ( "Number of eventlogs %d\n", i ) ); - /* check to see if we need to adjust our tables */ - - if ( ( ttdb != NULL ) ) { - if ( i != nlogs ) { - /* refresh the table, by closing and reconstructing */ - DEBUG( 10, ( "Closing existing table \n" ) ); - for ( j = 0; j < nlogs; j++ ) { - tdb_close( ttdb[j].log_tdb ); - } - TALLOC_FREE( ttdb ); - ttdb = NULL; - } else { /* i == nlogs */ - - for ( j = 0; j < nlogs; j++ ) { - if ( StrCaseCmp( ttdb[j].logname, elogs[i] ) ) { - /* something changed, have to discard */ - DEBUG( 10, - ( "Closing existing table \n" ) ); - for ( j = 0; j < nlogs; j++ ) { - tdb_close( ttdb[j].log_tdb ); - } - TALLOC_FREE( ttdb ); - ttdb = NULL; - break; - } +static WERROR elog_open( pipes_struct * p, const char *logname, POLICY_HND *hnd ) +{ + EVENTLOG_INFO *elog; + + /* first thing is to validate the eventlog name */ + + if ( !elog_validate_logname( logname ) ) + return WERR_OBJECT_PATH_INVALID; + + if ( !(elog = TALLOC_ZERO_P( NULL, EVENTLOG_INFO )) ) + return WERR_NOMEM; + + elog->logname = talloc_strdup( elog, logname ); + + /* Open the tdb first (so that we can create any new tdbs if necessary). + We have to do this as root and then use an internal access check + on the file permissions since you can only have a tdb open once + in a single process */ + + become_root(); + elog->tdb = elog_open_tdb( elog->logname ); + unbecome_root(); + + if ( !elog->tdb ) { + /* according to MSDN, if the logfile cannot be found, we should + default to the "Application" log */ + + if ( !strequal( logname, ELOG_APPL ) ) { + + TALLOC_FREE( elog->logname ); + + elog->logname = talloc_strdup( elog, ELOG_APPL ); + + /* do the access check */ + if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) { + TALLOC_FREE( elog ); + return WERR_ACCESS_DENIED; } + + become_root(); + elog->tdb = elog_open_tdb( elog->logname ); + unbecome_root(); + } + + if ( !elog->tdb ) { + TALLOC_FREE( elog ); + return WERR_ACCESS_DENIED; /* ??? */ } } + + /* now do the access check. Close the tdb if we fail here */ - /* note that this might happen because of above */ - if ( ( i > 0 ) && ( ttdb == NULL ) ) { - /* alloc the room */ - DEBUG( 10, ( "Creating the table\n" ) ); - ttdb = TALLOC( mem_ctx, sizeof( EventlogTDBInfo ) * i ); - if ( !ttdb ) { - DEBUG( 10, - ( "Can't allocate table for tdb handles \n" ) ); - return; - } - for ( j = 0; j < i; j++ ) { - pstrcpy( ttdb[j].tdbfname, - lock_path( mk_tdbfilename - ( ttdb[j].tdbfname, - ( char * ) elogs[j], - sizeof( pstring ) ) ) ); - pstrcpy( ttdb[j].logname, elogs[j] ); - DEBUG( 10, ( "Opening tdb for %s\n", elogs[j] ) ); - ttdb[j].log_tdb = - open_eventlog_tdb( ttdb[j].tdbfname ); - } + if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) { + elog_close_tdb( elog->tdb ); + TALLOC_FREE( elog ); + return WERR_ACCESS_DENIED; + } + + /* create the policy handle */ + + if ( !create_policy_hnd + ( p, hnd, free_eventlog_info, ( void * ) elog ) ) { + free_eventlog_info( elog ); + return WERR_NOMEM; } - nlogs = i; + + return WERR_OK; } /******************************************************************** ********************************************************************/ -TDB_CONTEXT *tdb_of( char *eventlog_name ) +static WERROR elog_close( pipes_struct *p, POLICY_HND *hnd ) { - int i; - - if ( !eventlog_name ) - return NULL; + if ( !( close_policy_hnd( p, hnd ) ) ) { + return WERR_BADFID; + } - if ( !ttdb ) { - DEBUG( 10, ( "Refreshing list of eventlogs\n" ) ); - refresh_eventlog_tdb_table( ); - - if ( !ttdb ) { - DEBUG( 10, - ( "eventlog tdb table is NULL after a refresh!\n" ) ); - return NULL; - } - } + return WERR_OK; +} - DEBUG( 10, ( "Number of eventlogs %d\n", nlogs ) ); +/******************************************************************* + *******************************************************************/ - for ( i = 0; i < nlogs; i++ ) { - if ( strequal( eventlog_name, ttdb[i].logname ) ) - return ttdb[i].log_tdb; +static int elog_size( EVENTLOG_INFO *info ) +{ + if ( !info || !info->tdb ) { + DEBUG(0,("elog_size: Invalid info* structure!\n")); + return 0; } - return NULL; + return elog_tdb_size( info->tdb, NULL, NULL ); } - /******************************************************************** For the given tdb, get the next eventlog record into the passed Eventlog_entry. returns NULL if it can't get the record for some reason. @@ -314,37 +323,12 @@ Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb, return ee; } -/******************************************************************** - ********************************************************************/ - -static void free_eventlog_info( void *ptr ) -{ - TALLOC_FREE( ptr ); -} - -/******************************************************************** - ********************************************************************/ - -static EventlogInfo *find_eventlog_info_by_hnd( pipes_struct * p, - POLICY_HND * handle ) -{ - EventlogInfo *info; - - if ( !find_policy_by_hnd( p, handle, ( void ** ) &info ) ) { - DEBUG( 2, - ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) ); - return NULL; - } - - return info; -} - /******************************************************************** note that this can only be called AFTER the table is constructed, since it uses the table to find the tdb handle ********************************************************************/ -static BOOL sync_eventlog_params( const char *elogname ) +static BOOL sync_eventlog_params( EVENTLOG_INFO *info ) { pstring path; uint32 uiMaxSize; @@ -353,14 +337,12 @@ static BOOL sync_eventlog_params( const char *elogname ) REGISTRY_VALUE *val; REGVAL_CTR *values; WERROR wresult; - TDB_CONTEXT *the_tdb; - - the_tdb = tdb_of( ( char * ) elogname ); + char *elogname = info->logname; DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) ); - if ( !the_tdb ) { - DEBUG( 4, ( "Can't open tdb for %s\n", elogname ) ); + if ( !info->tdb ) { + DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) ); return False; } /* set resonable defaults. 512Kb on size and 1 week on time */ @@ -402,112 +384,52 @@ static BOOL sync_eventlog_params( const char *elogname ) regkey_close_internal( keyinfo ); - tdb_store_int32( the_tdb, VN_maxsize, uiMaxSize ); - tdb_store_int32( the_tdb, VN_retention, uiRetention ); - - return True; -} - -/******************************************************************** - ********************************************************************/ + tdb_store_int32( info->tdb, EVT_MAXSIZE, uiMaxSize ); + tdb_store_int32( info->tdb, EVT_RETENTION, uiRetention ); -static BOOL open_eventlog_hook( EventlogInfo * info ) -{ return True; } /******************************************************************** ********************************************************************/ -/** - * Callout to get the number of records in the specified event log - * - * smbrun calling convention -- - * INPUT: - * OUTPUT: A single line with a single integer containing the number of - * entries in the log. If there are no entries in the log, return 0. - */ - - -static BOOL get_num_records_hook( EventlogInfo * info ) +static BOOL get_num_records_hook( EVENTLOG_INFO * info ) { - - TDB_CONTEXT *the_tdb = NULL; int next_record; int oldest_record; - - the_tdb = tdb_of( info->logname ); - - if ( !the_tdb ) { - DEBUG( 10, ( "Can't find tdb for %s\n", info->logname ) ); - info->num_records = 0; + if ( !info->tdb ) { + DEBUG( 10, ( "No open tdb for %s\n", info->logname ) ); return False; } - /* lock */ - tdb_lock_bystring( the_tdb, VN_next_record, 1 ); - - - /* read */ - next_record = tdb_fetch_int32( the_tdb, VN_next_record ); - oldest_record = tdb_fetch_int32( the_tdb, VN_oldest_entry ); - + /* lock the tdb since we have to get 2 records */ + tdb_lock_bystring( info->tdb, EVT_NEXT_RECORD, 1 ); + next_record = tdb_fetch_int32( info->tdb, EVT_NEXT_RECORD); + oldest_record = tdb_fetch_int32( info->tdb, EVT_OLDEST_ENTRY); + tdb_unlock_bystring( info->tdb, EVT_NEXT_RECORD); DEBUG( 8, - ( "Oldest Record %d Next Record %d\n", oldest_record, + ( "Oldest Record %d; Next Record %d\n", oldest_record, next_record ) ); info->num_records = ( next_record - oldest_record ); info->oldest_entry = oldest_record; - tdb_unlock_bystring( the_tdb, VN_next_record ); - return True; - - } /******************************************************************** ********************************************************************/ -/** - * Callout to find the oldest record in the log - * - * smbrun calling convention -- - * INPUT: - * OUTPUT: If there are entries in the event log, the index of the - * oldest entry. Must be 1 or greater. - * If there are no entries in the log, returns a 0 - */ - -static BOOL get_oldest_entry_hook( EventlogInfo * info ) +static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info ) { /* it's the same thing */ return get_num_records_hook( info ); } - -/******************************************************************** - ********************************************************************/ - -/** - * Callout to close the specified event log - * - * smbrun calling convention -- - * INPUT: - * OUTPUT: the string "SUCCESS" if the command succeeded - * no such string if there was a failure. - */ - -static BOOL close_eventlog_hook( EventlogInfo * info ) -{ - - return True; -} - /******************************************************************** ********************************************************************/ @@ -628,69 +550,6 @@ static BOOL add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u, return True; } -/******************************************************************** - ********************************************************************/ - -/** - * Callout to clear (and optionally backup) a specified event log - * - * smbrun calling convention -- - * INPUT: - * OUTPUT: A single line with the string "SUCCESS" if the command succeeded. - * Otherwise it is assumed to have failed - * - * INPUT: - * OUTPUT: A single line with the string "SUCCESS" if the command succeeded. - * Otherwise it is assumed to have failed - * The given log is copied to that location on the server. See comments for - * eventlog_io_q_clear_eventlog for info about odd file name behavior - */ -static BOOL clear_eventlog_hook( EventlogInfo * info, - pstring backup_file_name ) -{ - - int i; - - - if ( !info ) - return False; - DEBUG( 3, ( "There are %d event logs\n", nlogs ) ); - for ( i = 0; i < nlogs; i++ ) { - DEBUG( 3, - ( "Comparing Eventlog %s, %s\n", info->logname, - ttdb[i].logname ) ); - if ( !StrCaseCmp( info->logname, ttdb[i].logname ) ) { - /* close the current one, reinit */ - tdb_close( ttdb[i].log_tdb ); - DEBUG( 3, - ( "Closing Eventlog %s, file-on-disk %s\n", - info->logname, ttdb[i].tdbfname ) ); - ttdb[i].log_tdb = - init_eventlog_tdb( ttdb[i].tdbfname ); - return True; - } - } - - return False; /* not found */ - /* TODO- do something with the backup file name */ - -} - -/******************************************************************* - *******************************************************************/ - -static int eventlog_size( char *eventlog_name ) -{ - TDB_CONTEXT *tdb; - - if ( !eventlog_name ) - return 0; - tdb = tdb_of( eventlog_name ); - if ( !tdb ) - return 0; - return eventlog_tdb_size( tdb, NULL, NULL ); -} - /******************************************************************** ********************************************************************/ @@ -698,83 +557,81 @@ WERROR _eventlog_open_eventlog( pipes_struct * p, EVENTLOG_Q_OPEN_EVENTLOG * q_u, EVENTLOG_R_OPEN_EVENTLOG * r_u ) { - EventlogInfo *info = NULL; - fstring str; - - if ( !( info = TALLOC_ZERO_P( NULL, EventlogInfo ) ) ) - return WERR_NOMEM; + fstring servername, logname; + EVENTLOG_INFO *info; + WERROR wresult; - fstrcpy( str, global_myname( ) ); + fstrcpy( servername, "" ); if ( q_u->servername.string ) { - rpcstr_pull( str, q_u->servername.string->buffer, - sizeof( str ), + rpcstr_pull( servername, q_u->servername.string->buffer, + sizeof( servername ), q_u->servername.string->uni_str_len * 2, 0 ); } - info->servername = talloc_strdup( info, str ); - - fstrcpy( str, "Application" ); + fstrcpy( logname, "" ); if ( q_u->logname.string ) { - rpcstr_pull( str, q_u->logname.string->buffer, - sizeof( str ), + rpcstr_pull( logname, q_u->logname.string->buffer, + sizeof( logname ), q_u->logname.string->uni_str_len * 2, 0 ); } - - info->logname = talloc_strdup( info, str ); - - DEBUG( 1, - ( "Size of %s is %d\n", info->logname, - eventlog_size( info->logname ) ) ); - - - - DEBUG( 10, - ( "_eventlog_open_eventlog: Using [%s] as the server name.\n", - info->servername ) ); - DEBUG( 10, - ( "_eventlog_open_eventlog: Using [%s] as the source log file.\n", - info->logname ) ); - - - if ( !create_policy_hnd - ( p, &r_u->handle, free_eventlog_info, ( void * ) info ) ) { - free_eventlog_info( info ); - return WERR_NOMEM; + + DEBUG( 10,("_eventlog_open_eventlog: Server [%s], Log [%s]\n", + servername, logname )); + + /* according to MSDN, if the logfile cannot be found, we should + default to the "Application" log */ + + if ( !W_ERROR_IS_OK( wresult = elog_open( p, logname, &r_u->handle )) ) + return wresult; + + if ( !(info = find_eventlog_info_by_hnd( p, &r_u->handle )) ) { + DEBUG(0,("_eventlog_open_eventlog: eventlog (%s) opened but unable to find handle!\n", + logname )); + elog_close( p, &r_u->handle ); + return WERR_BADFID; } - if ( !open_eventlog_hook( info ) ) { - close_policy_hnd( p, &r_u->handle ); - return WERR_BADFILE; - } + DEBUG(10,("_eventlog_open_eventlog: Size [%d]\n", elog_size( info ))); - sync_eventlog_params( info->logname ); - prune_eventlog( tdb_of( info->logname ) ); + sync_eventlog_params( info ); + prune_eventlog( info->tdb ); return WERR_OK; } /******************************************************************** + This call still needs some work ********************************************************************/ WERROR _eventlog_clear_eventlog( pipes_struct * p, EVENTLOG_Q_CLEAR_EVENTLOG * q_u, EVENTLOG_R_CLEAR_EVENTLOG * r_u ) { - EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle ); + EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); pstring backup_file_name; - pstrcpy( backup_file_name, "" ); + if ( !info ) + return WERR_BADFID; - if ( q_u->backupfile.string ) - unistr2_to_ascii( backup_file_name, q_u->backupfile.string, - sizeof( backup_file_name ) ); + pstrcpy( backup_file_name, "" ); + if ( q_u->backupfile.string ) { + rpcstr_pull( backup_file_name, q_u->backupfile.string->buffer, + sizeof( backup_file_name ), + q_u->backupfile.string->uni_str_len * 2, 0 ); + } - DEBUG( 10, + DEBUG( 8, ( "_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].", backup_file_name, info->logname ) ); - if ( !( clear_eventlog_hook( info, backup_file_name ) ) ) - return WERR_BADFILE; +#if 0 + /* close the current one, reinit */ + + tdb_close( info->tdb ); + + if ( !(info->tdb = elog_init_tdb( ttdb[i].tdbfname )) ) + return WERR_ACCESS_DENIED; +#endif return WERR_OK; } @@ -786,16 +643,7 @@ WERROR _eventlog_close_eventlog( pipes_struct * p, EVENTLOG_Q_CLOSE_EVENTLOG * q_u, EVENTLOG_R_CLOSE_EVENTLOG * r_u ) { - EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle ); - - if ( !( close_eventlog_hook( info ) ) ) - return WERR_BADFILE; - - if ( !( close_policy_hnd( p, &q_u->handle ) ) ) { - return WERR_BADFID; - } - - return WERR_OK; + return elog_close( p, &q_u->handle ); } /******************************************************************** @@ -805,56 +653,55 @@ WERROR _eventlog_read_eventlog( pipes_struct * p, EVENTLOG_Q_READ_EVENTLOG * q_u, EVENTLOG_R_READ_EVENTLOG * r_u ) { - EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle ); + EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); Eventlog_entry entry, *ee_new; uint32 num_records_read = 0; prs_struct *ps; int bytes_left, record_number; - TDB_CONTEXT *the_tdb; - + TDB_CONTEXT *tdb; info->flags = q_u->flags; ps = &p->out_data.rdata; - bytes_left = q_u->max_read_size; - the_tdb = tdb_of( info->logname ); - if ( !the_tdb ) { - /* todo handle the error */ - + tdb = info->tdb; + if ( !tdb ) { + return WERR_EVENTLOG_FILE_CORRUPT; } - /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */ + /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */ record_number = q_u->offset; while ( bytes_left > 0 ) { if ( get_eventlog_record - ( ps, the_tdb, record_number, &entry ) ) { + ( ps, tdb, record_number, &entry ) ) { DEBUG( 8, ( "Retrieved record %d\n", record_number ) ); + /* Now see if there is enough room to add */ - if ( ( ee_new = - read_package_entry( ps, q_u, r_u, - &entry ) ) == NULL ) { + ee_new = read_package_entry( ps, q_u, r_u,&entry ); + if ( !ee_new ) return WERR_NOMEM; - } - if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) { r_u->bytes_in_next_record = ee_new->record.length; + /* response would be too big to fit in client-size buffer */ + bytes_left = 0; break; } + add_record_to_resp( r_u, ee_new ); bytes_left -= ee_new->record.length; ZERO_STRUCT( entry ); num_records_read = r_u->num_records - num_records_read; + DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n", num_records_read, r_u->num_records, @@ -866,13 +713,12 @@ WERROR _eventlog_read_eventlog( pipes_struct * p, } - if ( info->flags & EVENTLOG_FORWARDS_READ ) { + if ( info->flags & EVENTLOG_FORWARDS_READ ) record_number++; - } else { + else record_number--; - } - } + return WERR_OK; } @@ -883,7 +729,7 @@ WERROR _eventlog_get_oldest_entry( pipes_struct * p, EVENTLOG_Q_GET_OLDEST_ENTRY * q_u, EVENTLOG_R_GET_OLDEST_ENTRY * r_u ) { - EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle ); + EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); if ( !( get_oldest_entry_hook( info ) ) ) return WERR_BADFILE; @@ -900,7 +746,7 @@ WERROR _eventlog_get_num_records( pipes_struct * p, EVENTLOG_Q_GET_NUM_RECORDS * q_u, EVENTLOG_R_GET_NUM_RECORDS * r_u ) { - EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle ); + EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); if ( !( get_num_records_hook( info ) ) ) return WERR_BADFILE; -- cgit