1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

r11060: merging new eventlog code from trunk

(This used to be commit 1bcf7e82ed)
This commit is contained in:
Gerald Carter 2005-10-14 16:07:00 +00:00 committed by Gerald (Jerry) Carter
parent b9ae4455fd
commit bb68761a50
6 changed files with 728 additions and 532 deletions

View File

@ -130,7 +130,7 @@ BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
bin/tdbtool@EXEEXT@
BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ \
bin/smbcquotas@EXEEXT@
bin/smbcquotas@EXEEXT@ bin/wr_eventlog@EXEEXT@
TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
@ -614,6 +614,9 @@ SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
$(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ)
WR_EVENTLOG_OBJ = utils/wr_eventlog.o rpc_server/srv_eventlog_lib.o \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ)
TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) libsmb/nterr.o
RPCTORTURE_OBJ = torture/rpctorture.o \
@ -750,6 +753,8 @@ debug2html : SHOWFLAGS bin/debug2html@EXEEXT@
smbfilter : SHOWFLAGS bin/smbfilter@EXEEXT@
wr_eventlog: SHOWFLAGS bin/wr_eventlog@EXEEXT@
talloctort : SHOWFLAGS bin/talloctort@EXEEXT@
nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ @WINBIND_NSS@ \
@ -759,7 +764,7 @@ wins : SHOWFLAGS @WINBIND_WINS_NSS@
modules: SHOWFLAGS proto_exists $(MODULES)
everything: all libsmbclient debug2html smbfilter talloctort modules torture \
everything: all libsmbclient debug2html smbfilter talloctort modules torture wr_eventlog \
$(EVERYTHING_PROGS)
.SUFFIXES:
@ -972,6 +977,10 @@ bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/wr_eventlog@EXEEXT@: $(WR_EVENTLOG_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(WR_EVENTLOG_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)

View File

@ -47,11 +47,15 @@
#define EVENTLOG_AUDIT_FAILURE 0x0010
/* Defines for TDB keys */
#define VN_oldest_entry "INFO/oldest_entry"
#define VN_next_record "INFO/next_record"
#define VN_version "INFO/version"
#define VN_maxsize "INFO/maxsize"
#define VN_retention "INFO/retention"
#define EVT_OLDEST_ENTRY "INFO/oldest_entry"
#define EVT_NEXT_RECORD "INFO/next_record"
#define EVT_VERSION "INFO/version"
#define EVT_MAXSIZE "INFO/maxsize"
#define EVT_RETENTION "INFO/retention"
#define ELOG_APPL "Application"
#define ELOG_SYS "System"
#define ELOG_SEC "Security"
#define EVENTLOG_DATABASE_VERSION_V1 1

View File

@ -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 )
struct elog_open_tdb {
struct elog_open_tdb *prev, *next;
char *name;
TDB_CONTEXT *tdb;
int ref_count;
};
static struct elog_open_tdb *open_elog_list;
/********************************************************************
Init an Eventlog TDB, and return it. If null, something bad
happened.
********************************************************************/
TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
{
TDB_CONTEXT *the_tdb;
TDB_CONTEXT *tdb;
unlink( tdbfilename );
DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
tdbfilename));
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 ) );
tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
O_RDWR|O_CREAT|O_TRUNC, 0600 );
if ( !tdb ) {
DEBUG( 0, ( "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 );
/* 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( 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( the_tdb, VN_version, EVENTLOG_DATABASE_VERSION_V1 );
return the_tdb;
tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
return tdb;
}
/* 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 )
/********************************************************************
make the tdb file name for an event log, given destination buffer
and size. Caller must free memory.
********************************************************************/
char *elog_tdbname( const char *name )
{
pstring ondisk_name;
if ( !dest_buffer )
return NULL;
pstrcpy( ondisk_name, "EV" );
pstrcat( ondisk_name, eventlog_name );
pstrcat( ondisk_name, ".tdb" );
memset( dest_buffer, 0, size_dest );
/* 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" ) );
return NULL;
}
strncpy( dest_buffer, ondisk_name, size_dest );
return dest_buffer;
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;
}
/* count the number of bytes in the TDB */
/********************************************************************
this function is used to count up the number of bytes in a
particular TDB
********************************************************************/
/* Arg! Static Globals! */
struct trav_size_struct {
int size;
int rec_count;
};
static int eventlog_tdbcount;
static int eventlog_tdbsize;
/* 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.
/*
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 */
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 *the_tdb;
/*******************************************************************
*******************************************************************/
the_tdb =
tdb_open_log( tdbfilename, 0, TDB_DEFAULT, O_RDONLY,0664 );
if ( the_tdb == NULL ) {
return init_eventlog_tdb( tdbfilename );
TDB_CONTEXT *elog_open_tdb( char *logname )
{
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;
}
}
if ( EVENTLOG_DATABASE_VERSION_V1 !=
tdb_fetch_int32( the_tdb, VN_version ) ) {
tdb_close( the_tdb );
return init_eventlog_tdb( tdbfilename );
/* 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 );
}
}
return the_tdb;
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;
}
/* write an eventlog entry. Note that we have to lock, read next eventlog, increment, write, write the record, unlock */
/*******************************************************************
Wrapper to handle reference counts to the tdb
*******************************************************************/
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 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 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
*******************************************************************/
#define MARGIN 512
/* 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 */
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 )

View File

@ -25,191 +25,200 @@
#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;
#if 0 /* UNUSED */
/********************************************************************
********************************************************************/
void test_eventlog_tdb( TDB_CONTEXT * the_tdb )
{
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 );
}
}
#endif /* UNUSED */
uint32 access_granted;
} EVENTLOG_INFO;
/********************************************************************
********************************************************************/
static void refresh_eventlog_tdb_table( void )
static void free_eventlog_info( void *ptr )
{
const char **elogs = lp_eventlog_list( );
int i, j;
if ( !elogs )
return;
if ( !mem_ctx ) {
mem_ctx = talloc_init( "refresh_eventlog_tdb_table" );
}
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;
}
}
}
}
/* 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 );
}
}
nlogs = i;
EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr;
if ( elog->tdb )
elog_close_tdb( elog->tdb );
TALLOC_FREE( elog );
}
/********************************************************************
********************************************************************/
TDB_CONTEXT *tdb_of( char *eventlog_name )
static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
POLICY_HND * handle )
{
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;
}
/********************************************************************
********************************************************************/
static BOOL elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
{
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 );
}
/********************************************************************
********************************************************************/
static BOOL elog_validate_logname( const char *name )
{
int i;
if ( !eventlog_name )
return NULL;
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;
}
const char **elogs = lp_eventlog_list();
for ( i=0; elogs[i]; i++ ) {
if ( strequal( name, elogs[i] ) )
return True;
}
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;
}
return NULL;
return False;
}
/********************************************************************
********************************************************************/
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 */
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;
}
return WERR_OK;
}
/********************************************************************
********************************************************************/
static WERROR elog_close( pipes_struct *p, POLICY_HND *hnd )
{
if ( !( close_policy_hnd( p, hnd ) ) ) {
return WERR_BADFID;
}
return WERR_OK;
}
/*******************************************************************
*******************************************************************/
static int elog_size( EVENTLOG_INFO *info )
{
if ( !info || !info->tdb ) {
DEBUG(0,("elog_size: Invalid info* structure!\n"));
return 0;
}
return elog_tdb_size( info->tdb, NULL, NULL );
}
/********************************************************************
For the given tdb, get the next eventlog record into the passed
@ -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 );
tdb_store_int32( info->tdb, EVT_MAXSIZE, uiMaxSize );
tdb_store_int32( info->tdb, EVT_RETENTION, uiRetention );
return True;
}
/********************************************************************
********************************************************************/
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;
}
/********************************************************************
********************************************************************/
@ -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: <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 );
}
/********************************************************************
********************************************************************/
@ -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;
fstring servername, logname;
EVENTLOG_INFO *info;
WERROR wresult;
if ( !( info = TALLOC_ZERO_P( NULL, EventlogInfo ) ) )
return WERR_NOMEM;
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 );
}
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;
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;
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;
if ( !info )
return WERR_BADFID;
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 );
}
if ( q_u->backupfile.string )
unistr2_to_ascii( backup_file_name, q_u->backupfile.string,
sizeof( backup_file_name ) );
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;

View File

@ -4182,3 +4182,58 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST
/* Finally check other write access. */
return (psbuf->st_mode & S_IWOTH) ? True : False;
}
/********************************************************************
Pull the NT ACL from a file on disk or the OpenEventlog() access
check. Caller is responsible for freeing the returned security
descriptor via TALLOC_FREE(). This is designed for dealing with
user space access checks in smbd outside of the VFS. For example,
checking access rights in OpenEventlog().
Assume we are dealing with files (for now)
********************************************************************/
SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
{
SEC_DESC *psd, *ret_sd;
size_t sd_size;
connection_struct conn;
files_struct finfo;
struct fd_handle fh;
fstring path;
pstring filename;
ZERO_STRUCT( conn );
conn.service = -1;
if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
DEBUG(0,("novfs_get_nt_acl: talloc() failed!\n"));
return NULL;
}
fstrcpy( path, "/" );
string_set(&conn.connectpath, path);
if (!smbd_vfs_init(&conn)) {
DEBUG(0,("novfs_get_nt_acl: Unable to create a fake connection struct!\n"));
return NULL;
}
ZERO_STRUCT( finfo );
ZERO_STRUCT( fh );
finfo.fnum = -1;
finfo.conn = &conn;
finfo.fh = &fh;
finfo.fh->fd = -1;
pstrcpy( filename, fname );
finfo.fsp_name = filename;
sd_size = get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd );
ret_sd = dup_sec_desc( ctx, psd );
conn_free_internal( &conn );
return ret_sd;
}

166
source3/utils/wr_eventlog.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Samba Unix/Linux SMB client utility
* Write Eventlog records to a tdb
*
* Copyright (C) Brian Moran 2005.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_UTIL_EVENTLOG
Eventlog_entry ee;
extern int optind;
extern char *optarg;
int opt_debug = 0;
static void usage( char *s )
{
printf( "\nUsage: %s [-d] [-h] <Eventlog Name>\n", s );
printf( "\t-d\tturn debug on\n" );
printf( "\t-h\tdisplay help\n\n" );
}
static void display_eventlog_names( void )
{
const char **elogs;
int i;
elogs = lp_eventlog_list( );
printf( "Active eventlog names (from smb.conf):\n" );
printf( "--------------------------------------\n" );
for ( i = 0; elogs[i]; i++ ) {
printf( "\t%s\n", elogs[i] );
}
}
int main( int argc, char *argv[] )
{
FILE *f1;
/* fixed constants are bad bad bad */
pstring linein;
BOOL is_eor;
int pret, opt;
int rcnum;
char *argfname, *exename;
char *tdbname;
TDB_CONTEXT *elog_tdb;
opt_debug = 0; /* todo set this from getopts */
lp_load( dyn_CONFIGFILE, True, False, False );
exename = argv[0];
while ( ( opt = getopt( argc, argv, "dh" ) ) != -1 ) {
switch ( opt ) {
case 'h':
usage( argv[0] );
display_eventlog_names( );
exit( 0 );
break;
case 'd':
opt_debug = 1;
break;
}
}
argc -= optind;
argv += optind;
if ( argc < 1 ) {
usage( exename );
exit( 1 );
}
f1 = stdin;
if ( !f1 ) {
printf( "Can't open STDIN\n" );
return -1;
}
if ( opt_debug ) {
printf( "Starting %s for eventlog [%s]\n", exename, argv[0] );
display_eventlog_names( );
}
argfname = argv[0];
if ( !(elog_tdb = elog_open_tdb( argfname ) ) ) {
printf( "can't open the eventlog TDB (%s)\n", tdbname );
return -1;
}
ZERO_STRUCT( ee ); /* MUST initialize between records */
while ( !feof( f1 ) ) {
fgets( linein, sizeof( linein ) - 1, f1 );
linein[strlen( linein ) - 1] = 0; /* whack the line delimiter */
if ( opt_debug )
printf( "Read line [%s]\n", linein );
is_eor = False;
pret = parse_logentry( ( char * ) &linein, &ee, &is_eor );
if ( is_eor ) {
fixup_eventlog_entry( &ee );
if ( opt_debug )
printf( "record number [%d], tg [%d] , tw [%d]\n",
ee.record.record_number,
ee.record.time_generated,
ee.record.time_written );
if ( ee.record.time_generated != 0 ) {
/* printf("Writing to the event log\n"); */
rcnum = write_eventlog_tdb( elog_tdb, &ee );
if ( !rcnum ) {
printf( "Can't write to the event log\n" );
} else {
if ( opt_debug )
printf( "Wrote record %d\n",
rcnum );
}
} else {
if ( opt_debug )
printf( "<null record>\n" );
}
ZERO_STRUCT( ee ); /* MUST initialize between records */
}
}
tdb_close( elog_tdb );
return 0;
}