2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997.
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
6 * Copyright (C) Paul Ashton 1997.
7 * Copyright (C) Jeremy Allison 2001.
8 * Copyright (C) Gerald Carter 2002-2005.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* Implementation of registry functions. */
31 #define DBGC_CLASS DBGC_RPC_SRV
33 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
34 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
36 static struct generic_mapping reg_generic_map
=
37 { REG_KEY_READ
, REG_KEY_WRITE
, REG_KEY_EXECUTE
, REG_KEY_ALL
};
40 /******************************************************************
41 free() function for REGISTRY_KEY
42 *****************************************************************/
44 static void free_regkey_info(void *ptr
)
46 regkey_close_internal( (REGISTRY_KEY
*)ptr
);
49 /******************************************************************
50 Find a registry key handle and return a REGISTRY_KEY
51 *****************************************************************/
53 static REGISTRY_KEY
*find_regkey_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
55 REGISTRY_KEY
*regkey
= NULL
;
57 if(!find_policy_by_hnd(p
,hnd
,(void **)®key
)) {
58 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
66 /*******************************************************************
67 Function for open a new registry handle and creating a handle
68 Note that P should be valid & hnd should already have space
70 When we open a key, we store the full path to the key as
71 HK[LM|U]\<key>\<key>\...
72 *******************************************************************/
74 static WERROR
open_registry_key( pipes_struct
*p
, POLICY_HND
*hnd
,
75 REGISTRY_KEY
**keyinfo
, REGISTRY_KEY
*parent
,
76 const char *subkeyname
, uint32 access_desired
)
80 WERROR result
= WERR_OK
;
82 /* create a full registry path and strip any trailing '\'
85 pstr_sprintf( keypath
, "%s%s%s",
86 parent
? parent
->name
: "",
90 path_len
= strlen( keypath
);
91 if ( path_len
&& keypath
[path_len
-1] == '\\' )
92 keypath
[path_len
-1] = '\0';
94 /* now do the internal open */
96 result
= regkey_open_internal( keyinfo
, keypath
, p
->pipe_user
.nt_user_token
, access_desired
);
97 if ( !W_ERROR_IS_OK(result
) )
100 if ( !create_policy_hnd( p
, hnd
, free_regkey_info
, *keyinfo
) ) {
101 result
= WERR_BADFILE
;
102 regkey_close_internal( *keyinfo
);
108 /*******************************************************************
109 Function for open a new registry handle and creating a handle
110 Note that P should be valid & hnd should already have space
111 *******************************************************************/
113 static BOOL
close_registry_key(pipes_struct
*p
, POLICY_HND
*hnd
)
115 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd(p
, hnd
);
118 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
122 close_policy_hnd(p
, hnd
);
127 /********************************************************************
128 retrieve information about the subkeys
129 *******************************************************************/
131 static BOOL
get_subkey_information( REGISTRY_KEY
*key
, uint32
*maxnum
, uint32
*maxlen
)
135 REGSUBKEY_CTR
*subkeys
;
141 if ( !(subkeys
= TALLOC_ZERO_P( NULL
, REGSUBKEY_CTR
)) )
144 if ( fetch_reg_keys( key
, subkeys
) == -1 )
147 /* find the longest string */
150 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
152 for ( i
=0; i
<num_subkeys
; i
++ ) {
153 len
= strlen( regsubkey_ctr_specific_key(subkeys
, i
) );
154 max_len
= MAX(max_len
, len
);
157 *maxnum
= num_subkeys
;
160 TALLOC_FREE( subkeys
);
165 /********************************************************************
166 retrieve information about the values.
167 *******************************************************************/
169 static BOOL
get_value_information( REGISTRY_KEY
*key
, uint32
*maxnum
,
170 uint32
*maxlen
, uint32
*maxsize
)
174 uint32 sizemax
, lenmax
;
180 if ( !(values
= TALLOC_ZERO_P( NULL
, REGVAL_CTR
)) )
183 if ( fetch_reg_values( key
, values
) == -1 )
186 lenmax
= sizemax
= 0;
187 num_values
= regval_ctr_numvals( values
);
189 val
= regval_ctr_specific_value( values
, 0 );
191 for ( i
=0; i
<num_values
&& val
; i
++ )
193 lenmax
= MAX(lenmax
, val
->valuename
? strlen(val
->valuename
)+1 : 0 );
194 sizemax
= MAX(sizemax
, val
->size
);
196 val
= regval_ctr_specific_value( values
, i
);
199 *maxnum
= num_values
;
203 TALLOC_FREE( values
);
209 /********************************************************************
211 ********************************************************************/
213 WERROR
_reg_close(pipes_struct
*p
, REG_Q_CLOSE
*q_u
, REG_R_CLOSE
*r_u
)
215 /* close the policy handle */
217 if (!close_registry_key(p
, &q_u
->pol
))
223 /*******************************************************************
224 ********************************************************************/
226 WERROR
_reg_open_hklm(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
228 REGISTRY_KEY
*keyinfo
;
230 return open_registry_key( p
, &r_u
->pol
, &keyinfo
, NULL
, KEY_HKLM
, q_u
->access
);
233 /*******************************************************************
234 ********************************************************************/
236 WERROR
_reg_open_hkpd(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
238 REGISTRY_KEY
*keyinfo
;
240 return open_registry_key( p
, &r_u
->pol
, &keyinfo
, NULL
, KEY_HKPD
, q_u
->access
);
243 /*******************************************************************
244 ********************************************************************/
246 WERROR
_reg_open_hkpt(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
248 REGISTRY_KEY
*keyinfo
;
250 return open_registry_key( p
, &r_u
->pol
, &keyinfo
, NULL
, KEY_HKPT
, q_u
->access
);
253 /*******************************************************************
254 ********************************************************************/
256 WERROR
_reg_open_hkcr(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
258 REGISTRY_KEY
*keyinfo
;
260 return open_registry_key( p
, &r_u
->pol
, &keyinfo
, NULL
, KEY_HKCR
, q_u
->access
);
263 /*******************************************************************
264 ********************************************************************/
266 WERROR
_reg_open_hku(pipes_struct
*p
, REG_Q_OPEN_HIVE
*q_u
, REG_R_OPEN_HIVE
*r_u
)
268 REGISTRY_KEY
*keyinfo
;
270 return open_registry_key( p
, &r_u
->pol
, &keyinfo
, NULL
, KEY_HKU
, q_u
->access
);
273 /*******************************************************************
275 ********************************************************************/
277 WERROR
_reg_open_entry(pipes_struct
*p
, REG_Q_OPEN_ENTRY
*q_u
, REG_R_OPEN_ENTRY
*r_u
)
280 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->pol
);
281 REGISTRY_KEY
*newkey
= NULL
;
287 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
289 /* check granted access first; what is the correct mask here? */
291 check_rights
= ( SEC_RIGHTS_ENUM_SUBKEYS
|
292 SEC_RIGHTS_CREATE_SUBKEY
|
293 SEC_RIGHTS_QUERY_VALUE
|
294 SEC_RIGHTS_SET_VALUE
);
296 if ( !(parent
->access_granted
& check_rights
) ) {
297 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent
->access_granted
, check_rights
));
298 return WERR_ACCESS_DENIED
;
302 * very crazy, but regedit.exe on Win2k will attempt to call
303 * REG_OPEN_ENTRY with a keyname of "". We should return a new
304 * (second) handle here on the key->name. regedt32.exe does
305 * not do this stupidity. --jerry
308 return open_registry_key( p
, &r_u
->handle
, &newkey
, parent
, name
, q_u
->access
);
311 /*******************************************************************
313 ********************************************************************/
315 WERROR
_reg_query_value(pipes_struct
*p
, REG_Q_QUERY_VALUE
*q_u
, REG_R_QUERY_VALUE
*r_u
)
317 WERROR status
= WERR_BADFILE
;
319 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
320 REGISTRY_VALUE
*val
= NULL
;
327 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey
->name
));
328 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey
->type
));
330 rpcstr_pull(name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0);
332 DEBUG(5,("_reg_info: looking up value: [%s]\n", name
));
334 if ( !(regvals
= TALLOC_ZERO_P( p
->mem_ctx
, REGVAL_CTR
)) )
337 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
338 if(regkey
->type
== REG_KEY_HKPD
)
340 if(strequal(name
, "Global"))
344 prs_init(&prs_hkpd
, q_u
->bufsize
, p
->mem_ctx
, MARSHALL
);
345 status
= reg_perfcount_get_hkpd(&prs_hkpd
, q_u
->bufsize
, &outbuf_len
, NULL
);
346 regval_ctr_addvalue(regvals
, "HKPD", REG_BINARY
,
347 prs_hkpd
.data_p
, outbuf_len
);
348 val
= dup_registry_value(regval_ctr_specific_value(regvals
, 0));
349 prs_mem_free(&prs_hkpd
);
351 else if(strequal(name
, "Counter 009"))
358 base_index
= reg_perfcount_get_base_index();
359 buffer_size
= reg_perfcount_get_counter_names(base_index
, &buffer
);
360 regval_ctr_addvalue(regvals
, "Counter 009",
361 REG_MULTI_SZ
, buffer
, buffer_size
);
363 val
= dup_registry_value(regval_ctr_specific_value(regvals
, 0));
371 else if(strequal(name
, "Explain 009"))
378 base_index
= reg_perfcount_get_base_index();
379 buffer_size
= reg_perfcount_get_counter_help(base_index
, &buffer
);
380 regval_ctr_addvalue(regvals
, "Explain 009",
381 REG_MULTI_SZ
, buffer
, buffer_size
);
383 val
= dup_registry_value(regval_ctr_specific_value(regvals
, 0));
391 else if(isdigit(name
[0]))
393 /* we probably have a request for a specific object here */
396 prs_init(&prs_hkpd
, q_u
->bufsize
, p
->mem_ctx
, MARSHALL
);
397 status
= reg_perfcount_get_hkpd(&prs_hkpd
, q_u
->bufsize
, &outbuf_len
, name
);
398 regval_ctr_addvalue(regvals
, "HKPD", REG_BINARY
,
399 prs_hkpd
.data_p
, outbuf_len
);
401 val
= dup_registry_value(regval_ctr_specific_value(regvals
, 0));
402 prs_mem_free(&prs_hkpd
);
406 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name
));
410 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
413 for ( i
=0; fetch_reg_values_specific(regkey
, &val
, i
); i
++ )
415 DEBUG(10,("_reg_info: Testing value [%s]\n", val
->valuename
));
416 if ( strequal( val
->valuename
, name
) ) {
417 DEBUG(10,("_reg_info: Found match for value [%s]\n", name
));
422 free_registry_value( val
);
426 init_reg_r_query_value(q_u
->ptr_buf
, r_u
, val
, status
);
428 TALLOC_FREE( regvals
);
429 free_registry_value( val
);
434 /*****************************************************************************
435 Implementation of REG_QUERY_KEY
436 ****************************************************************************/
438 WERROR
_reg_query_key(pipes_struct
*p
, REG_Q_QUERY_KEY
*q_u
, REG_R_QUERY_KEY
*r_u
)
440 WERROR status
= WERR_OK
;
441 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
446 if ( !get_subkey_information( regkey
, &r_u
->num_subkeys
, &r_u
->max_subkeylen
) ) {
447 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
448 return WERR_ACCESS_DENIED
;
451 if ( !get_value_information( regkey
, &r_u
->num_values
, &r_u
->max_valnamelen
, &r_u
->max_valbufsize
) ) {
452 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
453 return WERR_ACCESS_DENIED
;
457 r_u
->sec_desc
= 0x00000078; /* size for key's sec_desc */
459 /* Win9x set this to 0x0 since it does not keep timestamps.
460 Doing the same here for simplicity --jerry */
462 ZERO_STRUCT(r_u
->mod_time
);
468 /*****************************************************************************
469 Implementation of REG_GETVERSION
470 ****************************************************************************/
472 WERROR
_reg_getversion(pipes_struct
*p
, REG_Q_GETVERSION
*q_u
, REG_R_GETVERSION
*r_u
)
474 WERROR status
= WERR_OK
;
475 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
480 r_u
->win_version
= 0x00000005; /* Windows 2000 registry API version */
486 /*****************************************************************************
487 Implementation of REG_ENUM_KEY
488 ****************************************************************************/
490 WERROR
_reg_enum_key(pipes_struct
*p
, REG_Q_ENUM_KEY
*q_u
, REG_R_ENUM_KEY
*r_u
)
492 WERROR status
= WERR_OK
;
493 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
500 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey
->name
));
502 if ( !fetch_reg_keys_specific( regkey
, &subkey
, q_u
->key_index
) )
504 status
= WERR_NO_MORE_ITEMS
;
508 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey
));
510 /* subkey has the string name now */
512 init_reg_r_enum_key( r_u
, subkey
);
519 /*****************************************************************************
520 Implementation of REG_ENUM_VALUE
521 ****************************************************************************/
523 WERROR
_reg_enum_value(pipes_struct
*p
, REG_Q_ENUM_VALUE
*q_u
, REG_R_ENUM_VALUE
*r_u
)
525 WERROR status
= WERR_OK
;
526 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
533 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey
->name
));
535 if ( !fetch_reg_values_specific( regkey
, &val
, q_u
->val_index
) ) {
536 status
= WERR_NO_MORE_ITEMS
;
540 if ( val
->type
== REG_MULTI_SZ
) {
544 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val
->valuename
));
546 /* subkey has the string name now */
548 init_reg_r_enum_val( r_u
, val
);
551 free_registry_value( val
);
557 /*******************************************************************
559 ********************************************************************/
561 WERROR
_reg_shutdown(pipes_struct
*p
, REG_Q_SHUTDOWN
*q_u
, REG_R_SHUTDOWN
*r_u
)
563 REG_Q_SHUTDOWN_EX q_u_ex
;
564 REG_R_SHUTDOWN_EX r_u_ex
;
566 /* copy fields (including stealing memory) */
568 q_u_ex
.server
= q_u
->server
;
569 q_u_ex
.message
= q_u
->message
;
570 q_u_ex
.timeout
= q_u
->timeout
;
571 q_u_ex
.force
= q_u
->force
;
572 q_u_ex
.reboot
= q_u
->reboot
;
573 q_u_ex
.reason
= 0x0; /* don't care for now */
575 /* thunk down to _reg_shutdown_ex() (just returns a status) */
577 return _reg_shutdown_ex( p
, &q_u_ex
, &r_u_ex
);
580 /*******************************************************************
582 ********************************************************************/
584 #define SHUTDOWN_R_STRING "-r"
585 #define SHUTDOWN_F_STRING "-f"
588 WERROR
_reg_shutdown_ex(pipes_struct
*p
, REG_Q_SHUTDOWN_EX
*q_u
, REG_R_SHUTDOWN_EX
*r_u
)
590 pstring shutdown_script
;
601 pstrcpy(shutdown_script
, lp_shutdown_script());
603 if ( !*shutdown_script
)
604 return WERR_ACCESS_DENIED
;
606 /* pull the message string and perform necessary sanity checks on it */
608 pstrcpy( message
, "" );
609 if ( q_u
->message
) {
610 UNISTR2
*msg_string
= q_u
->message
->string
;
612 rpcstr_pull( message
, msg_string
->buffer
, sizeof(message
), msg_string
->uni_str_len
*2, 0 );
614 alpha_strcpy (chkmsg
, message
, NULL
, sizeof(message
));
616 fstr_sprintf(timeout
, "%d", q_u
->timeout
);
617 fstr_sprintf(r
, (q_u
->reboot
) ? SHUTDOWN_R_STRING
: "");
618 fstr_sprintf(f
, (q_u
->force
) ? SHUTDOWN_F_STRING
: "");
619 fstr_sprintf( reason
, "%d", q_u
->reason
);
621 all_string_sub( shutdown_script
, "%z", chkmsg
, sizeof(shutdown_script
) );
622 all_string_sub( shutdown_script
, "%t", timeout
, sizeof(shutdown_script
) );
623 all_string_sub( shutdown_script
, "%r", r
, sizeof(shutdown_script
) );
624 all_string_sub( shutdown_script
, "%f", f
, sizeof(shutdown_script
) );
625 all_string_sub( shutdown_script
, "%x", reason
, sizeof(shutdown_script
) );
627 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
629 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
630 Take the error return from the script and provide it as the Windows return code. */
632 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
637 ret
= smbrun( shutdown_script
, NULL
);
642 /********** END SeRemoteShutdownPrivilege BLOCK **********/
644 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
645 shutdown_script
, ret
));
648 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
654 /*******************************************************************
656 ********************************************************************/
658 WERROR
_reg_abort_shutdown(pipes_struct
*p
, REG_Q_ABORT_SHUTDOWN
*q_u
, REG_R_ABORT_SHUTDOWN
*r_u
)
660 pstring abort_shutdown_script
;
664 pstrcpy(abort_shutdown_script
, lp_abort_shutdown_script());
666 if ( !*abort_shutdown_script
)
667 return WERR_ACCESS_DENIED
;
669 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
671 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
676 ret
= smbrun( abort_shutdown_script
, NULL
);
681 /********** END SeRemoteShutdownPrivilege BLOCK **********/
683 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
684 abort_shutdown_script
, ret
));
687 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
690 /*******************************************************************
691 ********************************************************************/
693 static int validate_reg_filename( pstring fname
)
696 int num_services
= lp_numservices();
701 /* convert to a unix path, stripping the C:\ along the way */
703 if ( !(p
= valid_share_pathname( fname
) ))
706 /* has to exist within a valid file share */
708 for ( snum
=0; snum
<num_services
; snum
++ ) {
710 if ( !lp_snum_ok(snum
) || lp_print_ok(snum
) )
713 pstrcpy( share_path
, lp_pathname(snum
) );
715 /* make sure we have a path (e.g. [homes] ) */
717 if ( strlen( share_path
) == 0 )
720 if ( strncmp( share_path
, p
, strlen( share_path
)) == 0 )
724 /* p and fname are overlapping memory so copy out and back in again */
726 pstrcpy( unix_fname
, p
);
727 pstrcpy( fname
, unix_fname
);
729 return (snum
< num_services
) ? snum
: -1;
732 /*******************************************************************
733 Note: topkeypat is the *full* path that this *key will be
734 loaded into (including the name of the key)
735 ********************************************************************/
737 static WERROR
reg_load_tree( REGF_FILE
*regfile
, const char *topkeypath
,
741 REGISTRY_KEY registry_key
;
743 REGSUBKEY_CTR
*subkeys
;
746 WERROR result
= WERR_OK
;
748 /* initialize the REGISTRY_KEY structure */
750 if ( !(registry_key
.hook
= reghook_cache_find(topkeypath
)) ) {
751 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
755 pstrcpy( registry_key
.name
, topkeypath
);
757 /* now start parsing the values and subkeys */
759 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
762 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
765 /* copy values into the REGVAL_CTR */
767 for ( i
=0; i
<key
->num_values
; i
++ ) {
768 regval_ctr_addvalue( values
, key
->values
[i
].valuename
, key
->values
[i
].type
,
769 (char*)key
->values
[i
].data
, (key
->values
[i
].data_size
& ~VK_DATA_IN_OFFSET
) );
772 /* copy subkeys into the REGSUBKEY_CTR */
774 key
->subkey_index
= 0;
775 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
776 regsubkey_ctr_addkey( subkeys
, subkey
->keyname
);
779 /* write this key and values out */
781 if ( !store_reg_values( ®istry_key
, values
)
782 || !store_reg_keys( ®istry_key
, subkeys
) )
784 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath
));
785 result
= WERR_REG_IO_FAILURE
;
788 TALLOC_FREE( subkeys
);
790 if ( !W_ERROR_IS_OK(result
) )
793 /* now continue to load each subkey registry tree */
795 key
->subkey_index
= 0;
796 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
797 pstr_sprintf( path
, "%s%s%s", topkeypath
, "\\", subkey
->keyname
);
798 result
= reg_load_tree( regfile
, path
, subkey
);
799 if ( !W_ERROR_IS_OK(result
) )
806 /*******************************************************************
807 ********************************************************************/
809 static WERROR
restore_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
812 REGF_NK_REC
*rootkey
;
815 /* open the registry file....fail if the file already exists */
817 if ( !(regfile
= regfio_open( fname
, (O_RDONLY
), 0 )) ) {
818 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
819 fname
, strerror(errno
) ));
820 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
823 /* get the rootkey from the regf file and then load the tree
824 via recursive calls */
826 if ( !(rootkey
= regfio_rootkey( regfile
)) )
827 return WERR_REG_FILE_INVALID
;
829 result
= reg_load_tree( regfile
, krecord
->name
, rootkey
);
833 regfio_close( regfile
);
838 /*******************************************************************
839 ********************************************************************/
841 WERROR
_reg_restore_key(pipes_struct
*p
, REG_Q_RESTORE_KEY
*q_u
, REG_R_RESTORE_KEY
*r_u
)
843 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
850 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
852 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey
->name
, filename
));
854 if ( (snum
= validate_reg_filename( filename
)) == -1 )
855 return WERR_OBJECT_PATH_INVALID
;
857 /* user must posses SeRestorePrivilege for this this proceed */
859 if ( !user_has_privileges( p
->pipe_user
.nt_user_token
, &se_restore
) )
860 return WERR_ACCESS_DENIED
;
862 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
864 return restore_registry_key( regkey
, filename
);
867 /********************************************************************
868 ********************************************************************/
870 static WERROR
reg_write_tree( REGF_FILE
*regfile
, const char *keypath
,
871 REGF_NK_REC
*parent
, SEC_DESC
*sec_desc
)
875 REGSUBKEY_CTR
*subkeys
;
878 char *keyname
, *parentpath
;
881 REGISTRY_KEY registry_key
;
882 WERROR result
= WERR_OK
;
885 return WERR_GENERAL_FAILURE
;
888 return WERR_OBJECT_PATH_INVALID
;
890 /* split up the registry key path */
892 pstrcpy( key_tmp
, keypath
);
893 if ( !reg_split_key( key_tmp
, &parentpath
, &keyname
) )
894 return WERR_OBJECT_PATH_INVALID
;
897 keyname
= parentpath
;
899 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
901 ZERO_STRUCT( registry_key
);
902 pstrcpy( registry_key
.name
, keypath
);
903 if ( !(registry_key
.hook
= reghook_cache_find( registry_key
.name
)) )
907 /* lookup the values and subkeys */
909 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
912 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
915 fetch_reg_keys( ®istry_key
, subkeys
);
916 fetch_reg_values( ®istry_key
, values
);
918 /* write out this key */
920 if ( !(key
= regfio_write_key( regfile
, keyname
, values
, subkeys
, sec_desc
, parent
)) ) {
921 result
= WERR_CAN_NOT_COMPLETE
;
925 /* write each one of the subkeys out */
927 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
928 for ( i
=0; i
<num_subkeys
; i
++ ) {
929 subkeyname
= regsubkey_ctr_specific_key( subkeys
, i
);
930 pstr_sprintf( subkeypath
, "%s\\%s", keypath
, subkeyname
);
931 result
= reg_write_tree( regfile
, subkeypath
, key
, sec_desc
);
932 if ( !W_ERROR_IS_OK(result
) )
936 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath
));
939 TALLOC_FREE( subkeys
);
944 /*******************************************************************
945 ********************************************************************/
947 static WERROR
make_default_reg_sd( TALLOC_CTX
*ctx
, SEC_DESC
**psd
)
949 DOM_SID adm_sid
, owner_sid
;
950 SEC_ACE ace
[2]; /* at most 2 entries */
955 /* set the owner to BUILTIN\Administrator */
957 sid_copy(&owner_sid
, &global_sid_Builtin
);
958 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
961 /* basic access for Everyone */
963 init_sec_access(&mask
, reg_generic_map
.generic_execute
| reg_generic_map
.generic_read
);
964 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
966 /* add Full Access 'BUILTIN\Administrators' */
968 init_sec_access(&mask
, reg_generic_map
.generic_all
);
969 sid_copy(&adm_sid
, &global_sid_Builtin
);
970 sid_append_rid(&adm_sid
, BUILTIN_ALIAS_RID_ADMINS
);
971 init_sec_ace(&ace
[1], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
973 /* create the security descriptor */
975 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 2, ace
)) == NULL
)
978 if ((*psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, &owner_sid
, NULL
, NULL
, psa
, &sd_size
)) == NULL
)
984 /*******************************************************************
985 ********************************************************************/
987 static WERROR
backup_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
993 /* open the registry file....fail if the file already exists */
995 if ( !(regfile
= regfio_open( fname
, (O_RDWR
|O_CREAT
|O_EXCL
), (S_IREAD
|S_IWRITE
) )) ) {
996 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
997 fname
, strerror(errno
) ));
998 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
1001 if ( !W_ERROR_IS_OK(result
= make_default_reg_sd( regfile
->mem_ctx
, &sd
)) ) {
1002 regfio_close( regfile
);
1006 /* write the registry tree to the file */
1008 result
= reg_write_tree( regfile
, krecord
->name
, NULL
, sd
);
1012 regfio_close( regfile
);
1017 /*******************************************************************
1018 ********************************************************************/
1020 WERROR
_reg_save_key(pipes_struct
*p
, REG_Q_SAVE_KEY
*q_u
, REG_R_SAVE_KEY
*r_u
)
1022 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
1029 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
1031 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey
->name
, filename
));
1033 if ( (snum
= validate_reg_filename( filename
)) == -1 )
1034 return WERR_OBJECT_PATH_INVALID
;
1036 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
1038 return backup_registry_key( regkey
, filename
);
1041 /*******************************************************************
1042 ********************************************************************/
1044 WERROR
_reg_create_key_ex(pipes_struct
*p
, REG_Q_CREATE_KEY_EX
*q_u
, REG_R_CREATE_KEY_EX
*r_u
)
1046 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1047 REGISTRY_KEY
*newparentinfo
, *keyinfo
;
1048 POLICY_HND newparent_handle
;
1049 REGSUBKEY_CTR
*subkeys
;
1057 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1059 /* ok. Here's what we do. */
1061 if ( strrchr( name
, '\\' ) ) {
1065 /* (1) check for enumerate rights on the parent handle. CLients can try
1066 create things like 'SOFTWARE\Samba' on the HKLM handle.
1067 (2) open the path to the child parent key if necessary */
1069 if ( !(parent
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
) )
1070 return WERR_ACCESS_DENIED
;
1072 pstrcpy( newkeyname
, name
);
1073 ptr
= strrchr( newkeyname
, '\\' );
1076 result
= open_registry_key( p
, &newparent_handle
, &newparentinfo
,
1077 parent
, newkeyname
, (REG_KEY_READ
|REG_KEY_WRITE
) );
1079 if ( !W_ERROR_IS_OK(result
) )
1082 /* copy the new key name (just the lower most keyname) */
1084 pstrcpy( name
, ptr
+1 );
1087 /* use the existing open key information */
1088 newparentinfo
= parent
;
1089 memcpy( &newparent_handle
, &q_u
->handle
, sizeof(POLICY_HND
) );
1092 /* (3) check for create subkey rights on the correct parent */
1094 if ( !(newparentinfo
->access_granted
& SEC_RIGHTS_CREATE_SUBKEY
) ) {
1095 result
= WERR_ACCESS_DENIED
;
1099 if ( !(subkeys
= TALLOC_ZERO_P( p
->mem_ctx
, REGSUBKEY_CTR
)) ) {
1100 result
= WERR_NOMEM
;
1104 /* (4) lookup the current keys and add the new one */
1106 fetch_reg_keys( newparentinfo
, subkeys
);
1107 regsubkey_ctr_addkey( subkeys
, name
);
1109 /* now write to the registry backend */
1111 write_result
= store_reg_keys( newparentinfo
, subkeys
);
1113 TALLOC_FREE( subkeys
);
1115 if ( !write_result
)
1116 return WERR_REG_IO_FAILURE
;
1118 /* (5) open the new key and return the handle. Note that it is probably
1119 not correct to grant full access on this open handle. */
1121 result
= open_registry_key( p
, &r_u
->handle
, &keyinfo
, newparentinfo
, name
, REG_KEY_READ
);
1122 keyinfo
->access_granted
= REG_KEY_ALL
;
1125 /* close any intermediate key handles */
1127 if ( newparentinfo
!= parent
)
1128 close_registry_key( p
, &newparent_handle
);
1134 /*******************************************************************
1135 ********************************************************************/
1137 WERROR
_reg_set_value(pipes_struct
*p
, REG_Q_SET_VALUE
*q_u
, REG_R_SET_VALUE
*r_u
)
1139 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1147 /* access checks first */
1149 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1150 return WERR_ACCESS_DENIED
;
1152 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1154 /* verify the name */
1157 return WERR_INVALID_PARAM
;
1159 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1161 if ( !(values
= TALLOC_ZERO_P( p
->mem_ctx
, REGVAL_CTR
)) )
1164 /* lookup the current values and add the new one */
1166 fetch_reg_values( key
, values
);
1168 regval_ctr_addvalue( values
, valuename
, q_u
->type
, (char*)q_u
->value
.buffer
, q_u
->value
.buf_len
);
1170 /* now write to the registry backend */
1172 write_result
= store_reg_values( key
, values
);
1174 TALLOC_FREE( values
);
1176 if ( !write_result
)
1177 return WERR_REG_IO_FAILURE
;
1182 /*******************************************************************
1183 ********************************************************************/
1185 WERROR
_reg_delete_key(pipes_struct
*p
, REG_Q_DELETE_KEY
*q_u
, REG_R_DELETE_KEY
*r_u
)
1187 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1188 REGISTRY_KEY
*newparentinfo
;
1189 POLICY_HND newparent_handle
;
1190 REGSUBKEY_CTR
*subkeys
;
1198 /* MSDN says parent the handle must have been opened with DELETE access */
1200 /* (1) check for delete rights on the parent */
1202 if ( !(parent
->access_granted
& STD_RIGHT_DELETE_ACCESS
) ) {
1203 result
= WERR_ACCESS_DENIED
;
1207 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1209 /* ok. Here's what we do. */
1211 if ( strrchr( name
, '\\' ) ) {
1215 /* (2) open the path to the child parent key if necessary */
1216 /* split the registry path and save the subkeyname */
1218 pstrcpy( newkeyname
, name
);
1219 ptr
= strrchr( newkeyname
, '\\' );
1221 pstrcpy( name
, ptr
+1 );
1223 result
= open_registry_key( p
, &newparent_handle
, &newparentinfo
, parent
, newkeyname
, (REG_KEY_READ
|REG_KEY_WRITE
) );
1224 if ( !W_ERROR_IS_OK(result
) )
1228 /* use the existing open key information */
1229 newparentinfo
= parent
;
1232 if ( !(subkeys
= TALLOC_ZERO_P( p
->mem_ctx
, REGSUBKEY_CTR
)) ) {
1233 result
= WERR_NOMEM
;
1237 /* lookup the current keys and delete the new one */
1239 fetch_reg_keys( newparentinfo
, subkeys
);
1241 regsubkey_ctr_delkey( subkeys
, name
);
1243 /* now write to the registry backend */
1245 write_result
= store_reg_keys( newparentinfo
, subkeys
);
1247 TALLOC_FREE( subkeys
);
1249 result
= write_result
? WERR_OK
: WERR_REG_IO_FAILURE
;
1252 /* close any intermediate key handles */
1254 if ( newparentinfo
!= parent
)
1255 close_registry_key( p
, &newparent_handle
);
1261 /*******************************************************************
1262 ********************************************************************/
1264 WERROR
_reg_delete_value(pipes_struct
*p
, REG_Q_DELETE_VALUE
*q_u
, REG_R_DELETE_VALUE
*r_u
)
1266 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1274 /* access checks first */
1276 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1277 return WERR_ACCESS_DENIED
;
1279 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1282 return WERR_INVALID_PARAM
;
1284 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1286 if ( !(values
= TALLOC_ZERO_P( p
->mem_ctx
, REGVAL_CTR
)) )
1289 /* lookup the current values and add the new one */
1291 fetch_reg_values( key
, values
);
1293 regval_ctr_delvalue( values
, valuename
);
1295 /* now write to the registry backend */
1297 write_result
= store_reg_values( key
, values
);
1299 TALLOC_FREE( values
);
1301 if ( !write_result
)
1302 return WERR_REG_IO_FAILURE
;
1307 /*******************************************************************
1308 ********************************************************************/
1310 WERROR
_reg_get_key_sec(pipes_struct
*p
, REG_Q_GET_KEY_SEC
*q_u
, REG_R_GET_KEY_SEC
*r_u
)
1312 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1317 /* access checks first */
1319 if ( !(key
->access_granted
& STD_RIGHT_READ_CONTROL_ACCESS
) )
1320 return WERR_ACCESS_DENIED
;
1322 return WERR_ACCESS_DENIED
;
1325 /*******************************************************************
1326 ********************************************************************/
1328 WERROR
_reg_set_key_sec(pipes_struct
*p
, REG_Q_SET_KEY_SEC
*q_u
, REG_R_SET_KEY_SEC
*r_u
)
1330 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1335 /* access checks first */
1337 if ( !(key
->access_granted
& STD_RIGHT_WRITE_DAC_ACCESS
) )
1338 return WERR_ACCESS_DENIED
;
1340 return WERR_ACCESS_DENIED
;