[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / rpc_server / srv_reg_nt.c
blob3728252c993190bbf3dba317d2fa077a5d028834
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997.
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
6 * Copyright (C) Paul Ashton 1997.
7 * Copyright (C) Jeremy Allison 2001.
8 * Copyright (C) Gerald Carter 2002-2005.
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 2 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, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* Implementation of registry functions. */
27 #include "includes.h"
28 #include "regfio.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 static struct generic_mapping reg_generic_map =
34 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
37 /******************************************************************
38 free() function for REGISTRY_KEY
39 *****************************************************************/
41 static void free_regkey_info(void *ptr)
43 regkey_close_internal( (REGISTRY_KEY*)ptr );
46 /******************************************************************
47 Find a registry key handle and return a REGISTRY_KEY
48 *****************************************************************/
50 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
52 REGISTRY_KEY *regkey = NULL;
54 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
55 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
56 return NULL;
59 return regkey;
63 /*******************************************************************
64 Function for open a new registry handle and creating a handle
65 Note that P should be valid & hnd should already have space
67 When we open a key, we store the full path to the key as
68 HK[LM|U]\<key>\<key>\...
69 *******************************************************************/
71 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
72 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
73 const char *subkeyname, uint32 access_desired )
75 pstring keypath;
76 int path_len;
77 WERROR result = WERR_OK;
79 /* create a full registry path and strip any trailing '\'
80 characters */
82 pstr_sprintf( keypath, "%s%s%s",
83 parent ? parent->name : "",
84 parent ? "\\" : "",
85 subkeyname );
87 path_len = strlen( keypath );
88 if ( path_len && keypath[path_len-1] == '\\' )
89 keypath[path_len-1] = '\0';
91 /* now do the internal open */
93 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
94 if ( !W_ERROR_IS_OK(result) )
95 return result;
97 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
98 result = WERR_BADFILE;
99 regkey_close_internal( *keyinfo );
102 return result;
105 /*******************************************************************
106 Function for open a new registry handle and creating a handle
107 Note that P should be valid & hnd should already have space
108 *******************************************************************/
110 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
112 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
114 if ( !regkey ) {
115 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
116 return False;
119 close_policy_hnd(p, hnd);
121 return True;
124 /********************************************************************
125 retrieve information about the subkeys
126 *******************************************************************/
128 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
130 int num_subkeys, i;
131 uint32 max_len;
132 REGSUBKEY_CTR *subkeys;
133 uint32 len;
135 if ( !key )
136 return False;
138 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
139 return False;
141 if ( fetch_reg_keys( key, subkeys ) == -1 )
142 return False;
144 /* find the longest string */
146 max_len = 0;
147 num_subkeys = regsubkey_ctr_numkeys( subkeys );
149 for ( i=0; i<num_subkeys; i++ ) {
150 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
151 max_len = MAX(max_len, len);
154 *maxnum = num_subkeys;
155 *maxlen = max_len*2;
157 TALLOC_FREE( subkeys );
159 return True;
162 /********************************************************************
163 retrieve information about the values.
164 *******************************************************************/
166 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
167 uint32 *maxlen, uint32 *maxsize )
169 REGVAL_CTR *values;
170 REGISTRY_VALUE *val;
171 uint32 sizemax, lenmax;
172 int i, num_values;
174 if ( !key )
175 return False;
177 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
178 return False;
180 if ( fetch_reg_values( key, values ) == -1 )
181 return False;
183 lenmax = sizemax = 0;
184 num_values = regval_ctr_numvals( values );
186 val = regval_ctr_specific_value( values, 0 );
188 for ( i=0; i<num_values && val; i++ )
190 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
191 sizemax = MAX(sizemax, val->size );
193 val = regval_ctr_specific_value( values, i );
196 *maxnum = num_values;
197 *maxlen = lenmax;
198 *maxsize = sizemax;
200 TALLOC_FREE( values );
202 return True;
206 /********************************************************************
207 reg_close
208 ********************************************************************/
210 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
212 /* close the policy handle */
214 if (!close_registry_key(p, &q_u->pol))
215 return WERR_BADFID;
217 return WERR_OK;
220 /*******************************************************************
221 ********************************************************************/
223 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
225 REGISTRY_KEY *keyinfo;
227 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access );
230 /*******************************************************************
231 ********************************************************************/
233 WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
235 REGISTRY_KEY *keyinfo;
237 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access );
240 /*******************************************************************
241 ********************************************************************/
243 WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
245 REGISTRY_KEY *keyinfo;
247 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access );
250 /*******************************************************************
251 ********************************************************************/
253 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
255 REGISTRY_KEY *keyinfo;
257 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access );
260 /*******************************************************************
261 ********************************************************************/
263 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
265 REGISTRY_KEY *keyinfo;
267 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access );
270 /*******************************************************************
271 reg_reply_open_entry
272 ********************************************************************/
274 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
276 fstring name;
277 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
278 REGISTRY_KEY *newkey = NULL;
279 uint32 check_rights;
281 if ( !parent )
282 return WERR_BADFID;
284 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
286 /* check granted access first; what is the correct mask here? */
288 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
289 SEC_RIGHTS_CREATE_SUBKEY|
290 SEC_RIGHTS_QUERY_VALUE|
291 SEC_RIGHTS_SET_VALUE);
293 if ( !(parent->access_granted & check_rights) ) {
294 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
295 return WERR_ACCESS_DENIED;
299 * very crazy, but regedit.exe on Win2k will attempt to call
300 * REG_OPEN_ENTRY with a keyname of "". We should return a new
301 * (second) handle here on the key->name. regedt32.exe does
302 * not do this stupidity. --jerry
305 return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
308 /*******************************************************************
309 reg_reply_info
310 ********************************************************************/
312 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
314 WERROR status = WERR_BADFILE;
315 fstring name;
316 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
317 REGISTRY_VALUE *val = NULL;
318 REGVAL_CTR *regvals;
319 int i;
321 if ( !regkey )
322 return WERR_BADFID;
324 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
325 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
327 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
329 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
331 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
332 return WERR_NOMEM;
334 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
335 if(regkey->type == REG_KEY_HKPD)
337 if(strequal(name, "Global"))
339 uint32 outbuf_len;
340 prs_struct prs_hkpd;
341 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
342 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
343 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
344 prs_hkpd.data_p, outbuf_len);
345 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
346 prs_mem_free(&prs_hkpd);
348 else if(strequal(name, "Counter 009"))
350 uint32 base_index;
351 uint32 buffer_size;
352 char *buffer;
354 buffer = NULL;
355 base_index = reg_perfcount_get_base_index();
356 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
357 regval_ctr_addvalue(regvals, "Counter 009",
358 REG_MULTI_SZ, buffer, buffer_size);
360 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
362 if(buffer_size > 0)
364 SAFE_FREE(buffer);
365 status = WERR_OK;
368 else if(strequal(name, "Explain 009"))
370 uint32 base_index;
371 uint32 buffer_size;
372 char *buffer;
374 buffer = NULL;
375 base_index = reg_perfcount_get_base_index();
376 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
377 regval_ctr_addvalue(regvals, "Explain 009",
378 REG_MULTI_SZ, buffer, buffer_size);
380 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
382 if(buffer_size > 0)
384 SAFE_FREE(buffer);
385 status = WERR_OK;
388 else if(isdigit(name[0]))
390 /* we probably have a request for a specific object here */
391 uint32 outbuf_len;
392 prs_struct prs_hkpd;
393 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
394 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
395 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
396 prs_hkpd.data_p, outbuf_len);
398 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
399 prs_mem_free(&prs_hkpd);
401 else
403 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
404 return WERR_BADFILE;
407 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
408 else
410 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
412 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
413 if ( strequal( val->valuename, name ) ) {
414 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
415 status = WERR_OK;
416 break;
419 free_registry_value( val );
423 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
425 TALLOC_FREE( regvals );
426 free_registry_value( val );
428 return status;
431 /*****************************************************************************
432 Implementation of REG_QUERY_KEY
433 ****************************************************************************/
435 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
437 WERROR status = WERR_OK;
438 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
440 if ( !regkey )
441 return WERR_BADFID;
443 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
444 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
445 return WERR_ACCESS_DENIED;
448 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
449 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
450 return WERR_ACCESS_DENIED;
454 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
456 /* Win9x set this to 0x0 since it does not keep timestamps.
457 Doing the same here for simplicity --jerry */
459 ZERO_STRUCT(r_u->mod_time);
461 return status;
465 /*****************************************************************************
466 Implementation of REG_GETVERSION
467 ****************************************************************************/
469 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
471 WERROR status = WERR_OK;
472 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
474 if ( !regkey )
475 return WERR_BADFID;
477 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
479 return status;
483 /*****************************************************************************
484 Implementation of REG_ENUM_KEY
485 ****************************************************************************/
487 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
489 WERROR status = WERR_OK;
490 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
491 char *subkey = NULL;
494 if ( !regkey )
495 return WERR_BADFID;
497 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
499 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
501 status = WERR_NO_MORE_ITEMS;
502 goto done;
505 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
507 /* subkey has the string name now */
509 init_reg_r_enum_key( r_u, subkey );
511 done:
512 SAFE_FREE( subkey );
513 return status;
516 /*****************************************************************************
517 Implementation of REG_ENUM_VALUE
518 ****************************************************************************/
520 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
522 WERROR status = WERR_OK;
523 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
524 REGISTRY_VALUE *val;
527 if ( !regkey )
528 return WERR_BADFID;
530 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
532 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
533 status = WERR_NO_MORE_ITEMS;
534 goto done;
537 #if 0 /* JERRY TEST CODE */
538 if ( val->type == REG_MULTI_SZ ) {
539 char **str;
540 int num_strings = regval_convert_multi_sz( (uint16*)regval_data_p(val), regval_size(val), &str );
541 uint16 *buffer;
542 size_t buf_size;
545 if ( num_strings )
546 buf_size = regval_build_multi_sz( str, &buffer );
548 TALLOC_FREE( str );
549 TALLOC_FREE( buffer );
551 #endif
553 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
555 /* subkey has the string name now */
557 init_reg_r_enum_val( r_u, val );
559 done:
560 free_registry_value( val );
562 return status;
566 /*******************************************************************
567 reg_shutdwon
568 ********************************************************************/
570 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
572 REG_Q_SHUTDOWN_EX q_u_ex;
573 REG_R_SHUTDOWN_EX r_u_ex;
575 /* copy fields (including stealing memory) */
577 q_u_ex.server = q_u->server;
578 q_u_ex.message = q_u->message;
579 q_u_ex.timeout = q_u->timeout;
580 q_u_ex.force = q_u->force;
581 q_u_ex.reboot = q_u->reboot;
582 q_u_ex.reason = 0x0; /* don't care for now */
584 /* thunk down to _reg_shutdown_ex() (just returns a status) */
586 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
589 /*******************************************************************
590 reg_shutdown_ex
591 ********************************************************************/
593 #define SHUTDOWN_R_STRING "-r"
594 #define SHUTDOWN_F_STRING "-f"
597 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
599 pstring shutdown_script;
600 pstring message;
601 pstring chkmsg;
602 fstring timeout;
603 fstring reason;
604 fstring r;
605 fstring f;
606 int ret;
607 BOOL can_shutdown;
610 pstrcpy(shutdown_script, lp_shutdown_script());
612 if ( !*shutdown_script )
613 return WERR_ACCESS_DENIED;
615 /* pull the message string and perform necessary sanity checks on it */
617 pstrcpy( message, "" );
618 if ( q_u->message ) {
619 UNISTR2 *msg_string = q_u->message->string;
621 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
623 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
625 fstr_sprintf(timeout, "%d", q_u->timeout);
626 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
627 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
628 fstr_sprintf( reason, "%d", q_u->reason );
630 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
631 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
632 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
633 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
634 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
636 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
638 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
639 Take the error return from the script and provide it as the Windows return code. */
641 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
643 if ( can_shutdown )
644 become_root();
646 ret = smbrun( shutdown_script, NULL );
648 if ( can_shutdown )
649 unbecome_root();
651 /********** END SeRemoteShutdownPrivilege BLOCK **********/
653 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
654 shutdown_script, ret));
657 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
663 /*******************************************************************
664 reg_abort_shutdwon
665 ********************************************************************/
667 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
669 pstring abort_shutdown_script;
670 int ret;
671 BOOL can_shutdown;
673 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
675 if ( !*abort_shutdown_script )
676 return WERR_ACCESS_DENIED;
678 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
680 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
682 if ( can_shutdown )
683 become_root();
685 ret = smbrun( abort_shutdown_script, NULL );
687 if ( can_shutdown )
688 unbecome_root();
690 /********** END SeRemoteShutdownPrivilege BLOCK **********/
692 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
693 abort_shutdown_script, ret));
696 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
699 /*******************************************************************
700 ********************************************************************/
702 static int validate_reg_filename( pstring fname )
704 char *p;
705 int num_services = lp_numservices();
706 int snum;
707 pstring share_path;
708 pstring unix_fname;
710 /* convert to a unix path, stripping the C:\ along the way */
712 if ( !(p = valid_share_pathname( fname ) ))
713 return -1;
715 /* has to exist within a valid file share */
717 for ( snum=0; snum<num_services; snum++ ) {
719 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
720 continue;
722 pstrcpy( share_path, lp_pathname(snum) );
724 /* make sure we have a path (e.g. [homes] ) */
726 if ( strlen( share_path ) == 0 )
727 continue;
729 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
730 break;
733 /* p and fname are overlapping memory so copy out and back in again */
735 pstrcpy( unix_fname, p );
736 pstrcpy( fname, unix_fname );
738 return (snum < num_services) ? snum : -1;
741 /*******************************************************************
742 Note: topkeypat is the *full* path that this *key will be
743 loaded into (including the name of the key)
744 ********************************************************************/
746 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
747 REGF_NK_REC *key )
749 REGF_NK_REC *subkey;
750 REGISTRY_KEY registry_key;
751 REGVAL_CTR *values;
752 REGSUBKEY_CTR *subkeys;
753 int i;
754 pstring path;
755 WERROR result = WERR_OK;
757 /* initialize the REGISTRY_KEY structure */
759 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
760 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
761 topkeypath ));
762 return WERR_BADFILE;
764 pstrcpy( registry_key.name, topkeypath );
766 /* now start parsing the values and subkeys */
768 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
769 return WERR_NOMEM;
771 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
772 return WERR_NOMEM;
774 /* copy values into the REGVAL_CTR */
776 for ( i=0; i<key->num_values; i++ ) {
777 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
778 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
781 /* copy subkeys into the REGSUBKEY_CTR */
783 key->subkey_index = 0;
784 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
785 regsubkey_ctr_addkey( subkeys, subkey->keyname );
788 /* write this key and values out */
790 if ( !store_reg_values( &registry_key, values )
791 || !store_reg_keys( &registry_key, subkeys ) )
793 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
794 result = WERR_REG_IO_FAILURE;
797 TALLOC_FREE( subkeys );
799 if ( !W_ERROR_IS_OK(result) )
800 return result;
802 /* now continue to load each subkey registry tree */
804 key->subkey_index = 0;
805 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
806 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
807 result = reg_load_tree( regfile, path, subkey );
808 if ( !W_ERROR_IS_OK(result) )
809 break;
812 return result;
815 /*******************************************************************
816 ********************************************************************/
818 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
820 REGF_FILE *regfile;
821 REGF_NK_REC *rootkey;
822 WERROR result;
824 /* open the registry file....fail if the file already exists */
826 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
827 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
828 fname, strerror(errno) ));
829 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
832 /* get the rootkey from the regf file and then load the tree
833 via recursive calls */
835 if ( !(rootkey = regfio_rootkey( regfile )) ) {
836 regfio_close( regfile );
837 return WERR_REG_FILE_INVALID;
840 result = reg_load_tree( regfile, krecord->name, rootkey );
842 /* cleanup */
844 regfio_close( regfile );
846 return result;
849 /*******************************************************************
850 ********************************************************************/
852 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
854 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
855 pstring filename;
856 int snum;
858 if ( !regkey )
859 return WERR_BADFID;
861 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
863 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
865 if ( (snum = validate_reg_filename( filename )) == -1 )
866 return WERR_OBJECT_PATH_INVALID;
868 /* user must posses SeRestorePrivilege for this this proceed */
870 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
871 return WERR_ACCESS_DENIED;
873 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
875 return restore_registry_key( regkey, filename );
878 /********************************************************************
879 ********************************************************************/
881 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
882 REGF_NK_REC *parent, SEC_DESC *sec_desc )
884 REGF_NK_REC *key;
885 REGVAL_CTR *values;
886 REGSUBKEY_CTR *subkeys;
887 int i, num_subkeys;
888 pstring key_tmp;
889 char *keyname, *parentpath;
890 pstring subkeypath;
891 char *subkeyname;
892 REGISTRY_KEY registry_key;
893 WERROR result = WERR_OK;
895 if ( !regfile )
896 return WERR_GENERAL_FAILURE;
898 if ( !keypath )
899 return WERR_OBJECT_PATH_INVALID;
901 /* split up the registry key path */
903 pstrcpy( key_tmp, keypath );
904 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
905 return WERR_OBJECT_PATH_INVALID;
907 if ( !keyname )
908 keyname = parentpath;
910 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
912 ZERO_STRUCT( registry_key );
913 pstrcpy( registry_key.name, keypath );
914 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
915 return WERR_BADFILE;
918 /* lookup the values and subkeys */
920 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
921 return WERR_NOMEM;
923 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
924 return WERR_NOMEM;
926 fetch_reg_keys( &registry_key, subkeys );
927 fetch_reg_values( &registry_key, values );
929 /* write out this key */
931 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
932 result = WERR_CAN_NOT_COMPLETE;
933 goto done;
936 /* write each one of the subkeys out */
938 num_subkeys = regsubkey_ctr_numkeys( subkeys );
939 for ( i=0; i<num_subkeys; i++ ) {
940 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
941 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
942 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
943 if ( !W_ERROR_IS_OK(result) )
944 goto done;
947 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
949 done:
950 TALLOC_FREE( subkeys );
952 return result;
955 /*******************************************************************
956 ********************************************************************/
958 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
960 DOM_SID adm_sid, owner_sid;
961 SEC_ACE ace[2]; /* at most 2 entries */
962 SEC_ACCESS mask;
963 SEC_ACL *psa = NULL;
964 size_t sd_size;
966 /* set the owner to BUILTIN\Administrator */
968 sid_copy(&owner_sid, &global_sid_Builtin);
969 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
972 /* basic access for Everyone */
974 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
975 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
977 /* add Full Access 'BUILTIN\Administrators' */
979 init_sec_access(&mask, reg_generic_map.generic_all);
980 sid_copy(&adm_sid, &global_sid_Builtin);
981 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
982 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
984 /* create the security descriptor */
986 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
987 return WERR_NOMEM;
989 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
990 return WERR_NOMEM;
992 return WERR_OK;
995 /*******************************************************************
996 ********************************************************************/
998 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1000 REGF_FILE *regfile;
1001 WERROR result;
1002 SEC_DESC *sd = NULL;
1004 /* open the registry file....fail if the file already exists */
1006 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1007 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1008 fname, strerror(errno) ));
1009 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1012 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1013 regfio_close( regfile );
1014 return result;
1017 /* write the registry tree to the file */
1019 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1021 /* cleanup */
1023 regfio_close( regfile );
1025 return result;
1028 /*******************************************************************
1029 ********************************************************************/
1031 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1033 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1034 pstring filename;
1035 int snum;
1037 if ( !regkey )
1038 return WERR_BADFID;
1040 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1042 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1044 if ( (snum = validate_reg_filename( filename )) == -1 )
1045 return WERR_OBJECT_PATH_INVALID;
1047 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1049 return backup_registry_key( regkey, filename );
1052 /*******************************************************************
1053 ********************************************************************/
1055 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1057 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1058 REGISTRY_KEY *newparentinfo, *keyinfo;
1059 POLICY_HND newparent_handle;
1060 REGSUBKEY_CTR *subkeys;
1061 BOOL write_result;
1062 pstring name;
1063 WERROR result;
1065 if ( !parent )
1066 return WERR_BADFID;
1068 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1070 /* ok. Here's what we do. */
1072 if ( strrchr( name, '\\' ) ) {
1073 pstring newkeyname;
1074 char *ptr;
1076 /* (1) check for enumerate rights on the parent handle. CLients can try
1077 create things like 'SOFTWARE\Samba' on the HKLM handle.
1078 (2) open the path to the child parent key if necessary */
1080 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1081 return WERR_ACCESS_DENIED;
1083 pstrcpy( newkeyname, name );
1084 ptr = strrchr( newkeyname, '\\' );
1085 *ptr = '\0';
1087 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1088 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1090 if ( !W_ERROR_IS_OK(result) )
1091 return result;
1093 /* copy the new key name (just the lower most keyname) */
1095 pstrcpy( name, ptr+1 );
1097 else {
1098 /* use the existing open key information */
1099 newparentinfo = parent;
1100 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1103 /* (3) check for create subkey rights on the correct parent */
1105 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1106 result = WERR_ACCESS_DENIED;
1107 goto done;
1110 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1111 result = WERR_NOMEM;
1112 goto done;
1115 /* (4) lookup the current keys and add the new one */
1117 fetch_reg_keys( newparentinfo, subkeys );
1118 regsubkey_ctr_addkey( subkeys, name );
1120 /* now write to the registry backend */
1122 write_result = store_reg_keys( newparentinfo, subkeys );
1124 TALLOC_FREE( subkeys );
1126 if ( !write_result )
1127 return WERR_REG_IO_FAILURE;
1129 /* (5) open the new key and return the handle. Note that it is probably
1130 not correct to grant full access on this open handle. */
1132 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1133 keyinfo->access_granted = REG_KEY_ALL;
1135 done:
1136 /* close any intermediate key handles */
1138 if ( newparentinfo != parent )
1139 close_registry_key( p, &newparent_handle );
1141 return result;
1145 /*******************************************************************
1146 ********************************************************************/
1148 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1150 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1151 REGVAL_CTR *values;
1152 BOOL write_result;
1153 fstring valuename;
1155 if ( !key )
1156 return WERR_BADFID;
1158 /* access checks first */
1160 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1161 return WERR_ACCESS_DENIED;
1163 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1165 /* verify the name */
1167 if ( !*valuename )
1168 return WERR_INVALID_PARAM;
1170 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1172 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1173 return WERR_NOMEM;
1175 /* lookup the current values and add the new one */
1177 fetch_reg_values( key, values );
1179 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
1181 /* now write to the registry backend */
1183 write_result = store_reg_values( key, values );
1185 TALLOC_FREE( values );
1187 if ( !write_result )
1188 return WERR_REG_IO_FAILURE;
1190 return WERR_OK;
1193 /*******************************************************************
1194 ********************************************************************/
1196 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1198 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1199 REGISTRY_KEY *newparentinfo = NULL;
1200 POLICY_HND newparent_handle;
1201 REGSUBKEY_CTR *subkeys;
1202 BOOL write_result;
1203 pstring name;
1204 WERROR result;
1206 if ( !parent )
1207 return WERR_BADFID;
1209 /* MSDN says parent the handle must have been opened with DELETE access */
1211 /* (1) check for delete rights on the parent */
1213 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1214 result = WERR_ACCESS_DENIED;
1215 goto done;
1218 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1220 /* ok. Here's what we do. */
1222 if ( strrchr( name, '\\' ) ) {
1223 pstring newkeyname;
1224 char *ptr;
1226 /* (2) open the path to the child parent key if necessary */
1227 /* split the registry path and save the subkeyname */
1229 pstrcpy( newkeyname, name );
1230 ptr = strrchr( newkeyname, '\\' );
1231 *ptr = '\0';
1232 pstrcpy( name, ptr+1 );
1234 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1235 if ( !W_ERROR_IS_OK(result) )
1236 return result;
1238 else {
1239 /* use the existing open key information */
1240 newparentinfo = parent;
1243 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1244 result = WERR_NOMEM;
1245 goto done;
1248 /* lookup the current keys and delete the new one */
1250 fetch_reg_keys( newparentinfo, subkeys );
1252 regsubkey_ctr_delkey( subkeys, name );
1254 /* now write to the registry backend */
1256 write_result = store_reg_keys( newparentinfo, subkeys );
1258 TALLOC_FREE( subkeys );
1260 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1262 done:
1263 /* close any intermediate key handles */
1265 if ( newparentinfo != parent )
1266 close_registry_key( p, &newparent_handle );
1268 return result;
1272 /*******************************************************************
1273 ********************************************************************/
1275 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1277 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1278 REGVAL_CTR *values;
1279 BOOL write_result;
1280 fstring valuename;
1282 if ( !key )
1283 return WERR_BADFID;
1285 /* access checks first */
1287 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1288 return WERR_ACCESS_DENIED;
1290 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1292 if ( !*valuename )
1293 return WERR_INVALID_PARAM;
1295 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1297 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1298 return WERR_NOMEM;
1300 /* lookup the current values and add the new one */
1302 fetch_reg_values( key, values );
1304 regval_ctr_delvalue( values, valuename );
1306 /* now write to the registry backend */
1308 write_result = store_reg_values( key, values );
1310 TALLOC_FREE( values );
1312 if ( !write_result )
1313 return WERR_REG_IO_FAILURE;
1315 return WERR_OK;
1318 /*******************************************************************
1319 ********************************************************************/
1321 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1323 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1325 if ( !key )
1326 return WERR_BADFID;
1328 /* access checks first */
1330 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1331 return WERR_ACCESS_DENIED;
1333 return WERR_ACCESS_DENIED;
1336 /*******************************************************************
1337 ********************************************************************/
1339 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1341 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1343 if ( !key )
1344 return WERR_BADFID;
1346 /* access checks first */
1348 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1349 return WERR_ACCESS_DENIED;
1351 return WERR_ACCESS_DENIED;