mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
5d1cb8e79e
pulling back all recent rpc changes from trunk into
3.0. I've tested a compile and so don't think I've missed
any files. But if so, just mail me and I'll clean backup
in a couple of hours.
Changes include \winreg, \eventlog, \svcctl, and
general parse_misc.c updates.
I am planning on bracketing the event code with an
#ifdef ENABLE_EVENTLOG until I finish merging Marcin's
changes (very soon).
(This used to be commit 4e0ac63c36
)
292 lines
9.0 KiB
C
292 lines
9.0 KiB
C
/*
|
|
* Unix SMB/CIFS implementation.
|
|
* RPC Pipe client / server routines
|
|
* 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"
|
|
|
|
#undef DBGC_CLASS
|
|
#define DBGC_CLASS DBGC_RPC_SRV
|
|
|
|
/*
|
|
* sertup the \PIPE\svcctl db API
|
|
*/
|
|
|
|
static TDB_CONTEXT *svcctl_tdb; /* used for share security descriptors */
|
|
|
|
#define SCVCTL_DATABASE_VERSION_V1 1
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
static BOOL init_svcctl_db( void )
|
|
{
|
|
static pid_t local_pid;
|
|
const char *vstring = "INFO/version";
|
|
|
|
/* see if we've already opened the tdb */
|
|
|
|
if (svcctl_tdb && local_pid == sys_getpid())
|
|
return True;
|
|
|
|
/* so open it */
|
|
if ( !(svcctl_tdb = tdb_open_log(lock_path("svcctl.tdb"), 0, TDB_DEFAULT,
|
|
O_RDWR|O_CREAT, 0600)))
|
|
{
|
|
DEBUG(0,("Failed to open svcctl database %s (%s)\n",
|
|
lock_path("svcctl.tdb"), strerror(errno) ));
|
|
return False;
|
|
}
|
|
|
|
local_pid = sys_getpid();
|
|
|
|
/***** BEGIN Check the tdb version ******/
|
|
|
|
tdb_lock_bystring(svcctl_tdb, vstring, 0);
|
|
|
|
if ( tdb_fetch_int32(svcctl_tdb, vstring) != SCVCTL_DATABASE_VERSION_V1 )
|
|
tdb_store_int32(svcctl_tdb, vstring, SCVCTL_DATABASE_VERSION_V1);
|
|
|
|
tdb_unlock_bystring(svcctl_tdb, vstring);
|
|
|
|
/***** END Check the tdb version ******/
|
|
|
|
return True;
|
|
}
|
|
|
|
/********************************************************************
|
|
TODO
|
|
(a) get and set security descriptors on services
|
|
(b) read and write QUERY_SERVICE_CONFIG structures
|
|
(c) create default secdesc objects for services and SCM
|
|
(d) check access control masks with se_access_check()
|
|
(e) implement SERVICE * for associating with open handles
|
|
********************************************************************/
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u)
|
|
{
|
|
/* just fake it for now */
|
|
|
|
if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) )
|
|
return WERR_ACCESS_DENIED;
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u)
|
|
{
|
|
fstring service;
|
|
|
|
rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
|
|
|
|
/* can only be called on service name (not displayname) */
|
|
|
|
if ( !(strequal( service, "NETLOGON") || strequal(service, "Spooler")) )
|
|
return WERR_NO_SUCH_SERVICE;
|
|
|
|
if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) )
|
|
return WERR_ACCESS_DENIED;
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u)
|
|
{
|
|
if ( !close_policy_hnd( p, &q_u->handle ) )
|
|
return WERR_BADFID;
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
|
|
{
|
|
fstring service;
|
|
fstring displayname;
|
|
|
|
rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
|
|
|
|
DEBUG(10,("_svcctl_get_display_name: service name [%s]\n", service));
|
|
|
|
if ( !strequal( service, "NETLOGON" ) )
|
|
return WERR_ACCESS_DENIED;
|
|
|
|
fstrcpy( displayname, "Net Logon");
|
|
init_svcctl_r_get_display_name( r_u, displayname );
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u)
|
|
{
|
|
|
|
r_u->svc_status.type = 0x0110;
|
|
r_u->svc_status.state = 0x0004;
|
|
r_u->svc_status.controls_accepted = 0x0005;
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
|
|
{
|
|
ENUM_SERVICES_STATUS *services = NULL;
|
|
uint32 num_services = 0;
|
|
int i = 0;
|
|
size_t buffer_size;
|
|
WERROR result = WERR_OK;
|
|
|
|
/* num_services = str_list_count( lp_enable_svcctl() ); */
|
|
num_services = 2;
|
|
|
|
if ( !(services = TALLOC_ARRAY( p->mem_ctx, ENUM_SERVICES_STATUS, num_services )) )
|
|
return WERR_NOMEM;
|
|
|
|
DEBUG(8,("_svcctl_enum_services_status: Enumerating %d services\n", num_services));
|
|
|
|
init_unistr( &services[i].servicename, "Spooler" );
|
|
init_unistr( &services[i].displayname, "Spooler" );
|
|
|
|
services[i].status.type = 0x110;
|
|
services[i].status.controls_accepted = 0x0;
|
|
services[i].status.win32_exit_code = 0x0;
|
|
services[i].status.service_exit_code = 0x0;
|
|
services[i].status.check_point = 0x0;
|
|
services[i].status.wait_hint = 0x0;
|
|
if ( !lp_disable_spoolss() )
|
|
services[i].status.state = SVCCTL_RUNNING;
|
|
else
|
|
services[i].status.state = SVCCTL_STOPPED;
|
|
|
|
i++;
|
|
|
|
init_unistr( &services[i].servicename, "Netlogon" );
|
|
init_unistr( &services[i].displayname, "Net Logon" );
|
|
|
|
services[i].status.type = 0x20;
|
|
services[i].status.controls_accepted = 0x0;
|
|
services[i].status.win32_exit_code = 0x0;
|
|
services[i].status.service_exit_code = 0x0;
|
|
services[i].status.check_point = 0x0;
|
|
services[i].status.wait_hint = 0x0;
|
|
if ( lp_servicenumber("NETLOGON") != -1 )
|
|
services[i].status.state = SVCCTL_RUNNING;
|
|
else
|
|
services[i].status.state = SVCCTL_STOPPED;
|
|
|
|
buffer_size = 0;
|
|
for (i=0; i<num_services; i++ )
|
|
buffer_size += svcctl_sizeof_enum_services_status( &services[i] );
|
|
|
|
buffer_size += buffer_size % 4;
|
|
|
|
if ( buffer_size > q_u->buffer_size ) {
|
|
num_services = 0;
|
|
result = WERR_MORE_DATA;
|
|
}
|
|
|
|
/* we have to set the outgoing buffer size to the same as the
|
|
incoming buffer size (even in the case of failure */
|
|
|
|
rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
|
|
|
|
if ( W_ERROR_IS_OK(result) ) {
|
|
for ( i=0; i<num_services; i++ )
|
|
svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
|
|
}
|
|
|
|
r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
|
|
r_u->returned = num_services;
|
|
|
|
if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
|
|
return WERR_NOMEM;
|
|
|
|
*r_u->resume = 0x0;
|
|
|
|
return result;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
|
|
{
|
|
return WERR_ACCESS_DENIED;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
|
|
{
|
|
return WERR_ACCESS_DENIED;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
|
|
{
|
|
|
|
/* we have to set the outgoing buffer size to the same as the
|
|
incoming buffer size (even in the case of failure */
|
|
|
|
rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
|
|
|
|
r_u->needed = q_u->buffer_size;
|
|
|
|
/* no dependent services...basically a stub function */
|
|
r_u->returned = 0;
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
********************************************************************/
|
|
|
|
WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
|
|
{
|
|
|
|
/* we have to set the outgoing buffer size to the same as the
|
|
incoming buffer size (even in the case of failure */
|
|
|
|
r_u->needed = q_u->buffer_size;
|
|
|
|
/* no dependent services...basically a stub function */
|
|
|
|
return WERR_ACCESS_DENIED;
|
|
}
|
|
|
|
|