2005-10-18 07:21:59 +04:00
2005-10-14 20:07:00 +04:00
/*
* Samba Unix / Linux SMB client utility
2005-10-17 19:53:12 +04:00
* Write Eventlog records to a tdb , perform other eventlog related functions
*
2005-10-14 20:07:00 +04:00
*
* Copyright ( C ) Brian Moran 2005.
2009-02-02 19:24:28 +03:00
* Copyright ( C ) Guenther Deschner 2009.
2005-10-14 20:07:00 +04:00
*
* 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
2007-07-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2005-10-14 20:07:00 +04:00
* ( 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
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2005-10-14 20:07:00 +04:00
*/
# include "includes.h"
2010-05-06 13:42:52 +04:00
# include "lib/eventlog/eventlog.h"
2009-10-02 02:17:06 +04:00
# include "registry.h"
2012-04-19 15:30:40 +04:00
# include "registry/reg_api.h"
# include "registry/reg_init_basic.h"
# include "registry/reg_util_token.h"
2012-04-19 15:32:26 +04:00
# include "registry/reg_backend_db.h"
2011-02-26 02:28:15 +03:00
# include "../libcli/registry/util_reg.h"
2005-10-14 20:07:00 +04:00
extern int optind ;
extern char * optarg ;
int opt_debug = 0 ;
static void usage ( char * s )
{
2005-10-18 07:21:59 +04:00
printf ( " \n Usage: %s [OPTION] \n \n " , s ) ;
printf ( " -o write <Eventlog Name> \t \t \t \t \t Writes records to eventlog from STDIN \n " ) ;
printf ( " -o addsource <EventlogName> <sourcename> <msgfileDLLname> \t Adds the specified source & DLL eventlog registry entry \n " ) ;
2009-01-22 22:11:19 +03:00
printf ( " -o dump <Eventlog Name> <starting_record> \t \t \t \t \t Dump stored eventlog entries on STDOUT \n " ) ;
2005-10-18 07:21:59 +04:00
printf ( " \n Miscellaneous options: \n " ) ;
2010-02-14 21:05:00 +03:00
printf ( " -s <filename> \t \t \t \t \t \t \t Use configuration file <filename>. \n " ) ;
2005-10-18 07:21:59 +04:00
printf ( " -d \t \t \t \t \t \t \t \t turn debug on \n " ) ;
printf ( " -h \t \t \t \t \t \t \t \t display help \n \n " ) ;
2005-10-14 20:07:00 +04:00
}
static void display_eventlog_names ( void )
{
const char * * elogs ;
int i ;
elogs = lp_eventlog_list ( ) ;
2010-02-14 21:05:00 +03:00
printf ( " Active eventlog names: \n " ) ;
2005-10-14 20:07:00 +04:00
printf ( " -------------------------------------- \n " ) ;
2005-12-15 21:39:28 +03:00
if ( elogs ) {
for ( i = 0 ; elogs [ i ] ; i + + ) {
printf ( " \t %s \n " , elogs [ i ] ) ;
}
}
else
printf ( " \t <None specified> \n " ) ;
2005-10-14 20:07:00 +04:00
}
2011-01-27 20:06:16 +03:00
/*********************************************************************
for an eventlog , add in a source name . If the eventlog doesn ' t
exist ( not in the list ) do nothing . If a source for the log
already exists , change the information ( remove , replace )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool eventlog_add_source ( const char * eventlog , const char * sourcename ,
const char * messagefile )
{
/* Find all of the eventlogs, add keys for each of them */
/* need to add to the value KEY_EVENTLOG/<eventlog>/Sources string (Creating if necessary)
need to add KEY of source to KEY_EVENTLOG / < eventlog > / < source > */
const char * * elogs = lp_eventlog_list ( ) ;
const char * * wrklist , * * wp ;
char * evtlogpath = NULL ;
int ii = 0 ;
bool already_in ;
int i ;
int numsources = 0 ;
2012-04-19 15:30:40 +04:00
TALLOC_CTX * ctx = talloc_stackframe ( ) ;
2011-01-27 20:06:16 +03:00
WERROR werr ;
2012-04-19 15:30:40 +04:00
struct registry_key * key_hive , * key_eventlog , * key_source ;
struct security_token * token = NULL ;
const char * hive_name , * relpath ;
enum winreg_CreateAction action ;
struct registry_value * value ;
2015-05-07 03:00:06 +03:00
static const uint32_t ACCESS = REG_KEY_READ | REG_KEY_WRITE ;
2012-04-19 15:30:40 +04:00
bool ret = false ;
2011-01-27 20:06:16 +03:00
if ( ! elogs ) {
2012-04-19 15:30:40 +04:00
d_printf ( " No Eventlogs configured \n " ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
for ( i = 0 ; elogs [ i ] ; i + + ) {
if ( strequal ( elogs [ i ] , eventlog ) )
break ;
}
if ( ! elogs [ i ] ) {
d_printf ( " Eventlog [%s] not found in list of valid event logs \n " ,
eventlog ) ;
2012-04-19 15:30:40 +04:00
goto done ;
2011-01-27 20:06:16 +03:00
}
/* have to assume that the evenlog key itself exists at this point */
/* add in a key of [sourcename] under the eventlog key */
/* todo add to Sources */
evtlogpath = talloc_asprintf ( ctx , " %s \\ %s " , KEY_EVENTLOG , eventlog ) ;
if ( ! evtlogpath ) {
2012-04-19 15:30:40 +04:00
d_printf ( " Out of memory \n " ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
2012-05-09 12:41:06 +04:00
relpath = evtlogpath + sizeof ( KEY_EVENTLOG ) ;
2012-04-19 15:30:40 +04:00
hive_name = talloc_strndup ( ctx , evtlogpath , relpath - evtlogpath ) ;
if ( ! hive_name ) {
d_printf ( " Out of memory \n " ) ;
goto done ;
}
relpath + + ;
2011-01-27 20:06:16 +03:00
2012-04-19 15:30:40 +04:00
werr = ntstatus_to_werror ( registry_create_admin_token ( ctx , & token ) ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
d_printf ( " Failed to create admin token: %s \n " , win_errstr ( werr ) ) ;
goto done ;
}
2011-01-27 20:06:16 +03:00
2012-04-19 15:30:40 +04:00
werr = reg_openhive ( ctx , hive_name , ACCESS , token , & key_hive ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
d_printf ( " Failed to open hive [%s]: %s \n " , hive_name , win_errstr ( werr ) ) ;
goto done ;
}
werr = reg_openkey ( ctx , key_hive , relpath , ACCESS , & key_eventlog ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
d_printf ( " Failed to open key [%s]: %s \n " , evtlogpath , win_errstr ( werr ) ) ;
goto done ;
}
werr = reg_queryvalue ( ctx , key_eventlog , " Sources " , & value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
d_printf ( " Failed to get value \" Sources \" for [%s]: %s \n " , evtlogpath , win_errstr ( werr ) ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
/* perhaps this adding a new string to a multi_sz should be a fn? */
/* check to see if it's there already */
2012-04-19 15:30:40 +04:00
if ( value - > type ! = REG_MULTI_SZ ) {
d_printf ( " Wrong type for \" Sources \" , should be REG_MULTI_SZ \n " ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
/* convert to a 'regulah' chars to do some comparisons */
2012-04-19 15:30:40 +04:00
already_in = false ;
2011-01-27 20:06:16 +03:00
wrklist = NULL ;
2012-04-19 15:30:40 +04:00
dump_data ( 1 , value - > data . data , value - > data . length ) ;
2011-01-27 20:06:16 +03:00
2012-04-19 15:30:40 +04:00
if ( ! pull_reg_multi_sz ( ctx , & value - > data , & wrklist ) ) {
d_printf ( " Failed to pull REG_MULTI_SZ from \" Sources \" \n " ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
for ( ii = 0 ; wrklist [ ii ] ; ii + + ) {
numsources + + ;
}
if ( numsources > 0 ) {
/* see if it's in there already */
wp = wrklist ;
while ( wp & & * wp ) {
if ( strequal ( * wp , sourcename ) ) {
d_printf ( " Source name [%s] already in list for [%s] \n " ,
sourcename , eventlog ) ;
2012-04-19 15:30:40 +04:00
already_in = true ;
2011-01-27 20:06:16 +03:00
break ;
}
wp + + ;
}
} else {
d_printf ( " Nothing in the sources list, this might be a problem \n " ) ;
}
if ( ! already_in ) {
/* make a new list with an additional entry; copy values, add another */
2012-04-19 15:30:40 +04:00
wp = talloc_realloc ( ctx , wrklist , const char * , numsources + 2 ) ;
2011-01-27 20:06:16 +03:00
if ( ! wp ) {
2012-04-19 15:30:40 +04:00
d_printf ( " Out of memory \n " ) ;
goto done ;
}
wp [ numsources ] = sourcename ;
wp [ numsources + 1 ] = NULL ;
if ( ! push_reg_multi_sz ( ctx , & value - > data , wp ) ) {
d_printf ( " Failed to push Sources \n " ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
2012-04-19 15:30:40 +04:00
dump_data ( 1 , value - > data . data , value - > data . length ) ;
werr = reg_setvalue ( key_eventlog , " Sources " , value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
d_printf ( " Failed to set value Sources: %s \n " , win_errstr ( werr ) ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
} else {
d_printf ( " Source name [%s] found in existing list of sources \n " ,
sourcename ) ;
}
2012-04-19 15:30:40 +04:00
werr = reg_createkey ( ctx , key_eventlog , sourcename , ACCESS , & key_source , & action ) ;
2011-01-27 20:06:16 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2012-04-19 15:30:40 +04:00
d_printf ( " Failed to create subkey \" %s \" of \" %s \" : %s \n " , sourcename , evtlogpath , win_errstr ( werr ) ) ;
goto done ;
2011-01-27 20:06:16 +03:00
}
2012-04-19 15:30:40 +04:00
if ( action = = REG_CREATED_NEW_KEY ) {
2011-01-27 20:06:16 +03:00
d_printf ( " Source name [%s] for eventlog [%s] didn't exist, adding \n " ,
sourcename , eventlog ) ;
}
/* at this point KEY_EVENTLOG/<eventlog>/<sourcename> key is in there. Now need to add EventMessageFile */
/* now add the values to the KEY_EVENTLOG/Application form key */
d_printf ( " Storing EventMessageFile [%s] to eventlog path of [%s] \n " ,
messagefile , evtlogpath ) ;
2012-04-19 15:30:40 +04:00
if ( ! push_reg_sz ( ctx , & value - > data , messagefile ) ) {
d_printf ( " Failed to push \" EventMessageFile \" \n " ) ;
goto done ;
}
value - > type = REG_SZ ;
2011-01-27 20:06:16 +03:00
2012-04-19 15:30:40 +04:00
werr = reg_setvalue ( key_source , " EventMessageFile " , value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
d_printf ( " Failed to set value \" EventMessageFile \" : %s \n " , win_errstr ( werr ) ) ;
return false ;
}
ret = true ;
done :
talloc_free ( ctx ) ;
return ret ;
2011-01-27 20:06:16 +03:00
}
2007-10-19 04:40:25 +04:00
static int DoAddSourceCommand ( int argc , char * * argv , bool debugflag , char * exename )
2005-10-14 20:07:00 +04:00
{
2012-04-19 15:30:40 +04:00
WERROR werr ;
2005-10-14 20:07:00 +04:00
2005-10-18 07:21:59 +04:00
if ( argc < 3 ) {
printf ( " need more arguments: \n " ) ;
2005-10-20 18:29:24 +04:00
printf ( " -o addsource EventlogName SourceName /path/to/EventMessageFile.dll \n " ) ;
2005-10-18 07:21:59 +04:00
return - 1 ;
2005-10-14 20:07:00 +04:00
}
2012-04-19 15:30:40 +04:00
2005-10-18 07:21:59 +04:00
/* must open the registry before we access it */
2012-04-19 15:30:40 +04:00
werr = registry_init_common ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
printf ( " Can't open the registry: %s. \n " , win_errstr ( werr ) ) ;
2005-10-18 07:21:59 +04:00
return - 1 ;
2005-10-14 20:07:00 +04:00
}
2012-04-19 15:32:26 +04:00
werr = regdb_transaction_start ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
printf ( " Can't start transaction on registry: %s. \n " , win_errstr ( werr ) ) ;
return - 1 ;
}
2005-10-14 20:07:00 +04:00
2012-04-19 15:32:26 +04:00
if ( ! eventlog_add_source ( argv [ 0 ] , argv [ 1 ] , argv [ 2 ] ) ) {
regdb_transaction_cancel ( ) ;
2005-10-18 07:21:59 +04:00
return - 2 ;
2012-04-19 15:32:26 +04:00
}
werr = regdb_transaction_commit ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
printf ( " Failed to commit transaction on registry: %s. \n " , win_errstr ( werr ) ) ;
return - 1 ;
}
2005-10-18 07:21:59 +04:00
return 0 ;
}
2007-10-19 04:40:25 +04:00
static int DoWriteCommand ( int argc , char * * argv , bool debugflag , char * exename )
2005-10-18 07:21:59 +04:00
{
FILE * f1 ;
char * argfname ;
2005-11-18 00:07:24 +03:00
ELOG_TDB * etdb ;
2009-02-02 19:24:28 +03:00
NTSTATUS status ;
2005-10-14 20:07:00 +04:00
2005-10-18 07:21:59 +04:00
/* fixed constants are bad bad bad */
2007-12-05 03:56:18 +03:00
char linein [ 1024 ] ;
2007-10-19 04:40:25 +04:00
bool is_eor ;
2009-02-02 19:24:28 +03:00
struct eventlog_Record_tdb ee ;
2009-09-16 12:15:46 +04:00
uint32_t record_number = 0 ;
2009-02-02 15:38:38 +03:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2005-10-14 20:07:00 +04:00
f1 = stdin ;
if ( ! f1 ) {
printf ( " Can't open STDIN \n " ) ;
return - 1 ;
}
2005-10-18 07:21:59 +04:00
if ( debugflag ) {
printf ( " Starting write for eventlog [%s] \n " , argv [ 0 ] ) ;
2005-10-14 20:07:00 +04:00
display_eventlog_names ( ) ;
}
argfname = argv [ 0 ] ;
2009-01-22 21:46:14 +03:00
if ( ! ( etdb = elog_open_tdb ( argfname , False , False ) ) ) {
2005-10-18 07:21:59 +04:00
printf ( " can't open the eventlog TDB (%s) \n " , argfname ) ;
2005-10-14 20:07:00 +04:00
return - 1 ;
}
ZERO_STRUCT ( ee ) ; /* MUST initialize between records */
while ( ! feof ( f1 ) ) {
2009-01-01 05:06:57 +03:00
if ( fgets ( linein , sizeof ( linein ) - 1 , f1 ) = = NULL ) {
break ;
}
2009-11-30 23:48:33 +03:00
if ( ( strlen ( linein ) > 0 )
& & ( linein [ strlen ( linein ) - 1 ] = = ' \n ' ) ) {
linein [ strlen ( linein ) - 1 ] = 0 ;
}
2005-10-14 20:07:00 +04:00
2005-10-18 07:21:59 +04:00
if ( debugflag )
2005-10-14 20:07:00 +04:00
printf ( " Read line [%s] \n " , linein ) ;
is_eor = False ;
2005-10-18 07:21:59 +04:00
2009-02-02 15:38:38 +03:00
parse_logentry ( mem_ctx , ( char * ) & linein , & ee , & is_eor ) ;
2005-10-18 07:21:59 +04:00
/* should we do something with the return code? */
2005-10-14 20:07:00 +04:00
if ( is_eor ) {
2009-02-02 19:24:28 +03:00
fixup_eventlog_record_tdb ( & ee ) ;
2005-10-14 20:07:00 +04:00
if ( opt_debug )
2009-02-02 19:24:28 +03:00
printf ( " record number [%d], tg [%d] , tw [%d] \n " ,
ee . record_number , ( int ) ee . time_generated , ( int ) ee . time_written ) ;
2005-10-14 20:07:00 +04:00
2009-02-02 19:24:28 +03:00
if ( ee . time_generated ! = 0 ) {
2005-10-14 20:07:00 +04:00
/* printf("Writing to the event log\n"); */
2009-02-02 19:24:28 +03:00
status = evlog_push_record_tdb ( mem_ctx , ELOG_TDB_CTX ( etdb ) ,
& ee , & record_number ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Can't write to the event log: %s \n " ,
nt_errstr ( status ) ) ;
2005-10-14 20:07:00 +04:00
} else {
if ( opt_debug )
printf ( " Wrote record %d \n " ,
2009-02-02 19:24:28 +03:00
record_number ) ;
2005-10-14 20:07:00 +04:00
}
} else {
if ( opt_debug )
printf ( " <null record> \n " ) ;
}
ZERO_STRUCT ( ee ) ; /* MUST initialize between records */
}
}
2005-11-18 00:07:24 +03:00
elog_close_tdb ( etdb , False ) ;
2005-10-14 20:07:00 +04:00
return 0 ;
}
2005-10-18 07:21:59 +04:00
2009-01-22 22:11:19 +03:00
static int DoDumpCommand ( int argc , char * * argv , bool debugflag , char * exename )
{
ELOG_TDB * etdb ;
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
uint32_t count = 1 ;
if ( argc > 2 ) {
return - 1 ;
}
if ( argc > 1 ) {
count = atoi ( argv [ 1 ] ) ;
}
etdb = elog_open_tdb ( argv [ 0 ] , false , true ) ;
if ( ! etdb ) {
printf ( " can't open the eventlog TDB (%s) \n " , argv [ 0 ] ) ;
return - 1 ;
}
while ( 1 ) {
struct eventlog_Record_tdb * r ;
char * s ;
r = evlog_pull_record_tdb ( mem_ctx , etdb - > tdb , count ) ;
if ( ! r ) {
break ;
}
printf ( " displaying record: %d \n " , count ) ;
s = NDR_PRINT_STRUCT_STRING ( mem_ctx , eventlog_Record_tdb , r ) ;
if ( s ) {
printf ( " %s \n " , s ) ;
talloc_free ( s ) ;
}
count + + ;
}
elog_close_tdb ( etdb , false ) ;
return 0 ;
}
2005-10-18 07:21:59 +04:00
/* would be nice to use the popT stuff here, however doing so forces us to drag in a lot of other infrastructure */
int main ( int argc , char * argv [ ] )
{
int opt , rc ;
char * exename ;
2010-02-14 21:05:00 +03:00
char * configfile = NULL ;
2007-11-23 16:34:13 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2005-10-18 07:21:59 +04:00
fstring opname ;
2015-03-21 22:00:06 +03:00
smb_init_locale ( ) ;
2005-12-29 01:48:54 +03:00
2005-10-18 07:21:59 +04:00
opt_debug = 0 ; /* todo set this from getopts */
exename = argv [ 0 ] ;
/* default */
fstrcpy ( opname , " write " ) ; /* the default */
#if 0 /* TESTING CODE */
eventlog_add_source ( " System " , " TestSourceX " , " SomeTestPathX " ) ;
# endif
2010-02-14 21:05:00 +03:00
while ( ( opt = getopt ( argc , argv , " dho:s: " ) ) ! = EOF ) {
2005-10-18 07:21:59 +04:00
switch ( opt ) {
case ' o ' :
fstrcpy ( opname , optarg ) ;
break ;
case ' h ' :
2006-06-29 01:56:03 +04:00
usage ( exename ) ;
2005-10-18 07:21:59 +04:00
display_eventlog_names ( ) ;
exit ( 0 ) ;
break ;
case ' d ' :
opt_debug = 1 ;
break ;
2010-02-14 21:05:00 +03:00
case ' s ' :
configfile = talloc_strdup ( frame , optarg ) ;
break ;
2005-10-18 07:21:59 +04:00
}
}
argc - = optind ;
argv + = optind ;
if ( argc < 1 ) {
printf ( " \n Not enough arguments! \n " ) ;
usage ( exename ) ;
exit ( 1 ) ;
}
2010-02-14 21:05:00 +03:00
if ( configfile = = NULL ) {
2011-07-28 12:17:32 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
} else if ( ! lp_load_global ( configfile ) ) {
2010-02-14 21:05:00 +03:00
printf ( " Unable to parse configfile '%s' \n " , configfile ) ;
exit ( 1 ) ;
}
2005-10-18 07:21:59 +04:00
/* note that the separate command types should call usage if they need to... */
while ( 1 ) {
2011-05-13 22:21:30 +04:00
if ( ! strcasecmp_m ( opname , " addsource " ) ) {
2005-10-18 07:21:59 +04:00
rc = DoAddSourceCommand ( argc , argv , opt_debug ,
exename ) ;
break ;
}
2011-05-13 22:21:30 +04:00
if ( ! strcasecmp_m ( opname , " write " ) ) {
2005-10-18 07:21:59 +04:00
rc = DoWriteCommand ( argc , argv , opt_debug , exename ) ;
break ;
}
2011-05-13 22:21:30 +04:00
if ( ! strcasecmp_m ( opname , " dump " ) ) {
2009-01-22 22:11:19 +03:00
rc = DoDumpCommand ( argc , argv , opt_debug , exename ) ;
break ;
}
2005-10-18 07:21:59 +04:00
printf ( " unknown command [%s] \n " , opname ) ;
usage ( exename ) ;
exit ( 1 ) ;
break ;
}
2007-11-23 16:34:13 +03:00
TALLOC_FREE ( frame ) ;
2005-10-18 07:21:59 +04:00
return rc ;
}