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 || !data ) {
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 || !data ) {
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 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1197 /* use the existing open key information */
1198 newparentinfo = parent;
1199 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1202 /* (3) check for create subkey rights on the correct parent */
1204 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1205 result = WERR_ACCESS_DENIED;
1209 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1210 result = WERR_NOMEM;
1214 /* (4) lookup the current keys and add the new one */
1216 fetch_reg_keys( newparentinfo, subkeys );
1217 regsubkey_ctr_addkey( subkeys, name );
1219 /* now write to the registry backend */
1221 write_result = store_reg_keys( newparentinfo, subkeys );
1223 TALLOC_FREE( subkeys );
1225 if ( !write_result )
1226 return WERR_REG_IO_FAILURE;
1228 /* (5) open the new key and return the handle. Note that it is probably
1229 not correct to grant full access on this open handle. */
1231 result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1232 keyinfo->access_granted = REG_KEY_ALL;
1234 /* FIXME: report the truth here */
1236 if ( action_taken ) {
1237 *action_taken = REG_CREATED_NEW_KEY;
1241 /* close any intermediate key handles */
1243 if ( newparentinfo != parent )
1244 close_registry_key( p, &newparent_handle );
1250 /*******************************************************************
1251 ********************************************************************/
1253 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1255 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1263 /* access checks first */
1265 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1266 return WERR_ACCESS_DENIED;
1268 /* verify the name */
1270 if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1271 return WERR_INVALID_PARAM;
1274 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1276 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1279 /* lookup the current values and add the new one */
1281 fetch_reg_values( key, values );
1283 regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1285 /* now write to the registry backend */
1287 write_result = store_reg_values( key, values );
1289 TALLOC_FREE( values );
1291 if ( !write_result )
1292 return WERR_REG_IO_FAILURE;
1297 /*******************************************************************
1298 ********************************************************************/
1300 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1302 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1303 REGISTRY_KEY *newparentinfo = NULL;
1304 POLICY_HND newparent_handle;
1305 REGSUBKEY_CTR *subkeys;
1313 /* MSDN says parent the handle must have been opened with DELETE access */
1315 /* (1) check for delete rights on the parent */
1317 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1318 result = WERR_ACCESS_DENIED;
1322 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1323 result = WERR_INVALID_PARAM;
1327 /* ok. Here's what we do. */
1329 if ( strrchr( name, '\\' ) ) {
1333 /* (2) open the path to the child parent key if necessary */
1334 /* split the registry path and save the subkeyname */
1336 pstrcpy( newkeyname, name );
1337 ptr = strrchr( newkeyname, '\\' );
1339 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1340 result = WERR_NOMEM;
1344 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1345 if ( !W_ERROR_IS_OK(result) ) {
1350 /* use the existing open key information */
1351 newparentinfo = parent;
1354 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1355 result = WERR_NOMEM;
1359 /* lookup the current keys and delete the new one */
1361 fetch_reg_keys( newparentinfo, subkeys );
1363 regsubkey_ctr_delkey( subkeys, name );
1365 /* now write to the registry backend */
1367 write_result = store_reg_keys( newparentinfo, subkeys );
1369 TALLOC_FREE( subkeys );
1371 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1374 /* close any intermediate key handles */
1376 if ( newparentinfo != parent )
1377 close_registry_key( p, &newparent_handle );
1383 /*******************************************************************
1384 ********************************************************************/
1386 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1388 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1396 /* access checks first */
1398 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1399 return WERR_ACCESS_DENIED;
1401 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1402 return WERR_INVALID_PARAM;
1405 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1407 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1410 /* lookup the current values and add the new one */
1412 fetch_reg_values( key, values );
1414 regval_ctr_delvalue( values, valuename );
1416 /* now write to the registry backend */
1418 write_result = store_reg_values( key, values );
1420 TALLOC_FREE( values );
1422 if ( !write_result )
1423 return WERR_REG_IO_FAILURE;
1428 /*******************************************************************
1429 ********************************************************************/
1431 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1433 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1438 /* access checks first */
1440 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1441 return WERR_ACCESS_DENIED;
1443 return WERR_ACCESS_DENIED;
1446 /*******************************************************************
1447 ********************************************************************/
1449 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1451 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1456 /* access checks first */
1458 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1459 return WERR_ACCESS_DENIED;
1461 return WERR_ACCESS_DENIED;
1464 /*******************************************************************
1465 ********************************************************************/
1467 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1469 /* I'm just replying OK because there's not a lot
1470 here I see to do i --jerry */
1475 /*******************************************************************
1476 ********************************************************************/
1478 WERROR _winreg_UnLoadKey(pipes_struct *p)
1480 /* fill in your code here if you think this call should
1483 return WERR_NOT_SUPPORTED;
1486 /*******************************************************************
1487 ********************************************************************/
1489 WERROR _winreg_ReplaceKey(pipes_struct *p)
1491 /* fill in your code here if you think this call should
1494 return WERR_NOT_SUPPORTED;
1497 /*******************************************************************
1498 ********************************************************************/
1500 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1502 /* fill in your code here if you think this call should
1505 return WERR_NOT_SUPPORTED;
1508 /*******************************************************************
1509 ********************************************************************/
1511 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)
1513 /* fill in your code here if you think this call should
1516 return WERR_NOT_SUPPORTED;
1519 /*******************************************************************
1520 ********************************************************************/
1522 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)
1524 /* fill in your code here if you think this call should
1527 return WERR_NOT_SUPPORTED;
1530 /*******************************************************************
1531 ********************************************************************/
1533 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1535 /* fill in your code here if you think this call should
1538 return WERR_NOT_SUPPORTED;