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. */
31 #define DBGC_CLASS DBGC_RPC_SRV
33 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
34 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
36 static struct generic_mapping reg_generic_map =
37 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
40 /******************************************************************
41 free() function for REGISTRY_KEY
42 *****************************************************************/
44 static void free_regkey_info(void *ptr)
49 /******************************************************************
50 Find a registry key handle and return a REGISTRY_KEY
51 *****************************************************************/
53 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
55 REGISTRY_KEY *regkey = NULL;
57 if(!find_policy_by_hnd(p,hnd,(void **)®key)) {
58 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
66 /*******************************************************************
67 Function for open a new registry handle and creating a handle
68 Note that P should be valid & hnd should already have space
70 When we open a key, we store the full path to the key as
71 HK[LM|U]\<key>\<key>\...
72 *******************************************************************/
74 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
75 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
76 const char *subkeyname, uint32 access_desired )
80 WERROR result = WERR_OK;
82 /* create a full registry path and strip any trailing '\'
85 pstr_sprintf( keypath, "%s%s%s",
86 parent ? parent->name : "",
90 path_len = strlen( keypath );
91 if ( path_len && keypath[path_len-1] == '\\' )
92 keypath[path_len-1] = '\0';
94 /* now do the internal open */
96 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
97 if ( !W_ERROR_IS_OK(result) )
100 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
101 result = WERR_BADFILE;
102 TALLOC_FREE( *keyinfo );
109 /*******************************************************************
110 Function for open a new registry handle and creating a handle
111 Note that P should be valid & hnd should already have space
112 *******************************************************************/
114 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
116 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
119 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
123 close_policy_hnd(p, hnd);
128 /********************************************************************
129 retrieve information about the subkeys
130 *******************************************************************/
132 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
136 REGSUBKEY_CTR *subkeys;
142 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
145 if ( fetch_reg_keys( key, subkeys ) == -1 )
148 /* find the longest string */
151 num_subkeys = regsubkey_ctr_numkeys( subkeys );
153 for ( i=0; i<num_subkeys; i++ ) {
154 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
155 max_len = MAX(max_len, len);
158 *maxnum = num_subkeys;
161 TALLOC_FREE( subkeys );
166 /********************************************************************
167 retrieve information about the values.
168 *******************************************************************/
170 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
171 uint32 *maxlen, uint32 *maxsize )
175 uint32 sizemax, lenmax;
181 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
184 if ( fetch_reg_values( key, values ) == -1 )
187 lenmax = sizemax = 0;
188 num_values = regval_ctr_numvals( values );
190 val = regval_ctr_specific_value( values, 0 );
192 for ( i=0; i<num_values && val; i++ )
194 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
195 sizemax = MAX(sizemax, val->size );
197 val = regval_ctr_specific_value( values, i );
200 *maxnum = num_values;
204 TALLOC_FREE( values );
210 /********************************************************************
212 ********************************************************************/
214 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
216 /* close the policy handle */
218 if (!close_registry_key(p, &q_u->pol))
224 /*******************************************************************
225 ********************************************************************/
227 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
229 REGISTRY_KEY *keyinfo;
231 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access );
234 /*******************************************************************
235 ********************************************************************/
237 WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
239 REGISTRY_KEY *keyinfo;
241 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access );
244 /*******************************************************************
245 ********************************************************************/
247 WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
249 REGISTRY_KEY *keyinfo;
251 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access );
254 /*******************************************************************
255 ********************************************************************/
257 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
259 REGISTRY_KEY *keyinfo;
261 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access );
264 /*******************************************************************
265 ********************************************************************/
267 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
269 REGISTRY_KEY *keyinfo;
271 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access );
274 /*******************************************************************
276 ********************************************************************/
278 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
281 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
282 REGISTRY_KEY *newkey = NULL;
288 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
290 /* check granted access first; what is the correct mask here? */
292 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
293 SEC_RIGHTS_CREATE_SUBKEY|
294 SEC_RIGHTS_QUERY_VALUE|
295 SEC_RIGHTS_SET_VALUE);
297 if ( !(parent->access_granted & check_rights) ) {
298 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
299 return WERR_ACCESS_DENIED;
303 * very crazy, but regedit.exe on Win2k will attempt to call
304 * REG_OPEN_ENTRY with a keyname of "". We should return a new
305 * (second) handle here on the key->name. regedt32.exe does
306 * not do this stupidity. --jerry
309 return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
312 /*******************************************************************
314 ********************************************************************/
316 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
318 WERROR status = WERR_BADFILE;
320 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
321 REGISTRY_VALUE *val = NULL;
328 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
329 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
331 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
333 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
335 if ( !(regvals = TALLOC_P( p->mem_ctx, REGVAL_CTR )) )
338 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
339 if(regkey->type == REG_KEY_HKPD)
341 if(strequal(name, "Global"))
345 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
346 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
347 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
348 prs_hkpd.data_p, outbuf_len);
349 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
350 prs_mem_free(&prs_hkpd);
352 else if(strequal(name, "Counter 009"))
359 base_index = reg_perfcount_get_base_index();
360 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
361 regval_ctr_addvalue(regvals, "Counter 009",
362 REG_MULTI_SZ, buffer, buffer_size);
364 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
372 else if(strequal(name, "Explain 009"))
379 base_index = reg_perfcount_get_base_index();
380 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
381 regval_ctr_addvalue(regvals, "Explain 009",
382 REG_MULTI_SZ, buffer, buffer_size);
384 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
392 else if(isdigit(name[0]))
394 /* we probably have a request for a specific object here */
397 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
398 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
399 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
400 prs_hkpd.data_p, outbuf_len);
402 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
403 prs_mem_free(&prs_hkpd);
407 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
411 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
414 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
416 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
417 if ( strequal( val->valuename, name ) ) {
418 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
423 free_registry_value( val );
427 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
429 TALLOC_FREE( regvals );
430 free_registry_value( val );
435 /*****************************************************************************
436 Implementation of REG_QUERY_KEY
437 ****************************************************************************/
439 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
441 WERROR status = WERR_OK;
442 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
447 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
448 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
449 return WERR_ACCESS_DENIED;
452 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
453 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
454 return WERR_ACCESS_DENIED;
458 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
460 /* Win9x set this to 0x0 since it does not keep timestamps.
461 Doing the same here for simplicity --jerry */
463 ZERO_STRUCT(r_u->mod_time);
469 /*****************************************************************************
470 Implementation of REG_GETVERSION
471 ****************************************************************************/
473 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
475 WERROR status = WERR_OK;
476 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
481 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
487 /*****************************************************************************
488 Implementation of REG_ENUM_KEY
489 ****************************************************************************/
491 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
493 WERROR status = WERR_OK;
494 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
501 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
503 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
505 status = WERR_NO_MORE_ITEMS;
509 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
511 /* subkey has the string name now */
513 init_reg_r_enum_key( r_u, subkey );
520 /*****************************************************************************
521 Implementation of REG_ENUM_VALUE
522 ****************************************************************************/
524 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
526 WERROR status = WERR_OK;
527 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
534 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
536 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
537 status = WERR_NO_MORE_ITEMS;
541 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
543 /* subkey has the string name now */
545 init_reg_r_enum_val( r_u, val );
548 free_registry_value( val );
554 /*******************************************************************
556 ********************************************************************/
558 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
560 REG_Q_SHUTDOWN_EX q_u_ex;
561 REG_R_SHUTDOWN_EX r_u_ex;
563 /* copy fields (including stealing memory) */
565 q_u_ex.server = q_u->server;
566 q_u_ex.message = q_u->message;
567 q_u_ex.timeout = q_u->timeout;
568 q_u_ex.force = q_u->force;
569 q_u_ex.reboot = q_u->reboot;
570 q_u_ex.reason = 0x0; /* don't care for now */
572 /* thunk down to _reg_shutdown_ex() (just returns a status) */
574 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
577 /*******************************************************************
579 ********************************************************************/
581 #define SHUTDOWN_R_STRING "-r"
582 #define SHUTDOWN_F_STRING "-f"
585 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
587 pstring shutdown_script;
598 pstrcpy(shutdown_script, lp_shutdown_script());
600 if ( !*shutdown_script )
601 return WERR_ACCESS_DENIED;
603 /* pull the message string and perform necessary sanity checks on it */
605 pstrcpy( message, "" );
606 if ( q_u->message ) {
607 UNISTR2 *msg_string = q_u->message->string;
609 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
611 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
613 fstr_sprintf(timeout, "%d", q_u->timeout);
614 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
615 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
616 fstr_sprintf( reason, "%d", q_u->reason );
618 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
619 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
620 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
621 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
622 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
624 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
626 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
627 Take the error return from the script and provide it as the Windows return code. */
629 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
634 ret = smbrun( shutdown_script, NULL );
639 /********** END SeRemoteShutdownPrivilege BLOCK **********/
641 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
642 shutdown_script, ret));
645 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
651 /*******************************************************************
653 ********************************************************************/
655 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
657 pstring abort_shutdown_script;
661 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
663 if ( !*abort_shutdown_script )
664 return WERR_ACCESS_DENIED;
666 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
668 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
673 ret = smbrun( abort_shutdown_script, NULL );
678 /********** END SeRemoteShutdownPrivilege BLOCK **********/
680 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
681 abort_shutdown_script, ret));
684 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
687 /*******************************************************************
688 ********************************************************************/
690 static int validate_reg_filename( pstring fname )
693 int num_services = lp_numservices();
698 /* convert to a unix path, stripping the C:\ along the way */
700 if ( !(p = valid_share_pathname( fname ) ))
703 /* has to exist within a valid file share */
705 for ( snum=0; snum<num_services; snum++ ) {
707 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
710 pstrcpy( share_path, lp_pathname(snum) );
712 /* make sure we have a path (e.g. [homes] ) */
714 if ( strlen( share_path ) == 0 )
717 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
721 /* p and fname are overlapping memory so copy out and back in again */
723 pstrcpy( unix_fname, p );
724 pstrcpy( fname, unix_fname );
726 return (snum < num_services) ? snum : -1;
729 /*******************************************************************
730 Note: topkeypat is the *full* path that this *key will be
731 loaded into (including the name of the key)
732 ********************************************************************/
734 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
738 REGISTRY_KEY registry_key;
740 REGSUBKEY_CTR *subkeys;
743 WERROR result = WERR_OK;
745 /* initialize the REGISTRY_KEY structure */
747 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
748 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
752 pstrcpy( registry_key.name, topkeypath );
754 /* now start parsing the values and subkeys */
756 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
759 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
762 /* copy values into the REGVAL_CTR */
764 for ( i=0; i<key->num_values; i++ ) {
765 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
766 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
769 /* copy subkeys into the REGSUBKEY_CTR */
771 key->subkey_index = 0;
772 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
773 regsubkey_ctr_addkey( subkeys, subkey->keyname );
776 /* write this key and values out */
778 if ( !store_reg_values( ®istry_key, values )
779 || !store_reg_keys( ®istry_key, subkeys ) )
781 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
782 result = WERR_REG_IO_FAILURE;
785 TALLOC_FREE( subkeys );
787 if ( !W_ERROR_IS_OK(result) )
790 /* now continue to load each subkey registry tree */
792 key->subkey_index = 0;
793 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
794 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
795 result = reg_load_tree( regfile, path, subkey );
796 if ( !W_ERROR_IS_OK(result) )
803 /*******************************************************************
804 ********************************************************************/
806 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
809 REGF_NK_REC *rootkey;
812 /* open the registry file....fail if the file already exists */
814 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
815 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
816 fname, strerror(errno) ));
817 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
820 /* get the rootkey from the regf file and then load the tree
821 via recursive calls */
823 if ( !(rootkey = regfio_rootkey( regfile )) )
824 return WERR_REG_FILE_INVALID;
826 result = reg_load_tree( regfile, krecord->name, rootkey );
830 regfio_close( regfile );
835 /*******************************************************************
836 ********************************************************************/
838 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
840 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
847 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
849 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
851 if ( (snum = validate_reg_filename( filename )) == -1 )
852 return WERR_OBJECT_PATH_INVALID;
854 /* user must posses SeRestorePrivilege for this this proceed */
856 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
857 return WERR_ACCESS_DENIED;
859 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
861 return restore_registry_key( regkey, filename );
864 /********************************************************************
865 ********************************************************************/
867 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
868 REGF_NK_REC *parent, SEC_DESC *sec_desc )
872 REGSUBKEY_CTR *subkeys;
875 char *keyname, *parentpath;
878 REGISTRY_KEY registry_key;
879 WERROR result = WERR_OK;
882 return WERR_GENERAL_FAILURE;
885 return WERR_OBJECT_PATH_INVALID;
887 /* split up the registry key path */
889 pstrcpy( key_tmp, keypath );
890 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
891 return WERR_OBJECT_PATH_INVALID;
894 keyname = parentpath;
896 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
898 ZERO_STRUCT( registry_key );
899 pstrcpy( registry_key.name, keypath );
900 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
904 /* lookup the values and subkeys */
906 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
909 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
912 fetch_reg_keys( ®istry_key, subkeys );
913 fetch_reg_values( ®istry_key, values );
915 /* write out this key */
917 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
918 result = WERR_CAN_NOT_COMPLETE;
922 /* write each one of the subkeys out */
924 num_subkeys = regsubkey_ctr_numkeys( subkeys );
925 for ( i=0; i<num_subkeys; i++ ) {
926 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
927 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
928 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
929 if ( !W_ERROR_IS_OK(result) )
933 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
936 TALLOC_FREE( subkeys );
941 /*******************************************************************
942 ********************************************************************/
944 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
946 DOM_SID adm_sid, owner_sid;
947 SEC_ACE ace[2]; /* at most 2 entries */
952 /* set the owner to BUILTIN\Administrator */
954 sid_copy(&owner_sid, &global_sid_Builtin);
955 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
958 /* basic access for Everyone */
960 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
961 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
963 /* add Full Access 'BUILTIN\Administrators' */
965 init_sec_access(&mask, reg_generic_map.generic_all);
966 sid_copy(&adm_sid, &global_sid_Builtin);
967 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
968 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
970 /* create the security descriptor */
972 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
975 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
981 /*******************************************************************
982 ********************************************************************/
984 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
990 /* open the registry file....fail if the file already exists */
992 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
993 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
994 fname, strerror(errno) ));
995 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
998 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
999 regfio_close( regfile );
1003 /* write the registry tree to the file */
1005 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1009 regfio_close( regfile );
1014 /*******************************************************************
1015 ********************************************************************/
1017 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1019 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1026 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1028 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1030 if ( (snum = validate_reg_filename( filename )) == -1 )
1031 return WERR_OBJECT_PATH_INVALID;
1033 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1035 return backup_registry_key( regkey, filename );
1038 /*******************************************************************
1039 ********************************************************************/
1041 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1043 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1044 REGISTRY_KEY *newparentinfo, *keyinfo;
1045 POLICY_HND newparent_handle;
1046 REGSUBKEY_CTR *subkeys;
1054 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1056 /* ok. Here's what we do. */
1058 if ( strrchr( name, '\\' ) ) {
1062 /* (1) check for enumerate rights on the parent handle. CLients can try
1063 create things like 'SOFTWARE\Samba' on the HKLM handle.
1064 (2) open the path to the child parent key if necessary */
1066 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1067 return WERR_ACCESS_DENIED;
1069 pstrcpy( newkeyname, name );
1070 ptr = strrchr( newkeyname, '\\' );
1073 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1074 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1076 if ( !W_ERROR_IS_OK(result) )
1079 /* copy the new key name (just the lower most keyname) */
1081 pstrcpy( name, ptr+1 );
1084 /* use the existing open key information */
1085 newparentinfo = parent;
1086 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1089 /* (3) check for create subkey rights on the correct parent */
1091 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1092 result = WERR_ACCESS_DENIED;
1096 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1097 result = WERR_NOMEM;
1101 /* (4) lookup the current keys and add the new one */
1103 fetch_reg_keys( newparentinfo, subkeys );
1104 regsubkey_ctr_addkey( subkeys, name );
1106 /* now write to the registry backend */
1108 write_result = store_reg_keys( newparentinfo, subkeys );
1110 TALLOC_FREE( subkeys );
1112 if ( !write_result )
1113 return WERR_REG_IO_FAILURE;
1115 /* (5) open the new key and return the handle. Note that it is probably
1116 not correct to grant full access on this open handle. */
1118 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1119 keyinfo->access_granted = REG_KEY_ALL;
1122 /* close any intermediate key handles */
1124 if ( newparentinfo != parent )
1125 close_registry_key( p, &newparent_handle );
1131 /*******************************************************************
1132 ********************************************************************/
1134 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1136 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1144 /* access checks first */
1146 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1147 return WERR_ACCESS_DENIED;
1149 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1151 /* verify the name */
1154 return WERR_INVALID_PARAM;
1156 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1158 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1161 /* lookup the current values and add the new one */
1163 fetch_reg_values( key, values );
1165 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
1167 /* now write to the registry backend */
1169 write_result = store_reg_values( key, values );
1171 TALLOC_FREE( values );
1173 if ( !write_result )
1174 return WERR_REG_IO_FAILURE;
1179 /*******************************************************************
1180 ********************************************************************/
1182 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1184 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1185 REGISTRY_KEY *newparentinfo;
1186 POLICY_HND newparent_handle;
1187 REGSUBKEY_CTR *subkeys;
1195 /* MSDN says parent the handle must have been opened with DELETE access */
1197 /* (1) check for delete rights on the parent */
1199 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1200 result = WERR_ACCESS_DENIED;
1204 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1206 /* ok. Here's what we do. */
1208 if ( strrchr( name, '\\' ) ) {
1212 /* (2) open the path to the child parent key if necessary */
1213 /* split the registry path and save the subkeyname */
1215 pstrcpy( newkeyname, name );
1216 ptr = strrchr( newkeyname, '\\' );
1218 pstrcpy( name, ptr+1 );
1220 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1221 if ( !W_ERROR_IS_OK(result) )
1225 /* use the existing open key information */
1226 newparentinfo = parent;
1229 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1230 result = WERR_NOMEM;
1234 /* lookup the current keys and delete the new one */
1236 fetch_reg_keys( newparentinfo, subkeys );
1238 regsubkey_ctr_delkey( subkeys, name );
1240 /* now write to the registry backend */
1242 write_result = store_reg_keys( newparentinfo, subkeys );
1244 TALLOC_FREE( subkeys );
1246 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1249 /* close any intermediate key handles */
1251 if ( newparentinfo != parent )
1252 close_registry_key( p, &newparent_handle );
1258 /*******************************************************************
1259 ********************************************************************/
1261 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1263 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1271 /* access checks first */
1273 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1274 return WERR_ACCESS_DENIED;
1276 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1279 return WERR_INVALID_PARAM;
1281 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1283 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1286 /* lookup the current values and add the new one */
1288 fetch_reg_values( key, values );
1290 regval_ctr_delvalue( values, valuename );
1292 /* now write to the registry backend */
1294 write_result = store_reg_values( key, values );
1296 TALLOC_FREE( values );
1298 if ( !write_result )
1299 return WERR_REG_IO_FAILURE;
1304 /*******************************************************************
1305 ********************************************************************/
1307 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1309 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1314 /* access checks first */
1316 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1317 return WERR_ACCESS_DENIED;
1319 return WERR_ACCESS_DENIED;
1322 /*******************************************************************
1323 ********************************************************************/
1325 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1327 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1332 /* access checks first */
1334 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1335 return WERR_ACCESS_DENIED;
1337 return WERR_ACCESS_DENIED;