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 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 *)®key
)) {
55 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
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
)
77 WERROR result
= WERR_OK
;
79 /* create a full registry path and strip any trailing '\'
82 pstr_sprintf( keypath
, "%s%s%s",
83 parent
? parent
->name
: "",
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
) )
97 if ( !create_policy_hnd( p
, hnd
, free_regkey_info
, *keyinfo
) ) {
98 result
= WERR_BADFILE
;
99 regkey_close_internal( *keyinfo
);
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
);
115 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
119 close_policy_hnd(p
, hnd
);
124 /********************************************************************
125 retrieve information about the subkeys
126 *******************************************************************/
128 static BOOL
get_subkey_information( REGISTRY_KEY
*key
, uint32
*maxnum
, uint32
*maxlen
)
132 REGSUBKEY_CTR
*subkeys
;
138 if ( !(subkeys
= TALLOC_ZERO_P( NULL
, REGSUBKEY_CTR
)) )
141 if ( fetch_reg_keys( key
, subkeys
) == -1 )
144 /* find the longest string */
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
;
157 TALLOC_FREE( subkeys
);
162 /********************************************************************
163 retrieve information about the values.
164 *******************************************************************/
166 static BOOL
get_value_information( REGISTRY_KEY
*key
, uint32
*maxnum
,
167 uint32
*maxlen
, uint32
*maxsize
)
171 uint32 sizemax
, lenmax
;
177 if ( !(values
= TALLOC_ZERO_P( NULL
, REGVAL_CTR
)) )
180 if ( fetch_reg_values( key
, values
) == -1 )
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
;
200 TALLOC_FREE( values
);
206 /********************************************************************
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
))
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 /*******************************************************************
272 ********************************************************************/
274 WERROR
_reg_open_entry(pipes_struct
*p
, REG_Q_OPEN_ENTRY
*q_u
, REG_R_OPEN_ENTRY
*r_u
)
277 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->pol
);
278 REGISTRY_KEY
*newkey
= NULL
;
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 /*******************************************************************
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
;
316 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
317 REGISTRY_VALUE
*val
= NULL
;
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
)) )
334 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
335 if(regkey
->type
== REG_KEY_HKPD
)
337 if(strequal(name
, "Global"))
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"))
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));
368 else if(strequal(name
, "Explain 009"))
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));
388 else if(isdigit(name
[0]))
390 /* we probably have a request for a specific object here */
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
);
403 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name
));
407 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
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
));
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
);
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
);
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
);
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
);
477 r_u
->win_version
= 0x00000005; /* Windows 2000 registry API version */
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
);
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
;
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
);
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
);
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
;
537 #if 0 /* JERRY TEST CODE */
538 if ( val
->type
== REG_MULTI_SZ
) {
540 int num_strings
= regval_convert_multi_sz( (uint16
*)regval_data_p(val
), regval_size(val
), &str
);
546 buf_size
= regval_build_multi_sz( str
, &buffer
);
549 TALLOC_FREE( buffer
);
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
);
560 free_registry_value( val
);
566 /*******************************************************************
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 /*******************************************************************
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
;
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 **********/
646 ret
= smbrun( shutdown_script
, NULL
);
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 /*******************************************************************
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
;
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 **********/
685 ret
= smbrun( abort_shutdown_script
, NULL
);
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
)
705 int num_services
= lp_numservices();
710 /* convert to a unix path, stripping the C:\ along the way */
712 if ( !(p
= valid_share_pathname( fname
) ))
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
) )
722 pstrcpy( share_path
, lp_pathname(snum
) );
724 /* make sure we have a path (e.g. [homes] ) */
726 if ( strlen( share_path
) == 0 )
729 if ( strncmp( share_path
, p
, strlen( share_path
)) == 0 )
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
,
750 REGISTRY_KEY registry_key
;
752 REGSUBKEY_CTR
*subkeys
;
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",
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
)) )
771 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
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( ®istry_key
, values
)
791 || !store_reg_keys( ®istry_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
) )
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
) )
815 /*******************************************************************
816 ********************************************************************/
818 static WERROR
restore_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
821 REGF_NK_REC
*rootkey
;
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
);
844 regfio_close( regfile
);
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
);
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
)
886 REGSUBKEY_CTR
*subkeys
;
889 char *keyname
, *parentpath
;
892 REGISTRY_KEY registry_key
;
893 WERROR result
= WERR_OK
;
896 return WERR_GENERAL_FAILURE
;
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
;
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
)) )
918 /* lookup the values and subkeys */
920 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
923 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
926 fetch_reg_keys( ®istry_key
, subkeys
);
927 fetch_reg_values( ®istry_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
;
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
) )
947 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath
));
950 TALLOC_FREE( subkeys
);
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 */
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
)
989 if ((*psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, &owner_sid
, NULL
, NULL
, psa
, &sd_size
)) == NULL
)
995 /*******************************************************************
996 ********************************************************************/
998 static WERROR
backup_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
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
);
1017 /* write the registry tree to the file */
1019 result
= reg_write_tree( regfile
, krecord
->name
, NULL
, sd
);
1023 regfio_close( regfile
);
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
);
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
;
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
, '\\' ) ) {
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
, '\\' );
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
) )
1093 /* copy the new key name (just the lower most keyname) */
1095 pstrcpy( name
, ptr
+1 );
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
;
1110 if ( !(subkeys
= TALLOC_ZERO_P( p
->mem_ctx
, REGSUBKEY_CTR
)) ) {
1111 result
= WERR_NOMEM
;
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
;
1136 /* close any intermediate key handles */
1138 if ( newparentinfo
!= parent
)
1139 close_registry_key( p
, &newparent_handle
);
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
);
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 */
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
)) )
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
;
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
;
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
;
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
, '\\' ) ) {
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
, '\\' );
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
) )
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
;
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
;
1263 /* close any intermediate key handles */
1265 if ( newparentinfo
!= parent
)
1266 close_registry_key( p
, &newparent_handle
);
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
);
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 );
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
)) )
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
;
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
);
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
);
1346 /* access checks first */
1348 if ( !(key
->access_granted
& STD_RIGHT_WRITE_DAC_ACCESS
) )
1349 return WERR_ACCESS_DENIED
;
1351 return WERR_ACCESS_DENIED
;