~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/services/services_db.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  Service Control API Implementation
 
4
 * 
 
5
 *  Copyright (C) Marcin Krzysztof Porwit         2005.
 
6
 *  Largely Rewritten by:
 
7
 *  Copyright (C) Gerald (Jerry) Carter           2005.
 
8
 *  
 
9
 *  This program is free software; you can redistribute it and/or modify
 
10
 *  it under the terms of the GNU General Public License as published by
 
11
 *  the Free Software Foundation; either version 3 of the License, or
 
12
 *  (at your option) any later version.
 
13
 *  
 
14
 *  This program is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 *  GNU General Public License for more details.
 
18
 *  
 
19
 *  You should have received a copy of the GNU General Public License
 
20
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
21
 */
 
22
 
 
23
#include "includes.h"
 
24
 
 
25
struct rcinit_file_information {
 
26
        char *description;
 
27
};
 
28
 
 
29
struct service_display_info {
 
30
        const char *servicename;
 
31
        const char *daemon;
 
32
        const char *dispname;
 
33
        const char *description;
 
34
};
 
35
 
 
36
struct service_display_info builtin_svcs[] = {
 
37
  { "Spooler",        "smbd",   "Print Spooler", "Internal service for spooling files to print devices" },
 
38
  { "NETLOGON",       "smbd",   "Net Logon", "File service providing access to policy and profile data (not remotely manageable)" },
 
39
  { "RemoteRegistry", "smbd",   "Remote Registry Service", "Internal service providing remote access to "
 
40
                                "the Samba registry" },
 
41
  { "WINS",           "nmbd",   "Windows Internet Name Service (WINS)", "Internal service providing a "
 
42
                                "NetBIOS point-to-point name server (not remotely manageable)" },
 
43
  { NULL, NULL, NULL, NULL }
 
44
};
 
45
 
 
46
struct service_display_info common_unix_svcs[] = {
 
47
  { "cups",          NULL, "Common Unix Printing System","Provides unified printing support for all operating systems" },
 
48
  { "postfix",       NULL, "Internet Mail Service",     "Provides support for sending and receiving electonic mail" },
 
49
  { "sendmail",      NULL, "Internet Mail Service",     "Provides support for sending and receiving electonic mail" },
 
50
  { "portmap",       NULL, "TCP Port to RPC PortMapper",NULL },
 
51
  { "xinetd",        NULL, "Internet Meta-Daemon",      NULL },
 
52
  { "inet",          NULL, "Internet Meta-Daemon",      NULL },
 
53
  { "xntpd",         NULL, "Network Time Service",      NULL },
 
54
  { "ntpd",          NULL, "Network Time Service",      NULL },
 
55
  { "lpd",           NULL, "BSD Print Spooler",         NULL },
 
56
  { "nfsserver",     NULL, "Network File Service",      NULL },
 
57
  { "cron",          NULL, "Scheduling Service",        NULL },
 
58
  { "at",            NULL, "Scheduling Service",        NULL },
 
59
  { "nscd",          NULL, "Name Service Cache Daemon", NULL },
 
60
  { "slapd",         NULL, "LDAP Directory Service",    NULL },
 
61
  { "ldap",          NULL, "LDAP DIrectory Service",    NULL },
 
62
  { "ypbind",        NULL, "NIS Directory Service",     NULL },
 
63
  { "courier-imap",  NULL, "IMAP4 Mail Service",        NULL },
 
64
  { "courier-pop3",  NULL, "POP3 Mail Service",         NULL },
 
65
  { "named",         NULL, "Domain Name Service",       NULL },
 
66
  { "bind",          NULL, "Domain Name Service",       NULL },
 
67
  { "httpd",         NULL, "HTTP Server",               NULL },
 
68
  { "apache",        NULL, "HTTP Server",               "Provides s highly scalable and flexible web server "
 
69
                                                        "capable of implementing various protocols incluing "
 
70
                                                        "but not limited to HTTP" },
 
71
  { "autofs",        NULL, "Automounter",               NULL },
 
72
  { "squid",         NULL, "Web Cache Proxy ",          NULL },
 
73
  { "perfcountd",    NULL, "Performance Monitoring Daemon", NULL },
 
74
  { "pgsql",         NULL, "PgSQL Database Server",     "Provides service for SQL database from Postgresql.org" },
 
75
  { "arpwatch",      NULL, "ARP Tables watcher",        "Provides service for monitoring ARP tables for changes" },
 
76
  { "dhcpd",         NULL, "DHCP Server",               "Provides service for dynamic host configuration and IP assignment" },
 
77
  { "nwserv",        NULL, "NetWare Server Emulator",   "Provides service for emulating Novell NetWare 3.12 server" },
 
78
  { "proftpd",       NULL, "Professional FTP Server",   "Provides high configurable service for FTP connection and "
 
79
                                                        "file transferring" },
 
80
  { "ssh2",          NULL, "SSH Secure Shell",          "Provides service for secure connection for remote administration" },
 
81
  { "sshd",          NULL, "SSH Secure Shell",          "Provides service for secure connection for remote administration" },
 
82
  { NULL, NULL, NULL, NULL }
 
83
};
 
84
 
 
85
 
 
86
/********************************************************************
 
87
********************************************************************/
 
88
 
 
89
static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
 
90
{
 
91
        SEC_ACE ace[4];
 
92
        size_t i = 0;
 
93
        SEC_DESC *sd = NULL;
 
94
        SEC_ACL *theacl = NULL;
 
95
        size_t sd_size;
 
96
 
 
97
        /* basic access for Everyone */
 
98
 
 
99
        init_sec_ace(&ace[i++], &global_sid_World,
 
100
                SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_READ_ACCESS, 0);
 
101
 
 
102
        init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users,
 
103
                        SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_EXECUTE_ACCESS, 0);
 
104
 
 
105
        init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators,
 
106
                SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
 
107
        init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
 
108
                SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
 
109
 
 
110
        /* create the security descriptor */
 
111
 
 
112
        if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
 
113
                return NULL;
 
114
 
 
115
        if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
 
116
                                  SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
 
117
                                  theacl, &sd_size)) )
 
118
                return NULL;
 
119
 
 
120
        return sd;
 
121
}
 
122
 
 
123
/********************************************************************
 
124
 This is where we do the dirty work of filling in things like the
 
125
 Display name, Description, etc...
 
126
********************************************************************/
 
127
 
 
128
static char *get_common_service_dispname( const char *servicename )
 
129
{
 
130
        int i;
 
131
 
 
132
        for ( i=0; common_unix_svcs[i].servicename; i++ ) {
 
133
                if (strequal(servicename, common_unix_svcs[i].servicename)) {
 
134
                        char *dispname;
 
135
                        if (asprintf(&dispname,
 
136
                                "%s (%s)",
 
137
                                common_unix_svcs[i].dispname,
 
138
                                common_unix_svcs[i].servicename) < 0) {
 
139
                                return NULL;
 
140
                        }
 
141
                        return dispname;
 
142
                }
 
143
        }
 
144
 
 
145
        return SMB_STRDUP(servicename );
 
146
}
 
147
 
 
148
/********************************************************************
 
149
********************************************************************/
 
150
 
 
151
static char *cleanup_string( const char *string )
 
152
{
 
153
        char *clean = NULL;
 
154
        char *begin, *end;
 
155
        TALLOC_CTX *ctx = talloc_tos();
 
156
 
 
157
        clean = talloc_strdup(ctx, string);
 
158
        if (!clean) {
 
159
                return NULL;
 
160
        }
 
161
        begin = clean;
 
162
 
 
163
        /* trim any beginning whilespace */
 
164
 
 
165
        while (isspace(*begin)) {
 
166
                begin++;
 
167
        }
 
168
 
 
169
        if (*begin == '\0') {
 
170
                return NULL;
 
171
        }
 
172
 
 
173
        /* trim any trailing whitespace or carriage returns.
 
174
           Start at the end and move backwards */
 
175
 
 
176
        end = begin + strlen(begin) - 1;
 
177
 
 
178
        while ( isspace(*end) || *end=='\n' || *end=='\r' ) {
 
179
                *end = '\0';
 
180
                end--;
 
181
        }
 
182
 
 
183
        return begin;
 
184
}
 
185
 
 
186
/********************************************************************
 
187
********************************************************************/
 
188
 
 
189
static bool read_init_file( const char *servicename, struct rcinit_file_information **service_info )
 
190
{
 
191
        struct rcinit_file_information *info = NULL;
 
192
        char *filepath = NULL;
 
193
        char str[1024];
 
194
        XFILE *f = NULL;
 
195
        char *p = NULL;
 
196
 
 
197
        if ( !(info = TALLOC_ZERO_P( NULL, struct rcinit_file_information ) ) )
 
198
                return False;
 
199
 
 
200
        /* attempt the file open */
 
201
 
 
202
        filepath = talloc_asprintf(info, "%s/%s/%s", get_dyn_MODULESDIR(),
 
203
                                SVCCTL_SCRIPT_DIR, servicename);
 
204
        if (!filepath) {
 
205
                TALLOC_FREE(info);
 
206
                return false;
 
207
        }
 
208
        if (!(f = x_fopen( filepath, O_RDONLY, 0 ))) {
 
209
                DEBUG(0,("read_init_file: failed to open [%s]\n", filepath));
 
210
                TALLOC_FREE(info);
 
211
                return false;
 
212
        }
 
213
 
 
214
        while ( (x_fgets( str, sizeof(str)-1, f )) != NULL ) {
 
215
                /* ignore everything that is not a full line
 
216
                   comment starting with a '#' */
 
217
 
 
218
                if ( str[0] != '#' )
 
219
                        continue;
 
220
 
 
221
                /* Look for a line like '^#.*Description:' */
 
222
 
 
223
                if ( (p = strstr( str, "Description:" )) != NULL ) {
 
224
                        char *desc;
 
225
 
 
226
                        p += strlen( "Description:" ) + 1;
 
227
                        if ( !p )
 
228
                                break;
 
229
 
 
230
                        if ( (desc = cleanup_string(p)) != NULL )
 
231
                                info->description = talloc_strdup( info, desc );
 
232
                }
 
233
        }
 
234
 
 
235
        x_fclose( f );
 
236
 
 
237
        if ( !info->description )
 
238
                info->description = talloc_strdup( info, "External Unix Service" );
 
239
 
 
240
        *service_info = info;
 
241
        TALLOC_FREE(filepath);
 
242
 
 
243
        return True;
 
244
}
 
245
 
 
246
/********************************************************************
 
247
 This is where we do the dirty work of filling in things like the
 
248
 Display name, Description, etc...
 
249
********************************************************************/
 
250
 
 
251
static void fill_service_values( const char *name, REGVAL_CTR *values )
 
252
{
 
253
        UNISTR2 data, dname, ipath, description;
 
254
        uint32 dword;
 
255
        int i;
 
256
 
 
257
        /* These values are hardcoded in all QueryServiceConfig() replies.
 
258
           I'm just storing them here for cosmetic purposes */
 
259
 
 
260
        dword = SVCCTL_AUTO_START;
 
261
        regval_ctr_addvalue( values, "Start", REG_DWORD, (char*)&dword, sizeof(uint32));
 
262
 
 
263
        dword = SERVICE_TYPE_WIN32_OWN_PROCESS;
 
264
        regval_ctr_addvalue( values, "Type", REG_DWORD, (char*)&dword, sizeof(uint32));
 
265
 
 
266
        dword = SVCCTL_SVC_ERROR_NORMAL;
 
267
        regval_ctr_addvalue( values, "ErrorControl", REG_DWORD, (char*)&dword, sizeof(uint32));
 
268
 
 
269
        /* everything runs as LocalSystem */
 
270
 
 
271
        init_unistr2( &data, "LocalSystem", UNI_STR_TERMINATE );
 
272
        regval_ctr_addvalue( values, "ObjectName", REG_SZ, (char*)data.buffer, data.uni_str_len*2);
 
273
 
 
274
        /* special considerations for internal services and the DisplayName value */
 
275
 
 
276
        for ( i=0; builtin_svcs[i].servicename; i++ ) {
 
277
                if ( strequal( name, builtin_svcs[i].servicename ) ) {
 
278
                        char *pstr = NULL;
 
279
                        if (asprintf(&pstr, "%s/%s/%s",
 
280
                                        get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR,
 
281
                                        builtin_svcs[i].daemon) > 0) {
 
282
                                init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
 
283
                                SAFE_FREE(pstr);
 
284
                        } else {
 
285
                                init_unistr2( &ipath, "", UNI_STR_TERMINATE );
 
286
                        }
 
287
                        init_unistr2( &description, builtin_svcs[i].description, UNI_STR_TERMINATE );
 
288
                        init_unistr2( &dname, builtin_svcs[i].dispname, UNI_STR_TERMINATE );
 
289
                        break;
 
290
                }
 
291
        }
 
292
 
 
293
        /* default to an external service if we haven't found a match */
 
294
 
 
295
        if ( builtin_svcs[i].servicename == NULL ) {
 
296
                char *pstr = NULL;
 
297
                char *dispname = NULL;
 
298
                struct rcinit_file_information *init_info = NULL;
 
299
 
 
300
                if (asprintf(&pstr, "%s/%s/%s",get_dyn_MODULESDIR(),
 
301
                                        SVCCTL_SCRIPT_DIR, name) > 0) {
 
302
                        init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
 
303
                        SAFE_FREE(pstr);
 
304
                } else {
 
305
                        init_unistr2( &ipath, "", UNI_STR_TERMINATE );
 
306
                }
 
307
 
 
308
                /* lookup common unix display names */
 
309
                dispname = get_common_service_dispname(name);
 
310
                init_unistr2( &dname, dispname ? dispname : "", UNI_STR_TERMINATE );
 
311
                SAFE_FREE(dispname);
 
312
 
 
313
                /* get info from init file itself */
 
314
                if ( read_init_file( name, &init_info ) ) {
 
315
                        init_unistr2( &description, init_info->description, UNI_STR_TERMINATE );
 
316
                        TALLOC_FREE( init_info );
 
317
                }
 
318
                else {
 
319
                        init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE );
 
320
                }
 
321
        }
 
322
 
 
323
        /* add the new values */
 
324
 
 
325
        regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2);
 
326
        regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2);
 
327
        regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2);
 
328
 
 
329
        return;
 
330
}
 
331
 
 
332
/********************************************************************
 
333
********************************************************************/
 
334
 
 
335
static void add_new_svc_name( REGISTRY_KEY *key_parent, struct regsubkey_ctr *subkeys,
 
336
                              const char *name )
 
337
{
 
338
        REGISTRY_KEY *key_service = NULL, *key_secdesc = NULL;
 
339
        WERROR wresult;
 
340
        char *path = NULL;
 
341
        REGVAL_CTR *values = NULL;
 
342
        struct regsubkey_ctr *svc_subkeys = NULL;
 
343
        SEC_DESC *sd = NULL;
 
344
        DATA_BLOB sd_blob;
 
345
        NTSTATUS status;
 
346
 
 
347
        /* add to the list and create the subkey path */
 
348
 
 
349
        regsubkey_ctr_addkey( subkeys, name );
 
350
        store_reg_keys( key_parent, subkeys );
 
351
 
 
352
        /* open the new service key */
 
353
 
 
354
        if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) {
 
355
                return;
 
356
        }
 
357
        wresult = regkey_open_internal( NULL, &key_service, path,
 
358
                                        get_root_nt_token(), REG_KEY_ALL );
 
359
        if ( !W_ERROR_IS_OK(wresult) ) {
 
360
                DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n",
 
361
                        path, win_errstr(wresult)));
 
362
                SAFE_FREE(path);
 
363
                return;
 
364
        }
 
365
        SAFE_FREE(path);
 
366
 
 
367
        /* add the 'Security' key */
 
368
 
 
369
        wresult = regsubkey_ctr_init(key_service, &svc_subkeys);
 
370
        if (!W_ERROR_IS_OK(wresult)) {
 
371
                DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
 
372
                TALLOC_FREE( key_service );
 
373
                return;
 
374
        }
 
375
 
 
376
        fetch_reg_keys( key_service, svc_subkeys );
 
377
        regsubkey_ctr_addkey( svc_subkeys, "Security" );
 
378
        store_reg_keys( key_service, svc_subkeys );
 
379
 
 
380
        /* now for the service values */
 
381
 
 
382
        if ( !(values = TALLOC_ZERO_P( key_service, REGVAL_CTR )) ) {
 
383
                DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
 
384
                TALLOC_FREE( key_service );
 
385
                return;
 
386
        }
 
387
 
 
388
        fill_service_values( name, values );
 
389
        store_reg_values( key_service, values );
 
390
 
 
391
        /* cleanup the service key*/
 
392
 
 
393
        TALLOC_FREE( key_service );
 
394
 
 
395
        /* now add the security descriptor */
 
396
 
 
397
        if (asprintf(&path, "%s\\%s\\%s", KEY_SERVICES, name, "Security") < 0) {
 
398
                return;
 
399
        }
 
400
        wresult = regkey_open_internal( NULL, &key_secdesc, path,
 
401
                                        get_root_nt_token(), REG_KEY_ALL );
 
402
        if ( !W_ERROR_IS_OK(wresult) ) {
 
403
                DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n",
 
404
                        path, win_errstr(wresult)));
 
405
                TALLOC_FREE( key_secdesc );
 
406
                SAFE_FREE(path);
 
407
                return;
 
408
        }
 
409
        SAFE_FREE(path);
 
410
 
 
411
        if ( !(values = TALLOC_ZERO_P( key_secdesc, REGVAL_CTR )) ) {
 
412
                DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
 
413
                TALLOC_FREE( key_secdesc );
 
414
                return;
 
415
        }
 
416
 
 
417
        if ( !(sd = construct_service_sd(key_secdesc)) ) {
 
418
                DEBUG(0,("add_new_svc_name: Failed to create default sec_desc!\n"));
 
419
                TALLOC_FREE( key_secdesc );
 
420
                return;
 
421
        }
 
422
 
 
423
        status = marshall_sec_desc(key_secdesc, sd, &sd_blob.data,
 
424
                                   &sd_blob.length);
 
425
        if (!NT_STATUS_IS_OK(status)) {
 
426
                DEBUG(0, ("marshall_sec_desc failed: %s\n",
 
427
                          nt_errstr(status)));
 
428
                TALLOC_FREE(key_secdesc);
 
429
                return;
 
430
        }
 
431
 
 
432
        regval_ctr_addvalue(values, "Security", REG_BINARY,
 
433
                            (const char *)sd_blob.data, sd_blob.length);
 
434
        store_reg_values( key_secdesc, values );
 
435
 
 
436
        TALLOC_FREE( key_secdesc );
 
437
 
 
438
        return;
 
439
}
 
440
 
 
441
/********************************************************************
 
442
********************************************************************/
 
443
 
 
444
void svcctl_init_keys( void )
 
445
{
 
446
        const char **service_list = lp_svcctl_list();
 
447
        int i;
 
448
        struct regsubkey_ctr *subkeys = NULL;
 
449
        REGISTRY_KEY *key = NULL;
 
450
        WERROR wresult;
 
451
 
 
452
        /* bad mojo here if the lookup failed.  Should not happen */
 
453
 
 
454
        wresult = regkey_open_internal( NULL, &key, KEY_SERVICES,
 
455
                                        get_root_nt_token(), REG_KEY_ALL );
 
456
 
 
457
        if ( !W_ERROR_IS_OK(wresult) ) {
 
458
                DEBUG(0,("svcctl_init_keys: key lookup failed! (%s)\n",
 
459
                        win_errstr(wresult)));
 
460
                return;
 
461
        }
 
462
 
 
463
        /* lookup the available subkeys */
 
464
 
 
465
        wresult = regsubkey_ctr_init(key, &subkeys);
 
466
        if (!W_ERROR_IS_OK(wresult)) {
 
467
                DEBUG(0,("svcctl_init_keys: talloc() failed!\n"));
 
468
                TALLOC_FREE( key );
 
469
                return;
 
470
        }
 
471
 
 
472
        fetch_reg_keys( key, subkeys );
 
473
 
 
474
        /* the builtin services exist */
 
475
 
 
476
        for ( i=0; builtin_svcs[i].servicename; i++ )
 
477
                add_new_svc_name( key, subkeys, builtin_svcs[i].servicename );
 
478
 
 
479
        for ( i=0; service_list && service_list[i]; i++ ) {
 
480
 
 
481
                /* only add new services */
 
482
                if ( regsubkey_ctr_key_exists( subkeys, service_list[i] ) )
 
483
                        continue;
 
484
 
 
485
                /* Add the new service key and initialize the appropriate values */
 
486
 
 
487
                add_new_svc_name( key, subkeys, service_list[i] );
 
488
        }
 
489
 
 
490
        TALLOC_FREE( key );
 
491
 
 
492
        /* initialize the control hooks */
 
493
 
 
494
        init_service_op_table();
 
495
 
 
496
        return;
 
497
}
 
498
 
 
499
/********************************************************************
 
500
 This is where we do the dirty work of filling in things like the
 
501
 Display name, Description, etc...Always return a default secdesc
 
502
 in case of any failure.
 
503
********************************************************************/
 
504
 
 
505
SEC_DESC *svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token )
 
506
{
 
507
        REGISTRY_KEY *key = NULL;
 
508
        REGVAL_CTR *values = NULL;
 
509
        REGISTRY_VALUE *val = NULL;
 
510
        SEC_DESC *ret_sd = NULL;
 
511
        char *path= NULL;
 
512
        WERROR wresult;
 
513
        NTSTATUS status;
 
514
 
 
515
        /* now add the security descriptor */
 
516
 
 
517
        if (asprintf(&path, "%s\\%s\\%s", KEY_SERVICES, name, "Security") < 0) {
 
518
                return NULL;
 
519
        }
 
520
        wresult = regkey_open_internal( NULL, &key, path, token,
 
521
                                        REG_KEY_ALL );
 
522
        if ( !W_ERROR_IS_OK(wresult) ) {
 
523
                DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n",
 
524
                        path, win_errstr(wresult)));
 
525
                goto done;
 
526
        }
 
527
 
 
528
        if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
 
529
                DEBUG(0,("svcctl_get_secdesc: talloc() failed!\n"));
 
530
                goto done;
 
531
        }
 
532
 
 
533
        if (fetch_reg_values( key, values ) == -1) {
 
534
                DEBUG(0, ("Error getting registry values\n"));
 
535
                goto done;
 
536
        }
 
537
 
 
538
        if ( !(val = regval_ctr_getvalue( values, "Security" )) ) {
 
539
                goto fallback_to_default_sd;
 
540
        }
 
541
 
 
542
        /* stream the service security descriptor */
 
543
 
 
544
        status = unmarshall_sec_desc(ctx, regval_data_p(val),
 
545
                                     regval_size(val), &ret_sd);
 
546
 
 
547
        if (NT_STATUS_IS_OK(status)) {
 
548
                goto done;
 
549
        }
 
550
 
 
551
fallback_to_default_sd:
 
552
        DEBUG(6, ("svcctl_get_secdesc: constructing default secdesc for "
 
553
                  "service [%s]\n", name));
 
554
        ret_sd = construct_service_sd(ctx);
 
555
 
 
556
done:
 
557
        SAFE_FREE(path);
 
558
        TALLOC_FREE(key);
 
559
        return ret_sd;
 
560
}
 
561
 
 
562
/********************************************************************
 
563
 Wrapper to make storing a Service sd easier
 
564
********************************************************************/
 
565
 
 
566
bool svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc, NT_USER_TOKEN *token )
 
567
{
 
568
        REGISTRY_KEY *key = NULL;
 
569
        WERROR wresult;
 
570
        char *path = NULL;
 
571
        REGVAL_CTR *values = NULL;
 
572
        DATA_BLOB blob;
 
573
        NTSTATUS status;
 
574
        bool ret = False;
 
575
 
 
576
        /* now add the security descriptor */
 
577
 
 
578
        if (asprintf(&path, "%s\\%s\\%s", KEY_SERVICES, name, "Security") < 0) {
 
579
                return false;
 
580
        }
 
581
        wresult = regkey_open_internal( NULL, &key, path, token,
 
582
                                        REG_KEY_ALL );
 
583
        if ( !W_ERROR_IS_OK(wresult) ) {
 
584
                DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n",
 
585
                        path, win_errstr(wresult)));
 
586
                SAFE_FREE(path);
 
587
                return False;
 
588
        }
 
589
        SAFE_FREE(path);
 
590
 
 
591
        if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
 
592
                DEBUG(0,("svcctl_set_secdesc: talloc() failed!\n"));
 
593
                TALLOC_FREE( key );
 
594
                return False;
 
595
        }
 
596
 
 
597
        /* stream the printer security descriptor */
 
598
 
 
599
        status = marshall_sec_desc(ctx, sec_desc, &blob.data, &blob.length);
 
600
        if (!NT_STATUS_IS_OK(status)) {
 
601
                DEBUG(0,("svcctl_set_secdesc: ndr_push_struct_blob() failed!\n"));
 
602
                TALLOC_FREE( key );
 
603
                return False;
 
604
        }
 
605
 
 
606
        regval_ctr_addvalue( values, "Security", REG_BINARY, (const char *)blob.data, blob.length);
 
607
        ret = store_reg_values( key, values );
 
608
 
 
609
        /* cleanup */
 
610
 
 
611
        TALLOC_FREE( key);
 
612
 
 
613
        return ret;
 
614
}
 
615
 
 
616
/********************************************************************
 
617
********************************************************************/
 
618
 
 
619
const char *svcctl_lookup_dispname(TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token )
 
620
{
 
621
        char *display_name = NULL;
 
622
        REGISTRY_KEY *key = NULL;
 
623
        REGVAL_CTR *values = NULL;
 
624
        REGISTRY_VALUE *val = NULL;
 
625
        char *path = NULL;
 
626
        WERROR wresult;
 
627
 
 
628
        /* now add the security descriptor */
 
629
 
 
630
        if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) {
 
631
                return NULL;
 
632
        }
 
633
        wresult = regkey_open_internal( NULL, &key, path, token,
 
634
                                        REG_KEY_READ );
 
635
        if ( !W_ERROR_IS_OK(wresult) ) {
 
636
                DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", 
 
637
                        path, win_errstr(wresult)));
 
638
                SAFE_FREE(path);
 
639
                goto fail;
 
640
        }
 
641
        SAFE_FREE(path);
 
642
 
 
643
        if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
 
644
                DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
 
645
                TALLOC_FREE( key );
 
646
                goto fail;
 
647
        }
 
648
 
 
649
        fetch_reg_values( key, values );
 
650
 
 
651
        if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) )
 
652
                goto fail;
 
653
 
 
654
        rpcstr_pull_talloc(ctx, &display_name, regval_data_p(val), regval_size(val), 0 );
 
655
 
 
656
        TALLOC_FREE( key );
 
657
 
 
658
        return display_name;
 
659
 
 
660
fail:
 
661
        /* default to returning the service name */
 
662
        TALLOC_FREE( key );
 
663
        return talloc_strdup(ctx, name);
 
664
}
 
665
 
 
666
/********************************************************************
 
667
********************************************************************/
 
668
 
 
669
const char *svcctl_lookup_description(TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token )
 
670
{
 
671
        char *description = NULL;
 
672
        REGISTRY_KEY *key = NULL;
 
673
        REGVAL_CTR *values = NULL;
 
674
        REGISTRY_VALUE *val = NULL;
 
675
        char *path = NULL;
 
676
        WERROR wresult;
 
677
 
 
678
        /* now add the security descriptor */
 
679
 
 
680
        if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) {
 
681
                return NULL;
 
682
        }
 
683
        wresult = regkey_open_internal( NULL, &key, path, token,
 
684
                                        REG_KEY_READ );
 
685
        if ( !W_ERROR_IS_OK(wresult) ) {
 
686
                DEBUG(0,("svcctl_lookup_description: key lookup failed! [%s] (%s)\n", 
 
687
                        path, win_errstr(wresult)));
 
688
                SAFE_FREE(path);
 
689
                return NULL;
 
690
        }
 
691
        SAFE_FREE(path);
 
692
 
 
693
        if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
 
694
                DEBUG(0,("svcctl_lookup_description: talloc() failed!\n"));
 
695
                TALLOC_FREE( key );
 
696
                return NULL;
 
697
        }
 
698
 
 
699
        fetch_reg_values( key, values );
 
700
 
 
701
        if ( !(val = regval_ctr_getvalue( values, "Description" )) ) {
 
702
                TALLOC_FREE( key );
 
703
                return "Unix Service";
 
704
        }
 
705
        rpcstr_pull_talloc(ctx, &description, regval_data_p(val), regval_size(val), 0 );
 
706
        TALLOC_FREE(key);
 
707
 
 
708
        return description;
 
709
}
 
710
 
 
711
 
 
712
/********************************************************************
 
713
********************************************************************/
 
714
 
 
715
REGVAL_CTR *svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token )
 
716
{
 
717
        REGISTRY_KEY *key = NULL;
 
718
        REGVAL_CTR *values = NULL;
 
719
        char *path = NULL;
 
720
        WERROR wresult;
 
721
 
 
722
        /* now add the security descriptor */
 
723
 
 
724
        if (asprintf(&path, "%s\\%s", KEY_SERVICES, name) < 0) {
 
725
                return NULL;
 
726
        }
 
727
        wresult = regkey_open_internal( NULL, &key, path, token,
 
728
                                        REG_KEY_READ );
 
729
        if ( !W_ERROR_IS_OK(wresult) ) {
 
730
                DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n",
 
731
                        path, win_errstr(wresult)));
 
732
                SAFE_FREE(path);
 
733
                return NULL;
 
734
        }
 
735
        SAFE_FREE(path);
 
736
 
 
737
        if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
 
738
                DEBUG(0,("svcctl_fetch_regvalues: talloc() failed!\n"));
 
739
                TALLOC_FREE( key );
 
740
                return NULL;
 
741
        }
 
742
        fetch_reg_values( key, values );
 
743
 
 
744
        TALLOC_FREE( key );
 
745
        return values;
 
746
}