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())
37 static struct generic_mapping reg_generic_map
= { REG_KEY_READ
, REG_KEY_WRITE
, REG_KEY_EXECUTE
, REG_KEY_ALL
};
39 /********************************************************************
40 ********************************************************************/
42 NTSTATUS
registry_access_check( SEC_DESC
*sec_desc
, NT_USER_TOKEN
*token
,
43 uint32 access_desired
, uint32
*access_granted
)
47 se_map_generic( &access_desired
, ®_generic_map
);
48 se_access_check( sec_desc
, token
, access_desired
, access_granted
, &result
);
53 /********************************************************************
54 ********************************************************************/
56 SEC_DESC
* construct_registry_sd( TALLOC_CTX
*ctx
)
65 /* basic access for Everyone */
67 init_sec_access(&mask
, REG_KEY_READ
);
68 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
70 /* Full Access 'BUILTIN\Administrators' */
72 init_sec_access(&mask
, REG_KEY_ALL
);
73 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
76 /* create the security descriptor */
78 if ( !(acl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
81 if ( !(sd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
, acl
, &sd_size
)) )
87 /******************************************************************
88 free() function for REGISTRY_KEY
89 *****************************************************************/
91 static void free_regkey_info(void *ptr
)
93 REGISTRY_KEY
*info
= (REGISTRY_KEY
*)ptr
;
98 /******************************************************************
99 Find a registry key handle and return a REGISTRY_KEY
100 *****************************************************************/
102 static REGISTRY_KEY
*find_regkey_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
104 REGISTRY_KEY
*regkey
= NULL
;
106 if(!find_policy_by_hnd(p
,hnd
,(void **)®key
)) {
107 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
115 /*******************************************************************
116 Function for open a new registry handle and creating a handle
117 Note that P should be valid & hnd should already have space
119 When we open a key, we store the full path to the key as
120 HK[LM|U]\<key>\<key>\...
121 *******************************************************************/
123 static WERROR
open_registry_key(pipes_struct
*p
, POLICY_HND
*hnd
, REGISTRY_KEY
*parent
,
124 const char *subkeyname
, uint32 access_granted
)
126 REGISTRY_KEY
*regkey
= NULL
;
127 WERROR result
= WERR_OK
;
128 REGSUBKEY_CTR subkeys
;
132 DEBUG(7,("open_registry_key: name = [%s][%s]\n",
133 parent
? parent
->name
: "NULL", subkeyname
));
135 /* strip any trailing '\'s */
136 pstrcpy( subkeyname2
, subkeyname
);
137 subkey_len
= strlen ( subkeyname2
);
138 if ( subkey_len
&& subkeyname2
[subkey_len
-1] == '\\' )
139 subkeyname2
[subkey_len
-1] = '\0';
141 if ((regkey
=SMB_MALLOC_P(REGISTRY_KEY
)) == NULL
)
144 ZERO_STRUCTP( regkey
);
147 * very crazy, but regedit.exe on Win2k will attempt to call
148 * REG_OPEN_ENTRY with a keyname of "". We should return a new
149 * (second) handle here on the key->name. regedt32.exe does
150 * not do this stupidity. --jerry
154 pstrcpy( regkey
->name
, parent
->name
);
157 pstrcpy( regkey
->name
, "" );
159 pstrcat( regkey
->name
, parent
->name
);
160 pstrcat( regkey
->name
, "\\" );
162 pstrcat( regkey
->name
, subkeyname2
);
165 /* Look up the table of registry I/O operations */
167 if ( !(regkey
->hook
= reghook_cache_find( regkey
->name
)) ) {
168 DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
173 /* check if the path really exists; failed is indicated by -1 */
174 /* if the subkey count failed, bail out */
176 regsubkey_ctr_init( &subkeys
);
178 if ( fetch_reg_keys( regkey
, &subkeys
) == -1 ) {
179 result
= WERR_BADFILE
;
183 if ( !create_policy_hnd( p
, hnd
, free_regkey_info
, regkey
) ) {
184 result
= WERR_BADFILE
;
188 /* save the access mask */
190 regkey
->access_granted
= access_granted
;
195 regsubkey_ctr_destroy( &subkeys
);
197 if ( ! NT_STATUS_IS_OK(result
) )
200 DEBUG(7,("open_registry_key: exit\n"));
205 /*******************************************************************
206 Function for open a new registry handle and creating a handle
207 Note that P should be valid & hnd should already have space
208 *******************************************************************/
210 static BOOL
close_registry_key(pipes_struct
*p
, POLICY_HND
*hnd
)
212 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd(p
, hnd
);
215 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
219 close_policy_hnd(p
, hnd
);
224 /********************************************************************
225 retrieve information about the subkeys
226 *******************************************************************/
228 static BOOL
get_subkey_information( REGISTRY_KEY
*key
, uint32
*maxnum
, uint32
*maxlen
)
232 REGSUBKEY_CTR subkeys
;
238 regsubkey_ctr_init( &subkeys
);
240 if ( fetch_reg_keys( key
, &subkeys
) == -1 )
243 /* find the longest string */
246 num_subkeys
= regsubkey_ctr_numkeys( &subkeys
);
248 for ( i
=0; i
<num_subkeys
; i
++ ) {
249 len
= strlen( regsubkey_ctr_specific_key(&subkeys
, i
) );
250 max_len
= MAX(max_len
, len
);
253 *maxnum
= num_subkeys
;
256 regsubkey_ctr_destroy( &subkeys
);
261 /********************************************************************
262 retrieve information about the values.
263 *******************************************************************/
265 static BOOL
get_value_information( REGISTRY_KEY
*key
, uint32
*maxnum
,
266 uint32
*maxlen
, uint32
*maxsize
)
270 uint32 sizemax
, lenmax
;
276 regval_ctr_init( &values
);
278 if ( fetch_reg_values( key
, &values
) == -1 )
281 lenmax
= sizemax
= 0;
282 num_values
= regval_ctr_numvals( &values
);
284 val
= regval_ctr_specific_value( &values
, 0 );
286 for ( i
=0; i
<num_values
&& val
; i
++ )
288 lenmax
= MAX(lenmax
, val
->valuename
? strlen(val
->valuename
)+1 : 0 );
289 sizemax
= MAX(sizemax
, val
->size
);
291 val
= regval_ctr_specific_value( &values
, i
);
294 *maxnum
= num_values
;
298 regval_ctr_destroy( &values
);
304 /********************************************************************
306 ********************************************************************/
308 WERROR
_reg_close(pipes_struct
*p
, REG_Q_CLOSE
*q_u
, REG_R_CLOSE
*r_u
)
310 /* close the policy handle */
312 if (!close_registry_key(p
, &q_u
->pol
))
318 /*******************************************************************
319 ********************************************************************/
321 WERROR
_reg_open_hklm(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
324 uint32 access_granted
= 0;
327 /* perform access checks */
328 /* top level keys are done here without passing through the REGISTRY_HOOK api */
330 if ( !(sec_desc
= construct_registry_sd( p
->mem_ctx
)) )
333 status
= registry_access_check( sec_desc
, p
->pipe_user
.nt_user_token
, q_u
->access
, &access_granted
);
334 if ( !NT_STATUS_IS_OK(status
) )
335 return ntstatus_to_werror( status
);
337 return open_registry_key( p
, &r_u
->pol
, NULL
, KEY_HKLM
, access_granted
);
340 /*******************************************************************
341 ********************************************************************/
343 WERROR
_reg_open_hkcr(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
346 uint32 access_granted
= 0;
349 /* perform access checks */
350 /* top level keys are done here without passing through the REGISTRY_HOOK api */
352 if ( !(sec_desc
= construct_registry_sd( p
->mem_ctx
)) )
355 status
= registry_access_check( sec_desc
, p
->pipe_user
.nt_user_token
, q_u
->access
, &access_granted
);
356 if ( !NT_STATUS_IS_OK(status
) )
357 return ntstatus_to_werror( status
);
359 return open_registry_key( p
, &r_u
->pol
, NULL
, KEY_HKCR
, access_granted
);
362 /*******************************************************************
363 ********************************************************************/
365 WERROR
_reg_open_hku(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
368 uint32 access_granted
= 0;
371 /* perform access checks */
372 /* top level keys are done here without passing through the REGISTRY_HOOK api */
374 if ( !(sec_desc
= construct_registry_sd( p
->mem_ctx
)) )
377 status
= registry_access_check( sec_desc
, p
->pipe_user
.nt_user_token
, q_u
->access
, &access_granted
);
378 if ( !NT_STATUS_IS_OK(status
) )
379 return ntstatus_to_werror( status
);
381 return open_registry_key( p
, &r_u
->pol
, NULL
, KEY_HKU
, access_granted
);
384 /*******************************************************************
386 ********************************************************************/
388 WERROR
_reg_open_entry(pipes_struct
*p
, REG_Q_OPEN_ENTRY
*q_u
, REG_R_OPEN_ENTRY
*r_u
)
391 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->pol
);
392 REGISTRY_KEY
*newkey
;
393 uint32 access_granted
;
396 DEBUG(5,("reg_open_entry: Enter\n"));
401 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
403 /* check granted access first; what is the correct mask here? */
405 if ( !(parent
->access_granted
& (SEC_RIGHTS_ENUM_SUBKEYS
|SEC_RIGHTS_CREATE_SUBKEY
)) )
406 return WERR_ACCESS_DENIED
;
408 /* open the key first to get the appropriate REGISTRY_HOOK
409 and then check the premissions */
411 if ( !W_ERROR_IS_OK(result
= open_registry_key( p
, &r_u
->handle
, parent
, name
, 0 )) )
414 newkey
= find_regkey_index_by_hnd(p
, &r_u
->handle
);
416 /* finally allow the backend to check the access for the requested key */
418 if ( !regkey_access_check( newkey
, q_u
->access
, &access_granted
, p
->pipe_user
.nt_user_token
) ) {
419 close_registry_key( p
, &r_u
->handle
);
420 return WERR_ACCESS_DENIED
;
423 /* if successful, save the granted access mask */
425 newkey
->access_granted
= access_granted
;
430 /*******************************************************************
432 ********************************************************************/
434 WERROR
_reg_query_value(pipes_struct
*p
, REG_Q_QUERY_VALUE
*q_u
, REG_R_QUERY_VALUE
*r_u
)
436 WERROR status
= WERR_BADFILE
;
438 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
439 REGISTRY_VALUE
*val
= NULL
;
443 DEBUG(5,("_reg_info: Enter\n"));
448 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey
->name
));
450 rpcstr_pull(name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0);
452 DEBUG(5,("reg_info: looking up value: [%s]\n", name
));
454 regval_ctr_init( ®vals
);
456 for ( i
=0; fetch_reg_values_specific(regkey
, &val
, i
); i
++ )
458 DEBUG(10,("_reg_info: Testing value [%s]\n", val
->valuename
));
459 if ( strequal( val
->valuename
, name
) ) {
460 DEBUG(10,("_reg_info: Found match for value [%s]\n", name
));
465 free_registry_value( val
);
468 init_reg_r_query_value(q_u
->ptr_buf
, r_u
, val
, status
);
470 regval_ctr_destroy( ®vals
);
471 free_registry_value( val
);
473 DEBUG(5,("_reg_info: Exit\n"));
479 /*****************************************************************************
480 Implementation of REG_QUERY_KEY
481 ****************************************************************************/
483 WERROR
_reg_query_key(pipes_struct
*p
, REG_Q_QUERY_KEY
*q_u
, REG_R_QUERY_KEY
*r_u
)
485 WERROR status
= WERR_OK
;
486 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
488 DEBUG(5,("_reg_query_key: Enter\n"));
493 if ( !get_subkey_information( regkey
, &r_u
->num_subkeys
, &r_u
->max_subkeylen
) ) {
494 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
495 return WERR_ACCESS_DENIED
;
498 if ( !get_value_information( regkey
, &r_u
->num_values
, &r_u
->max_valnamelen
, &r_u
->max_valbufsize
) ) {
499 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
500 return WERR_ACCESS_DENIED
;
504 r_u
->sec_desc
= 0x00000078; /* size for key's sec_desc */
506 /* Win9x set this to 0x0 since it does not keep timestamps.
507 Doing the same here for simplicity --jerry */
509 ZERO_STRUCT(r_u
->mod_time
);
511 DEBUG(5,("_reg_query_key: Exit\n"));
517 /*****************************************************************************
518 Implementation of REG_GETVERSION
519 ****************************************************************************/
521 WERROR
_reg_getversion(pipes_struct
*p
, REG_Q_GETVERSION
*q_u
, REG_R_GETVERSION
*r_u
)
523 WERROR status
= WERR_OK
;
524 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
526 DEBUG(5,("_reg_getversion: Enter\n"));
531 r_u
->win_version
= 0x00000005; /* Windows 2000 registry API version */
533 DEBUG(5,("_reg_getversion: Exit\n"));
539 /*****************************************************************************
540 Implementation of REG_ENUM_KEY
541 ****************************************************************************/
543 WERROR
_reg_enum_key(pipes_struct
*p
, REG_Q_ENUM_KEY
*q_u
, REG_R_ENUM_KEY
*r_u
)
545 WERROR status
= WERR_OK
;
546 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
550 DEBUG(5,("_reg_enum_key: Enter\n"));
555 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey
->name
));
557 if ( !fetch_reg_keys_specific( regkey
, &subkey
, q_u
->key_index
) )
559 status
= WERR_NO_MORE_ITEMS
;
563 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey
));
565 /* subkey has the string name now */
567 init_reg_r_enum_key( r_u
, subkey
);
569 DEBUG(5,("_reg_enum_key: Exit\n"));
576 /*****************************************************************************
577 Implementation of REG_ENUM_VALUE
578 ****************************************************************************/
580 WERROR
_reg_enum_value(pipes_struct
*p
, REG_Q_ENUM_VALUE
*q_u
, REG_R_ENUM_VALUE
*r_u
)
582 WERROR status
= WERR_OK
;
583 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
587 DEBUG(5,("_reg_enum_value: Enter\n"));
592 DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey
->name
));
594 if ( !fetch_reg_values_specific( regkey
, &val
, q_u
->val_index
) ) {
595 status
= WERR_NO_MORE_ITEMS
;
599 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val
->valuename
));
601 /* subkey has the string name now */
603 init_reg_r_enum_val( r_u
, val
);
606 DEBUG(5,("_reg_enum_value: Exit\n"));
609 free_registry_value( val
);
615 /*******************************************************************
617 ********************************************************************/
619 WERROR
_reg_shutdown(pipes_struct
*p
, REG_Q_SHUTDOWN
*q_u
, REG_R_SHUTDOWN
*r_u
)
621 REG_Q_SHUTDOWN_EX q_u_ex
;
622 REG_R_SHUTDOWN_EX r_u_ex
;
624 /* copy fields (including stealing memory) */
626 q_u_ex
.server
= q_u
->server
;
627 q_u_ex
.message
= q_u
->message
;
628 q_u_ex
.timeout
= q_u
->timeout
;
629 q_u_ex
.force
= q_u
->force
;
630 q_u_ex
.reboot
= q_u
->reboot
;
631 q_u_ex
.reason
= 0x0; /* don't care for now */
633 /* thunk down to _reg_shutdown_ex() (just returns a status) */
635 return _reg_shutdown_ex( p
, &q_u_ex
, &r_u_ex
);
638 /*******************************************************************
640 ********************************************************************/
642 #define SHUTDOWN_R_STRING "-r"
643 #define SHUTDOWN_F_STRING "-f"
646 WERROR
_reg_shutdown_ex(pipes_struct
*p
, REG_Q_SHUTDOWN_EX
*q_u
, REG_R_SHUTDOWN_EX
*r_u
)
648 pstring shutdown_script
;
659 pstrcpy(shutdown_script
, lp_shutdown_script());
661 if ( !*shutdown_script
)
662 return WERR_ACCESS_DENIED
;
664 /* pull the message string and perform necessary sanity checks on it */
666 pstrcpy( message
, "" );
667 if ( q_u
->message
) {
668 UNISTR2
*msg_string
= q_u
->message
->string
;
670 rpcstr_pull( message
, msg_string
->buffer
, sizeof(message
), msg_string
->uni_str_len
*2, 0 );
672 alpha_strcpy (chkmsg
, message
, NULL
, sizeof(message
));
674 fstr_sprintf(timeout
, "%d", q_u
->timeout
);
675 fstr_sprintf(r
, (q_u
->reboot
) ? SHUTDOWN_R_STRING
: "");
676 fstr_sprintf(f
, (q_u
->force
) ? SHUTDOWN_F_STRING
: "");
677 fstr_sprintf( reason
, "%d", q_u
->reason
);
679 all_string_sub( shutdown_script
, "%z", chkmsg
, sizeof(shutdown_script
) );
680 all_string_sub( shutdown_script
, "%t", timeout
, sizeof(shutdown_script
) );
681 all_string_sub( shutdown_script
, "%r", r
, sizeof(shutdown_script
) );
682 all_string_sub( shutdown_script
, "%f", f
, sizeof(shutdown_script
) );
683 all_string_sub( shutdown_script
, "%x", reason
, sizeof(shutdown_script
) );
685 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
687 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
688 Take the error return from the script and provide it as the Windows return code. */
690 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
695 ret
= smbrun( shutdown_script
, NULL
);
700 /********** END SeRemoteShutdownPrivilege BLOCK **********/
702 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
703 shutdown_script
, ret
));
706 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
712 /*******************************************************************
714 ********************************************************************/
716 WERROR
_reg_abort_shutdown(pipes_struct
*p
, REG_Q_ABORT_SHUTDOWN
*q_u
, REG_R_ABORT_SHUTDOWN
*r_u
)
718 pstring abort_shutdown_script
;
722 pstrcpy(abort_shutdown_script
, lp_abort_shutdown_script());
724 if ( !*abort_shutdown_script
)
725 return WERR_ACCESS_DENIED
;
727 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
729 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
734 ret
= smbrun( abort_shutdown_script
, NULL
);
739 /********** END SeRemoteShutdownPrivilege BLOCK **********/
741 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
742 abort_shutdown_script
, ret
));
745 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
748 /*******************************************************************
749 ********************************************************************/
751 static int validate_reg_filename( pstring fname
)
754 int num_services
= lp_numservices();
759 /* convert to a unix path, stripping the C:\ along the way */
761 if ( !(p
= valid_share_pathname( fname
) ))
764 /* has to exist within a valid file share */
766 for ( snum
=0; snum
<num_services
; snum
++ ) {
768 if ( !lp_snum_ok(snum
) || lp_print_ok(snum
) )
771 pstrcpy( share_path
, lp_pathname(snum
) );
773 /* make sure we have a path (e.g. [homes] ) */
775 if ( strlen( share_path
) == 0 )
778 if ( strncmp( share_path
, p
, strlen( share_path
)) == 0 )
782 /* p and fname are overlapping memory so copy out and back in again */
784 pstrcpy( unix_fname
, p
);
785 pstrcpy( fname
, unix_fname
);
787 return (snum
< num_services
) ? snum
: -1;
790 /*******************************************************************
791 Note: topkeypat is the *full* path that this *key will be
792 loaded into (including the name of the key)
793 ********************************************************************/
795 static WERROR
reg_load_tree( REGF_FILE
*regfile
, const char *topkeypath
,
799 REGISTRY_KEY registry_key
;
801 REGSUBKEY_CTR subkeys
;
804 WERROR result
= WERR_OK
;
806 /* initialize the REGISTRY_KEY structure */
808 if ( !(registry_key
.hook
= reghook_cache_find(topkeypath
)) ) {
809 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
813 pstrcpy( registry_key
.name
, topkeypath
);
815 /* now start parsing the values and subkeys */
817 regsubkey_ctr_init( &subkeys
);
818 regval_ctr_init( &values
);
820 /* copy values into the REGVAL_CTR */
822 for ( i
=0; i
<key
->num_values
; i
++ ) {
823 regval_ctr_addvalue( &values
, key
->values
[i
].valuename
, key
->values
[i
].type
,
824 key
->values
[i
].data
, (key
->values
[i
].data_size
& ~VK_DATA_IN_OFFSET
) );
827 /* copy subkeys into the REGSUBKEY_CTR */
829 key
->subkey_index
= 0;
830 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
831 regsubkey_ctr_addkey( &subkeys
, subkey
->keyname
);
834 /* write this key and values out */
836 if ( !store_reg_values( ®istry_key
, &values
)
837 || !store_reg_keys( ®istry_key
, &subkeys
) )
839 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath
));
840 result
= WERR_REG_IO_FAILURE
;
843 regval_ctr_destroy( &values
);
844 regsubkey_ctr_destroy( &subkeys
);
846 if ( !W_ERROR_IS_OK(result
) )
849 /* now continue to load each subkey registry tree */
851 key
->subkey_index
= 0;
852 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
853 pstr_sprintf( path
, "%s%s%s", topkeypath
, "\\", subkey
->keyname
);
854 result
= reg_load_tree( regfile
, path
, subkey
);
855 if ( !W_ERROR_IS_OK(result
) )
862 /*******************************************************************
863 ********************************************************************/
865 static WERROR
restore_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
868 REGF_NK_REC
*rootkey
;
871 /* open the registry file....fail if the file already exists */
873 if ( !(regfile
= regfio_open( fname
, (O_RDONLY
), 0 )) ) {
874 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
875 fname
, strerror(errno
) ));
876 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
879 /* get the rootkey from the regf file and then load the tree
880 via recursive calls */
882 if ( !(rootkey
= regfio_rootkey( regfile
)) )
883 return WERR_REG_FILE_INVALID
;
885 result
= reg_load_tree( regfile
, krecord
->name
, rootkey
);
889 regfio_close( regfile
);
894 /*******************************************************************
895 ********************************************************************/
897 WERROR
_reg_restore_key(pipes_struct
*p
, REG_Q_RESTORE_KEY
*q_u
, REG_R_RESTORE_KEY
*r_u
)
899 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
903 DEBUG(5,("_reg_restore_key: Enter\n"));
908 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
910 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey
->name
, filename
));
912 if ( (snum
= validate_reg_filename( filename
)) == -1 )
913 return WERR_OBJECT_PATH_INVALID
;
915 /* user must posses SeRestorePrivilege for this this proceed */
917 if ( !user_has_privileges( p
->pipe_user
.nt_user_token
, &se_restore
) )
918 return WERR_ACCESS_DENIED
;
920 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
922 return restore_registry_key( regkey
, filename
);
925 /********************************************************************
926 ********************************************************************/
928 static WERROR
reg_write_tree( REGF_FILE
*regfile
, const char *keypath
,
929 REGF_NK_REC
*parent
, SEC_DESC
*sec_desc
)
933 REGSUBKEY_CTR subkeys
;
936 char *keyname
, *parentpath
;
939 REGISTRY_KEY registry_key
;
940 WERROR result
= WERR_OK
;
943 return WERR_GENERAL_FAILURE
;
946 return WERR_OBJECT_PATH_INVALID
;
948 /* split up the registry key path */
950 pstrcpy( key_tmp
, keypath
);
951 if ( !reg_split_key( key_tmp
, &parentpath
, &keyname
) )
952 return WERR_OBJECT_PATH_INVALID
;
955 keyname
= parentpath
;
957 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
959 ZERO_STRUCT( registry_key
);
960 pstrcpy( registry_key
.name
, keypath
);
961 if ( !(registry_key
.hook
= reghook_cache_find( registry_key
.name
)) )
965 /* lookup the values and subkeys */
967 regsubkey_ctr_init( &subkeys
);
968 regval_ctr_init( &values
);
970 fetch_reg_keys( ®istry_key
, &subkeys
);
971 fetch_reg_values( ®istry_key
, &values
);
973 /* write out this key */
975 if ( !(key
= regfio_write_key( regfile
, keyname
, &values
, &subkeys
, sec_desc
, parent
)) ) {
976 result
= WERR_CAN_NOT_COMPLETE
;
980 /* write each one of the subkeys out */
982 num_subkeys
= regsubkey_ctr_numkeys( &subkeys
);
983 for ( i
=0; i
<num_subkeys
; i
++ ) {
984 subkeyname
= regsubkey_ctr_specific_key( &subkeys
, i
);
985 pstr_sprintf( subkeypath
, "%s\\%s", keypath
, subkeyname
);
986 result
= reg_write_tree( regfile
, subkeypath
, key
, sec_desc
);
987 if ( !W_ERROR_IS_OK(result
) )
991 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath
));
994 regval_ctr_destroy( &values
);
995 regsubkey_ctr_destroy( &subkeys
);
1000 /*******************************************************************
1001 ********************************************************************/
1003 static WERROR
make_default_reg_sd( TALLOC_CTX
*ctx
, SEC_DESC
**psd
)
1005 DOM_SID adm_sid
, owner_sid
;
1006 SEC_ACE ace
[2]; /* at most 2 entries */
1008 SEC_ACL
*psa
= NULL
;
1011 /* set the owner to BUILTIN\Administrator */
1013 sid_copy(&owner_sid
, &global_sid_Builtin
);
1014 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
1017 /* basic access for Everyone */
1019 init_sec_access(&mask
, reg_generic_map
.generic_execute
| reg_generic_map
.generic_read
);
1020 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
1022 /* add Full Access 'BUILTIN\Administrators' */
1024 init_sec_access(&mask
, reg_generic_map
.generic_all
);
1025 sid_copy(&adm_sid
, &global_sid_Builtin
);
1026 sid_append_rid(&adm_sid
, BUILTIN_ALIAS_RID_ADMINS
);
1027 init_sec_ace(&ace
[1], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
1029 /* create the security descriptor */
1031 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 2, ace
)) == NULL
)
1034 if ((*psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, &owner_sid
, NULL
, NULL
, psa
, &sd_size
)) == NULL
)
1040 /*******************************************************************
1041 ********************************************************************/
1043 static WERROR
backup_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
1047 SEC_DESC
*sd
= NULL
;
1049 /* open the registry file....fail if the file already exists */
1051 if ( !(regfile
= regfio_open( fname
, (O_RDWR
|O_CREAT
|O_EXCL
), (S_IREAD
|S_IWRITE
) )) ) {
1052 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1053 fname
, strerror(errno
) ));
1054 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
1057 if ( !W_ERROR_IS_OK(result
= make_default_reg_sd( regfile
->mem_ctx
, &sd
)) ) {
1058 regfio_close( regfile
);
1062 /* write the registry tree to the file */
1064 result
= reg_write_tree( regfile
, krecord
->name
, NULL
, sd
);
1068 regfio_close( regfile
);
1073 /*******************************************************************
1074 ********************************************************************/
1076 WERROR
_reg_save_key(pipes_struct
*p
, REG_Q_SAVE_KEY
*q_u
, REG_R_SAVE_KEY
*r_u
)
1078 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
1082 DEBUG(5,("_reg_save_key: Enter\n"));
1087 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
1089 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey
->name
, filename
));
1091 if ( (snum
= validate_reg_filename( filename
)) == -1 )
1092 return WERR_OBJECT_PATH_INVALID
;
1094 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
1096 return backup_registry_key( regkey
, filename
);
1101 /*******************************************************************
1102 ********************************************************************/
1104 WERROR
_reg_create_key_ex(pipes_struct
*p
, REG_Q_CREATE_KEY_EX
*q_u
, REG_R_CREATE_KEY_EX
*r_u
)
1106 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1107 REGISTRY_KEY
*newparent
;
1108 POLICY_HND newparent_handle
;
1109 REGSUBKEY_CTR subkeys
;
1117 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1119 /* ok. Here's what we do. */
1121 if ( strrchr( name
, '\\' ) ) {
1124 uint32 access_granted
;
1126 /* (1) check for enumerate rights on the parent handle. CLients can try
1127 create things like 'SOFTWARE\Samba' on the HKLM handle.
1128 (2) open the path to the child parent key if necessary */
1130 if ( !(parent
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
) )
1131 return WERR_ACCESS_DENIED
;
1133 pstrcpy( newkeyname
, name
);
1134 ptr
= strrchr( newkeyname
, '\\' );
1137 result
= open_registry_key( p
, &newparent_handle
, parent
, newkeyname
, 0 );
1138 if ( !W_ERROR_IS_OK(result
) )
1141 newparent
= find_regkey_index_by_hnd(p
, &newparent_handle
);
1142 SMB_ASSERT( newparent
!= NULL
);
1144 if ( !regkey_access_check( newparent
, REG_KEY_READ
|REG_KEY_WRITE
, &access_granted
, p
->pipe_user
.nt_user_token
) ) {
1145 result
= WERR_ACCESS_DENIED
;
1149 newparent
->access_granted
= access_granted
;
1151 /* copy the new key name (just the lower most keyname) */
1153 pstrcpy( name
, ptr
+1 );
1156 /* use the existing open key information */
1158 memcpy( &newparent_handle
, &q_u
->handle
, sizeof(POLICY_HND
) );
1161 /* (3) check for create subkey rights on the correct parent */
1163 if ( !(newparent
->access_granted
& SEC_RIGHTS_CREATE_SUBKEY
) ) {
1164 result
= WERR_ACCESS_DENIED
;
1168 regsubkey_ctr_init( &subkeys
);
1170 /* (4) lookup the current keys and add the new one */
1172 fetch_reg_keys( newparent
, &subkeys
);
1173 regsubkey_ctr_addkey( &subkeys
, name
);
1175 /* now write to the registry backend */
1177 write_result
= store_reg_keys( newparent
, &subkeys
);
1179 regsubkey_ctr_destroy( &subkeys
);
1181 if ( !write_result
)
1182 return WERR_REG_IO_FAILURE
;
1184 /* (5) open the new key and return the handle. Note that it is probably
1185 not correct to grant full access on this open handle. We should pass
1186 the new open through the regkey_access_check() like we do for
1187 _reg_open_entry() but this is ok for now. */
1189 result
= open_registry_key( p
, &r_u
->handle
, newparent
, name
, REG_KEY_ALL
);
1192 /* close any intermediate key handles */
1194 if ( newparent
!= parent
)
1195 close_registry_key( p
, &newparent_handle
);
1201 /*******************************************************************
1202 ********************************************************************/
1204 WERROR
_reg_set_value(pipes_struct
*p
, REG_Q_SET_VALUE
*q_u
, REG_R_SET_VALUE
*r_u
)
1206 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1214 /* access checks first */
1216 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1217 return WERR_ACCESS_DENIED
;
1219 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1221 /* verify the name */
1224 return WERR_INVALID_PARAM
;
1226 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1228 regval_ctr_init( &values
);
1230 /* lookup the current values and add the new one */
1232 fetch_reg_values( key
, &values
);
1234 regval_ctr_addvalue( &values
, valuename
, q_u
->type
, q_u
->value
.buffer
, q_u
->value
.buf_len
);
1236 /* now write to the registry backend */
1238 write_result
= store_reg_values( key
, &values
);
1240 regval_ctr_destroy( &values
);
1242 if ( !write_result
)
1243 return WERR_REG_IO_FAILURE
;
1248 /*******************************************************************
1249 ********************************************************************/
1251 WERROR
_reg_delete_key(pipes_struct
*p
, REG_Q_DELETE_KEY
*q_u
, REG_R_DELETE_KEY
*r_u
)
1253 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1254 REGISTRY_KEY
*newparent
;
1255 POLICY_HND newparent_handle
;
1256 REGSUBKEY_CTR subkeys
;
1264 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1266 /* ok. Here's what we do. */
1268 if ( strrchr( name
, '\\' ) ) {
1271 uint32 access_granted
;
1273 /* (1) check for enumerate rights on the parent handle. CLients can try
1274 create things like 'SOFTWARE\Samba' on the HKLM handle.
1275 (2) open the path to the child parent key if necessary */
1277 if ( !(parent
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
) )
1278 return WERR_ACCESS_DENIED
;
1280 pstrcpy( newkeyname
, name
);
1281 ptr
= strrchr( newkeyname
, '\\' );
1284 result
= open_registry_key( p
, &newparent_handle
, parent
, newkeyname
, 0 );
1285 if ( !W_ERROR_IS_OK(result
) )
1288 newparent
= find_regkey_index_by_hnd(p
, &newparent_handle
);
1289 SMB_ASSERT( newparent
!= NULL
);
1291 if ( !regkey_access_check( newparent
, REG_KEY_READ
|REG_KEY_WRITE
, &access_granted
, p
->pipe_user
.nt_user_token
) ) {
1292 result
= WERR_ACCESS_DENIED
;
1296 newparent
->access_granted
= access_granted
;
1298 /* copy the new key name (just the lower most keyname) */
1300 pstrcpy( name
, ptr
+1 );
1303 /* use the existing open key information */
1305 memcpy( &newparent_handle
, &q_u
->handle
, sizeof(POLICY_HND
) );
1308 /* (3) check for create subkey rights on the correct parent */
1310 if ( !(newparent
->access_granted
& STD_RIGHT_DELETE_ACCESS
) ) {
1311 result
= WERR_ACCESS_DENIED
;
1315 regsubkey_ctr_init( &subkeys
);
1317 /* lookup the current keys and delete the new one */
1319 fetch_reg_keys( newparent
, &subkeys
);
1321 regsubkey_ctr_delkey( &subkeys
, name
);
1323 /* now write to the registry backend */
1325 write_result
= store_reg_keys( newparent
, &subkeys
);
1327 regsubkey_ctr_destroy( &subkeys
);
1329 result
= write_result
? WERR_OK
: WERR_REG_IO_FAILURE
;
1332 /* close any intermediate key handles */
1334 if ( newparent
!= parent
)
1335 close_registry_key( p
, &newparent_handle
);
1341 /*******************************************************************
1342 ********************************************************************/
1344 WERROR
_reg_delete_value(pipes_struct
*p
, REG_Q_DELETE_VALUE
*q_u
, REG_R_DELETE_VALUE
*r_u
)
1346 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1354 /* access checks first */
1356 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1357 return WERR_ACCESS_DENIED
;
1359 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1362 return WERR_INVALID_PARAM
;
1364 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1366 regval_ctr_init( &values
);
1368 /* lookup the current values and add the new one */
1370 fetch_reg_values( key
, &values
);
1372 regval_ctr_delvalue( &values
, valuename
);
1374 /* now write to the registry backend */
1376 write_result
= store_reg_values( key
, &values
);
1378 regval_ctr_destroy( &values
);
1380 if ( !write_result
)
1381 return WERR_REG_IO_FAILURE
;
1386 /*******************************************************************
1387 ********************************************************************/
1389 WERROR
_reg_get_key_sec(pipes_struct
*p
, REG_Q_GET_KEY_SEC
*q_u
, REG_R_GET_KEY_SEC
*r_u
)
1391 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1396 /* access checks first */
1398 if ( !(key
->access_granted
& STD_RIGHT_READ_CONTROL_ACCESS
) )
1399 return WERR_ACCESS_DENIED
;
1401 return WERR_ACCESS_DENIED
;
1404 /*******************************************************************
1405 ********************************************************************/
1407 WERROR
_reg_set_key_sec(pipes_struct
*p
, REG_Q_SET_KEY_SEC
*q_u
, REG_R_SET_KEY_SEC
*r_u
)
1409 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1414 /* access checks first */
1416 if ( !(key
->access_granted
& STD_RIGHT_WRITE_DAC_ACCESS
) )
1417 return WERR_ACCESS_DENIED
;
1419 return WERR_ACCESS_DENIED
;