Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : *
5 : * Copyright (C) Marcin Krzysztof Porwit 2005.
6 : *
7 : * Largely Rewritten (Again) by:
8 : * Copyright (C) Gerald (Jerry) Carter 2005.
9 : * Copyright (C) Guenther Deschner 2008,2009.
10 : *
11 : * This program is free software; you can redistribute it and/or modify
12 : * it under the terms of the GNU General Public License as published by
13 : * the Free Software Foundation; either version 3 of the License, or
14 : * (at your option) any later version.
15 : *
16 : * This program is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU General Public License
22 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include "system/passwd.h" /* uid_wrapper */
27 : #include "ntdomain.h"
28 : #include "../libcli/security/security.h"
29 : #include "../librpc/gen_ndr/ndr_security.h"
30 : #include "services/services.h"
31 : #include "services/svc_winreg_glue.h"
32 : #include "auth.h"
33 : #include "rpc_server/svcctl/srv_svcctl_nt.h"
34 :
35 : #include "rpc_server/rpc_server.h"
36 : #include "librpc/rpc/dcesrv_core.h"
37 : #include "librpc/gen_ndr/ndr_svcctl.h"
38 : #include "librpc/gen_ndr/ndr_svcctl_scompat.h"
39 : #include "srv_svcctl_reg.h"
40 : #include "lib/global_contexts.h"
41 :
42 : #undef DBGC_CLASS
43 : #define DBGC_CLASS DBGC_RPC_SRV
44 :
45 : struct service_control_op {
46 : const char *name;
47 : SERVICE_CONTROL_OPS *ops;
48 : };
49 :
50 : /* handle external services */
51 : extern SERVICE_CONTROL_OPS rcinit_svc_ops;
52 :
53 : /* builtin services (see service_db.c and services/svc_*.c */
54 : extern SERVICE_CONTROL_OPS spoolss_svc_ops;
55 : extern SERVICE_CONTROL_OPS netlogon_svc_ops;
56 : extern SERVICE_CONTROL_OPS winreg_svc_ops;
57 : extern SERVICE_CONTROL_OPS wins_svc_ops;
58 :
59 : /* make sure this number patches the number of builtin
60 : SERVICE_CONTROL_OPS structure listed above */
61 :
62 : #define SVCCTL_NUM_INTERNAL_SERVICES 4
63 :
64 : struct service_control_op *svcctl_ops;
65 :
66 : static const struct generic_mapping scm_generic_map =
67 : { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
68 : static const struct generic_mapping svc_generic_map =
69 : { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
70 :
71 :
72 : /********************************************************************
73 : ********************************************************************/
74 :
75 31 : bool init_service_op_table( void )
76 : {
77 31 : const char **service_list = lp_svcctl_list();
78 31 : int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length( service_list );
79 : int i;
80 :
81 31 : if ( !(svcctl_ops = talloc_array( NULL, struct service_control_op, num_services+1)) ) {
82 0 : DEBUG(0,("init_service_op_table: talloc() failed!\n"));
83 0 : return False;
84 : }
85 :
86 : /* services listed in smb.conf get the rc.init interface */
87 :
88 31 : for ( i=0; service_list && service_list[i]; i++ ) {
89 0 : svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );
90 0 : svcctl_ops[i].ops = &rcinit_svc_ops;
91 : }
92 :
93 : /* add builtin services */
94 :
95 31 : svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
96 31 : svcctl_ops[i].ops = &spoolss_svc_ops;
97 31 : i++;
98 :
99 31 : svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
100 31 : svcctl_ops[i].ops = &netlogon_svc_ops;
101 31 : i++;
102 :
103 31 : svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
104 31 : svcctl_ops[i].ops = &winreg_svc_ops;
105 31 : i++;
106 :
107 31 : svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
108 31 : svcctl_ops[i].ops = &wins_svc_ops;
109 31 : i++;
110 :
111 : /* NULL terminate the array */
112 :
113 31 : svcctl_ops[i].name = NULL;
114 31 : svcctl_ops[i].ops = NULL;
115 :
116 31 : return True;
117 : }
118 :
119 30 : bool shutdown_service_op_table(void)
120 : {
121 30 : TALLOC_FREE(svcctl_ops);
122 :
123 30 : return true;
124 : }
125 :
126 : /********************************************************************
127 : ********************************************************************/
128 :
129 0 : static struct service_control_op* find_service_by_name( const char *name )
130 : {
131 : int i;
132 :
133 0 : for ( i=0; svcctl_ops[i].name; i++ ) {
134 0 : if ( strequal( name, svcctl_ops[i].name ) )
135 0 : return &svcctl_ops[i];
136 : }
137 :
138 0 : return NULL;
139 : }
140 : /********************************************************************
141 : ********************************************************************/
142 :
143 0 : static NTSTATUS svcctl_access_check( struct security_descriptor *sec_desc, struct security_token *token,
144 : uint32_t access_desired, uint32_t *access_granted )
145 : {
146 : NTSTATUS status;
147 0 : if ( geteuid() == sec_initial_uid() ) {
148 0 : DEBUG(5,("svcctl_access_check: using root's token\n"));
149 0 : status = get_root_nt_token(&token);
150 0 : if(!NT_STATUS_IS_OK(status)) {
151 0 : return status;
152 : }
153 : }
154 :
155 0 : return se_access_check( sec_desc, token, access_desired, access_granted);
156 : }
157 :
158 : /********************************************************************
159 : ********************************************************************/
160 :
161 0 : static struct security_descriptor* construct_scm_sd( TALLOC_CTX *ctx )
162 : {
163 : struct security_ace ace[2];
164 0 : size_t i = 0;
165 : struct security_descriptor *sd;
166 : struct security_acl *theacl;
167 : size_t sd_size;
168 :
169 : /* basic access for Everyone */
170 :
171 0 : init_sec_ace(&ace[i++], &global_sid_World,
172 : SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0);
173 :
174 : /* Full Access 'BUILTIN\Administrators' */
175 :
176 0 : init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
177 : SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0);
178 :
179 :
180 : /* create the security descriptor */
181 :
182 0 : if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
183 0 : return NULL;
184 :
185 0 : if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
186 : SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
187 : theacl, &sd_size)) )
188 0 : return NULL;
189 :
190 0 : return sd;
191 : }
192 :
193 : /******************************************************************
194 : Find a registry key handle and return a SERVICE_INFO
195 : *****************************************************************/
196 :
197 0 : static SERVICE_INFO *find_service_info_by_hnd(struct pipes_struct *p,
198 : struct policy_handle *hnd)
199 : {
200 0 : SERVICE_INFO *service_info = NULL;
201 : NTSTATUS status;
202 :
203 0 : service_info = find_policy_by_hnd(p,
204 : hnd,
205 : DCESRV_HANDLE_ANY,
206 : SERVICE_INFO,
207 : &status);
208 0 : if (!NT_STATUS_IS_OK(status)) {
209 0 : DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
210 0 : return NULL;
211 : }
212 :
213 0 : return service_info;
214 : }
215 :
216 : /******************************************************************
217 : *****************************************************************/
218 :
219 0 : static WERROR create_open_service_handle(struct pipes_struct *p,
220 : struct policy_handle *handle,
221 : uint32_t type,
222 : const char *service,
223 : uint32_t access_granted)
224 : {
225 0 : SERVICE_INFO *info = NULL;
226 0 : WERROR result = WERR_OK;
227 : struct service_control_op *s_op;
228 :
229 0 : if ( !(info = talloc_zero( NULL, SERVICE_INFO )) )
230 0 : return WERR_NOT_ENOUGH_MEMORY;
231 :
232 : /* the Service Manager has a NULL name */
233 :
234 0 : info->type = SVC_HANDLE_IS_SCM;
235 :
236 0 : switch ( type ) {
237 0 : case SVC_HANDLE_IS_SCM:
238 0 : info->type = SVC_HANDLE_IS_SCM;
239 0 : break;
240 :
241 0 : case SVC_HANDLE_IS_DBLOCK:
242 0 : info->type = SVC_HANDLE_IS_DBLOCK;
243 0 : break;
244 :
245 0 : case SVC_HANDLE_IS_SERVICE:
246 0 : info->type = SVC_HANDLE_IS_SERVICE;
247 :
248 : /* lookup the SERVICE_CONTROL_OPS */
249 :
250 0 : if ( !(s_op = find_service_by_name( service )) ) {
251 0 : result = WERR_SERVICE_DOES_NOT_EXIST;
252 0 : goto done;
253 : }
254 :
255 0 : info->ops = s_op->ops;
256 :
257 0 : if ( !(info->name = talloc_strdup( info, s_op->name )) ) {
258 0 : result = WERR_NOT_ENOUGH_MEMORY;
259 0 : goto done;
260 : }
261 0 : break;
262 :
263 0 : default:
264 0 : result = WERR_SERVICE_DOES_NOT_EXIST;
265 0 : goto done;
266 : }
267 :
268 0 : info->access_granted = access_granted;
269 :
270 : /* store the SERVICE_INFO and create an open handle */
271 :
272 0 : if ( !create_policy_hnd( p, handle, 0, info ) ) {
273 0 : result = WERR_ACCESS_DENIED;
274 0 : goto done;
275 : }
276 :
277 0 : done:
278 0 : if ( !W_ERROR_IS_OK(result) )
279 0 : TALLOC_FREE(info);
280 :
281 0 : return result;
282 : }
283 :
284 : /********************************************************************
285 : _svcctl_OpenSCManagerW
286 : ********************************************************************/
287 :
288 0 : WERROR _svcctl_OpenSCManagerW(struct pipes_struct *p,
289 : struct svcctl_OpenSCManagerW *r)
290 : {
291 0 : struct dcesrv_call_state *dce_call = p->dce_call;
292 0 : struct auth_session_info *session_info =
293 0 : dcesrv_call_session_info(dce_call);
294 : struct security_descriptor *sec_desc;
295 0 : uint32_t access_granted = 0;
296 : NTSTATUS status;
297 :
298 : /* perform access checks */
299 :
300 0 : if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
301 0 : return WERR_NOT_ENOUGH_MEMORY;
302 :
303 0 : se_map_generic( &r->in.access_mask, &scm_generic_map );
304 0 : status = svcctl_access_check( sec_desc, session_info->security_token,
305 : r->in.access_mask, &access_granted );
306 0 : if ( !NT_STATUS_IS_OK(status) )
307 0 : return ntstatus_to_werror( status );
308 :
309 0 : return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
310 : }
311 :
312 : /********************************************************************
313 : _svcctl_OpenServiceW
314 : ********************************************************************/
315 :
316 0 : WERROR _svcctl_OpenServiceW(struct pipes_struct *p,
317 : struct svcctl_OpenServiceW *r)
318 : {
319 0 : struct dcesrv_call_state *dce_call = p->dce_call;
320 0 : struct auth_session_info *session_info =
321 0 : dcesrv_call_session_info(dce_call);
322 : struct security_descriptor *sec_desc;
323 0 : uint32_t access_granted = 0;
324 : NTSTATUS status;
325 0 : const char *service = NULL;
326 : WERROR err;
327 :
328 0 : service = r->in.ServiceName;
329 0 : if (!service) {
330 0 : return WERR_NOT_ENOUGH_MEMORY;
331 : }
332 0 : DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service));
333 :
334 : /* based on my tests you can open a service if you have a valid scm handle */
335 :
336 0 : if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) )
337 0 : return WERR_INVALID_HANDLE;
338 :
339 : /*
340 : * Perform access checks. Use the system session_info in order to ensure
341 : * that we retrieve the security descriptor
342 : */
343 0 : err = svcctl_get_secdesc(p->msg_ctx,
344 : get_session_info_system(),
345 : service,
346 : p->mem_ctx,
347 : &sec_desc);
348 0 : if (W_ERROR_EQUAL(err, WERR_FILE_NOT_FOUND)) {
349 0 : DBG_NOTICE("service %s does not exist\n", service);
350 0 : return WERR_SERVICE_DOES_NOT_EXIST;
351 : }
352 0 : if (!W_ERROR_IS_OK(err)) {
353 0 : DBG_NOTICE("Failed to get a valid secdesc for %s: %s\n",
354 : service, win_errstr(err));
355 0 : return err;
356 : }
357 :
358 0 : se_map_generic( &r->in.access_mask, &svc_generic_map );
359 0 : status = svcctl_access_check( sec_desc, session_info->security_token,
360 : r->in.access_mask, &access_granted );
361 0 : if ( !NT_STATUS_IS_OK(status) )
362 0 : return ntstatus_to_werror( status );
363 :
364 0 : return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
365 : }
366 :
367 : /********************************************************************
368 : _svcctl_CloseServiceHandle
369 : ********************************************************************/
370 :
371 0 : WERROR _svcctl_CloseServiceHandle(struct pipes_struct *p,
372 : struct svcctl_CloseServiceHandle *r)
373 : {
374 0 : if ( !close_policy_hnd( p, r->in.handle ) )
375 0 : return WERR_INVALID_HANDLE;
376 :
377 0 : ZERO_STRUCTP(r->out.handle);
378 :
379 0 : return WERR_OK;
380 : }
381 :
382 : /********************************************************************
383 : _svcctl_GetServiceDisplayNameW
384 : ********************************************************************/
385 :
386 0 : WERROR _svcctl_GetServiceDisplayNameW(struct pipes_struct *p,
387 : struct svcctl_GetServiceDisplayNameW *r)
388 : {
389 0 : struct dcesrv_call_state *dce_call = p->dce_call;
390 0 : struct auth_session_info *session_info =
391 0 : dcesrv_call_session_info(dce_call);
392 : const char *service;
393 : const char *display_name;
394 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
395 :
396 : /* can only use an SCM handle here */
397 :
398 0 : if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
399 0 : return WERR_INVALID_HANDLE;
400 :
401 0 : service = r->in.service_name;
402 :
403 0 : display_name = svcctl_lookup_dispname(p->mem_ctx,
404 : p->msg_ctx,
405 : session_info,
406 : service);
407 0 : if (!display_name) {
408 0 : display_name = "";
409 : }
410 :
411 0 : *r->out.display_name = display_name;
412 0 : *r->out.display_name_length = strlen(display_name);
413 :
414 0 : return WERR_OK;
415 : }
416 :
417 : /********************************************************************
418 : _svcctl_QueryServiceStatus
419 : ********************************************************************/
420 :
421 0 : WERROR _svcctl_QueryServiceStatus(struct pipes_struct *p,
422 : struct svcctl_QueryServiceStatus *r)
423 : {
424 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
425 :
426 : /* perform access checks */
427 :
428 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
429 0 : return WERR_INVALID_HANDLE;
430 :
431 0 : if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
432 0 : return WERR_ACCESS_DENIED;
433 :
434 : /* try the service specific status call */
435 :
436 0 : return info->ops->service_status( info->name, r->out.service_status );
437 : }
438 :
439 : /********************************************************************
440 : ********************************************************************/
441 :
442 0 : static int enumerate_status(TALLOC_CTX *ctx,
443 : struct messaging_context *msg_ctx,
444 : struct auth_session_info *session_info,
445 : struct ENUM_SERVICE_STATUSW **status)
446 : {
447 0 : int num_services = 0;
448 : int i;
449 : struct ENUM_SERVICE_STATUSW *st;
450 : const char *display_name;
451 :
452 : /* just count */
453 0 : while ( svcctl_ops[num_services].name )
454 0 : num_services++;
455 :
456 0 : if ( !(st = talloc_array( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
457 0 : DEBUG(0,("enumerate_status: talloc() failed!\n"));
458 0 : return -1;
459 : }
460 :
461 0 : for ( i=0; i<num_services; i++ ) {
462 0 : st[i].service_name = talloc_strdup(st, svcctl_ops[i].name );
463 :
464 0 : display_name = svcctl_lookup_dispname(ctx,
465 : msg_ctx,
466 : session_info,
467 0 : svcctl_ops[i].name);
468 0 : st[i].display_name = talloc_strdup(st, display_name ? display_name : "");
469 :
470 0 : svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
471 : }
472 :
473 0 : *status = st;
474 :
475 0 : return num_services;
476 : }
477 :
478 : /********************************************************************
479 : _svcctl_EnumServicesStatusW
480 : ********************************************************************/
481 :
482 0 : WERROR _svcctl_EnumServicesStatusW(struct pipes_struct *p,
483 : struct svcctl_EnumServicesStatusW *r)
484 : {
485 0 : struct dcesrv_call_state *dce_call = p->dce_call;
486 0 : struct auth_session_info *session_info =
487 0 : dcesrv_call_session_info(dce_call);
488 0 : struct ENUM_SERVICE_STATUSW *services = NULL;
489 : int num_services;
490 0 : int i = 0;
491 0 : size_t buffer_size = 0;
492 0 : WERROR result = WERR_OK;
493 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
494 0 : DATA_BLOB blob = data_blob_null;
495 :
496 : /* perform access checks */
497 :
498 0 : if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
499 0 : return WERR_INVALID_HANDLE;
500 :
501 0 : if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
502 0 : return WERR_ACCESS_DENIED;
503 : }
504 :
505 0 : num_services = enumerate_status(p->mem_ctx,
506 : p->msg_ctx,
507 : session_info,
508 : &services);
509 0 : if (num_services == -1 ) {
510 0 : return WERR_NOT_ENOUGH_MEMORY;
511 : }
512 :
513 0 : for ( i=0; i<num_services; i++ ) {
514 0 : buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], 0);
515 : }
516 :
517 0 : buffer_size += buffer_size % 4;
518 :
519 0 : if (buffer_size > r->in.offered) {
520 0 : num_services = 0;
521 0 : result = WERR_MORE_DATA;
522 : }
523 :
524 0 : if ( W_ERROR_IS_OK(result) ) {
525 :
526 : enum ndr_err_code ndr_err;
527 : struct ndr_push *ndr;
528 :
529 0 : ndr = ndr_push_init_ctx(p->mem_ctx);
530 0 : if (ndr == NULL) {
531 0 : return WERR_INVALID_PARAMETER;
532 : }
533 :
534 0 : ndr_err = ndr_push_ENUM_SERVICE_STATUSW_array(
535 : ndr, num_services, services);
536 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
537 0 : return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err));
538 : }
539 0 : blob = ndr_push_blob(ndr);
540 0 : memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
541 : }
542 :
543 0 : *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
544 0 : *r->out.services_returned = (uint32_t)num_services;
545 0 : if (r->out.resume_handle) {
546 0 : *r->out.resume_handle = 0;
547 : }
548 :
549 0 : return result;
550 : }
551 :
552 : /********************************************************************
553 : _svcctl_StartServiceW
554 : ********************************************************************/
555 :
556 0 : WERROR _svcctl_StartServiceW(struct pipes_struct *p,
557 : struct svcctl_StartServiceW *r)
558 : {
559 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
560 :
561 : /* perform access checks */
562 :
563 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
564 0 : return WERR_INVALID_HANDLE;
565 :
566 0 : if ( !(info->access_granted & SC_RIGHT_SVC_START) )
567 0 : return WERR_ACCESS_DENIED;
568 :
569 0 : return info->ops->start_service( info->name );
570 : }
571 :
572 : /********************************************************************
573 : _svcctl_ControlService
574 : ********************************************************************/
575 :
576 0 : WERROR _svcctl_ControlService(struct pipes_struct *p,
577 : struct svcctl_ControlService *r)
578 : {
579 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
580 :
581 : /* perform access checks */
582 :
583 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
584 0 : return WERR_INVALID_HANDLE;
585 :
586 0 : switch ( r->in.control ) {
587 0 : case SVCCTL_CONTROL_STOP:
588 0 : if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
589 0 : return WERR_ACCESS_DENIED;
590 :
591 0 : return info->ops->stop_service( info->name,
592 : r->out.service_status );
593 :
594 0 : case SVCCTL_CONTROL_INTERROGATE:
595 0 : if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
596 0 : return WERR_ACCESS_DENIED;
597 :
598 0 : return info->ops->service_status( info->name,
599 : r->out.service_status );
600 0 : default:
601 0 : return WERR_INVALID_PARAMETER;
602 : }
603 : }
604 :
605 : /********************************************************************
606 : _svcctl_EnumDependentServicesW
607 : ********************************************************************/
608 :
609 0 : WERROR _svcctl_EnumDependentServicesW(struct pipes_struct *p,
610 : struct svcctl_EnumDependentServicesW *r)
611 : {
612 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service );
613 :
614 : /* perform access checks */
615 :
616 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
617 0 : return WERR_INVALID_HANDLE;
618 :
619 0 : if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
620 0 : return WERR_ACCESS_DENIED;
621 :
622 0 : switch (r->in.state) {
623 0 : case SERVICE_STATE_ACTIVE:
624 : case SERVICE_STATE_INACTIVE:
625 : case SERVICE_STATE_ALL:
626 0 : break;
627 0 : default:
628 0 : return WERR_INVALID_PARAMETER;
629 : }
630 :
631 : /* we have to set the outgoing buffer size to the same as the
632 : incoming buffer size (even in the case of failure */
633 : /* this is done in the autogenerated server already - gd */
634 :
635 0 : *r->out.needed = r->in.offered;
636 :
637 : /* no dependent services...basically a stub function */
638 0 : *r->out.services_returned = 0;
639 :
640 0 : return WERR_OK;
641 : }
642 :
643 : /********************************************************************
644 : _svcctl_QueryServiceStatusEx
645 : ********************************************************************/
646 :
647 0 : WERROR _svcctl_QueryServiceStatusEx(struct pipes_struct *p,
648 : struct svcctl_QueryServiceStatusEx *r)
649 : {
650 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
651 : uint32_t buffer_size;
652 :
653 : /* perform access checks */
654 :
655 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
656 0 : return WERR_INVALID_HANDLE;
657 :
658 0 : if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
659 0 : return WERR_ACCESS_DENIED;
660 :
661 : /* we have to set the outgoing buffer size to the same as the
662 : incoming buffer size (even in the case of failure) */
663 0 : *r->out.needed = r->in.offered;
664 :
665 0 : switch ( r->in.info_level ) {
666 0 : case SVC_STATUS_PROCESS_INFO:
667 : {
668 : struct SERVICE_STATUS_PROCESS svc_stat_proc;
669 : enum ndr_err_code ndr_err;
670 : DATA_BLOB blob;
671 :
672 : /* Get the status of the service.. */
673 0 : info->ops->service_status( info->name, &svc_stat_proc.status );
674 0 : svc_stat_proc.process_id = getpid();
675 0 : svc_stat_proc.service_flags = 0x0;
676 :
677 0 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &svc_stat_proc,
678 : (ndr_push_flags_fn_t)ndr_push_SERVICE_STATUS_PROCESS);
679 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
680 0 : return WERR_INVALID_PARAMETER;
681 : }
682 :
683 0 : r->out.buffer = blob.data;
684 0 : buffer_size = sizeof(struct SERVICE_STATUS_PROCESS);
685 0 : break;
686 : }
687 :
688 0 : default:
689 0 : return WERR_INVALID_LEVEL;
690 : }
691 :
692 :
693 0 : buffer_size += buffer_size % 4;
694 0 : *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
695 :
696 0 : if (buffer_size > r->in.offered ) {
697 0 : return WERR_INSUFFICIENT_BUFFER;
698 : }
699 :
700 0 : return WERR_OK;
701 : }
702 :
703 : /********************************************************************
704 : ********************************************************************/
705 :
706 0 : static WERROR fill_svc_config(TALLOC_CTX *mem_ctx,
707 : struct messaging_context *msg_ctx,
708 : struct auth_session_info *session_info,
709 : const char *name,
710 : struct QUERY_SERVICE_CONFIG *config)
711 : {
712 0 : const char *result = NULL;
713 :
714 : /* now fill in the individual values */
715 :
716 0 : ZERO_STRUCTP(config);
717 :
718 0 : config->displayname = svcctl_lookup_dispname(mem_ctx,
719 : msg_ctx,
720 : session_info,
721 : name);
722 :
723 0 : result = svcctl_get_string_value(mem_ctx,
724 : msg_ctx,
725 : session_info,
726 : name,
727 : "ObjectName");
728 0 : if (result != NULL) {
729 0 : config->startname = result;
730 : }
731 :
732 0 : result = svcctl_get_string_value(mem_ctx,
733 : msg_ctx,
734 : session_info,
735 : name,
736 : "ImagePath");
737 0 : if (result != NULL) {
738 0 : config->executablepath = result;
739 : }
740 :
741 : /* a few hard coded values */
742 : /* loadordergroup and dependencies are empty */
743 :
744 0 : config->tag_id = 0x00000000; /* unassigned loadorder group */
745 0 : config->service_type = SERVICE_TYPE_WIN32_OWN_PROCESS;
746 0 : config->error_control = SVCCTL_SVC_ERROR_NORMAL;
747 :
748 : /* set the start type. NetLogon and WINS are disabled to prevent
749 : the client from showing the "Start" button (if of course the services
750 : are not running */
751 :
752 0 : if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
753 0 : config->start_type = SVCCTL_DISABLED;
754 0 : else if ( strequal( name, "WINS" ) && ( !lp_we_are_a_wins_server() ))
755 0 : config->start_type = SVCCTL_DISABLED;
756 : else
757 0 : config->start_type = SVCCTL_DEMAND_START;
758 :
759 0 : return WERR_OK;
760 : }
761 :
762 : /********************************************************************
763 : _svcctl_QueryServiceConfigW
764 : ********************************************************************/
765 :
766 0 : WERROR _svcctl_QueryServiceConfigW(struct pipes_struct *p,
767 : struct svcctl_QueryServiceConfigW *r)
768 : {
769 0 : struct dcesrv_call_state *dce_call = p->dce_call;
770 0 : struct auth_session_info *session_info =
771 0 : dcesrv_call_session_info(dce_call);
772 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
773 : uint32_t buffer_size;
774 : WERROR wresult;
775 :
776 : /* perform access checks */
777 :
778 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
779 0 : return WERR_INVALID_HANDLE;
780 :
781 0 : if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
782 0 : return WERR_ACCESS_DENIED;
783 :
784 : /* we have to set the outgoing buffer size to the same as the
785 : incoming buffer size (even in the case of failure */
786 :
787 0 : *r->out.needed = r->in.offered;
788 :
789 0 : wresult = fill_svc_config(p->mem_ctx,
790 : p->msg_ctx,
791 : session_info,
792 0 : info->name,
793 : r->out.query);
794 0 : if ( !W_ERROR_IS_OK(wresult) )
795 0 : return wresult;
796 :
797 0 : buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, 0);
798 0 : *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
799 :
800 0 : if (buffer_size > r->in.offered ) {
801 0 : ZERO_STRUCTP(r->out.query);
802 0 : return WERR_INSUFFICIENT_BUFFER;
803 : }
804 :
805 0 : return WERR_OK;
806 : }
807 :
808 : /********************************************************************
809 : _svcctl_QueryServiceConfig2W
810 : ********************************************************************/
811 :
812 0 : WERROR _svcctl_QueryServiceConfig2W(struct pipes_struct *p,
813 : struct svcctl_QueryServiceConfig2W *r)
814 : {
815 0 : struct dcesrv_call_state *dce_call = p->dce_call;
816 0 : struct auth_session_info *session_info =
817 0 : dcesrv_call_session_info(dce_call);
818 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
819 : uint32_t buffer_size;
820 0 : DATA_BLOB blob = data_blob_null;
821 :
822 : /* perform access checks */
823 :
824 0 : if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
825 0 : return WERR_INVALID_HANDLE;
826 :
827 0 : if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
828 0 : return WERR_ACCESS_DENIED;
829 :
830 : /* we have to set the outgoing buffer size to the same as the
831 : incoming buffer size (even in the case of failure */
832 0 : *r->out.needed = r->in.offered;
833 :
834 0 : switch ( r->in.info_level ) {
835 0 : case SERVICE_CONFIG_DESCRIPTION:
836 : {
837 : struct SERVICE_DESCRIPTION desc_buf;
838 : const char *description;
839 : enum ndr_err_code ndr_err;
840 :
841 0 : description = svcctl_lookup_description(p->mem_ctx,
842 : p->msg_ctx,
843 : session_info,
844 0 : info->name);
845 :
846 0 : desc_buf.description = description;
847 :
848 0 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &desc_buf,
849 : (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION);
850 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
851 0 : return WERR_INVALID_PARAMETER;
852 : }
853 :
854 0 : break;
855 : }
856 : break;
857 0 : case SERVICE_CONFIG_FAILURE_ACTIONS:
858 : {
859 : struct SERVICE_FAILURE_ACTIONS actions;
860 : enum ndr_err_code ndr_err;
861 :
862 : /* nothing to say...just service the request */
863 :
864 0 : ZERO_STRUCT( actions );
865 :
866 0 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &actions,
867 : (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS);
868 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
869 0 : return WERR_INVALID_PARAMETER;
870 : }
871 :
872 0 : break;
873 : }
874 : break;
875 :
876 0 : default:
877 0 : return WERR_INVALID_LEVEL;
878 : }
879 :
880 0 : buffer_size = blob.length;
881 0 : buffer_size += buffer_size % 4;
882 0 : *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
883 :
884 0 : if (buffer_size > r->in.offered)
885 0 : return WERR_INSUFFICIENT_BUFFER;
886 :
887 0 : memcpy(r->out.buffer, blob.data, blob.length);
888 :
889 0 : return WERR_OK;
890 : }
891 :
892 : /********************************************************************
893 : _svcctl_LockServiceDatabase
894 : ********************************************************************/
895 :
896 0 : WERROR _svcctl_LockServiceDatabase(struct pipes_struct *p,
897 : struct svcctl_LockServiceDatabase *r)
898 : {
899 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
900 :
901 : /* perform access checks */
902 :
903 0 : if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
904 0 : return WERR_INVALID_HANDLE;
905 :
906 0 : if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
907 0 : return WERR_ACCESS_DENIED;
908 :
909 : /* Just open a handle. Doesn't actually lock anything */
910 :
911 0 : return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
912 : }
913 :
914 : /********************************************************************
915 : _svcctl_UnlockServiceDatabase
916 : ********************************************************************/
917 :
918 0 : WERROR _svcctl_UnlockServiceDatabase(struct pipes_struct *p,
919 : struct svcctl_UnlockServiceDatabase *r)
920 : {
921 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
922 :
923 :
924 0 : if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
925 0 : return WERR_INVALID_HANDLE;
926 :
927 0 : return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_INVALID_HANDLE;
928 : }
929 :
930 : /********************************************************************
931 : _svcctl_QueryServiceObjectSecurity
932 : ********************************************************************/
933 :
934 0 : WERROR _svcctl_QueryServiceObjectSecurity(struct pipes_struct *p,
935 : struct svcctl_QueryServiceObjectSecurity *r)
936 : {
937 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
938 : struct security_descriptor *sec_desc;
939 : NTSTATUS status;
940 0 : uint8_t *buffer = NULL;
941 0 : size_t len = 0;
942 : WERROR err;
943 :
944 :
945 : /* only support the SCM and individual services */
946 :
947 0 : if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
948 0 : return WERR_INVALID_HANDLE;
949 :
950 : /* check access reights (according to MSDN) */
951 :
952 0 : if ( !(info->access_granted & SEC_STD_READ_CONTROL) )
953 0 : return WERR_ACCESS_DENIED;
954 :
955 : /* TODO: handle something besides SECINFO_DACL */
956 :
957 0 : if ( (r->in.security_flags & SECINFO_DACL) != SECINFO_DACL )
958 0 : return WERR_INVALID_PARAMETER;
959 :
960 : /* Lookup the security descriptor and marshall it up for a reply */
961 0 : err = svcctl_get_secdesc(p->msg_ctx,
962 : get_session_info_system(),
963 0 : info->name,
964 : p->mem_ctx,
965 : &sec_desc);
966 0 : if (W_ERROR_EQUAL(err, WERR_FILE_NOT_FOUND)) {
967 0 : DBG_NOTICE("service %s does not exist\n", info->name);
968 0 : return WERR_SERVICE_DOES_NOT_EXIST;
969 : }
970 0 : if (!W_ERROR_IS_OK(err)) {
971 0 : DBG_NOTICE("Failed to get a valid secdesc for %s: %s\n",
972 : info->name, win_errstr(err));
973 0 : return err;
974 : }
975 :
976 0 : *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
977 :
978 0 : if ( *r->out.needed > r->in.offered) {
979 0 : return WERR_INSUFFICIENT_BUFFER;
980 : }
981 :
982 0 : status = marshall_sec_desc(p->mem_ctx, sec_desc, &buffer, &len);
983 0 : if (!NT_STATUS_IS_OK(status)) {
984 0 : return ntstatus_to_werror(status);
985 : }
986 :
987 0 : *r->out.needed = len;
988 0 : memcpy(r->out.buffer, buffer, len);
989 :
990 0 : return WERR_OK;
991 : }
992 :
993 : /********************************************************************
994 : _svcctl_SetServiceObjectSecurity
995 : ********************************************************************/
996 :
997 0 : WERROR _svcctl_SetServiceObjectSecurity(struct pipes_struct *p,
998 : struct svcctl_SetServiceObjectSecurity *r)
999 : {
1000 0 : struct dcesrv_call_state *dce_call = p->dce_call;
1001 0 : struct auth_session_info *session_info =
1002 0 : dcesrv_call_session_info(dce_call);
1003 0 : SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
1004 0 : struct security_descriptor *sec_desc = NULL;
1005 : uint32_t required_access;
1006 : NTSTATUS status;
1007 :
1008 0 : if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
1009 0 : return WERR_INVALID_HANDLE;
1010 :
1011 : /* can't set the security de4scriptor on the ServiceControlManager */
1012 :
1013 0 : if ( info->type == SVC_HANDLE_IS_SCM )
1014 0 : return WERR_ACCESS_DENIED;
1015 :
1016 : /* check the access on the open handle */
1017 :
1018 0 : switch ( r->in.security_flags ) {
1019 0 : case SECINFO_DACL:
1020 0 : required_access = SEC_STD_WRITE_DAC;
1021 0 : break;
1022 :
1023 0 : case SECINFO_OWNER:
1024 : case SECINFO_GROUP:
1025 0 : required_access = SEC_STD_WRITE_OWNER;
1026 0 : break;
1027 :
1028 0 : case SECINFO_SACL:
1029 0 : return WERR_INVALID_PARAMETER;
1030 0 : default:
1031 0 : return WERR_INVALID_PARAMETER;
1032 : }
1033 :
1034 0 : if ( !(info->access_granted & required_access) )
1035 0 : return WERR_ACCESS_DENIED;
1036 :
1037 : /* read the security descfriptor */
1038 :
1039 0 : status = unmarshall_sec_desc(p->mem_ctx,
1040 : r->in.buffer,
1041 0 : r->in.offered,
1042 : &sec_desc);
1043 0 : if (!NT_STATUS_IS_OK(status)) {
1044 0 : return ntstatus_to_werror(status);
1045 : }
1046 :
1047 : /* store the new SD */
1048 :
1049 0 : if (!svcctl_set_secdesc(p->msg_ctx, session_info, info->name, sec_desc))
1050 0 : return WERR_ACCESS_DENIED;
1051 :
1052 0 : return WERR_OK;
1053 : }
1054 :
1055 :
1056 0 : WERROR _svcctl_DeleteService(struct pipes_struct *p,
1057 : struct svcctl_DeleteService *r)
1058 : {
1059 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1060 0 : return WERR_NOT_SUPPORTED;
1061 : }
1062 :
1063 0 : WERROR _svcctl_SetServiceStatus(struct pipes_struct *p,
1064 : struct svcctl_SetServiceStatus *r)
1065 : {
1066 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1067 0 : return WERR_NOT_SUPPORTED;
1068 : }
1069 :
1070 0 : WERROR _svcctl_NotifyBootConfigStatus(struct pipes_struct *p,
1071 : struct svcctl_NotifyBootConfigStatus *r)
1072 : {
1073 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1074 0 : return WERR_NOT_SUPPORTED;
1075 : }
1076 :
1077 0 : WERROR _svcctl_SCSetServiceBitsW(struct pipes_struct *p,
1078 : struct svcctl_SCSetServiceBitsW *r)
1079 : {
1080 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1081 0 : return WERR_NOT_SUPPORTED;
1082 : }
1083 :
1084 0 : WERROR _svcctl_ChangeServiceConfigW(struct pipes_struct *p,
1085 : struct svcctl_ChangeServiceConfigW *r)
1086 : {
1087 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1088 0 : return WERR_NOT_SUPPORTED;
1089 : }
1090 :
1091 0 : WERROR _svcctl_CreateServiceW(struct pipes_struct *p,
1092 : struct svcctl_CreateServiceW *r)
1093 : {
1094 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1095 0 : return WERR_NOT_SUPPORTED;
1096 : }
1097 :
1098 0 : WERROR _svcctl_QueryServiceLockStatusW(struct pipes_struct *p,
1099 : struct svcctl_QueryServiceLockStatusW *r)
1100 : {
1101 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1102 0 : return WERR_NOT_SUPPORTED;
1103 : }
1104 :
1105 0 : WERROR _svcctl_GetServiceKeyNameW(struct pipes_struct *p,
1106 : struct svcctl_GetServiceKeyNameW *r)
1107 : {
1108 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1109 0 : return WERR_NOT_SUPPORTED;
1110 : }
1111 :
1112 0 : WERROR _svcctl_SCSetServiceBitsA(struct pipes_struct *p,
1113 : struct svcctl_SCSetServiceBitsA *r)
1114 : {
1115 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1116 0 : return WERR_NOT_SUPPORTED;
1117 : }
1118 :
1119 0 : WERROR _svcctl_ChangeServiceConfigA(struct pipes_struct *p,
1120 : struct svcctl_ChangeServiceConfigA *r)
1121 : {
1122 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1123 0 : return WERR_NOT_SUPPORTED;
1124 : }
1125 :
1126 0 : WERROR _svcctl_CreateServiceA(struct pipes_struct *p,
1127 : struct svcctl_CreateServiceA *r)
1128 : {
1129 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1130 0 : return WERR_NOT_SUPPORTED;
1131 : }
1132 :
1133 0 : WERROR _svcctl_EnumDependentServicesA(struct pipes_struct *p,
1134 : struct svcctl_EnumDependentServicesA *r)
1135 : {
1136 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1137 0 : return WERR_NOT_SUPPORTED;
1138 : }
1139 :
1140 0 : WERROR _svcctl_EnumServicesStatusA(struct pipes_struct *p,
1141 : struct svcctl_EnumServicesStatusA *r)
1142 : {
1143 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1144 0 : return WERR_NOT_SUPPORTED;
1145 : }
1146 :
1147 0 : WERROR _svcctl_OpenSCManagerA(struct pipes_struct *p,
1148 : struct svcctl_OpenSCManagerA *r)
1149 : {
1150 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1151 0 : return WERR_NOT_SUPPORTED;
1152 : }
1153 :
1154 0 : WERROR _svcctl_OpenServiceA(struct pipes_struct *p,
1155 : struct svcctl_OpenServiceA *r)
1156 : {
1157 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1158 0 : return WERR_NOT_SUPPORTED;
1159 : }
1160 :
1161 0 : WERROR _svcctl_QueryServiceConfigA(struct pipes_struct *p,
1162 : struct svcctl_QueryServiceConfigA *r)
1163 : {
1164 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1165 0 : return WERR_NOT_SUPPORTED;
1166 : }
1167 :
1168 0 : WERROR _svcctl_QueryServiceLockStatusA(struct pipes_struct *p,
1169 : struct svcctl_QueryServiceLockStatusA *r)
1170 : {
1171 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1172 0 : return WERR_NOT_SUPPORTED;
1173 : }
1174 :
1175 0 : WERROR _svcctl_StartServiceA(struct pipes_struct *p,
1176 : struct svcctl_StartServiceA *r)
1177 : {
1178 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1179 0 : return WERR_NOT_SUPPORTED;
1180 : }
1181 :
1182 0 : WERROR _svcctl_GetServiceDisplayNameA(struct pipes_struct *p,
1183 : struct svcctl_GetServiceDisplayNameA *r)
1184 : {
1185 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1186 0 : return WERR_NOT_SUPPORTED;
1187 : }
1188 :
1189 0 : WERROR _svcctl_GetServiceKeyNameA(struct pipes_struct *p,
1190 : struct svcctl_GetServiceKeyNameA *r)
1191 : {
1192 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1193 0 : return WERR_NOT_SUPPORTED;
1194 : }
1195 :
1196 0 : WERROR _svcctl_GetCurrentGroupeStateW(struct pipes_struct *p,
1197 : struct svcctl_GetCurrentGroupeStateW *r)
1198 : {
1199 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1200 0 : return WERR_NOT_SUPPORTED;
1201 : }
1202 :
1203 0 : WERROR _svcctl_EnumServiceGroupW(struct pipes_struct *p,
1204 : struct svcctl_EnumServiceGroupW *r)
1205 : {
1206 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1207 0 : return WERR_NOT_SUPPORTED;
1208 : }
1209 :
1210 0 : WERROR _svcctl_ChangeServiceConfig2A(struct pipes_struct *p,
1211 : struct svcctl_ChangeServiceConfig2A *r)
1212 : {
1213 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1214 0 : return WERR_NOT_SUPPORTED;
1215 : }
1216 :
1217 0 : WERROR _svcctl_ChangeServiceConfig2W(struct pipes_struct *p,
1218 : struct svcctl_ChangeServiceConfig2W *r)
1219 : {
1220 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1221 0 : return WERR_NOT_SUPPORTED;
1222 : }
1223 :
1224 0 : WERROR _svcctl_QueryServiceConfig2A(struct pipes_struct *p,
1225 : struct svcctl_QueryServiceConfig2A *r)
1226 : {
1227 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1228 0 : return WERR_NOT_SUPPORTED;
1229 : }
1230 :
1231 0 : WERROR _EnumServicesStatusExA(struct pipes_struct *p,
1232 : struct EnumServicesStatusExA *r)
1233 : {
1234 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1235 0 : return WERR_NOT_SUPPORTED;
1236 : }
1237 :
1238 0 : WERROR _EnumServicesStatusExW(struct pipes_struct *p,
1239 : struct EnumServicesStatusExW *r)
1240 : {
1241 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1242 0 : return WERR_NOT_SUPPORTED;
1243 : }
1244 :
1245 0 : WERROR _svcctl_SCSendTSMessage(struct pipes_struct *p,
1246 : struct svcctl_SCSendTSMessage *r)
1247 : {
1248 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1249 0 : return WERR_NOT_SUPPORTED;
1250 : }
1251 :
1252 : static NTSTATUS svcctl__op_init_server(struct dcesrv_context *dce_ctx,
1253 : const struct dcesrv_endpoint_server *ep_server);
1254 :
1255 : static NTSTATUS svcctl__op_shutdown_server(struct dcesrv_context *dce_ctx,
1256 : const struct dcesrv_endpoint_server *ep_server);
1257 :
1258 : #define DCESRV_INTERFACE_SVCCTL_INIT_SERVER \
1259 : svcctl_init_server
1260 :
1261 : #define DCESRV_INTERFACE_SVCCTL_SHUTDOWN_SERVER \
1262 : svcctl_shutdown_server
1263 :
1264 31 : static NTSTATUS svcctl_init_server(struct dcesrv_context *dce_ctx,
1265 : const struct dcesrv_endpoint_server *ep_server)
1266 : {
1267 31 : struct messaging_context *msg_ctx = global_messaging_context();
1268 : bool ok;
1269 :
1270 : /* initialize the control hooks */
1271 31 : init_service_op_table();
1272 :
1273 31 : ok = svcctl_init_winreg(msg_ctx);
1274 31 : if (!ok) {
1275 0 : return NT_STATUS_UNSUCCESSFUL;
1276 : }
1277 :
1278 31 : return svcctl__op_init_server(dce_ctx, ep_server);
1279 : }
1280 :
1281 30 : static NTSTATUS svcctl_shutdown_server(struct dcesrv_context *dce_ctx,
1282 : const struct dcesrv_endpoint_server *ep_server)
1283 : {
1284 30 : shutdown_service_op_table();
1285 :
1286 30 : return svcctl__op_shutdown_server(dce_ctx, ep_server);
1287 : }
1288 :
1289 : /* include the generated boilerplate */
1290 : #include "librpc/gen_ndr/ndr_svcctl_scompat.c"
|