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 *size, uint32_t *length)
355 WERROR status = WERR_BADFILE;
357 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
358 REGISTRY_VALUE *val = NULL;
365 *size = *length = *type = 0;
366 value_name.name = NULL;
368 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
369 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
371 if ( (name = talloc_strdup( p->mem_ctx, value_name.name )) == NULL ) {
375 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
377 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
380 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
381 if(regkey->type == REG_KEY_HKPD)
383 if(strequal(name, "Global"))
387 prs_init(&prs_hkpd, *size, p->mem_ctx, MARSHALL);
388 status = reg_perfcount_get_hkpd(&prs_hkpd, *size, &outbuf_len, NULL);
389 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
390 prs_hkpd.data_p, outbuf_len);
391 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
392 prs_mem_free(&prs_hkpd);
394 else if(strequal(name, "Counter 009"))
401 base_index = reg_perfcount_get_base_index();
402 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
403 regval_ctr_addvalue(regvals, "Counter 009",
404 REG_MULTI_SZ, buffer, buffer_size);
406 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
414 else if(strequal(name, "Explain 009"))
421 base_index = reg_perfcount_get_base_index();
422 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
423 regval_ctr_addvalue(regvals, "Explain 009",
424 REG_MULTI_SZ, buffer, buffer_size);
426 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
434 else if(isdigit(name[0]))
436 /* we probably have a request for a specific object here */
439 prs_init(&prs_hkpd, *size, p->mem_ctx, MARSHALL);
440 status = reg_perfcount_get_hkpd(&prs_hkpd, *size, &outbuf_len, name);
441 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
442 prs_hkpd.data_p, outbuf_len);
444 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
445 prs_mem_free(&prs_hkpd);
449 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
453 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
456 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
458 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
459 if ( strequal( val->valuename, name ) ) {
460 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
465 free_registry_value( val );
470 *size = regval_size( val );
471 *length = regval_size( val );
473 if ( (*data = talloc_memdup( p->mem_ctx, regval_data_p(val), *size )) == NULL ) {
480 TALLOC_FREE( regvals );
481 free_registry_value( val );
486 /*****************************************************************************
487 Implementation of REG_QUERY_KEY
488 ****************************************************************************/
490 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle,
491 struct winreg_String class_in,
492 struct winreg_String *class_out, uint32_t *num_subkeys,
493 uint32_t *max_subkeylen, uint32_t *max_subkeysize,
494 uint32_t *num_values, uint32_t *max_valnamelen,
495 uint32_t *max_valbufsize, uint32_t *secdescsize,
496 NTTIME *last_changed_time)
498 WERROR status = WERR_OK;
499 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
504 if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
505 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
506 return WERR_ACCESS_DENIED;
509 if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
510 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
511 return WERR_ACCESS_DENIED;
514 *secdescsize = 0x00000078; /* size for key's sec_desc */
516 /* Win9x set this to 0x0 since it does not keep timestamps.
517 Doing the same here for simplicity --jerry */
519 *last_changed_time = 0;
525 /*****************************************************************************
526 Implementation of REG_GETVERSION
527 ****************************************************************************/
529 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
531 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
536 *version = 0x00000005; /* Windows 2000 registry API version */
542 /*****************************************************************************
543 Implementation of REG_ENUM_KEY
544 ****************************************************************************/
546 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)
548 WERROR status = WERR_OK;
549 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
556 if ( !name || !keyclass || !last_changed_time )
557 return WERR_INVALID_PARAM;
559 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
561 if ( !fetch_reg_keys_specific( regkey, &subkey, enum_index ) ) {
562 status = WERR_NO_MORE_ITEMS;
566 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
568 *last_changed_time = 0;
569 keyclass->name = NULL;
570 if ( (name->name = talloc_strdup( p->mem_ctx, subkey )) == NULL ) {
579 /*****************************************************************************
580 Implementation of REG_ENUM_VALUE
581 ****************************************************************************/
583 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)
585 WERROR status = WERR_OK;
586 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
592 if ( !name || !type || !value || !size || !length )
593 return WERR_INVALID_PARAM;
595 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
597 if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
598 status = WERR_NO_MORE_ITEMS;
602 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
604 /* subkey has the string name now */
606 if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
610 *size = regval_size( val );
611 *length = regval_size( val );
613 if ( (value = talloc_memdup( p->mem_ctx, regval_data_p(val), *size )) == NULL ) {
620 free_registry_value( val );
626 /*******************************************************************
628 ********************************************************************/
630 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
634 /* thunk down to _winreg_InitiateSystemShutdownEx()
635 (just returns a status) */
637 return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout,
638 force_apps, reboot, reason );
641 /*******************************************************************
643 ********************************************************************/
645 #define SHUTDOWN_R_STRING "-r"
646 #define SHUTDOWN_F_STRING "-f"
649 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)
651 pstring shutdown_script;
662 pstrcpy(shutdown_script, lp_shutdown_script());
664 if ( !*shutdown_script )
665 return WERR_ACCESS_DENIED;
667 /* pull the message string and perform necessary sanity checks on it */
669 if ( message && message->name && message->name->name ) {
670 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
674 alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
676 fstr_sprintf(str_timeout, "%d", timeout);
677 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
678 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
679 fstr_sprintf(str_reason, "%d", reason );
681 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
682 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
683 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
684 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
685 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
687 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
689 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
690 Take the error return from the script and provide it as the Windows return code. */
692 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
697 ret = smbrun( shutdown_script, NULL );
702 /********** END SeRemoteShutdownPrivilege BLOCK **********/
704 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
705 shutdown_script, ret));
708 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
714 /*******************************************************************
716 ********************************************************************/
718 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
720 pstring abort_shutdown_script;
724 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
726 if ( !*abort_shutdown_script )
727 return WERR_ACCESS_DENIED;
729 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
731 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
736 ret = smbrun( abort_shutdown_script, NULL );
741 /********** END SeRemoteShutdownPrivilege BLOCK **********/
743 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
744 abort_shutdown_script, ret));
747 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
750 #if 0 /* This code works but is disabled for now until I
751 fix the WinReg IDL file -- jerry */
753 /*******************************************************************
754 ********************************************************************/
756 static int validate_reg_filename( pstring fname )
759 int num_services = lp_numservices();
764 /* convert to a unix path, stripping the C:\ along the way */
766 if ( !(p = valid_share_pathname( fname ) ))
769 /* has to exist within a valid file share */
771 for ( snum=0; snum<num_services; snum++ ) {
773 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
776 pstrcpy( share_path, lp_pathname(snum) );
778 /* make sure we have a path (e.g. [homes] ) */
780 if ( strlen( share_path ) == 0 )
783 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
787 /* p and fname are overlapping memory so copy out and back in again */
789 pstrcpy( unix_fname, p );
790 pstrcpy( fname, unix_fname );
792 return (snum < num_services) ? snum : -1;
795 /*******************************************************************
796 Note: topkeypat is the *full* path that this *key will be
797 loaded into (including the name of the key)
798 ********************************************************************/
800 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
804 REGISTRY_KEY registry_key;
806 REGSUBKEY_CTR *subkeys;
809 WERROR result = WERR_OK;
811 /* initialize the REGISTRY_KEY structure */
813 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
814 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
818 pstrcpy( registry_key.name, topkeypath );
820 /* now start parsing the values and subkeys */
822 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
825 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
828 /* copy values into the REGVAL_CTR */
830 for ( i=0; i<key->num_values; i++ ) {
831 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
832 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
835 /* copy subkeys into the REGSUBKEY_CTR */
837 key->subkey_index = 0;
838 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
839 regsubkey_ctr_addkey( subkeys, subkey->keyname );
842 /* write this key and values out */
844 if ( !store_reg_values( ®istry_key, values )
845 || !store_reg_keys( ®istry_key, subkeys ) )
847 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
848 result = WERR_REG_IO_FAILURE;
851 TALLOC_FREE( subkeys );
853 if ( !W_ERROR_IS_OK(result) )
856 /* now continue to load each subkey registry tree */
858 key->subkey_index = 0;
859 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
860 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
861 result = reg_load_tree( regfile, path, subkey );
862 if ( !W_ERROR_IS_OK(result) )
869 /*******************************************************************
870 ********************************************************************/
872 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
875 REGF_NK_REC *rootkey;
878 /* open the registry file....fail if the file already exists */
880 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
881 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
882 fname, strerror(errno) ));
883 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
886 /* get the rootkey from the regf file and then load the tree
887 via recursive calls */
889 if ( !(rootkey = regfio_rootkey( regfile )) ) {
890 regfio_close( regfile );
891 return WERR_REG_FILE_INVALID;
894 result = reg_load_tree( regfile, krecord->name, rootkey );
898 regfio_close( regfile );
905 /*******************************************************************
906 ********************************************************************/
908 WERROR _winreg_RestoreKey(pipes_struct *p)
910 #if 0 /* temporarily disabled */
911 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
918 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
920 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
922 if ( (snum = validate_reg_filename( filename )) == -1 )
923 return WERR_OBJECT_PATH_INVALID;
925 /* user must posses SeRestorePrivilege for this this proceed */
927 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
928 return WERR_ACCESS_DENIED;
930 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
932 return restore_registry_key( regkey, filename );
935 return WERR_NOT_SUPPORTED;
938 #if 0 /* this code works but has been disable until I fix
939 the winreg IDL -- jerry */
941 /********************************************************************
942 ********************************************************************/
944 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
945 REGF_NK_REC *parent, SEC_DESC *sec_desc )
949 REGSUBKEY_CTR *subkeys;
952 char *keyname, *parentpath;
955 REGISTRY_KEY registry_key;
956 WERROR result = WERR_OK;
959 return WERR_GENERAL_FAILURE;
962 return WERR_OBJECT_PATH_INVALID;
964 /* split up the registry key path */
966 pstrcpy( key_tmp, keypath );
967 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
968 return WERR_OBJECT_PATH_INVALID;
971 keyname = parentpath;
973 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
975 ZERO_STRUCT( registry_key );
976 pstrcpy( registry_key.name, keypath );
977 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
981 /* lookup the values and subkeys */
983 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
986 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
989 fetch_reg_keys( ®istry_key, subkeys );
990 fetch_reg_values( ®istry_key, values );
992 /* write out this key */
994 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
995 result = WERR_CAN_NOT_COMPLETE;
999 /* write each one of the subkeys out */
1001 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1002 for ( i=0; i<num_subkeys; i++ ) {
1003 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1004 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1005 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1006 if ( !W_ERROR_IS_OK(result) )
1010 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1013 TALLOC_FREE( subkeys );
1018 /*******************************************************************
1019 ********************************************************************/
1021 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1023 DOM_SID adm_sid, owner_sid;
1024 SEC_ACE ace[2]; /* at most 2 entries */
1026 SEC_ACL *psa = NULL;
1029 /* set the owner to BUILTIN\Administrator */
1031 sid_copy(&owner_sid, &global_sid_Builtin);
1032 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1035 /* basic access for Everyone */
1037 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1038 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1040 /* add Full Access 'BUILTIN\Administrators' */
1042 init_sec_access(&mask, reg_generic_map.generic_all);
1043 sid_copy(&adm_sid, &global_sid_Builtin);
1044 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1045 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1047 /* create the security descriptor */
1049 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1052 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1058 /*******************************************************************
1059 ********************************************************************/
1061 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1065 SEC_DESC *sd = NULL;
1067 /* open the registry file....fail if the file already exists */
1069 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1070 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1071 fname, strerror(errno) ));
1072 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1075 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1076 regfio_close( regfile );
1080 /* write the registry tree to the file */
1082 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1086 regfio_close( regfile );
1092 /*******************************************************************
1093 ********************************************************************/
1095 WERROR _winreg_SaveKey(pipes_struct *p)
1098 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1105 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1107 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1109 if ( (snum = validate_reg_filename( filename )) == -1 )
1110 return WERR_OBJECT_PATH_INVALID;
1112 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1114 return backup_registry_key( regkey, filename );
1117 /* disabled for now until I fix the IDL --jerry */
1118 return WERR_NOT_SUPPORTED;
1121 /*******************************************************************
1122 ********************************************************************/
1124 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1126 /* disabled for now until I fix the IDL --jerry */
1127 return WERR_NOT_SUPPORTED;
1130 /*******************************************************************
1131 ********************************************************************/
1133 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname,
1134 struct winreg_String keyclass, uint32_t options, uint32_t access_mask,
1135 struct winreg_SecBuf *secdesc, struct policy_handle *new_handle,
1136 enum winreg_CreateAction *action_taken )
1138 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1139 REGISTRY_KEY *newparentinfo, *keyinfo;
1140 POLICY_HND newparent_handle;
1141 REGSUBKEY_CTR *subkeys;
1149 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1153 /* ok. Here's what we do. */
1155 if ( strrchr( name, '\\' ) ) {
1159 /* (1) check for enumerate rights on the parent handle. CLients can try
1160 create things like 'SOFTWARE\Samba' on the HKLM handle.
1161 (2) open the path to the child parent key if necessary */
1163 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1164 return WERR_ACCESS_DENIED;
1166 pstrcpy( newkeyname, name );
1167 ptr = strrchr( newkeyname, '\\' );
1170 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1171 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1173 if ( !W_ERROR_IS_OK(result) )
1176 /* copy the new key name (just the lower most keyname) */
1178 pstrcpy( name, ptr+1 );
1181 /* use the existing open key information */
1182 newparentinfo = parent;
1183 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1186 /* (3) check for create subkey rights on the correct parent */
1188 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1189 result = WERR_ACCESS_DENIED;
1193 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1194 result = WERR_NOMEM;
1198 /* (4) lookup the current keys and add the new one */
1200 fetch_reg_keys( newparentinfo, subkeys );
1201 regsubkey_ctr_addkey( subkeys, name );
1203 /* now write to the registry backend */
1205 write_result = store_reg_keys( newparentinfo, subkeys );
1207 TALLOC_FREE( subkeys );
1209 if ( !write_result )
1210 return WERR_REG_IO_FAILURE;
1212 /* (5) open the new key and return the handle. Note that it is probably
1213 not correct to grant full access on this open handle. */
1215 result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1216 keyinfo->access_granted = REG_KEY_ALL;
1218 /* FIXME: report the truth here */
1220 *action_taken = REG_CREATED_NEW_KEY;
1223 /* close any intermediate key handles */
1225 if ( newparentinfo != parent )
1226 close_registry_key( p, &newparent_handle );
1232 /*******************************************************************
1233 ********************************************************************/
1235 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1237 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1245 /* access checks first */
1247 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1248 return WERR_ACCESS_DENIED;
1250 /* verify the name */
1252 if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1253 return WERR_INVALID_PARAM;
1256 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1258 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1261 /* lookup the current values and add the new one */
1263 fetch_reg_values( key, values );
1265 regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1267 /* now write to the registry backend */
1269 write_result = store_reg_values( key, values );
1271 TALLOC_FREE( values );
1273 if ( !write_result )
1274 return WERR_REG_IO_FAILURE;
1279 /*******************************************************************
1280 ********************************************************************/
1282 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1284 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1285 REGISTRY_KEY *newparentinfo = NULL;
1286 POLICY_HND newparent_handle;
1287 REGSUBKEY_CTR *subkeys;
1295 /* MSDN says parent the handle must have been opened with DELETE access */
1297 /* (1) check for delete rights on the parent */
1299 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1300 result = WERR_ACCESS_DENIED;
1304 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1305 result = WERR_INVALID_PARAM;
1309 /* ok. Here's what we do. */
1311 if ( strrchr( name, '\\' ) ) {
1315 /* (2) open the path to the child parent key if necessary */
1316 /* split the registry path and save the subkeyname */
1318 pstrcpy( newkeyname, name );
1319 ptr = strrchr( newkeyname, '\\' );
1321 pstrcpy( name, ptr+1 );
1323 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1324 if ( !W_ERROR_IS_OK(result) )
1328 /* use the existing open key information */
1329 newparentinfo = parent;
1332 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1333 result = WERR_NOMEM;
1337 /* lookup the current keys and delete the new one */
1339 fetch_reg_keys( newparentinfo, subkeys );
1341 regsubkey_ctr_delkey( subkeys, name );
1343 /* now write to the registry backend */
1345 write_result = store_reg_keys( newparentinfo, subkeys );
1347 TALLOC_FREE( subkeys );
1349 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1352 /* close any intermediate key handles */
1354 if ( newparentinfo != parent )
1355 close_registry_key( p, &newparent_handle );
1361 /*******************************************************************
1362 ********************************************************************/
1364 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1366 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1374 /* access checks first */
1376 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1377 return WERR_ACCESS_DENIED;
1379 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1380 return WERR_INVALID_PARAM;
1383 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1385 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1388 /* lookup the current values and add the new one */
1390 fetch_reg_values( key, values );
1392 regval_ctr_delvalue( values, valuename );
1394 /* now write to the registry backend */
1396 write_result = store_reg_values( key, values );
1398 TALLOC_FREE( values );
1400 if ( !write_result )
1401 return WERR_REG_IO_FAILURE;
1406 /*******************************************************************
1407 ********************************************************************/
1409 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1411 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1416 /* access checks first */
1418 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1419 return WERR_ACCESS_DENIED;
1421 return WERR_ACCESS_DENIED;
1424 /*******************************************************************
1425 ********************************************************************/
1427 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1429 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1434 /* access checks first */
1436 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1437 return WERR_ACCESS_DENIED;
1439 return WERR_ACCESS_DENIED;
1442 /*******************************************************************
1443 ********************************************************************/
1445 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1447 /* I'm just replying OK because there's not a lot
1448 here I see to do i --jerry */
1453 /*******************************************************************
1454 ********************************************************************/
1456 WERROR _winreg_UnLoadKey(pipes_struct *p)
1458 /* fill in your code here if you think this call should
1461 return WERR_NOT_SUPPORTED;
1464 /*******************************************************************
1465 ********************************************************************/
1467 WERROR _winreg_ReplaceKey(pipes_struct *p)
1469 /* fill in your code here if you think this call should
1472 return WERR_NOT_SUPPORTED;
1475 /*******************************************************************
1476 ********************************************************************/
1478 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1480 /* fill in your code here if you think this call should
1483 return WERR_NOT_SUPPORTED;
1486 /*******************************************************************
1487 ********************************************************************/
1489 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)
1491 /* fill in your code here if you think this call should
1494 return WERR_NOT_SUPPORTED;
1497 /*******************************************************************
1498 ********************************************************************/
1500 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)
1502 /* fill in your code here if you think this call should
1505 return WERR_NOT_SUPPORTED;
1508 /*******************************************************************
1509 ********************************************************************/
1511 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1513 /* fill in your code here if you think this call should
1516 return WERR_NOT_SUPPORTED;