Revert "s3:smbd: set req->smb2req->compat_chain_fsp in file_fsp()"
[Samba/gebeck_regimport.git] / source3 / rpc_server / svcctl / srv_svcctl_reg.c
blobe695f0df8fdc2ab94cd6f426abbef810a5f81d7c
1 /*
2 * Unix SMB/CIFS implementation.
4 * SVCCTL RPC server keys initialization
6 * Copyright (c) 2005 Marcin Krzysztof Porwit
7 * Copyright (c) 2005 Gerald (Jerry) Carter
8 * Copyright (c) 2011 Andreas Schneider <asn@samba.org>
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.
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.
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/>.
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"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_REGISTRY
38 #define TOP_LEVEL_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
40 struct rcinit_file_information {
41 char *description;
44 struct service_display_info {
45 const char *servicename;
46 const char *daemon;
47 const char *dispname;
48 const char *description;
51 static struct service_display_info builtin_svcs[] = {
53 "Spooler",
54 "smbd",
55 "Print Spooler",
56 "Internal service for spooling files to print devices"
59 "NETLOGON",
60 "smbd",
61 "Net Logon",
62 "File service providing access to policy and profile data (not"
63 "remotely manageable)"
66 "RemoteRegistry",
67 "smbd",
68 "Remote Registry Service",
69 "Internal service providing remote access to the Samba registry"
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)"
78 { NULL, NULL, NULL, NULL }
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 incluing "
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 }
120 /********************************************************************
121 This is where we do the dirty work of filling in things like the
122 Display name, Description, etc...
123 ********************************************************************/
124 static char *svcctl_get_common_service_dispname(TALLOC_CTX *mem_ctx,
125 const char *servicename)
127 uint32_t i;
129 for (i = 0; common_unix_svcs[i].servicename; i++) {
130 if (strequal(servicename, common_unix_svcs[i].servicename)) {
131 char *dispname;
132 dispname = talloc_asprintf(mem_ctx, "%s (%s)",
133 common_unix_svcs[i].dispname,
134 common_unix_svcs[i].servicename);
135 if (dispname == NULL) {
136 return NULL;
138 return dispname;
142 return talloc_strdup(mem_ctx, servicename);
145 /********************************************************************
146 ********************************************************************/
147 static char *svcctl_cleanup_string(TALLOC_CTX *mem_ctx,
148 const char *string)
150 char *clean = NULL;
151 char *begin, *end;
153 clean = talloc_strdup(mem_ctx, string);
154 if (clean == NULL) {
155 return NULL;
157 begin = clean;
159 /* trim any beginning whilespace */
160 while (isspace(*begin)) {
161 begin++;
164 if (*begin == '\0') {
165 return NULL;
168 /* trim any trailing whitespace or carriage returns.
169 Start at the end and move backwards */
171 end = begin + strlen(begin) - 1;
173 while (isspace(*end) || *end=='\n' || *end=='\r') {
174 *end = '\0';
175 end--;
178 return begin;
181 /********************************************************************
182 ********************************************************************/
183 static bool read_init_file(TALLOC_CTX *mem_ctx,
184 const char *servicename,
185 struct rcinit_file_information **service_info)
187 struct rcinit_file_information *info = NULL;
188 char *filepath = NULL;
189 char str[1024];
190 XFILE *f = NULL;
191 char *p = NULL;
193 info = talloc_zero(mem_ctx, struct rcinit_file_information);
194 if (info == NULL) {
195 return false;
198 /* attempt the file open */
200 filepath = talloc_asprintf(mem_ctx,
201 "%s/%s/%s",
202 get_dyn_MODULESDIR(),
203 SVCCTL_SCRIPT_DIR,
204 servicename);
205 if (filepath == NULL) {
206 return false;
208 f = x_fopen( filepath, O_RDONLY, 0 );
209 if (f == NULL) {
210 DEBUG(0,("read_init_file: failed to open [%s]\n", filepath));
211 return false;
214 while ((x_fgets(str, sizeof(str) - 1, f)) != NULL) {
215 /* ignore everything that is not a full line
216 comment starting with a '#' */
218 if (str[0] != '#') {
219 continue;
222 /* Look for a line like '^#.*Description:' */
224 p = strstr(str, "Description:");
225 if (p != NULL) {
226 char *desc;
228 p += strlen( "Description:" ) + 1;
229 if (p == NULL) {
230 break;
233 desc = svcctl_cleanup_string(mem_ctx, p);
234 if (desc != NULL) {
235 info->description = talloc_strdup(info, desc);
240 x_fclose(f);
242 if (info->description == NULL) {
243 info->description = talloc_strdup(info,
244 "External Unix Service");
245 if (info->description == NULL) {
246 return false;
250 *service_info = info;
252 return true;
255 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)
262 enum winreg_CreateAction action = REG_ACTION_NONE;
263 struct security_descriptor *sd = NULL;
264 struct policy_handle key_hnd;
265 struct winreg_String wkey;
266 struct winreg_String wkeyclass;
267 char *description = NULL;
268 char *dname = NULL;
269 char *ipath = NULL;
270 bool ok = false;
271 uint32_t i;
272 NTSTATUS status;
273 WERROR result = WERR_OK;
275 ZERO_STRUCT(key_hnd);
277 ZERO_STRUCT(wkey);
278 wkey.name = talloc_asprintf(mem_ctx, "%s\\%s", key, name);
279 if (wkey.name == NULL) {
280 goto done;
283 ZERO_STRUCT(wkeyclass);
284 wkeyclass.name = "";
286 status = dcerpc_winreg_CreateKey(h,
287 mem_ctx,
288 hive_hnd,
289 wkey,
290 wkeyclass,
292 access_mask,
293 NULL,
294 &key_hnd,
295 &action,
296 &result);
297 if (!NT_STATUS_IS_OK(status)) {
298 DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
299 wkey.name, nt_errstr(status)));
300 goto done;
302 if (!W_ERROR_IS_OK(result)) {
303 DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
304 wkey.name, win_errstr(result)));
305 goto done;
308 /* These values are hardcoded in all QueryServiceConfig() replies.
309 I'm just storing them here for cosmetic purposes */
310 status = dcerpc_winreg_set_dword(mem_ctx,
312 &key_hnd,
313 "Start",
314 SVCCTL_AUTO_START,
315 &result);
316 if (!NT_STATUS_IS_OK(status)) {
317 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
318 nt_errstr(status)));
319 goto done;
321 if (!W_ERROR_IS_OK(result)) {
322 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
323 win_errstr(result)));
324 goto done;
327 status = dcerpc_winreg_set_dword(mem_ctx,
329 &key_hnd,
330 "Type",
331 SERVICE_TYPE_WIN32_OWN_PROCESS,
332 &result);
333 if (!NT_STATUS_IS_OK(status)) {
334 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
335 nt_errstr(status)));
336 goto done;
338 if (!W_ERROR_IS_OK(result)) {
339 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
340 win_errstr(result)));
341 goto done;
344 status = dcerpc_winreg_set_dword(mem_ctx,
346 &key_hnd,
347 "ErrorControl",
348 SVCCTL_SVC_ERROR_NORMAL,
349 &result);
350 if (!NT_STATUS_IS_OK(status)) {
351 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
352 nt_errstr(status)));
353 goto done;
355 if (!W_ERROR_IS_OK(result)) {
356 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
357 win_errstr(result)));
358 goto done;
361 status = dcerpc_winreg_set_sz(mem_ctx,
363 &key_hnd,
364 "ObjectName",
365 "LocalSystem",
366 &result);
367 if (!NT_STATUS_IS_OK(status)) {
368 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
369 nt_errstr(status)));
370 goto done;
372 if (!W_ERROR_IS_OK(result)) {
373 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
374 win_errstr(result)));
375 goto done;
379 * Special considerations for internal services and the DisplayName
380 * value.
382 for (i = 0; builtin_svcs[i].servicename; i++) {
383 if (strequal(name, builtin_svcs[i].servicename)) {
384 ipath = talloc_asprintf(mem_ctx,
385 "%s/%s/%s",
386 get_dyn_MODULESDIR(),
387 SVCCTL_SCRIPT_DIR,
388 builtin_svcs[i].daemon);
389 description = talloc_strdup(mem_ctx, builtin_svcs[i].description);
390 dname = talloc_strdup(mem_ctx, builtin_svcs[i].dispname);
391 break;
395 if (ipath == NULL || dname == NULL || description == NULL) {
396 goto done;
399 /* Default to an external service if we haven't found a match */
400 if (builtin_svcs[i].servicename == NULL) {
401 struct rcinit_file_information *init_info = NULL;
402 char *dispname = NULL;
404 ipath = talloc_asprintf(mem_ctx,
405 "%s/%s/%s",
406 get_dyn_MODULESDIR(),
407 SVCCTL_SCRIPT_DIR,
408 name);
410 /* lookup common unix display names */
411 dispname = svcctl_get_common_service_dispname(mem_ctx, name);
412 dname = talloc_strdup(mem_ctx, dispname ? dispname : "");
414 /* get info from init file itself */
415 if (read_init_file(mem_ctx, name, &init_info)) {
416 description = talloc_strdup(mem_ctx,
417 init_info->description);
418 } else {
419 description = talloc_strdup(mem_ctx,
420 "External Unix Service");
424 if (ipath == NULL || dname == NULL || description == NULL) {
425 goto done;
428 status = dcerpc_winreg_set_sz(mem_ctx,
430 &key_hnd,
431 "DisplayName",
432 dname,
433 &result);
434 if (!NT_STATUS_IS_OK(status)) {
435 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
436 nt_errstr(status)));
437 goto done;
439 if (!W_ERROR_IS_OK(result)) {
440 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
441 win_errstr(result)));
442 goto done;
445 status = dcerpc_winreg_set_sz(mem_ctx,
447 &key_hnd,
448 "ImagePath",
449 ipath,
450 &result);
451 if (!NT_STATUS_IS_OK(status)) {
452 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
453 nt_errstr(status)));
454 goto done;
456 if (!W_ERROR_IS_OK(result)) {
457 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
458 win_errstr(result)));
459 goto done;
462 status = dcerpc_winreg_set_sz(mem_ctx,
464 &key_hnd,
465 "Description",
466 description,
467 &result);
468 if (!NT_STATUS_IS_OK(status)) {
469 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
470 nt_errstr(status)));
471 goto done;
473 if (!W_ERROR_IS_OK(result)) {
474 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
475 win_errstr(result)));
476 goto done;
479 sd = svcctl_gen_service_sd(mem_ctx);
480 if (sd == NULL) {
481 DEBUG(0, ("add_new_svc_name: Failed to create default "
482 "sec_desc!\n"));
483 goto done;
486 if (is_valid_policy_hnd(&key_hnd)) {
487 dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result);
489 ZERO_STRUCT(key_hnd);
491 ZERO_STRUCT(wkey);
492 wkey.name = talloc_asprintf(mem_ctx, "%s\\%s\\Security", key, name);
493 if (wkey.name == NULL) {
494 result = WERR_NOMEM;
495 goto done;
498 ZERO_STRUCT(wkeyclass);
499 wkeyclass.name = "";
501 status = dcerpc_winreg_CreateKey(h,
502 mem_ctx,
503 hive_hnd,
504 wkey,
505 wkeyclass,
507 access_mask,
508 NULL,
509 &key_hnd,
510 &action,
511 &result);
512 if (!NT_STATUS_IS_OK(status)) {
513 DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
514 wkey.name, nt_errstr(status)));
515 goto done;
517 if (!W_ERROR_IS_OK(result)) {
518 DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n",
519 wkey.name, win_errstr(result)));
520 goto done;
523 status = dcerpc_winreg_set_sd(mem_ctx,
525 &key_hnd,
526 "Security",
528 &result);
529 if (!NT_STATUS_IS_OK(status)) {
530 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
531 nt_errstr(status)));
532 goto done;
534 if (!W_ERROR_IS_OK(result)) {
535 DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
536 win_errstr(result)));
537 goto done;
540 ok = true;
541 done:
542 if (is_valid_policy_hnd(&key_hnd)) {
543 dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result);
546 return ok;
549 bool svcctl_init_winreg(struct messaging_context *msg_ctx)
551 struct dcerpc_binding_handle *h = NULL;
552 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
553 struct policy_handle hive_hnd, key_hnd;
554 const char **service_list = lp_svcctl_list();
555 const char **subkeys = NULL;
556 uint32_t num_subkeys = 0;
557 char *key = NULL;
558 uint32_t i;
559 NTSTATUS status;
560 WERROR result = WERR_OK;
561 bool ok = false;
562 TALLOC_CTX *tmp_ctx;
564 tmp_ctx = talloc_stackframe();
565 if (tmp_ctx == NULL) {
566 return false;
569 DEBUG(3, ("Initialise the svcctl registry keys if needed.\n"));
571 ZERO_STRUCT(hive_hnd);
572 ZERO_STRUCT(key_hnd);
574 key = talloc_strdup(tmp_ctx, TOP_LEVEL_SERVICES_KEY);
575 if (key == NULL) {
576 goto done;
579 result = regdb_open();
580 if (!W_ERROR_IS_OK(result)) {
581 DEBUG(10, ("regdb_open failed: %s\n",
582 win_errstr(result)));
583 goto done;
585 result = regdb_transaction_start();
586 if (!W_ERROR_IS_OK(result)) {
587 DEBUG(10, ("regdb_transaction_start failed: %s\n",
588 win_errstr(result)));
589 goto done;
592 status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
593 get_session_info_system(),
594 msg_ctx,
596 key,
597 false,
598 access_mask,
599 &hive_hnd,
600 &key_hnd,
601 &result);
602 if (!NT_STATUS_IS_OK(status)) {
603 DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n",
604 key, nt_errstr(status)));
605 goto done;
607 if (!W_ERROR_IS_OK(result)) {
608 DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n",
609 key, win_errstr(result)));
610 goto done;
613 /* get all subkeys */
614 status = dcerpc_winreg_enum_keys(tmp_ctx,
616 &key_hnd,
617 &num_subkeys,
618 &subkeys,
619 &result);
620 if (!NT_STATUS_IS_OK(status)) {
621 DEBUG(0, ("svcctl_init_winreg: Could enum keys at %s - %s\n",
622 key, nt_errstr(status)));
623 goto done;
625 if (!W_ERROR_IS_OK(result)) {
626 DEBUG(0, ("svcctl_init_winreg: Could enum keys at %s - %s\n",
627 key, win_errstr(result)));
628 goto done;
631 for (i = 0; builtin_svcs[i].servicename != NULL; i++) {
632 uint32_t j;
633 bool skip = false;
635 for (j = 0; j < num_subkeys; j++) {
636 if (strequal(subkeys[i], builtin_svcs[i].servicename)) {
637 skip = true;
641 if (skip) {
642 continue;
645 ok = svcctl_add_service(tmp_ctx,
647 &hive_hnd,
648 key,
649 access_mask,
650 builtin_svcs[i].servicename);
651 if (!ok) {
652 goto done;
656 for (i = 0; service_list && service_list[i]; i++) {
657 uint32_t j;
658 bool skip = false;
660 for (j = 0; j < num_subkeys; j++) {
661 if (strequal(subkeys[i], service_list[i])) {
662 skip = true;
666 if (skip) {
667 continue;
670 ok = svcctl_add_service(tmp_ctx,
672 &hive_hnd,
673 key,
674 access_mask,
675 service_list[i]);
676 if (is_valid_policy_hnd(&key_hnd)) {
677 dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
679 ZERO_STRUCT(key_hnd);
681 if (!ok) {
682 goto done;
686 done:
687 if (is_valid_policy_hnd(&key_hnd)) {
688 dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
691 if (ok) {
692 result = regdb_transaction_commit();
693 if (!W_ERROR_IS_OK(result)) {
694 DEBUG(10, ("regdb_transaction_commit failed: %s\n",
695 win_errstr(result)));
697 } else {
698 result = regdb_transaction_cancel();
699 if (!W_ERROR_IS_OK(result)) {
700 DEBUG(10, ("regdb_transaction_cancel failed: %s\n",
701 win_errstr(result)));
704 regdb_close();
705 return ok;
708 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */