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:
parent
b9ae4455fd
commit
bb68761a50
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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( ¤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 *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 )
|
||||
|
@ -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;
|
||||
|
@ -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
166
source3/utils/wr_eventlog.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user