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 */
692 if ( message && message->name && message->name->name ) {
693 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
697 alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
699 fstr_sprintf(str_timeout, "%d", timeout);
700 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
701 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
702 fstr_sprintf(str_reason, "%d", reason );
704 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
705 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
706 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
707 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
708 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
710 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
712 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
713 Take the error return from the script and provide it as the Windows return code. */
715 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
720 ret = smbrun( shutdown_script, NULL );
725 /********** END SeRemoteShutdownPrivilege BLOCK **********/
727 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
728 shutdown_script, ret));
731 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
737 /*******************************************************************
739 ********************************************************************/
741 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
743 pstring abort_shutdown_script;
747 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
749 if ( !*abort_shutdown_script )
750 return WERR_ACCESS_DENIED;
752 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
754 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
759 ret = smbrun( abort_shutdown_script, NULL );
764 /********** END SeRemoteShutdownPrivilege BLOCK **********/
766 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
767 abort_shutdown_script, ret));
770 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
773 /*******************************************************************
774 ********************************************************************/
776 static int validate_reg_filename( pstring fname )
779 int num_services = lp_numservices();
784 /* convert to a unix path, stripping the C:\ along the way */
786 if ( !(p = valid_share_pathname( fname ) ))
789 /* has to exist within a valid file share */
791 for ( snum=0; snum<num_services; snum++ ) {
793 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
796 pstrcpy( share_path, lp_pathname(snum) );
798 /* make sure we have a path (e.g. [homes] ) */
800 if ( strlen( share_path ) == 0 )
803 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
807 /* p and fname are overlapping memory so copy out and back in again */
809 pstrcpy( unix_fname, p );
810 pstrcpy( fname, unix_fname );
812 return (snum < num_services) ? snum : -1;
815 /*******************************************************************
816 Note: topkeypat is the *full* path that this *key will be
817 loaded into (including the name of the key)
818 ********************************************************************/
820 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
824 REGISTRY_KEY registry_key;
826 REGSUBKEY_CTR *subkeys;
829 WERROR result = WERR_OK;
831 /* initialize the REGISTRY_KEY structure */
833 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
834 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
838 pstrcpy( registry_key.name, topkeypath );
840 /* now start parsing the values and subkeys */
842 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
845 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
848 /* copy values into the REGVAL_CTR */
850 for ( i=0; i<key->num_values; i++ ) {
851 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
852 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
855 /* copy subkeys into the REGSUBKEY_CTR */
857 key->subkey_index = 0;
858 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
859 regsubkey_ctr_addkey( subkeys, subkey->keyname );
862 /* write this key and values out */
864 if ( !store_reg_values( ®istry_key, values )
865 || !store_reg_keys( ®istry_key, subkeys ) )
867 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
868 result = WERR_REG_IO_FAILURE;
871 TALLOC_FREE( subkeys );
873 if ( !W_ERROR_IS_OK(result) )
876 /* now continue to load each subkey registry tree */
878 key->subkey_index = 0;
879 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
880 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
881 result = reg_load_tree( regfile, path, subkey );
882 if ( !W_ERROR_IS_OK(result) )
889 /*******************************************************************
890 ********************************************************************/
892 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
895 REGF_NK_REC *rootkey;
898 /* open the registry file....fail if the file already exists */
900 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
901 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
902 fname, strerror(errno) ));
903 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
906 /* get the rootkey from the regf file and then load the tree
907 via recursive calls */
909 if ( !(rootkey = regfio_rootkey( regfile )) ) {
910 regfio_close( regfile );
911 return WERR_REG_FILE_INVALID;
914 result = reg_load_tree( regfile, krecord->name, rootkey );
918 regfio_close( regfile );
923 /*******************************************************************
924 ********************************************************************/
926 WERROR _winreg_RestoreKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, uint32_t flags)
928 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
935 if ( !filename || !filename->name )
936 return WERR_INVALID_PARAM;
938 pstrcpy( fname, filename->name );
940 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from \"%s\"\n", regkey->name, fname));
942 if ( (snum = validate_reg_filename( fname )) == -1 )
943 return WERR_OBJECT_PATH_INVALID;
945 /* user must posses SeRestorePrivilege for this this proceed */
947 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
948 return WERR_ACCESS_DENIED;
950 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
952 return restore_registry_key( regkey, fname );
955 /********************************************************************
956 ********************************************************************/
958 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
959 REGF_NK_REC *parent, SEC_DESC *sec_desc )
963 REGSUBKEY_CTR *subkeys;
966 char *keyname, *parentpath;
969 REGISTRY_KEY registry_key;
970 WERROR result = WERR_OK;
973 return WERR_GENERAL_FAILURE;
976 return WERR_OBJECT_PATH_INVALID;
978 /* split up the registry key path */
980 pstrcpy( key_tmp, keypath );
981 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
982 return WERR_OBJECT_PATH_INVALID;
985 keyname = parentpath;
987 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
989 ZERO_STRUCT( registry_key );
991 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
994 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
997 /* lookup the values and subkeys */
999 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
1002 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
1005 fetch_reg_keys( ®istry_key, subkeys );
1006 fetch_reg_values( ®istry_key, values );
1008 /* write out this key */
1010 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1011 result = WERR_CAN_NOT_COMPLETE;
1015 /* write each one of the subkeys out */
1017 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1018 for ( i=0; i<num_subkeys; i++ ) {
1019 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1020 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1021 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1022 if ( !W_ERROR_IS_OK(result) )
1026 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1029 TALLOC_FREE( subkeys );
1030 TALLOC_FREE( registry_key.name );
1035 /*******************************************************************
1036 ********************************************************************/
1038 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1040 DOM_SID adm_sid, owner_sid;
1041 SEC_ACE ace[2]; /* at most 2 entries */
1043 SEC_ACL *psa = NULL;
1046 /* set the owner to BUILTIN\Administrator */
1048 sid_copy(&owner_sid, &global_sid_Builtin);
1049 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1052 /* basic access for Everyone */
1054 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1055 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1057 /* add Full Access 'BUILTIN\Administrators' */
1059 init_sec_access(&mask, reg_generic_map.generic_all);
1060 sid_copy(&adm_sid, &global_sid_Builtin);
1061 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1062 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1064 /* create the security descriptor */
1066 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1069 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1075 /*******************************************************************
1076 ********************************************************************/
1078 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1082 SEC_DESC *sd = NULL;
1084 /* open the registry file....fail if the file already exists */
1086 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1087 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1088 fname, strerror(errno) ));
1089 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1092 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1093 regfio_close( regfile );
1097 /* write the registry tree to the file */
1099 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1103 regfio_close( regfile );
1108 /*******************************************************************
1109 ********************************************************************/
1111 WERROR _winreg_SaveKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, struct KeySecurityAttribute *sec_attrib)
1113 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
1120 if ( !filename || !filename->name )
1121 return WERR_INVALID_PARAM;
1123 pstrcpy( fname, filename->name );
1125 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n", regkey->name, fname));
1127 if ( (snum = validate_reg_filename( fname )) == -1 )
1128 return WERR_OBJECT_PATH_INVALID;
1130 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
1132 return backup_registry_key( regkey, fname );
1135 /*******************************************************************
1136 ********************************************************************/
1138 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1140 /* fill in your code here if you think this call should
1143 p->rng_fault_state = True;
1144 return WERR_NOT_SUPPORTED;
1147 /*******************************************************************
1148 ********************************************************************/
1150 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname,
1151 struct winreg_String keyclass, uint32_t options, uint32_t access_mask,
1152 struct winreg_SecBuf *secdesc, struct policy_handle *new_handle,
1153 enum winreg_CreateAction *action_taken )
1155 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1156 REGISTRY_KEY *newparentinfo, *keyinfo;
1157 POLICY_HND newparent_handle;
1158 REGSUBKEY_CTR *subkeys;
1166 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1170 /* ok. Here's what we do. */
1172 if ( strrchr( name, '\\' ) ) {
1176 /* (1) check for enumerate rights on the parent handle. CLients can try
1177 create things like 'SOFTWARE\Samba' on the HKLM handle.
1178 (2) open the path to the child parent key if necessary */
1180 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1181 return WERR_ACCESS_DENIED;
1183 pstrcpy( newkeyname, name );
1184 ptr = strrchr( newkeyname, '\\' );
1187 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1188 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1190 if ( !W_ERROR_IS_OK(result) )
1193 /* copy the new key name (just the lower most keyname) */
1195 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1200 /* use the existing open key information */
1201 newparentinfo = parent;
1202 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1205 /* (3) check for create subkey rights on the correct parent */
1207 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1208 result = WERR_ACCESS_DENIED;
1212 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1213 result = WERR_NOMEM;
1217 /* (4) lookup the current keys and add the new one */
1219 fetch_reg_keys( newparentinfo, subkeys );
1220 regsubkey_ctr_addkey( subkeys, name );
1222 /* now write to the registry backend */
1224 write_result = store_reg_keys( newparentinfo, subkeys );
1226 TALLOC_FREE( subkeys );
1228 if ( !write_result )
1229 return WERR_REG_IO_FAILURE;
1231 /* (5) open the new key and return the handle. Note that it is probably
1232 not correct to grant full access on this open handle. */
1234 result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1235 keyinfo->access_granted = REG_KEY_ALL;
1237 /* FIXME: report the truth here */
1239 if ( action_taken ) {
1240 *action_taken = REG_CREATED_NEW_KEY;
1244 /* close any intermediate key handles */
1246 if ( newparentinfo != parent )
1247 close_registry_key( p, &newparent_handle );
1253 /*******************************************************************
1254 ********************************************************************/
1256 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1258 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1266 /* access checks first */
1268 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1269 return WERR_ACCESS_DENIED;
1271 /* verify the name */
1273 if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1274 return WERR_INVALID_PARAM;
1277 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1279 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1282 /* lookup the current values and add the new one */
1284 fetch_reg_values( key, values );
1286 regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1288 /* now write to the registry backend */
1290 write_result = store_reg_values( key, values );
1292 TALLOC_FREE( values );
1294 if ( !write_result )
1295 return WERR_REG_IO_FAILURE;
1300 /*******************************************************************
1301 ********************************************************************/
1303 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1305 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1306 REGISTRY_KEY *newparentinfo = NULL;
1307 POLICY_HND newparent_handle;
1308 REGSUBKEY_CTR *subkeys;
1316 /* MSDN says parent the handle must have been opened with DELETE access */
1318 /* (1) check for delete rights on the parent */
1320 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1321 result = WERR_ACCESS_DENIED;
1325 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1326 result = WERR_INVALID_PARAM;
1330 /* ok. Here's what we do. */
1332 if ( strrchr( name, '\\' ) ) {
1336 /* (2) open the path to the child parent key if necessary */
1337 /* split the registry path and save the subkeyname */
1339 pstrcpy( newkeyname, name );
1340 ptr = strrchr( newkeyname, '\\' );
1342 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1343 result = WERR_NOMEM;
1347 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1348 if ( !W_ERROR_IS_OK(result) ) {
1353 /* use the existing open key information */
1354 newparentinfo = parent;
1357 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1358 result = WERR_NOMEM;
1362 /* lookup the current keys and delete the new one */
1364 fetch_reg_keys( newparentinfo, subkeys );
1366 regsubkey_ctr_delkey( subkeys, name );
1368 /* now write to the registry backend */
1370 write_result = store_reg_keys( newparentinfo, subkeys );
1372 TALLOC_FREE( subkeys );
1374 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1377 /* close any intermediate key handles */
1379 if ( newparentinfo != parent )
1380 close_registry_key( p, &newparent_handle );
1386 /*******************************************************************
1387 ********************************************************************/
1389 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1391 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1399 /* access checks first */
1401 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1402 return WERR_ACCESS_DENIED;
1404 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1405 return WERR_INVALID_PARAM;
1408 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1410 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1413 /* lookup the current values and add the new one */
1415 fetch_reg_values( key, values );
1417 regval_ctr_delvalue( values, valuename );
1419 /* now write to the registry backend */
1421 write_result = store_reg_values( key, values );
1423 TALLOC_FREE( values );
1425 if ( !write_result )
1426 return WERR_REG_IO_FAILURE;
1431 /*******************************************************************
1432 ********************************************************************/
1434 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1436 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1441 /* access checks first */
1443 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1444 return WERR_ACCESS_DENIED;
1446 return WERR_ACCESS_DENIED;
1449 /*******************************************************************
1450 ********************************************************************/
1452 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1454 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1459 /* access checks first */
1461 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1462 return WERR_ACCESS_DENIED;
1464 return WERR_ACCESS_DENIED;
1467 /*******************************************************************
1468 ********************************************************************/
1470 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1472 /* I'm just replying OK because there's not a lot
1473 here I see to do i --jerry */
1478 /*******************************************************************
1479 ********************************************************************/
1481 WERROR _winreg_UnLoadKey(pipes_struct *p)
1483 /* fill in your code here if you think this call should
1486 p->rng_fault_state = True;
1487 return WERR_NOT_SUPPORTED;
1490 /*******************************************************************
1491 ********************************************************************/
1493 WERROR _winreg_ReplaceKey(pipes_struct *p)
1495 /* fill in your code here if you think this call should
1498 p->rng_fault_state = True;
1499 return WERR_NOT_SUPPORTED;
1502 /*******************************************************************
1503 ********************************************************************/
1505 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1507 /* fill in your code here if you think this call should
1510 p->rng_fault_state = True;
1511 return WERR_NOT_SUPPORTED;
1514 /*******************************************************************
1515 ********************************************************************/
1517 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)
1519 /* fill in your code here if you think this call should
1522 p->rng_fault_state = True;
1523 return WERR_NOT_SUPPORTED;
1526 /*******************************************************************
1527 ********************************************************************/
1529 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)
1531 /* fill in your code here if you think this call should
1534 p->rng_fault_state = True;
1535 return WERR_NOT_SUPPORTED;
1538 /*******************************************************************
1539 ********************************************************************/
1541 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1543 /* fill in your code here if you think this call should
1546 p->rng_fault_state = True;
1547 return WERR_NOT_SUPPORTED;