1
0
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:
Gerald Carter 2005-10-06 17:48:03 +00:00 committed by Gerald (Jerry) Carter
parent 6de37ee5f5
commit 0bf72b6e33
17 changed files with 1647 additions and 1049 deletions

View File

@ -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

View File

@ -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
/***********************************/

View File

@ -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 };

View File

@ -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
*/

View File

@ -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)
{

View File

@ -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
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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) )

View 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( &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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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)));

View File

@ -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;
}
/*********************************************************************
*********************************************************************/

View 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
};