+
/*
* Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines
- * Copyright (C) Marcin Krzysztof Porwit 2005.
+ * Virtual Windows Registry Layer
+ * 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
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
+
#include "includes.h"
+#include "registry.h"
+#include "reg_backend_db.h"
+#include "reg_eventlog.h"
+#include "reg_objects.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
/**********************************************************************
- handle enumeration of values AT KEY_EVENTLOG
- *********************************************************************/
-
-static int eventlog_topkey_values( char *key, REGVAL_CTR *val )
+ for an eventlog, add in the default values
+*********************************************************************/
+
+bool eventlog_init_keys(void)
{
- int num_values = 0;
- char *keystr, *key2 = NULL;
- char *base, *new_path;
- fstring evtlogname;
- UNISTR2 data;
- int iDisplayNameId;
- int iMaxSize;
-
- /*
- * TODO - callout to get these values...
- */
-
- if ( key )
- {
- key2 = SMB_STRDUP( key );
- keystr = key2;
- reg_split_path( keystr, &base, &new_path );
-
- iDisplayNameId = 0x00000100;
- iMaxSize= 0x00080000;
-
- fstrcpy( evtlogname, base );
- DEBUG(10,("eventlog_topkey_values: subkey root=> [%s] subkey path=>[%s]\n", base,new_path));
-
- if ( !new_path )
- {
- iDisplayNameId = 0x01;
- regval_ctr_addvalue( val, "ErrorControl", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) );
-
- init_unistr2( &data, "EventLog", UNI_STR_TERMINATE);
- regval_ctr_addvalue( val, "DisplayName", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-
- num_values = regval_ctr_numvals( val );
-
-
- num_values = 0;
+ /* Find all of the eventlogs, add keys for each of them */
+ const char **elogs = lp_eventlog_list();
+ char *evtlogpath = NULL;
+ char *evtfilepath = NULL;
+ struct regsubkey_ctr *subkeys;
+ struct regval_ctr *values;
+ uint32 uiMaxSize;
+ uint32 uiRetention;
+ uint32 uiCategoryCount;
+ DATA_BLOB data;
+ TALLOC_CTX *ctx = talloc_tos();
+ WERROR werr;
+
+ while (elogs && *elogs) {
+ werr = regsubkey_ctr_init(ctx, &subkeys);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ regdb_fetch_keys(KEY_EVENTLOG, subkeys);
+ regsubkey_ctr_addkey( subkeys, *elogs );
+ if ( !regdb_store_keys( KEY_EVENTLOG, subkeys ) ) {
+ TALLOC_FREE(subkeys);
+ return False;
+ }
+ TALLOC_FREE(subkeys);
+
+ /* add in the key of form KEY_EVENTLOG/Application */
+ DEBUG( 5,
+ ( "Adding key of [%s] to path of [%s]\n", *elogs,
+ KEY_EVENTLOG ) );
+
+ evtlogpath = talloc_asprintf(ctx, "%s\\%s",
+ KEY_EVENTLOG, *elogs);
+ if (!evtlogpath) {
+ return false;
+ }
+ /* add in the key of form KEY_EVENTLOG/Application/Application */
+ DEBUG( 5,
+ ( "Adding key of [%s] to path of [%s]\n", *elogs,
+ evtlogpath ) );
+ werr = regsubkey_ctr_init(ctx, &subkeys);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ regdb_fetch_keys( evtlogpath, subkeys );
+ regsubkey_ctr_addkey( subkeys, *elogs );
+
+ if ( !regdb_store_keys( evtlogpath, subkeys ) ) {
+ TALLOC_FREE(subkeys);
+ return False;
+ }
+ TALLOC_FREE( subkeys );
+
+ /* now add the values to the KEY_EVENTLOG/Application form key */
+
+ werr = regval_ctr_init(ctx, &values);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ DEBUG( 5,
+ ( "Storing values to eventlog path of [%s]\n",
+ evtlogpath ) );
+ regdb_fetch_values( evtlogpath, values );
+
+
+ if (!regval_ctr_key_exists(values, "MaxSize")) {
+
+ /* assume we have none, add them all */
+
+ /* hard code some initial values */
+
+ /* uiDisplayNameId = 0x00000100; */
+ uiMaxSize = 0x00080000;
+ uiRetention = 0x93A80;
+
+ regval_ctr_addvalue(values, "MaxSize", REG_DWORD,
+ (uint8 *)&uiMaxSize,
+ sizeof(uint32));
+
+ regval_ctr_addvalue(values, "Retention", REG_DWORD,
+ (uint8 *)&uiRetention,
+ sizeof(uint32));
+
+ regval_ctr_addvalue_sz(values, "PrimaryModule", *elogs);
+ push_reg_sz(talloc_tos(), &data, *elogs);
+
+ regval_ctr_addvalue(values, "Sources", REG_MULTI_SZ,
+ data.data,
+ data.length);
+
+ evtfilepath = talloc_asprintf(ctx,
+ "%%SystemRoot%%\\system32\\config\\%s.tdb",
+ *elogs);
+ if (!evtfilepath) {
+ TALLOC_FREE(values);
+ }
+ push_reg_sz(talloc_tos(), &data, evtfilepath);
+ regval_ctr_addvalue(values, "File", REG_EXPAND_SZ, data.data,
+ data.length);
+ regdb_store_values(evtlogpath, values);
+
+ }
+
+ TALLOC_FREE(values);
+
+ /* now do the values under KEY_EVENTLOG/Application/Application */
+ TALLOC_FREE(evtlogpath);
+ evtlogpath = talloc_asprintf(ctx, "%s\\%s\\%s",
+ KEY_EVENTLOG, *elogs, *elogs);
+ if (!evtlogpath) {
+ return false;
+ }
+
+ werr = regval_ctr_init(ctx, &values);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ DEBUG( 5,
+ ( "Storing values to eventlog path of [%s]\n",
+ evtlogpath));
+ regdb_fetch_values(evtlogpath, values);
+ if (!regval_ctr_key_exists( values, "CategoryCount")) {
+
+ /* hard code some initial values */
+
+ uiCategoryCount = 0x00000007;
+ regval_ctr_addvalue( values, "CategoryCount",
+ REG_DWORD,
+ (uint8 *) &uiCategoryCount,
+ sizeof( uint32 ) );
+ push_reg_sz(talloc_tos(), &data,
+ "%SystemRoot%\\system32\\eventlog.dll");
+
+ regval_ctr_addvalue( values, "CategoryMessageFile",
+ REG_EXPAND_SZ,
+ data.data,
+ data.length);
+ regdb_store_values( evtlogpath, values );
+ }
+ TALLOC_FREE(values);
+ elogs++;
}
- }
-
- SAFE_FREE( key2 );
- return num_values;
-}
-/**********************************************************************
- handle enumeration of values below KEY_EVENTLOG\<Eventlog>
- *********************************************************************/
-
-static int eventlog_subkey_values( char *key, REGVAL_CTR *val )
-{
- int num_values = 0;
- char *keystr, *key2 = NULL;
- char *base, *new_path;
- fstring evtlogname;
- UNISTR2 data;
- int iDisplayNameId;
- int iMaxSize;
- int iRetention;
-
- /*
- * TODO - callout to get these values...
- */
-
- if ( !key )
- return num_values;
-
- key2 = SMB_STRDUP( key );
- keystr = key2;
- reg_split_path( keystr, &base, &new_path );
-
- iDisplayNameId = 0x00000100;
- /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */
- iMaxSize= 0xFFFF0000;
- /* records in the samba log are not overwritten */
- iRetention = 0xFFFFFFFF;
-
- fstrcpy( evtlogname, base );
- DEBUG(10,("eventlog_subpath_values_printer: eventlogname [%s]\n", base));
- DEBUG(10,("eventlog_subpath_values_printer: new_path [%s]\n", new_path));
- if ( !new_path )
- {
-#if 0
- regval_ctr_addvalue( val, "DisplayNameId", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) );
-
- init_unistr2( &data, "%SystemRoot%\\system32\\els.dll", UNI_STR_TERMINATE);
- regval_ctr_addvalue( val, "DisplayNameFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
- regval_ctr_addvalue( val, "MaxSize", REG_DWORD, (char*)&iMaxSize, sizeof(int));
- regval_ctr_addvalue( val, "Retention", REG_DWORD, (char *)&iRetention, sizeof(int));
-#if 0
- init_unistr2( &data, lp_logfile(), UNI_STR_TERMINATE);
- regval_ctr_addvalue( val, "File", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
- init_unistr2( &data, base, UNI_STR_TERMINATE);
- regval_ctr_addvalue( val, "PrimaryModule", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-
- init_unistr2( &data, base, UNI_STR_TERMINATE);
- regval_ctr_addvalue( val, "Sources", REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-
- num_values = regval_ctr_numvals( val );
-
- }
- else
- {
- iDisplayNameId = 0x07;
- regval_ctr_addvalue( val, "CategoryCount", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) );
-
- init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE);
- regval_ctr_addvalue( val, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-
- num_values = regval_ctr_numvals( val );
-
- num_values = 0;
- }
-
- SAFE_FREE( key2 );
- return num_values;
+ return true;
}
+/*********************************************************************
+ 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)
+*********************************************************************/
-/**********************************************************************
- It is safe to assume that every registry path passed into on of
- the exported functions here begins with KEY_EVENTLOG else
- these functions would have never been called. This is a small utility
- function to strip the beginning of the path and make a copy that the
- caller can modify. Note that the caller is responsible for releasing
- the memory allocated here.
- **********************************************************************/
-
-static char* trim_eventlog_reg_path( char *path )
+bool eventlog_add_source( const char *eventlog, const char *sourcename,
+ const char *messagefile )
{
- char *p;
- uint16 key_len = strlen(KEY_EVENTLOG);
-
- /*
- * sanity check...this really should never be True.
- * It is only here to prevent us from accessing outside
- * the path buffer in the extreme case.
- */
-
- if ( strlen(path) < key_len ) {
- DEBUG(0,("trim_reg_path: Registry path too short! [%s]\n", path));
- DEBUG(0,("trim_reg_path: KEY_EVENTLOG => [%s]!\n", KEY_EVENTLOG));
- return NULL;
+ /* 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;
+ struct regsubkey_ctr *subkeys;
+ struct regval_ctr *values;
+ struct regval_blob *rval;
+ int ii = 0;
+ bool already_in;
+ int i;
+ int numsources = 0;
+ TALLOC_CTX *ctx = talloc_tos();
+ WERROR werr;
+ DATA_BLOB blob;
+
+ if (!elogs) {
+ return False;
}
-
-
- p = path + strlen( KEY_EVENTLOG );
-
- if ( *p == '\\' )
- p++;
-
- if ( *p )
- return SMB_STRDUP(p);
- else
- return NULL;
-}
-/**********************************************************************
- Enumerate registry subkey names given a registry path.
- Caller is responsible for freeing memory to **subkeys
- *********************************************************************/
-int eventlog_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
-{
- char *path;
- BOOL top_level = False;
- int num_subkeys = 0;
- const char **evtlog_list;
-
- path = trim_eventlog_reg_path( key );
- DEBUG(10,("eventlog_subkey_info: entire key=>[%s] SUBkey=>[%s]\n", key,path));
-
- /* check to see if we are dealing with the top level key */
- num_subkeys = 0;
-
- if ( !path )
- top_level = True;
-
- evtlog_list = lp_eventlog_list();
- num_subkeys = 0;
-
- if ( top_level )
- {
- /* todo - get the eventlog subkey values from the smb.conf file
- for ( num_subkeys=0; num_subkeys<MAX_TOP_LEVEL_KEYS; num_subkeys++ )
- regsubkey_ctr_addkey( subkey_ctr, top_level_keys[num_subkeys] ); */
- DEBUG(10,("eventlog_subkey_info: Adding eventlog subkeys from globals\n"));
- /* TODO - make this from the globals.szEventLogs list */
-
- while (*evtlog_list)
- {
- DEBUG(10,("eventlog_subkey_info: Adding subkey =>[%s]\n",*evtlog_list));
- regsubkey_ctr_addkey( subkey_ctr, *evtlog_list);
- evtlog_list++;
- num_subkeys++;
+
+ for ( i = 0; elogs[i]; i++ ) {
+ if ( strequal( elogs[i], eventlog ) )
+ break;
}
- }
- else
- {
- while (*evtlog_list && (0==num_subkeys) )
- {
- if (0 == StrCaseCmp(path,*evtlog_list))
- {
- DEBUG(10,("eventlog_subkey_info: Adding subkey [%s] for key =>[%s]\n",path,*evtlog_list));
- regsubkey_ctr_addkey( subkey_ctr, *evtlog_list);
- num_subkeys = 1;
- }
- evtlog_list++;
+
+ if ( !elogs[i] ) {
+ DEBUG( 0,
+ ( "Eventlog [%s] not found in list of valid event logs\n",
+ eventlog ) );
+ return false; /* invalid named passed in */
}
-
- if (0==num_subkeys)
- DEBUG(10,("eventlog_subkey_info: No match on SUBkey=>[%s]\n", path));
- }
-
- SAFE_FREE( path );
- return num_subkeys;
-}
-/**********************************************************************
- Enumerate registry values given a registry path.
- Caller is responsible for freeing memory
- *********************************************************************/
+ /* have to assume that the evenlog key itself exists at this point */
+ /* add in a key of [sourcename] under the eventlog key */
-int eventlog_value_info( char *key, REGVAL_CTR *val )
-{
- char *path;
- BOOL top_level = False;
- int num_values = 0;
-
- DEBUG(10,("eventlog_value_info: key=>[%s]\n", key));
-
- path = trim_eventlog_reg_path( key );
-
- /* check to see if we are dealing with the top level key */
-
- if ( !path )
- top_level = True;
- if ( top_level )
- num_values = eventlog_topkey_values(path,val);
- else
- {
- DEBUG(10,("eventlog_value_info: SUBkey=>[%s]\n", path));
- num_values = eventlog_subkey_values(path,val);
+ /* todo add to Sources */
+
+ werr = regval_ctr_init(ctx, &values);
+ if(!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ));
+ return false;
}
- return num_values;
-}
-/**********************************************************************
- Stub function which always returns failure since we don't want
- people storing eventlog information directly via registry calls
- (for now at least)
- *********************************************************************/
-BOOL eventlog_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
-{
- return False;
-}
+ evtlogpath = talloc_asprintf(ctx, "%s\\%s", KEY_EVENTLOG, eventlog);
+ if (!evtlogpath) {
+ TALLOC_FREE(values);
+ return false;
+ }
-/**********************************************************************
- Stub function which always returns failure since we don't want
- people storing eventlog information directly via registry calls
- (for now at least)
- *********************************************************************/
-BOOL eventlog_store_value( char *key, REGVAL_CTR *val )
-{
- return False;
-}
+ regdb_fetch_values( evtlogpath, values );
-/*
- * Table of function pointers for accessing eventlog data
- */
-REGISTRY_OPS eventlog_ops = {
- eventlog_subkey_info,
- eventlog_value_info,
- eventlog_store_subkey,
- eventlog_store_value
-};
+
+ if ( !( rval = regval_ctr_getvalue( values, "Sources" ) ) ) {
+ DEBUG( 0, ( "No Sources value for [%s]!\n", eventlog ) );
+ return False;
+ }
+ /* perhaps this adding a new string to a multi_sz should be a fn? */
+ /* check to see if it's there already */
+
+ if ( regval_type(rval) != REG_MULTI_SZ ) {
+ DEBUG( 0,
+ ( "Wrong type for Sources, should be REG_MULTI_SZ\n" ) );
+ return False;
+ }
+ /* convert to a 'regulah' chars to do some comparisons */
+
+ already_in = False;
+ wrklist = NULL;
+ dump_data(1, regval_data_p(rval), regval_size(rval));
+
+ blob = data_blob_const(regval_data_p(rval), regval_size(rval));
+ if (!pull_reg_multi_sz(talloc_tos(), &blob, &wrklist)) {
+ return false;
+ }
+
+ 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 ) ) {
+ DEBUG( 5,
+ ( "Source name [%s] already in list for [%s] \n",
+ sourcename, eventlog ) );
+ already_in = True;
+ break;
+ }
+ wp++;
+ }
+ } else {
+ DEBUG( 3,
+ ( "Nothing in the sources list, this might be a problem\n" ) );
+ }
+
+ wp = wrklist;
+
+ if ( !already_in ) {
+ /* make a new list with an additional entry; copy values, add another */
+ wp = TALLOC_ARRAY(ctx, const char *, numsources + 2 );
+
+ if ( !wp ) {
+ DEBUG( 0, ( "talloc() failed \n" ) );
+ return False;
+ }
+ memcpy( wp, wrklist, sizeof( char * ) * numsources );
+ *( wp + numsources ) = ( char * ) sourcename;
+ *( wp + numsources + 1 ) = NULL;
+ if (!push_reg_multi_sz(ctx, &blob, wp)) {
+ return false;
+ }
+ dump_data( 1, blob.data, blob.length);
+ regval_ctr_addvalue( values, "Sources", REG_MULTI_SZ,
+ blob.data, blob.length);
+ regdb_store_values( evtlogpath, values );
+ data_blob_free(&blob);
+ } else {
+ DEBUG( 3,
+ ( "Source name [%s] found in existing list of sources\n",
+ sourcename ) );
+ }
+ TALLOC_FREE(values);
+ TALLOC_FREE(wrklist); /* */
+
+ werr = regsubkey_ctr_init(ctx, &subkeys);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ TALLOC_FREE(evtlogpath);
+ evtlogpath = talloc_asprintf(ctx, "%s\\%s", KEY_EVENTLOG, eventlog );
+ if (!evtlogpath) {
+ TALLOC_FREE(subkeys);
+ return false;
+ }
+
+ regdb_fetch_keys( evtlogpath, subkeys );
+
+ if ( !regsubkey_ctr_key_exists( subkeys, sourcename ) ) {
+ DEBUG( 5,
+ ( " Source name [%s] for eventlog [%s] didn't exist, adding \n",
+ sourcename, eventlog ) );
+ regsubkey_ctr_addkey( subkeys, sourcename );
+ if ( !regdb_store_keys( evtlogpath, subkeys ) )
+ return False;
+ }
+ TALLOC_FREE(subkeys);
+
+ /* at this point KEY_EVENTLOG/<eventlog>/<sourcename> key is in there. Now need to add EventMessageFile */
+
+ /* now allocate room for the source's subkeys */
+
+ werr = regsubkey_ctr_init(ctx, &subkeys);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ TALLOC_FREE(evtlogpath);
+ evtlogpath = talloc_asprintf(ctx, "%s\\%s\\%s",
+ KEY_EVENTLOG, eventlog, sourcename);
+ if (!evtlogpath) {
+ TALLOC_FREE(subkeys);
+ return false;
+ }
+
+ regdb_fetch_keys( evtlogpath, subkeys );
+
+ /* now add the values to the KEY_EVENTLOG/Application form key */
+ werr = regval_ctr_init(ctx, &values);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ DEBUG( 5,
+ ( "Storing EventMessageFile [%s] to eventlog path of [%s]\n",
+ messagefile, evtlogpath ) );
+
+ regdb_fetch_values( evtlogpath, values );
+
+ regval_ctr_addvalue_sz(values, "EventMessageFile", messagefile);
+ regdb_store_values( evtlogpath, values );
+
+ TALLOC_FREE(values);
+
+ return True;
+}