2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Gerald Carter 2002-2006.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 /* Implementation of registry functions. */
27 #define DBGC_CLASS DBGC_RPC_SRV
29 static struct generic_mapping reg_generic_map
=
30 { REG_KEY_READ
, REG_KEY_WRITE
, REG_KEY_EXECUTE
, REG_KEY_ALL
};
32 /******************************************************************
33 free() function for struct registry_key
34 *****************************************************************/
36 static void free_regkey(void *ptr
)
38 struct registry_key
*key
= (struct registry_key
*)ptr
;
42 /******************************************************************
43 Find a registry key handle and return a REGISTRY_KEY
44 *****************************************************************/
46 static struct registry_key
*find_regkey_by_hnd(pipes_struct
*p
,
49 struct registry_key
*regkey
= NULL
;
51 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)®key
)) {
52 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
59 /*******************************************************************
60 Function for open a new registry handle and creating a handle
61 Note that P should be valid & hnd should already have space
63 When we open a key, we store the full path to the key as
64 HK[LM|U]\<key>\<key>\...
65 *******************************************************************/
67 static WERROR
open_registry_key( pipes_struct
*p
, POLICY_HND
*hnd
,
68 struct registry_key
*parent
,
69 const char *subkeyname
,
70 uint32 access_desired
)
72 WERROR result
= WERR_OK
;
73 struct registry_key
*key
;
76 result
= reg_openhive(NULL
, subkeyname
, access_desired
,
77 p
->pipe_user
.nt_user_token
, &key
);
80 result
= reg_openkey(NULL
, parent
, subkeyname
, access_desired
,
84 if ( !W_ERROR_IS_OK(result
) ) {
88 if ( !create_policy_hnd( p
, hnd
, free_regkey
, key
) ) {
95 /*******************************************************************
96 Function for open a new registry handle and creating a handle
97 Note that P should be valid & hnd should already have space
98 *******************************************************************/
100 static BOOL
close_registry_key(pipes_struct
*p
, POLICY_HND
*hnd
)
102 struct registry_key
*regkey
= find_regkey_by_hnd(p
, hnd
);
105 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
110 close_policy_hnd(p
, hnd
);
115 /********************************************************************
117 ********************************************************************/
119 WERROR
_winreg_CloseKey(pipes_struct
*p
, struct winreg_CloseKey
*r
)
121 /* close the policy handle */
123 if (!close_registry_key(p
, r
->in
.handle
))
126 ZERO_STRUCTP(r
->out
.handle
);
131 /*******************************************************************
132 ********************************************************************/
134 WERROR
_winreg_OpenHKLM(pipes_struct
*p
, struct winreg_OpenHKLM
*r
)
136 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKLM
, r
->in
.access_mask
);
139 /*******************************************************************
140 ********************************************************************/
142 WERROR
_winreg_OpenHKPD(pipes_struct
*p
, struct winreg_OpenHKPD
*r
)
144 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKPD
, r
->in
.access_mask
);
147 /*******************************************************************
148 ********************************************************************/
150 WERROR
_winreg_OpenHKPT(pipes_struct
*p
, struct winreg_OpenHKPT
*r
)
152 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKPT
, r
->in
.access_mask
);
155 /*******************************************************************
156 ********************************************************************/
158 WERROR
_winreg_OpenHKCR(pipes_struct
*p
, struct winreg_OpenHKCR
*r
)
160 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKCR
, r
->in
.access_mask
);
163 /*******************************************************************
164 ********************************************************************/
166 WERROR
_winreg_OpenHKU(pipes_struct
*p
, struct winreg_OpenHKU
*r
)
168 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKU
, r
->in
.access_mask
);
171 /*******************************************************************
172 ********************************************************************/
174 WERROR
_winreg_OpenHKCU(pipes_struct
*p
, struct winreg_OpenHKCU
*r
)
176 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKCU
, r
->in
.access_mask
);
179 /*******************************************************************
180 ********************************************************************/
182 WERROR
_winreg_OpenHKCC(pipes_struct
*p
, struct winreg_OpenHKCC
*r
)
184 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKCC
, r
->in
.access_mask
);
187 /*******************************************************************
188 ********************************************************************/
190 WERROR
_winreg_OpenHKDD(pipes_struct
*p
, struct winreg_OpenHKDD
*r
)
192 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKDD
, r
->in
.access_mask
);
195 /*******************************************************************
196 ********************************************************************/
198 WERROR
_winreg_OpenHKPN(pipes_struct
*p
, struct winreg_OpenHKPN
*r
)
200 return open_registry_key(p
, r
->out
.handle
, NULL
, KEY_HKPN
, r
->in
.access_mask
);
203 /*******************************************************************
205 ********************************************************************/
207 WERROR
_winreg_OpenKey(pipes_struct
*p
, struct winreg_OpenKey
*r
)
209 struct registry_key
*parent
= find_regkey_by_hnd(p
, r
->in
.parent_handle
);
214 return open_registry_key(p
, r
->out
.handle
, parent
, r
->in
.keyname
.name
, r
->in
.access_mask
);
217 /*******************************************************************
219 ********************************************************************/
221 WERROR
_winreg_QueryValue(pipes_struct
*p
, struct winreg_QueryValue
*r
)
223 WERROR status
= WERR_BADFILE
;
224 struct registry_key
*regkey
= find_regkey_by_hnd( p
, r
->in
.handle
);
228 uint32_t outbuf_size
;
231 BOOL free_buf
= False
;
232 BOOL free_prs
= False
;
237 *r
->out
.value_length
= *r
->out
.type
= 0;
239 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey
->key
->name
));
240 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey
->key
->type
));
242 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
243 if(regkey
->key
->type
== REG_KEY_HKPD
)
245 if(strequal(r
->in
.value_name
.name
, "Global")) {
246 prs_init(&prs_hkpd
, *r
->in
.data_size
, p
->mem_ctx
, MARSHALL
);
247 status
= reg_perfcount_get_hkpd(
248 &prs_hkpd
, *r
->in
.data_size
, &outbuf_size
, NULL
);
249 outbuf
= (uint8_t *)prs_hkpd
.data_p
;
252 else if(strequal(r
->in
.value_name
.name
, "Counter 009")) {
253 outbuf_size
= reg_perfcount_get_counter_names(
254 reg_perfcount_get_base_index(),
255 (char **)(void *)&outbuf
);
258 else if(strequal(r
->in
.value_name
.name
, "Explain 009")) {
259 outbuf_size
= reg_perfcount_get_counter_help(
260 reg_perfcount_get_base_index(),
261 (char **)(void *)&outbuf
);
264 else if(isdigit(r
->in
.value_name
.name
[0])) {
265 /* we probably have a request for a specific object
267 prs_init(&prs_hkpd
, *r
->in
.data_size
, p
->mem_ctx
, MARSHALL
);
268 status
= reg_perfcount_get_hkpd(
269 &prs_hkpd
, *r
->in
.data_size
, &outbuf_size
,
270 r
->in
.value_name
.name
);
271 outbuf
= (uint8_t *)prs_hkpd
.data_p
;
275 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
276 r
->in
.value_name
.name
));
280 *r
->out
.type
= REG_BINARY
;
283 struct registry_value
*val
;
285 status
= reg_queryvalue(p
->mem_ctx
, regkey
, r
->in
.value_name
.name
,
287 if (!W_ERROR_IS_OK(status
)) {
288 if (r
->out
.data_size
) {
289 *r
->out
.data_size
= 0;
291 if (r
->out
.value_length
) {
292 *r
->out
.value_length
= 0;
297 status
= registry_push_value(p
->mem_ctx
, val
, &val_blob
);
298 if (!W_ERROR_IS_OK(status
)) {
302 outbuf
= val_blob
.data
;
303 outbuf_size
= val_blob
.length
;
304 *r
->out
.type
= val
->type
;
307 *r
->out
.value_length
= outbuf_size
;
309 if ( *r
->in
.data_size
== 0 || !r
->out
.data
) {
311 } else if ( *r
->out
.value_length
> *r
->in
.data_size
) {
312 status
= WERR_MORE_DATA
;
314 memcpy( r
->out
.data
, outbuf
, *r
->out
.value_length
);
318 *r
->out
.data_size
= *r
->out
.value_length
;
320 if (free_prs
) prs_mem_free(&prs_hkpd
);
321 if (free_buf
) SAFE_FREE(outbuf
);
326 /*****************************************************************************
327 Implementation of REG_QUERY_KEY
328 ****************************************************************************/
330 WERROR
_winreg_QueryInfoKey(pipes_struct
*p
, struct winreg_QueryInfoKey
*r
)
332 WERROR status
= WERR_OK
;
333 struct registry_key
*regkey
= find_regkey_by_hnd( p
, r
->in
.handle
);
338 r
->out
.classname
->name
= NULL
;
340 status
= reg_queryinfokey(regkey
, r
->out
.num_subkeys
, r
->out
.max_subkeylen
,
341 r
->out
.max_classlen
, r
->out
.num_values
, r
->out
.max_valnamelen
,
342 r
->out
.max_valbufsize
, r
->out
.secdescsize
,
343 r
->out
.last_changed_time
);
344 if (!W_ERROR_IS_OK(status
)) {
349 * These calculations account for the registry buffers being
350 * UTF-16. They are inexact at best, but so far they worked.
353 *r
->out
.max_subkeylen
*= 2;
355 *r
->out
.max_valnamelen
+= 1;
356 *r
->out
.max_valnamelen
*= 2;
362 /*****************************************************************************
363 Implementation of REG_GETVERSION
364 ****************************************************************************/
366 WERROR
_winreg_GetVersion(pipes_struct
*p
, struct winreg_GetVersion
*r
)
368 struct registry_key
*regkey
= find_regkey_by_hnd( p
, r
->in
.handle
);
373 *r
->out
.version
= 0x00000005; /* Windows 2000 registry API version */
379 /*****************************************************************************
380 Implementation of REG_ENUM_KEY
381 ****************************************************************************/
383 WERROR
_winreg_EnumKey(pipes_struct
*p
, struct winreg_EnumKey
*r
)
386 struct registry_key
*key
= find_regkey_by_hnd( p
, r
->in
.handle
);
391 if ( !r
->in
.name
|| !r
->in
.keyclass
)
392 return WERR_INVALID_PARAM
;
394 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key
->key
->name
));
396 err
= reg_enumkey(p
->mem_ctx
, key
, r
->in
.enum_index
, (char **)&r
->out
.name
->name
,
397 r
->out
.last_changed_time
);
398 if (!W_ERROR_IS_OK(err
)) {
401 r
->out
.keyclass
->name
= "";
405 /*****************************************************************************
406 Implementation of REG_ENUM_VALUE
407 ****************************************************************************/
409 WERROR
_winreg_EnumValue(pipes_struct
*p
, struct winreg_EnumValue
*r
)
412 struct registry_key
*key
= find_regkey_by_hnd( p
, r
->in
.handle
);
414 struct registry_value
*val
;
415 DATA_BLOB value_blob
;
421 return WERR_INVALID_PARAM
;
423 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
426 err
= reg_enumvalue(p
->mem_ctx
, key
, r
->in
.enum_index
, &valname
, &val
);
427 if (!W_ERROR_IS_OK(err
)) {
431 err
= registry_push_value(p
->mem_ctx
, val
, &value_blob
);
432 if (!W_ERROR_IS_OK(err
)) {
436 if (r
->out
.name
!= NULL
) {
437 r
->out
.name
->name
= valname
;
440 if (r
->out
.type
!= NULL
) {
441 *r
->out
.type
= val
->type
;
444 if (r
->out
.value
!= NULL
) {
445 if ((r
->out
.size
== NULL
) || (r
->out
.length
== NULL
)) {
446 return WERR_INVALID_PARAM
;
449 if (value_blob
.length
> *r
->out
.size
) {
450 return WERR_MORE_DATA
;
453 memcpy( r
->out
.value
, value_blob
.data
, value_blob
.length
);
456 if (r
->out
.length
!= NULL
) {
457 *r
->out
.length
= value_blob
.length
;
459 if (r
->out
.size
!= NULL
) {
460 *r
->out
.size
= value_blob
.length
;
466 /*******************************************************************
468 ********************************************************************/
470 WERROR
_winreg_InitiateSystemShutdown(pipes_struct
*p
, struct winreg_InitiateSystemShutdown
*r
)
472 struct winreg_InitiateSystemShutdownEx s
;
474 s
.in
.hostname
= r
->in
.hostname
;
475 s
.in
.message
= r
->in
.message
;
476 s
.in
.timeout
= r
->in
.timeout
;
477 s
.in
.force_apps
= r
->in
.force_apps
;
478 s
.in
.reboot
= r
->in
.reboot
;
481 /* thunk down to _winreg_InitiateSystemShutdownEx()
482 (just returns a status) */
484 return _winreg_InitiateSystemShutdownEx( p
, &s
);
487 /*******************************************************************
489 ********************************************************************/
491 #define SHUTDOWN_R_STRING "-r"
492 #define SHUTDOWN_F_STRING "-f"
495 WERROR
_winreg_InitiateSystemShutdownEx(pipes_struct
*p
, struct winreg_InitiateSystemShutdownEx
*r
)
497 pstring shutdown_script
;
508 pstrcpy(shutdown_script
, lp_shutdown_script());
510 if ( !*shutdown_script
)
511 return WERR_ACCESS_DENIED
;
513 /* pull the message string and perform necessary sanity checks on it */
517 if ( r
->in
.message
&& r
->in
.message
->name
&& r
->in
.message
->name
->name
) {
518 if ( (msg
= talloc_strdup(p
->mem_ctx
, r
->in
.message
->name
->name
)) == NULL
) {
521 alpha_strcpy (chkmsg
, msg
, NULL
, sizeof(chkmsg
));
524 fstr_sprintf(str_timeout
, "%d", r
->in
.timeout
);
525 fstr_sprintf(reboot
, r
->in
.reboot
? SHUTDOWN_R_STRING
: "");
526 fstr_sprintf(f
, r
->in
.force_apps
? SHUTDOWN_F_STRING
: "");
527 fstr_sprintf(str_reason
, "%d", r
->in
.reason
);
529 all_string_sub( shutdown_script
, "%z", chkmsg
, sizeof(shutdown_script
) );
530 all_string_sub( shutdown_script
, "%t", str_timeout
, sizeof(shutdown_script
) );
531 all_string_sub( shutdown_script
, "%r", reboot
, sizeof(shutdown_script
) );
532 all_string_sub( shutdown_script
, "%f", f
, sizeof(shutdown_script
) );
533 all_string_sub( shutdown_script
, "%x", str_reason
, sizeof(shutdown_script
) );
535 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
537 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
538 Take the error return from the script and provide it as the Windows return code. */
540 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
545 ret
= smbrun( shutdown_script
, NULL
);
550 /********** END SeRemoteShutdownPrivilege BLOCK **********/
552 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
553 shutdown_script
, ret
));
556 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
562 /*******************************************************************
564 ********************************************************************/
566 WERROR
_winreg_AbortSystemShutdown(pipes_struct
*p
, struct winreg_AbortSystemShutdown
*r
)
568 pstring abort_shutdown_script
;
572 pstrcpy(abort_shutdown_script
, lp_abort_shutdown_script());
574 if ( !*abort_shutdown_script
)
575 return WERR_ACCESS_DENIED
;
577 can_shutdown
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_remote_shutdown
);
579 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
584 ret
= smbrun( abort_shutdown_script
, NULL
);
589 /********** END SeRemoteShutdownPrivilege BLOCK **********/
591 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
592 abort_shutdown_script
, ret
));
595 return (ret
== 0) ? WERR_OK
: WERR_ACCESS_DENIED
;
598 /*******************************************************************
599 ********************************************************************/
601 static int validate_reg_filename( pstring fname
)
604 int num_services
= lp_numservices();
609 /* convert to a unix path, stripping the C:\ along the way */
611 if ( !(p
= valid_share_pathname( fname
) ))
614 /* has to exist within a valid file share */
616 for ( snum
=0; snum
<num_services
; snum
++ ) {
618 if ( !lp_snum_ok(snum
) || lp_print_ok(snum
) )
621 pstrcpy( share_path
, lp_pathname(snum
) );
623 /* make sure we have a path (e.g. [homes] ) */
625 if ( strlen( share_path
) == 0 )
628 if ( strncmp( share_path
, p
, strlen( share_path
)) == 0 )
632 /* p and fname are overlapping memory so copy out and back in again */
634 pstrcpy( unix_fname
, p
);
635 pstrcpy( fname
, unix_fname
);
637 return (snum
< num_services
) ? snum
: -1;
640 /*******************************************************************
641 Note: topkeypat is the *full* path that this *key will be
642 loaded into (including the name of the key)
643 ********************************************************************/
645 static WERROR
reg_load_tree( REGF_FILE
*regfile
, const char *topkeypath
,
649 REGISTRY_KEY registry_key
;
651 REGSUBKEY_CTR
*subkeys
;
654 WERROR result
= WERR_OK
;
656 /* initialize the REGISTRY_KEY structure */
658 if ( !(registry_key
.hook
= reghook_cache_find(topkeypath
)) ) {
659 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
664 registry_key
.name
= talloc_strdup( regfile
->mem_ctx
, topkeypath
);
665 if ( !registry_key
.name
) {
666 DEBUG(0,("reg_load_tree: Talloc failed for reg_key.name!\n"));
670 /* now start parsing the values and subkeys */
672 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
675 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
678 /* copy values into the REGVAL_CTR */
680 for ( i
=0; i
<key
->num_values
; i
++ ) {
681 regval_ctr_addvalue( values
, key
->values
[i
].valuename
, key
->values
[i
].type
,
682 (char*)key
->values
[i
].data
, (key
->values
[i
].data_size
& ~VK_DATA_IN_OFFSET
) );
685 /* copy subkeys into the REGSUBKEY_CTR */
687 key
->subkey_index
= 0;
688 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
689 regsubkey_ctr_addkey( subkeys
, subkey
->keyname
);
692 /* write this key and values out */
694 if ( !store_reg_values( ®istry_key
, values
)
695 || !store_reg_keys( ®istry_key
, subkeys
) )
697 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath
));
698 result
= WERR_REG_IO_FAILURE
;
701 TALLOC_FREE( subkeys
);
703 if ( !W_ERROR_IS_OK(result
) )
706 /* now continue to load each subkey registry tree */
708 key
->subkey_index
= 0;
709 while ( (subkey
= regfio_fetch_subkey( regfile
, key
)) ) {
710 pstr_sprintf( path
, "%s%s%s", topkeypath
, "\\", subkey
->keyname
);
711 result
= reg_load_tree( regfile
, path
, subkey
);
712 if ( !W_ERROR_IS_OK(result
) )
719 /*******************************************************************
720 ********************************************************************/
722 static WERROR
restore_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
725 REGF_NK_REC
*rootkey
;
728 /* open the registry file....fail if the file already exists */
730 if ( !(regfile
= regfio_open( fname
, (O_RDONLY
), 0 )) ) {
731 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
732 fname
, strerror(errno
) ));
733 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
736 /* get the rootkey from the regf file and then load the tree
737 via recursive calls */
739 if ( !(rootkey
= regfio_rootkey( regfile
)) ) {
740 regfio_close( regfile
);
741 return WERR_REG_FILE_INVALID
;
744 result
= reg_load_tree( regfile
, krecord
->name
, rootkey
);
748 regfio_close( regfile
);
753 /*******************************************************************
754 ********************************************************************/
756 WERROR
_winreg_RestoreKey(pipes_struct
*p
, struct winreg_RestoreKey
*r
)
758 struct registry_key
*regkey
= find_regkey_by_hnd( p
, r
->in
.handle
);
765 if ( !r
->in
.filename
|| !r
->in
.filename
->name
)
766 return WERR_INVALID_PARAM
;
768 pstrcpy( fname
, r
->in
.filename
->name
);
770 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
771 "\"%s\"\n", regkey
->key
->name
, fname
));
773 if ( (snum
= validate_reg_filename( fname
)) == -1 )
774 return WERR_OBJECT_PATH_INVALID
;
776 /* user must posses SeRestorePrivilege for this this proceed */
778 if ( !user_has_privileges( p
->pipe_user
.nt_user_token
, &se_restore
) )
779 return WERR_ACCESS_DENIED
;
781 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
782 regkey
->key
->name
, fname
, lp_servicename(snum
) ));
784 return restore_registry_key( regkey
->key
, fname
);
787 /********************************************************************
788 ********************************************************************/
790 static WERROR
reg_write_tree( REGF_FILE
*regfile
, const char *keypath
,
791 REGF_NK_REC
*parent
, SEC_DESC
*sec_desc
)
795 REGSUBKEY_CTR
*subkeys
;
798 char *keyname
, *parentpath
;
801 REGISTRY_KEY registry_key
;
802 WERROR result
= WERR_OK
;
805 return WERR_GENERAL_FAILURE
;
808 return WERR_OBJECT_PATH_INVALID
;
810 /* split up the registry key path */
812 pstrcpy( key_tmp
, keypath
);
813 if ( !reg_split_key( key_tmp
, &parentpath
, &keyname
) )
814 return WERR_OBJECT_PATH_INVALID
;
817 keyname
= parentpath
;
819 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
821 ZERO_STRUCT( registry_key
);
823 if ( (registry_key
.name
= talloc_strdup(regfile
->mem_ctx
, keypath
)) == NULL
)
826 if ( (registry_key
.hook
= reghook_cache_find( registry_key
.name
)) == NULL
)
829 /* lookup the values and subkeys */
831 if ( !(subkeys
= TALLOC_ZERO_P( regfile
->mem_ctx
, REGSUBKEY_CTR
)) )
834 if ( !(values
= TALLOC_ZERO_P( subkeys
, REGVAL_CTR
)) )
837 fetch_reg_keys( ®istry_key
, subkeys
);
838 fetch_reg_values( ®istry_key
, values
);
840 /* write out this key */
842 if ( !(key
= regfio_write_key( regfile
, keyname
, values
, subkeys
, sec_desc
, parent
)) ) {
843 result
= WERR_CAN_NOT_COMPLETE
;
847 /* write each one of the subkeys out */
849 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
850 for ( i
=0; i
<num_subkeys
; i
++ ) {
851 subkeyname
= regsubkey_ctr_specific_key( subkeys
, i
);
852 pstr_sprintf( subkeypath
, "%s\\%s", keypath
, subkeyname
);
853 result
= reg_write_tree( regfile
, subkeypath
, key
, sec_desc
);
854 if ( !W_ERROR_IS_OK(result
) )
858 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath
));
861 TALLOC_FREE( subkeys
);
862 TALLOC_FREE( registry_key
.name
);
867 /*******************************************************************
868 ********************************************************************/
870 static WERROR
make_default_reg_sd( TALLOC_CTX
*ctx
, SEC_DESC
**psd
)
872 DOM_SID adm_sid
, owner_sid
;
873 SEC_ACE ace
[2]; /* at most 2 entries */
878 /* set the owner to BUILTIN\Administrator */
880 sid_copy(&owner_sid
, &global_sid_Builtin
);
881 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
884 /* basic access for Everyone */
886 init_sec_access(&mask
, reg_generic_map
.generic_execute
| reg_generic_map
.generic_read
);
887 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
889 /* add Full Access 'BUILTIN\Administrators' */
891 init_sec_access(&mask
, reg_generic_map
.generic_all
);
892 sid_copy(&adm_sid
, &global_sid_Builtin
);
893 sid_append_rid(&adm_sid
, BUILTIN_ALIAS_RID_ADMINS
);
894 init_sec_ace(&ace
[1], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
896 /* create the security descriptor */
898 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 2, ace
)) == NULL
)
901 if ((*psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, &owner_sid
, NULL
, NULL
, psa
, &sd_size
)) == NULL
)
907 /*******************************************************************
908 ********************************************************************/
910 static WERROR
backup_registry_key ( REGISTRY_KEY
*krecord
, const char *fname
)
916 /* open the registry file....fail if the file already exists */
918 if ( !(regfile
= regfio_open( fname
, (O_RDWR
|O_CREAT
|O_EXCL
), (S_IREAD
|S_IWRITE
) )) ) {
919 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
920 fname
, strerror(errno
) ));
921 return ( ntstatus_to_werror(map_nt_error_from_unix( errno
)) );
924 if ( !W_ERROR_IS_OK(result
= make_default_reg_sd( regfile
->mem_ctx
, &sd
)) ) {
925 regfio_close( regfile
);
929 /* write the registry tree to the file */
931 result
= reg_write_tree( regfile
, krecord
->name
, NULL
, sd
);
935 regfio_close( regfile
);
940 /*******************************************************************
941 ********************************************************************/
943 WERROR
_winreg_SaveKey(pipes_struct
*p
, struct winreg_SaveKey
*r
)
945 struct registry_key
*regkey
= find_regkey_by_hnd( p
, r
->in
.handle
);
952 if ( !r
->in
.filename
|| !r
->in
.filename
->name
)
953 return WERR_INVALID_PARAM
;
955 pstrcpy( fname
, r
->in
.filename
->name
);
957 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
958 regkey
->key
->name
, fname
));
960 if ( (snum
= validate_reg_filename( fname
)) == -1 )
961 return WERR_OBJECT_PATH_INVALID
;
963 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
964 regkey
->key
->name
, fname
, lp_servicename(snum
) ));
966 return backup_registry_key( regkey
->key
, fname
);
969 /*******************************************************************
970 ********************************************************************/
972 WERROR
_winreg_SaveKeyEx(pipes_struct
*p
, struct winreg_SaveKeyEx
*r
)
974 /* fill in your code here if you think this call should
977 p
->rng_fault_state
= True
;
978 return WERR_NOT_SUPPORTED
;
981 /*******************************************************************
982 ********************************************************************/
984 WERROR
_winreg_CreateKey( pipes_struct
*p
, struct winreg_CreateKey
*r
)
986 struct registry_key
*parent
= find_regkey_by_hnd(p
, r
->in
.handle
);
987 struct registry_key
*new_key
;
993 result
= reg_createkey(NULL
, parent
, r
->in
.name
.name
, r
->in
.access_mask
,
994 &new_key
, r
->out
.action_taken
);
995 if (!W_ERROR_IS_OK(result
)) {
999 if (!create_policy_hnd(p
, r
->out
.new_handle
, free_regkey
, new_key
)) {
1000 TALLOC_FREE(new_key
);
1001 return WERR_BADFILE
;
1007 /*******************************************************************
1008 ********************************************************************/
1010 WERROR
_winreg_SetValue(pipes_struct
*p
, struct winreg_SetValue
*r
)
1012 struct registry_key
*key
= find_regkey_by_hnd(p
, r
->in
.handle
);
1013 struct registry_value
*val
;
1019 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
1020 key
->key
->name
, r
->in
.name
.name
));
1022 status
= registry_pull_value(p
->mem_ctx
, &val
, r
->in
.type
, r
->in
.data
,
1023 r
->in
.size
, r
->in
.size
);
1024 if (!W_ERROR_IS_OK(status
)) {
1028 return reg_setvalue(key
, r
->in
.name
.name
, val
);
1031 /*******************************************************************
1032 ********************************************************************/
1034 WERROR
_winreg_DeleteKey(pipes_struct
*p
, struct winreg_DeleteKey
*r
)
1036 struct registry_key
*parent
= find_regkey_by_hnd(p
, r
->in
.handle
);
1041 return reg_deletekey(parent
, r
->in
.key
.name
);
1045 /*******************************************************************
1046 ********************************************************************/
1048 WERROR
_winreg_DeleteValue(pipes_struct
*p
, struct winreg_DeleteValue
*r
)
1050 struct registry_key
*key
= find_regkey_by_hnd(p
, r
->in
.handle
);
1055 return reg_deletevalue(key
, r
->in
.value
.name
);
1058 /*******************************************************************
1059 ********************************************************************/
1061 WERROR
_winreg_GetKeySecurity(pipes_struct
*p
, struct winreg_GetKeySecurity
*r
)
1063 struct registry_key
*key
= find_regkey_by_hnd(p
, r
->in
.handle
);
1065 struct security_descriptor
*secdesc
;
1072 /* access checks first */
1074 if ( !(key
->key
->access_granted
& STD_RIGHT_READ_CONTROL_ACCESS
) )
1075 return WERR_ACCESS_DENIED
;
1077 err
= regkey_get_secdesc(p
->mem_ctx
, key
->key
, &secdesc
);
1078 if (!W_ERROR_IS_OK(err
)) {
1082 err
= ntstatus_to_werror(marshall_sec_desc(p
->mem_ctx
, secdesc
,
1084 if (!W_ERROR_IS_OK(err
)) {
1088 if (len
> r
->out
.sd
->size
) {
1089 r
->out
.sd
->size
= len
;
1090 return WERR_INSUFFICIENT_BUFFER
;
1093 r
->out
.sd
->size
= len
;
1094 r
->out
.sd
->len
= len
;
1095 r
->out
.sd
->data
= data
;
1100 /*******************************************************************
1101 ********************************************************************/
1103 WERROR
_winreg_SetKeySecurity(pipes_struct
*p
, struct winreg_SetKeySecurity
*r
)
1105 struct registry_key
*key
= find_regkey_by_hnd(p
, r
->in
.handle
);
1106 struct security_descriptor
*secdesc
;
1112 /* access checks first */
1114 if ( !(key
->key
->access_granted
& STD_RIGHT_WRITE_DAC_ACCESS
) )
1115 return WERR_ACCESS_DENIED
;
1117 err
= ntstatus_to_werror(unmarshall_sec_desc(p
->mem_ctx
, r
->in
.sd
->data
,
1118 r
->in
.sd
->len
, &secdesc
));
1119 if (!W_ERROR_IS_OK(err
)) {
1123 return regkey_set_secdesc(key
->key
, secdesc
);
1126 /*******************************************************************
1127 ********************************************************************/
1129 WERROR
_winreg_FlushKey(pipes_struct
*p
, struct winreg_FlushKey
*r
)
1131 /* I'm just replying OK because there's not a lot
1132 here I see to do i --jerry */
1137 /*******************************************************************
1138 ********************************************************************/
1140 WERROR
_winreg_UnLoadKey(pipes_struct
*p
, struct winreg_UnLoadKey
*r
)
1142 /* fill in your code here if you think this call should
1145 p
->rng_fault_state
= True
;
1146 return WERR_NOT_SUPPORTED
;
1149 /*******************************************************************
1150 ********************************************************************/
1152 WERROR
_winreg_ReplaceKey(pipes_struct
*p
, struct winreg_ReplaceKey
*r
)
1154 /* fill in your code here if you think this call should
1157 p
->rng_fault_state
= True
;
1158 return WERR_NOT_SUPPORTED
;
1161 /*******************************************************************
1162 ********************************************************************/
1164 WERROR
_winreg_LoadKey(pipes_struct
*p
, struct winreg_LoadKey
*r
)
1166 /* fill in your code here if you think this call should
1169 p
->rng_fault_state
= True
;
1170 return WERR_NOT_SUPPORTED
;
1173 /*******************************************************************
1174 ********************************************************************/
1176 WERROR
_winreg_NotifyChangeKeyValue(pipes_struct
*p
, struct winreg_NotifyChangeKeyValue
*r
)
1178 /* fill in your code here if you think this call should
1181 p
->rng_fault_state
= True
;
1182 return WERR_NOT_SUPPORTED
;
1185 /*******************************************************************
1186 ********************************************************************/
1188 WERROR
_winreg_QueryMultipleValues(pipes_struct
*p
, struct winreg_QueryMultipleValues
*r
)
1190 /* fill in your code here if you think this call should
1193 p
->rng_fault_state
= True
;
1194 return WERR_NOT_SUPPORTED
;
1197 /*******************************************************************
1198 ********************************************************************/
1200 WERROR
_winreg_QueryMultipleValues2(pipes_struct
*p
, struct winreg_QueryMultipleValues2
*r
)
1202 /* fill in your code here if you think this call should
1205 p
->rng_fault_state
= True
;
1206 return WERR_NOT_SUPPORTED
;