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 0 /* JERRY TEST CODE */
541 if ( val
->type
== REG_MULTI_SZ
) {
543 int num_strings
= regval_convert_multi_sz( (uint16
*)regval_data_p(val
), regval_size(val
), &str
);
549 buf_size
= regval_build_multi_sz( str
, &buffer
);
552 TALLOC_FREE( buffer
);
556 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val
->valuename
));
558 /* subkey has the string name now */
560 init_reg_r_enum_val( r_u
, val
);
563 free_registry_value( val
);
569 /*******************************************************************
571 ********************************************************************/
573 WERROR
_reg_shutdown(pipes_struct
*p
, REG_Q_SHUTDOWN
*q_u
, REG_R_SHUTDOWN
*r_u
)
575 REG_Q_SHUTDOWN_EX q_u_ex
;
576 REG_R_SHUTDOWN_EX r_u_ex
;
578 /* copy fields (including stealing memory) */
580 q_u_ex
.server
= q_u
->server
;
581 q_u_ex
.message
= q_u
->message
;
582 q_u_ex
.timeout
= q_u
->timeout
;
583 q_u_ex
.force
= q_u
->force
;
584 q_u_ex
.reboot
= q_u
->reboot
;
585 q_u_ex
.reason
= 0x0; /* don't care for now */
587 /* thunk down to _reg_shutdown_ex() (just returns a status) */
589 return _reg_shutdown_ex( p
, &q_u_ex
, &r_u_ex
);
592 /*******************************************************************
594 ********************************************************************/
596 #define SHUTDOWN_R_STRING "-r"
597 #define SHUTDOWN_F_STRING "-f"
600 WERROR
_reg_shutdown_ex(pipes_struct
*p
, REG_Q_SHUTDOWN_EX
*q_u
, REG_R_SHUTDOWN_EX
*r_u
)
602 pstring shutdown_script
;
613 pstrcpy(shutdown_script
, lp_shutdown_script());
615 if ( !*shutdown_script
)
616 return WERR_ACCESS_DENIED
;
618 /* pull the message string and perform necessary sanity checks on it */
620 pstrcpy( message
, "" );
621 if ( q_u
->message
) {
622 UNISTR2
*msg_string
= q_u
->message
->string
;
624 rpcstr_pull( message
, msg_string
->buffer
, sizeof(message
), msg_string
->uni_str_len
*2, 0 );
626 alpha_strcpy (chkmsg
, message
, NULL
, sizeof(message
));
628 fstr_sprintf(timeout
, "%d", q_u
->timeout
);
629 fstr_sprintf(r
, (q_u
->reboot
) ? SHUTDOWN_R_STRING
: "");
630 fstr_sprintf(f
, (q_u
->force
) ? SHUTDOWN_F_STRING
: "");
631 fstr_sprintf( reason
, "%d", q_u
->reason
);
633 all_string_sub( shutdown_script
, "%z", chkmsg
, sizeof(shutdown_script
) );
634 all_string_sub( shutdown_script
, "%t", timeout
, sizeof(shutdown_script
) );
635 all_string_sub( shutdown_script
, "%r", r
, sizeof(shutdown_script
) );
636 all_string_sub( shutdown_script
, "%f", f
, sizeof(shutdown_script
) );
637 all_string_sub( shutdown_script
, "%x", reason
, sizeof(shutdown_script
) );
639 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
641 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
642 Take the error return from the script and provide it as the Windows return code. */
644 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
649 ret
= smbrun( shutdown_script
, NULL
);
654 /********** END SeRemoteShutdownPrivilege BLOCK **********/
656 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
657 shutdown_script
, ret
));
660 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
666 /*******************************************************************
668 ********************************************************************/
670 WERROR
_reg_abort_shutdown(pipes_struct
*p
, REG_Q_ABORT_SHUTDOWN
*q_u
, REG_R_ABORT_SHUTDOWN
*r_u
)
672 pstring abort_shutdown_script
;
676 pstrcpy(abort_shutdown_script
, lp_abort_shutdown_script());
678 if ( !*abort_shutdown_script
)
679 return WERR_ACCESS_DENIED
;
681 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
683 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
688 ret
= smbrun( abort_shutdown_script
, NULL
);
693 /********** END SeRemoteShutdownPrivilege BLOCK **********/
695 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
696 abort_shutdown_script
, ret
));
699 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
702 /*******************************************************************
703 ********************************************************************/
705 static int validate_reg_filename( pstring fname
)
708 int num_services
= lp_numservices();
713 /* convert to a unix path, stripping the C:\ along the way */
715 if ( !(p
= valid_share_pathname( fname
) ))
718 /* has to exist within a valid file share */
720 for ( snum
=0; snum
<num_services
; snum
++ ) {
722 if ( !lp_snum_ok(snum
) || lp_print_ok(snum
) )
725 pstrcpy( share_path
, lp_pathname(snum
) );
727 /* make sure we have a path (e.g. [homes] ) */
729 if ( strlen( share_path
) == 0 )
732 if ( strncmp( share_path
, p
, strlen( share_path
)) == 0 )
736 /* p and fname are overlapping memory so copy out and back in again */
738 pstrcpy( unix_fname
, p
);
739 pstrcpy( fname
, unix_fname
);
741 return (snum
< num_services
) ? snum
: -1;
744 /*******************************************************************
745 Note: topkeypat is the *full* path that this *key will be
746 loaded into (including the name of the key)
747 ********************************************************************/
749 static WERROR
reg_load_tree( REGF_FILE
*regfile
, const char *topkeypath
,
753 REGISTRY_KEY registry_key
;
755 REGSUBKEY_CTR
*subkeys
;
758 WERROR result
= WERR_OK
;
760 /* initialize the REGISTRY_KEY structure */
762 if ( !(registry_key
.hook
= reghook_cache_find(topkeypath
)) ) {
763 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
767 pstrcpy( registry_key
.name
, topkeypath
);
769 /* now start parsing the values and subkeys */
771 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
774 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
777 /* copy values into the REGVAL_CTR */
779 for ( i
=0; i
<key
->num_values
; i
++ ) {
780 regval_ctr_addvalue( values
, key
->values
[i
].valuename
, key
->values
[i
].type
,
781 (char*)key
->values
[i
].data
, (key
->values
[i
].data_size
& ~VK_DATA_IN_OFFSET
) );
784 /* copy subkeys into the REGSUBKEY_CTR */
786 key
->subkey_index
= 0;
787 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
788 regsubkey_ctr_addkey( subkeys
, subkey
->keyname
);
791 /* write this key and values out */
793 if ( !store_reg_values( ®istry_key
, values
)
794 || !store_reg_keys( ®istry_key
, subkeys
) )
796 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath
));
797 result
= WERR_REG_IO_FAILURE
;
800 TALLOC_FREE( subkeys
);
802 if ( !W_ERROR_IS_OK(result
) )
805 /* now continue to load each subkey registry tree */
807 key
->subkey_index
= 0;
808 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
809 pstr_sprintf( path
, "%s%s%s", topkeypath
, "\\", subkey
->keyname
);
810 result
= reg_load_tree( regfile
, path
, subkey
);
811 if ( !W_ERROR_IS_OK(result
) )
818 /*******************************************************************
819 ********************************************************************/
821 static WERROR
restore_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
824 REGF_NK_REC
*rootkey
;
827 /* open the registry file....fail if the file already exists */
829 if ( !(regfile
= regfio_open( fname
, (O_RDONLY
), 0 )) ) {
830 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
831 fname
, strerror(errno
) ));
832 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
835 /* get the rootkey from the regf file and then load the tree
836 via recursive calls */
838 if ( !(rootkey
= regfio_rootkey( regfile
)) )
839 return WERR_REG_FILE_INVALID
;
841 result
= reg_load_tree( regfile
, krecord
->name
, rootkey
);
845 regfio_close( regfile
);
850 /*******************************************************************
851 ********************************************************************/
853 WERROR
_reg_restore_key(pipes_struct
*p
, REG_Q_RESTORE_KEY
*q_u
, REG_R_RESTORE_KEY
*r_u
)
855 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
862 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
864 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey
->name
, filename
));
866 if ( (snum
= validate_reg_filename( filename
)) == -1 )
867 return WERR_OBJECT_PATH_INVALID
;
869 /* user must posses SeRestorePrivilege for this this proceed */
871 if ( !user_has_privileges( p
->pipe_user
.nt_user_token
, &se_restore
) )
872 return WERR_ACCESS_DENIED
;
874 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
876 return restore_registry_key( regkey
, filename
);
879 /********************************************************************
880 ********************************************************************/
882 static WERROR
reg_write_tree( REGF_FILE
*regfile
, const char *keypath
,
883 REGF_NK_REC
*parent
, SEC_DESC
*sec_desc
)
887 REGSUBKEY_CTR
*subkeys
;
890 char *keyname
, *parentpath
;
893 REGISTRY_KEY registry_key
;
894 WERROR result
= WERR_OK
;
897 return WERR_GENERAL_FAILURE
;
900 return WERR_OBJECT_PATH_INVALID
;
902 /* split up the registry key path */
904 pstrcpy( key_tmp
, keypath
);
905 if ( !reg_split_key( key_tmp
, &parentpath
, &keyname
) )
906 return WERR_OBJECT_PATH_INVALID
;
909 keyname
= parentpath
;
911 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
913 ZERO_STRUCT( registry_key
);
914 pstrcpy( registry_key
.name
, keypath
);
915 if ( !(registry_key
.hook
= reghook_cache_find( registry_key
.name
)) )
919 /* lookup the values and subkeys */
921 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
924 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
927 fetch_reg_keys( ®istry_key
, subkeys
);
928 fetch_reg_values( ®istry_key
, values
);
930 /* write out this key */
932 if ( !(key
= regfio_write_key( regfile
, keyname
, values
, subkeys
, sec_desc
, parent
)) ) {
933 result
= WERR_CAN_NOT_COMPLETE
;
937 /* write each one of the subkeys out */
939 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
940 for ( i
=0; i
<num_subkeys
; i
++ ) {
941 subkeyname
= regsubkey_ctr_specific_key( subkeys
, i
);
942 pstr_sprintf( subkeypath
, "%s\\%s", keypath
, subkeyname
);
943 result
= reg_write_tree( regfile
, subkeypath
, key
, sec_desc
);
944 if ( !W_ERROR_IS_OK(result
) )
948 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath
));
951 TALLOC_FREE( subkeys
);
956 /*******************************************************************
957 ********************************************************************/
959 static WERROR
make_default_reg_sd( TALLOC_CTX
*ctx
, SEC_DESC
**psd
)
961 DOM_SID adm_sid
, owner_sid
;
962 SEC_ACE ace
[2]; /* at most 2 entries */
967 /* set the owner to BUILTIN\Administrator */
969 sid_copy(&owner_sid
, &global_sid_Builtin
);
970 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
973 /* basic access for Everyone */
975 init_sec_access(&mask
, reg_generic_map
.generic_execute
| reg_generic_map
.generic_read
);
976 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
978 /* add Full Access 'BUILTIN\Administrators' */
980 init_sec_access(&mask
, reg_generic_map
.generic_all
);
981 sid_copy(&adm_sid
, &global_sid_Builtin
);
982 sid_append_rid(&adm_sid
, BUILTIN_ALIAS_RID_ADMINS
);
983 init_sec_ace(&ace
[1], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
985 /* create the security descriptor */
987 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 2, ace
)) == NULL
)
990 if ((*psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, &owner_sid
, NULL
, NULL
, psa
, &sd_size
)) == NULL
)
996 /*******************************************************************
997 ********************************************************************/
999 static WERROR
backup_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
1003 SEC_DESC
*sd
= NULL
;
1005 /* open the registry file....fail if the file already exists */
1007 if ( !(regfile
= regfio_open( fname
, (O_RDWR
|O_CREAT
|O_EXCL
), (S_IREAD
|S_IWRITE
) )) ) {
1008 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1009 fname
, strerror(errno
) ));
1010 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
1013 if ( !W_ERROR_IS_OK(result
= make_default_reg_sd( regfile
->mem_ctx
, &sd
)) ) {
1014 regfio_close( regfile
);
1018 /* write the registry tree to the file */
1020 result
= reg_write_tree( regfile
, krecord
->name
, NULL
, sd
);
1024 regfio_close( regfile
);
1029 /*******************************************************************
1030 ********************************************************************/
1032 WERROR
_reg_save_key(pipes_struct
*p
, REG_Q_SAVE_KEY
*q_u
, REG_R_SAVE_KEY
*r_u
)
1034 REGISTRY_KEY
*regkey
= find_regkey_index_by_hnd( p
, &q_u
->pol
);
1041 rpcstr_pull(filename
, q_u
->filename
.string
->buffer
, sizeof(filename
), q_u
->filename
.string
->uni_str_len
*2, STR_TERMINATE
);
1043 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey
->name
, filename
));
1045 if ( (snum
= validate_reg_filename( filename
)) == -1 )
1046 return WERR_OBJECT_PATH_INVALID
;
1048 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey
->name
, filename
, lp_servicename(snum
) ));
1050 return backup_registry_key( regkey
, filename
);
1053 /*******************************************************************
1054 ********************************************************************/
1056 WERROR
_reg_create_key_ex(pipes_struct
*p
, REG_Q_CREATE_KEY_EX
*q_u
, REG_R_CREATE_KEY_EX
*r_u
)
1058 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1059 REGISTRY_KEY
*newparentinfo
, *keyinfo
;
1060 POLICY_HND newparent_handle
;
1061 REGSUBKEY_CTR
*subkeys
;
1069 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1071 /* ok. Here's what we do. */
1073 if ( strrchr( name
, '\\' ) ) {
1077 /* (1) check for enumerate rights on the parent handle. CLients can try
1078 create things like 'SOFTWARE\Samba' on the HKLM handle.
1079 (2) open the path to the child parent key if necessary */
1081 if ( !(parent
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
) )
1082 return WERR_ACCESS_DENIED
;
1084 pstrcpy( newkeyname
, name
);
1085 ptr
= strrchr( newkeyname
, '\\' );
1088 result
= open_registry_key( p
, &newparent_handle
, &newparentinfo
,
1089 parent
, newkeyname
, (REG_KEY_READ
|REG_KEY_WRITE
) );
1091 if ( !W_ERROR_IS_OK(result
) )
1094 /* copy the new key name (just the lower most keyname) */
1096 pstrcpy( name
, ptr
+1 );
1099 /* use the existing open key information */
1100 newparentinfo
= parent
;
1101 memcpy( &newparent_handle
, &q_u
->handle
, sizeof(POLICY_HND
) );
1104 /* (3) check for create subkey rights on the correct parent */
1106 if ( !(newparentinfo
->access_granted
& SEC_RIGHTS_CREATE_SUBKEY
) ) {
1107 result
= WERR_ACCESS_DENIED
;
1111 if ( !(subkeys
= TALLOC_ZERO_P( p
->mem_ctx
, REGSUBKEY_CTR
)) ) {
1112 result
= WERR_NOMEM
;
1116 /* (4) lookup the current keys and add the new one */
1118 fetch_reg_keys( newparentinfo
, subkeys
);
1119 regsubkey_ctr_addkey( subkeys
, name
);
1121 /* now write to the registry backend */
1123 write_result
= store_reg_keys( newparentinfo
, subkeys
);
1125 TALLOC_FREE( subkeys
);
1127 if ( !write_result
)
1128 return WERR_REG_IO_FAILURE
;
1130 /* (5) open the new key and return the handle. Note that it is probably
1131 not correct to grant full access on this open handle. */
1133 result
= open_registry_key( p
, &r_u
->handle
, &keyinfo
, newparentinfo
, name
, REG_KEY_READ
);
1134 keyinfo
->access_granted
= REG_KEY_ALL
;
1137 /* close any intermediate key handles */
1139 if ( newparentinfo
!= parent
)
1140 close_registry_key( p
, &newparent_handle
);
1146 /*******************************************************************
1147 ********************************************************************/
1149 WERROR
_reg_set_value(pipes_struct
*p
, REG_Q_SET_VALUE
*q_u
, REG_R_SET_VALUE
*r_u
)
1151 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1159 /* access checks first */
1161 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1162 return WERR_ACCESS_DENIED
;
1164 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1166 /* verify the name */
1169 return WERR_INVALID_PARAM
;
1171 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1173 if ( !(values
= TALLOC_ZERO_P( p
->mem_ctx
, REGVAL_CTR
)) )
1176 /* lookup the current values and add the new one */
1178 fetch_reg_values( key
, values
);
1180 regval_ctr_addvalue( values
, valuename
, q_u
->type
, (char*)q_u
->value
.buffer
, q_u
->value
.buf_len
);
1182 /* now write to the registry backend */
1184 write_result
= store_reg_values( key
, values
);
1186 TALLOC_FREE( values
);
1188 if ( !write_result
)
1189 return WERR_REG_IO_FAILURE
;
1194 /*******************************************************************
1195 ********************************************************************/
1197 WERROR
_reg_delete_key(pipes_struct
*p
, REG_Q_DELETE_KEY
*q_u
, REG_R_DELETE_KEY
*r_u
)
1199 REGISTRY_KEY
*parent
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1200 REGISTRY_KEY
*newparentinfo
;
1201 POLICY_HND newparent_handle
;
1202 REGSUBKEY_CTR
*subkeys
;
1210 /* MSDN says parent the handle must have been opened with DELETE access */
1212 /* (1) check for delete rights on the parent */
1214 if ( !(parent
->access_granted
& STD_RIGHT_DELETE_ACCESS
) ) {
1215 result
= WERR_ACCESS_DENIED
;
1219 rpcstr_pull( name
, q_u
->name
.string
->buffer
, sizeof(name
), q_u
->name
.string
->uni_str_len
*2, 0 );
1221 /* ok. Here's what we do. */
1223 if ( strrchr( name
, '\\' ) ) {
1227 /* (2) open the path to the child parent key if necessary */
1228 /* split the registry path and save the subkeyname */
1230 pstrcpy( newkeyname
, name
);
1231 ptr
= strrchr( newkeyname
, '\\' );
1233 pstrcpy( name
, ptr
+1 );
1235 result
= open_registry_key( p
, &newparent_handle
, &newparentinfo
, parent
, newkeyname
, (REG_KEY_READ
|REG_KEY_WRITE
) );
1236 if ( !W_ERROR_IS_OK(result
) )
1240 /* use the existing open key information */
1241 newparentinfo
= parent
;
1244 if ( !(subkeys
= TALLOC_ZERO_P( p
->mem_ctx
, REGSUBKEY_CTR
)) ) {
1245 result
= WERR_NOMEM
;
1249 /* lookup the current keys and delete the new one */
1251 fetch_reg_keys( newparentinfo
, subkeys
);
1253 regsubkey_ctr_delkey( subkeys
, name
);
1255 /* now write to the registry backend */
1257 write_result
= store_reg_keys( newparentinfo
, subkeys
);
1259 TALLOC_FREE( subkeys
);
1261 result
= write_result
? WERR_OK
: WERR_REG_IO_FAILURE
;
1264 /* close any intermediate key handles */
1266 if ( newparentinfo
!= parent
)
1267 close_registry_key( p
, &newparent_handle
);
1273 /*******************************************************************
1274 ********************************************************************/
1276 WERROR
_reg_delete_value(pipes_struct
*p
, REG_Q_DELETE_VALUE
*q_u
, REG_R_DELETE_VALUE
*r_u
)
1278 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1286 /* access checks first */
1288 if ( !(key
->access_granted
& SEC_RIGHTS_SET_VALUE
) )
1289 return WERR_ACCESS_DENIED
;
1291 rpcstr_pull( valuename
, q_u
->name
.string
->buffer
, sizeof(valuename
), q_u
->name
.string
->uni_str_len
*2, 0 );
1294 return WERR_INVALID_PARAM
;
1296 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key
->name
, valuename
));
1298 if ( !(values
= TALLOC_ZERO_P( p
->mem_ctx
, REGVAL_CTR
)) )
1301 /* lookup the current values and add the new one */
1303 fetch_reg_values( key
, values
);
1305 regval_ctr_delvalue( values
, valuename
);
1307 /* now write to the registry backend */
1309 write_result
= store_reg_values( key
, values
);
1311 TALLOC_FREE( values
);
1313 if ( !write_result
)
1314 return WERR_REG_IO_FAILURE
;
1319 /*******************************************************************
1320 ********************************************************************/
1322 WERROR
_reg_get_key_sec(pipes_struct
*p
, REG_Q_GET_KEY_SEC
*q_u
, REG_R_GET_KEY_SEC
*r_u
)
1324 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1329 /* access checks first */
1331 if ( !(key
->access_granted
& STD_RIGHT_READ_CONTROL_ACCESS
) )
1332 return WERR_ACCESS_DENIED
;
1334 return WERR_ACCESS_DENIED
;
1337 /*******************************************************************
1338 ********************************************************************/
1340 WERROR
_reg_set_key_sec(pipes_struct
*p
, REG_Q_SET_KEY_SEC
*q_u
, REG_R_SET_KEY_SEC
*r_u
)
1342 REGISTRY_KEY
*key
= find_regkey_index_by_hnd(p
, &q_u
->handle
);
1347 /* access checks first */
1349 if ( !(key
->access_granted
& STD_RIGHT_WRITE_DAC_ACCESS
) )
1350 return WERR_ACCESS_DENIED
;
1352 return WERR_ACCESS_DENIED
;