2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997.
5 * Copyright (C) Jeremy Allison 2001.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* Implementation of registry functions. */
29 #define DBGC_CLASS DBGC_RPC_SRV
31 #if 0 /* temporaily disabled */
32 static struct generic_mapping reg_generic_map =
33 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
36 /******************************************************************
37 free() function for REGISTRY_KEY
38 *****************************************************************/
40 static void free_regkey_info(void *ptr)
42 regkey_close_internal( (REGISTRY_KEY*)ptr );
45 /******************************************************************
46 Find a registry key handle and return a REGISTRY_KEY
47 *****************************************************************/
49 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
51 REGISTRY_KEY *regkey = NULL;
53 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
54 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
62 /*******************************************************************
63 Function for open a new registry handle and creating a handle
64 Note that P should be valid & hnd should already have space
66 When we open a key, we store the full path to the key as
67 HK[LM|U]\<key>\<key>\...
68 *******************************************************************/
70 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
71 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
72 const char *subkeyname, uint32 access_desired )
76 WERROR result = WERR_OK;
78 /* create a full registry path and strip any trailing '\'
81 pstr_sprintf( keypath, "%s%s%s",
82 parent ? parent->name : "",
86 path_len = strlen( keypath );
87 if ( path_len && keypath[path_len-1] == '\\' )
88 keypath[path_len-1] = '\0';
90 /* now do the internal open */
92 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
93 if ( !W_ERROR_IS_OK(result) )
96 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
97 result = WERR_BADFILE;
98 regkey_close_internal( *keyinfo );
104 /*******************************************************************
105 Function for open a new registry handle and creating a handle
106 Note that P should be valid & hnd should already have space
107 *******************************************************************/
109 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
111 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
114 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
118 close_policy_hnd(p, hnd);
123 /********************************************************************
124 retrieve information about the subkeys
125 *******************************************************************/
127 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
131 REGSUBKEY_CTR *subkeys;
137 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
140 if ( fetch_reg_keys( key, subkeys ) == -1 )
143 /* find the longest string */
146 num_subkeys = regsubkey_ctr_numkeys( subkeys );
148 for ( i=0; i<num_subkeys; i++ ) {
149 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
150 max_len = MAX(max_len, len);
153 *maxnum = num_subkeys;
156 TALLOC_FREE( subkeys );
161 /********************************************************************
162 retrieve information about the values.
163 *******************************************************************/
165 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
166 uint32 *maxlen, uint32 *maxsize )
170 uint32 sizemax, lenmax;
176 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
179 if ( fetch_reg_values( key, values ) == -1 )
182 lenmax = sizemax = 0;
183 num_values = regval_ctr_numvals( values );
185 val = regval_ctr_specific_value( values, 0 );
187 for ( i=0; i<num_values && val; i++ )
189 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
190 sizemax = MAX(sizemax, val->size );
192 val = regval_ctr_specific_value( values, i );
195 *maxnum = num_values;
199 TALLOC_FREE( values );
205 /********************************************************************
207 ********************************************************************/
209 WERROR _winreg_CloseKey(pipes_struct *p, struct policy_handle *handle)
211 /* close the policy handle */
213 if (!close_registry_key(p, handle))
219 /*******************************************************************
220 ********************************************************************/
222 WERROR _winreg_OpenHKLM(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
224 REGISTRY_KEY *keyinfo;
226 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKLM, access_mask );
229 /*******************************************************************
230 ********************************************************************/
232 WERROR _winreg_OpenHKPD(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
234 REGISTRY_KEY *keyinfo;
236 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPD, access_mask );
239 /*******************************************************************
240 ********************************************************************/
242 WERROR _winreg_OpenHKPT(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
244 REGISTRY_KEY *keyinfo;
246 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPT, access_mask );
249 /*******************************************************************
250 ********************************************************************/
252 WERROR _winreg_OpenHKCR(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
254 REGISTRY_KEY *keyinfo;
256 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCR, access_mask );
259 /*******************************************************************
260 ********************************************************************/
262 WERROR _winreg_OpenHKU(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
264 REGISTRY_KEY *keyinfo;
266 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKU, access_mask );
269 /*******************************************************************
270 ********************************************************************/
272 WERROR _winreg_OpenHKCU(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
274 REGISTRY_KEY *keyinfo;
276 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCU, access_mask );
279 /*******************************************************************
280 ********************************************************************/
282 WERROR _winreg_OpenHKCC(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
284 REGISTRY_KEY *keyinfo;
286 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCC, access_mask );
289 /*******************************************************************
290 ********************************************************************/
292 WERROR _winreg_OpenHKDD(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
294 REGISTRY_KEY *keyinfo;
296 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKDD, access_mask );
299 /*******************************************************************
300 ********************************************************************/
302 WERROR _winreg_OpenHKPN(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
304 REGISTRY_KEY *keyinfo;
306 return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPN, access_mask );
309 /*******************************************************************
311 ********************************************************************/
313 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)
316 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, parent_handle );
317 REGISTRY_KEY *newkey = NULL;
323 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
324 return WERR_INVALID_PARAM;
327 /* check granted access first; what is the correct mask here? */
329 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
330 SEC_RIGHTS_CREATE_SUBKEY|
331 SEC_RIGHTS_QUERY_VALUE|
332 SEC_RIGHTS_SET_VALUE);
334 if ( !(parent->access_granted & check_rights) ) {
335 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
336 return WERR_ACCESS_DENIED;
340 * very crazy, but regedit.exe on Win2k will attempt to call
341 * REG_OPEN_ENTRY with a keyname of "". We should return a new
342 * (second) handle here on the key->name. regedt32.exe does
343 * not do this stupidity. --jerry
346 return open_registry_key( p, handle, &newkey, parent, name, access_mask );
349 /*******************************************************************
351 ********************************************************************/
353 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)
355 WERROR status = WERR_BADFILE;
357 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
358 REGISTRY_VALUE *val = NULL;
365 *value_length = *type = 0;
367 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
368 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
370 if ( (name = talloc_strdup( p->mem_ctx, value_name.name )) == NULL ) {
374 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
376 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
379 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
380 if(regkey->type == REG_KEY_HKPD)
382 if(strequal(name, "Global"))
386 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
387 status = reg_perfcount_get_hkpd(&prs_hkpd, *data_size, &outbuf_len, NULL);
388 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
389 prs_hkpd.data_p, outbuf_len);
390 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
391 prs_mem_free(&prs_hkpd);
393 else if(strequal(name, "Counter 009"))
400 base_index = reg_perfcount_get_base_index();
401 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
402 regval_ctr_addvalue(regvals, "Counter 009",
403 REG_MULTI_SZ, buffer, buffer_size);
405 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
413 else if(strequal(name, "Explain 009"))
420 base_index = reg_perfcount_get_base_index();
421 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
422 regval_ctr_addvalue(regvals, "Explain 009",
423 REG_MULTI_SZ, buffer, buffer_size);
425 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
433 else if(isdigit(name[0]))
435 /* we probably have a request for a specific object here */
438 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
439 status = reg_perfcount_get_hkpd(&prs_hkpd, *data_size, &outbuf_len, name);
440 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
441 prs_hkpd.data_p, outbuf_len);
443 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
444 prs_mem_free(&prs_hkpd);
448 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
452 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
455 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
457 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
458 if ( strequal( val->valuename, name ) ) {
459 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
464 free_registry_value( val );
468 /* if we have a value then copy it to the output */
471 *value_length = regval_size( val );
474 if ( *data_size == 0 ) {
476 } else if ( *value_length > *data_size ) {
477 status = WERR_MORE_DATA;
479 memcpy( data, regval_data_p(val), *value_length );
484 TALLOC_FREE( regvals );
485 free_registry_value( val );
490 /*****************************************************************************
491 Implementation of REG_QUERY_KEY
492 ****************************************************************************/
494 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle,
495 struct winreg_String class_in,
496 struct winreg_String *class_out, uint32_t *num_subkeys,
497 uint32_t *max_subkeylen, uint32_t *max_subkeysize,
498 uint32_t *num_values, uint32_t *max_valnamelen,
499 uint32_t *max_valbufsize, uint32_t *secdescsize,
500 NTTIME *last_changed_time)
502 WERROR status = WERR_OK;
503 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
508 if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
509 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
510 return WERR_ACCESS_DENIED;
513 if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
514 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
515 return WERR_ACCESS_DENIED;
518 *secdescsize = 0x00000078; /* size for key's sec_desc */
520 /* Win9x set this to 0x0 since it does not keep timestamps.
521 Doing the same here for simplicity --jerry */
523 *last_changed_time = 0;
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 *value, uint32_t *size, uint32_t *length)
591 WERROR status = WERR_OK;
592 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
598 if ( !name || !type || !value || !size || !length )
599 return WERR_INVALID_PARAM;
601 DEBUG(8,("_reg_enum_value: 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,("_reg_enum_value: 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 ) {
616 *size = regval_size( val );
617 *length = regval_size( val );
619 if ( (value = talloc_memdup( p->mem_ctx, regval_data_p(val), *size )) == NULL ) {
626 free_registry_value( val );
632 /*******************************************************************
634 ********************************************************************/
636 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
640 /* thunk down to _winreg_InitiateSystemShutdownEx()
641 (just returns a status) */
643 return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout,
644 force_apps, reboot, reason );
647 /*******************************************************************
649 ********************************************************************/
651 #define SHUTDOWN_R_STRING "-r"
652 #define SHUTDOWN_F_STRING "-f"
655 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)
657 pstring shutdown_script;
668 pstrcpy(shutdown_script, lp_shutdown_script());
670 if ( !*shutdown_script )
671 return WERR_ACCESS_DENIED;
673 /* pull the message string and perform necessary sanity checks on it */
675 if ( message && message->name && message->name->name ) {
676 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
680 alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
682 fstr_sprintf(str_timeout, "%d", timeout);
683 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
684 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
685 fstr_sprintf(str_reason, "%d", reason );
687 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
688 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
689 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
690 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
691 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
693 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
695 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
696 Take the error return from the script and provide it as the Windows return code. */
698 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
703 ret = smbrun( shutdown_script, NULL );
708 /********** END SeRemoteShutdownPrivilege BLOCK **********/
710 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
711 shutdown_script, ret));
714 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
720 /*******************************************************************
722 ********************************************************************/
724 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
726 pstring abort_shutdown_script;
730 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
732 if ( !*abort_shutdown_script )
733 return WERR_ACCESS_DENIED;
735 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
737 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
742 ret = smbrun( abort_shutdown_script, NULL );
747 /********** END SeRemoteShutdownPrivilege BLOCK **********/
749 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
750 abort_shutdown_script, ret));
753 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
756 #if 0 /* This code works but is disabled for now until I
757 fix the WinReg IDL file -- jerry */
759 /*******************************************************************
760 ********************************************************************/
762 static int validate_reg_filename( pstring fname )
765 int num_services = lp_numservices();
770 /* convert to a unix path, stripping the C:\ along the way */
772 if ( !(p = valid_share_pathname( fname ) ))
775 /* has to exist within a valid file share */
777 for ( snum=0; snum<num_services; snum++ ) {
779 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
782 pstrcpy( share_path, lp_pathname(snum) );
784 /* make sure we have a path (e.g. [homes] ) */
786 if ( strlen( share_path ) == 0 )
789 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
793 /* p and fname are overlapping memory so copy out and back in again */
795 pstrcpy( unix_fname, p );
796 pstrcpy( fname, unix_fname );
798 return (snum < num_services) ? snum : -1;
801 /*******************************************************************
802 Note: topkeypat is the *full* path that this *key will be
803 loaded into (including the name of the key)
804 ********************************************************************/
806 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
810 REGISTRY_KEY registry_key;
812 REGSUBKEY_CTR *subkeys;
815 WERROR result = WERR_OK;
817 /* initialize the REGISTRY_KEY structure */
819 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
820 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
824 pstrcpy( registry_key.name, topkeypath );
826 /* now start parsing the values and subkeys */
828 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
831 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
834 /* copy values into the REGVAL_CTR */
836 for ( i=0; i<key->num_values; i++ ) {
837 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
838 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
841 /* copy subkeys into the REGSUBKEY_CTR */
843 key->subkey_index = 0;
844 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
845 regsubkey_ctr_addkey( subkeys, subkey->keyname );
848 /* write this key and values out */
850 if ( !store_reg_values( ®istry_key, values )
851 || !store_reg_keys( ®istry_key, subkeys ) )
853 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
854 result = WERR_REG_IO_FAILURE;
857 TALLOC_FREE( subkeys );
859 if ( !W_ERROR_IS_OK(result) )
862 /* now continue to load each subkey registry tree */
864 key->subkey_index = 0;
865 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
866 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
867 result = reg_load_tree( regfile, path, subkey );
868 if ( !W_ERROR_IS_OK(result) )
875 /*******************************************************************
876 ********************************************************************/
878 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
881 REGF_NK_REC *rootkey;
884 /* open the registry file....fail if the file already exists */
886 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
887 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
888 fname, strerror(errno) ));
889 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
892 /* get the rootkey from the regf file and then load the tree
893 via recursive calls */
895 if ( !(rootkey = regfio_rootkey( regfile )) ) {
896 regfio_close( regfile );
897 return WERR_REG_FILE_INVALID;
900 result = reg_load_tree( regfile, krecord->name, rootkey );
904 regfio_close( regfile );
911 /*******************************************************************
912 ********************************************************************/
914 WERROR _winreg_RestoreKey(pipes_struct *p)
916 #if 0 /* temporarily disabled */
917 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
924 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
926 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
928 if ( (snum = validate_reg_filename( filename )) == -1 )
929 return WERR_OBJECT_PATH_INVALID;
931 /* user must posses SeRestorePrivilege for this this proceed */
933 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
934 return WERR_ACCESS_DENIED;
936 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
938 return restore_registry_key( regkey, filename );
941 return WERR_NOT_SUPPORTED;
944 #if 0 /* this code works but has been disable until I fix
945 the winreg IDL -- jerry */
947 /********************************************************************
948 ********************************************************************/
950 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
951 REGF_NK_REC *parent, SEC_DESC *sec_desc )
955 REGSUBKEY_CTR *subkeys;
958 char *keyname, *parentpath;
961 REGISTRY_KEY registry_key;
962 WERROR result = WERR_OK;
965 return WERR_GENERAL_FAILURE;
968 return WERR_OBJECT_PATH_INVALID;
970 /* split up the registry key path */
972 pstrcpy( key_tmp, keypath );
973 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
974 return WERR_OBJECT_PATH_INVALID;
977 keyname = parentpath;
979 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
981 ZERO_STRUCT( registry_key );
982 pstrcpy( registry_key.name, keypath );
983 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
987 /* lookup the values and subkeys */
989 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
992 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
995 fetch_reg_keys( ®istry_key, subkeys );
996 fetch_reg_values( ®istry_key, values );
998 /* write out this key */
1000 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1001 result = WERR_CAN_NOT_COMPLETE;
1005 /* write each one of the subkeys out */
1007 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1008 for ( i=0; i<num_subkeys; i++ ) {
1009 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1010 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1011 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1012 if ( !W_ERROR_IS_OK(result) )
1016 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1019 TALLOC_FREE( subkeys );
1024 /*******************************************************************
1025 ********************************************************************/
1027 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1029 DOM_SID adm_sid, owner_sid;
1030 SEC_ACE ace[2]; /* at most 2 entries */
1032 SEC_ACL *psa = NULL;
1035 /* set the owner to BUILTIN\Administrator */
1037 sid_copy(&owner_sid, &global_sid_Builtin);
1038 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1041 /* basic access for Everyone */
1043 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1044 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1046 /* add Full Access 'BUILTIN\Administrators' */
1048 init_sec_access(&mask, reg_generic_map.generic_all);
1049 sid_copy(&adm_sid, &global_sid_Builtin);
1050 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1051 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1053 /* create the security descriptor */
1055 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1058 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1064 /*******************************************************************
1065 ********************************************************************/
1067 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1071 SEC_DESC *sd = NULL;
1073 /* open the registry file....fail if the file already exists */
1075 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1076 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1077 fname, strerror(errno) ));
1078 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1081 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1082 regfio_close( regfile );
1086 /* write the registry tree to the file */
1088 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1092 regfio_close( regfile );
1098 /*******************************************************************
1099 ********************************************************************/
1101 WERROR _winreg_SaveKey(pipes_struct *p)
1104 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1111 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1113 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1115 if ( (snum = validate_reg_filename( filename )) == -1 )
1116 return WERR_OBJECT_PATH_INVALID;
1118 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1120 return backup_registry_key( regkey, filename );
1123 /* disabled for now until I fix the IDL --jerry */
1124 return WERR_NOT_SUPPORTED;
1127 /*******************************************************************
1128 ********************************************************************/
1130 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1132 /* disabled for now until I fix the IDL --jerry */
1133 return WERR_NOT_SUPPORTED;
1136 /*******************************************************************
1137 ********************************************************************/
1139 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname,
1140 struct winreg_String keyclass, uint32_t options, uint32_t access_mask,
1141 struct winreg_SecBuf *secdesc, struct policy_handle *new_handle,
1142 enum winreg_CreateAction *action_taken )
1144 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1145 REGISTRY_KEY *newparentinfo, *keyinfo;
1146 POLICY_HND newparent_handle;
1147 REGSUBKEY_CTR *subkeys;
1155 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1159 /* ok. Here's what we do. */
1161 if ( strrchr( name, '\\' ) ) {
1165 /* (1) check for enumerate rights on the parent handle. CLients can try
1166 create things like 'SOFTWARE\Samba' on the HKLM handle.
1167 (2) open the path to the child parent key if necessary */
1169 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1170 return WERR_ACCESS_DENIED;
1172 pstrcpy( newkeyname, name );
1173 ptr = strrchr( newkeyname, '\\' );
1176 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1177 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1179 if ( !W_ERROR_IS_OK(result) )
1182 /* copy the new key name (just the lower most keyname) */
1184 pstrcpy( name, ptr+1 );
1187 /* use the existing open key information */
1188 newparentinfo = parent;
1189 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1192 /* (3) check for create subkey rights on the correct parent */
1194 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1195 result = WERR_ACCESS_DENIED;
1199 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1200 result = WERR_NOMEM;
1204 /* (4) lookup the current keys and add the new one */
1206 fetch_reg_keys( newparentinfo, subkeys );
1207 regsubkey_ctr_addkey( subkeys, name );
1209 /* now write to the registry backend */
1211 write_result = store_reg_keys( newparentinfo, subkeys );
1213 TALLOC_FREE( subkeys );
1215 if ( !write_result )
1216 return WERR_REG_IO_FAILURE;
1218 /* (5) open the new key and return the handle. Note that it is probably
1219 not correct to grant full access on this open handle. */
1221 result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1222 keyinfo->access_granted = REG_KEY_ALL;
1224 /* FIXME: report the truth here */
1226 *action_taken = REG_CREATED_NEW_KEY;
1229 /* close any intermediate key handles */
1231 if ( newparentinfo != parent )
1232 close_registry_key( p, &newparent_handle );
1238 /*******************************************************************
1239 ********************************************************************/
1241 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1243 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1251 /* access checks first */
1253 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1254 return WERR_ACCESS_DENIED;
1256 /* verify the name */
1258 if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1259 return WERR_INVALID_PARAM;
1262 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1264 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1267 /* lookup the current values and add the new one */
1269 fetch_reg_values( key, values );
1271 regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1273 /* now write to the registry backend */
1275 write_result = store_reg_values( key, values );
1277 TALLOC_FREE( values );
1279 if ( !write_result )
1280 return WERR_REG_IO_FAILURE;
1285 /*******************************************************************
1286 ********************************************************************/
1288 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1290 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1291 REGISTRY_KEY *newparentinfo = NULL;
1292 POLICY_HND newparent_handle;
1293 REGSUBKEY_CTR *subkeys;
1301 /* MSDN says parent the handle must have been opened with DELETE access */
1303 /* (1) check for delete rights on the parent */
1305 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1306 result = WERR_ACCESS_DENIED;
1310 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1311 result = WERR_INVALID_PARAM;
1315 /* ok. Here's what we do. */
1317 if ( strrchr( name, '\\' ) ) {
1321 /* (2) open the path to the child parent key if necessary */
1322 /* split the registry path and save the subkeyname */
1324 pstrcpy( newkeyname, name );
1325 ptr = strrchr( newkeyname, '\\' );
1327 pstrcpy( name, ptr+1 );
1329 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1330 if ( !W_ERROR_IS_OK(result) )
1334 /* use the existing open key information */
1335 newparentinfo = parent;
1338 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1339 result = WERR_NOMEM;
1343 /* lookup the current keys and delete the new one */
1345 fetch_reg_keys( newparentinfo, subkeys );
1347 regsubkey_ctr_delkey( subkeys, name );
1349 /* now write to the registry backend */
1351 write_result = store_reg_keys( newparentinfo, subkeys );
1353 TALLOC_FREE( subkeys );
1355 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1358 /* close any intermediate key handles */
1360 if ( newparentinfo != parent )
1361 close_registry_key( p, &newparent_handle );
1367 /*******************************************************************
1368 ********************************************************************/
1370 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1372 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1380 /* access checks first */
1382 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1383 return WERR_ACCESS_DENIED;
1385 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1386 return WERR_INVALID_PARAM;
1389 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1391 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1394 /* lookup the current values and add the new one */
1396 fetch_reg_values( key, values );
1398 regval_ctr_delvalue( values, valuename );
1400 /* now write to the registry backend */
1402 write_result = store_reg_values( key, values );
1404 TALLOC_FREE( values );
1406 if ( !write_result )
1407 return WERR_REG_IO_FAILURE;
1412 /*******************************************************************
1413 ********************************************************************/
1415 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1417 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1422 /* access checks first */
1424 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1425 return WERR_ACCESS_DENIED;
1427 return WERR_ACCESS_DENIED;
1430 /*******************************************************************
1431 ********************************************************************/
1433 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1435 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1440 /* access checks first */
1442 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1443 return WERR_ACCESS_DENIED;
1445 return WERR_ACCESS_DENIED;
1448 /*******************************************************************
1449 ********************************************************************/
1451 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1453 /* I'm just replying OK because there's not a lot
1454 here I see to do i --jerry */
1459 /*******************************************************************
1460 ********************************************************************/
1462 WERROR _winreg_UnLoadKey(pipes_struct *p)
1464 /* fill in your code here if you think this call should
1467 return WERR_NOT_SUPPORTED;
1470 /*******************************************************************
1471 ********************************************************************/
1473 WERROR _winreg_ReplaceKey(pipes_struct *p)
1475 /* fill in your code here if you think this call should
1478 return WERR_NOT_SUPPORTED;
1481 /*******************************************************************
1482 ********************************************************************/
1484 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1486 /* fill in your code here if you think this call should
1489 return WERR_NOT_SUPPORTED;
1492 /*******************************************************************
1493 ********************************************************************/
1495 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)
1497 /* fill in your code here if you think this call should
1500 return WERR_NOT_SUPPORTED;
1503 /*******************************************************************
1504 ********************************************************************/
1506 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)
1508 /* fill in your code here if you think this call should
1511 return WERR_NOT_SUPPORTED;
1514 /*******************************************************************
1515 ********************************************************************/
1517 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1519 /* fill in your code here if you think this call should
1522 return WERR_NOT_SUPPORTED;