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/>.
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"
33
#include "registry/reg_backend_db.h"
36
#define DBGC_CLASS DBGC_REGISTRY
38
#define TOP_LEVEL_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
40
struct rcinit_file_information {
44
struct service_display_info {
45
const char *servicename;
48
const char *description;
51
static struct service_display_info builtin_svcs[] = {
56
"Internal service for spooling files to print devices"
62
"File service providing access to policy and profile data (not"
63
"remotely manageable)"
68
"Remote Registry Service",
69
"Internal service providing remote access to the Samba registry"
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)
129
for (i = 0; common_unix_svcs[i].servicename; i++) {
130
if (strequal(servicename, common_unix_svcs[i].servicename)) {
132
dispname = talloc_asprintf(mem_ctx, "%s (%s)",
133
common_unix_svcs[i].dispname,
134
common_unix_svcs[i].servicename);
135
if (dispname == NULL) {
142
return talloc_strdup(mem_ctx, servicename);
145
/********************************************************************
146
********************************************************************/
147
static char *svcctl_cleanup_string(TALLOC_CTX *mem_ctx,
153
clean = talloc_strdup(mem_ctx, string);
159
/* trim any beginning whilespace */
160
while (isspace(*begin)) {
164
if (*begin == '\0') {
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') {
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;
193
info = talloc_zero(mem_ctx, struct rcinit_file_information);
198
/* attempt the file open */
200
filepath = talloc_asprintf(mem_ctx,
202
get_dyn_MODULESDIR(),
205
if (filepath == NULL) {
208
f = x_fopen( filepath, O_RDONLY, 0 );
210
DEBUG(0,("read_init_file: failed to open [%s]\n", filepath));
214
while ((x_fgets(str, sizeof(str) - 1, f)) != NULL) {
215
/* ignore everything that is not a full line
216
comment starting with a '#' */
222
/* Look for a line like '^#.*Description:' */
224
p = strstr(str, "Description:");
228
p += strlen( "Description:" ) + 1;
233
desc = svcctl_cleanup_string(mem_ctx, p);
235
info->description = talloc_strdup(info, desc);
242
if (info->description == NULL) {
243
info->description = talloc_strdup(info,
244
"External Unix Service");
245
if (info->description == NULL) {
250
*service_info = info;
255
static bool svcctl_add_service(TALLOC_CTX *mem_ctx,
256
struct dcerpc_binding_handle *h,
257
struct policy_handle *hive_hnd,
259
uint32_t access_mask,
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;
273
WERROR result = WERR_OK;
275
ZERO_STRUCT(key_hnd);
278
wkey.name = talloc_asprintf(mem_ctx, "%s\\%s", key, name);
279
if (wkey.name == NULL) {
283
ZERO_STRUCT(wkeyclass);
286
status = dcerpc_winreg_CreateKey(h,
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)));
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)));
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,
316
if (!NT_STATUS_IS_OK(status)) {
317
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
321
if (!W_ERROR_IS_OK(result)) {
322
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
323
win_errstr(result)));
327
status = dcerpc_winreg_set_dword(mem_ctx,
331
SERVICE_TYPE_WIN32_OWN_PROCESS,
333
if (!NT_STATUS_IS_OK(status)) {
334
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
338
if (!W_ERROR_IS_OK(result)) {
339
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
340
win_errstr(result)));
344
status = dcerpc_winreg_set_dword(mem_ctx,
348
SVCCTL_SVC_ERROR_NORMAL,
350
if (!NT_STATUS_IS_OK(status)) {
351
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
355
if (!W_ERROR_IS_OK(result)) {
356
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
357
win_errstr(result)));
361
status = dcerpc_winreg_set_sz(mem_ctx,
367
if (!NT_STATUS_IS_OK(status)) {
368
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
372
if (!W_ERROR_IS_OK(result)) {
373
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
374
win_errstr(result)));
379
* Special considerations for internal services and the DisplayName
382
for (i = 0; builtin_svcs[i].servicename; i++) {
383
if (strequal(name, builtin_svcs[i].servicename)) {
384
ipath = talloc_asprintf(mem_ctx,
386
get_dyn_MODULESDIR(),
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);
395
if (ipath == NULL || dname == NULL || description == NULL) {
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,
406
get_dyn_MODULESDIR(),
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);
419
description = talloc_strdup(mem_ctx,
420
"External Unix Service");
424
if (ipath == NULL || dname == NULL || description == NULL) {
428
status = dcerpc_winreg_set_sz(mem_ctx,
434
if (!NT_STATUS_IS_OK(status)) {
435
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
439
if (!W_ERROR_IS_OK(result)) {
440
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
441
win_errstr(result)));
445
status = dcerpc_winreg_set_sz(mem_ctx,
451
if (!NT_STATUS_IS_OK(status)) {
452
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
456
if (!W_ERROR_IS_OK(result)) {
457
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
458
win_errstr(result)));
462
status = dcerpc_winreg_set_sz(mem_ctx,
468
if (!NT_STATUS_IS_OK(status)) {
469
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
473
if (!W_ERROR_IS_OK(result)) {
474
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
475
win_errstr(result)));
479
sd = svcctl_gen_service_sd(mem_ctx);
481
DEBUG(0, ("add_new_svc_name: Failed to create default "
486
if (is_valid_policy_hnd(&key_hnd)) {
487
dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result);
489
ZERO_STRUCT(key_hnd);
492
wkey.name = talloc_asprintf(mem_ctx, "%s\\%s\\Security", key, name);
493
if (wkey.name == NULL) {
498
ZERO_STRUCT(wkeyclass);
501
status = dcerpc_winreg_CreateKey(h,
512
if (!NT_STATUS_IS_OK(status)) {
513
DEBUG(0, ("eventlog_init_winreg_keys: Could not create key %s: %s\n",
514
wkey.name, nt_errstr(status)));
517
if (!W_ERROR_IS_OK(result)) {
518
DEBUG(0, ("eventlog_init_winreg_keys: Could not create key %s: %s\n",
519
wkey.name, win_errstr(result)));
523
status = dcerpc_winreg_set_sd(mem_ctx,
529
if (!NT_STATUS_IS_OK(status)) {
530
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
534
if (!W_ERROR_IS_OK(result)) {
535
DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n",
536
win_errstr(result)));
542
if (is_valid_policy_hnd(&key_hnd)) {
543
dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result);
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;
560
WERROR result = WERR_OK;
564
tmp_ctx = talloc_stackframe();
565
if (tmp_ctx == NULL) {
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);
579
result = regdb_open();
580
if (!W_ERROR_IS_OK(result)) {
581
DEBUG(10, ("regdb_open failed: %s\n",
582
win_errstr(result)));
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)));
592
status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
593
get_session_info_system(),
602
if (!NT_STATUS_IS_OK(status)) {
603
DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n",
604
key, nt_errstr(status)));
607
if (!W_ERROR_IS_OK(result)) {
608
DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n",
609
key, win_errstr(result)));
613
/* get all subkeys */
614
status = dcerpc_winreg_enum_keys(tmp_ctx,
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)));
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)));
631
for (i = 0; builtin_svcs[i].servicename != NULL; i++) {
635
for (j = 0; j < num_subkeys; j++) {
636
if (strequal(subkeys[i], builtin_svcs[i].servicename)) {
645
ok = svcctl_add_service(tmp_ctx,
650
builtin_svcs[i].servicename);
656
for (i = 0; service_list && service_list[i]; i++) {
660
for (j = 0; j < num_subkeys; j++) {
661
if (strequal(subkeys[i], service_list[i])) {
670
ok = svcctl_add_service(tmp_ctx,
676
if (is_valid_policy_hnd(&key_hnd)) {
677
dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
679
ZERO_STRUCT(key_hnd);
687
if (is_valid_policy_hnd(&key_hnd)) {
688
dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
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)));
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)));
708
/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */