summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-10-14 16:07:00 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:04:59 -0500
commitbb68761a500fc5d426c75e53700fa793e016135f (patch)
treeb644c2323b3f0ea635e56dcd0435ebec7ae5c1af /source3/rpc_server
parentb9ae4455fd0be70c6c7b08807425066e0dd91242 (diff)
downloadsamba-bb68761a500fc5d426c75e53700fa793e016135f.tar.gz
samba-bb68761a500fc5d426c75e53700fa793e016135f.tar.bz2
samba-bb68761a500fc5d426c75e53700fa793e016135f.zip
r11060: merging new eventlog code from trunk
(This used to be commit 1bcf7e82ede63a851a244162a3b939373787b693)
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_eventlog_lib.c348
-rw-r--r--source3/rpc_server/srv_eventlog_nt.c628
2 files changed, 469 insertions, 507 deletions
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( &current_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.
@@ -315,36 +324,11 @@ Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb,
}
/********************************************************************
- ********************************************************************/
-
-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: <get_num_records_cmd> <log name> <policy handle>
- * 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: <oldest_entry_cmd> <log name> <policy handle>
- * 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: <close_cmd> <log name> <policy handle>
- * 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;
-}
-
/********************************************************************
********************************************************************/
@@ -631,150 +553,85 @@ static BOOL add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u,
/********************************************************************
********************************************************************/
-/**
- * Callout to clear (and optionally backup) a specified event log
- *
- * smbrun calling convention --
- * INPUT: <clear_eventlog_cmd> <log name> <policy handle>
- * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
- * Otherwise it is assumed to have failed
- *
- * INPUT: <clear_eventlog_cmd> <log name> <backup file> <policy handle>
- * 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 );
-}
-
-/********************************************************************
- ********************************************************************/
-
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;