Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * SVCCTL RPC server keys initialization
5 : *
6 : * Copyright (c) 2005 Marcin Krzysztof Porwit
7 : * Copyright (c) 2005 Gerald (Jerry) Carter
8 : * Copyright (c) 2011 Andreas Schneider <asn@samba.org>
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "system/filesys.h"
26 : #include "services/services.h"
27 : #include "services/svc_winreg_glue.h"
28 : #include "../librpc/gen_ndr/ndr_winreg_c.h"
29 : #include "rpc_client/cli_winreg_int.h"
30 : #include "rpc_client/cli_winreg.h"
31 : #include "rpc_server/svcctl/srv_svcctl_reg.h"
32 : #include "auth.h"
33 : #include "registry/reg_backend_db.h"
34 :
35 : #undef DBGC_CLASS
36 : #define DBGC_CLASS DBGC_REGISTRY
37 :
38 : #define TOP_LEVEL_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
39 :
40 : struct rcinit_file_information {
41 : char *description;
42 : };
43 :
44 : struct service_display_info {
45 : const char *servicename;
46 : const char *daemon;
47 : const char *dispname;
48 : const char *description;
49 : };
50 :
51 : static struct service_display_info builtin_svcs[] = {
52 : {
53 : "Spooler",
54 : "smbd",
55 : "Print Spooler",
56 : "Internal service for spooling files to print devices"
57 : },
58 : {
59 : "NETLOGON",
60 : "smbd",
61 : "Net Logon",
62 : "File service providing access to policy and profile data (not"
63 : "remotely manageable)"
64 : },
65 : {
66 : "RemoteRegistry",
67 : "smbd",
68 : "Remote Registry Service",
69 : "Internal service providing remote access to the Samba registry"
70 : },
71 : {
72 : "WINS",
73 : "nmbd",
74 : "Windows Internet Name Service (WINS)",
75 : "Internal service providing a NetBIOS point-to-point name server"
76 : "(not remotely manageable)"
77 : },
78 : { NULL, NULL, NULL, NULL }
79 : };
80 :
81 : static struct service_display_info common_unix_svcs[] = {
82 : { "cups", NULL, "Common Unix Printing System","Provides unified printing support for all operating systems" },
83 : { "postfix", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" },
84 : { "sendmail", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" },
85 : { "portmap", NULL, "TCP Port to RPC PortMapper",NULL },
86 : { "xinetd", NULL, "Internet Meta-Daemon", NULL },
87 : { "inet", NULL, "Internet Meta-Daemon", NULL },
88 : { "xntpd", NULL, "Network Time Service", NULL },
89 : { "ntpd", NULL, "Network Time Service", NULL },
90 : { "lpd", NULL, "BSD Print Spooler", NULL },
91 : { "nfsserver", NULL, "Network File Service", NULL },
92 : { "cron", NULL, "Scheduling Service", NULL },
93 : { "at", NULL, "Scheduling Service", NULL },
94 : { "nscd", NULL, "Name Service Cache Daemon", NULL },
95 : { "slapd", NULL, "LDAP Directory Service", NULL },
96 : { "ldap", NULL, "LDAP DIrectory Service", NULL },
97 : { "ypbind", NULL, "NIS Directory Service", NULL },
98 : { "courier-imap", NULL, "IMAP4 Mail Service", NULL },
99 : { "courier-pop3", NULL, "POP3 Mail Service", NULL },
100 : { "named", NULL, "Domain Name Service", NULL },
101 : { "bind", NULL, "Domain Name Service", NULL },
102 : { "httpd", NULL, "HTTP Server", NULL },
103 : { "apache", NULL, "HTTP Server", "Provides s highly scalable and flexible web server "
104 : "capable of implementing various protocols including "
105 : "but not limited to HTTP" },
106 : { "autofs", NULL, "Automounter", NULL },
107 : { "squid", NULL, "Web Cache Proxy ", NULL },
108 : { "perfcountd", NULL, "Performance Monitoring Daemon", NULL },
109 : { "pgsql", NULL, "PgSQL Database Server", "Provides service for SQL database from Postgresql.org" },
110 : { "arpwatch", NULL, "ARP Tables watcher", "Provides service for monitoring ARP tables for changes" },
111 : { "dhcpd", NULL, "DHCP Server", "Provides service for dynamic host configuration and IP assignment" },
112 : { "nwserv", NULL, "NetWare Server Emulator", "Provides service for emulating Novell NetWare 3.12 server" },
113 : { "proftpd", NULL, "Professional FTP Server", "Provides high configurable service for FTP connection and "
114 : "file transferring" },
115 : { "ssh2", NULL, "SSH Secure Shell", "Provides service for secure connection for remote administration" },
116 : { "sshd", NULL, "SSH Secure Shell", "Provides service for secure connection for remote administration" },
117 : { NULL, NULL, NULL, NULL }
118 : };
119 :
120 : /********************************************************************
121 : This is where we do the dirty work of filling in things like the
122 : Display name, Description, etc...
123 : ********************************************************************/
124 0 : static char *svcctl_get_common_service_dispname(TALLOC_CTX *mem_ctx,
125 : const char *servicename)
126 : {
127 0 : uint32_t i;
128 :
129 0 : for (i = 0; common_unix_svcs[i].servicename; i++) {
130 0 : if (strequal(servicename, common_unix_svcs[i].servicename)) {
131 0 : char *dispname;
132 0 : dispname = talloc_asprintf(mem_ctx, "%s (%s)",
133 : common_unix_svcs[i].dispname,
134 : common_unix_svcs[i].servicename);
135 0 : if (dispname == NULL) {
136 0 : return NULL;
137 : }
138 0 : return dispname;
139 : }
140 : }
141 :
142 0 : return talloc_strdup(mem_ctx, servicename);
143 : }
144 :
145 : /********************************************************************
146 : ********************************************************************/
147 0 : static char *svcctl_cleanup_string(TALLOC_CTX *mem_ctx,
148 : const char *string)
149 : {
150 0 : char *clean = NULL;
151 0 : char *begin, *end;
152 :
153 0 : clean = talloc_strdup(mem_ctx, string);
154 0 : if (clean == NULL) {
155 0 : return NULL;
156 : }
157 0 : begin = clean;
158 :
159 : /* trim any beginning whilespace */
160 0 : while (isspace(*begin)) {
161 0 : begin++;
162 : }
163 :
164 0 : if (*begin == '\0') {
165 0 : return NULL;
166 : }
167 :
168 : /* trim any trailing whitespace or carriage returns.
169 : Start at the end and move backwards */
170 :
171 0 : end = begin + strlen(begin) - 1;
172 :
173 0 : while (isspace(*end) || *end=='\n' || *end=='\r') {
174 0 : *end = '\0';
175 0 : end--;
176 : }
177 :
178 0 : return begin;
179 : }
180 :
181 : /********************************************************************
182 : ********************************************************************/
183 0 : static bool read_init_file(TALLOC_CTX *mem_ctx,
184 : const char *servicename,
185 : struct rcinit_file_information **service_info)
186 : {
187 0 : struct rcinit_file_information *info = NULL;
188 0 : char *filepath = NULL;
189 0 : char str[1024];
190 0 : FILE *f = NULL;
191 0 : char *p = NULL;
192 :
193 0 : info = talloc_zero(mem_ctx, struct rcinit_file_information);
194 0 : if (info == NULL) {
195 0 : return false;
196 : }
197 :
198 : /* attempt the file open */
199 :
200 0 : filepath = talloc_asprintf(mem_ctx,
201 : "%s/%s/%s",
202 : get_dyn_MODULESDIR(),
203 : SVCCTL_SCRIPT_DIR,
204 : servicename);
205 0 : if (filepath == NULL) {
206 0 : return false;
207 : }
208 0 : f = fopen( filepath, "r" );
209 0 : if (f == NULL) {
210 0 : DEBUG(0,("read_init_file: failed to open [%s]\n", filepath));
211 0 : return false;
212 : }
213 :
214 0 : while ((fgets(str, sizeof(str) - 1, f)) != NULL) {
215 : /* ignore everything that is not a full line
216 : comment starting with a '#' */
217 :
218 0 : if (str[0] != '#') {
219 0 : continue;
220 : }
221 :
222 : /* Look for a line like '^#.*Description:' */
223 :
224 0 : p = strstr(str, "Description:");
225 0 : if (p != NULL) {
226 0 : char *desc;
227 0 : size_t len = strlen(p);
228 :
229 0 : if (len <= 12) {
230 0 : break;
231 : }
232 :
233 0 : desc = svcctl_cleanup_string(mem_ctx, p + 12);
234 0 : if (desc != NULL) {
235 0 : info->description = talloc_strdup(info, desc);
236 : }
237 : }
238 : }
239 :
240 0 : fclose(f);
241 :
242 0 : if (info->description == NULL) {
243 0 : info->description = talloc_strdup(info,
244 : "External Unix Service");
245 0 : if (info->description == NULL) {
246 0 : return false;
247 : }
248 : }
249 :
250 0 : *service_info = info;
251 :
252 0 : return true;
253 : }
254 :
255 504 : static bool svcctl_add_service(TALLOC_CTX *mem_ctx,
256 : struct dcerpc_binding_handle *h,
257 : struct policy_handle *hive_hnd,
258 : const char *key,
259 : uint32_t access_mask,
260 : const char *name)
261 : {
262 504 : enum winreg_CreateAction action = REG_ACTION_NONE;
263 504 : struct security_descriptor *sd = NULL;
264 0 : struct policy_handle key_hnd;
265 0 : struct winreg_String wkey;
266 0 : struct winreg_String wkeyclass;
267 504 : char *description = NULL;
268 504 : char *dname = NULL;
269 504 : char *ipath = NULL;
270 504 : bool ok = false;
271 0 : uint32_t i;
272 0 : NTSTATUS status;
273 504 : WERROR result = WERR_OK;
274 :
275 504 : ZERO_STRUCT(key_hnd);
276 :
277 504 : ZERO_STRUCT(wkey);
278 504 : wkey.name = talloc_asprintf(mem_ctx, "%s\\%s", key, name);
279 504 : if (wkey.name == NULL) {
280 0 : goto done;
281 : }
282 :
283 504 : ZERO_STRUCT(wkeyclass);
284 504 : wkeyclass.name = "";
285 :
286 504 : status = dcerpc_winreg_CreateKey(h,
287 : mem_ctx,
288 : hive_hnd,
289 : wkey,
290 : wkeyclass,
291 : 0,
292 : access_mask,
293 : NULL,
294 : &key_hnd,
295 : &action,
296 : &result);
297 504 : if (!NT_STATUS_IS_OK(status)) {
298 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
299 : wkey.name, nt_errstr(status)));
300 0 : goto done;
301 : }
302 504 : if (!W_ERROR_IS_OK(result)) {
303 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
304 : wkey.name, win_errstr(result)));
305 0 : goto done;
306 : }
307 :
308 : /* These values are hardcoded in all QueryServiceConfig() replies.
309 : I'm just storing them here for cosmetic purposes */
310 504 : status = dcerpc_winreg_set_dword(mem_ctx,
311 : h,
312 : &key_hnd,
313 : "Start",
314 : SVCCTL_AUTO_START,
315 : &result);
316 504 : if (!NT_STATUS_IS_OK(status)) {
317 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
318 : nt_errstr(status)));
319 0 : goto done;
320 : }
321 504 : if (!W_ERROR_IS_OK(result)) {
322 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
323 : win_errstr(result)));
324 0 : goto done;
325 : }
326 :
327 504 : status = dcerpc_winreg_set_dword(mem_ctx,
328 : h,
329 : &key_hnd,
330 : "Type",
331 : SERVICE_TYPE_WIN32_OWN_PROCESS,
332 : &result);
333 504 : if (!NT_STATUS_IS_OK(status)) {
334 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
335 : nt_errstr(status)));
336 0 : goto done;
337 : }
338 504 : if (!W_ERROR_IS_OK(result)) {
339 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
340 : win_errstr(result)));
341 0 : goto done;
342 : }
343 :
344 504 : status = dcerpc_winreg_set_dword(mem_ctx,
345 : h,
346 : &key_hnd,
347 : "ErrorControl",
348 : SVCCTL_SVC_ERROR_NORMAL,
349 : &result);
350 504 : if (!NT_STATUS_IS_OK(status)) {
351 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
352 : nt_errstr(status)));
353 0 : goto done;
354 : }
355 504 : if (!W_ERROR_IS_OK(result)) {
356 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
357 : win_errstr(result)));
358 0 : goto done;
359 : }
360 :
361 504 : status = dcerpc_winreg_set_sz(mem_ctx,
362 : h,
363 : &key_hnd,
364 : "ObjectName",
365 : "LocalSystem",
366 : &result);
367 504 : if (!NT_STATUS_IS_OK(status)) {
368 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
369 : nt_errstr(status)));
370 0 : goto done;
371 : }
372 504 : if (!W_ERROR_IS_OK(result)) {
373 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
374 : win_errstr(result)));
375 0 : goto done;
376 : }
377 :
378 : /*
379 : * Special considerations for internal services and the DisplayName
380 : * value.
381 : */
382 1260 : for (i = 0; builtin_svcs[i].servicename; i++) {
383 1260 : if (strequal(name, builtin_svcs[i].servicename)) {
384 504 : ipath = talloc_asprintf(mem_ctx,
385 : "%s/%s/%s",
386 : get_dyn_MODULESDIR(),
387 : SVCCTL_SCRIPT_DIR,
388 : builtin_svcs[i].daemon);
389 504 : description = talloc_strdup(mem_ctx, builtin_svcs[i].description);
390 504 : dname = talloc_strdup(mem_ctx, builtin_svcs[i].dispname);
391 504 : break;
392 : }
393 : }
394 :
395 : /* Default to an external service if we haven't found a match */
396 504 : if (builtin_svcs[i].servicename == NULL) {
397 0 : struct rcinit_file_information *init_info = NULL;
398 0 : char *dispname = NULL;
399 :
400 0 : ipath = talloc_asprintf(mem_ctx,
401 : "%s/%s/%s",
402 : get_dyn_MODULESDIR(),
403 : SVCCTL_SCRIPT_DIR,
404 : name);
405 :
406 : /* lookup common unix display names */
407 0 : dispname = svcctl_get_common_service_dispname(mem_ctx, name);
408 0 : dname = talloc_strdup(mem_ctx, dispname ? dispname : "");
409 :
410 : /* get info from init file itself */
411 0 : if (read_init_file(mem_ctx, name, &init_info)) {
412 0 : description = talloc_strdup(mem_ctx,
413 0 : init_info->description);
414 : } else {
415 0 : description = talloc_strdup(mem_ctx,
416 : "External Unix Service");
417 : }
418 : }
419 :
420 504 : if (ipath == NULL || dname == NULL || description == NULL) {
421 0 : goto done;
422 : }
423 :
424 504 : status = dcerpc_winreg_set_sz(mem_ctx,
425 : h,
426 : &key_hnd,
427 : "DisplayName",
428 : dname,
429 : &result);
430 504 : if (!NT_STATUS_IS_OK(status)) {
431 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
432 : nt_errstr(status)));
433 0 : goto done;
434 : }
435 504 : if (!W_ERROR_IS_OK(result)) {
436 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
437 : win_errstr(result)));
438 0 : goto done;
439 : }
440 :
441 504 : status = dcerpc_winreg_set_sz(mem_ctx,
442 : h,
443 : &key_hnd,
444 : "ImagePath",
445 : ipath,
446 : &result);
447 504 : if (!NT_STATUS_IS_OK(status)) {
448 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
449 : nt_errstr(status)));
450 0 : goto done;
451 : }
452 504 : if (!W_ERROR_IS_OK(result)) {
453 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
454 : win_errstr(result)));
455 0 : goto done;
456 : }
457 :
458 504 : status = dcerpc_winreg_set_sz(mem_ctx,
459 : h,
460 : &key_hnd,
461 : "Description",
462 : description,
463 : &result);
464 504 : if (!NT_STATUS_IS_OK(status)) {
465 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
466 : nt_errstr(status)));
467 0 : goto done;
468 : }
469 504 : if (!W_ERROR_IS_OK(result)) {
470 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
471 : win_errstr(result)));
472 0 : goto done;
473 : }
474 :
475 504 : sd = svcctl_gen_service_sd(mem_ctx);
476 504 : if (sd == NULL) {
477 0 : DEBUG(0, ("add_new_svc_name: Failed to create default "
478 : "sec_desc!\n"));
479 0 : goto done;
480 : }
481 :
482 504 : if (is_valid_policy_hnd(&key_hnd)) {
483 504 : dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result);
484 : }
485 504 : ZERO_STRUCT(key_hnd);
486 :
487 504 : ZERO_STRUCT(wkey);
488 504 : wkey.name = talloc_asprintf(mem_ctx, "%s\\%s\\Security", key, name);
489 504 : if (wkey.name == NULL) {
490 0 : result = WERR_NOT_ENOUGH_MEMORY;
491 0 : goto done;
492 : }
493 :
494 504 : ZERO_STRUCT(wkeyclass);
495 504 : wkeyclass.name = "";
496 :
497 504 : status = dcerpc_winreg_CreateKey(h,
498 : mem_ctx,
499 : hive_hnd,
500 : wkey,
501 : wkeyclass,
502 : 0,
503 : access_mask,
504 : NULL,
505 : &key_hnd,
506 : &action,
507 : &result);
508 504 : if (!NT_STATUS_IS_OK(status)) {
509 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
510 : wkey.name, nt_errstr(status)));
511 0 : goto done;
512 : }
513 504 : if (!W_ERROR_IS_OK(result)) {
514 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
515 : wkey.name, win_errstr(result)));
516 0 : goto done;
517 : }
518 :
519 504 : status = dcerpc_winreg_set_sd(mem_ctx,
520 : h,
521 : &key_hnd,
522 : "Security",
523 : sd,
524 : &result);
525 504 : if (!NT_STATUS_IS_OK(status)) {
526 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
527 : nt_errstr(status)));
528 0 : goto done;
529 : }
530 504 : if (!W_ERROR_IS_OK(result)) {
531 0 : DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
532 : win_errstr(result)));
533 0 : goto done;
534 : }
535 :
536 504 : ok = true;
537 504 : done:
538 504 : if (is_valid_policy_hnd(&key_hnd)) {
539 504 : dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result);
540 : }
541 :
542 504 : return ok;
543 : }
544 :
545 126 : bool svcctl_init_winreg(struct messaging_context *msg_ctx)
546 : {
547 126 : struct dcerpc_binding_handle *h = NULL;
548 126 : uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
549 0 : struct policy_handle hive_hnd, key_hnd;
550 126 : const char **service_list = lp_svcctl_list();
551 126 : const char **subkeys = NULL;
552 126 : uint32_t num_subkeys = 0;
553 126 : char *key = NULL;
554 0 : uint32_t i;
555 0 : NTSTATUS status;
556 126 : WERROR result = WERR_OK;
557 126 : bool ok = false;
558 0 : TALLOC_CTX *tmp_ctx;
559 :
560 126 : tmp_ctx = talloc_stackframe();
561 126 : if (tmp_ctx == NULL) {
562 0 : return false;
563 : }
564 :
565 126 : DEBUG(3, ("Initialise the svcctl registry keys if needed.\n"));
566 :
567 126 : ZERO_STRUCT(hive_hnd);
568 126 : ZERO_STRUCT(key_hnd);
569 :
570 126 : key = talloc_strdup(tmp_ctx, TOP_LEVEL_SERVICES_KEY);
571 126 : if (key == NULL) {
572 0 : goto done;
573 : }
574 :
575 126 : status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
576 : get_session_info_system(),
577 : msg_ctx,
578 : &h,
579 : key,
580 : false,
581 : access_mask,
582 : &hive_hnd,
583 : &key_hnd,
584 : &result);
585 126 : if (!NT_STATUS_IS_OK(status)) {
586 0 : DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n",
587 : key, nt_errstr(status)));
588 0 : goto done;
589 : }
590 126 : if (!W_ERROR_IS_OK(result)) {
591 0 : DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n",
592 : key, win_errstr(result)));
593 0 : goto done;
594 : }
595 :
596 : /* get all subkeys */
597 126 : status = dcerpc_winreg_enum_keys(tmp_ctx,
598 : h,
599 : &key_hnd,
600 : &num_subkeys,
601 : &subkeys,
602 : &result);
603 126 : if (!NT_STATUS_IS_OK(status)) {
604 0 : DEBUG(0, ("svcctl_init_winreg: Could not enum keys at %s - %s\n",
605 : key, nt_errstr(status)));
606 0 : goto done;
607 : }
608 126 : if (!W_ERROR_IS_OK(result)) {
609 0 : DEBUG(0, ("svcctl_init_winreg: Could not enum keys at %s - %s\n",
610 : key, win_errstr(result)));
611 0 : goto done;
612 : }
613 :
614 630 : for (i = 0; builtin_svcs[i].servicename != NULL; i++) {
615 : uint32_t j;
616 504 : bool skip = false;
617 :
618 3456 : for (j = 0; j < num_subkeys; j++) {
619 2952 : if (strequal(subkeys[i], builtin_svcs[i].servicename)) {
620 0 : skip = true;
621 : }
622 : }
623 :
624 504 : if (skip) {
625 0 : continue;
626 : }
627 :
628 504 : ok = svcctl_add_service(tmp_ctx,
629 : h,
630 : &hive_hnd,
631 : key,
632 : access_mask,
633 : builtin_svcs[i].servicename);
634 504 : if (!ok) {
635 0 : goto done;
636 : }
637 : }
638 :
639 126 : for (i = 0; service_list && service_list[i]; i++) {
640 : uint32_t j;
641 0 : bool skip = false;
642 :
643 0 : for (j = 0; j < num_subkeys; j++) {
644 0 : if (strequal(subkeys[i], service_list[i])) {
645 0 : skip = true;
646 : }
647 : }
648 :
649 0 : if (skip) {
650 0 : continue;
651 : }
652 :
653 0 : ok = svcctl_add_service(tmp_ctx,
654 : h,
655 : &hive_hnd,
656 : key,
657 : access_mask,
658 0 : service_list[i]);
659 0 : if (is_valid_policy_hnd(&key_hnd)) {
660 0 : dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
661 : }
662 0 : ZERO_STRUCT(key_hnd);
663 :
664 0 : if (!ok) {
665 0 : goto done;
666 : }
667 : }
668 :
669 126 : done:
670 126 : if (is_valid_policy_hnd(&key_hnd)) {
671 126 : dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
672 : }
673 :
674 126 : talloc_free(tmp_ctx);
675 126 : return ok;
676 : }
677 :
678 : /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */
|