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 2 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, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* Implementation of registry functions. */
28 #define DBGC_CLASS DBGC_RPC_SRV
30 static struct generic_mapping reg_generic_map =
31 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
35 REGVAL_CTR *value_cache;
36 REGSUBKEY_CTR *subkey_cache;
39 /******************************************************************
40 free() function for struct regkey_info
41 *****************************************************************/
43 static void free_regkey_info(void *ptr)
45 struct regkey_info *info = (struct regkey_info *)ptr;
49 /******************************************************************
50 Find a registry key handle and return a REGISTRY_KEY
51 *****************************************************************/
53 static struct regkey_info *find_regkey_info_by_hnd(pipes_struct *p,
56 struct regkey_info *regkey = NULL;
58 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
59 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
66 static REGISTRY_KEY *find_regkey_by_hnd(pipes_struct *p, POLICY_HND *hnd)
68 struct regkey_info *regkey = find_regkey_info_by_hnd(p, hnd);
77 static WERROR fill_value_cache(struct regkey_info *info)
79 if (info->value_cache != NULL) {
83 if (!(info->value_cache = TALLOC_ZERO_P(info, REGVAL_CTR))) {
87 if (fetch_reg_values(info->key, info->value_cache) == -1) {
88 TALLOC_FREE(info->value_cache);
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
99 When we open a key, we store the full path to the key as
100 HK[LM|U]\<key>\<key>\...
101 *******************************************************************/
103 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
104 struct regkey_info **pinfo,
105 REGISTRY_KEY *parent,
106 const char *subkeyname,
107 uint32 access_desired )
109 WERROR result = WERR_OK;
110 struct regkey_info *info;
112 /* create a full registry path and strip any trailing '\'
115 if (!(info = TALLOC_ZERO_P(NULL, struct regkey_info))) {
119 /* now do the internal open */
121 result = regkey_open_internal( info, parent, &info->key, subkeyname,
122 p->pipe_user.nt_user_token,
125 if ( !W_ERROR_IS_OK(result) ) {
130 if ( !create_policy_hnd( p, hnd, free_regkey_info, info ) ) {
142 /*******************************************************************
143 Function for open a new registry handle and creating a handle
144 Note that P should be valid & hnd should already have space
145 *******************************************************************/
147 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
149 REGISTRY_KEY *regkey = find_regkey_by_hnd(p, hnd);
152 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
156 close_policy_hnd(p, hnd);
161 /********************************************************************
162 retrieve information about the subkeys
163 *******************************************************************/
165 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
169 REGSUBKEY_CTR *subkeys;
175 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
178 if ( fetch_reg_keys( key, subkeys ) == -1 )
181 /* find the longest string */
184 num_subkeys = regsubkey_ctr_numkeys( subkeys );
186 for ( i=0; i<num_subkeys; i++ ) {
187 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
188 max_len = MAX(max_len, len);
191 *maxnum = num_subkeys;
194 TALLOC_FREE( subkeys );
199 /********************************************************************
200 retrieve information about the values.
201 *******************************************************************/
203 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
204 uint32 *maxlen, uint32 *maxsize )
207 uint32 sizemax, lenmax;
213 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
216 if ( fetch_reg_values( key, values ) == -1 )
219 lenmax = sizemax = 0;
220 num_values = regval_ctr_numvals( values );
222 for ( i=0; i<num_values; i++ ) {
225 if (!(val = regval_ctr_specific_value( values, i ))) {
229 lenmax = MAX(lenmax, val->valuename ?
230 strlen(val->valuename)+1 : 0 );
231 sizemax = MAX(sizemax, val->size );
234 *maxnum = num_values;
238 TALLOC_FREE( values );
244 /********************************************************************
246 ********************************************************************/
248 WERROR _winreg_CloseKey(pipes_struct *p, struct policy_handle *handle)
250 /* close the policy handle */
252 if (!close_registry_key(p, handle))
258 /*******************************************************************
259 ********************************************************************/
261 WERROR _winreg_OpenHKLM(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
263 return open_registry_key(p, handle, NULL, NULL, KEY_HKLM, access_mask);
266 /*******************************************************************
267 ********************************************************************/
269 WERROR _winreg_OpenHKPD(pipes_struct *p, uint16_t *system_name,
270 uint32_t access_mask, struct policy_handle *handle)
272 return open_registry_key(p, handle, NULL, NULL, KEY_HKPD, access_mask);
275 /*******************************************************************
276 ********************************************************************/
278 WERROR _winreg_OpenHKPT(pipes_struct *p, uint16_t *system_name,
279 uint32_t access_mask, struct policy_handle *handle)
281 return open_registry_key(p, handle, NULL, NULL, KEY_HKPT, access_mask);
284 /*******************************************************************
285 ********************************************************************/
287 WERROR _winreg_OpenHKCR(pipes_struct *p, uint16_t *system_name,
288 uint32_t access_mask, struct policy_handle *handle)
290 return open_registry_key(p, handle, NULL, NULL, KEY_HKCR, access_mask);
293 /*******************************************************************
294 ********************************************************************/
296 WERROR _winreg_OpenHKU(pipes_struct *p, uint16_t *system_name,
297 uint32_t access_mask, struct policy_handle *handle)
299 return open_registry_key(p, handle, NULL, NULL, KEY_HKU, access_mask);
302 /*******************************************************************
303 ********************************************************************/
305 WERROR _winreg_OpenHKCU(pipes_struct *p, uint16_t *system_name,
306 uint32_t access_mask, struct policy_handle *handle)
308 return open_registry_key(p, handle, NULL, NULL, KEY_HKCU, access_mask);
311 /*******************************************************************
312 ********************************************************************/
314 WERROR _winreg_OpenHKCC(pipes_struct *p, uint16_t *system_name,
315 uint32_t access_mask, struct policy_handle *handle)
317 return open_registry_key(p, handle, NULL, NULL, KEY_HKCC, access_mask);
320 /*******************************************************************
321 ********************************************************************/
323 WERROR _winreg_OpenHKDD(pipes_struct *p, uint16_t *system_name,
324 uint32_t access_mask, struct policy_handle *handle)
326 return open_registry_key(p, handle, NULL, NULL, KEY_HKDD, access_mask);
329 /*******************************************************************
330 ********************************************************************/
332 WERROR _winreg_OpenHKPN(pipes_struct *p, uint16_t *system_name,
333 uint32_t access_mask, struct policy_handle *handle)
335 return open_registry_key(p, handle, NULL, NULL, KEY_HKPN, access_mask);
338 /*******************************************************************
340 ********************************************************************/
342 WERROR _winreg_OpenKey(pipes_struct *p, struct policy_handle *parent_handle, struct winreg_String keyname, uint32_t unknown, uint32_t access_mask, struct policy_handle *handle)
345 REGISTRY_KEY *parent = find_regkey_by_hnd(p, parent_handle );
351 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
352 return WERR_INVALID_PARAM;
355 /* check granted access first; what is the correct mask here? */
357 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
358 SEC_RIGHTS_CREATE_SUBKEY|
359 SEC_RIGHTS_QUERY_VALUE|
360 SEC_RIGHTS_SET_VALUE);
362 if ( !(parent->access_granted & check_rights) ) {
363 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
364 return WERR_ACCESS_DENIED;
368 * very crazy, but regedit.exe on Win2k will attempt to call
369 * REG_OPEN_ENTRY with a keyname of "". We should return a new
370 * (second) handle here on the key->name. regedt32.exe does
371 * not do this stupidity. --jerry
374 return open_registry_key( p, handle, NULL, parent, name, access_mask );
377 /*******************************************************************
379 ********************************************************************/
381 WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
382 struct winreg_String value_name,
383 enum winreg_Type *type, uint8_t *data,
384 uint32_t *data_size, uint32_t *value_length)
386 WERROR status = WERR_BADFILE;
387 struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
388 REGISTRY_KEY *regkey;
392 uint32_t outbuf_size;
394 BOOL free_buf = False;
395 BOOL free_prs = False;
402 *value_length = *type = 0;
404 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
405 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
407 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
408 if(regkey->type == REG_KEY_HKPD)
410 if(strequal(value_name.name, "Global")) {
411 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
412 status = reg_perfcount_get_hkpd(
413 &prs_hkpd, *data_size, &outbuf_size, NULL);
414 outbuf = (uint8_t *)prs_hkpd.data_p;
417 else if(strequal(value_name.name, "Counter 009")) {
418 outbuf_size = reg_perfcount_get_counter_names(
419 reg_perfcount_get_base_index(),
420 (char **)(void *)&outbuf);
423 else if(strequal(value_name.name, "Explain 009")) {
424 outbuf_size = reg_perfcount_get_counter_help(
425 reg_perfcount_get_base_index(),
426 (char **)(void *)&outbuf);
429 else if(isdigit(value_name.name[0])) {
430 /* we probably have a request for a specific object
432 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
433 status = reg_perfcount_get_hkpd(
434 &prs_hkpd, *data_size, &outbuf_size,
436 outbuf = (uint8_t *)prs_hkpd.data_p;
440 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
448 REGISTRY_VALUE *val = NULL;
451 status = fill_value_cache(info);
453 if (!(W_ERROR_IS_OK(status))) {
457 for (i=0; i<info->value_cache->num_values; i++) {
458 if (strequal(info->value_cache->values[i]->valuename,
460 val = info->value_cache->values[i];
475 outbuf = val->data_p;
476 outbuf_size = val->size;
480 *value_length = outbuf_size;
482 if ( *data_size == 0 || !data ) {
484 } else if ( *value_length > *data_size ) {
485 status = WERR_MORE_DATA;
487 memcpy( data, outbuf, *value_length );
491 *data_size = *value_length;
493 if (free_prs) prs_mem_free(&prs_hkpd);
494 if (free_buf) SAFE_FREE(outbuf);
499 /*****************************************************************************
500 Implementation of REG_QUERY_KEY
501 ****************************************************************************/
503 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle,
504 struct winreg_String *classname,
505 uint32_t *num_subkeys, uint32_t *max_subkeylen,
506 uint32_t *max_subkeysize,
507 uint32_t *num_values, uint32_t *max_valnamelen,
508 uint32_t *max_valbufsize,
509 uint32_t *secdescsize, NTTIME *last_changed_time)
511 WERROR status = WERR_OK;
512 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
517 if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
518 DEBUG(0,("_winreg_QueryInfoKey: get_subkey_information() failed!\n"));
519 return WERR_ACCESS_DENIED;
522 if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
523 DEBUG(0,("_winreg_QueryInfoKey: get_value_information() failed!\n"));
524 return WERR_ACCESS_DENIED;
527 *secdescsize = 0; /* used to be hard coded for 0x00000078 */
528 *last_changed_time = 0;
529 *max_subkeysize = 0; /* maybe this is the classname length ? */
531 /* don't bother with class names for now */
533 classname->name = NULL;
539 /*****************************************************************************
540 Implementation of REG_GETVERSION
541 ****************************************************************************/
543 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
545 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
550 *version = 0x00000005; /* Windows 2000 registry API version */
556 /*****************************************************************************
557 Implementation of REG_ENUM_KEY
558 ****************************************************************************/
560 WERROR _winreg_EnumKey(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, struct winreg_StringBuf *keyclass, NTTIME *last_changed_time)
562 WERROR status = WERR_OK;
563 struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
564 REGISTRY_KEY *regkey;
571 if ( !name || !keyclass )
572 return WERR_INVALID_PARAM;
574 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
576 if (!info->subkey_cache) {
577 if (!(info->subkey_cache = TALLOC_ZERO_P(
578 info, REGSUBKEY_CTR))) {
582 if (fetch_reg_keys(regkey, info->subkey_cache) == -1) {
583 TALLOC_FREE(info->subkey_cache);
584 return WERR_NO_MORE_ITEMS;
588 if (enum_index >= info->subkey_cache->num_subkeys) {
589 return WERR_NO_MORE_ITEMS;
592 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n",
593 info->subkey_cache->subkeys[enum_index]));
595 if (!(name->name = talloc_strdup(
596 p->mem_ctx, info->subkey_cache->subkeys[enum_index]))) {
599 if ( last_changed_time ) {
600 *last_changed_time = 0;
607 /*****************************************************************************
608 Implementation of REG_ENUM_VALUE
609 ****************************************************************************/
611 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle,
612 uint32_t enum_index, struct winreg_ValNameBuf *name,
613 enum winreg_Type *type, uint8_t *data,
614 uint32_t *data_size, uint32_t *value_length)
616 WERROR status = WERR_OK;
617 struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
618 REGISTRY_KEY *regkey;
619 REGISTRY_VALUE *val = NULL;
625 return WERR_INVALID_PARAM;
629 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
632 status = fill_value_cache(info);
633 if (!W_ERROR_IS_OK(status)) {
637 if (enum_index >= info->value_cache->num_values) {
641 val = info->value_cache->values[enum_index];
643 if (!(name->name = talloc_strdup(p->mem_ctx, val->valuename))) {
652 if ((data_size == NULL) || (value_length == NULL)) {
653 return WERR_INVALID_PARAM;
656 if (val->size > *data_size) {
657 return WERR_MORE_DATA;
660 memcpy( data, val->data_p, val->size );
663 if (value_length != NULL) {
664 *value_length = val->size;
666 if (data_size != NULL) {
667 *data_size = val->size;
673 /*******************************************************************
675 ********************************************************************/
677 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
681 /* thunk down to _winreg_InitiateSystemShutdownEx()
682 (just returns a status) */
684 return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout,
685 force_apps, reboot, reason );
688 /*******************************************************************
690 ********************************************************************/
692 #define SHUTDOWN_R_STRING "-r"
693 #define SHUTDOWN_F_STRING "-f"
696 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot, uint32_t reason)
698 pstring shutdown_script;
709 pstrcpy(shutdown_script, lp_shutdown_script());
711 if ( !*shutdown_script )
712 return WERR_ACCESS_DENIED;
714 /* pull the message string and perform necessary sanity checks on it */
718 if ( message && message->name && message->name->name ) {
719 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
722 alpha_strcpy (chkmsg, msg, NULL, sizeof(chkmsg));
725 fstr_sprintf(str_timeout, "%d", timeout);
726 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
727 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
728 fstr_sprintf(str_reason, "%d", reason );
730 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
731 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
732 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
733 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
734 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
736 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
738 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
739 Take the error return from the script and provide it as the Windows return code. */
741 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
746 ret = smbrun( shutdown_script, NULL );
751 /********** END SeRemoteShutdownPrivilege BLOCK **********/
753 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
754 shutdown_script, ret));
757 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
763 /*******************************************************************
765 ********************************************************************/
767 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
769 pstring abort_shutdown_script;
773 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
775 if ( !*abort_shutdown_script )
776 return WERR_ACCESS_DENIED;
778 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
780 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
785 ret = smbrun( abort_shutdown_script, NULL );
790 /********** END SeRemoteShutdownPrivilege BLOCK **********/
792 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
793 abort_shutdown_script, ret));
796 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
799 /*******************************************************************
800 ********************************************************************/
802 static int validate_reg_filename( pstring fname )
805 int num_services = lp_numservices();
810 /* convert to a unix path, stripping the C:\ along the way */
812 if ( !(p = valid_share_pathname( fname ) ))
815 /* has to exist within a valid file share */
817 for ( snum=0; snum<num_services; snum++ ) {
819 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
822 pstrcpy( share_path, lp_pathname(snum) );
824 /* make sure we have a path (e.g. [homes] ) */
826 if ( strlen( share_path ) == 0 )
829 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
833 /* p and fname are overlapping memory so copy out and back in again */
835 pstrcpy( unix_fname, p );
836 pstrcpy( fname, unix_fname );
838 return (snum < num_services) ? snum : -1;
841 /*******************************************************************
842 Note: topkeypat is the *full* path that this *key will be
843 loaded into (including the name of the key)
844 ********************************************************************/
846 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
850 REGISTRY_KEY registry_key;
852 REGSUBKEY_CTR *subkeys;
855 WERROR result = WERR_OK;
857 /* initialize the REGISTRY_KEY structure */
859 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
860 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
864 pstrcpy( registry_key.name, topkeypath );
866 /* now start parsing the values and subkeys */
868 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
871 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
874 /* copy values into the REGVAL_CTR */
876 for ( i=0; i<key->num_values; i++ ) {
877 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
878 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
881 /* copy subkeys into the REGSUBKEY_CTR */
883 key->subkey_index = 0;
884 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
885 regsubkey_ctr_addkey( subkeys, subkey->keyname );
888 /* write this key and values out */
890 if ( !store_reg_values( ®istry_key, values )
891 || !store_reg_keys( ®istry_key, subkeys ) )
893 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
894 result = WERR_REG_IO_FAILURE;
897 TALLOC_FREE( subkeys );
899 if ( !W_ERROR_IS_OK(result) )
902 /* now continue to load each subkey registry tree */
904 key->subkey_index = 0;
905 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
906 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
907 result = reg_load_tree( regfile, path, subkey );
908 if ( !W_ERROR_IS_OK(result) )
915 /*******************************************************************
916 ********************************************************************/
918 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
921 REGF_NK_REC *rootkey;
924 /* open the registry file....fail if the file already exists */
926 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
927 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
928 fname, strerror(errno) ));
929 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
932 /* get the rootkey from the regf file and then load the tree
933 via recursive calls */
935 if ( !(rootkey = regfio_rootkey( regfile )) ) {
936 regfio_close( regfile );
937 return WERR_REG_FILE_INVALID;
940 result = reg_load_tree( regfile, krecord->name, rootkey );
944 regfio_close( regfile );
949 /*******************************************************************
950 ********************************************************************/
952 WERROR _winreg_RestoreKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, uint32_t flags)
954 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
961 if ( !filename || !filename->name )
962 return WERR_INVALID_PARAM;
964 pstrcpy( fname, filename->name );
966 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from \"%s\"\n", regkey->name, fname));
968 if ( (snum = validate_reg_filename( fname )) == -1 )
969 return WERR_OBJECT_PATH_INVALID;
971 /* user must posses SeRestorePrivilege for this this proceed */
973 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
974 return WERR_ACCESS_DENIED;
976 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
978 return restore_registry_key( regkey, fname );
981 /********************************************************************
982 ********************************************************************/
984 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
985 REGF_NK_REC *parent, SEC_DESC *sec_desc )
989 REGSUBKEY_CTR *subkeys;
992 char *keyname, *parentpath;
995 REGISTRY_KEY registry_key;
996 WERROR result = WERR_OK;
999 return WERR_GENERAL_FAILURE;
1002 return WERR_OBJECT_PATH_INVALID;
1004 /* split up the registry key path */
1006 pstrcpy( key_tmp, keypath );
1007 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
1008 return WERR_OBJECT_PATH_INVALID;
1011 keyname = parentpath;
1013 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
1015 ZERO_STRUCT( registry_key );
1017 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
1020 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
1021 return WERR_BADFILE;
1023 /* lookup the values and subkeys */
1025 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
1028 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
1031 fetch_reg_keys( ®istry_key, subkeys );
1032 fetch_reg_values( ®istry_key, values );
1034 /* write out this key */
1036 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1037 result = WERR_CAN_NOT_COMPLETE;
1041 /* write each one of the subkeys out */
1043 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1044 for ( i=0; i<num_subkeys; i++ ) {
1045 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1046 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1047 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1048 if ( !W_ERROR_IS_OK(result) )
1052 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1055 TALLOC_FREE( subkeys );
1056 TALLOC_FREE( registry_key.name );
1061 /*******************************************************************
1062 ********************************************************************/
1064 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1066 DOM_SID adm_sid, owner_sid;
1067 SEC_ACE ace[2]; /* at most 2 entries */
1069 SEC_ACL *psa = NULL;
1072 /* set the owner to BUILTIN\Administrator */
1074 sid_copy(&owner_sid, &global_sid_Builtin);
1075 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1078 /* basic access for Everyone */
1080 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1081 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1083 /* add Full Access 'BUILTIN\Administrators' */
1085 init_sec_access(&mask, reg_generic_map.generic_all);
1086 sid_copy(&adm_sid, &global_sid_Builtin);
1087 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1088 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1090 /* create the security descriptor */
1092 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1095 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1101 /*******************************************************************
1102 ********************************************************************/
1104 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1108 SEC_DESC *sd = NULL;
1110 /* open the registry file....fail if the file already exists */
1112 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1113 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1114 fname, strerror(errno) ));
1115 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1118 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1119 regfio_close( regfile );
1123 /* write the registry tree to the file */
1125 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1129 regfio_close( regfile );
1134 /*******************************************************************
1135 ********************************************************************/
1137 WERROR _winreg_SaveKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, struct KeySecurityAttribute *sec_attrib)
1139 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
1146 if ( !filename || !filename->name )
1147 return WERR_INVALID_PARAM;
1149 pstrcpy( fname, filename->name );
1151 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n", regkey->name, fname));
1153 if ( (snum = validate_reg_filename( fname )) == -1 )
1154 return WERR_OBJECT_PATH_INVALID;
1156 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
1158 return backup_registry_key( regkey, fname );
1161 /*******************************************************************
1162 ********************************************************************/
1164 WERROR _winreg_SaveKeyEx(pipes_struct *p)
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_CreateKey( pipes_struct *p, struct policy_handle *handle,
1177 struct winreg_String keyname,
1178 struct winreg_String keyclass,
1179 uint32_t options, uint32_t access_mask,
1180 struct winreg_SecBuf *secdesc,
1181 struct policy_handle *new_handle,
1182 enum winreg_CreateAction *action_taken )
1184 struct regkey_info *parent = find_regkey_info_by_hnd(p, handle);
1185 struct regkey_info *newparentinfo, *keyinfo;
1186 POLICY_HND newparent_handle;
1187 REGSUBKEY_CTR *subkeys;
1195 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1199 /* ok. Here's what we do. */
1201 if ( strrchr( name, '\\' ) ) {
1205 /* (1) check for enumerate rights on the parent handle.
1206 Clients can try create things like 'SOFTWARE\Samba' on
1207 the HKLM handle. (2) open the path to the child parent
1210 if ( !(parent->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1211 return WERR_ACCESS_DENIED;
1213 pstrcpy( newkeyname, name );
1214 ptr = strrchr( newkeyname, '\\' );
1217 result = open_registry_key( p, &newparent_handle,
1219 parent->key, newkeyname,
1220 (REG_KEY_READ|REG_KEY_WRITE) );
1222 if ( !W_ERROR_IS_OK(result) )
1225 /* copy the new key name (just the lower most keyname) */
1227 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1232 /* use the existing open key information */
1233 newparentinfo = parent;
1234 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1237 /* (3) check for create subkey rights on the correct parent */
1239 if ( !(newparentinfo->key->access_granted
1240 & SEC_RIGHTS_CREATE_SUBKEY) ) {
1241 result = WERR_ACCESS_DENIED;
1245 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1246 result = WERR_NOMEM;
1250 /* (4) lookup the current keys and add the new one */
1252 fetch_reg_keys( newparentinfo->key, subkeys );
1253 regsubkey_ctr_addkey( subkeys, name );
1255 /* now write to the registry backend */
1257 write_result = store_reg_keys( newparentinfo->key, subkeys );
1259 TALLOC_FREE( subkeys );
1260 TALLOC_FREE( newparentinfo->subkey_cache );
1262 if ( !write_result )
1263 return WERR_REG_IO_FAILURE;
1265 /* (5) open the new key and return the handle. Note that it is probably
1266 not correct to grant full access on this open handle. */
1268 result = open_registry_key( p, new_handle, &keyinfo,
1269 newparentinfo->key, name, REG_KEY_READ );
1270 keyinfo->key->access_granted = REG_KEY_ALL;
1272 /* FIXME: report the truth here */
1274 if ( action_taken ) {
1275 *action_taken = REG_CREATED_NEW_KEY;
1279 /* close any intermediate key handles */
1281 if ( newparentinfo != parent )
1282 close_registry_key( p, &newparent_handle );
1288 /*******************************************************************
1289 ********************************************************************/
1291 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1293 struct regkey_info *info = find_regkey_info_by_hnd(p, handle);
1303 /* access checks first */
1305 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1306 return WERR_ACCESS_DENIED;
1308 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name,
1311 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1314 /* lookup the current values and add the new one */
1316 fetch_reg_values( key, values );
1318 regval_ctr_addvalue( values, name.name, type,
1319 (const char *)data, size );
1321 /* now write to the registry backend */
1323 write_result = store_reg_values( key, values );
1325 TALLOC_FREE( values );
1327 if ( !write_result )
1328 return WERR_REG_IO_FAILURE;
1330 TALLOC_FREE(info->value_cache);
1335 /*******************************************************************
1336 ********************************************************************/
1338 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1340 struct regkey_info *parent = find_regkey_info_by_hnd(p, handle);
1341 struct regkey_info *newparentinfo = NULL;
1342 POLICY_HND newparent_handle;
1343 REGSUBKEY_CTR *subkeys;
1351 /* MSDN says parent the handle must have been opened with DELETE access */
1353 /* (1) check for delete rights on the parent */
1355 if ( !(parent->key->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1356 result = WERR_ACCESS_DENIED;
1360 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1361 result = WERR_INVALID_PARAM;
1365 /* ok. Here's what we do. */
1367 if ( strrchr( name, '\\' ) ) {
1371 /* (2) open the path to the child parent key if necessary */
1372 /* split the registry path and save the subkeyname */
1374 pstrcpy( newkeyname, name );
1375 ptr = strrchr( newkeyname, '\\' );
1377 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1378 result = WERR_NOMEM;
1382 result = open_registry_key( p, &newparent_handle,
1383 &newparentinfo, parent->key,
1385 (REG_KEY_READ|REG_KEY_WRITE) );
1386 if ( !W_ERROR_IS_OK(result) ) {
1391 /* use the existing open key information */
1392 newparentinfo = parent;
1395 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1396 result = WERR_NOMEM;
1400 /* lookup the current keys and delete the new one */
1402 fetch_reg_keys( newparentinfo->key, subkeys );
1404 regsubkey_ctr_delkey( subkeys, name );
1406 /* now write to the registry backend */
1408 write_result = store_reg_keys( newparentinfo->key, subkeys );
1410 TALLOC_FREE( subkeys );
1411 TALLOC_FREE( newparentinfo->subkey_cache );
1413 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1416 /* close any intermediate key handles */
1418 if ( newparentinfo != parent )
1419 close_registry_key( p, &newparent_handle );
1425 /*******************************************************************
1426 ********************************************************************/
1428 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1430 struct regkey_info *info = find_regkey_info_by_hnd(p, handle);
1441 /* access checks first */
1443 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1444 return WERR_ACCESS_DENIED;
1446 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1447 return WERR_INVALID_PARAM;
1450 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1452 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1455 /* lookup the current values and add the new one */
1457 fetch_reg_values( key, values );
1459 regval_ctr_delvalue( values, valuename );
1461 /* now write to the registry backend */
1463 write_result = store_reg_values( key, values );
1465 TALLOC_FREE( values );
1467 if ( !write_result )
1468 return WERR_REG_IO_FAILURE;
1470 TALLOC_FREE(info->value_cache);
1475 /*******************************************************************
1476 ********************************************************************/
1478 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1480 REGISTRY_KEY *key = find_regkey_by_hnd(p, handle);
1482 struct security_descriptor *secdesc;
1489 /* access checks first */
1491 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1492 return WERR_ACCESS_DENIED;
1494 err = regkey_get_secdesc(p->mem_ctx, key, &secdesc);
1495 if (!W_ERROR_IS_OK(err)) {
1499 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1501 if (!W_ERROR_IS_OK(err)) {
1505 if (len > sd->size) {
1507 return WERR_INSUFFICIENT_BUFFER;
1517 /*******************************************************************
1518 ********************************************************************/
1520 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1522 REGISTRY_KEY *key = find_regkey_by_hnd(p, handle);
1523 struct security_descriptor *secdesc;
1529 /* access checks first */
1531 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1532 return WERR_ACCESS_DENIED;
1534 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, sd->data,
1535 sd->len, &secdesc));
1536 if (!W_ERROR_IS_OK(err)) {
1540 return regkey_set_secdesc(key, secdesc);
1543 /*******************************************************************
1544 ********************************************************************/
1546 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1548 /* I'm just replying OK because there's not a lot
1549 here I see to do i --jerry */
1554 /*******************************************************************
1555 ********************************************************************/
1557 WERROR _winreg_UnLoadKey(pipes_struct *p)
1559 /* fill in your code here if you think this call should
1562 p->rng_fault_state = True;
1563 return WERR_NOT_SUPPORTED;
1566 /*******************************************************************
1567 ********************************************************************/
1569 WERROR _winreg_ReplaceKey(pipes_struct *p)
1571 /* fill in your code here if you think this call should
1574 p->rng_fault_state = True;
1575 return WERR_NOT_SUPPORTED;
1578 /*******************************************************************
1579 ********************************************************************/
1581 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1583 /* fill in your code here if you think this call should
1586 p->rng_fault_state = True;
1587 return WERR_NOT_SUPPORTED;
1590 /*******************************************************************
1591 ********************************************************************/
1593 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct policy_handle *handle, uint8_t watch_subtree, uint32_t notify_filter, uint32_t unknown, struct winreg_String string1, struct winreg_String string2, uint32_t unknown2)
1595 /* fill in your code here if you think this call should
1598 p->rng_fault_state = True;
1599 return WERR_NOT_SUPPORTED;
1602 /*******************************************************************
1603 ********************************************************************/
1605 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct policy_handle *key_handle, struct QueryMultipleValue *values, uint32_t num_values, uint8_t *buffer, uint32_t *buffer_size)
1607 /* fill in your code here if you think this call should
1610 p->rng_fault_state = True;
1611 return WERR_NOT_SUPPORTED;
1614 /*******************************************************************
1615 ********************************************************************/
1617 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1619 /* fill in your code here if you think this call should
1622 p->rng_fault_state = True;
1623 return WERR_NOT_SUPPORTED;