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
;
399 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
401 /* check granted access first; what is the correct mask here? */
403 if ( !(parent
->access_granted
& (SEC_RIGHTS_ENUM_SUBKEYS
|SEC_RIGHTS_CREATE_SUBKEY
)) )
404 return WERR_ACCESS_DENIED
;
406 /* open the key first to get the appropriate REGISTRY_HOOK
407 and then check the premissions */
409 if ( !W_ERROR_IS_OK(result
= open_registry_key( p
, &r_u
->handle
, parent
, name
, 0 )) )
412 newkey
= find_regkey_index_by_hnd(p
, &r_u
->handle
);
414 /* finally allow the backend to check the access for the requested key */
416 if ( !regkey_access_check( newkey
, q_u
->access
, &access_granted
, p
->pipe_user
.nt_user_token
) ) {
417 close_registry_key( p
, &r_u
->handle
);
418 return WERR_ACCESS_DENIED
;
421 /* if successful, save the granted access mask */
423 newkey
->access_granted
= access_granted
;
428 /*******************************************************************
430 ********************************************************************/
432 WERROR
_reg_query_value(pipes_struct
*p
, REG_Q_QUERY_VALUE
*q_u
, REG_R_QUERY_VALUE
*r_u
)
434 WERROR status
= WERR_BADFILE
;
436 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
437 REGISTRY_VALUE
*val
= NULL
;
444 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey
->name
));
446 rpcstr_pull(name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0);
448 DEBUG(5,("reg_info: looking up value: [%s]\n", name
));
450 regval_ctr_init( ®vals
);
452 for ( i
=0; fetch_reg_values_specific(regkey
, &val
, i
); i
++ )
454 DEBUG(10,("_reg_info: Testing value [%s]\n", val
->valuename
));
455 if ( strequal( val
->valuename
, name
) ) {
456 DEBUG(10,("_reg_info: Found match for value [%s]\n", name
));
461 free_registry_value( val
);
464 init_reg_r_query_value(q_u
->ptr_buf
, r_u
, val
, status
);
466 regval_ctr_destroy( ®vals
);
467 free_registry_value( val
);
473 /*****************************************************************************
474 Implementation of REG_QUERY_KEY
475 ****************************************************************************/
477 WERROR
_reg_query_key(pipes_struct
*p
, REG_Q_QUERY_KEY
*q_u
, REG_R_QUERY_KEY
*r_u
)
479 WERROR status
= WERR_OK
;
480 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
485 if ( !get_subkey_information( regkey
, &r_u
->num_subkeys
, &r_u
->max_subkeylen
) ) {
486 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
487 return WERR_ACCESS_DENIED
;
490 if ( !get_value_information( regkey
, &r_u
->num_values
, &r_u
->max_valnamelen
, &r_u
->max_valbufsize
) ) {
491 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
492 return WERR_ACCESS_DENIED
;
496 r_u
->sec_desc
= 0x00000078; /* size for key's sec_desc */
498 /* Win9x set this to 0x0 since it does not keep timestamps.
499 Doing the same here for simplicity --jerry */
501 ZERO_STRUCT(r_u
->mod_time
);
507 /*****************************************************************************
508 Implementation of REG_GETVERSION
509 ****************************************************************************/
511 WERROR
_reg_getversion(pipes_struct
*p
, REG_Q_GETVERSION
*q_u
, REG_R_GETVERSION
*r_u
)
513 WERROR status
= WERR_OK
;
514 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
519 r_u
->win_version
= 0x00000005; /* Windows 2000 registry API version */
525 /*****************************************************************************
526 Implementation of REG_ENUM_KEY
527 ****************************************************************************/
529 WERROR
_reg_enum_key(pipes_struct
*p
, REG_Q_ENUM_KEY
*q_u
, REG_R_ENUM_KEY
*r_u
)
531 WERROR status
= WERR_OK
;
532 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
539 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey
->name
));
541 if ( !fetch_reg_keys_specific( regkey
, &subkey
, q_u
->key_index
) )
543 status
= WERR_NO_MORE_ITEMS
;
547 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey
));
549 /* subkey has the string name now */
551 init_reg_r_enum_key( r_u
, subkey
);
558 /*****************************************************************************
559 Implementation of REG_ENUM_VALUE
560 ****************************************************************************/
562 WERROR
_reg_enum_value(pipes_struct
*p
, REG_Q_ENUM_VALUE
*q_u
, REG_R_ENUM_VALUE
*r_u
)
564 WERROR status
= WERR_OK
;
565 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
572 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey
->name
));
574 if ( !fetch_reg_values_specific( regkey
, &val
, q_u
->val_index
) ) {
575 status
= WERR_NO_MORE_ITEMS
;
579 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val
->valuename
));
581 /* subkey has the string name now */
583 init_reg_r_enum_val( r_u
, val
);
586 free_registry_value( val
);
592 /*******************************************************************
594 ********************************************************************/
596 WERROR
_reg_shutdown(pipes_struct
*p
, REG_Q_SHUTDOWN
*q_u
, REG_R_SHUTDOWN
*r_u
)
598 REG_Q_SHUTDOWN_EX q_u_ex
;
599 REG_R_SHUTDOWN_EX r_u_ex
;
601 /* copy fields (including stealing memory) */
603 q_u_ex
.server
= q_u
->server
;
604 q_u_ex
.message
= q_u
->message
;
605 q_u_ex
.timeout
= q_u
->timeout
;
606 q_u_ex
.force
= q_u
->force
;
607 q_u_ex
.reboot
= q_u
->reboot
;
608 q_u_ex
.reason
= 0x0; /* don't care for now */
610 /* thunk down to _reg_shutdown_ex() (just returns a status) */
612 return _reg_shutdown_ex( p
, &q_u_ex
, &r_u_ex
);
615 /*******************************************************************
617 ********************************************************************/
619 #define SHUTDOWN_R_STRING "-r"
620 #define SHUTDOWN_F_STRING "-f"
623 WERROR
_reg_shutdown_ex(pipes_struct
*p
, REG_Q_SHUTDOWN_EX
*q_u
, REG_R_SHUTDOWN_EX
*r_u
)
625 pstring shutdown_script
;
636 pstrcpy(shutdown_script
, lp_shutdown_script());
638 if ( !*shutdown_script
)
639 return WERR_ACCESS_DENIED
;
641 /* pull the message string and perform necessary sanity checks on it */
643 pstrcpy( message
, "" );
644 if ( q_u
->message
) {
645 UNISTR2
*msg_string
= q_u
->message
->string
;
647 rpcstr_pull( message
, msg_string
->buffer
, sizeof(message
), msg_string
->uni_str_len
*2, 0 );
649 alpha_strcpy (chkmsg
, message
, NULL
, sizeof(message
));
651 fstr_sprintf(timeout
, "%d", q_u
->timeout
);
652 fstr_sprintf(r
, (q_u
->reboot
) ? SHUTDOWN_R_STRING
: "");
653 fstr_sprintf(f
, (q_u
->force
) ? SHUTDOWN_F_STRING
: "");
654 fstr_sprintf( reason
, "%d", q_u
->reason
);
656 all_string_sub( shutdown_script
, "%z", chkmsg
, sizeof(shutdown_script
) );
657 all_string_sub( shutdown_script
, "%t", timeout
, sizeof(shutdown_script
) );
658 all_string_sub( shutdown_script
, "%r", r
, sizeof(shutdown_script
) );
659 all_string_sub( shutdown_script
, "%f", f
, sizeof(shutdown_script
) );
660 all_string_sub( shutdown_script
, "%x", reason
, sizeof(shutdown_script
) );
662 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
664 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
665 Take the error return from the script and provide it as the Windows return code. */
667 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
672 ret
= smbrun( shutdown_script
, NULL
);
677 /********** END SeRemoteShutdownPrivilege BLOCK **********/
679 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
680 shutdown_script
, ret
));
683 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
689 /*******************************************************************
691 ********************************************************************/
693 WERROR
_reg_abort_shutdown(pipes_struct
*p
, REG_Q_ABORT_SHUTDOWN
*q_u
, REG_R_ABORT_SHUTDOWN
*r_u
)
695 pstring abort_shutdown_script
;
699 pstrcpy(abort_shutdown_script
, lp_abort_shutdown_script());
701 if ( !*abort_shutdown_script
)
702 return WERR_ACCESS_DENIED
;
704 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
706 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
711 ret
= smbrun( abort_shutdown_script
, NULL
);
716 /********** END SeRemoteShutdownPrivilege BLOCK **********/
718 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
719 abort_shutdown_script
, ret
));
722 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
725 /*******************************************************************
726 ********************************************************************/
728 static int validate_reg_filename( pstring fname
)
731 int num_services
= lp_numservices();
736 /* convert to a unix path, stripping the C:\ along the way */
738 if ( !(p
= valid_share_pathname( fname
) ))
741 /* has to exist within a valid file share */
743 for ( snum
=0; snum
<num_services
; snum
++ ) {
745 if ( !lp_snum_ok(snum
) || lp_print_ok(snum
) )
748 pstrcpy( share_path
, lp_pathname(snum
) );
750 /* make sure we have a path (e.g. [homes] ) */
752 if ( strlen( share_path
) == 0 )
755 if ( strncmp( share_path
, p
, strlen( share_path
)) == 0 )
759 /* p and fname are overlapping memory so copy out and back in again */
761 pstrcpy( unix_fname
, p
);
762 pstrcpy( fname
, unix_fname
);
764 return (snum
< num_services
) ? snum
: -1;
767 /*******************************************************************
768 Note: topkeypat is the *full* path that this *key will be
769 loaded into (including the name of the key)
770 ********************************************************************/
772 static WERROR
reg_load_tree( REGF_FILE
*regfile
, const char *topkeypath
,
776 REGISTRY_KEY registry_key
;
778 REGSUBKEY_CTR subkeys
;
781 WERROR result
= WERR_OK
;
783 /* initialize the REGISTRY_KEY structure */
785 if ( !(registry_key
.hook
= reghook_cache_find(topkeypath
)) ) {
786 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
790 pstrcpy( registry_key
.name
, topkeypath
);
792 /* now start parsing the values and subkeys */
794 regsubkey_ctr_init( &subkeys
);
795 regval_ctr_init( &values
);
797 /* copy values into the REGVAL_CTR */
799 for ( i
=0; i
<key
->num_values
; i
++ ) {
800 regval_ctr_addvalue( &values
, key
->values
[i
].valuename
, key
->values
[i
].type
,
801 key
->values
[i
].data
, (key
->values
[i
].data_size
& ~VK_DATA_IN_OFFSET
) );
804 /* copy subkeys into the REGSUBKEY_CTR */
806 key
->subkey_index
= 0;
807 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
808 regsubkey_ctr_addkey( &subkeys
, subkey
->keyname
);
811 /* write this key and values out */
813 if ( !store_reg_values( ®istry_key
, &values
)
814 || !store_reg_keys( ®istry_key
, &subkeys
) )
816 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath
));
817 result
= WERR_REG_IO_FAILURE
;
820 regval_ctr_destroy( &values
);
821 regsubkey_ctr_destroy( &subkeys
);
823 if ( !W_ERROR_IS_OK(result
) )
826 /* now continue to load each subkey registry tree */
828 key
->subkey_index
= 0;
829 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
830 pstr_sprintf( path
, "%s%s%s", topkeypath
, "\\", subkey
->keyname
);
831 result
= reg_load_tree( regfile
, path
, subkey
);
832 if ( !W_ERROR_IS_OK(result
) )
839 /*******************************************************************
840 ********************************************************************/
842 static WERROR
restore_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
845 REGF_NK_REC
*rootkey
;
848 /* open the registry file....fail if the file already exists */
850 if ( !(regfile
= regfio_open( fname
, (O_RDONLY
), 0 )) ) {
851 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
852 fname
, strerror(errno
) ));
853 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
856 /* get the rootkey from the regf file and then load the tree
857 via recursive calls */
859 if ( !(rootkey
= regfio_rootkey( regfile
)) )
860 return WERR_REG_FILE_INVALID
;
862 result
= reg_load_tree( regfile
, krecord
->name
, rootkey
);
866 regfio_close( regfile
);
871 /*******************************************************************
872 ********************************************************************/
874 WERROR
_reg_restore_key(pipes_struct
*p
, REG_Q_RESTORE_KEY
*q_u
, REG_R_RESTORE_KEY
*r_u
)
876 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
883 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
885 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey
->name
, filename
));
887 if ( (snum
= validate_reg_filename( filename
)) == -1 )
888 return WERR_OBJECT_PATH_INVALID
;
890 /* user must posses SeRestorePrivilege for this this proceed */
892 if ( !user_has_privileges( p
->pipe_user
.nt_user_token
, &se_restore
) )
893 return WERR_ACCESS_DENIED
;
895 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
897 return restore_registry_key( regkey
, filename
);
900 /********************************************************************
901 ********************************************************************/
903 static WERROR
reg_write_tree( REGF_FILE
*regfile
, const char *keypath
,
904 REGF_NK_REC
*parent
, SEC_DESC
*sec_desc
)
908 REGSUBKEY_CTR subkeys
;
911 char *keyname
, *parentpath
;
914 REGISTRY_KEY registry_key
;
915 WERROR result
= WERR_OK
;
918 return WERR_GENERAL_FAILURE
;
921 return WERR_OBJECT_PATH_INVALID
;
923 /* split up the registry key path */
925 pstrcpy( key_tmp
, keypath
);
926 if ( !reg_split_key( key_tmp
, &parentpath
, &keyname
) )
927 return WERR_OBJECT_PATH_INVALID
;
930 keyname
= parentpath
;
932 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
934 ZERO_STRUCT( registry_key
);
935 pstrcpy( registry_key
.name
, keypath
);
936 if ( !(registry_key
.hook
= reghook_cache_find( registry_key
.name
)) )
940 /* lookup the values and subkeys */
942 regsubkey_ctr_init( &subkeys
);
943 regval_ctr_init( &values
);
945 fetch_reg_keys( ®istry_key
, &subkeys
);
946 fetch_reg_values( ®istry_key
, &values
);
948 /* write out this key */
950 if ( !(key
= regfio_write_key( regfile
, keyname
, &values
, &subkeys
, sec_desc
, parent
)) ) {
951 result
= WERR_CAN_NOT_COMPLETE
;
955 /* write each one of the subkeys out */
957 num_subkeys
= regsubkey_ctr_numkeys( &subkeys
);
958 for ( i
=0; i
<num_subkeys
; i
++ ) {
959 subkeyname
= regsubkey_ctr_specific_key( &subkeys
, i
);
960 pstr_sprintf( subkeypath
, "%s\\%s", keypath
, subkeyname
);
961 result
= reg_write_tree( regfile
, subkeypath
, key
, sec_desc
);
962 if ( !W_ERROR_IS_OK(result
) )
966 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath
));
969 regval_ctr_destroy( &values
);
970 regsubkey_ctr_destroy( &subkeys
);
975 /*******************************************************************
976 ********************************************************************/
978 static WERROR
make_default_reg_sd( TALLOC_CTX
*ctx
, SEC_DESC
**psd
)
980 DOM_SID adm_sid
, owner_sid
;
981 SEC_ACE ace
[2]; /* at most 2 entries */
986 /* set the owner to BUILTIN\Administrator */
988 sid_copy(&owner_sid
, &global_sid_Builtin
);
989 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
992 /* basic access for Everyone */
994 init_sec_access(&mask
, reg_generic_map
.generic_execute
| reg_generic_map
.generic_read
);
995 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
997 /* add Full Access 'BUILTIN\Administrators' */
999 init_sec_access(&mask
, reg_generic_map
.generic_all
);
1000 sid_copy(&adm_sid
, &global_sid_Builtin
);
1001 sid_append_rid(&adm_sid
, BUILTIN_ALIAS_RID_ADMINS
);
1002 init_sec_ace(&ace
[1], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
1004 /* create the security descriptor */
1006 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 2, ace
)) == NULL
)
1009 if ((*psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, &owner_sid
, NULL
, NULL
, psa
, &sd_size
)) == NULL
)
1015 /*******************************************************************
1016 ********************************************************************/
1018 static WERROR
backup_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
1022 SEC_DESC
*sd
= NULL
;
1024 /* open the registry file....fail if the file already exists */
1026 if ( !(regfile
= regfio_open( fname
, (O_RDWR
|O_CREAT
|O_EXCL
), (S_IREAD
|S_IWRITE
) )) ) {
1027 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1028 fname
, strerror(errno
) ));
1029 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
1032 if ( !W_ERROR_IS_OK(result
= make_default_reg_sd( regfile
->mem_ctx
, &sd
)) ) {
1033 regfio_close( regfile
);
1037 /* write the registry tree to the file */
1039 result
= reg_write_tree( regfile
, krecord
->name
, NULL
, sd
);
1043 regfio_close( regfile
);
1048 /*******************************************************************
1049 ********************************************************************/
1051 WERROR
_reg_save_key(pipes_struct
*p
, REG_Q_SAVE_KEY
*q_u
, REG_R_SAVE_KEY
*r_u
)
1053 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
1060 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
1062 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey
->name
, filename
));
1064 if ( (snum
= validate_reg_filename( filename
)) == -1 )
1065 return WERR_OBJECT_PATH_INVALID
;
1067 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
1069 return backup_registry_key( regkey
, filename
);
1074 /*******************************************************************
1075 ********************************************************************/
1077 WERROR
_reg_create_key_ex(pipes_struct
*p
, REG_Q_CREATE_KEY_EX
*q_u
, REG_R_CREATE_KEY_EX
*r_u
)
1079 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1080 REGISTRY_KEY
*newparent
;
1081 POLICY_HND newparent_handle
;
1082 REGSUBKEY_CTR subkeys
;
1090 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1092 /* ok. Here's what we do. */
1094 if ( strrchr( name
, '\\' ) ) {
1097 uint32 access_granted
;
1099 /* (1) check for enumerate rights on the parent handle. CLients can try
1100 create things like 'SOFTWARE\Samba' on the HKLM handle.
1101 (2) open the path to the child parent key if necessary */
1103 if ( !(parent
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
) )
1104 return WERR_ACCESS_DENIED
;
1106 pstrcpy( newkeyname
, name
);
1107 ptr
= strrchr( newkeyname
, '\\' );
1110 result
= open_registry_key( p
, &newparent_handle
, parent
, newkeyname
, 0 );
1111 if ( !W_ERROR_IS_OK(result
) )
1114 newparent
= find_regkey_index_by_hnd(p
, &newparent_handle
);
1115 SMB_ASSERT( newparent
!= NULL
);
1117 if ( !regkey_access_check( newparent
, REG_KEY_READ
|REG_KEY_WRITE
, &access_granted
, p
->pipe_user
.nt_user_token
) ) {
1118 result
= WERR_ACCESS_DENIED
;
1122 newparent
->access_granted
= access_granted
;
1124 /* copy the new key name (just the lower most keyname) */
1126 pstrcpy( name
, ptr
+1 );
1129 /* use the existing open key information */
1131 memcpy( &newparent_handle
, &q_u
->handle
, sizeof(POLICY_HND
) );
1134 /* (3) check for create subkey rights on the correct parent */
1136 if ( !(newparent
->access_granted
& SEC_RIGHTS_CREATE_SUBKEY
) ) {
1137 result
= WERR_ACCESS_DENIED
;
1141 regsubkey_ctr_init( &subkeys
);
1143 /* (4) lookup the current keys and add the new one */
1145 fetch_reg_keys( newparent
, &subkeys
);
1146 regsubkey_ctr_addkey( &subkeys
, name
);
1148 /* now write to the registry backend */
1150 write_result
= store_reg_keys( newparent
, &subkeys
);
1152 regsubkey_ctr_destroy( &subkeys
);
1154 if ( !write_result
)
1155 return WERR_REG_IO_FAILURE
;
1157 /* (5) open the new key and return the handle. Note that it is probably
1158 not correct to grant full access on this open handle. We should pass
1159 the new open through the regkey_access_check() like we do for
1160 _reg_open_entry() but this is ok for now. */
1162 result
= open_registry_key( p
, &r_u
->handle
, newparent
, name
, REG_KEY_ALL
);
1165 /* close any intermediate key handles */
1167 if ( newparent
!= parent
)
1168 close_registry_key( p
, &newparent_handle
);
1174 /*******************************************************************
1175 ********************************************************************/
1177 WERROR
_reg_set_value(pipes_struct
*p
, REG_Q_SET_VALUE
*q_u
, REG_R_SET_VALUE
*r_u
)
1179 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1187 /* access checks first */
1189 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1190 return WERR_ACCESS_DENIED
;
1192 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1194 /* verify the name */
1197 return WERR_INVALID_PARAM
;
1199 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1201 regval_ctr_init( &values
);
1203 /* lookup the current values and add the new one */
1205 fetch_reg_values( key
, &values
);
1207 regval_ctr_addvalue( &values
, valuename
, q_u
->type
, q_u
->value
.buffer
, q_u
->value
.buf_len
);
1209 /* now write to the registry backend */
1211 write_result
= store_reg_values( key
, &values
);
1213 regval_ctr_destroy( &values
);
1215 if ( !write_result
)
1216 return WERR_REG_IO_FAILURE
;
1221 /*******************************************************************
1222 ********************************************************************/
1224 WERROR
_reg_delete_key(pipes_struct
*p
, REG_Q_DELETE_KEY
*q_u
, REG_R_DELETE_KEY
*r_u
)
1226 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1227 REGISTRY_KEY
*newparent
;
1228 POLICY_HND newparent_handle
;
1229 REGSUBKEY_CTR subkeys
;
1237 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1239 /* ok. Here's what we do. */
1241 if ( strrchr( name
, '\\' ) ) {
1244 uint32 access_granted
;
1246 /* (1) check for enumerate rights on the parent handle. CLients can try
1247 create things like 'SOFTWARE\Samba' on the HKLM handle.
1248 (2) open the path to the child parent key if necessary */
1250 if ( !(parent
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
) )
1251 return WERR_ACCESS_DENIED
;
1253 pstrcpy( newkeyname
, name
);
1254 ptr
= strrchr( newkeyname
, '\\' );
1257 result
= open_registry_key( p
, &newparent_handle
, parent
, newkeyname
, 0 );
1258 if ( !W_ERROR_IS_OK(result
) )
1261 newparent
= find_regkey_index_by_hnd(p
, &newparent_handle
);
1262 SMB_ASSERT( newparent
!= NULL
);
1264 if ( !regkey_access_check( newparent
, REG_KEY_READ
|REG_KEY_WRITE
, &access_granted
, p
->pipe_user
.nt_user_token
) ) {
1265 result
= WERR_ACCESS_DENIED
;
1269 newparent
->access_granted
= access_granted
;
1271 /* copy the new key name (just the lower most keyname) */
1273 pstrcpy( name
, ptr
+1 );
1276 /* use the existing open key information */
1278 memcpy( &newparent_handle
, &q_u
->handle
, sizeof(POLICY_HND
) );
1281 /* (3) check for create subkey rights on the correct parent */
1283 if ( !(newparent
->access_granted
& STD_RIGHT_DELETE_ACCESS
) ) {
1284 result
= WERR_ACCESS_DENIED
;
1288 regsubkey_ctr_init( &subkeys
);
1290 /* lookup the current keys and delete the new one */
1292 fetch_reg_keys( newparent
, &subkeys
);
1294 regsubkey_ctr_delkey( &subkeys
, name
);
1296 /* now write to the registry backend */
1298 write_result
= store_reg_keys( newparent
, &subkeys
);
1300 regsubkey_ctr_destroy( &subkeys
);
1302 result
= write_result
? WERR_OK
: WERR_REG_IO_FAILURE
;
1305 /* close any intermediate key handles */
1307 if ( newparent
!= parent
)
1308 close_registry_key( p
, &newparent_handle
);
1314 /*******************************************************************
1315 ********************************************************************/
1317 WERROR
_reg_delete_value(pipes_struct
*p
, REG_Q_DELETE_VALUE
*q_u
, REG_R_DELETE_VALUE
*r_u
)
1319 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1327 /* access checks first */
1329 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1330 return WERR_ACCESS_DENIED
;
1332 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1335 return WERR_INVALID_PARAM
;
1337 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1339 regval_ctr_init( &values
);
1341 /* lookup the current values and add the new one */
1343 fetch_reg_values( key
, &values
);
1345 regval_ctr_delvalue( &values
, valuename
);
1347 /* now write to the registry backend */
1349 write_result
= store_reg_values( key
, &values
);
1351 regval_ctr_destroy( &values
);
1353 if ( !write_result
)
1354 return WERR_REG_IO_FAILURE
;
1359 /*******************************************************************
1360 ********************************************************************/
1362 WERROR
_reg_get_key_sec(pipes_struct
*p
, REG_Q_GET_KEY_SEC
*q_u
, REG_R_GET_KEY_SEC
*r_u
)
1364 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1369 /* access checks first */
1371 if ( !(key
->access_granted
& STD_RIGHT_READ_CONTROL_ACCESS
) )
1372 return WERR_ACCESS_DENIED
;
1374 return WERR_ACCESS_DENIED
;
1377 /*******************************************************************
1378 ********************************************************************/
1380 WERROR
_reg_set_key_sec(pipes_struct
*p
, REG_Q_SET_KEY_SEC
*q_u
, REG_R_SET_KEY_SEC
*r_u
)
1382 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1387 /* access checks first */
1389 if ( !(key
->access_granted
& STD_RIGHT_WRITE_DAC_ACCESS
) )
1390 return WERR_ACCESS_DENIED
;
1392 return WERR_ACCESS_DENIED
;