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 );
483 *data_size = *value_length;
486 TALLOC_FREE( regvals );
487 free_registry_value( val );
492 /*****************************************************************************
493 Implementation of REG_QUERY_KEY
494 ****************************************************************************/
496 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle,
497 struct winreg_String *classname,
498 uint32_t *num_subkeys, uint32_t *max_subkeylen,
499 uint32_t *max_subkeysize,
500 uint32_t *num_values, uint32_t *max_valnamelen,
501 uint32_t *max_valbufsize,
502 uint32_t *secdescsize, NTTIME *last_changed_time)
504 WERROR status = WERR_OK;
505 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
510 if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
511 DEBUG(0,("_winreg_QueryInfoKey: get_subkey_information() failed!\n"));
512 return WERR_ACCESS_DENIED;
515 if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
516 DEBUG(0,("_winreg_QueryInfoKey: get_value_information() failed!\n"));
517 return WERR_ACCESS_DENIED;
520 *secdescsize = 0; /* used to be hard coded for 0x00000078 */
521 *last_changed_time = 0;
522 *max_subkeysize = 0; /* maybe this is the classname length ? */
524 /* don't bother with class names for now */
526 classname->name = NULL;
532 /*****************************************************************************
533 Implementation of REG_GETVERSION
534 ****************************************************************************/
536 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
538 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
543 *version = 0x00000005; /* Windows 2000 registry API version */
549 /*****************************************************************************
550 Implementation of REG_ENUM_KEY
551 ****************************************************************************/
553 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)
555 WERROR status = WERR_OK;
556 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
563 if ( !name || !keyclass )
564 return WERR_INVALID_PARAM;
566 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
568 if ( !fetch_reg_keys_specific( regkey, &subkey, enum_index ) ) {
569 status = WERR_NO_MORE_ITEMS;
573 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
575 if ( last_changed_time ) {
576 *last_changed_time = 0;
578 keyclass->name = NULL;
579 if ( (name->name = talloc_strdup( p->mem_ctx, subkey )) == NULL ) {
588 /*****************************************************************************
589 Implementation of REG_ENUM_VALUE
590 ****************************************************************************/
592 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)
594 WERROR status = WERR_OK;
595 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, handle );
602 return WERR_INVALID_PARAM;
604 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n", regkey->name));
606 if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
607 status = WERR_NO_MORE_ITEMS;
611 DEBUG(10,("_winreg_EnumValue: retrieved value named [%s]\n", val->valuename));
613 /* subkey has the string name now */
615 if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
619 *value_length = regval_size( val );
622 if ( *data_size == 0 ) {
624 } else if ( *value_length > *data_size ) {
625 status = WERR_MORE_DATA;
627 memcpy( data, regval_data_p(val), *value_length );
631 *data_size = *value_length;
634 free_registry_value( val );
640 /*******************************************************************
642 ********************************************************************/
644 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
648 /* thunk down to _winreg_InitiateSystemShutdownEx()
649 (just returns a status) */
651 return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout,
652 force_apps, reboot, reason );
655 /*******************************************************************
657 ********************************************************************/
659 #define SHUTDOWN_R_STRING "-r"
660 #define SHUTDOWN_F_STRING "-f"
663 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)
665 pstring shutdown_script;
676 pstrcpy(shutdown_script, lp_shutdown_script());
678 if ( !*shutdown_script )
679 return WERR_ACCESS_DENIED;
681 /* pull the message string and perform necessary sanity checks on it */
683 if ( message && message->name && message->name->name ) {
684 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
688 alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
690 fstr_sprintf(str_timeout, "%d", timeout);
691 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
692 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
693 fstr_sprintf(str_reason, "%d", reason );
695 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
696 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
697 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
698 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
699 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
701 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
703 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
704 Take the error return from the script and provide it as the Windows return code. */
706 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
711 ret = smbrun( shutdown_script, NULL );
716 /********** END SeRemoteShutdownPrivilege BLOCK **********/
718 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
719 shutdown_script, ret));
722 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
728 /*******************************************************************
730 ********************************************************************/
732 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
734 pstring abort_shutdown_script;
738 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
740 if ( !*abort_shutdown_script )
741 return WERR_ACCESS_DENIED;
743 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
745 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
750 ret = smbrun( abort_shutdown_script, NULL );
755 /********** END SeRemoteShutdownPrivilege BLOCK **********/
757 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
758 abort_shutdown_script, ret));
761 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
764 #if 0 /* This code works but is disabled for now until I
765 fix the WinReg IDL file -- jerry */
767 /*******************************************************************
768 ********************************************************************/
770 static int validate_reg_filename( pstring fname )
773 int num_services = lp_numservices();
778 /* convert to a unix path, stripping the C:\ along the way */
780 if ( !(p = valid_share_pathname( fname ) ))
783 /* has to exist within a valid file share */
785 for ( snum=0; snum<num_services; snum++ ) {
787 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
790 pstrcpy( share_path, lp_pathname(snum) );
792 /* make sure we have a path (e.g. [homes] ) */
794 if ( strlen( share_path ) == 0 )
797 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
801 /* p and fname are overlapping memory so copy out and back in again */
803 pstrcpy( unix_fname, p );
804 pstrcpy( fname, unix_fname );
806 return (snum < num_services) ? snum : -1;
809 /*******************************************************************
810 Note: topkeypat is the *full* path that this *key will be
811 loaded into (including the name of the key)
812 ********************************************************************/
814 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
818 REGISTRY_KEY registry_key;
820 REGSUBKEY_CTR *subkeys;
823 WERROR result = WERR_OK;
825 /* initialize the REGISTRY_KEY structure */
827 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
828 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
832 pstrcpy( registry_key.name, topkeypath );
834 /* now start parsing the values and subkeys */
836 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
839 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
842 /* copy values into the REGVAL_CTR */
844 for ( i=0; i<key->num_values; i++ ) {
845 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
846 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
849 /* copy subkeys into the REGSUBKEY_CTR */
851 key->subkey_index = 0;
852 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
853 regsubkey_ctr_addkey( subkeys, subkey->keyname );
856 /* write this key and values out */
858 if ( !store_reg_values( ®istry_key, values )
859 || !store_reg_keys( ®istry_key, subkeys ) )
861 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
862 result = WERR_REG_IO_FAILURE;
865 TALLOC_FREE( subkeys );
867 if ( !W_ERROR_IS_OK(result) )
870 /* now continue to load each subkey registry tree */
872 key->subkey_index = 0;
873 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
874 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
875 result = reg_load_tree( regfile, path, subkey );
876 if ( !W_ERROR_IS_OK(result) )
883 /*******************************************************************
884 ********************************************************************/
886 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
889 REGF_NK_REC *rootkey;
892 /* open the registry file....fail if the file already exists */
894 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
895 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
896 fname, strerror(errno) ));
897 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
900 /* get the rootkey from the regf file and then load the tree
901 via recursive calls */
903 if ( !(rootkey = regfio_rootkey( regfile )) ) {
904 regfio_close( regfile );
905 return WERR_REG_FILE_INVALID;
908 result = reg_load_tree( regfile, krecord->name, rootkey );
912 regfio_close( regfile );
919 /*******************************************************************
920 ********************************************************************/
922 WERROR _winreg_RestoreKey(pipes_struct *p)
924 #if 0 /* temporarily disabled */
925 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
932 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
934 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
936 if ( (snum = validate_reg_filename( filename )) == -1 )
937 return WERR_OBJECT_PATH_INVALID;
939 /* user must posses SeRestorePrivilege for this this proceed */
941 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
942 return WERR_ACCESS_DENIED;
944 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
946 return restore_registry_key( regkey, filename );
949 return WERR_NOT_SUPPORTED;
952 #if 0 /* this code works but has been disable until I fix
953 the winreg IDL -- jerry */
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 );
990 pstrcpy( registry_key.name, keypath );
991 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
995 /* lookup the values and subkeys */
997 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
1000 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
1003 fetch_reg_keys( ®istry_key, subkeys );
1004 fetch_reg_values( ®istry_key, values );
1006 /* write out this key */
1008 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1009 result = WERR_CAN_NOT_COMPLETE;
1013 /* write each one of the subkeys out */
1015 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1016 for ( i=0; i<num_subkeys; i++ ) {
1017 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1018 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1019 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1020 if ( !W_ERROR_IS_OK(result) )
1024 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1027 TALLOC_FREE( subkeys );
1032 /*******************************************************************
1033 ********************************************************************/
1035 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1037 DOM_SID adm_sid, owner_sid;
1038 SEC_ACE ace[2]; /* at most 2 entries */
1040 SEC_ACL *psa = NULL;
1043 /* set the owner to BUILTIN\Administrator */
1045 sid_copy(&owner_sid, &global_sid_Builtin);
1046 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1049 /* basic access for Everyone */
1051 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1052 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1054 /* add Full Access 'BUILTIN\Administrators' */
1056 init_sec_access(&mask, reg_generic_map.generic_all);
1057 sid_copy(&adm_sid, &global_sid_Builtin);
1058 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1059 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1061 /* create the security descriptor */
1063 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1066 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1072 /*******************************************************************
1073 ********************************************************************/
1075 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1079 SEC_DESC *sd = NULL;
1081 /* open the registry file....fail if the file already exists */
1083 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1084 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1085 fname, strerror(errno) ));
1086 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1089 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1090 regfio_close( regfile );
1094 /* write the registry tree to the file */
1096 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1100 regfio_close( regfile );
1106 /*******************************************************************
1107 ********************************************************************/
1109 WERROR _winreg_SaveKey(pipes_struct *p)
1112 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1119 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1121 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1123 if ( (snum = validate_reg_filename( filename )) == -1 )
1124 return WERR_OBJECT_PATH_INVALID;
1126 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1128 return backup_registry_key( regkey, filename );
1131 /* disabled for now until I fix the IDL --jerry */
1132 return WERR_NOT_SUPPORTED;
1135 /*******************************************************************
1136 ********************************************************************/
1138 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1140 /* disabled for now until I fix the IDL --jerry */
1141 return WERR_NOT_SUPPORTED;
1144 /*******************************************************************
1145 ********************************************************************/
1147 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname,
1148 struct winreg_String keyclass, uint32_t options, uint32_t access_mask,
1149 struct winreg_SecBuf *secdesc, struct policy_handle *new_handle,
1150 enum winreg_CreateAction *action_taken )
1152 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1153 REGISTRY_KEY *newparentinfo, *keyinfo;
1154 POLICY_HND newparent_handle;
1155 REGSUBKEY_CTR *subkeys;
1163 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1167 /* ok. Here's what we do. */
1169 if ( strrchr( name, '\\' ) ) {
1173 /* (1) check for enumerate rights on the parent handle. CLients can try
1174 create things like 'SOFTWARE\Samba' on the HKLM handle.
1175 (2) open the path to the child parent key if necessary */
1177 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1178 return WERR_ACCESS_DENIED;
1180 pstrcpy( newkeyname, name );
1181 ptr = strrchr( newkeyname, '\\' );
1184 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1185 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1187 if ( !W_ERROR_IS_OK(result) )
1190 /* copy the new key name (just the lower most keyname) */
1192 pstrcpy( name, ptr+1 );
1195 /* use the existing open key information */
1196 newparentinfo = parent;
1197 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1200 /* (3) check for create subkey rights on the correct parent */
1202 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1203 result = WERR_ACCESS_DENIED;
1207 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1208 result = WERR_NOMEM;
1212 /* (4) lookup the current keys and add the new one */
1214 fetch_reg_keys( newparentinfo, subkeys );
1215 regsubkey_ctr_addkey( subkeys, name );
1217 /* now write to the registry backend */
1219 write_result = store_reg_keys( newparentinfo, subkeys );
1221 TALLOC_FREE( subkeys );
1223 if ( !write_result )
1224 return WERR_REG_IO_FAILURE;
1226 /* (5) open the new key and return the handle. Note that it is probably
1227 not correct to grant full access on this open handle. */
1229 result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1230 keyinfo->access_granted = REG_KEY_ALL;
1232 /* FIXME: report the truth here */
1234 if ( action_taken ) {
1235 *action_taken = REG_CREATED_NEW_KEY;
1239 /* close any intermediate key handles */
1241 if ( newparentinfo != parent )
1242 close_registry_key( p, &newparent_handle );
1248 /*******************************************************************
1249 ********************************************************************/
1251 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1253 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1261 /* access checks first */
1263 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1264 return WERR_ACCESS_DENIED;
1266 /* verify the name */
1268 if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1269 return WERR_INVALID_PARAM;
1272 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1274 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1277 /* lookup the current values and add the new one */
1279 fetch_reg_values( key, values );
1281 regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1283 /* now write to the registry backend */
1285 write_result = store_reg_values( key, values );
1287 TALLOC_FREE( values );
1289 if ( !write_result )
1290 return WERR_REG_IO_FAILURE;
1295 /*******************************************************************
1296 ********************************************************************/
1298 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1300 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1301 REGISTRY_KEY *newparentinfo = NULL;
1302 POLICY_HND newparent_handle;
1303 REGSUBKEY_CTR *subkeys;
1311 /* MSDN says parent the handle must have been opened with DELETE access */
1313 /* (1) check for delete rights on the parent */
1315 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1316 result = WERR_ACCESS_DENIED;
1320 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1321 result = WERR_INVALID_PARAM;
1325 /* ok. Here's what we do. */
1327 if ( strrchr( name, '\\' ) ) {
1331 /* (2) open the path to the child parent key if necessary */
1332 /* split the registry path and save the subkeyname */
1334 pstrcpy( newkeyname, name );
1335 ptr = strrchr( newkeyname, '\\' );
1337 pstrcpy( name, ptr+1 );
1339 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1340 if ( !W_ERROR_IS_OK(result) )
1344 /* use the existing open key information */
1345 newparentinfo = parent;
1348 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1349 result = WERR_NOMEM;
1353 /* lookup the current keys and delete the new one */
1355 fetch_reg_keys( newparentinfo, subkeys );
1357 regsubkey_ctr_delkey( subkeys, name );
1359 /* now write to the registry backend */
1361 write_result = store_reg_keys( newparentinfo, subkeys );
1363 TALLOC_FREE( subkeys );
1365 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1368 /* close any intermediate key handles */
1370 if ( newparentinfo != parent )
1371 close_registry_key( p, &newparent_handle );
1377 /*******************************************************************
1378 ********************************************************************/
1380 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1382 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1390 /* access checks first */
1392 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1393 return WERR_ACCESS_DENIED;
1395 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1396 return WERR_INVALID_PARAM;
1399 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1401 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1404 /* lookup the current values and add the new one */
1406 fetch_reg_values( key, values );
1408 regval_ctr_delvalue( values, valuename );
1410 /* now write to the registry backend */
1412 write_result = store_reg_values( key, values );
1414 TALLOC_FREE( values );
1416 if ( !write_result )
1417 return WERR_REG_IO_FAILURE;
1422 /*******************************************************************
1423 ********************************************************************/
1425 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1427 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1432 /* access checks first */
1434 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1435 return WERR_ACCESS_DENIED;
1437 return WERR_ACCESS_DENIED;
1440 /*******************************************************************
1441 ********************************************************************/
1443 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1445 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1450 /* access checks first */
1452 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1453 return WERR_ACCESS_DENIED;
1455 return WERR_ACCESS_DENIED;
1458 /*******************************************************************
1459 ********************************************************************/
1461 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1463 /* I'm just replying OK because there's not a lot
1464 here I see to do i --jerry */
1469 /*******************************************************************
1470 ********************************************************************/
1472 WERROR _winreg_UnLoadKey(pipes_struct *p)
1474 /* fill in your code here if you think this call should
1477 return WERR_NOT_SUPPORTED;
1480 /*******************************************************************
1481 ********************************************************************/
1483 WERROR _winreg_ReplaceKey(pipes_struct *p)
1485 /* fill in your code here if you think this call should
1488 return WERR_NOT_SUPPORTED;
1491 /*******************************************************************
1492 ********************************************************************/
1494 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1496 /* fill in your code here if you think this call should
1499 return WERR_NOT_SUPPORTED;
1502 /*******************************************************************
1503 ********************************************************************/
1505 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)
1507 /* fill in your code here if you think this call should
1510 return WERR_NOT_SUPPORTED;
1513 /*******************************************************************
1514 ********************************************************************/
1516 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)
1518 /* fill in your code here if you think this call should
1521 return WERR_NOT_SUPPORTED;
1524 /*******************************************************************
1525 ********************************************************************/
1527 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1529 /* fill in your code here if you think this call should
1532 return WERR_NOT_SUPPORTED;