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 };
35 REGVAL_CTR *value_cache;
36 REGSUBKEY_CTR *subkey_cache;
39 /******************************************************************
40 free() function for struct regkey_info
41 *****************************************************************/
43 static void free_regkey_info(void *ptr)
45 struct regkey_info *info = (struct regkey_info *)ptr;
46 regkey_close_internal( info->key );
50 /******************************************************************
51 Find a registry key handle and return a REGISTRY_KEY
52 *****************************************************************/
54 static struct regkey_info *find_regkey_info_by_hnd(pipes_struct *p,
57 struct regkey_info *regkey = NULL;
59 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
60 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
67 static REGISTRY_KEY *find_regkey_by_hnd(pipes_struct *p, POLICY_HND *hnd)
69 struct regkey_info *regkey = find_regkey_info_by_hnd(p, hnd);
78 static WERROR fill_value_cache(struct regkey_info *info)
80 if (info->value_cache != NULL) {
84 if (!(info->value_cache = TALLOC_ZERO_P(info, REGVAL_CTR))) {
88 if (fetch_reg_values(info->key, info->value_cache) == -1) {
89 TALLOC_FREE(info->value_cache);
96 /*******************************************************************
97 Function for open a new registry handle and creating a handle
98 Note that P should be valid & hnd should already have space
100 When we open a key, we store the full path to the key as
101 HK[LM|U]\<key>\<key>\...
102 *******************************************************************/
104 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
105 struct regkey_info **pinfo,
106 REGISTRY_KEY *parent,
107 const char *subkeyname,
108 uint32 access_desired )
112 WERROR result = WERR_OK;
113 struct regkey_info *info;
115 /* create a full registry path and strip any trailing '\'
118 if (asprintf(&keypath, "%s%s%s",
119 parent ? parent->name : "",
125 path_len = strlen( keypath );
126 if ( path_len && keypath[path_len-1] == '\\' )
127 keypath[path_len-1] = '\0';
129 if (!(info = TALLOC_ZERO_P(NULL, struct regkey_info))) {
134 /* now do the internal open */
136 result = regkey_open_internal( &info->key, keypath,
137 p->pipe_user.nt_user_token,
141 if ( !W_ERROR_IS_OK(result) ) {
146 if ( !create_policy_hnd( p, hnd, free_regkey_info, info ) ) {
147 regkey_close_internal( info->key );
159 /*******************************************************************
160 Function for open a new registry handle and creating a handle
161 Note that P should be valid & hnd should already have space
162 *******************************************************************/
164 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
166 REGISTRY_KEY *regkey = find_regkey_by_hnd(p, hnd);
169 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
173 close_policy_hnd(p, hnd);
178 /********************************************************************
179 retrieve information about the subkeys
180 *******************************************************************/
182 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
186 REGSUBKEY_CTR *subkeys;
192 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
195 if ( fetch_reg_keys( key, subkeys ) == -1 )
198 /* find the longest string */
201 num_subkeys = regsubkey_ctr_numkeys( subkeys );
203 for ( i=0; i<num_subkeys; i++ ) {
204 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
205 max_len = MAX(max_len, len);
208 *maxnum = num_subkeys;
211 TALLOC_FREE( subkeys );
216 /********************************************************************
217 retrieve information about the values.
218 *******************************************************************/
220 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
221 uint32 *maxlen, uint32 *maxsize )
224 uint32 sizemax, lenmax;
230 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
233 if ( fetch_reg_values( key, values ) == -1 )
236 lenmax = sizemax = 0;
237 num_values = regval_ctr_numvals( values );
239 for ( i=0; i<num_values; i++ ) {
242 if (!(val = regval_ctr_specific_value( values, i ))) {
246 lenmax = MAX(lenmax, val->valuename ?
247 strlen(val->valuename)+1 : 0 );
248 sizemax = MAX(sizemax, val->size );
251 *maxnum = num_values;
255 TALLOC_FREE( values );
261 /********************************************************************
263 ********************************************************************/
265 WERROR _winreg_CloseKey(pipes_struct *p, struct policy_handle *handle)
267 /* close the policy handle */
269 if (!close_registry_key(p, handle))
275 /*******************************************************************
276 ********************************************************************/
278 WERROR _winreg_OpenHKLM(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
280 return open_registry_key(p, handle, NULL, NULL, KEY_HKLM, access_mask);
283 /*******************************************************************
284 ********************************************************************/
286 WERROR _winreg_OpenHKPD(pipes_struct *p, uint16_t *system_name,
287 uint32_t access_mask, struct policy_handle *handle)
289 return open_registry_key(p, handle, NULL, NULL, KEY_HKPD, access_mask);
292 /*******************************************************************
293 ********************************************************************/
295 WERROR _winreg_OpenHKPT(pipes_struct *p, uint16_t *system_name,
296 uint32_t access_mask, struct policy_handle *handle)
298 return open_registry_key(p, handle, NULL, NULL, KEY_HKPT, access_mask);
301 /*******************************************************************
302 ********************************************************************/
304 WERROR _winreg_OpenHKCR(pipes_struct *p, uint16_t *system_name,
305 uint32_t access_mask, struct policy_handle *handle)
307 return open_registry_key(p, handle, NULL, NULL, KEY_HKCR, access_mask);
310 /*******************************************************************
311 ********************************************************************/
313 WERROR _winreg_OpenHKU(pipes_struct *p, uint16_t *system_name,
314 uint32_t access_mask, struct policy_handle *handle)
316 return open_registry_key(p, handle, NULL, NULL, KEY_HKU, access_mask);
319 /*******************************************************************
320 ********************************************************************/
322 WERROR _winreg_OpenHKCU(pipes_struct *p, uint16_t *system_name,
323 uint32_t access_mask, struct policy_handle *handle)
325 return open_registry_key(p, handle, NULL, NULL, KEY_HKCU, access_mask);
328 /*******************************************************************
329 ********************************************************************/
331 WERROR _winreg_OpenHKCC(pipes_struct *p, uint16_t *system_name,
332 uint32_t access_mask, struct policy_handle *handle)
334 return open_registry_key(p, handle, NULL, NULL, KEY_HKCC, access_mask);
337 /*******************************************************************
338 ********************************************************************/
340 WERROR _winreg_OpenHKDD(pipes_struct *p, uint16_t *system_name,
341 uint32_t access_mask, struct policy_handle *handle)
343 return open_registry_key(p, handle, NULL, NULL, KEY_HKDD, access_mask);
346 /*******************************************************************
347 ********************************************************************/
349 WERROR _winreg_OpenHKPN(pipes_struct *p, uint16_t *system_name,
350 uint32_t access_mask, struct policy_handle *handle)
352 return open_registry_key(p, handle, NULL, NULL, KEY_HKPN, access_mask);
355 /*******************************************************************
357 ********************************************************************/
359 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)
362 REGISTRY_KEY *parent = find_regkey_by_hnd(p, parent_handle );
368 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
369 return WERR_INVALID_PARAM;
372 /* check granted access first; what is the correct mask here? */
374 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
375 SEC_RIGHTS_CREATE_SUBKEY|
376 SEC_RIGHTS_QUERY_VALUE|
377 SEC_RIGHTS_SET_VALUE);
379 if ( !(parent->access_granted & check_rights) ) {
380 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
381 return WERR_ACCESS_DENIED;
385 * very crazy, but regedit.exe on Win2k will attempt to call
386 * REG_OPEN_ENTRY with a keyname of "". We should return a new
387 * (second) handle here on the key->name. regedt32.exe does
388 * not do this stupidity. --jerry
391 return open_registry_key( p, handle, NULL, parent, name, access_mask );
394 /*******************************************************************
396 ********************************************************************/
398 WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
399 struct winreg_String value_name,
400 enum winreg_Type *type, uint8_t *data,
401 uint32_t *data_size, uint32_t *value_length)
403 WERROR status = WERR_BADFILE;
404 struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
405 REGISTRY_KEY *regkey;
409 uint32_t outbuf_size;
411 BOOL free_buf = False;
412 BOOL free_prs = False;
419 *value_length = *type = 0;
421 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
422 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
424 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
425 if(regkey->type == REG_KEY_HKPD)
427 if(strequal(value_name.name, "Global")) {
428 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
429 status = reg_perfcount_get_hkpd(
430 &prs_hkpd, *data_size, &outbuf_size, NULL);
431 outbuf = (uint8_t *)prs_hkpd.data_p;
434 else if(strequal(value_name.name, "Counter 009")) {
435 outbuf_size = reg_perfcount_get_counter_names(
436 reg_perfcount_get_base_index(),
437 (char **)(void *)&outbuf);
440 else if(strequal(value_name.name, "Explain 009")) {
441 outbuf_size = reg_perfcount_get_counter_help(
442 reg_perfcount_get_base_index(),
443 (char **)(void *)&outbuf);
446 else if(isdigit(value_name.name[0])) {
447 /* we probably have a request for a specific object
449 prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
450 status = reg_perfcount_get_hkpd(
451 &prs_hkpd, *data_size, &outbuf_size,
453 outbuf = (uint8_t *)prs_hkpd.data_p;
457 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
465 REGISTRY_VALUE *val = NULL;
468 status = fill_value_cache(info);
470 if (!(W_ERROR_IS_OK(status))) {
474 for (i=0; i<info->value_cache->num_values; i++) {
475 if (strequal(info->value_cache->values[i]->valuename,
477 val = info->value_cache->values[i];
492 outbuf = val->data_p;
493 outbuf_size = val->size;
497 *value_length = outbuf_size;
499 if ( *data_size == 0 || !data ) {
501 } else if ( *value_length > *data_size ) {
502 status = WERR_MORE_DATA;
504 memcpy( data, outbuf, *value_length );
508 *data_size = *value_length;
510 if (free_prs) prs_mem_free(&prs_hkpd);
511 if (free_buf) SAFE_FREE(outbuf);
516 /*****************************************************************************
517 Implementation of REG_QUERY_KEY
518 ****************************************************************************/
520 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle,
521 struct winreg_String *classname,
522 uint32_t *num_subkeys, uint32_t *max_subkeylen,
523 uint32_t *max_subkeysize,
524 uint32_t *num_values, uint32_t *max_valnamelen,
525 uint32_t *max_valbufsize,
526 uint32_t *secdescsize, NTTIME *last_changed_time)
528 WERROR status = WERR_OK;
529 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
534 if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
535 DEBUG(0,("_winreg_QueryInfoKey: get_subkey_information() failed!\n"));
536 return WERR_ACCESS_DENIED;
539 if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
540 DEBUG(0,("_winreg_QueryInfoKey: get_value_information() failed!\n"));
541 return WERR_ACCESS_DENIED;
544 *secdescsize = 0; /* used to be hard coded for 0x00000078 */
545 *last_changed_time = 0;
546 *max_subkeysize = 0; /* maybe this is the classname length ? */
548 /* don't bother with class names for now */
550 classname->name = NULL;
556 /*****************************************************************************
557 Implementation of REG_GETVERSION
558 ****************************************************************************/
560 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
562 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
567 *version = 0x00000005; /* Windows 2000 registry API version */
573 /*****************************************************************************
574 Implementation of REG_ENUM_KEY
575 ****************************************************************************/
577 WERROR _winreg_EnumKey(pipes_struct *p, struct policy_handle *handle,
578 uint32_t enum_index, struct winreg_StringBuf *name,
579 struct winreg_StringBuf **keyclass,
580 NTTIME **last_changed_time)
582 WERROR status = WERR_OK;
583 struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
584 REGISTRY_KEY *regkey;
591 if ( !name || !keyclass )
592 return WERR_INVALID_PARAM;
594 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
596 if (!info->subkey_cache) {
597 if (!(info->subkey_cache = TALLOC_ZERO_P(
598 info, REGSUBKEY_CTR))) {
602 if (fetch_reg_keys(regkey, info->subkey_cache) == -1) {
603 TALLOC_FREE(info->subkey_cache);
604 return WERR_NO_MORE_ITEMS;
608 if (enum_index >= info->subkey_cache->num_subkeys) {
609 return WERR_NO_MORE_ITEMS;
612 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n",
613 info->subkey_cache->subkeys[enum_index]));
615 if (!(name->name = talloc_strdup(
616 p->mem_ctx, info->subkey_cache->subkeys[enum_index]))) {
619 if ( *last_changed_time ) {
620 **last_changed_time = 0;
623 (*keyclass)->name = "";
629 /*****************************************************************************
630 Implementation of REG_ENUM_VALUE
631 ****************************************************************************/
633 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle,
634 uint32_t enum_index, struct winreg_ValNameBuf *name,
635 enum winreg_Type *type, uint8_t *data,
636 uint32_t *data_size, uint32_t *value_length)
638 WERROR status = WERR_OK;
639 struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
640 REGISTRY_KEY *regkey;
641 REGISTRY_VALUE *val = NULL;
647 return WERR_INVALID_PARAM;
651 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
654 status = fill_value_cache(info);
655 if (!W_ERROR_IS_OK(status)) {
659 if (enum_index >= info->value_cache->num_values) {
663 val = info->value_cache->values[enum_index];
665 if (!(name->name = talloc_strdup(p->mem_ctx, val->valuename))) {
674 if ((data_size == NULL) || (value_length == NULL)) {
675 return WERR_INVALID_PARAM;
678 if (val->size > *data_size) {
679 return WERR_MORE_DATA;
682 memcpy( data, val->data_p, val->size );
685 if (value_length != NULL) {
686 *value_length = val->size;
688 if (data_size != NULL) {
689 *data_size = val->size;
695 /*******************************************************************
697 ********************************************************************/
699 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
703 /* thunk down to _winreg_InitiateSystemShutdownEx()
704 (just returns a status) */
706 return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout,
707 force_apps, reboot, reason );
710 /*******************************************************************
712 ********************************************************************/
714 #define SHUTDOWN_R_STRING "-r"
715 #define SHUTDOWN_F_STRING "-f"
718 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)
720 pstring shutdown_script;
731 pstrcpy(shutdown_script, lp_shutdown_script());
733 if ( !*shutdown_script )
734 return WERR_ACCESS_DENIED;
736 /* pull the message string and perform necessary sanity checks on it */
740 if ( message && message->name && message->name->name ) {
741 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
744 alpha_strcpy (chkmsg, msg, NULL, sizeof(chkmsg));
747 fstr_sprintf(str_timeout, "%d", timeout);
748 fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
749 fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
750 fstr_sprintf(str_reason, "%d", reason );
752 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
753 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
754 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
755 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
756 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
758 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
760 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
761 Take the error return from the script and provide it as the Windows return code. */
763 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
768 ret = smbrun( shutdown_script, NULL );
773 /********** END SeRemoteShutdownPrivilege BLOCK **********/
775 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
776 shutdown_script, ret));
779 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
785 /*******************************************************************
787 ********************************************************************/
789 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
791 pstring abort_shutdown_script;
795 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
797 if ( !*abort_shutdown_script )
798 return WERR_ACCESS_DENIED;
800 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
802 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
807 ret = smbrun( abort_shutdown_script, NULL );
812 /********** END SeRemoteShutdownPrivilege BLOCK **********/
814 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
815 abort_shutdown_script, ret));
818 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
821 /*******************************************************************
822 ********************************************************************/
824 static int validate_reg_filename( pstring fname )
827 int num_services = lp_numservices();
832 /* convert to a unix path, stripping the C:\ along the way */
834 if ( !(p = valid_share_pathname( fname ) ))
837 /* has to exist within a valid file share */
839 for ( snum=0; snum<num_services; snum++ ) {
841 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
844 pstrcpy( share_path, lp_pathname(snum) );
846 /* make sure we have a path (e.g. [homes] ) */
848 if ( strlen( share_path ) == 0 )
851 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
855 /* p and fname are overlapping memory so copy out and back in again */
857 pstrcpy( unix_fname, p );
858 pstrcpy( fname, unix_fname );
860 return (snum < num_services) ? snum : -1;
863 /*******************************************************************
864 Note: topkeypat is the *full* path that this *key will be
865 loaded into (including the name of the key)
866 ********************************************************************/
868 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
872 REGISTRY_KEY registry_key;
874 REGSUBKEY_CTR *subkeys;
877 WERROR result = WERR_OK;
879 /* initialize the REGISTRY_KEY structure */
881 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
882 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
886 pstrcpy( registry_key.name, topkeypath );
888 /* now start parsing the values and subkeys */
890 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
893 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
896 /* copy values into the REGVAL_CTR */
898 for ( i=0; i<key->num_values; i++ ) {
899 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
900 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
903 /* copy subkeys into the REGSUBKEY_CTR */
905 key->subkey_index = 0;
906 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
907 regsubkey_ctr_addkey( subkeys, subkey->keyname );
910 /* write this key and values out */
912 if ( !store_reg_values( ®istry_key, values )
913 || !store_reg_keys( ®istry_key, subkeys ) )
915 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
916 result = WERR_REG_IO_FAILURE;
919 TALLOC_FREE( subkeys );
921 if ( !W_ERROR_IS_OK(result) )
924 /* now continue to load each subkey registry tree */
926 key->subkey_index = 0;
927 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
928 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
929 result = reg_load_tree( regfile, path, subkey );
930 if ( !W_ERROR_IS_OK(result) )
937 /*******************************************************************
938 ********************************************************************/
940 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
943 REGF_NK_REC *rootkey;
946 /* open the registry file....fail if the file already exists */
948 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
949 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
950 fname, strerror(errno) ));
951 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
954 /* get the rootkey from the regf file and then load the tree
955 via recursive calls */
957 if ( !(rootkey = regfio_rootkey( regfile )) ) {
958 regfio_close( regfile );
959 return WERR_REG_FILE_INVALID;
962 result = reg_load_tree( regfile, krecord->name, rootkey );
966 regfio_close( regfile );
971 /*******************************************************************
972 ********************************************************************/
974 WERROR _winreg_RestoreKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, uint32_t flags)
976 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
983 if ( !filename || !filename->name )
984 return WERR_INVALID_PARAM;
986 pstrcpy( fname, filename->name );
988 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from \"%s\"\n", regkey->name, fname));
990 if ( (snum = validate_reg_filename( fname )) == -1 )
991 return WERR_OBJECT_PATH_INVALID;
993 /* user must posses SeRestorePrivilege for this this proceed */
995 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
996 return WERR_ACCESS_DENIED;
998 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
1000 return restore_registry_key( regkey, fname );
1003 /********************************************************************
1004 ********************************************************************/
1006 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
1007 REGF_NK_REC *parent, SEC_DESC *sec_desc )
1011 REGSUBKEY_CTR *subkeys;
1014 char *keyname, *parentpath;
1017 REGISTRY_KEY registry_key;
1018 WERROR result = WERR_OK;
1021 return WERR_GENERAL_FAILURE;
1024 return WERR_OBJECT_PATH_INVALID;
1026 /* split up the registry key path */
1028 pstrcpy( key_tmp, keypath );
1029 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
1030 return WERR_OBJECT_PATH_INVALID;
1033 keyname = parentpath;
1035 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
1037 ZERO_STRUCT( registry_key );
1039 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
1042 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
1043 return WERR_BADFILE;
1045 /* lookup the values and subkeys */
1047 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
1050 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
1053 fetch_reg_keys( ®istry_key, subkeys );
1054 fetch_reg_values( ®istry_key, values );
1056 /* write out this key */
1058 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1059 result = WERR_CAN_NOT_COMPLETE;
1063 /* write each one of the subkeys out */
1065 num_subkeys = regsubkey_ctr_numkeys( subkeys );
1066 for ( i=0; i<num_subkeys; i++ ) {
1067 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1068 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1069 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1070 if ( !W_ERROR_IS_OK(result) )
1074 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1077 TALLOC_FREE( subkeys );
1078 TALLOC_FREE( registry_key.name );
1083 /*******************************************************************
1084 ********************************************************************/
1086 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1088 DOM_SID adm_sid, owner_sid;
1089 SEC_ACE ace[2]; /* at most 2 entries */
1091 SEC_ACL *psa = NULL;
1094 /* set the owner to BUILTIN\Administrator */
1096 sid_copy(&owner_sid, &global_sid_Builtin);
1097 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1100 /* basic access for Everyone */
1102 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1103 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1105 /* add Full Access 'BUILTIN\Administrators' */
1107 init_sec_access(&mask, reg_generic_map.generic_all);
1108 sid_copy(&adm_sid, &global_sid_Builtin);
1109 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1110 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1112 /* create the security descriptor */
1114 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1117 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1123 /*******************************************************************
1124 ********************************************************************/
1126 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1130 SEC_DESC *sd = NULL;
1132 /* open the registry file....fail if the file already exists */
1134 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1135 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1136 fname, strerror(errno) ));
1137 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1140 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1141 regfio_close( regfile );
1145 /* write the registry tree to the file */
1147 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1151 regfio_close( regfile );
1156 /*******************************************************************
1157 ********************************************************************/
1159 WERROR _winreg_SaveKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, struct KeySecurityAttribute *sec_attrib)
1161 REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
1168 if ( !filename || !filename->name )
1169 return WERR_INVALID_PARAM;
1171 pstrcpy( fname, filename->name );
1173 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n", regkey->name, fname));
1175 if ( (snum = validate_reg_filename( fname )) == -1 )
1176 return WERR_OBJECT_PATH_INVALID;
1178 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n", regkey->name, fname, lp_servicename(snum) ));
1180 return backup_registry_key( regkey, fname );
1183 /*******************************************************************
1184 ********************************************************************/
1186 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1188 /* fill in your code here if you think this call should
1191 p->rng_fault_state = True;
1192 return WERR_NOT_SUPPORTED;
1195 /*******************************************************************
1196 ********************************************************************/
1198 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle,
1199 struct winreg_String keyname,
1200 struct winreg_String keyclass,
1201 uint32_t options, uint32_t access_mask,
1202 struct winreg_SecBuf *secdesc,
1203 struct policy_handle *new_handle,
1204 enum winreg_CreateAction **action_taken )
1206 struct regkey_info *parent = find_regkey_info_by_hnd(p, handle);
1207 struct regkey_info *newparentinfo, *keyinfo;
1208 POLICY_HND newparent_handle;
1209 REGSUBKEY_CTR *subkeys;
1217 if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1221 /* ok. Here's what we do. */
1223 if ( strrchr( name, '\\' ) ) {
1227 /* (1) check for enumerate rights on the parent handle.
1228 Clients can try create things like 'SOFTWARE\Samba' on
1229 the HKLM handle. (2) open the path to the child parent
1232 if ( !(parent->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1233 return WERR_ACCESS_DENIED;
1235 pstrcpy( newkeyname, name );
1236 ptr = strrchr( newkeyname, '\\' );
1239 result = open_registry_key( p, &newparent_handle,
1241 parent->key, newkeyname,
1242 (REG_KEY_READ|REG_KEY_WRITE) );
1244 if ( !W_ERROR_IS_OK(result) )
1247 /* copy the new key name (just the lower most keyname) */
1249 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1254 /* use the existing open key information */
1255 newparentinfo = parent;
1256 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1259 /* (3) check for create subkey rights on the correct parent */
1261 if ( !(newparentinfo->key->access_granted
1262 & SEC_RIGHTS_CREATE_SUBKEY) ) {
1263 result = WERR_ACCESS_DENIED;
1267 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1268 result = WERR_NOMEM;
1272 /* (4) lookup the current keys and add the new one */
1274 fetch_reg_keys( newparentinfo->key, subkeys );
1275 regsubkey_ctr_addkey( subkeys, name );
1277 /* now write to the registry backend */
1279 write_result = store_reg_keys( newparentinfo->key, subkeys );
1281 TALLOC_FREE( subkeys );
1282 TALLOC_FREE( newparentinfo->subkey_cache );
1284 if ( !write_result )
1285 return WERR_REG_IO_FAILURE;
1287 /* (5) open the new key and return the handle. Note that it is probably
1288 not correct to grant full access on this open handle. */
1290 result = open_registry_key( p, new_handle, &keyinfo,
1291 newparentinfo->key, name, REG_KEY_READ );
1292 keyinfo->key->access_granted = REG_KEY_ALL;
1294 /* FIXME: report the truth here */
1296 if ( *action_taken ) {
1297 **action_taken = REG_CREATED_NEW_KEY;
1301 /* close any intermediate key handles */
1303 if ( newparentinfo != parent )
1304 close_registry_key( p, &newparent_handle );
1310 /*******************************************************************
1311 ********************************************************************/
1313 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1315 struct regkey_info *info = find_regkey_info_by_hnd(p, handle);
1325 /* access checks first */
1327 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1328 return WERR_ACCESS_DENIED;
1330 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name,
1333 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1336 /* lookup the current values and add the new one */
1338 fetch_reg_values( key, values );
1340 regval_ctr_addvalue( values, name.name, type,
1341 (const char *)data, size );
1343 /* now write to the registry backend */
1345 write_result = store_reg_values( key, values );
1347 TALLOC_FREE( values );
1349 if ( !write_result )
1350 return WERR_REG_IO_FAILURE;
1352 TALLOC_FREE(info->value_cache);
1357 /*******************************************************************
1358 ********************************************************************/
1360 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1362 struct regkey_info *parent = find_regkey_info_by_hnd(p, handle);
1363 struct regkey_info *newparentinfo = NULL;
1364 POLICY_HND newparent_handle;
1365 REGSUBKEY_CTR *subkeys;
1373 /* MSDN says parent the handle must have been opened with DELETE access */
1375 /* (1) check for delete rights on the parent */
1377 if ( !(parent->key->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1378 result = WERR_ACCESS_DENIED;
1382 if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1383 result = WERR_INVALID_PARAM;
1387 /* ok. Here's what we do. */
1389 if ( strrchr( name, '\\' ) ) {
1393 /* (2) open the path to the child parent key if necessary */
1394 /* split the registry path and save the subkeyname */
1396 pstrcpy( newkeyname, name );
1397 ptr = strrchr( newkeyname, '\\' );
1399 if ( (name = talloc_strdup( p->mem_ctx, ptr+1 )) == NULL ) {
1400 result = WERR_NOMEM;
1404 result = open_registry_key( p, &newparent_handle,
1405 &newparentinfo, parent->key,
1407 (REG_KEY_READ|REG_KEY_WRITE) );
1408 if ( !W_ERROR_IS_OK(result) ) {
1413 /* use the existing open key information */
1414 newparentinfo = parent;
1417 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1418 result = WERR_NOMEM;
1422 /* lookup the current keys and delete the new one */
1424 fetch_reg_keys( newparentinfo->key, subkeys );
1426 regsubkey_ctr_delkey( subkeys, name );
1428 /* now write to the registry backend */
1430 write_result = store_reg_keys( newparentinfo->key, subkeys );
1432 TALLOC_FREE( subkeys );
1433 TALLOC_FREE( newparentinfo->subkey_cache );
1435 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1438 /* close any intermediate key handles */
1440 if ( newparentinfo != parent )
1441 close_registry_key( p, &newparent_handle );
1447 /*******************************************************************
1448 ********************************************************************/
1450 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1452 struct regkey_info *info = find_regkey_info_by_hnd(p, handle);
1463 /* access checks first */
1465 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1466 return WERR_ACCESS_DENIED;
1468 if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1469 return WERR_INVALID_PARAM;
1472 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1474 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1477 /* lookup the current values and add the new one */
1479 fetch_reg_values( key, values );
1481 regval_ctr_delvalue( values, valuename );
1483 /* now write to the registry backend */
1485 write_result = store_reg_values( key, values );
1487 TALLOC_FREE( values );
1489 if ( !write_result )
1490 return WERR_REG_IO_FAILURE;
1492 TALLOC_FREE(info->value_cache);
1497 /*******************************************************************
1498 ********************************************************************/
1500 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1502 REGISTRY_KEY *key = find_regkey_by_hnd(p, handle);
1507 /* access checks first */
1509 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1510 return WERR_ACCESS_DENIED;
1512 return WERR_ACCESS_DENIED;
1515 /*******************************************************************
1516 ********************************************************************/
1518 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1520 REGISTRY_KEY *key = find_regkey_by_hnd(p, handle);
1525 /* access checks first */
1527 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1528 return WERR_ACCESS_DENIED;
1530 return WERR_ACCESS_DENIED;
1533 /*******************************************************************
1534 ********************************************************************/
1536 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1538 /* I'm just replying OK because there's not a lot
1539 here I see to do i --jerry */
1544 /*******************************************************************
1545 ********************************************************************/
1547 WERROR _winreg_UnLoadKey(pipes_struct *p)
1549 /* fill in your code here if you think this call should
1552 p->rng_fault_state = True;
1553 return WERR_NOT_SUPPORTED;
1556 /*******************************************************************
1557 ********************************************************************/
1559 WERROR _winreg_ReplaceKey(pipes_struct *p)
1561 /* fill in your code here if you think this call should
1564 p->rng_fault_state = True;
1565 return WERR_NOT_SUPPORTED;
1568 /*******************************************************************
1569 ********************************************************************/
1571 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1573 /* fill in your code here if you think this call should
1576 p->rng_fault_state = True;
1577 return WERR_NOT_SUPPORTED;
1580 /*******************************************************************
1581 ********************************************************************/
1583 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)
1585 /* fill in your code here if you think this call should
1588 p->rng_fault_state = True;
1589 return WERR_NOT_SUPPORTED;
1592 /*******************************************************************
1593 ********************************************************************/
1595 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)
1597 /* fill in your code here if you think this call should
1600 p->rng_fault_state = True;
1601 return WERR_NOT_SUPPORTED;
1604 /*******************************************************************
1605 ********************************************************************/
1607 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1609 /* fill in your code here if you think this call should
1612 p->rng_fault_state = True;
1613 return WERR_NOT_SUPPORTED;