X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source%2Frpc_server%2Fsrv_svcctl_nt.c;h=a0b8b66f508156fee7a0fbfa66975f1913925610;hb=e3a28bf4c8064f7053b7d1a25a2f087ac2095fcd;hp=e8df2acb22fec61ea99995e048343afcd4c875c5;hpb=939c3cb5d78e3a2236209b296aa8aba8bdce32d3;p=kai%2Fsamba-autobuild%2F.git diff --git a/source/rpc_server/srv_svcctl_nt.c b/source/rpc_server/srv_svcctl_nt.c index e8df2acb22f..a0b8b66f508 100644 --- a/source/rpc_server/srv_svcctl_nt.c +++ b/source/rpc_server/srv_svcctl_nt.c @@ -32,10 +32,21 @@ struct service_control_op { SERVICE_CONTROL_OPS *ops; }; -extern SERVICE_CONTROL_OPS spoolss_svc_ops; +#define SVCCTL_NUM_INTERNAL_SERVICES 4 + +/* handle external services */ extern SERVICE_CONTROL_OPS rcinit_svc_ops; + +/* builtin services (see service_db.c and services/svc_*.c */ +extern SERVICE_CONTROL_OPS spoolss_svc_ops; extern SERVICE_CONTROL_OPS netlogon_svc_ops; extern SERVICE_CONTROL_OPS winreg_svc_ops; +extern SERVICE_CONTROL_OPS wins_svc_ops; + +/* make sure this number patches the number of builtin + SERVICE_CONTROL_OPS structure listed above */ + +#define SVCCTL_NUM_INTERNAL_SERVICES 4 struct service_control_op *svcctl_ops; @@ -51,7 +62,7 @@ static struct generic_mapping svc_generic_map = BOOL init_service_op_table( void ) { const char **service_list = lp_svcctl_list(); - int num_services = 3 + str_list_count( service_list ); + int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_count( service_list ); int i; if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) { @@ -61,7 +72,7 @@ BOOL init_service_op_table( void ) /* services listed in smb.conf get the rc.init interface */ - for ( i=0; service_list[i]; i++ ) { + for ( i=0; service_list && service_list[i]; i++ ) { svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] ); svcctl_ops[i].ops = &rcinit_svc_ops; } @@ -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; @@ -171,7 +186,7 @@ static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd) { SERVICE_INFO *service_info = NULL; - if( !find_policy_by_hnd( p, hnd, (void **)&service_info) ) { + if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) { DEBUG(2,("find_service_info_by_hnd: handle not found")); return NULL; } @@ -600,9 +615,20 @@ static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG config->tag_id = 0x00000000; /* unassigned loadorder group */ config->service_type = SVCCTL_WIN32_OWN_PROC; - config->start_type = SVCCTL_DEMAND_START; config->error_control = SVCCTL_SVC_ERROR_NORMAL; + /* set the start type. NetLogon and WINS are disabled to prevent + the client from showing the "Start" button (if of course the services + are not running */ + + if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) ) + config->start_type = SVCCTL_DISABLED; + else if ( strequal( name, "WINS" ) && ( !lp_wins_support() )) + config->start_type = SVCCTL_DISABLED; + else + config->start_type = SVCCTL_DEMAND_START; + + TALLOC_FREE( values ); return WERR_OK; @@ -745,3 +771,100 @@ WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID; } + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_query_service_sec( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_SEC *q_u, SVCCTL_R_QUERY_SERVICE_SEC *r_u ) +{ + SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + SEC_DESC *sec_desc; + + + /* only support the SCM and individual services */ + + if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) ) + return WERR_BADFID; + + /* check access reights (according to MSDN) */ + + if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) ) + return WERR_ACCESS_DENIED; + + /* TODO: handle something besides DACL_SECURITY_INFORMATION */ + + if ( (q_u->security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION ) + return WERR_INVALID_PARAM; + + /* lookup the security descriptor and marshall it up for a reply */ + + if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) ) + return WERR_NOMEM; + + r_u->needed = sec_desc_size( sec_desc ); + + if ( r_u->needed > q_u->buffer_size ) { + ZERO_STRUCTP( &r_u->buffer ); + return WERR_INSUFFICIENT_BUFFER; + } + + rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); + + if ( !sec_io_desc("", &sec_desc, &r_u->buffer.prs, 0 ) ) + return WERR_NOMEM; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_set_service_sec( pipes_struct *p, SVCCTL_Q_SET_SERVICE_SEC *q_u, SVCCTL_R_SET_SERVICE_SEC *r_u ) +{ + SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + SEC_DESC *sec_desc = NULL; + uint32 required_access; + + if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) ) + return WERR_BADFID; + + /* can't set the security de4scriptor on the ServiceControlManager */ + + if ( info->type == SVC_HANDLE_IS_SCM ) + return WERR_ACCESS_DENIED; + + /* check the access on the open handle */ + + switch ( q_u->security_flags ) { + case DACL_SECURITY_INFORMATION: + required_access = STD_RIGHT_WRITE_DAC_ACCESS; + break; + + case OWNER_SECURITY_INFORMATION: + case GROUP_SECURITY_INFORMATION: + required_access = STD_RIGHT_WRITE_OWNER_ACCESS; + break; + + case SACL_SECURITY_INFORMATION: + return WERR_INVALID_PARAM; + default: + return WERR_INVALID_PARAM; + } + + if ( !(info->access_granted & required_access) ) + return WERR_ACCESS_DENIED; + + /* read the security descfriptor */ + + if ( !sec_io_desc("", &sec_desc, &q_u->buffer.prs, 0 ) ) + return WERR_NOMEM; + + /* store the new SD */ + + if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc, p->pipe_user.nt_user_token ) ) + return WERR_ACCESS_DENIED; + + return WERR_OK; +} + +