r6149: Fixes bugs #2498 and 2484.
[samba.git] / source / rpc_server / srv_svcctl_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Gerald (Jerry) Carter             2005
5  *  
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_SRV
25
26 /*
27  * sertup the \PIPE\svcctl db API
28  */
29  
30 #define SCVCTL_DATABASE_VERSION_V1 1
31
32 /********************************************************************
33 ********************************************************************/
34
35 #if 0 /* unused static function and static variable*/
36
37 static TDB_CONTEXT *svcctl_tdb; /* used for share security descriptors */
38
39 static BOOL init_svcctl_db( void )
40 {
41         static pid_t local_pid;
42         const char *vstring = "INFO/version";
43  
44         /* see if we've already opened the tdb */
45         
46         if (svcctl_tdb && local_pid == sys_getpid())
47                 return True;
48         
49         /* so open it */        
50         if ( !(svcctl_tdb = tdb_open_log(lock_path("svcctl.tdb"), 0, TDB_DEFAULT, 
51                 O_RDWR|O_CREAT, 0600))) 
52         {
53                 DEBUG(0,("Failed to open svcctl database %s (%s)\n", 
54                         lock_path("svcctl.tdb"), strerror(errno) ));
55                 return False;
56         }
57  
58         local_pid = sys_getpid();
59  
60         /***** BEGIN Check the tdb version ******/
61         
62         tdb_lock_bystring(svcctl_tdb, vstring, 0);
63         
64         if ( tdb_fetch_int32(svcctl_tdb, vstring) != SCVCTL_DATABASE_VERSION_V1 )
65                 tdb_store_int32(svcctl_tdb, vstring, SCVCTL_DATABASE_VERSION_V1);
66
67         tdb_unlock_bystring(svcctl_tdb, vstring);
68         
69         /***** END Check the tdb version ******/
70
71         return True;
72 }
73
74 #endif
75
76 /********************************************************************
77  TODO
78  (a) get and set security descriptors on services
79  (b) read and write QUERY_SERVICE_CONFIG structures
80  (c) create default secdesc objects for services and SCM
81  (d) check access control masks with se_access_check()
82  (e) implement SERVICE * for associating with open handles
83 ********************************************************************/
84
85 /********************************************************************
86 ********************************************************************/
87
88 WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u)
89 {
90         /* just fake it for now */
91         
92         if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) )
93                 return WERR_ACCESS_DENIED;
94         
95         return WERR_OK;
96 }
97
98 /********************************************************************
99 ********************************************************************/
100
101 WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u)
102 {
103         fstring service;
104
105         rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
106         
107         /* can only be called on service name (not displayname) */
108
109         if ( !(strequal( service, "NETLOGON") || strequal(service, "Spooler")) )
110                 return WERR_NO_SUCH_SERVICE;
111
112         if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) )
113                 return WERR_ACCESS_DENIED;
114
115         return WERR_OK;
116 }
117
118 /********************************************************************
119 ********************************************************************/
120
121 WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u)
122 {
123         if ( !close_policy_hnd( p, &q_u->handle ) )
124                 return WERR_BADFID;
125         
126         return WERR_OK;
127 }
128
129 /********************************************************************
130 ********************************************************************/
131
132 WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
133 {
134         fstring service;
135         fstring displayname;
136
137         rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
138
139         DEBUG(10,("_svcctl_get_display_name: service name [%s]\n", service));
140
141         if ( !strequal( service, "NETLOGON" ) )
142                 return WERR_ACCESS_DENIED;
143
144         fstrcpy( displayname, "Net Logon");
145         init_svcctl_r_get_display_name( r_u, displayname );
146
147         return WERR_OK;
148 }
149
150 /********************************************************************
151 ********************************************************************/
152
153 WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u)
154 {
155
156         r_u->svc_status.type = 0x0110;
157         r_u->svc_status.state = 0x0004;
158         r_u->svc_status.controls_accepted = 0x0005;
159
160         return WERR_OK;
161 }
162
163 /********************************************************************
164 ********************************************************************/
165
166 WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
167 {
168         ENUM_SERVICES_STATUS *services = NULL;
169         uint32 num_services = 0;
170         int i = 0;
171         size_t buffer_size;
172         WERROR result = WERR_OK;
173                 
174         /* num_services = str_list_count( lp_enable_svcctl() ); */
175         num_services = 2;
176         
177         if ( !(services = TALLOC_ARRAY( p->mem_ctx, ENUM_SERVICES_STATUS, num_services )) )
178                 return WERR_NOMEM;
179                 
180         DEBUG(8,("_svcctl_enum_services_status: Enumerating %d services\n", num_services));
181                                 
182         init_unistr( &services[i].servicename, "Spooler" );
183         init_unistr( &services[i].displayname, "Spooler" );
184         
185         services[i].status.type               = 0x110;
186         services[i].status.controls_accepted  = 0x0;
187         services[i].status.win32_exit_code    = 0x0;
188         services[i].status.service_exit_code  = 0x0;
189         services[i].status.check_point        = 0x0;
190         services[i].status.wait_hint          = 0x0;
191         if ( !lp_disable_spoolss() ) 
192                 services[i].status.state              = SVCCTL_RUNNING;
193         else
194                 services[i].status.state              = SVCCTL_STOPPED;
195
196         i++;            
197         
198         init_unistr( &services[i].servicename, "Netlogon" );
199         init_unistr( &services[i].displayname, "Net Logon" );
200         
201         services[i].status.type               = 0x20;   
202         services[i].status.controls_accepted  = 0x0;
203         services[i].status.win32_exit_code    = 0x0;
204         services[i].status.service_exit_code  = 0x0;
205         services[i].status.check_point        = 0x0;
206         services[i].status.wait_hint          = 0x0;
207         if ( lp_servicenumber("NETLOGON") != -1 ) 
208                 services[i].status.state              = SVCCTL_RUNNING;
209         else
210                 services[i].status.state              = SVCCTL_STOPPED;
211         
212         buffer_size = 0;
213         for (i=0; i<num_services; i++ )
214                 buffer_size += svcctl_sizeof_enum_services_status( &services[i] );
215                 
216         buffer_size += buffer_size % 4;
217         
218         if ( buffer_size > q_u->buffer_size ) {
219                 num_services = 0;
220                 result = WERR_MORE_DATA;
221         }
222                 
223         /* we have to set the outgoing buffer size to the same as the 
224            incoming buffer size (even in the case of failure */
225
226         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
227                 
228         if ( W_ERROR_IS_OK(result) ) {
229                 for ( i=0; i<num_services; i++ )
230                         svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
231         }
232                 
233         r_u->needed      = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
234         r_u->returned    = num_services;
235
236         if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
237                 return WERR_NOMEM;
238
239         *r_u->resume = 0x0;
240
241         return result;
242 }
243
244 /********************************************************************
245 ********************************************************************/
246
247 WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
248 {
249         return WERR_ACCESS_DENIED;
250 }
251
252 /********************************************************************
253 ********************************************************************/
254
255 WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
256 {
257         return WERR_ACCESS_DENIED;
258 }
259
260 /********************************************************************
261 ********************************************************************/
262
263 WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
264 {
265         
266         /* we have to set the outgoing buffer size to the same as the 
267            incoming buffer size (even in the case of failure */
268
269         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
270                                 
271         r_u->needed      = q_u->buffer_size;
272         
273         /* no dependent services...basically a stub function */
274         r_u->returned    = 0;
275
276         return WERR_OK;
277 }
278
279 /********************************************************************
280 ********************************************************************/
281
282 WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
283 {
284         
285         /* we have to set the outgoing buffer size to the same as the 
286            incoming buffer size (even in the case of failure */
287
288         r_u->needed      = q_u->buffer_size;
289         
290         /* no dependent services...basically a stub function */
291
292         return WERR_ACCESS_DENIED;
293 }
294
295