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 };
33 /******************************************************************
34 free() function for REGISTRY_KEY
35 *****************************************************************/
37 static void free_regkey_info(void *ptr)
39 regkey_close_internal( (REGISTRY_KEY*)ptr );
42 /******************************************************************
43 Find a registry key handle and return a REGISTRY_KEY
44 *****************************************************************/
46 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
48 REGISTRY_KEY *regkey = NULL;
50 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
51 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 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
69 const char *subkeyname, uint32 access_desired )
73 WERROR result = WERR_OK;
75 /* create a full registry path and strip any trailing '\'
78 pstr_sprintf( keypath, "%s%s%s",
79 parent ? parent->name : "",
83 path_len = strlen( keypath );
84 if ( path_len && keypath[path_len-1] == '\\' )
85 keypath[path_len-1] = '\0';
87 /* now do the internal open */
89 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
90 if ( !W_ERROR_IS_OK(result) )
93 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
94 result = WERR_BADFILE;
95 regkey_close_internal( *keyinfo );
101 /*******************************************************************
102 Function for open a new registry handle and creating a handle
103 Note that P should be valid & hnd should already have space
104 *******************************************************************/
106 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
108 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
111 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
115 close_policy_hnd(p, hnd);
120 /********************************************************************
121 retrieve information about the subkeys
122 *******************************************************************/
124 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
128 REGSUBKEY_CTR *subkeys;
134 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
137 if ( fetch_reg_keys( key, subkeys ) == -1 )
140 /* find the longest string */
143 num_subkeys = regsubkey_ctr_numkeys( subkeys );
145 for ( i=0; i<num_subkeys; i++ ) {
146 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
147 max_len = MAX(max_len, len);
150 *maxnum = num_subkeys;
153 TALLOC_FREE( subkeys );
158 /********************************************************************
159 retrieve information about the values.
160 *******************************************************************/
162 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
163 uint32 *maxlen, uint32 *maxsize )
167 uint32 sizemax, lenmax;
173 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
176 if ( fetch_reg_values( key, values ) == -1 )
179 lenmax = sizemax = 0;
180 num_values = regval_ctr_numvals( values );
182 val = regval_ctr_specific_value( values, 0 );
184 for ( i=0; i<num_values && val; i++ )
186 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
187 sizemax = MAX(sizemax, val->size );
189 val = regval_ctr_specific_value( values, i );
192 *maxnum = num_values;
196 TALLOC_FREE( values );
202 /********************************************************************
204 ********************************************************************/
206 WERROR _winreg_CloseKey(pipes_struct *p, struct policy_handle *handle)
208 /* close the policy handle */
210 if (!close_registry_key(p, handle))
216 /*******************************************************************
217 ********************************************************************/
219 WERROR _winreg_OpenHKLM(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
221 REGISTRY_KEY *keyinfo;
223 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKLM, access_mask );
226 /*******************************************************************
227 ********************************************************************/
229 WERROR _winreg_OpenHKPD(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
231 REGISTRY_KEY *keyinfo;
233 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPD, access_mask );
236 /*******************************************************************
237 ********************************************************************/
239 WERROR _winreg_OpenHKPT(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
241 REGISTRY_KEY *keyinfo;
243 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPT, access_mask );
246 /*******************************************************************
247 ********************************************************************/
249 WERROR _winreg_OpenHKCR(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
251 REGISTRY_KEY *keyinfo;
253 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCR, access_mask );
256 /*******************************************************************
257 ********************************************************************/
259 WERROR _winreg_OpenHKU(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
261 REGISTRY_KEY *keyinfo;
263 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKU, access_mask );
266 /*******************************************************************
267 ********************************************************************/
269 WERROR _winreg_OpenHKCU(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
271 REGISTRY_KEY *keyinfo;
273 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCU, access_mask );
276 /*******************************************************************
277 ********************************************************************/
279 WERROR _winreg_OpenHKCC(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
281 REGISTRY_KEY *keyinfo;
283 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCC, access_mask );
286 /*******************************************************************
287 ********************************************************************/
289 WERROR _winreg_OpenHKDD(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
291 REGISTRY_KEY *keyinfo;
293 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKDD, access_mask );
296 /*******************************************************************
297 ********************************************************************/
299 WERROR _winreg_OpenHKPN(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
301 REGISTRY_KEY *keyinfo;
303 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPN, access_mask );
306 /*******************************************************************
308 ********************************************************************/
310 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)
313 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, parent_handle );
314 REGISTRY_KEY *newkey = NULL;
320 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
321 return WERR_INVALID_PARAM;
324 /* check granted access first; what is the correct mask here? */
326 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
327 SEC_RIGHTS_CREATE_SUBKEY|
328 SEC_RIGHTS_QUERY_VALUE|
329 SEC_RIGHTS_SET_VALUE);
331 if ( !(parent->access_granted & check_rights) ) {
332 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
333 return WERR_ACCESS_DENIED;
337 * very crazy, but regedit.exe on Win2k will attempt to call
338 * REG_OPEN_ENTRY with a keyname of "". We should return a new
339 * (second) handle here on the key->name. regedt32.exe does
340 * not do this stupidity. --jerry
343 return open_registry_key( p, handle, &newkey, parent, name, access_mask );
346 /*******************************************************************
348 ********************************************************************/
350 WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value_name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length)
352 WERROR status = WERR_BADFILE;
354 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
355 REGISTRY_VALUE *val = NULL;
362 *value_length = *type = 0;
364 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
365 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
367 if ( (name = talloc_strdup( p->mem_ctx, value_name.name )) == NULL ) {
371 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
373 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
376 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
377 if(regkey->type == REG_KEY_HKPD)
379 if(strequal(name, "Global"))
383 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
384 status = reg_perfcount_get_hkpd(&prs_hkpd, *data_size, &outbuf_len, NULL);
385 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
386 prs_hkpd.data_p, outbuf_len);
387 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
388 prs_mem_free(&prs_hkpd);
390 else if(strequal(name, "Counter 009"))
397 base_index = reg_perfcount_get_base_index();
398 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
399 regval_ctr_addvalue(regvals, "Counter 009",
400 REG_MULTI_SZ, buffer, buffer_size);
402 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
410 else if(strequal(name, "Explain 009"))
417 base_index = reg_perfcount_get_base_index();
418 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
419 regval_ctr_addvalue(regvals, "Explain 009",
420 REG_MULTI_SZ, buffer, buffer_size);
422 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
430 else if(isdigit(name[0]))
432 /* we probably have a request for a specific object here */
435 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
436 status = reg_perfcount_get_hkpd(&prs_hkpd, *data_size, &outbuf_len, name);
437 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
438 prs_hkpd.data_p, outbuf_len);
440 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
441 prs_mem_free(&prs_hkpd);
445 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
449 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
452 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
454 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
455 if ( strequal( val->valuename, name ) ) {
456 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
461 free_registry_value( val );
465 /* if we have a value then copy it to the output */
468 *value_length = regval_size( val );
471 if ( *data_size == 0 || !data ) {
473 } else if ( *value_length > *data_size ) {
474 status = WERR_MORE_DATA;
476 memcpy( data, regval_data_p(val), *value_length );
480 *data_size = *value_length;
483 TALLOC_FREE( regvals );
484 free_registry_value( val );
489 /*****************************************************************************
490 Implementation of REG_QUERY_KEY
491 ****************************************************************************/
493 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle,
494 struct winreg_String *classname,
495 uint32_t *num_subkeys, uint32_t *max_subkeylen,
496 uint32_t *max_subkeysize,
497 uint32_t *num_values, uint32_t *max_valnamelen,
498 uint32_t *max_valbufsize,
499 uint32_t *secdescsize, NTTIME *last_changed_time)
501 WERROR status = WERR_OK;
502 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
507 if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
508 DEBUG(0,("_winreg_QueryInfoKey: get_subkey_information() failed!\n"));
509 return WERR_ACCESS_DENIED;
512 if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
513 DEBUG(0,("_winreg_QueryInfoKey: get_value_information() failed!\n"));
514 return WERR_ACCESS_DENIED;
517 *secdescsize = 0; /* used to be hard coded for 0x00000078 */
518 *last_changed_time = 0;
519 *max_subkeysize = 0; /* maybe this is the classname length ? */
521 /* don't bother with class names for now */
523 classname->name = NULL;
529 /*****************************************************************************
530 Implementation of REG_GETVERSION
531 ****************************************************************************/
533 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
535 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
540 *version = 0x00000005; /* Windows 2000 registry API version */
546 /*****************************************************************************
547 Implementation of REG_ENUM_KEY
548 ****************************************************************************/
550 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)
552 WERROR status = WERR_OK;
553 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
560 if ( !name || !keyclass )
561 return WERR_INVALID_PARAM;
563 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
565 if ( !fetch_reg_keys_specific( regkey, &subkey, enum_index ) ) {
566 status = WERR_NO_MORE_ITEMS;
570 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
572 if ( last_changed_time ) {
573 *last_changed_time = 0;
575 keyclass->name = NULL;
576 if ( (name->name = talloc_strdup( p->mem_ctx, subkey )) == NULL ) {
585 /*****************************************************************************
586 Implementation of REG_ENUM_VALUE
587 ****************************************************************************/
589 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length)
591 WERROR status = WERR_OK;
592 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
599 return WERR_INVALID_PARAM;
601 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n", regkey->name));
603 if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
604 status = WERR_NO_MORE_ITEMS;
608 DEBUG(10,("_winreg_EnumValue: retrieved value named [%s]\n", val->valuename));
610 /* subkey has the string name now */
612 if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
621 if ((data_size == NULL) || (value_length == NULL)) {
622 status = WERR_INVALID_PARAM;
626 if (regval_size(val) > *data_size) {
627 status = WERR_MORE_DATA;
631 memcpy( data, regval_data_p(val), regval_size(val) );
635 if (value_length != NULL) {
636 *value_length = regval_size( val );
638 if (data_size != NULL) {
639 *data_size = regval_size( val );
643 free_registry_value( val );
649 /*******************************************************************
651 ********************************************************************/
653 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
657 /* thunk down to _winreg_InitiateSystemShutdownEx()
658 (just returns a status) */
660 return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout,
661 force_apps, reboot, reason );
664 /*******************************************************************
666 ********************************************************************/
668 #define SHUTDOWN_R_STRING "-r"
669 #define SHUTDOWN_F_STRING "-f"
672 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)
674 pstring shutdown_script;
685 pstrcpy(shutdown_script, lp_shutdown_script());
687 if ( !*shutdown_script )
688 return WERR_ACCESS_DENIED;
690 /* pull the message string and perform necessary sanity checks on it */
694 if ( message && message->name && message->name->name ) {
695 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
698 alpha_strcpy (chkmsg, msg, NULL, sizeof(chkmsg));
701 fstr_sprintf(str_timeout, "%d", timeout);
702 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
703 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
704 fstr_sprintf(str_reason, "%d", reason );
706 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
707 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
708 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
709 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
710 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
712 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
714 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
715 Take the error return from the script and provide it as the Windows return code. */
717 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
722 ret = smbrun( shutdown_script, NULL );
727 /********** END SeRemoteShutdownPrivilege BLOCK **********/
729 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
730 shutdown_script, ret));
733 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
739 /*******************************************************************
741 ********************************************************************/
743 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
745 pstring abort_shutdown_script;
749 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
751 if ( !*abort_shutdown_script )
752 return WERR_ACCESS_DENIED;
754 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
756 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
761 ret = smbrun( abort_shutdown_script, NULL );
766 /********** END SeRemoteShutdownPrivilege BLOCK **********/
768 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
769 abort_shutdown_script, ret));
772 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
775 /*******************************************************************
776 ********************************************************************/
778 static int validate_reg_filename( pstring fname )
781 int num_services = lp_numservices();
786 /* convert to a unix path, stripping the C:\ along the way */
788 if ( !(p = valid_share_pathname( fname ) ))
791 /* has to exist within a valid file share */
793 for ( snum=0; snum<num_services; snum++ ) {
795 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
798 pstrcpy( share_path, lp_pathname(snum) );
800 /* make sure we have a path (e.g. [homes] ) */
802 if ( strlen( share_path ) == 0 )
805 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
809 /* p and fname are overlapping memory so copy out and back in again */
811 pstrcpy( unix_fname, p );
812 pstrcpy( fname, unix_fname );
814 return (snum < num_services) ? snum : -1;
817 /*******************************************************************
818 Note: topkeypat is the *full* path that this *key will be
819 loaded into (including the name of the key)
820 ********************************************************************/
822 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
826 REGISTRY_KEY registry_key;
828 REGSUBKEY_CTR *subkeys;
831 WERROR result = WERR_OK;
833 /* initialize the REGISTRY_KEY structure */
835 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
836 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
840 pstrcpy( registry_key.name, topkeypath );
842 /* now start parsing the values and subkeys */
844 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
847 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
850 /* copy values into the REGVAL_CTR */
852 for ( i=0; i<key->num_values; i++ ) {
853 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
854 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
857 /* copy subkeys into the REGSUBKEY_CTR */
859 key->subkey_index = 0;
860 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
861 regsubkey_ctr_addkey( subkeys, subkey->keyname );
864 /* write this key and values out */
866 if ( !store_reg_values( ®istry_key, values )
867 || !store_reg_keys( ®istry_key, subkeys ) )
869 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
870 result = WERR_REG_IO_FAILURE;
873 TALLOC_FREE( subkeys );
875 if ( !W_ERROR_IS_OK(result) )
878 /* now continue to load each subkey registry tree */
880 key->subkey_index = 0;
881 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
882 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
883 result = reg_load_tree( regfile, path, subkey );
884 if ( !W_ERROR_IS_OK(result) )
891 /*******************************************************************
892 ********************************************************************/
894 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
897 REGF_NK_REC *rootkey;
900 /* open the registry file....fail if the file already exists */
902 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
903 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
904 fname, strerror(errno) ));
905 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
908 /* get the rootkey from the regf file and then load the tree
909 via recursive calls */
911 if ( !(rootkey = regfio_rootkey( regfile )) ) {
912 regfio_close( regfile );
913 return WERR_REG_FILE_INVALID;
916 result = reg_load_tree( regfile, krecord->name, rootkey );
920 regfio_close( regfile );
925 /*******************************************************************
926 ********************************************************************/
928 WERROR _winreg_RestoreKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, uint32_t flags)
930 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
937 if ( !filename || !filename->name )
938 return WERR_INVALID_PARAM;
940 pstrcpy( fname, filename->name );
942 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from \"%s\"\n", regkey->name, fname));
944 if ( (snum = validate_reg_filename( fname )) == -1 )
945 return WERR_OBJECT_PATH_INVALID;
947 /* user must posses SeRestorePrivilege for this this proceed */
949 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
950 return WERR_ACCESS_DENIED;
952 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
954 return restore_registry_key( regkey, fname );
957 /********************************************************************
958 ********************************************************************/
960 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
961 REGF_NK_REC *parent, SEC_DESC *sec_desc )
965 REGSUBKEY_CTR *subkeys;
968 char *keyname, *parentpath;
971 REGISTRY_KEY registry_key;
972 WERROR result = WERR_OK;
975 return WERR_GENERAL_FAILURE;
978 return WERR_OBJECT_PATH_INVALID;
980 /* split up the registry key path */
982 pstrcpy( key_tmp, keypath );
983 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
984 return WERR_OBJECT_PATH_INVALID;
987 keyname = parentpath;
989 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
991 ZERO_STRUCT( registry_key );
993 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
996 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
999 /* lookup the values and subkeys */
1001 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
1004 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
1007 fetch_reg_keys( ®istry_key, subkeys );
1008 fetch_reg_values( ®istry_key, values );
1010 /* write out this key */
1012 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1013 result = WERR_CAN_NOT_COMPLETE;
1017 /* write each one of the subkeys out */
1019 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1020 for ( i=0; i<num_subkeys; i++ ) {
1021 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1022 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1023 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1024 if ( !W_ERROR_IS_OK(result) )
1028 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1031 TALLOC_FREE( subkeys );
1032 TALLOC_FREE( registry_key.name );
1037 /*******************************************************************
1038 ********************************************************************/
1040 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1042 DOM_SID adm_sid, owner_sid;
1043 SEC_ACE ace[2]; /* at most 2 entries */
1045 SEC_ACL *psa = NULL;
1048 /* set the owner to BUILTIN\Administrator */
1050 sid_copy(&owner_sid, &global_sid_Builtin);
1051 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1054 /* basic access for Everyone */
1056 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1057 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1059 /* add Full Access 'BUILTIN\Administrators' */
1061 init_sec_access(&mask, reg_generic_map.generic_all);
1062 sid_copy(&adm_sid, &global_sid_Builtin);
1063 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1064 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1066 /* create the security descriptor */
1068 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1071 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1077 /*******************************************************************
1078 ********************************************************************/
1080 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1084 SEC_DESC *sd = NULL;
1086 /* open the registry file....fail if the file already exists */
1088 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1089 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1090 fname, strerror(errno) ));
1091 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1094 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1095 regfio_close( regfile );
1099 /* write the registry tree to the file */
1101 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1105 regfio_close( regfile );
1110 /*******************************************************************
1111 ********************************************************************/
1113 WERROR _winreg_SaveKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, struct KeySecurityAttribute *sec_attrib)
1115 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
1122 if ( !filename || !filename->name )
1123 return WERR_INVALID_PARAM;
1125 pstrcpy( fname, filename->name );
1127 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n", regkey->name, fname));
1129 if ( (snum = validate_reg_filename( fname )) == -1 )
1130 return WERR_OBJECT_PATH_INVALID;
1132 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
1134 return backup_registry_key( regkey, fname );
1137 /*******************************************************************
1138 ********************************************************************/
1140 WERROR _winreg_SaveKeyEx(pipes_struct *p)
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_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname,
1153 struct winreg_String keyclass, uint32_t options, uint32_t access_mask,
1154 struct winreg_SecBuf *secdesc, struct policy_handle *new_handle,
1155 enum winreg_CreateAction *action_taken )
1157 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1158 REGISTRY_KEY *newparentinfo, *keyinfo;
1159 POLICY_HND newparent_handle;
1160 REGSUBKEY_CTR *subkeys;
1168 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1172 /* ok. Here's what we do. */
1174 if ( strrchr( name, '\\' ) ) {
1178 /* (1) check for enumerate rights on the parent handle. CLients can try
1179 create things like 'SOFTWARE\Samba' on the HKLM handle.
1180 (2) open the path to the child parent key if necessary */
1182 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1183 return WERR_ACCESS_DENIED;
1185 pstrcpy( newkeyname, name );
1186 ptr = strrchr( newkeyname, '\\' );
1189 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1190 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1192 if ( !W_ERROR_IS_OK(result) )
1195 /* copy the new key name (just the lower most keyname) */
1197 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1202 /* use the existing open key information */
1203 newparentinfo = parent;
1204 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1207 /* (3) check for create subkey rights on the correct parent */
1209 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1210 result = WERR_ACCESS_DENIED;
1214 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1215 result = WERR_NOMEM;
1219 /* (4) lookup the current keys and add the new one */
1221 fetch_reg_keys( newparentinfo, subkeys );
1222 regsubkey_ctr_addkey( subkeys, name );
1224 /* now write to the registry backend */
1226 write_result = store_reg_keys( newparentinfo, subkeys );
1228 TALLOC_FREE( subkeys );
1230 if ( !write_result )
1231 return WERR_REG_IO_FAILURE;
1233 /* (5) open the new key and return the handle. Note that it is probably
1234 not correct to grant full access on this open handle. */
1236 result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1237 keyinfo->access_granted = REG_KEY_ALL;
1239 /* FIXME: report the truth here */
1241 if ( action_taken ) {
1242 *action_taken = REG_CREATED_NEW_KEY;
1246 /* close any intermediate key handles */
1248 if ( newparentinfo != parent )
1249 close_registry_key( p, &newparent_handle );
1255 /*******************************************************************
1256 ********************************************************************/
1258 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1260 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1268 /* access checks first */
1270 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1271 return WERR_ACCESS_DENIED;
1273 /* verify the name */
1275 if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1276 return WERR_INVALID_PARAM;
1279 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1281 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1284 /* lookup the current values and add the new one */
1286 fetch_reg_values( key, values );
1288 regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1290 /* now write to the registry backend */
1292 write_result = store_reg_values( key, values );
1294 TALLOC_FREE( values );
1296 if ( !write_result )
1297 return WERR_REG_IO_FAILURE;
1302 /*******************************************************************
1303 ********************************************************************/
1305 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1307 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1308 REGISTRY_KEY *newparentinfo = NULL;
1309 POLICY_HND newparent_handle;
1310 REGSUBKEY_CTR *subkeys;
1318 /* MSDN says parent the handle must have been opened with DELETE access */
1320 /* (1) check for delete rights on the parent */
1322 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1323 result = WERR_ACCESS_DENIED;
1327 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1328 result = WERR_INVALID_PARAM;
1332 /* ok. Here's what we do. */
1334 if ( strrchr( name, '\\' ) ) {
1338 /* (2) open the path to the child parent key if necessary */
1339 /* split the registry path and save the subkeyname */
1341 pstrcpy( newkeyname, name );
1342 ptr = strrchr( newkeyname, '\\' );
1344 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1345 result = WERR_NOMEM;
1349 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1350 if ( !W_ERROR_IS_OK(result) ) {
1355 /* use the existing open key information */
1356 newparentinfo = parent;
1359 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1360 result = WERR_NOMEM;
1364 /* lookup the current keys and delete the new one */
1366 fetch_reg_keys( newparentinfo, subkeys );
1368 regsubkey_ctr_delkey( subkeys, name );
1370 /* now write to the registry backend */
1372 write_result = store_reg_keys( newparentinfo, subkeys );
1374 TALLOC_FREE( subkeys );
1376 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1379 /* close any intermediate key handles */
1381 if ( newparentinfo != parent )
1382 close_registry_key( p, &newparent_handle );
1388 /*******************************************************************
1389 ********************************************************************/
1391 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1393 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1401 /* access checks first */
1403 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1404 return WERR_ACCESS_DENIED;
1406 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1407 return WERR_INVALID_PARAM;
1410 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1412 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1415 /* lookup the current values and add the new one */
1417 fetch_reg_values( key, values );
1419 regval_ctr_delvalue( values, valuename );
1421 /* now write to the registry backend */
1423 write_result = store_reg_values( key, values );
1425 TALLOC_FREE( values );
1427 if ( !write_result )
1428 return WERR_REG_IO_FAILURE;
1433 /*******************************************************************
1434 ********************************************************************/
1436 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1438 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1443 /* access checks first */
1445 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1446 return WERR_ACCESS_DENIED;
1448 return WERR_ACCESS_DENIED;
1451 /*******************************************************************
1452 ********************************************************************/
1454 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1456 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1461 /* access checks first */
1463 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1464 return WERR_ACCESS_DENIED;
1466 return WERR_ACCESS_DENIED;
1469 /*******************************************************************
1470 ********************************************************************/
1472 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1474 /* I'm just replying OK because there's not a lot
1475 here I see to do i --jerry */
1480 /*******************************************************************
1481 ********************************************************************/
1483 WERROR _winreg_UnLoadKey(pipes_struct *p)
1485 /* fill in your code here if you think this call should
1488 p->rng_fault_state = True;
1489 return WERR_NOT_SUPPORTED;
1492 /*******************************************************************
1493 ********************************************************************/
1495 WERROR _winreg_ReplaceKey(pipes_struct *p)
1497 /* fill in your code here if you think this call should
1500 p->rng_fault_state = True;
1501 return WERR_NOT_SUPPORTED;
1504 /*******************************************************************
1505 ********************************************************************/
1507 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1509 /* fill in your code here if you think this call should
1512 p->rng_fault_state = True;
1513 return WERR_NOT_SUPPORTED;
1516 /*******************************************************************
1517 ********************************************************************/
1519 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)
1521 /* fill in your code here if you think this call should
1524 p->rng_fault_state = True;
1525 return WERR_NOT_SUPPORTED;
1528 /*******************************************************************
1529 ********************************************************************/
1531 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)
1533 /* fill in your code here if you think this call should
1536 p->rng_fault_state = True;
1537 return WERR_NOT_SUPPORTED;
1540 /*******************************************************************
1541 ********************************************************************/
1543 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1545 /* fill in your code here if you think this call should
1548 p->rng_fault_state = True;
1549 return WERR_NOT_SUPPORTED;