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 return WERR_ACCESS_DENIED;
301 * very crazy, but regedit.exe on Win2k will attempt to call
302 * REG_OPEN_ENTRY with a keyname of "". We should return a new
303 * (second) handle here on the key->name. regedt32.exe does
304 * not do this stupidity. --jerry
307 return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
310 /*******************************************************************
312 ********************************************************************/
314 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
316 WERROR status = WERR_BADFILE;
318 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
319 REGISTRY_VALUE *val = NULL;
326 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
327 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
329 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
331 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
333 if ( !(regvals = TALLOC_P( p->mem_ctx, REGVAL_CTR )) )
336 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
337 if(regkey->type == REG_KEY_HKPD)
339 if(strequal(name, "Global"))
343 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
344 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
345 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
346 prs_hkpd.data_p, outbuf_len);
347 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
348 prs_mem_free(&prs_hkpd);
350 else if(strequal(name, "Counter 009"))
357 base_index = reg_perfcount_get_base_index();
358 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
359 regval_ctr_addvalue(regvals, "Counter 009",
360 REG_MULTI_SZ, buffer, buffer_size);
362 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
370 else if(strequal(name, "Explain 009"))
377 base_index = reg_perfcount_get_base_index();
378 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
379 regval_ctr_addvalue(regvals, "Explain 009",
380 REG_MULTI_SZ, buffer, buffer_size);
382 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
390 else if(isdigit(name[0]))
392 /* we probably have a request for a specific object here */
395 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
396 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
397 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
398 prs_hkpd.data_p, outbuf_len);
400 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
401 prs_mem_free(&prs_hkpd);
405 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
409 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
412 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
414 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
415 if ( strequal( val->valuename, name ) ) {
416 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
421 free_registry_value( val );
425 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
427 TALLOC_FREE( regvals );
428 free_registry_value( val );
433 /*****************************************************************************
434 Implementation of REG_QUERY_KEY
435 ****************************************************************************/
437 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
439 WERROR status = WERR_OK;
440 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
445 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
446 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
447 return WERR_ACCESS_DENIED;
450 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
451 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
452 return WERR_ACCESS_DENIED;
456 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
458 /* Win9x set this to 0x0 since it does not keep timestamps.
459 Doing the same here for simplicity --jerry */
461 ZERO_STRUCT(r_u->mod_time);
467 /*****************************************************************************
468 Implementation of REG_GETVERSION
469 ****************************************************************************/
471 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
473 WERROR status = WERR_OK;
474 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
479 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
485 /*****************************************************************************
486 Implementation of REG_ENUM_KEY
487 ****************************************************************************/
489 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
491 WERROR status = WERR_OK;
492 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
499 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
501 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
503 status = WERR_NO_MORE_ITEMS;
507 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
509 /* subkey has the string name now */
511 init_reg_r_enum_key( r_u, subkey );
518 /*****************************************************************************
519 Implementation of REG_ENUM_VALUE
520 ****************************************************************************/
522 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
524 WERROR status = WERR_OK;
525 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
532 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
534 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
535 status = WERR_NO_MORE_ITEMS;
539 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
541 /* subkey has the string name now */
543 init_reg_r_enum_val( r_u, val );
546 free_registry_value( val );
552 /*******************************************************************
554 ********************************************************************/
556 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
558 REG_Q_SHUTDOWN_EX q_u_ex;
559 REG_R_SHUTDOWN_EX r_u_ex;
561 /* copy fields (including stealing memory) */
563 q_u_ex.server = q_u->server;
564 q_u_ex.message = q_u->message;
565 q_u_ex.timeout = q_u->timeout;
566 q_u_ex.force = q_u->force;
567 q_u_ex.reboot = q_u->reboot;
568 q_u_ex.reason = 0x0; /* don't care for now */
570 /* thunk down to _reg_shutdown_ex() (just returns a status) */
572 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
575 /*******************************************************************
577 ********************************************************************/
579 #define SHUTDOWN_R_STRING "-r"
580 #define SHUTDOWN_F_STRING "-f"
583 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
585 pstring shutdown_script;
596 pstrcpy(shutdown_script, lp_shutdown_script());
598 if ( !*shutdown_script )
599 return WERR_ACCESS_DENIED;
601 /* pull the message string and perform necessary sanity checks on it */
603 pstrcpy( message, "" );
604 if ( q_u->message ) {
605 UNISTR2 *msg_string = q_u->message->string;
607 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
609 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
611 fstr_sprintf(timeout, "%d", q_u->timeout);
612 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
613 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
614 fstr_sprintf( reason, "%d", q_u->reason );
616 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
617 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
618 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
619 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
620 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
622 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
624 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
625 Take the error return from the script and provide it as the Windows return code. */
627 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
632 ret = smbrun( shutdown_script, NULL );
637 /********** END SeRemoteShutdownPrivilege BLOCK **********/
639 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
640 shutdown_script, ret));
643 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
649 /*******************************************************************
651 ********************************************************************/
653 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
655 pstring abort_shutdown_script;
659 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
661 if ( !*abort_shutdown_script )
662 return WERR_ACCESS_DENIED;
664 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
666 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
671 ret = smbrun( abort_shutdown_script, NULL );
676 /********** END SeRemoteShutdownPrivilege BLOCK **********/
678 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
679 abort_shutdown_script, ret));
682 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
685 /*******************************************************************
686 ********************************************************************/
688 static int validate_reg_filename( pstring fname )
691 int num_services = lp_numservices();
696 /* convert to a unix path, stripping the C:\ along the way */
698 if ( !(p = valid_share_pathname( fname ) ))
701 /* has to exist within a valid file share */
703 for ( snum=0; snum<num_services; snum++ ) {
705 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
708 pstrcpy( share_path, lp_pathname(snum) );
710 /* make sure we have a path (e.g. [homes] ) */
712 if ( strlen( share_path ) == 0 )
715 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
719 /* p and fname are overlapping memory so copy out and back in again */
721 pstrcpy( unix_fname, p );
722 pstrcpy( fname, unix_fname );
724 return (snum < num_services) ? snum : -1;
727 /*******************************************************************
728 Note: topkeypat is the *full* path that this *key will be
729 loaded into (including the name of the key)
730 ********************************************************************/
732 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
736 REGISTRY_KEY registry_key;
738 REGSUBKEY_CTR *subkeys;
741 WERROR result = WERR_OK;
743 /* initialize the REGISTRY_KEY structure */
745 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
746 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
750 pstrcpy( registry_key.name, topkeypath );
752 /* now start parsing the values and subkeys */
754 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
757 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
760 /* copy values into the REGVAL_CTR */
762 for ( i=0; i<key->num_values; i++ ) {
763 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
764 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
767 /* copy subkeys into the REGSUBKEY_CTR */
769 key->subkey_index = 0;
770 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
771 regsubkey_ctr_addkey( subkeys, subkey->keyname );
774 /* write this key and values out */
776 if ( !store_reg_values( ®istry_key, values )
777 || !store_reg_keys( ®istry_key, subkeys ) )
779 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
780 result = WERR_REG_IO_FAILURE;
783 TALLOC_FREE( subkeys );
785 if ( !W_ERROR_IS_OK(result) )
788 /* now continue to load each subkey registry tree */
790 key->subkey_index = 0;
791 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
792 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
793 result = reg_load_tree( regfile, path, subkey );
794 if ( !W_ERROR_IS_OK(result) )
801 /*******************************************************************
802 ********************************************************************/
804 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
807 REGF_NK_REC *rootkey;
810 /* open the registry file....fail if the file already exists */
812 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
813 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
814 fname, strerror(errno) ));
815 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
818 /* get the rootkey from the regf file and then load the tree
819 via recursive calls */
821 if ( !(rootkey = regfio_rootkey( regfile )) )
822 return WERR_REG_FILE_INVALID;
824 result = reg_load_tree( regfile, krecord->name, rootkey );
828 regfio_close( regfile );
833 /*******************************************************************
834 ********************************************************************/
836 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
838 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
845 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
847 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
849 if ( (snum = validate_reg_filename( filename )) == -1 )
850 return WERR_OBJECT_PATH_INVALID;
852 /* user must posses SeRestorePrivilege for this this proceed */
854 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
855 return WERR_ACCESS_DENIED;
857 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
859 return restore_registry_key( regkey, filename );
862 /********************************************************************
863 ********************************************************************/
865 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
866 REGF_NK_REC *parent, SEC_DESC *sec_desc )
870 REGSUBKEY_CTR *subkeys;
873 char *keyname, *parentpath;
876 REGISTRY_KEY registry_key;
877 WERROR result = WERR_OK;
880 return WERR_GENERAL_FAILURE;
883 return WERR_OBJECT_PATH_INVALID;
885 /* split up the registry key path */
887 pstrcpy( key_tmp, keypath );
888 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
889 return WERR_OBJECT_PATH_INVALID;
892 keyname = parentpath;
894 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
896 ZERO_STRUCT( registry_key );
897 pstrcpy( registry_key.name, keypath );
898 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
902 /* lookup the values and subkeys */
904 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
907 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
910 fetch_reg_keys( ®istry_key, subkeys );
911 fetch_reg_values( ®istry_key, values );
913 /* write out this key */
915 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
916 result = WERR_CAN_NOT_COMPLETE;
920 /* write each one of the subkeys out */
922 num_subkeys = regsubkey_ctr_numkeys( subkeys );
923 for ( i=0; i<num_subkeys; i++ ) {
924 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
925 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
926 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
927 if ( !W_ERROR_IS_OK(result) )
931 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
934 TALLOC_FREE( subkeys );
939 /*******************************************************************
940 ********************************************************************/
942 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
944 DOM_SID adm_sid, owner_sid;
945 SEC_ACE ace[2]; /* at most 2 entries */
950 /* set the owner to BUILTIN\Administrator */
952 sid_copy(&owner_sid, &global_sid_Builtin);
953 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
956 /* basic access for Everyone */
958 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
959 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
961 /* add Full Access 'BUILTIN\Administrators' */
963 init_sec_access(&mask, reg_generic_map.generic_all);
964 sid_copy(&adm_sid, &global_sid_Builtin);
965 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
966 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
968 /* create the security descriptor */
970 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
973 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
979 /*******************************************************************
980 ********************************************************************/
982 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
988 /* open the registry file....fail if the file already exists */
990 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
991 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
992 fname, strerror(errno) ));
993 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
996 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
997 regfio_close( regfile );
1001 /* write the registry tree to the file */
1003 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1007 regfio_close( regfile );
1012 /*******************************************************************
1013 ********************************************************************/
1015 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1017 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1024 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1026 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1028 if ( (snum = validate_reg_filename( filename )) == -1 )
1029 return WERR_OBJECT_PATH_INVALID;
1031 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1033 return backup_registry_key( regkey, filename );
1036 /*******************************************************************
1037 ********************************************************************/
1039 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1041 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1042 REGISTRY_KEY *newparentinfo, *keyinfo;
1043 POLICY_HND newparent_handle;
1044 REGSUBKEY_CTR *subkeys;
1052 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1054 /* ok. Here's what we do. */
1056 if ( strrchr( name, '\\' ) ) {
1060 /* (1) check for enumerate rights on the parent handle. CLients can try
1061 create things like 'SOFTWARE\Samba' on the HKLM handle.
1062 (2) open the path to the child parent key if necessary */
1064 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1065 return WERR_ACCESS_DENIED;
1067 pstrcpy( newkeyname, name );
1068 ptr = strrchr( newkeyname, '\\' );
1071 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1072 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1074 if ( !W_ERROR_IS_OK(result) )
1077 /* copy the new key name (just the lower most keyname) */
1079 pstrcpy( name, ptr+1 );
1082 /* use the existing open key information */
1083 newparentinfo = parent;
1084 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1087 /* (3) check for create subkey rights on the correct parent */
1089 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1090 result = WERR_ACCESS_DENIED;
1094 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1095 result = WERR_NOMEM;
1099 /* (4) lookup the current keys and add the new one */
1101 fetch_reg_keys( newparentinfo, subkeys );
1102 regsubkey_ctr_addkey( subkeys, name );
1104 /* now write to the registry backend */
1106 write_result = store_reg_keys( newparentinfo, subkeys );
1108 TALLOC_FREE( subkeys );
1110 if ( !write_result )
1111 return WERR_REG_IO_FAILURE;
1113 /* (5) open the new key and return the handle. Note that it is probably
1114 not correct to grant full access on this open handle. */
1116 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1117 keyinfo->access_granted = REG_KEY_ALL;
1120 /* close any intermediate key handles */
1122 if ( newparentinfo != parent )
1123 close_registry_key( p, &newparent_handle );
1129 /*******************************************************************
1130 ********************************************************************/
1132 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1134 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1142 /* access checks first */
1144 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1145 return WERR_ACCESS_DENIED;
1147 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1149 /* verify the name */
1152 return WERR_INVALID_PARAM;
1154 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1156 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1159 /* lookup the current values and add the new one */
1161 fetch_reg_values( key, values );
1163 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
1165 /* now write to the registry backend */
1167 write_result = store_reg_values( key, values );
1169 TALLOC_FREE( values );
1171 if ( !write_result )
1172 return WERR_REG_IO_FAILURE;
1177 /*******************************************************************
1178 ********************************************************************/
1180 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1182 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1183 REGISTRY_KEY *newparentinfo;
1184 POLICY_HND newparent_handle;
1185 REGSUBKEY_CTR *subkeys;
1193 /* MSDN says parent the handle must have been opened with DELETE access */
1195 /* (1) check for delete rights on the parent */
1197 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1198 result = WERR_ACCESS_DENIED;
1202 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1204 /* ok. Here's what we do. */
1206 if ( strrchr( name, '\\' ) ) {
1210 /* (2) open the path to the child parent key if necessary */
1211 /* split the registry path and save the subkeyname */
1213 pstrcpy( newkeyname, name );
1214 ptr = strrchr( newkeyname, '\\' );
1216 pstrcpy( name, ptr+1 );
1218 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1219 if ( !W_ERROR_IS_OK(result) )
1223 /* use the existing open key information */
1224 newparentinfo = parent;
1227 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1228 result = WERR_NOMEM;
1232 /* lookup the current keys and delete the new one */
1234 fetch_reg_keys( newparentinfo, subkeys );
1236 regsubkey_ctr_delkey( subkeys, name );
1238 /* now write to the registry backend */
1240 write_result = store_reg_keys( newparentinfo, subkeys );
1242 TALLOC_FREE( subkeys );
1244 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1247 /* close any intermediate key handles */
1249 if ( newparentinfo != parent )
1250 close_registry_key( p, &newparent_handle );
1256 /*******************************************************************
1257 ********************************************************************/
1259 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1261 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1269 /* access checks first */
1271 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1272 return WERR_ACCESS_DENIED;
1274 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1277 return WERR_INVALID_PARAM;
1279 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1281 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1284 /* lookup the current values and add the new one */
1286 fetch_reg_values( key, values );
1288 regval_ctr_delvalue( values, valuename );
1290 /* now write to the registry backend */
1292 write_result = store_reg_values( key, values );
1294 TALLOC_FREE( values );
1296 if ( !write_result )
1297 return WERR_REG_IO_FAILURE;
1302 /*******************************************************************
1303 ********************************************************************/
1305 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1307 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1312 /* access checks first */
1314 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1315 return WERR_ACCESS_DENIED;
1317 return WERR_ACCESS_DENIED;
1320 /*******************************************************************
1321 ********************************************************************/
1323 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1325 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1330 /* access checks first */
1332 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1333 return WERR_ACCESS_DENIED;
1335 return WERR_ACCESS_DENIED;