mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
r10781: merging eventlog and svcctl code from trunk
(This used to be commit f10aa9fb84bfac4f1a22b74d63999668700ffaac)
This commit is contained in:
parent
6de37ee5f5
commit
0bf72b6e33
@ -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
|
||||
|
@ -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
|
||||
|
||||
/***********************************/
|
||||
|
||||
|
@ -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 };
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 );
|
||||
}
|
||||
regdb_fetch_keys( KEY_EVENTLOG, subkeys );
|
||||
regsubkey_ctr_addkey( subkeys, *elogs );
|
||||
if ( !regdb_store_keys( KEY_EVENTLOG, subkeys ) )
|
||||
return False;
|
||||
TALLOC_FREE( subkeys );
|
||||
|
||||
#if 0
|
||||
/* hmmm....what to do here? A subkey underneath the log name ? */
|
||||
/* add in the key of form KEY_EVENTLOG/Application */
|
||||
DEBUG( 5,
|
||||
( "Adding key of [%s] to path of [%s]\n", *elogs,
|
||||
KEY_EVENTLOG ) );
|
||||
|
||||
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 );
|
||||
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 );
|
||||
|
||||
/* 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 );
|
||||
|
||||
}
|
||||
|
||||
TALLOC_FREE( values );
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
static BOOL elog_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
|
||||
{
|
||||
/* cannot create any subkeys here */
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
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 );
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
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
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) )
|
||||
|
620
source3/rpc_server/srv_eventlog_lib.c
Normal file
620
source3/rpc_server/srv_eventlog_lib.c
Normal file
@ -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( ¤t_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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
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, "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 );
|
||||
}
|
||||
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)));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
|
66
source3/services/svc_wins.c
Normal file
66
source3/services/svc_wins.c
Normal file
@ -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
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user