summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in5
-rw-r--r--source3/include/rpc_eventlog.h8
-rw-r--r--source3/include/rpc_misc.h2
-rw-r--r--source3/include/rpc_svcctl.h17
-rw-r--r--source3/param/loadparm.c37
-rw-r--r--source3/registry/reg_eventlog.c273
-rw-r--r--source3/registry/reg_frontend.c8
-rw-r--r--source3/rpc_parse/parse_misc.c4
-rw-r--r--source3/rpc_parse/parse_ntsvcs.c2
-rw-r--r--source3/rpc_server/srv_eventlog_lib.c620
-rw-r--r--source3/rpc_server/srv_eventlog_nt.c1225
-rw-r--r--source3/rpc_server/srv_ntsvcs_nt.c6
-rw-r--r--source3/rpc_server/srv_reg_nt.c6
-rw-r--r--source3/rpc_server/srv_svcctl_nt.c19
-rw-r--r--source3/services/services_db.c238
-rw-r--r--source3/services/svc_rcinit.c148
-rw-r--r--source3/services/svc_wins.c66
17 files changed, 1641 insertions, 1043 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 07c348bd84..4310f51bd5 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -283,7 +283,8 @@ RPC_WKS_OBJ = rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o
RPC_SVCCTL_OBJ = rpc_server/srv_svcctl.o rpc_server/srv_svcctl_nt.o \
services/svc_spoolss.o services/svc_rcinit.o services/services_db.o \
- services/svc_netlogon.o services/svc_winreg.o
+ services/svc_netlogon.o services/svc_winreg.o \
+ services/svc_wins.o
RPC_NTSVCS_OBJ = rpc_server/srv_ntsvcs.o rpc_server/srv_ntsvcs_nt.o
@@ -291,7 +292,7 @@ RPC_DFS_OBJ = rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o
RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o
-RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog.o rpc_server/srv_eventlog_nt.o
+RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog.o rpc_server/srv_eventlog_nt.o rpc_server/srv_eventlog_lib.o
RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \
rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o
diff --git a/source3/include/rpc_eventlog.h b/source3/include/rpc_eventlog.h
index 7ce1199b21..9f968fb54e 100644
--- a/source3/include/rpc_eventlog.h
+++ b/source3/include/rpc_eventlog.h
@@ -46,6 +46,14 @@
#define EVENTLOG_AUDIT_SUCCESS 0x0008
#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 EVENTLOG_DATABASE_VERSION_V1 1
/***********************************/
diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h
index e5d91c1b63..091ba3395e 100644
--- a/source3/include/rpc_misc.h
+++ b/source3/include/rpc_misc.h
@@ -27,7 +27,7 @@
#define SMB_RPC_INTERFACE_VERSION 1
#define PRS_POINTER_CAST BOOL (*)(const char*, prs_struct*, int, void*)
-enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_TERMINATE = 2, UNI_BROKEN_NON_NULL = 3 };
+enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_TERMINATE = 2, UNI_BROKEN_NON_NULL = 3, UNI_STR_DBLTERMINATE = 4 };
diff --git a/source3/include/rpc_svcctl.h b/source3/include/rpc_svcctl.h
index 443a6588a6..f5ad2afa1c 100644
--- a/source3/include/rpc_svcctl.h
+++ b/source3/include/rpc_svcctl.h
@@ -175,23 +175,6 @@ typedef struct {
SC_ACTION *actions;
} SERVICE_FAILURE_ACTIONS;
-typedef struct Service_info_struct {
- uint32 type; /* should be SVC_HANDLE_IS_SERVICE */
- pstring servicename; /* the name of the service */
- pstring servicetype; /* internal or external */
- pstring filename; /* what file name we can find this in,
- as well as the "index" for what the
- service name is */
- pstring provides;
- pstring dependencies;
- pstring shouldstart;
- pstring shouldstop;
- pstring requiredstart;
- pstring requiredstop;
- pstring shortdescription;
- pstring description;
-} Service_info;
-
/*
* dispatch table of functions to handle the =ServiceControl API
*/
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 0a4f0556ae..126d70939c 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -183,13 +183,6 @@ typedef struct
char *szAddShareCommand;
char *szChangeShareCommand;
char *szDeleteShareCommand;
- char *szEventLogOpenCommand;
- char *szEventLogReadCommand;
- char *szEventLogClearCommand;
- char *szEventLogNumRecordsCommand;
- char *szEventLogOldestRecordCommand;
- char *szEventLogCloseCommand;
- char *szEventLogControlCommand;
char **szEventLogs;
char *szGuestaccount;
char *szManglingMethod;
@@ -608,7 +601,6 @@ static BOOL handle_netbios_scope( int snum, const char *pszParmValue, char **ptr
static BOOL handle_charset( int snum, const char *pszParmValue, char **ptr );
static BOOL handle_acl_compatibility( int snum, const char *pszParmValue, char **ptr);
static BOOL handle_printing( int snum, const char *pszParmValue, char **ptr);
-static BOOL handle_eventlog( int snum, const char *pszParmValue, char **ptr);
static void set_server_role(void);
static void set_default_server_announce_type(void);
@@ -1154,13 +1146,6 @@ static struct parm_struct parm_table[] = {
{"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED},
{N_("EventLog Options"), P_SEP, P_SEPARATOR},
- {"eventlog open command", P_STRING, P_GLOBAL, &Globals.szEventLogOpenCommand, handle_eventlog, NULL, FLAG_ADVANCED},
- {"eventlog read command", P_STRING, P_GLOBAL, &Globals.szEventLogReadCommand, handle_eventlog, NULL, FLAG_ADVANCED},
- {"eventlog clear command", P_STRING, P_GLOBAL, &Globals.szEventLogClearCommand, handle_eventlog, NULL, FLAG_ADVANCED},
- {"eventlog num records command", P_STRING, P_GLOBAL, &Globals.szEventLogNumRecordsCommand, handle_eventlog, NULL, FLAG_ADVANCED},
- {"eventlog oldest record command", P_STRING, P_GLOBAL, &Globals.szEventLogOldestRecordCommand, handle_eventlog, NULL, FLAG_ADVANCED},
- {"eventlog close command", P_STRING, P_GLOBAL, &Globals.szEventLogCloseCommand, handle_eventlog, NULL, FLAG_ADVANCED},
- {"eventlog control command", P_STRING, P_GLOBAL, &Globals.szEventLogControlCommand, handle_eventlog, NULL, FLAG_ADVANCED},
{"eventlog list", P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
{"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
@@ -1581,14 +1566,6 @@ static void init_globals(void)
string_set(&Globals.szCupsServer, "");
string_set(&Globals.szIPrintServer, "");
- string_set(&Globals.szEventLogOpenCommand, "");
- string_set(&Globals.szEventLogReadCommand, "");
- string_set(&Globals.szEventLogClearCommand, "");
- string_set(&Globals.szEventLogNumRecordsCommand, "");
- string_set(&Globals.szEventLogOldestRecordCommand, "");
- string_set(&Globals.szEventLogCloseCommand, "");
- string_set(&Globals.szEventLogControlCommand, "");
-
Globals.winbind_cache_time = 300; /* 5 minutes */
Globals.bWinbindEnumUsers = True;
Globals.bWinbindEnumGroups = True;
@@ -1806,14 +1783,6 @@ FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
-FN_GLOBAL_STRING(lp_eventlog_open_cmd, &Globals.szEventLogOpenCommand)
-FN_GLOBAL_STRING(lp_eventlog_read_cmd, &Globals.szEventLogReadCommand)
-FN_GLOBAL_STRING(lp_eventlog_clear_cmd, &Globals.szEventLogClearCommand)
-FN_GLOBAL_STRING(lp_eventlog_num_records_cmd, &Globals.szEventLogNumRecordsCommand)
-FN_GLOBAL_STRING(lp_eventlog_oldest_record_cmd, &Globals.szEventLogOldestRecordCommand)
-FN_GLOBAL_STRING(lp_eventlog_close_cmd, &Globals.szEventLogCloseCommand)
-FN_GLOBAL_STRING(lp_eventlog_control_cmd, &Globals.szEventLogControlCommand)
-
FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
@@ -2908,11 +2877,7 @@ static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr)
return True;
}
-static BOOL handle_eventlog(int snum, const char *pszParmValue, char **ptr)
-{
- string_set(ptr, pszParmValue);
- return True;
-}
+
static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr)
{
diff --git a/source3/registry/reg_eventlog.c b/source3/registry/reg_eventlog.c
index bed9e1d59a..204c4c6e1c 100644
--- a/source3/registry/reg_eventlog.c
+++ b/source3/registry/reg_eventlog.c
@@ -2,6 +2,7 @@
* Unix SMB/CIFS implementation.
* 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
@@ -18,171 +19,135 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+
#include "includes.h"
/**********************************************************************
- Enumerate registry subkey names given a registry path.
+ for an eventlog, add in the default values
*********************************************************************/
-static int elog_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
+BOOL eventlog_init_keys( void )
{
- const char **elogs = lp_eventlog_list();
- char *path;
- int i;
-
- path = reg_remaining_path( key + strlen(KEY_EVENTLOG) );
-
- DEBUG(10,("elog_fetch_keys: entire key => [%s], subkey => [%s]\n",
- key, path));
-
- if ( !path ) {
-
- if ( !elogs || !*elogs )
- return 0;
-
- DEBUG(10,("elog_fetch_keys: Adding eventlog subkeys from smb.conf\n"));
-
- for ( i=0; elogs[i]; i++ )
- regsubkey_ctr_addkey( subkeys, elogs[i] );
-
- return regsubkey_ctr_numkeys( subkeys );
- }
-
- /* if we get <logname>/<logname> then we don't add anymore */
-
- if ( strchr( path, '\\' ) ) {
- DEBUG(10,("elog_fetch_keys: Not adding subkey to %s\n",path));
- return 0;
- }
-
- /* add in a subkey with the same name as the eventlog... */
-
- DEBUG(10,("elog_fetch_keys: Looking to add eventlog subkey to %s\n",path));
-
- /* look for a match */
-
- if ( !elogs )
- return -1;
-
- for ( i=0; elogs[i]; i++ ) {
- /* just verify that the keyname is a valid log name */
- if ( strequal( path, elogs[i] ) )
- return 0;
- }
-
- return -1;
-}
-
-/**********************************************************************
- Enumerate registry values given a registry path.
- Caller is responsible for freeing memory
-*********************************************************************/
-
-static int elog_fetch_values( const char *key, REGVAL_CTR *values )
-{
- char *path;
- uint32 uiDisplayNameId, uiMaxSize, uiRetention;
- char *base, *new_path;
+ /* Find all of the eventlogs, add keys for each of them */
+ const char **elogs = lp_eventlog_list( );
+ pstring evtlogpath;
+ REGSUBKEY_CTR *subkeys;
+ REGVAL_CTR *values;
+ uint32 uiDisplayNameId;
+ uint32 uiMaxSize;
+ uint32 uiRetention;
+ uint32 uiCategoryCount;
UNISTR2 data;
-
- DEBUG(10,("elog_fetch_values: key=>[%s]\n", key));
-
- path = reg_remaining_path( key + strlen(KEY_EVENTLOG) );
-
- /* check to see if we are dealing with the top level key */
-
- if ( !path )
- return regdb_fetch_values( KEY_EVENTLOG, values );
-
- /* deal with a log name */
-
- reg_split_path( path, &base, &new_path );
-
- /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */
-
-
- if ( !new_path ) {
-
- /* try to fetch from the registry */
-
- regdb_fetch_values( key, values );
-
- /* just verify one of the important keys. If this
- fails, then assume the values have not been initialized */
-
- if ( regval_ctr_getvalue( values, "Retention" ) )
- return regval_ctr_numvals( values );
-
- /* hard code some initial values */
-
- uiDisplayNameId = 0x00000100;
- uiMaxSize = 0x00080000;
- uiRetention = 0x93A80;
-
- regval_ctr_addvalue( values, "MaxSize", REG_DWORD, (char*)&uiMaxSize, sizeof(uint32));
- regval_ctr_addvalue( values, "Retention", REG_DWORD, (char *)&uiRetention, sizeof(uint32));
-
- init_unistr2( &data, base, UNI_STR_TERMINATE);
- regval_ctr_addvalue( values, "PrimaryModule", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-
- init_unistr2( &data, base, UNI_STR_TERMINATE);
- regval_ctr_addvalue( values, "Sources", REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-
- /* store them for later updates. Complain if this fails but continue on */
-
- if ( !regdb_store_values( key, values ) ) {
- DEBUG(0,("elog_fetch_values: Failed to store initial values for log [%s]\n",
- base ));
+
+ while ( elogs && *elogs ) {
+ if ( !( subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR ) ) ) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
}
-
- return regval_ctr_numvals( values );
- }
-
-#if 0
- /* hmmm....what to do here? A subkey underneath the log name ? */
-
- uiDisplayNameId = 0x07;
- regval_ctr_addvalue( values, "CategoryCount", REG_DWORD, (char*)&uiDisplayNameId, sizeof(uint32) );
-
- init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE);
- regval_ctr_addvalue( values, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
-
- return regval_ctr_numvals( values );
-}
+ regdb_fetch_keys( KEY_EVENTLOG, subkeys );
+ regsubkey_ctr_addkey( subkeys, *elogs );
+ if ( !regdb_store_keys( KEY_EVENTLOG, 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 ) );
+
+ slprintf( evtlogpath, sizeof( evtlogpath ) - 1, "%s\\%s",
+ KEY_EVENTLOG, *elogs );
+ /* add in the key of form KEY_EVENTLOG/Application/Application */
+ DEBUG( 5,
+ ( "Adding key of [%s] to path of [%s]\n", *elogs,
+ evtlogpath ) );
+ if ( !( subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR ) ) ) {
+ DEBUG( 0, ( "talloc() failure!\n" ) );
+ return False;
+ }
+ regdb_fetch_keys( evtlogpath, subkeys );
+ regsubkey_ctr_addkey( subkeys, *elogs );
-/**********************************************************************
-*********************************************************************/
+ if ( !regdb_store_keys( evtlogpath, subkeys ) )
+ return False;
+ TALLOC_FREE( subkeys );
-static BOOL elog_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
-{
- /* cannot create any subkeys here */
-
- return False;
-}
+ /* now add the values to the KEY_EVENTLOG/Application form key */
+ if ( !( values = TALLOC_ZERO_P( NULL, REGVAL_CTR ) ) ) {
+ 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,
+ ( char * ) &uiMaxSize,
+ sizeof( uint32 ) );
+ regval_ctr_addvalue( values, "Retention", REG_DWORD,
+ ( char * ) &uiRetention,
+ sizeof( uint32 ) );
+ init_unistr2( &data, *elogs, UNI_STR_TERMINATE );
+ regval_ctr_addvalue( values, "PrimaryModule", REG_SZ,
+ ( char * ) data.buffer,
+ data.uni_str_len *
+ sizeof( uint16 ) );
+ init_unistr2( &data, *elogs, UNI_STR_TERMINATE );
+
+ regval_ctr_addvalue( values, "Sources", REG_MULTI_SZ,
+ ( char * ) data.buffer,
+ data.uni_str_len *
+ sizeof( uint16 ) );
+ regdb_store_values( evtlogpath, values );
-/**********************************************************************
- Allow storing of particular values related to eventlog operation.
-*********************************************************************/
+ }
-static BOOL elog_store_value( const char *key, REGVAL_CTR *values )
-{
- /* the client had to have a valid handle to get here
- so just hand off to the registry tdb */
-
- return regdb_store_values( key, values );
-}
+ TALLOC_FREE( values );
-/********************************************************************
- Table of function pointers for accessing eventlog data
- *******************************************************************/
-
-REGISTRY_OPS eventlog_ops = {
- elog_fetch_keys,
- elog_fetch_values,
- elog_store_keys,
- elog_store_value,
- NULL
-};
+ /* now do the values under KEY_EVENTLOG/Application/Application */
+ slprintf( evtlogpath, sizeof( evtlogpath ) - 1, "%s\\%s\\%s",
+ KEY_EVENTLOG, *elogs, *elogs );
+ if ( !( values = TALLOC_ZERO_P( NULL, REGVAL_CTR ) ) ) {
+ 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,
+ ( char * ) &uiCategoryCount,
+ sizeof( uint32 ) );
+ init_unistr2( &data,
+ "%SystemRoot%\\system32\\eventlog.dll",
+ UNI_STR_TERMINATE );
+
+ regval_ctr_addvalue( values, "CategoryMessageFile",
+ REG_EXPAND_SZ,
+ ( char * ) data.buffer,
+ data.uni_str_len *
+ sizeof( uint16 ) );
+ regdb_store_values( evtlogpath, values );
+ }
+ TALLOC_FREE( values );
+ elogs++;
+ }
+ return True;
+}
diff --git a/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c
index f41c5885bc..f5284e9e88 100644
--- a/source3/registry/reg_frontend.c
+++ b/source3/registry/reg_frontend.c
@@ -38,7 +38,6 @@ REGISTRY_HOOK reg_hooks[] = {
{ KEY_PRINTING, &printing_ops },
{ KEY_PRINTING_2K, &printing_ops },
{ KEY_PRINTING_PORTS, &printing_ops },
- { KEY_EVENTLOG, &eventlog_ops },
{ KEY_SHARES, &shares_reg_ops },
#endif
{ NULL, NULL }
@@ -128,13 +127,10 @@ BOOL init_registry( void )
if ( DEBUGLEVEL >= 20 )
reghook_dump_cache(20);
- /* inform the external eventlog machinery of the change */
-
- eventlog_refresh_external_parameters( get_root_nt_token() );
-
- /* add any services keys */
+ /* add any keys for other services */
svcctl_init_keys();
+ eventlog_init_keys();
return True;
}
diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c
index 8bbb97f226..26da87b280 100644
--- a/source3/rpc_parse/parse_misc.c
+++ b/source3/rpc_parse/parse_misc.c
@@ -830,6 +830,8 @@ void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags)
if (buf) {
/* We always null terminate the copy. */
len = strlen(buf) + 1;
+ if ( flags == UNI_STR_DBLTERMINATE )
+ len++;
} else {
/* no buffer -- nothing to do */
str->uni_max_len = 0;
@@ -859,6 +861,8 @@ void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags)
if (flags == UNI_STR_TERMINATE || flags == UNI_MAXLEN_TERMINATE) {
num_chars++;
}
+ if ( flags == UNI_STR_DBLTERMINATE )
+ num_chars += 2;
}
str->uni_max_len = num_chars;
diff --git a/source3/rpc_parse/parse_ntsvcs.c b/source3/rpc_parse/parse_ntsvcs.c
index f2e4456025..24bf3a455b 100644
--- a/source3/rpc_parse/parse_ntsvcs.c
+++ b/source3/rpc_parse/parse_ntsvcs.c
@@ -79,7 +79,7 @@ BOOL ntsvcs_io_q_get_device_list_size(const char *desc, NTSVCS_Q_GET_DEVICE_LIST
if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
return False;
- if( !prs_align(ps) )
+ if ( !prs_align(ps) )
return False;
if ( !prs_uint32("flags", ps, depth, &q_u->flags) )
diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/rpc_server/srv_eventlog_lib.c
new file mode 100644
index 0000000000..a8c1ad51d2
--- /dev/null
+++ b/source3/rpc_server/srv_eventlog_lib.c
@@ -0,0 +1,620 @@
+
+/*
+ * Unix SMB/CIFS implementation.
+ * Eventlog utility routines
+ * Copyright (C) Marcin Krzysztof Porwit 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
+ * (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"
+
+
+/****************************************************************
+Init an Eventlog TDB, and return it. If null, something bad happened.
+****************************************************************/
+TDB_CONTEXT *init_eventlog_tdb( char *tdbfilename )
+{
+ TDB_CONTEXT *the_tdb;
+
+ unlink( tdbfilename );
+
+ the_tdb =
+ tdb_open_log( tdbfilename, 0, TDB_DEFAULT, O_RDWR | O_CREAT,
+ 0664 );
+ if ( the_tdb == NULL ) {
+ DEBUG( 1, ( "Can't open tdb for [%s]\n", tdbfilename ) );
+ return NULL;
+ }
+ tdb_store_int32( the_tdb, VN_oldest_entry, 1 );
+ tdb_store_int32( the_tdb, VN_next_record, 1 );
+
+ /* initialize with defaults, copy real values in here from registry */
+
+ tdb_store_int32( the_tdb, VN_maxsize, 0x80000 );
+ tdb_store_int32( the_tdb, VN_retention, 0x93A80 );
+
+ tdb_store_int32( the_tdb, VN_version, EVENTLOG_DATABASE_VERSION_V1 );
+ return the_tdb;
+}
+
+/* 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 )
+{
+ if ( !dest_buffer )
+ return NULL;
+ pstring ondisk_name;
+
+ 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;
+}
+
+
+/* count the number of bytes in the TDB */
+
+/* Arg! Static Globals! */
+
+static int eventlog_tdbcount;
+static int eventlog_tdbsize;
+
+/* this function is used to count up the number of bytes in a particular TDB */
+int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
+ void *state )
+{
+ eventlog_tdbsize += data.dsize;
+ eventlog_tdbcount++;
+ 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. */
+
+int eventlog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
+{
+ if ( !tdb )
+ return 0;
+ eventlog_tdbcount = 0;
+ eventlog_tdbsize = 0;
+
+ tdb_traverse( tdb, eventlog_tdb_size_fn, NULL );
+
+ if ( MaxSize != NULL ) {
+ *MaxSize = tdb_fetch_int32( tdb, VN_maxsize );
+ }
+
+ if ( Retention != NULL ) {
+ *Retention = tdb_fetch_int32( tdb, VN_retention );
+ }
+
+ DEBUG( 1,
+ ( "eventlog size: [%d] for [%d] records\n", eventlog_tdbsize,
+ eventlog_tdbcount ) );
+ return eventlog_tdbsize;
+}
+
+
+/*
+ Discard early event logs until we have enough for 'needed' bytes...
+ NO checking done beforehand to see that we actually need to do this, and
+ it's going to pluck records one-by-one. So, it's best to determine that this
+ needs to be done before doing it.
+
+ Setting whack_by_date to True indicates that eventlogs falling outside of the
+ retention range need to go...
+
+*/
+
+/* return True if we made enough room to accommodate needed bytes */
+
+BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
+ BOOL whack_by_date )
+{
+ 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 */
+
+ /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
+ although records not necessarily guaranteed to have successive times */
+ /* */
+ mem_ctx = talloc_init( "make_way_for_eventlogs" ); /* Homage to BPG */
+
+ if ( mem_ctx == NULL )
+ return False; /* can't allocate memory indicates bigger problems */
+ /* lock */
+ tdb_lock_bystring( the_tdb, VN_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 );
+
+ time( &current_time );
+
+ /* calculate ... */
+ exp_time = current_time - Retention; /* discard older than exp_time */
+
+ /* todo - check for sanity in next_record */
+ nbytes = 0;
+
+ DEBUG( 3,
+ ( "MaxSize [%d] Retention [%d] Current Time [%d] exp_time [%d]\n",
+ MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
+ DEBUG( 3,
+ ( "Start Record [%d] End Record [%d]\n", start_record,
+ end_record ) );
+
+ for ( i = start_record; i < end_record; i++ ) {
+ /* read a record, add the amt to nbytes */
+ key.dsize = sizeof( int32 );
+ key.dptr = ( char * ) ( int32 * ) & i;
+ ret = tdb_fetch( the_tdb, key );
+ if ( ret.dsize == 0 ) {
+ DEBUG( 8,
+ ( "Can't find a record for the key, record [%d]\n",
+ i ) );
+ tdb_unlock_bystring( the_tdb, VN_next_record );
+ return False;
+ }
+ nbytes += ret.dsize; /* note this includes overhead */
+
+ len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
+ &tresv1, &trecnum, &timegen, &timewr );
+ DEBUG( 8,
+ ( "read record %d, record size is [%d], total so far [%d]\n",
+ i, reclen, nbytes ) );
+
+ SAFE_FREE( ret.dptr );
+
+ /* note that other servers may just stop writing records when the size limit
+ is reached, and there are no records older than 'retention'. This doesn't
+ like a very useful thing to do, so instead we whack (as in sleeps with the
+ fishes) just enough records to fit the what we need. This behavior could
+ be changed to 'match', if the need arises. */
+
+ if ( !whack_by_date && ( nbytes >= needed ) )
+ break; /* done */
+ if ( whack_by_date && ( timegen >= exp_time ) )
+ break; /* done */
+ }
+
+ DEBUG( 3,
+ ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
+ nbytes, needed, start_record, i ) );
+ /* todo - remove eventlog entries here and set starting record to start_record... */
+ new_start = i;
+ if ( start_record != new_start ) {
+ for ( i = start_record; i < new_start; i++ ) {
+ key.dsize = sizeof( int32 );
+ key.dptr = ( char * ) ( int32 * ) & i;
+ tdb_delete( the_tdb, key );
+ }
+
+ tdb_store_int32( the_tdb, VN_oldest_entry, new_start );
+ }
+ tdb_unlock_bystring( the_tdb, VN_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 )
+{
+ int MaxSize, Retention, CalcdSize;
+
+ if ( !tdb ) {
+ DEBUG( 4, ( "No eventlog tdb handle\n" ) );
+ return False;
+ }
+
+ CalcdSize = eventlog_tdb_size( tdb, &MaxSize, &Retention );
+ DEBUG( 3,
+ ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
+ MaxSize ) );
+
+ if ( CalcdSize > MaxSize ) {
+ return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
+ False );
+ }
+
+ return make_way_for_eventlogs( tdb, 0, True );
+}
+
+BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
+{
+ int calcd_size;
+ int MaxSize, Retention;
+
+ /* see if we can write to the eventlog -- do a policy enforcement */
+ if ( !tdb )
+ return False; /* tdb is null, so we can't write to it */
+
+
+ if ( needed < 0 )
+ return False;
+ MaxSize = 0;
+ Retention = 0;
+
+ calcd_size = eventlog_tdb_size( tdb, &MaxSize, &Retention );
+
+ if ( calcd_size <= MaxSize )
+ return True; /* you betcha */
+ if ( calcd_size + needed < MaxSize )
+ return True;
+
+ if ( Retention == 0xffffffff ) {
+ return False; /* see msdn - we can't write no room, discard */
+ }
+ /*
+ note don't have to test, but always good to show intent, in case changes needed
+ later
+ */
+
+ if ( Retention == 0x00000000 ) {
+ /* discard record(s) */
+ /* todo - decide when to remove a bunch vs. just what we need... */
+ return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
+ True );
+ }
+
+ 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_RDWR | O_CREAT,
+ 0664 );
+ if ( the_tdb == NULL ) {
+ return init_eventlog_tdb( tdbfilename );
+ }
+ if ( EVENTLOG_DATABASE_VERSION_V1 !=
+ tdb_fetch_int32( the_tdb, VN_version ) ) {
+ tdb_close( the_tdb );
+ return init_eventlog_tdb( tdbfilename );
+ }
+ return the_tdb;
+}
+
+/* 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 */
+int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
+{
+ int32 next_record;
+ uint8 *packed_ee;
+ TALLOC_CTX *mem_ctx = NULL;
+ TDB_DATA kbuf, ebuf;
+ uint32 n_packed;
+
+ if ( !ee )
+ return 0;
+
+ mem_ctx = talloc_init( "write_eventlog_tdb" );
+
+ if ( mem_ctx == NULL )
+ return 0;
+
+ if ( !ee )
+ return 0;
+ /* discard any entries that have bogus time, which usually indicates a bogus entry as well. */
+ if ( ee->record.time_generated == 0 )
+ return 0;
+
+#define MARGIN 512
+
+ /* todo - check for sanity in next_record */
+
+ fixup_eventlog_entry( ee );
+
+ if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) {
+ DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) );
+ talloc_destroy( mem_ctx );
+ return 0;
+ }
+
+ /* alloc mem for the packed version */
+ packed_ee = TALLOC( mem_ctx, ee->record.length + MARGIN );
+ if ( !packed_ee ) {
+ talloc_destroy( mem_ctx );
+ return 0;
+ }
+
+ /* need to read the record number and insert it into the entry here */
+
+ /* lock */
+ tdb_lock_bystring( the_tdb, VN_next_record, 1 );
+ /* read */
+ next_record = tdb_fetch_int32( the_tdb, VN_next_record );
+
+ n_packed =
+ tdb_pack( packed_ee, ee->record.length + MARGIN,
+ "ddddddwwwwddddddBBdBBBd", ee->record.length,
+ ee->record.reserved1, next_record,
+ ee->record.time_generated, ee->record.time_written,
+ ee->record.event_id, ee->record.event_type,
+ ee->record.num_strings, ee->record.event_category,
+ ee->record.reserved2,
+ ee->record.closing_record_number,
+ ee->record.string_offset,
+ ee->record.user_sid_length,
+ ee->record.user_sid_offset, ee->record.data_length,
+ ee->record.data_offset,
+ ee->data_record.source_name_len,
+ ee->data_record.source_name,
+ ee->data_record.computer_name_len,
+ ee->data_record.computer_name,
+ ee->data_record.sid_padding,
+ ee->record.user_sid_length, ee->data_record.sid,
+ ee->data_record.strings_len,
+ ee->data_record.strings,
+ ee->data_record.user_data_len,
+ ee->data_record.user_data,
+ ee->data_record.data_padding );
+
+ /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */
+
+ /* increment the record count */
+
+ kbuf.dsize = sizeof( int32 );
+ kbuf.dptr = ( uint8 * ) & next_record;
+
+ ebuf.dsize = n_packed;
+ ebuf.dptr = packed_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 );
+ 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 );
+ talloc_destroy( mem_ctx );
+ return ( next_record - 1 );
+}
+
+/* calculate the correct fields etc for an eventlog entry */
+
+void fixup_eventlog_entry( Eventlog_entry * ee )
+{
+ /* fix up the eventlog entry structure as necessary */
+
+ ee->data_record.sid_padding =
+ ( ( 4 -
+ ( ( ee->data_record.source_name_len +
+ ee->data_record.computer_name_len ) % 4 ) ) % 4 );
+ ee->data_record.data_padding =
+ ( 4 -
+ ( ( ee->data_record.strings_len +
+ ee->data_record.user_data_len ) % 4 ) ) % 4;
+ ee->record.length = sizeof( Eventlog_record );
+ ee->record.length += ee->data_record.source_name_len;
+ ee->record.length += ee->data_record.computer_name_len;
+ if ( ee->record.user_sid_length == 0 ) {
+ /* Should not pad to a DWORD boundary for writing out the sid if there is
+ no SID, so just propagate the padding to pad the data */
+ ee->data_record.data_padding += ee->data_record.sid_padding;
+ ee->data_record.sid_padding = 0;
+ }
+ /* DEBUG(10, ("sid_padding is [%d].\n", ee->data_record.sid_padding)); */
+ /* DEBUG(10, ("data_padding is [%d].\n", ee->data_record.data_padding)); */
+
+ ee->record.length += ee->data_record.sid_padding;
+ ee->record.length += ee->record.user_sid_length;
+ ee->record.length += ee->data_record.strings_len;
+ ee->record.length += ee->data_record.user_data_len;
+ ee->record.length += ee->data_record.data_padding;
+ /* need another copy of length at the end of the data */
+ ee->record.length += sizeof( ee->record.length );
+}
+
+/********************************************************************
+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 )
+{
+ char *start = NULL, *stop = NULL;
+ pstring temp;
+ int temp_len = 0;
+
+ start = line;
+
+ /* empty line signyfiying record delimeter, or we're at the end of the buffer */
+ if ( start == NULL || strlen( start ) == 0 ) {
+ DEBUG( 6,
+ ( "parse_logentry: found end-of-record indicator.\n" ) );
+ *eor = True;
+ return True;
+ }
+ if ( !( stop = strchr( line, ':' ) ) ) {
+ return False;
+ }
+
+ DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
+
+ if ( 0 == strncmp( start, "LEN", stop - start ) ) {
+ /* This will get recomputed later anyway -- probably not necessary */
+ entry->record.length = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
+ /* For now all these reserved entries seem to have the same value,
+ which can be hardcoded to int(1699505740) for now */
+ entry->record.reserved1 = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
+ entry->record.record_number = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
+ entry->record.time_generated = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
+ entry->record.time_written = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
+ entry->record.event_id = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
+ if ( strstr( start, "ERROR" ) ) {
+ entry->record.event_type = EVENTLOG_ERROR_TYPE;
+ } else if ( strstr( start, "WARNING" ) ) {
+ entry->record.event_type = EVENTLOG_WARNING_TYPE;
+ } else if ( strstr( start, "INFO" ) ) {
+ entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
+ } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
+ entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
+ } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
+ entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
+ } else if ( strstr( start, "SUCCESS" ) ) {
+ entry->record.event_type = EVENTLOG_SUCCESS;
+ } else {
+ /* some other eventlog type -- currently not defined in MSDN docs, so error out */
+ return False;
+ }
+ }
+
+/*
+ else if(0 == strncmp(start, "NST", stop - start))
+ {
+ entry->record.num_strings = atoi(stop + 1);
+ }
+*/
+ else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
+ entry->record.event_category = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
+ entry->record.reserved2 = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
+ entry->record.closing_record_number = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
+ entry->record.user_sid_length = atoi( stop + 1 );
+ } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
+ memset( temp, 0, sizeof( temp ) );
+ stop++;
+ while ( isspace( stop[0] ) ) {
+ stop++;
+ }
+ temp_len = strlen( stop );
+ strncpy( temp, stop, temp_len );
+ rpcstr_push( ( void * ) ( entry->data_record.source_name ),
+ temp, sizeof( entry->data_record.source_name ),
+ STR_TERMINATE );
+ entry->data_record.source_name_len =
+ ( strlen_w( entry->data_record.source_name ) * 2 ) +
+ 2;
+ } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
+ memset( temp, 0, sizeof( temp ) );
+ stop++;
+ while ( isspace( stop[0] ) ) {
+ stop++;
+ }
+ temp_len = strlen( stop );
+ strncpy( temp, stop, temp_len );
+ rpcstr_push( ( void * ) ( entry->data_record.computer_name ),
+ temp, sizeof( entry->data_record.computer_name ),
+ STR_TERMINATE );
+ entry->data_record.computer_name_len =
+ ( strlen_w( entry->data_record.computer_name ) * 2 ) +
+ 2;
+ } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
+ memset( temp, 0, sizeof( temp ) );
+ stop++;
+ while ( isspace( stop[0] ) ) {
+ stop++;
+ }
+ temp_len = strlen( stop );
+ strncpy( temp, stop, temp_len );
+ rpcstr_push( ( void * ) ( entry->data_record.sid ), temp,
+ sizeof( entry->data_record.sid ),
+ STR_TERMINATE );
+ entry->record.user_sid_length =
+ ( strlen_w( entry->data_record.sid ) * 2 ) + 2;
+ } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
+ /* skip past initial ":" */
+ stop++;
+ /* now skip any other leading whitespace */
+ while ( isspace( stop[0] ) ) {
+ stop++;
+ }
+ temp_len = strlen( stop );
+ memset( temp, 0, sizeof( temp ) );
+ strncpy( temp, stop, temp_len );
+ rpcstr_push( ( void * ) ( entry->data_record.strings +
+ entry->data_record.strings_len ),
+ temp,
+ sizeof( entry->data_record.strings ) -
+ entry->data_record.strings_len, STR_TERMINATE );
+ entry->data_record.strings_len += temp_len + 1;
+ entry->record.num_strings++;
+ } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
+ /* Now that we're done processing the STR data, adjust the length to account for
+ unicode, then proceed with the DAT data. */
+ entry->data_record.strings_len *= 2;
+ /* skip past initial ":" */
+ stop++;
+ /* now skip any other leading whitespace */
+ while ( isspace( stop[0] ) ) {
+ stop++;
+ }
+ entry->data_record.user_data_len = strlen( stop );
+ memset( entry->data_record.user_data, 0,
+ sizeof( entry->data_record.user_data ) );
+ if ( entry->data_record.user_data_len > 0 ) {
+ /* copy no more than the first 1024 bytes */
+ if ( entry->data_record.user_data_len >
+ sizeof( entry->data_record.user_data ) )
+ entry->data_record.user_data_len =
+ sizeof( entry->data_record.
+ user_data );
+ memcpy( entry->data_record.user_data, stop,
+ entry->data_record.user_data_len );
+ }
+ } else {
+ /* some other eventlog entry -- not implemented, so dropping on the floor */
+ DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
+ /* For now return true so that we can keep on parsing this mess. Eventually
+ we will return False here. */
+ return True;
+ }
+ return True;
+}
diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c
index 414c99d28e..6067c94fe8 100644
--- a/source3/rpc_server/srv_eventlog_nt.c
+++ b/source3/rpc_server/srv_eventlog_nt.c
@@ -2,6 +2,7 @@
* Unix SMB/CIFS implementation.
* RPC Pipe client / server 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
@@ -18,12 +19,23 @@
* 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
+#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;
@@ -32,54 +44,295 @@ typedef struct {
uint32 flags;
} EventlogInfo;
-
+
+
+#if 0 /* UNUSED */
/********************************************************************
- Inform the external eventlog machinery of default values (on startup
- probably)
-********************************************************************/
+ ********************************************************************/
+
+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 */
+
+/********************************************************************
+ ********************************************************************/
-void eventlog_refresh_external_parameters( NT_USER_TOKEN *token )
+static void refresh_eventlog_tdb_table( void )
{
- const char **elogs = lp_eventlog_list();
- int i;
+ const char **elogs = lp_eventlog_list( );
+ int i, j;
if ( !elogs )
- return ;
+ return;
- if ( !*lp_eventlog_control_cmd() )
+ 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;
+ }
+ }
+ }
+ }
- for ( i=0; elogs[i]; i++ ) {
-
- DEBUG(10,("eventlog_refresh_external_parameters: Refreshing =>[%s]\n",
- elogs[i]));
-
- if ( !control_eventlog_hook( token, elogs[i] ) ) {
- DEBUG(0,("eventlog_refresh_external_parameters: failed to refresh [%s]\n",
- elogs[i]));
+ /* 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;
}
- }
-
- 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;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-static void free_eventlog_info(void *ptr)
+TDB_CONTEXT *tdb_of( char *eventlog_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;
+ }
+ }
+
+ 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;
+}
+
+
+/********************************************************************
+ For the given tdb, get the next eventlog record into the passed
+ Eventlog_entry. returns NULL if it can't get the record for some reason.
+ ********************************************************************/
+
+Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb,
+ int recno, Eventlog_entry * ee )
+{
+ TDB_DATA ret, key;
+
+ int srecno;
+ int reclen;
+ int len;
+ uint8 *rbuff;
+
+ pstring *wpsource, *wpcomputer, *wpsid, *wpstrs, *puserdata;
+
+ key.dsize = sizeof( int32 );
+ rbuff = NULL;
+
+ srecno = recno;
+ key.dptr = ( char * ) &srecno;
+
+ ret = tdb_fetch( tdb, key );
+
+ if ( ret.dsize == 0 ) {
+ DEBUG( 8,
+ ( "Can't find a record for the key, record %d\n",
+ recno ) );
+ return NULL;
+ }
+
+ len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen );
+
+ DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) );
+
+ if ( !len )
+ return NULL;
+
+ /* ee = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); */
+
+ if ( !ee )
+ return NULL;
+
+ len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd",
+ &ee->record.length, &ee->record.reserved1,
+ &ee->record.record_number,
+ &ee->record.time_generated,
+ &ee->record.time_written, &ee->record.event_id,
+ &ee->record.event_type, &ee->record.num_strings,
+ &ee->record.event_category, &ee->record.reserved2,
+ &ee->record.closing_record_number,
+ &ee->record.string_offset,
+ &ee->record.user_sid_length,
+ &ee->record.user_sid_offset,
+ &ee->record.data_length, &ee->record.data_offset,
+ &ee->data_record.source_name_len, &wpsource,
+ &ee->data_record.computer_name_len, &wpcomputer,
+ &ee->data_record.sid_padding,
+ &ee->record.user_sid_length, &wpsid,
+ &ee->data_record.strings_len, &wpstrs,
+ &ee->data_record.user_data_len, &puserdata,
+ &ee->data_record.data_padding );
+ DEBUG( 10,
+ ( "Read record %d, len in tdb was %d\n",
+ ee->record.record_number, len ) );
+
+ /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff
+ into it's 2nd argment for 'B' */
+
+ if ( wpcomputer )
+ memcpy( ee->data_record.computer_name, wpcomputer,
+ ee->data_record.computer_name_len );
+ if ( wpsource )
+ memcpy( ee->data_record.source_name, wpsource,
+ ee->data_record.source_name_len );
+
+ if ( wpsid )
+ memcpy( ee->data_record.sid, wpsid,
+ ee->record.user_sid_length );
+ if ( wpstrs )
+ memcpy( ee->data_record.strings, wpstrs,
+ ee->data_record.strings_len );
+
+ /* note that userdata is a pstring */
+ if ( puserdata )
+ memcpy( ee->data_record.user_data, puserdata,
+ ee->data_record.user_data_len );
+
+ SAFE_FREE( wpcomputer );
+ SAFE_FREE( wpsource );
+ SAFE_FREE( wpsid );
+ SAFE_FREE( wpstrs );
+ SAFE_FREE( puserdata );
+
+ DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) );
+ DEBUG( 10,
+ ( "get_eventlog_record: computer_name %d is ",
+ ee->data_record.computer_name_len ) );
+ SAFE_FREE( ret.dptr );
+ 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)
+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"));
+
+ if ( !find_policy_by_hnd( p, handle, ( void ** ) &info ) ) {
+ DEBUG( 2,
+ ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
return NULL;
}
@@ -87,144 +340,85 @@ static EventlogInfo *find_eventlog_info_by_hnd(pipes_struct *p, POLICY_HND *hand
}
/********************************************************************
- Callout to control the specified event log - passing out only
- the MaxSize and Retention values, along with eventlog name
- uses smbrun...
- INPUT: <control_cmd> <log name> <retention> <maxsize>
- OUTPUT: nothing
-********************************************************************/
+ note that this can only be called AFTER the table is constructed,
+ since it uses the table to find the tdb handle
+ ********************************************************************/
-BOOL control_eventlog_hook(NT_USER_TOKEN *token, const char *elogname )
+static BOOL sync_eventlog_params( const char *elogname )
{
- char *cmd = lp_eventlog_control_cmd();
- pstring command;
- int ret;
- int fd = -1;
- uint32 uiMaxSize, uiRetention;
pstring path;
+ uint32 uiMaxSize;
+ uint32 uiRetention;
REGISTRY_KEY *keyinfo;
REGISTRY_VALUE *val;
REGVAL_CTR *values;
WERROR wresult;
+ TDB_CONTEXT *the_tdb;
+
+ the_tdb = tdb_of( ( char * ) elogname );
+
+ DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("control_eventlog_hook: No \"eventlog control command\" defined in smb.conf!\n"));
+ if ( !the_tdb ) {
+ DEBUG( 4, ( "Can't open tdb for %s\n", elogname ) );
return False;
}
-
/* set resonable defaults. 512Kb on size and 1 week on time */
-
+
uiMaxSize = 0x80000;
uiRetention = 604800;
-
+
/* the general idea is to internally open the registry
key and retreive the values. That way we can continue
to use the same fetch/store api that we use in
srv_reg_nt.c */
pstr_sprintf( path, "%s/%s", KEY_EVENTLOG, elogname );
- wresult = regkey_open_internal( &keyinfo, path, token, REG_KEY_READ );
-
+
+ wresult =
+ regkey_open_internal( &keyinfo, path, get_root_nt_token( ),
+ REG_KEY_READ );
+
if ( !W_ERROR_IS_OK( wresult ) ) {
- DEBUG(4,("control_eventlog_hook: Failed to open key [%s] (%s)\n",
- path, dos_errstr(wresult) ));
+ DEBUG( 4,
+ ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
+ path, dos_errstr( wresult ) ) );
return False;
}
-
- if ( !(values = TALLOC_ZERO_P( keyinfo, REGVAL_CTR )) ) {
+
+ if ( !( values = TALLOC_ZERO_P( keyinfo, REGVAL_CTR ) ) ) {
TALLOC_FREE( keyinfo );
- DEBUG(0,("control_eventlog_hook: talloc() failed!\n"));
-
+ DEBUG( 0, ( "control_eventlog_hook: talloc() failed!\n" ) );
+
return False;
}
fetch_reg_values( keyinfo, values );
-
- if ( (val = regval_ctr_getvalue( values, "Retention" )) != NULL )
- uiRetention = IVAL( regval_data_p(val), 0 );
- if ( (val = regval_ctr_getvalue( values, "MaxSize" )) != NULL )
- uiMaxSize = IVAL( regval_data_p(val), 0 );
-
- TALLOC_FREE( keyinfo );
-
- /* now run the command */
+ if ( ( val = regval_ctr_getvalue( values, "Retention" ) ) != NULL )
+ uiRetention = IVAL( regval_data_p( val ), 0 );
- pstr_sprintf(command, "%s \"%s\" %u %u", cmd, elogname, uiRetention, uiMaxSize );
+ if ( ( val = regval_ctr_getvalue( values, "MaxSize" ) ) != NULL )
+ uiMaxSize = IVAL( regval_data_p( val ), 0 );
- DEBUG(10, ("control_eventlog_hook: Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
+ TALLOC_FREE( keyinfo );
- if ( ret != 0 ) {
- DEBUG(10,("control_eventlog_hook: Command returned [%d]\n", ret));
- if (fd != -1 )
- close(fd);
- return False;
- }
+ tdb_store_int32( the_tdb, VN_maxsize, uiMaxSize );
+ tdb_store_int32( the_tdb, VN_retention, uiRetention );
- close(fd);
return True;
}
-
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-/**
- * Callout to open the specified event log
- *
- * smbrun calling convention --
- * INPUT: <open_cmd> <log name> <policy handle>
- * OUTPUT: the string "SUCCESS" if the command succeeded
- * no such string if there was a failure.
- */
-static BOOL open_eventlog_hook( EventlogInfo *info )
+static BOOL open_eventlog_hook( EventlogInfo * info )
{
- char *cmd = lp_eventlog_open_cmd();
- char **qlines;
- pstring command;
- int numlines = 0;
- int ret;
- int fd = -1;
-
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n"));
- return False;
- }
-
- pstr_sprintf(command, "%s \"%s\"", cmd, info->logname );
-
- DEBUG(10, ("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
-
- if(ret != 0) {
- if(fd != -1) {
- close(fd);
- }
- return False;
- }
-
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
- close(fd);
-
- if(numlines) {
- DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
- if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) {
- DEBUGADD(10, ("Able to open [%s].\n", info->logname));
- file_lines_free(qlines);
- return True;
- }
- }
-
- file_lines_free(qlines);
-
- return False;
+ return True;
}
/********************************************************************
********************************************************************/
+
/**
* Callout to get the number of records in the specified event log
*
@@ -234,50 +428,49 @@ static BOOL open_eventlog_hook( EventlogInfo *info )
* 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( EventlogInfo * info )
{
- char *cmd = lp_eventlog_num_records_cmd();
- char **qlines;
- pstring command;
- int numlines = 0;
- int ret;
- int fd = -1;
-
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n"));
- return False;
- }
- pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
+ TDB_CONTEXT *the_tdb = NULL;
+ int next_record;
+ int oldest_record;
- DEBUG(10, ("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
- if(ret != 0) {
- if(fd != -1) {
- close(fd);
- }
+ the_tdb = tdb_of( info->logname );
+
+ if ( !the_tdb ) {
+ DEBUG( 10, ( "Can't find tdb for %s\n", info->logname ) );
+ info->num_records = 0;
return False;
}
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
- close(fd);
+ /* 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 );
+
+
+
+ DEBUG( 8,
+ ( "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;
- if(numlines) {
- DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
- sscanf(qlines[0], "%d", &(info->num_records));
- file_lines_free(qlines);
- return True;
- }
- file_lines_free(qlines);
- return False;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
/**
* Callout to find the oldest record in the log
@@ -289,50 +482,17 @@ static BOOL get_num_records_hook(EventlogInfo *info)
* 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( EventlogInfo * info )
{
- char *cmd = lp_eventlog_oldest_record_cmd();
- char **qlines;
- pstring command;
- int numlines = 0;
- int ret;
- int fd = -1;
-
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n"));
- return False;
- }
-
- pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
-
- DEBUG(10, ("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
- if(ret != 0) {
- if(fd != -1) {
- close(fd);
- }
- return False;
- }
-
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
- close(fd);
-
- if(numlines) {
- DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
- sscanf(qlines[0], "%d", &(info->oldest_entry));
- file_lines_free(qlines);
- return True;
- }
-
- file_lines_free(qlines);
- return False;
+ /* it's the same thing */
+ return get_num_records_hook( info );
}
+
/********************************************************************
-********************************************************************/
+ ********************************************************************/
+
/**
* Callout to close the specified event log
*
@@ -342,323 +502,51 @@ static BOOL get_oldest_entry_hook(EventlogInfo *info)
* no such string if there was a failure.
*/
-static BOOL close_eventlog_hook(EventlogInfo *info)
-{
- char *cmd = lp_eventlog_close_cmd();
- char **qlines;
- pstring command;
- int numlines = 0;
- int ret;
- int fd = -1;
-
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n"));
- return False;
- }
-
- pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
-
- DEBUG(10, ("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
-
- if(ret != 0) {
- if(fd != -1) {
- close(fd);
- }
- return False;
- }
-
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
- close(fd);
-
- if(numlines) {
- DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
- if(0 == strncmp(qlines[0], "SUCCESS", 7)) {
- DEBUGADD(10, ("Able to close [%s].\n", info->logname));
- file_lines_free(qlines);
- return True;
- }
- }
-
- file_lines_free(qlines);
- return False;
-}
-
-/********************************************************************
-********************************************************************/
-
-static BOOL parse_logentry(char *line, Eventlog_entry *entry, BOOL *eor)
+static BOOL close_eventlog_hook( EventlogInfo * info )
{
- char *start = NULL, *stop = NULL;
- pstring temp;
- int temp_len = 0, i;
-
- start = line;
- /* empty line signyfiying record delimeter, or we're at the end of the buffer */
- if(start == NULL || strlen(start) == 0) {
- DEBUG(6, ("parse_logentry: found end-of-record indicator.\n"));
- *eor = True;
- return True;
- }
- if(!(stop = strchr(line, ':'))) {
- return False;
- }
-
- DEBUG(6, ("parse_logentry: trying to parse [%s].\n", line));
-
- if(0 == strncmp(start, "LEN", stop - start)) {
- /* This will get recomputed later anyway -- probably not necessary */
- entry->record.length = atoi(stop + 1);
- } else if(0 == strncmp(start, "RS1", stop - start)) {
- /* For now all these reserved entries seem to have the same value,
- which can be hardcoded to int(1699505740) for now */
- entry->record.reserved1 = atoi(stop + 1);
- } else if(0 == strncmp(start, "RCN", stop - start)) {
- entry->record.record_number = atoi(stop + 1);
- } else if(0 == strncmp(start, "TMG", stop - start)) {
- entry->record.time_generated = atoi(stop + 1);
- } else if(0 == strncmp(start, "TMW", stop - start)) {
- entry->record.time_written = atoi(stop + 1);
- } else if(0 == strncmp(start, "EID", stop - start)) {
- entry->record.event_id = atoi(stop + 1);
- } else if(0 == strncmp(start, "ETP", stop - start)) {
- if(strstr(start, "ERROR")) {
- entry->record.event_type = EVENTLOG_ERROR_TYPE;
- } else if(strstr(start, "WARNING")) {
- entry->record.event_type = EVENTLOG_WARNING_TYPE;
- } else if(strstr(start, "INFO")) {
- entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
- } else if(strstr(start, "AUDIT_SUCCESS")) {
- entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
- } else if(strstr(start, "AUDIT_FAILURE")) {
- entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
- } else if(strstr(start, "SUCCESS")) {
- entry->record.event_type = EVENTLOG_SUCCESS;
- } else {
- /* some other eventlog type -- currently not defined in MSDN docs, so error out */
- return False;
- }
- }
-/*
- else if(0 == strncmp(start, "NST", stop - start))
- {
- entry->record.num_strings = atoi(stop + 1);
- }
-*/
- else if(0 == strncmp(start, "ECT", stop - start)) {
- entry->record.event_category = atoi(stop + 1);
- } else if(0 == strncmp(start, "RS2", stop - start)) {
- entry->record.reserved2 = atoi(stop + 1);
- } else if(0 == strncmp(start, "CRN", stop - start)) {
- entry->record.closing_record_number = atoi(stop + 1);
- } else if(0 == strncmp(start, "USL", stop - start)) {
- entry->record.user_sid_length = atoi(stop + 1);
- } else if(0 == strncmp(start, "SRC", stop - start)) {
- memset(temp, 0, sizeof(temp));
- stop++;
- while(isspace(stop[0])) {
- stop++;
- }
- temp_len = strlen(stop);
- strncpy(temp, stop, temp_len);
- rpcstr_push((void *)(entry->data_record.source_name), temp,
- sizeof(entry->data_record.source_name), STR_TERMINATE);
- entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2;
- } else if(0 == strncmp(start, "SRN", stop - start)) {
- memset(temp, 0, sizeof(temp));
- stop++;
- while(isspace(stop[0])) {
- stop++;
- }
- temp_len = strlen(stop);
- strncpy(temp, stop, temp_len);
- rpcstr_push((void *)(entry->data_record.computer_name), temp,
- sizeof(entry->data_record.computer_name), STR_TERMINATE);
- entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2;
- } else if(0 == strncmp(start, "SID", stop - start)) {
- memset(temp, 0, sizeof(temp));
- stop++;
- while(isspace(stop[0])) {
- stop++;
- }
- temp_len = strlen(stop);
- strncpy(temp, stop, temp_len);
- rpcstr_push((void *)(entry->data_record.sid), temp,
- sizeof(entry->data_record.sid), STR_TERMINATE);
- entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2;
- } else if(0 == strncmp(start, "STR", stop - start)) {
- /* skip past initial ":" */
- stop++;
- /* now skip any other leading whitespace */
- while(isspace(stop[0])) {
- stop++;
- }
- temp_len = strlen(stop);
- memset(temp, 0, sizeof(temp));
- strncpy(temp, stop, temp_len);
- rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len),
- temp,
- sizeof(entry->data_record.strings) - entry->data_record.strings_len,
- STR_TERMINATE);
- entry->data_record.strings_len += temp_len + 1;
- fprintf(stderr, "Dumping strings:\n");
- for(i = 0; i < entry->data_record.strings_len; i++) {
- fputc((char)entry->data_record.strings[i], stderr);
- }
- fprintf(stderr, "\nDone\n");
- entry->record.num_strings++;
- } else if(0 == strncmp(start, "DAT", stop - start)) {
- /* Now that we're done processing the STR data, adjust the length to account for
- unicode, then proceed with the DAT data. */
- entry->data_record.strings_len *= 2;
- /* skip past initial ":" */
- stop++;
- /* now skip any other leading whitespace */
- while(isspace(stop[0])) {
- stop++;
- }
- entry->data_record.user_data_len = strlen(stop);
- memset(entry->data_record.user_data, 0, sizeof(entry->data_record.user_data));
- if(entry->data_record.user_data_len > 0) {
- /* copy no more than the first 1024 bytes */
- if(entry->data_record.user_data_len > sizeof(entry->data_record.user_data))
- entry->data_record.user_data_len = sizeof(entry->data_record.user_data);
- memcpy(entry->data_record.user_data, stop, entry->data_record.user_data_len);
- }
- } else {
- /* some other eventlog entry -- not implemented, so dropping on the floor */
- DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line));
- /* For now return true so that we can keep on parsing this mess. Eventually
- we will return False here. */
- return True;
- }
return True;
}
/********************************************************************
-********************************************************************/
-
-/**
- * Callout to read entries from the specified event log
- *
- * smbrun calling convention --
- * INPUT: <read_cmd> <log name> <direction> <starting record> <buffer size> <policy handle>
- * where direction is either "forward" or "backward", the starting record is somewhere
- * between the oldest_record and oldest_record+num_records, and the buffer size is the
- * maximum size of the buffer that the client can accomodate.
- * OUTPUT: A buffer containing a set of entries, one to a line, of the format:
- * Multiple log entries can be contained in the buffer, delimited by an empty line
- * line type:line data
- * These are the allowed line types:
- * RS1:(uint32) - reserved. All M$ entries seem to have int(1699505740) for now
- * RCN:(uint32) - record number of the record, however it may be calculated by the script
- * TMG:(uint32) - time generated, seconds since January 1, 1970, 0000 UTC
- * TMW:(uint32) - time written, seconds since January 1, 1970, 0000 UTC
- * EID:(uint32) - eventlog source defined event identifier. If there's a stringfile for the event, it is an index into that
- * ETP:(uint16) - eventlog type - one of ERROR, WARNING, INFO, AUDIT_SUCCESS, AUDIT_FAILURE
- * ECT:(uint16) - event category - depends on the eventlog generator...
- * RS2:(uint16) - reserved, make it 0000
- * CRN:(uint32) - reserved, make it 00000000 for now
- * USL:(uint32) - user SID length. No sid? Make this 0. Must match SID below
- * SRC:[(uint8)] - Name of the source, for example ccPwdSvc, in hex bytes. Can not be multiline.
- * SRN:[(uint8)] - Name of the computer on which this is generated, the short hostname usually.
- * SID:[(uint8)] - User sid if one exists. Must be present even if there is no SID.
- * STR:[(uint8)] - String data. One string per line. Multiple strings can be specified using consecutive "STR" lines,
- * up to a total aggregate string length of 1024 characters.
- * DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines.
- * <empty line> - end-of-record indicator
- */
-
-static BOOL read_eventlog_hook(EventlogInfo *info, Eventlog_entry *entry,
- const char *direction, int starting_record,
- int buffer_size, BOOL *eof,
- char ***buffer, int *numlines)
-{
- char *cmd = lp_eventlog_read_cmd();
- pstring command;
- int ret;
- int fd = -1;
-
- if ( !info )
- return False;
-
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n"));
- return False;
- }
-
- pstr_sprintf( command, "%s \"%s\" %s %d %d",
- cmd, info->logname, direction, starting_record, buffer_size );
-
- *numlines = 0;
-
- DEBUG(10, ("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
-
- if(ret != 0) {
- if(fd != -1) {
- close(fd);
- }
- return False;
- }
-
- *buffer = fd_lines_load(fd, numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
- close(fd);
-
- if(*numlines) {
- /*
- for(i = 0; i < numlines; i++)
- {
- DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
- parse_logentry(qlines[i], entry);
- }
- file_lines_free(qlines);
- */
- *eof = False;
- return True;
- }
- *eof = True;
-
-/* file_lines_free(qlines);*/
- return False;
-}
-
-/********************************************************************
-********************************************************************/
+ ********************************************************************/
-static Eventlog_entry *read_package_entry(prs_struct *ps,
- EVENTLOG_Q_READ_EVENTLOG *q_u,
- EVENTLOG_R_READ_EVENTLOG *r_u,
- Eventlog_entry *entry)
+static Eventlog_entry *read_package_entry( prs_struct * ps,
+ EVENTLOG_Q_READ_EVENTLOG * q_u,
+ EVENTLOG_R_READ_EVENTLOG * r_u,
+ Eventlog_entry * entry )
{
uint8 *offset;
Eventlog_entry *ee_new = NULL;
- ee_new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1);
- if(ee_new == NULL) {
+ ee_new = PRS_ALLOC_MEM( ps, Eventlog_entry, 1 );
+ if ( ee_new == NULL ) {
return NULL;
}
- entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len
- + entry->data_record.computer_name_len) % 4)) %4);
- entry->data_record.data_padding = (4 - ((entry->data_record.strings_len
- + entry->data_record.user_data_len) % 4)) % 4;
- entry->record.length = sizeof(Eventlog_record);
+ entry->data_record.sid_padding =
+ ( ( 4 -
+ ( ( entry->data_record.source_name_len +
+ entry->data_record.computer_name_len ) % 4 ) ) % 4 );
+ entry->data_record.data_padding =
+ ( 4 -
+ ( ( entry->data_record.strings_len +
+ entry->data_record.user_data_len ) % 4 ) ) % 4;
+ entry->record.length = sizeof( Eventlog_record );
entry->record.length += entry->data_record.source_name_len;
entry->record.length += entry->data_record.computer_name_len;
- if(entry->record.user_sid_length == 0) {
+ if ( entry->record.user_sid_length == 0 ) {
/* Should not pad to a DWORD boundary for writing out the sid if there is
no SID, so just propagate the padding to pad the data */
- entry->data_record.data_padding += entry->data_record.sid_padding;
+ entry->data_record.data_padding +=
+ entry->data_record.sid_padding;
entry->data_record.sid_padding = 0;
}
- DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding));
- DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding));
+ DEBUG( 10,
+ ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) );
+ DEBUG( 10,
+ ( "data_padding is [%d].\n",
+ entry->data_record.data_padding ) );
entry->record.length += entry->data_record.sid_padding;
entry->record.length += entry->record.user_sid_length;
@@ -666,66 +554,82 @@ static Eventlog_entry *read_package_entry(prs_struct *ps,
entry->record.length += entry->data_record.user_data_len;
entry->record.length += entry->data_record.data_padding;
/* need another copy of length at the end of the data */
- entry->record.length += sizeof(entry->record.length);
- DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length));
- entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length));
- if(entry->data == NULL) {
+ entry->record.length += sizeof( entry->record.length );
+ DEBUG( 10,
+ ( "entry->record.length is [%d].\n", entry->record.length ) );
+ entry->data =
+ PRS_ALLOC_MEM( ps, uint8,
+ entry->record.length -
+ sizeof( Eventlog_record ) -
+ sizeof( entry->record.length ) );
+ if ( entry->data == NULL ) {
return NULL;
}
offset = entry->data;
- memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len);
+ memcpy( offset, &( entry->data_record.source_name ),
+ entry->data_record.source_name_len );
offset += entry->data_record.source_name_len;
- memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len);
+ memcpy( offset, &( entry->data_record.computer_name ),
+ entry->data_record.computer_name_len );
offset += entry->data_record.computer_name_len;
/* SID needs to be DWORD-aligned */
offset += entry->data_record.sid_padding;
- entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data);
- memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length);
+ entry->record.user_sid_offset =
+ sizeof( Eventlog_record ) + ( offset - entry->data );
+ memcpy( offset, &( entry->data_record.sid ),
+ entry->record.user_sid_length );
offset += entry->record.user_sid_length;
/* Now do the strings */
- entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data);
- memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len);
+ entry->record.string_offset =
+ sizeof( Eventlog_record ) + ( offset - entry->data );
+ memcpy( offset, &( entry->data_record.strings ),
+ entry->data_record.strings_len );
offset += entry->data_record.strings_len;
/* Now do the data */
entry->record.data_length = entry->data_record.user_data_len;
- entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data);
- memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len);
+ entry->record.data_offset =
+ sizeof( Eventlog_record ) + ( offset - entry->data );
+ memcpy( offset, &( entry->data_record.user_data ),
+ entry->data_record.user_data_len );
offset += entry->data_record.user_data_len;
- memcpy(&(ee_new->record), &entry->record, sizeof(Eventlog_record));
- memcpy(&(ee_new->data_record), &entry->data_record, sizeof(Eventlog_data_record));
+ memcpy( &( ee_new->record ), &entry->record,
+ sizeof( Eventlog_record ) );
+ memcpy( &( ee_new->data_record ), &entry->data_record,
+ sizeof( Eventlog_data_record ) );
ee_new->data = entry->data;
return ee_new;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-static BOOL add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *ee_new)
+static BOOL add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u,
+ Eventlog_entry * ee_new )
{
Eventlog_entry *insert_point;
- insert_point=r_u->entry;
+ insert_point = r_u->entry;
- if (NULL == insert_point) {
+ if ( NULL == insert_point ) {
r_u->entry = ee_new;
ee_new->next = NULL;
} else {
- while ((NULL != insert_point->next)) {
- insert_point=insert_point->next;
+ while ( ( NULL != insert_point->next ) ) {
+ insert_point = insert_point->next;
}
ee_new->next = NULL;
insert_point->next = ee_new;
}
- r_u->num_records++;
+ r_u->num_records++;
r_u->num_bytes_in_resp += ee_new->record.length;
return True;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
/**
* Callout to clear (and optionally backup) a specified event log
@@ -741,128 +645,153 @@ static BOOL add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *ee
* 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)
+static BOOL clear_eventlog_hook( EventlogInfo * info,
+ pstring backup_file_name )
{
- char *cmd = lp_eventlog_clear_cmd();
- char **qlines;
- pstring command;
- int numlines = 0;
- int ret;
- int fd = -1;
-
- if ( !cmd || !*cmd ) {
- DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n"));
- return False;
- }
- if ( strlen(backup_file_name) )
- pstr_sprintf( command, "%s \"%s\" \"%s\"", cmd, info->logname, backup_file_name );
- else
- pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
+ int i;
- DEBUG(10, ("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10, ("returned [%d]\n", ret));
- if(ret != 0) {
- if(fd != -1) {
- close(fd);
- }
+ if ( !info )
return False;
- }
-
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
- close(fd);
-
- if(numlines) {
- DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
- if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) {
- DEBUGADD(10, ("Able to clear [%s].\n", info->logname));
- file_lines_free(qlines);
+ 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;
}
}
- file_lines_free(qlines);
- return False;
+ return False; /* not found */
+ /* TODO- do something with the backup file name */
+
}
/*******************************************************************
-*******************************************************************/
+ *******************************************************************/
+
+static int eventlog_size( char *eventlog_name )
+{
+ TDB_CONTEXT *tdb;
+
+ if ( !eventlog_name )
+ return 0;
+ tdb = tdb_of( eventlog_name );
+ if ( !tdb )
+ return 0;
+ return eventlog_tdb_size( tdb, NULL, NULL );
+}
+
+/********************************************************************
+ ********************************************************************/
-WERROR _eventlog_open_eventlog(pipes_struct *p, EVENTLOG_Q_OPEN_EVENTLOG *q_u, EVENTLOG_R_OPEN_EVENTLOG *r_u)
+WERROR _eventlog_open_eventlog( pipes_struct * p,
+ EVENTLOG_Q_OPEN_EVENTLOG * q_u,
+ EVENTLOG_R_OPEN_EVENTLOG * r_u )
{
EventlogInfo *info = NULL;
fstring str;
-
- if ( !(info = TALLOC_ZERO_P(NULL, EventlogInfo)) )
+
+ if ( !( info = TALLOC_ZERO_P( NULL, EventlogInfo ) ) )
return WERR_NOMEM;
- fstrcpy( str, global_myname() );
+ fstrcpy( str, global_myname( ) );
if ( q_u->servername.string ) {
- rpcstr_pull( str, q_u->servername.string->buffer,
- sizeof(str), q_u->servername.string->uni_str_len*2, 0 );
- }
+ rpcstr_pull( str, q_u->servername.string->buffer,
+ sizeof( str ),
+ q_u->servername.string->uni_str_len * 2, 0 );
+ }
+
info->servername = talloc_strdup( info, str );
fstrcpy( str, "Application" );
if ( q_u->logname.string ) {
- rpcstr_pull( str, q_u->logname.string->buffer,
- sizeof(str), q_u->logname.string->uni_str_len*2, 0 );
- }
+ rpcstr_pull( str, q_u->logname.string->buffer,
+ sizeof( str ),
+ q_u->logname.string->uni_str_len * 2, 0 );
+ }
+
info->logname = talloc_strdup( info, str );
- 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));
+ DEBUG( 1,
+ ( "Size of %s is %d\n", info->logname,
+ eventlog_size( info->logname ) ) );
- if ( !create_policy_hnd(p, &r_u->handle, free_eventlog_info, (void *)info) ) {
- free_eventlog_info(info);
+
+
+ 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 ( !(open_eventlog_hook(info)) ) {
- close_policy_hnd(p, &r_u->handle);
+
+ if ( !open_eventlog_hook( info ) ) {
+ close_policy_hnd( p, &r_u->handle );
return WERR_BADFILE;
}
-
+
+ sync_eventlog_params( info->logname );
+ prune_eventlog( tdb_of( info->logname ) );
+
return WERR_OK;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-WERROR _eventlog_clear_eventlog(pipes_struct *p, EVENTLOG_Q_CLEAR_EVENTLOG *q_u, EVENTLOG_R_CLEAR_EVENTLOG *r_u)
+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);
+ EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
pstring backup_file_name;
pstrcpy( backup_file_name, "" );
- if ( q_u->backupfile.string )
- unistr2_to_ascii(backup_file_name, q_u->backupfile.string, sizeof(backup_file_name));
+ if ( q_u->backupfile.string )
+ unistr2_to_ascii( backup_file_name, q_u->backupfile.string,
+ sizeof( backup_file_name ) );
- DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
- backup_file_name, info->logname));
+ DEBUG( 10,
+ ( "_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)) )
+ if ( !( clear_eventlog_hook( info, backup_file_name ) ) )
return WERR_BADFILE;
return WERR_OK;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-WERROR _eventlog_close_eventlog(pipes_struct *p, EVENTLOG_Q_CLOSE_EVENTLOG *q_u, EVENTLOG_R_CLOSE_EVENTLOG *r_u)
+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);
+ EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
- if ( !(close_eventlog_hook(info)) )
+ if ( !( close_eventlog_hook( info ) ) )
return WERR_BADFILE;
- if ( !(close_policy_hnd(p, &q_u->handle)) ) {
+ if ( !( close_policy_hnd( p, &q_u->handle ) ) ) {
return WERR_BADFID;
}
@@ -870,76 +799,93 @@ WERROR _eventlog_close_eventlog(pipes_struct *p, EVENTLOG_Q_CLOSE_EVENTLOG *q_u,
}
/********************************************************************
-********************************************************************/
-
-WERROR _eventlog_read_eventlog(pipes_struct *p, EVENTLOG_Q_READ_EVENTLOG *q_u, EVENTLOG_R_READ_EVENTLOG *r_u)
+ ********************************************************************/
+
+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);
+ EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
Eventlog_entry entry, *ee_new;
- BOOL eof = False, eor = False;
- const char *direction = "";
+
uint32 num_records_read = 0;
prs_struct *ps;
- int numlines, i;
- char **buffer;
+ int bytes_left, record_number;
+ TDB_CONTEXT *the_tdb;
+
info->flags = q_u->flags;
ps = &p->out_data.rdata;
- if ( info->flags & EVENTLOG_FORWARDS_READ )
- direction = "forward";
- else if ( info->flags & EVENTLOG_BACKWARDS_READ )
- direction = "backward";
- if ( !(read_eventlog_hook(info, &entry, direction, q_u->offset, q_u->max_read_size, &eof, &buffer, &numlines)) ) {
- if(eof == False) {
- return WERR_NOMEM;
- }
+ bytes_left = q_u->max_read_size;
+ the_tdb = tdb_of( info->logname );
+ if ( !the_tdb ) {
+ /* todo handle the error */
+
}
+ /* 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 ) ) {
+ 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 ) {
+ return WERR_NOMEM;
- if(numlines > 0) {
- ZERO_STRUCT(entry);
- for(i = 0; i < numlines; i++) {
- num_records_read = r_u->num_records;
- DEBUGADD(10, ("Line[%d] = [%s]\n", i, buffer[i]));
- parse_logentry(buffer[i], &entry, &eor);
- if(eor == True) {
- /* package ee_new entry */
- if((ee_new = read_package_entry(ps, q_u, r_u, &entry)) == NULL) {
- SAFE_FREE(buffer);
- return WERR_NOMEM;
- }
- /* Now see if there is enough room to add */
- 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 */
- break;
- }
- add_record_to_resp(r_u, ee_new);
- ZERO_STRUCT(entry);
- eor=False;
- 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,
- r_u->num_bytes_in_resp,
- q_u->max_read_size));
}
+
+ 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,
+ r_u->num_bytes_in_resp,
+ q_u->max_read_size ) );
+ } else {
+ DEBUG( 8, ( "get_eventlog_record returned NULL\n" ) );
+ return WERR_NOMEM; /* wrong error - but return one anyway */
}
- SAFE_FREE(buffer);
- }
+
+ if ( info->flags & EVENTLOG_FORWARDS_READ ) {
+ record_number++;
+ } else {
+ record_number--;
+ }
+
+ }
return WERR_OK;
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-WERROR _eventlog_get_oldest_entry(pipes_struct *p, EVENTLOG_Q_GET_OLDEST_ENTRY *q_u, EVENTLOG_R_GET_OLDEST_ENTRY *r_u)
+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);
+ EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
- if ( !(get_oldest_entry_hook(info)) )
+ if ( !( get_oldest_entry_hook( info ) ) )
return WERR_BADFILE;
r_u->oldest_entry = info->oldest_entry;
@@ -948,17 +894,18 @@ WERROR _eventlog_get_oldest_entry(pipes_struct *p, EVENTLOG_Q_GET_OLDEST_ENTRY *
}
/********************************************************************
-********************************************************************/
+ ********************************************************************/
-WERROR _eventlog_get_num_records(pipes_struct *p, EVENTLOG_Q_GET_NUM_RECORDS *q_u, EVENTLOG_R_GET_NUM_RECORDS *r_u)
+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);
+ EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
- if ( !(get_num_records_hook(info)) )
+ if ( !( get_num_records_hook( info ) ) )
return WERR_BADFILE;
r_u->num_records = info->num_records;
return WERR_OK;
}
-
diff --git a/source3/rpc_server/srv_ntsvcs_nt.c b/source3/rpc_server/srv_ntsvcs_nt.c
index 0bb9154aaf..79259174fd 100644
--- a/source3/rpc_server/srv_ntsvcs_nt.c
+++ b/source3/rpc_server/srv_ntsvcs_nt.c
@@ -80,11 +80,9 @@ WERROR _ntsvcs_get_device_list( pipes_struct *p, NTSVCS_Q_GET_DEVICE_LIST *q_u,
rpcstr_pull(device, q_u->devicename->buffer, sizeof(device), q_u->devicename->uni_str_len*2, 0);
devicepath = get_device_path( device );
- /* From the packet traces I've see, I think this really should be an array
- of UNISTR2's. But I've never seen more than one string in spite of the
- fact that the string in double NULL terminated. -- jerry */
+ /* This has to be DOUBLE NULL terminated */
- init_unistr2( &r_u->devicepath, devicepath, UNI_STR_TERMINATE );
+ init_unistr2( &r_u->devicepath, devicepath, UNI_STR_DBLTERMINATE );
r_u->needed = r_u->devicepath.uni_str_len;
return WERR_OK;
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index 4db5ed0ed6..0ba3e04b99 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -293,9 +293,11 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY
SEC_RIGHTS_CREATE_SUBKEY|
SEC_RIGHTS_QUERY_VALUE|
SEC_RIGHTS_SET_VALUE);
-
- if ( !(parent->access_granted & check_rights) )
+
+ if ( !(parent->access_granted & check_rights) ) {
+ DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
return WERR_ACCESS_DENIED;
+ }
/*
* very crazy, but regedit.exe on Win2k will attempt to call
diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c
index e8df2acb22..19648f5e78 100644
--- a/source3/rpc_server/srv_svcctl_nt.c
+++ b/source3/rpc_server/srv_svcctl_nt.c
@@ -32,10 +32,21 @@ struct service_control_op {
SERVICE_CONTROL_OPS *ops;
};
-extern SERVICE_CONTROL_OPS spoolss_svc_ops;
+#define SVCCTL_NUM_INTERNAL_SERVICES 4
+
+/* handle external services */
extern SERVICE_CONTROL_OPS rcinit_svc_ops;
+
+/* builtin services (see service_db.c and services/svc_*.c */
+extern SERVICE_CONTROL_OPS spoolss_svc_ops;
extern SERVICE_CONTROL_OPS netlogon_svc_ops;
extern SERVICE_CONTROL_OPS winreg_svc_ops;
+extern SERVICE_CONTROL_OPS wins_svc_ops;
+
+/* make sure this number patches the number of builtin
+ SERVICE_CONTROL_OPS structure listed above */
+
+#define SVCCTL_NUM_INTERNAL_SERVICES 4
struct service_control_op *svcctl_ops;
@@ -51,7 +62,7 @@ static struct generic_mapping svc_generic_map =
BOOL init_service_op_table( void )
{
const char **service_list = lp_svcctl_list();
- int num_services = 3 + str_list_count( service_list );
+ int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_count( service_list );
int i;
if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {
@@ -80,6 +91,10 @@ BOOL init_service_op_table( void )
svcctl_ops[i].ops = &winreg_svc_ops;
i++;
+ svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
+ svcctl_ops[i].ops = &wins_svc_ops;
+ i++;
+
/* NULL terminate the array */
svcctl_ops[i].name = NULL;
diff --git a/source3/services/services_db.c b/source3/services/services_db.c
index b59cd5330e..7c75d41352 100644
--- a/source3/services/services_db.c
+++ b/source3/services/services_db.c
@@ -23,6 +23,58 @@
#include "includes.h"
+struct rcinit_file_information {
+ char *description;
+};
+
+struct service_display_info {
+ const char *servicename;
+ const char *daemon;
+ const char *dispname;
+ const char *description;
+};
+
+struct service_display_info builtin_svcs[] = {
+ { "Spooler", "smbd", "Print Spooler",
+ "Internal service for spooling files to print devices" },
+ { "NETLOGON", "smbd", "Net Logon",
+ "File service providing access to policy and profile data" },
+ { "RemoteRegistry", "smbd", "Remote Registry Service",
+ "Internal service providing remote access to the Samba registry" },
+ { "WINS", "nmbd", "Windows Internet Name Service (WINS)",
+ "Internal service providing a NetBIOS point-to-point name server" },
+ { NULL, NULL, NULL, NULL }
+};
+
+struct service_display_info common_unix_svcs[] = {
+ { "cups", NULL, "Common Unix Printing System", NULL },
+ { "postfix", NULL, "Internet Mail Service", NULL },
+ { "sendmail", NULL, "Internet Mail Service", NULL },
+ { "portmap", NULL, "TCP Port to RPC PortMapper", NULL },
+ { "xinetd", NULL, "Internet Meta-Daemon", NULL },
+ { "inet", NULL, "Internet Meta-Daemon", NULL },
+ { "xntpd", NULL, "Network Time Service", NULL },
+ { "ntpd", NULL, "Network Time Service", NULL },
+ { "lpd", NULL, "BSD Print Spooler", NULL },
+ { "nfsserver", NULL, "Network File Service", NULL },
+ { "cron", NULL, "Scheduling Service", NULL },
+ { "at", NULL, "Scheduling Service", NULL },
+ { "nscd", NULL, "Name Service Cache Daemon", NULL },
+ { "slapd", NULL, "LDAP Directory Service", NULL },
+ { "ldap", NULL, "LDAP DIrectory Service", NULL },
+ { "ypbind", NULL, "NIS Directory Service", NULL },
+ { "courier-imap", NULL, "IMAP4 Mail Service", NULL },
+ { "courier-pop3", NULL, "POP3 Mail Service", NULL },
+ { "named", NULL, "Domain Name Service", NULL },
+ { "bind", NULL, "Domain Name Service", NULL },
+ { "httpd", NULL, "HTTP Server", NULL },
+ { "apache", NULL, "HTTP Server", NULL },
+ { "autofs", NULL, "Automounter", NULL },
+ { "squid", NULL, "Web Cache Proxy ", NULL },
+ { NULL, NULL, NULL, NULL }
+};
+
+
/********************************************************************
********************************************************************/
@@ -63,11 +115,122 @@ static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
Display name, Description, etc...
********************************************************************/
+static char *get_common_service_dispname( const char *servicename )
+{
+ static fstring dispname;
+ int i;
+
+ for ( i=0; common_unix_svcs[i].servicename; i++ ) {
+ if ( strequal( servicename, common_unix_svcs[i].servicename ) ) {
+ fstr_sprintf( dispname, "%s (%s)",
+ common_unix_svcs[i].dispname,
+ common_unix_svcs[i].servicename );
+
+ return dispname;
+ }
+ }
+
+ fstrcpy( dispname, servicename );
+
+ return dispname;
+}
+
+/********************************************************************
+********************************************************************/
+
+static char* cleanup_string( const char *string )
+{
+ static pstring clean;
+ char *begin, *end;
+
+ pstrcpy( clean, string );
+ begin = clean;
+
+ /* trim any beginning whilespace */
+
+ while ( isspace(*begin) )
+ begin++;
+
+ if ( !begin )
+ return NULL;
+
+ /* trim any trailing whitespace or carriage returns.
+ Start at the end and move backwards */
+
+ end = begin + strlen(begin) - 1;
+
+ while ( isspace(*end) || *end=='\n' || *end=='\r' ) {
+ *end = '\0';
+ end--;
+ }
+
+ return begin;
+}
+
+/********************************************************************
+********************************************************************/
+
+static BOOL read_init_file( const char *servicename, struct rcinit_file_information **service_info )
+{
+ struct rcinit_file_information *info;
+ pstring filepath, str;
+ XFILE *f;
+ char *p, *s;
+
+ if ( !(info = TALLOC_ZERO_P( NULL, struct rcinit_file_information ) ) )
+ return False;
+
+ /* attempt the file open */
+
+ pstr_sprintf( filepath, "%s/%s/%s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, servicename );
+ if ( !(f = x_fopen( filepath, O_RDONLY, 0 )) ) {
+ DEBUG(0,("read_init_file: failed to open [%s]\n", filepath));
+ TALLOC_FREE(info);
+ return False;
+ }
+
+ while ( (s = x_fgets( str, sizeof(str)-1, f )) != NULL ) {
+ /* ignore everything that is not a full line
+ comment starting with a '#' */
+
+ if ( str[0] != '#' )
+ continue;
+
+ /* Look for a line like '^#.*Description:' */
+
+ if ( (p = strstr( str, "Description:" )) != NULL ) {
+ char *desc;
+
+ p += strlen( "Description:" ) + 1;
+ if ( !p )
+ break;
+
+ if ( (desc = cleanup_string(p)) != NULL )
+ info->description = talloc_strdup( info, desc );
+ }
+ }
+
+ x_fclose( f );
+
+ if ( !info->description )
+ info->description = talloc_strdup( info, "External Unix Service" );
+
+ *service_info = info;
+
+ return True;
+}
+
+/********************************************************************
+ This is where we do the dirty work of filling in things like the
+ Display name, Description, etc...
+********************************************************************/
+
static void fill_service_values( const char *name, REGVAL_CTR *values )
{
UNISTR2 data, dname, ipath, description;
uint32 dword;
pstring pstr;
+ int i;
/* These values are hardcoded in all QueryServiceConfig() replies.
I'm just storing them here for cosmetic purposes */
@@ -88,30 +251,39 @@ static void fill_service_values( const char *name, REGVAL_CTR *values )
/* special considerations for internal services and the DisplayName value */
- if ( strequal(name, "Spooler") ) {
- pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
- init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
- init_unistr2( &description, "Internal service for spooling files to print devices", UNI_STR_TERMINATE );
- init_unistr2( &dname, "Print Spooler", UNI_STR_TERMINATE );
- }
- else if ( strequal(name, "NETLOGON") ) {
- pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
- init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
- init_unistr2( &description, "File service providing access to policy and profile data", UNI_STR_TERMINATE );
- init_unistr2( &dname, "Net Logon", UNI_STR_TERMINATE );
+ for ( i=0; builtin_svcs[i].servicename; i++ ) {
+ if ( strequal( name, builtin_svcs[i].servicename ) ) {
+ pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, builtin_svcs[i].daemon );
+ init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
+ init_unistr2( &description, builtin_svcs[i].description, UNI_STR_TERMINATE );
+ init_unistr2( &dname, builtin_svcs[i].dispname, UNI_STR_TERMINATE );
+ break;
+ }
}
- else if ( strequal(name, "RemoteRegistry") ) {
- pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
- init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
- init_unistr2( &description, "Internal service providing remote access to the Samba registry", UNI_STR_TERMINATE );
- init_unistr2( &dname, "Remote Registry Service", UNI_STR_TERMINATE );
- }
- else {
+
+ /* default to an external service if we haven't found a match */
+
+ if ( builtin_svcs[i].servicename == NULL ) {
+ struct rcinit_file_information *init_info = NULL;
+
pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, name );
init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
- init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE );
- init_unistr2( &dname, name, UNI_STR_TERMINATE );
+
+ /* lookup common unix display names */
+ init_unistr2( &dname, get_common_service_dispname( name ), UNI_STR_TERMINATE );
+
+ /* get info from init file itself */
+ if ( read_init_file( name, &init_info ) ) {
+ init_unistr2( &description, init_info->description, UNI_STR_TERMINATE );
+ TALLOC_FREE( init_info );
+ }
+ else {
+ init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE );
+ }
}
+
+ /* add the new values */
+
regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2);
regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2);
regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2);
@@ -248,9 +420,8 @@ void svcctl_init_keys( void )
/* the builting services exist */
- add_new_svc_name( key, subkeys, "Spooler" );
- add_new_svc_name( key, subkeys, "NETLOGON" );
- add_new_svc_name( key, subkeys, "RemoteRegistry" );
+ for ( i=0; builtin_svcs[i].servicename; i++ )
+ add_new_svc_name( key, subkeys, builtin_svcs[i].servicename );
for ( i=0; service_list[i]; i++ ) {
@@ -352,29 +523,34 @@ char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token )
/* now add the security descriptor */
pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
- wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+ wresult = regkey_open_internal( &key, path, token, REG_KEY_READ );
if ( !W_ERROR_IS_OK(wresult) ) {
DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n",
path, dos_errstr(wresult)));
- return NULL;
+ goto fail;
}
if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
TALLOC_FREE( key );
- return NULL;
+ goto fail;
}
fetch_reg_values( key, values );
if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) )
- fstrcpy( display_name, name );
- else
- rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 );
+ goto fail;
+
+ rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 );
TALLOC_FREE( key );
return display_name;
+
+fail:
+ /* default to returning the service name */
+ fstrcpy( display_name, name );
+ return display_name;
}
/********************************************************************
@@ -392,7 +568,7 @@ char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token )
/* now add the security descriptor */
pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
- wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+ wresult = regkey_open_internal( &key, path, token, REG_KEY_READ );
if ( !W_ERROR_IS_OK(wresult) ) {
DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n",
path, dos_errstr(wresult)));
@@ -431,7 +607,7 @@ REGVAL_CTR* svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token )
/* now add the security descriptor */
pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
- wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+ wresult = regkey_open_internal( &key, path, token, REG_KEY_READ );
if ( !W_ERROR_IS_OK(wresult) ) {
DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n",
path, dos_errstr(wresult)));
diff --git a/source3/services/svc_rcinit.c b/source3/services/svc_rcinit.c
index 5801d076c4..f60019601f 100644
--- a/source3/services/svc_rcinit.c
+++ b/source3/services/svc_rcinit.c
@@ -1,4 +1,3 @@
-
/*
* Unix SMB/CIFS implementation.
* Service Control API Implementation
@@ -21,153 +20,6 @@
#include "includes.h"
-/* Implementation for LSB compliant init scripts */
-
-/*******************************************************************************
- Get the services information by reading and parsing the shell scripts. These
- are symbolically linked into the SVCCTL_SCRIPT_DIR directory.
-
- Get the names of the services/scripts to read from the smb.conf file.
-*******************************************************************************/
-
-BOOL get_LSB_data(char *fname,Service_info *si )
-{
- pstring initdfile;
- char mybuffer[256];
- const char *tokenptr;
- char **qlines;
- int fd = -1;
- int nlines, *numlines,i,in_section,in_description;
-
- pstrcpy(si->servicename,"");
- pstrcpy(si->servicetype,"EXTERNAL");
- pstrcpy(si->filename,fname);
- pstrcpy(si->provides,"");
- pstrcpy(si->dependencies,"");
- pstrcpy(si->shouldstart,"");
- pstrcpy(si->shouldstop,"");
- pstrcpy(si->requiredstart,"");
- pstrcpy(si->requiredstop,"");
- pstrcpy(si->description,"");
- pstrcpy(si->shortdescription,"");
-
- numlines = &nlines;
- in_section = 0;
- in_description = 0;
-
-
- if( !fname || !*fname ) {
- DEBUG(0, ("Must define an \"LSB-style init file\" to read.\n"));
- return False;
- }
- pstrcpy(initdfile,dyn_LIBDIR);
- pstrcat(initdfile,SVCCTL_SCRIPT_DIR);
- pstrcat(initdfile,fname);
-
- /* TODO - should check to see if the file that we're trying to open is
- actually a script. If it's NOT, we should do something like warn,
- and not continue to try to find info we're looking for */
-
- DEBUG(10, ("Opening [%s]\n", initdfile));
- fd = -1;
- fd = open(initdfile,O_RDONLY);
- *numlines = 0;
-
- if (fd == -1) {
- DEBUG(10, ("Couldn't open [%s]\n", initdfile));
- return False;
- }
-
- qlines = fd_lines_load(fd, numlines);
- DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
- close(fd);
-
-
- if (*numlines) {
-
- for(i = 0; i < *numlines; i++) {
-
- DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
- if (!in_section && (0==strwicmp("### BEGIN INIT INFO", qlines[i]))) {
- /* we now can look for params */
- DEBUGADD(10, ("Configuration information starts on line = [%d]\n", i));
- in_section = 1;
-
- } else if (in_section && (0==strwicmp("### END INIT INFO", qlines[i]))) {
- DEBUGADD(10, ("Configuration information ends on line = [%d]\n", i));
- DEBUGADD(10, ("Description is [%s]\n", si->description));
- in_description = 0;
- in_section = 0;
- break;
- } else if (in_section) {
- tokenptr = qlines[i];
- if (in_description) {
- DEBUGADD(10, ("Processing DESCRIPTION [%d]\n", *tokenptr));
- if (tokenptr && (*tokenptr=='#') && (*(tokenptr+1)=='\t')) {
- DEBUGADD(10, ("Adding to DESCRIPTION [%d]\n", *tokenptr));
- pstrcat(si->description," ");
- pstrcat(si->description,tokenptr+2);
- continue;
- }
- in_description = 0;
- DEBUGADD(10, ("Not a description!\n"));
- }
- if (!next_token(&tokenptr,mybuffer," \t",sizeof(mybuffer))) {
- DEBUGADD(10, ("Invalid line [%d]\n", i));
- break; /* bad line? */
- }
- if (0 != strncmp(mybuffer,"#",1)) {
- DEBUGADD(10, ("Invalid line [%d], is %s\n", i,mybuffer));
- break;
- }
- if (!next_token(&tokenptr,mybuffer," \t",sizeof(mybuffer))) {
- DEBUGADD(10, ("Invalid token on line [%d]\n", i));
- break; /* bad line? */
- }
- DEBUGADD(10, ("Keyword is [%s]\n", mybuffer));
- if (0==strwicmp(mybuffer,"Description:")) {
- while (tokenptr && *tokenptr && (strchr(" \t",*tokenptr))) {
- tokenptr++;
- }
- pstrcpy(si->description,tokenptr);
- DEBUGADD(10, ("FOUND DESCRIPTION! Data is [%s]\n", tokenptr));
- in_description = 1;
- } else {
- while (tokenptr && *tokenptr && (strchr(" \t",*tokenptr))) {
- tokenptr++;
- }
- DEBUGADD(10, ("Data is [%s]\n", tokenptr));
- in_description = 0;
-
- /* save certain keywords, don't save others */
- if (0==strwicmp(mybuffer, "Provides:")) {
- pstrcpy(si->provides,tokenptr);
- pstrcpy(si->servicename,tokenptr);
- }
-
- if (0==strwicmp(mybuffer, "Short-Description:")) {
- pstrcpy(si->shortdescription,tokenptr);
- }
-
- if (0==strwicmp(mybuffer, "Required-start:")) {
- pstrcpy(si->requiredstart,tokenptr);
- pstrcpy(si->dependencies,tokenptr);
- }
-
- if (0==strwicmp(mybuffer, "Should-start:")) {
- pstrcpy(si->shouldstart,tokenptr);
- }
- }
- }
- }
-
- file_lines_free(qlines);
- return True;
- }
-
- return False;
-}
-
/*********************************************************************
*********************************************************************/
diff --git a/source3/services/svc_wins.c b/source3/services/svc_wins.c
new file mode 100644
index 0000000000..3a4650664d
--- /dev/null
+++ b/source3/services/svc_wins.c
@@ -0,0 +1,66 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Service Control API Implementation
+ * Copyright (C) Gerald 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
+ * (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"
+
+/* Implementation for internal wins service */
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR wins_stop( const char *service, SERVICE_STATUS *service_status )
+{
+ return WERR_ACCESS_DENIED;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR wins_start( const char *service )
+{
+ return WERR_ACCESS_DENIED;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR wins_status( const char *service, SERVICE_STATUS *service_status )
+{
+ ZERO_STRUCTP( service_status );
+
+ service_status->type = 0x10;
+ if ( lp_wins_support() )
+ service_status->state = SVCCTL_RUNNING;
+ else
+ service_status->state = SVCCTL_STOPPED;
+
+ return WERR_OK;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+/* struct for svcctl control to manipulate wins service */
+
+SERVICE_CONTROL_OPS wins_svc_ops = {
+ wins_stop,
+ wins_start,
+ wins_status
+};