r14182: Ensure we know that dom_sid cannot be null.
[kai/samba-autobuild/.git] / source / rpc_server / srv_svcctl_nt.c
index e8df2acb22fec61ea99995e048343afcd4c875c5..a0b8b66f508156fee7a0fbfa66975f1913925610 100644 (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)) ) {
@@ -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;
+}
+
+