r22099: Revert parts of revision 22056 as proto_exists is not required by
[Samba.git] / source / registry / reg_frontend.c
blob2ec532dcdc5588b30a31e440d7b805a9831d746f
1 /*
2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Gerald Carter 2002-2005
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* Implementation of registry frontend view functions. */
23 #include "includes.h"
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
28 extern REGISTRY_OPS printing_ops;
29 extern REGISTRY_OPS eventlog_ops;
30 extern REGISTRY_OPS shares_reg_ops;
31 extern REGISTRY_OPS smbconf_reg_ops;
32 extern REGISTRY_OPS regdb_ops; /* these are the default */
34 /* array of REGISTRY_HOOK's which are read into a tree for easy access */
35 /* #define REG_TDB_ONLY 1 */
37 REGISTRY_HOOK reg_hooks[] = {
38 #ifndef REG_TDB_ONLY
39 { KEY_PRINTING, &printing_ops },
40 { KEY_PRINTING_2K, &printing_ops },
41 { KEY_PRINTING_PORTS, &printing_ops },
42 { KEY_SHARES, &shares_reg_ops },
43 { KEY_SMBCONF, &smbconf_reg_ops },
44 #endif
45 { NULL, NULL }
49 static struct generic_mapping reg_generic_map =
50 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
52 /********************************************************************
53 ********************************************************************/
55 static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
57 SEC_ACE ace[2];
58 SEC_ACCESS mask;
59 size_t i = 0;
60 SEC_DESC *sd;
61 SEC_ACL *acl;
62 size_t sd_size;
64 /* basic access for Everyone */
66 init_sec_access(&mask, REG_KEY_READ );
67 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
69 /* Full Access 'BUILTIN\Administrators' */
71 init_sec_access(&mask, REG_KEY_ALL );
72 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
75 /* create the security descriptor */
77 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
78 return NULL;
80 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
81 return NULL;
83 return sd;
87 /***********************************************************************
88 Open the registry database and initialize the REGISTRY_HOOK cache
89 ***********************************************************************/
91 BOOL init_registry( void )
93 int i;
96 if ( !regdb_init() ) {
97 DEBUG(0,("init_registry: failed to initialize the registry tdb!\n"));
98 return False;
101 /* build the cache tree of registry hooks */
103 reghook_cache_init();
105 for ( i=0; reg_hooks[i].keyname; i++ ) {
106 if ( !reghook_cache_add(&reg_hooks[i]) )
107 return False;
110 if ( DEBUGLEVEL >= 20 )
111 reghook_dump_cache(20);
113 /* add any keys for other services */
115 svcctl_init_keys();
116 eventlog_init_keys();
117 perfcount_init_keys();
119 /* close and let each smbd open up as necessary */
121 regdb_close();
123 return True;
126 /***********************************************************************
127 High level wrapper function for storing registry subkeys
128 ***********************************************************************/
130 BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
132 if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
133 return key->hook->ops->store_subkeys( key->name, subkeys );
135 return False;
139 /***********************************************************************
140 High level wrapper function for storing registry values
141 ***********************************************************************/
143 BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
145 if ( check_dynamic_reg_values( key ) )
146 return False;
148 if ( key->hook && key->hook->ops && key->hook->ops->store_values )
149 return key->hook->ops->store_values( key->name, val );
151 return False;
155 /***********************************************************************
156 High level wrapper function for enumerating registry subkeys
157 Initialize the TALLOC_CTX if necessary
158 ***********************************************************************/
160 int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
162 int result = -1;
164 if ( key->hook && key->hook->ops && key->hook->ops->fetch_subkeys )
165 result = key->hook->ops->fetch_subkeys( key->name, subkey_ctr );
167 return result;
170 /***********************************************************************
171 High level wrapper function for enumerating registry values
172 ***********************************************************************/
174 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
176 int result = -1;
178 if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
179 result = key->hook->ops->fetch_values( key->name, val );
181 /* if the backend lookup returned no data, try the dynamic overlay */
183 if ( result == 0 ) {
184 result = fetch_dynamic_reg_values( key, val );
186 return ( result != -1 ) ? result : 0;
189 return result;
192 /***********************************************************************
193 High level access check for passing the required access mask to the
194 underlying registry backend
195 ***********************************************************************/
197 BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
198 const struct nt_user_token *token )
200 SEC_DESC *sec_desc;
201 NTSTATUS status;
202 WERROR err;
203 TALLOC_CTX *mem_ctx;
205 /* use the default security check if the backend has not defined its
206 * own */
208 if (key->hook && key->hook->ops && key->hook->ops->reg_access_check) {
209 return key->hook->ops->reg_access_check( key->name, requested,
210 granted, token );
214 * The secdesc routines can't yet cope with a NULL talloc ctx sanely.
217 if (!(mem_ctx = talloc_init("regkey_access_check"))) {
218 return False;
221 err = regkey_get_secdesc(mem_ctx, key, &sec_desc);
223 if (!W_ERROR_IS_OK(err)) {
224 TALLOC_FREE(mem_ctx);
225 return False;
228 se_map_generic( &requested, &reg_generic_map );
230 if (!se_access_check(sec_desc, token, requested, granted, &status)) {
231 TALLOC_FREE(mem_ctx);
232 return False;
235 TALLOC_FREE(mem_ctx);
236 return NT_STATUS_IS_OK(status);
239 /***********************************************************************
240 ***********************************************************************/
242 static int regkey_destructor(REGISTRY_KEY *key)
244 return regdb_close();
247 WERROR regkey_open_onelevel( TALLOC_CTX *mem_ctx, struct registry_key *parent,
248 const char *name,
249 const struct nt_user_token *token,
250 uint32 access_desired,
251 struct registry_key **pregkey)
253 WERROR result = WERR_OK;
254 struct registry_key *regkey;
255 REGISTRY_KEY *key;
256 REGSUBKEY_CTR *subkeys = NULL;
258 DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
260 SMB_ASSERT(strchr(name, '\\') == NULL);
262 if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
263 !(regkey->token = dup_nt_token(regkey, token)) ||
264 !(regkey->key = TALLOC_ZERO_P(regkey, REGISTRY_KEY))) {
265 result = WERR_NOMEM;
266 goto done;
269 if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
270 goto done;
273 key = regkey->key;
274 talloc_set_destructor(key, regkey_destructor);
276 /* initialization */
278 key->type = REG_KEY_GENERIC;
280 if (name[0] == '\0') {
282 * Open a copy of the parent key
284 if (!parent) {
285 result = WERR_BADFILE;
286 goto done;
288 key->name = talloc_strdup(key, parent->key->name);
290 else {
292 * Normal subkey open
294 key->name = talloc_asprintf(key, "%s%s%s",
295 parent ? parent->key->name : "",
296 parent ? "\\": "",
297 name);
300 if (key->name == NULL) {
301 result = WERR_NOMEM;
302 goto done;
305 /* Tag this as a Performance Counter Key */
307 if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
308 key->type = REG_KEY_HKPD;
310 /* Look up the table of registry I/O operations */
312 if ( !(key->hook = reghook_cache_find( key->name )) ) {
313 DEBUG(0,("reg_open_onelevel: Failed to assigned a "
314 "REGISTRY_HOOK to [%s]\n", key->name ));
315 result = WERR_BADFILE;
316 goto done;
319 /* check if the path really exists; failed is indicated by -1 */
320 /* if the subkey count failed, bail out */
322 if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
323 result = WERR_NOMEM;
324 goto done;
327 if ( fetch_reg_keys( key, subkeys ) == -1 ) {
328 result = WERR_BADFILE;
329 goto done;
332 TALLOC_FREE( subkeys );
334 if ( !regkey_access_check( key, access_desired, &key->access_granted,
335 token ) ) {
336 result = WERR_ACCESS_DENIED;
337 goto done;
340 *pregkey = regkey;
341 result = WERR_OK;
343 done:
344 if ( !W_ERROR_IS_OK(result) ) {
345 TALLOC_FREE(regkey);
348 return result;
351 WERROR regkey_open_internal( TALLOC_CTX *ctx, REGISTRY_KEY **regkey,
352 const char *path,
353 const struct nt_user_token *token,
354 uint32 access_desired )
356 struct registry_key *key;
357 WERROR err;
359 err = reg_open_path(NULL, path, access_desired, token, &key);
360 if (!W_ERROR_IS_OK(err)) {
361 return err;
364 *regkey = talloc_move(ctx, &key->key);
365 TALLOC_FREE(key);
366 return WERR_OK;
369 WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
370 struct security_descriptor **psecdesc)
372 struct security_descriptor *secdesc;
374 if (key->hook && key->hook->ops && key->hook->ops->get_secdesc) {
375 WERROR err;
377 err = key->hook->ops->get_secdesc(mem_ctx, key->name,
378 psecdesc);
379 if (W_ERROR_IS_OK(err)) {
380 return WERR_OK;
384 if (!(secdesc = construct_registry_sd(mem_ctx))) {
385 return WERR_NOMEM;
388 *psecdesc = secdesc;
389 return WERR_OK;
392 WERROR regkey_set_secdesc(REGISTRY_KEY *key,
393 struct security_descriptor *psecdesc)
395 if (key->hook && key->hook->ops && key->hook->ops->set_secdesc) {
396 return key->hook->ops->set_secdesc(key->name, psecdesc);
399 return WERR_ACCESS_DENIED;
404 * Utility function to open a complete registry path including the hive
405 * prefix. This should become the replacement function for
406 * regkey_open_internal.
409 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
410 uint32 desired_access, const struct nt_user_token *token,
411 struct registry_key **pkey)
413 struct registry_key *hive, *key;
414 char *path, *p;
415 WERROR err;
417 if (!(path = SMB_STRDUP(orig_path))) {
418 return WERR_NOMEM;
421 p = strchr(path, '\\');
423 if ((p == NULL) || (p[1] == '\0')) {
425 * No key behind the hive, just return the hive
428 err = reg_openhive(mem_ctx, path, desired_access, token,
429 &hive);
430 if (!W_ERROR_IS_OK(err)) {
431 SAFE_FREE(path);
432 return err;
434 SAFE_FREE(path);
435 *pkey = hive;
436 return WERR_OK;
439 *p = '\0';
441 err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
442 &hive);
443 if (!W_ERROR_IS_OK(err)) {
444 SAFE_FREE(path);
445 return err;
448 err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
450 TALLOC_FREE(hive);
451 SAFE_FREE(path);
453 if (!W_ERROR_IS_OK(err)) {
454 return err;
457 *pkey = key;
458 return WERR_OK;
462 * Utility function to create a registry key without opening the hive
463 * before. Assumes the hive already exists.
466 WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
467 uint32 desired_access,
468 const struct nt_user_token *token,
469 enum winreg_CreateAction *paction,
470 struct registry_key **pkey)
472 struct registry_key *hive;
473 char *path, *p;
474 WERROR err;
476 if (!(path = SMB_STRDUP(orig_path))) {
477 return WERR_NOMEM;
480 p = strchr(path, '\\');
482 if ((p == NULL) || (p[1] == '\0')) {
484 * No key behind the hive, just return the hive
487 err = reg_openhive(mem_ctx, path, desired_access, token,
488 &hive);
489 if (!W_ERROR_IS_OK(err)) {
490 SAFE_FREE(path);
491 return err;
493 SAFE_FREE(path);
494 *pkey = hive;
495 *paction = REG_OPENED_EXISTING_KEY;
496 return WERR_OK;
499 *p = '\0';
501 err = reg_openhive(mem_ctx, path,
502 (strchr(p+1, '\\') != NULL) ?
503 SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
504 token, &hive);
505 if (!W_ERROR_IS_OK(err)) {
506 SAFE_FREE(path);
507 return err;
510 err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
511 SAFE_FREE(path);
512 TALLOC_FREE(hive);
513 return err;
517 * Utility function to create a registry key without opening the hive
518 * before. Will not delete a hive.
521 WERROR reg_delete_path(const struct nt_user_token *token,
522 const char *orig_path)
524 struct registry_key *hive;
525 char *path, *p;
526 WERROR err;
528 if (!(path = SMB_STRDUP(orig_path))) {
529 return WERR_NOMEM;
532 p = strchr(path, '\\');
534 if ((p == NULL) || (p[1] == '\0')) {
535 SAFE_FREE(path);
536 return WERR_INVALID_PARAM;
539 *p = '\0';
541 err = reg_openhive(NULL, path,
542 (strchr(p+1, '\\') != NULL) ?
543 SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
544 token, &hive);
545 if (!W_ERROR_IS_OK(err)) {
546 SAFE_FREE(path);
547 return err;
550 err = reg_deletekey(hive, p+1);
551 SAFE_FREE(path);
552 TALLOC_FREE(hive);
553 return err;