r10206: * QueryServiceConfig2() now works, but only for info level
[Samba.git] / source / services / services_db.c
blobf5d404cc55e8c048ce2de720d7bc3a1658e14869
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 2 of the License, or
12 * (at your option) any later version.
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 /********************************************************************
27 ********************************************************************/
29 static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
31 SEC_ACE ace[4];
32 SEC_ACCESS mask;
33 size_t i = 0;
34 SEC_DESC *sd;
35 SEC_ACL *acl;
36 size_t sd_size;
38 /* basic access for Everyone */
40 init_sec_access(&mask, SERVICE_READ_ACCESS );
41 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
43 init_sec_access(&mask,SERVICE_EXECUTE_ACCESS );
44 init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
46 init_sec_access(&mask,SERVICE_ALL_ACCESS );
47 init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
48 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
50 /* create the security descriptor */
52 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
53 return NULL;
55 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
56 return NULL;
58 return sd;
61 /********************************************************************
62 This is where we do the dirty work of filling in things like the
63 Display name, Description, etc...
64 ********************************************************************/
66 static void fill_service_values( const char *name, REGVAL_CTR *values )
68 UNISTR2 data, dname, ipath, description;
69 uint32 dword;
70 pstring pstr;
72 /* These values are hardcoded in all QueryServiceConfig() replies.
73 I'm just storing them here for cosmetic purposes */
75 dword = SVCCTL_DEMAND_START;
76 regval_ctr_addvalue( values, "Start", REG_DWORD, (char*)&dword, sizeof(uint32));
78 dword = SVCCTL_WIN32_OWN_PROC;
79 regval_ctr_addvalue( values, "Type", REG_DWORD, (char*)&dword, sizeof(uint32));
81 dword = SVCCTL_SVC_ERROR_NORMAL;
82 regval_ctr_addvalue( values, "ErrorControl", REG_DWORD, (char*)&dword, sizeof(uint32));
84 /* everything runs as LocalSystem */
86 init_unistr2( &data, "LocalSystem", UNI_STR_TERMINATE );
87 regval_ctr_addvalue( values, "ObjectName", REG_SZ, (char*)data.buffer, data.uni_str_len*2);
89 /* special considerations for internal services and the DisplayName value */
91 if ( strequal(name, "Spooler") ) {
92 pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
93 init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
94 init_unistr2( &description, "Internal service for spooling files to print devices", UNI_STR_TERMINATE );
95 init_unistr2( &dname, "Print Spooler", UNI_STR_TERMINATE );
97 else if ( strequal(name, "NETLOGON") ) {
98 pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
99 init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
100 init_unistr2( &description, "File service providing access to policy and profile data", UNI_STR_TERMINATE );
101 init_unistr2( &dname, "Net Logon", UNI_STR_TERMINATE );
103 else if ( strequal(name, "RemoteRegistry") ) {
104 pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
105 init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
106 init_unistr2( &description, "Internal service providing remote access to the Samba registry", UNI_STR_TERMINATE );
107 init_unistr2( &dname, "Remote Registry Service", UNI_STR_TERMINATE );
109 else {
110 pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, name );
111 init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
112 init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE );
113 init_unistr2( &dname, name, UNI_STR_TERMINATE );
115 regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2);
116 regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2);
117 regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2);
119 return;
122 /********************************************************************
123 ********************************************************************/
125 static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys,
126 const char *name )
128 REGISTRY_KEY *key_service, *key_secdesc;
129 WERROR wresult;
130 pstring path;
131 REGVAL_CTR *values;
132 REGSUBKEY_CTR *svc_subkeys;
133 SEC_DESC *sd;
134 prs_struct ps;
136 /* add to the list and create the subkey path */
138 regsubkey_ctr_addkey( subkeys, name );
139 store_reg_keys( key_parent, subkeys );
141 /* open the new service key */
143 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
144 wresult = regkey_open_internal( &key_service, path, get_root_nt_token(),
145 REG_KEY_ALL );
146 if ( !W_ERROR_IS_OK(wresult) ) {
147 DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n",
148 path, dos_errstr(wresult)));
149 return;
152 /* add the 'Security' key */
154 if ( !(svc_subkeys = TALLOC_ZERO_P( key_service, REGSUBKEY_CTR )) ) {
155 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
156 return;
159 fetch_reg_keys( key_service, svc_subkeys );
160 regsubkey_ctr_addkey( svc_subkeys, "Security" );
161 store_reg_keys( key_service, svc_subkeys );
163 /* now for the service values */
165 if ( !(values = TALLOC_ZERO_P( key_service, REGVAL_CTR )) ) {
166 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
167 return;
170 fill_service_values( name, values );
171 store_reg_values( key_service, values );
173 /* cleanup the service key*/
175 TALLOC_FREE( key_service );
177 /* now add the security descriptor */
179 pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
180 wresult = regkey_open_internal( &key_secdesc, path, get_root_nt_token(),
181 REG_KEY_ALL );
182 if ( !W_ERROR_IS_OK(wresult) ) {
183 DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n",
184 path, dos_errstr(wresult)));
185 return;
188 if ( !(values = TALLOC_ZERO_P( key_secdesc, REGVAL_CTR )) ) {
189 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
190 return;
193 if ( !(sd = construct_service_sd(key_secdesc)) ) {
194 DEBUG(0,("add_new_svc_name: Failed to create default sec_desc!\n"));
195 TALLOC_FREE( key_secdesc );
196 return;
199 /* stream the printer security descriptor */
201 prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key_secdesc, MARSHALL);
203 if ( sec_io_desc("sec_desc", &sd, &ps, 0 ) ) {
204 uint32 offset = prs_offset( &ps );
205 regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset );
206 store_reg_values( key_secdesc, values );
209 /* finally cleanup the Security key */
211 prs_mem_free( &ps );
212 TALLOC_FREE( key_secdesc );
214 return;
217 /********************************************************************
218 ********************************************************************/
220 void svcctl_init_keys( void )
222 const char **service_list = lp_svcctl_list();
223 int i;
224 REGSUBKEY_CTR *subkeys;
225 REGISTRY_KEY *key = NULL;
226 WERROR wresult;
227 BOOL new_services = False;
229 /* bad mojo here if the lookup failed. Should not happen */
231 wresult = regkey_open_internal( &key, KEY_SERVICES, get_root_nt_token(),
232 REG_KEY_ALL );
234 if ( !W_ERROR_IS_OK(wresult) ) {
235 DEBUG(0,("init_services_keys: key lookup failed! (%s)\n",
236 dos_errstr(wresult)));
237 return;
240 /* lookup the available subkeys */
242 if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
243 DEBUG(0,("init_services_keys: talloc() failed!\n"));
244 return;
247 fetch_reg_keys( key, subkeys );
249 /* the builting services exist */
251 add_new_svc_name( key, subkeys, "Spooler" );
252 add_new_svc_name( key, subkeys, "NETLOGON" );
253 add_new_svc_name( key, subkeys, "RemoteRegistry" );
255 for ( i=0; service_list[i]; i++ ) {
257 /* only add new services */
258 if ( regsubkey_ctr_key_exists( subkeys, service_list[i] ) )
259 continue;
261 /* Add the new service key and initialize the appropriate values */
263 add_new_svc_name( key, subkeys, service_list[i] );
265 new_services = True;
268 TALLOC_FREE( key );
270 /* initialize the control hooks */
272 init_service_op_table();
274 return;
277 /********************************************************************
278 This is where we do the dirty work of filling in things like the
279 Display name, Description, etc...Always return a default secdesc
280 in case of any failure.
281 ********************************************************************/
283 SEC_DESC* svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token )
285 REGISTRY_KEY *key;
286 prs_struct ps;
287 REGVAL_CTR *values;
288 REGISTRY_VALUE *val;
289 SEC_DESC *sd = NULL;
290 SEC_DESC *ret_sd = NULL;
291 pstring path;
292 WERROR wresult;
294 /* now add the security descriptor */
296 pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
297 wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
298 if ( !W_ERROR_IS_OK(wresult) ) {
299 DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n",
300 path, dos_errstr(wresult)));
301 return NULL;
304 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
305 DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
306 TALLOC_FREE( key );
307 return NULL;
310 fetch_reg_values( key, values );
312 if ( !(val = regval_ctr_getvalue( values, "Security" )) ) {
313 DEBUG(6,("svcctl_get_secdesc: constructing default secdesc for service [%s]\n",
314 name));
315 TALLOC_FREE( key );
316 return construct_service_sd( ctx );
320 /* stream the printer security descriptor */
322 prs_init( &ps, 0, key, UNMARSHALL);
323 prs_give_memory( &ps, regval_data_p(val), regval_size(val), False );
325 if ( !sec_io_desc("sec_desc", &sd, &ps, 0 ) ) {
326 TALLOC_FREE( key );
327 return construct_service_sd( ctx );
330 ret_sd = dup_sec_desc( ctx, sd );
332 /* finally cleanup the Security key */
334 prs_mem_free( &ps );
335 TALLOC_FREE( key );
337 return ret_sd;
340 /********************************************************************
341 ********************************************************************/
343 char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token )
345 static fstring display_name;
346 REGISTRY_KEY *key;
347 REGVAL_CTR *values;
348 REGISTRY_VALUE *val;
349 pstring path;
350 WERROR wresult;
352 /* now add the security descriptor */
354 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
355 wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
356 if ( !W_ERROR_IS_OK(wresult) ) {
357 DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n",
358 path, dos_errstr(wresult)));
359 return NULL;
362 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
363 DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
364 TALLOC_FREE( key );
365 return NULL;
368 fetch_reg_values( key, values );
370 if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) )
371 fstrcpy( display_name, name );
372 else
373 rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 );
375 TALLOC_FREE( key );
377 return display_name;
380 /********************************************************************
381 ********************************************************************/
383 char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token )
385 static fstring description;
386 REGISTRY_KEY *key;
387 REGVAL_CTR *values;
388 REGISTRY_VALUE *val;
389 pstring path;
390 WERROR wresult;
392 /* now add the security descriptor */
394 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
395 wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
396 if ( !W_ERROR_IS_OK(wresult) ) {
397 DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n",
398 path, dos_errstr(wresult)));
399 return NULL;
402 if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
403 DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
404 TALLOC_FREE( key );
405 return NULL;
408 fetch_reg_values( key, values );
410 if ( !(val = regval_ctr_getvalue( values, "Description" )) )
411 fstrcpy( description, "Unix Service");
412 else
413 rpcstr_pull( description, regval_data_p(val), sizeof(description), regval_size(val), 0 );
415 TALLOC_FREE( key );
417 return description;
421 /********************************************************************
422 ********************************************************************/
424 REGVAL_CTR* svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token )
426 REGISTRY_KEY *key;
427 REGVAL_CTR *values;
428 pstring path;
429 WERROR wresult;
431 /* now add the security descriptor */
433 pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
434 wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
435 if ( !W_ERROR_IS_OK(wresult) ) {
436 DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n",
437 path, dos_errstr(wresult)));
438 return NULL;
441 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
442 DEBUG(0,("svcctl_fetch_regvalues: talloc() failed!\n"));
443 TALLOC_FREE( key );
444 return NULL;
447 fetch_reg_values( key, values );
449 TALLOC_FREE( key );
451 return values;