2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997.
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
6 * Copyright (C) Paul Ashton 1997.
7 * Copyright (C) Jeremy Allison 2001.
8 * Copyright (C) Gerald Carter 2002-2005.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* Implementation of registry functions. */
31 #define DBGC_CLASS DBGC_RPC_SRV
33 #define REGSTR_PRODUCTTYPE "ProductType"
34 #define REG_PT_WINNT "WinNT"
35 #define REG_PT_LANMANNT "LanmanNT"
36 #define REG_PT_SERVERNT "ServerNT"
38 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
39 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
42 /* no idea if this is correct, just use the file access bits for now */
44 struct generic_mapping reg_map = { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
46 /********************************************************************
47 ********************************************************************/
49 NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
50 uint32 access_desired, uint32 *access_granted )
54 se_access_check( sec_desc, token, access_desired, access_granted, &result );
59 /********************************************************************
60 ********************************************************************/
62 SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
71 /* basic access for Everyone */
73 init_sec_access(&mask, REG_KEY_READ );
74 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
76 /* Full Access 'BUILTIN\Administrators' */
78 init_sec_access(&mask, REG_KEY_ALL );
79 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
82 /* create the security descriptor */
84 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
87 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
93 /******************************************************************
94 free() function for REGISTRY_KEY
95 *****************************************************************/
97 static void free_regkey_info(void *ptr)
99 REGISTRY_KEY *info = (REGISTRY_KEY*)ptr;
104 /******************************************************************
105 Find a registry key handle and return a REGISTRY_KEY
106 *****************************************************************/
108 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
110 REGISTRY_KEY *regkey = NULL;
112 if(!find_policy_by_hnd(p,hnd,(void **)®key)) {
113 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
121 /*******************************************************************
122 Function for open a new registry handle and creating a handle
123 Note that P should be valid & hnd should already have space
125 When we open a key, we store the full path to the key as
126 HK[LM|U]\<key>\<key>\...
127 *******************************************************************/
129 static WERROR open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent,
130 const char *subkeyname, uint32 access_granted )
132 REGISTRY_KEY *regkey = NULL;
133 WERROR result = WERR_OK;
134 REGSUBKEY_CTR subkeys;
138 DEBUG(7,("open_registry_key: name = [%s][%s]\n",
139 parent ? parent->name : "NULL", subkeyname));
141 /* strip any trailing '\'s */
142 pstrcpy( subkeyname2, subkeyname );
143 subkey_len = strlen ( subkeyname2 );
144 if ( subkey_len && subkeyname2[subkey_len-1] == '\\' )
145 subkeyname2[subkey_len-1] = '\0';
147 if ((regkey=SMB_MALLOC_P(REGISTRY_KEY)) == NULL)
150 ZERO_STRUCTP( regkey );
153 * very crazy, but regedit.exe on Win2k will attempt to call
154 * REG_OPEN_ENTRY with a keyname of "". We should return a new
155 * (second) handle here on the key->name. regedt32.exe does
156 * not do this stupidity. --jerry
160 pstrcpy( regkey->name, parent->name );
163 pstrcpy( regkey->name, "" );
165 pstrcat( regkey->name, parent->name );
166 pstrcat( regkey->name, "\\" );
168 pstrcat( regkey->name, subkeyname2 );
171 /* Look up the table of registry I/O operations */
173 if ( !(regkey->hook = reghook_cache_find( regkey->name )) ) {
174 DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
179 /* check if the path really exists; failed is indicated by -1 */
180 /* if the subkey count failed, bail out */
182 ZERO_STRUCTP( &subkeys );
184 regsubkey_ctr_init( &subkeys );
186 if ( fetch_reg_keys( regkey, &subkeys ) == -1 ) {
188 /* don't really know what to return here */
189 result = WERR_BADFILE;
193 * This would previously return NT_STATUS_TOO_MANY_SECRETS
194 * that doesn't sound quite right to me --jerry
197 if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) )
198 result = WERR_BADFILE;
203 regsubkey_ctr_destroy( &subkeys );
205 if ( ! NT_STATUS_IS_OK(result) )
208 DEBUG(7,("open_registry_key: exit\n"));
213 /*******************************************************************
214 Function for open a new registry handle and creating a handle
215 Note that P should be valid & hnd should already have space
216 *******************************************************************/
218 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
220 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
223 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
227 close_policy_hnd(p, hnd);
232 /********************************************************************
233 retrieve information about the subkeys
234 *******************************************************************/
236 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
240 REGSUBKEY_CTR subkeys;
246 ZERO_STRUCTP( &subkeys );
248 regsubkey_ctr_init( &subkeys );
250 if ( fetch_reg_keys( key, &subkeys ) == -1 )
253 /* find the longest string */
256 num_subkeys = regsubkey_ctr_numkeys( &subkeys );
258 for ( i=0; i<num_subkeys; i++ ) {
259 len = strlen( regsubkey_ctr_specific_key(&subkeys, i) );
260 max_len = MAX(max_len, len);
263 *maxnum = num_subkeys;
266 regsubkey_ctr_destroy( &subkeys );
271 /********************************************************************
272 retrieve information about the values. We don't store values
273 here. The registry tdb is intended to be a frontend to oether
274 Samba tdb's (such as ntdrivers.tdb).
275 *******************************************************************/
277 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
278 uint32 *maxlen, uint32 *maxsize )
282 uint32 sizemax, lenmax;
289 ZERO_STRUCTP( &values );
291 regval_ctr_init( &values );
293 if ( fetch_reg_values( key, &values ) == -1 )
296 lenmax = sizemax = 0;
297 num_values = regval_ctr_numvals( &values );
299 val = regval_ctr_specific_value( &values, 0 );
301 for ( i=0; i<num_values && val; i++ )
303 lenmax = MAX(lenmax, strlen(val->valuename)+1 );
304 sizemax = MAX(sizemax, val->size );
306 val = regval_ctr_specific_value( &values, i );
309 *maxnum = num_values;
313 regval_ctr_destroy( &values );
319 /********************************************************************
321 ********************************************************************/
323 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
325 /* close the policy handle */
327 if ( !close_registry_key(p, &q_u->pol) )
333 /*******************************************************************
334 ********************************************************************/
336 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
339 uint32 access_granted = 0;
342 /* perform access checks */
343 /* top level keys are done here without passing through the REGISTRY_HOOK api */
345 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
348 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
349 if ( !NT_STATUS_IS_OK(status) )
350 return ntstatus_to_werror( status );
352 return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, access_granted );
355 /*******************************************************************
356 ********************************************************************/
358 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
361 uint32 access_granted = 0;
364 /* perform access checks */
365 /* top level keys are done here without passing through the REGISTRY_HOOK api */
367 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
370 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
371 if ( !NT_STATUS_IS_OK(status) )
372 return ntstatus_to_werror( status );
374 return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, access_granted );
377 /*******************************************************************
378 ********************************************************************/
380 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
383 uint32 access_granted = 0;
386 /* perform access checks */
387 /* top level keys are done here without passing through the REGISTRY_HOOK api */
389 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
392 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
393 if ( !NT_STATUS_IS_OK(status) )
394 return ntstatus_to_werror( status );
396 return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, access_granted );
399 /*******************************************************************
401 ********************************************************************/
403 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
407 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->pol);
410 DEBUG(5,("reg_open_entry: Enter\n"));
415 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
417 result = open_registry_key( p, &pol, key, name, 0x0 );
419 init_reg_r_open_entry( r_u, &pol, result );
421 DEBUG(5,("reg_open_entry: Exit\n"));
426 /*******************************************************************
428 ********************************************************************/
430 WERROR _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
432 WERROR status = WERR_BADFILE;
434 const char *value_ascii = "";
437 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
438 REGISTRY_VALUE *val = NULL;
442 DEBUG(5,("_reg_info: Enter\n"));
447 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
449 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
451 DEBUG(5,("reg_info: looking up value: [%s]\n", name));
453 ZERO_STRUCTP( ®vals );
455 regval_ctr_init( ®vals );
457 /* couple of hard coded registry values */
459 if ( strequal(name, "RefusePasswordChange") ) {
462 if ( (val = SMB_MALLOC_P(REGISTRY_VALUE)) == NULL ) {
463 DEBUG(0,("_reg_info: malloc() failed!\n"));
467 if (!account_policy_get(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue))
469 regval_ctr_addvalue(®vals, "RefusePasswordChange",
471 (const char*)&dwValue, sizeof(dwValue));
472 val = dup_registry_value(
473 regval_ctr_specific_value( ®vals, 0 ) );
480 if ( strequal(name, REGSTR_PRODUCTTYPE) ) {
481 /* This makes the server look like a member server to clients */
482 /* which tells clients that we have our own local user and */
483 /* group databases and helps with ACL support. */
485 switch (lp_server_role()) {
486 case ROLE_DOMAIN_PDC:
487 case ROLE_DOMAIN_BDC:
488 value_ascii = REG_PT_LANMANNT;
490 case ROLE_STANDALONE:
491 value_ascii = REG_PT_SERVERNT;
493 case ROLE_DOMAIN_MEMBER:
494 value_ascii = REG_PT_WINNT;
497 value_length = push_ucs2(value, value, value_ascii,
499 STR_TERMINATE|STR_NOALIGN);
500 regval_ctr_addvalue(®vals, REGSTR_PRODUCTTYPE, REG_SZ,
501 value, value_length);
503 val = dup_registry_value( regval_ctr_specific_value( ®vals, 0 ) );
510 /* else fall back to actually looking up the value */
512 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
514 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
515 if ( StrCaseCmp( val->valuename, name ) == 0 ) {
516 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
521 free_registry_value( val );
526 init_reg_r_info(q_u->ptr_buf, r_u, val, status);
528 regval_ctr_destroy( ®vals );
529 free_registry_value( val );
531 DEBUG(5,("_reg_info: Exit\n"));
537 /*****************************************************************************
538 Implementation of REG_QUERY_KEY
539 ****************************************************************************/
541 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
543 WERROR status = WERR_OK;
544 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
546 DEBUG(5,("_reg_query_key: Enter\n"));
551 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) )
552 return WERR_ACCESS_DENIED;
554 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) )
555 return WERR_ACCESS_DENIED;
558 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
560 /* Win9x set this to 0x0 since it does not keep timestamps.
561 Doing the same here for simplicity --jerry */
563 ZERO_STRUCT(r_u->mod_time);
565 DEBUG(5,("_reg_query_key: Exit\n"));
571 /*****************************************************************************
572 Implementation of REG_GETVERSION
573 ****************************************************************************/
575 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
577 WERROR status = WERR_OK;
578 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
580 DEBUG(5,("_reg_getversion: Enter\n"));
585 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
587 DEBUG(5,("_reg_getversion: Exit\n"));
593 /*****************************************************************************
594 Implementation of REG_ENUM_KEY
595 ****************************************************************************/
597 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
599 WERROR status = WERR_OK;
600 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
604 DEBUG(5,("_reg_enum_key: Enter\n"));
609 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
611 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
613 status = WERR_NO_MORE_ITEMS;
617 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
619 /* subkey has the string name now */
621 init_reg_r_enum_key( r_u, subkey );
623 DEBUG(5,("_reg_enum_key: Exit\n"));
630 /*****************************************************************************
631 Implementation of REG_ENUM_VALUE
632 ****************************************************************************/
634 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
636 WERROR status = WERR_OK;
637 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
641 DEBUG(5,("_reg_enum_value: Enter\n"));
646 DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey->name));
648 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
649 status = WERR_NO_MORE_ITEMS;
653 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
655 /* subkey has the string name now */
657 init_reg_r_enum_val( r_u, val );
660 DEBUG(5,("_reg_enum_value: Exit\n"));
663 free_registry_value( val );
669 /*******************************************************************
671 ********************************************************************/
673 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
675 REG_Q_SHUTDOWN_EX q_u_ex;
676 REG_R_SHUTDOWN_EX r_u_ex;
678 /* copy fields (including stealing memory) */
680 q_u_ex.server = q_u->server;
681 q_u_ex.message = q_u->message;
682 q_u_ex.timeout = q_u->timeout;
683 q_u_ex.force = q_u->force;
684 q_u_ex.reboot = q_u->reboot;
685 q_u_ex.reason = 0x0; /* don't care for now */
687 /* thunk down to _reg_shutdown_ex() (just returns a status) */
689 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
692 /*******************************************************************
694 ********************************************************************/
696 #define SHUTDOWN_R_STRING "-r"
697 #define SHUTDOWN_F_STRING "-f"
700 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
702 pstring shutdown_script;
713 pstrcpy(shutdown_script, lp_shutdown_script());
715 if ( !*shutdown_script )
716 return WERR_ACCESS_DENIED;
718 /* pull the message string and perform necessary sanity checks on it */
720 pstrcpy( message, "" );
721 if ( q_u->message ) {
722 UNISTR2 *msg_string = q_u->message->string;
724 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
726 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
728 fstr_sprintf(timeout, "%d", q_u->timeout);
729 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
730 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
731 fstr_sprintf( reason, "%d", q_u->reason );
733 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
734 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
735 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
736 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
737 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
739 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
741 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
742 Take the error return from the script and provide it as the Windows return code. */
744 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
749 ret = smbrun( shutdown_script, NULL );
754 /********** END SeRemoteShutdownPrivilege BLOCK **********/
756 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
757 shutdown_script, ret));
760 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
766 /*******************************************************************
768 ********************************************************************/
770 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
772 pstring abort_shutdown_script;
776 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
778 if ( !*abort_shutdown_script )
779 return WERR_ACCESS_DENIED;
781 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
783 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
788 ret = smbrun( abort_shutdown_script, NULL );
793 /********** END SeRemoteShutdownPrivilege BLOCK **********/
795 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
796 abort_shutdown_script, ret));
799 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
802 /*******************************************************************
803 ********************************************************************/
805 static int validate_reg_filename( pstring fname )
808 int num_services = lp_numservices();
813 /* convert to a unix path, stripping the C:\ along the way */
815 if ( !(p = valid_share_pathname( fname ) ))
818 /* has to exist within a valid file share */
820 for ( snum=0; snum<num_services; snum++ ) {
822 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
825 pstrcpy( share_path, lp_pathname(snum) );
827 /* make sure we have a path (e.g. [homes] ) */
829 if ( strlen( share_path ) == 0 )
832 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
836 /* p and fname are overlapping memory so copy out and back in again */
838 pstrcpy( unix_fname, p );
839 pstrcpy( fname, unix_fname );
841 return (snum < num_services) ? snum : -1;
844 /*******************************************************************
845 Note: topkeypaty is the *full* path that this *key will be
846 loaded into (including the name of the key)
847 ********************************************************************/
849 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
853 REGISTRY_KEY registry_key;
855 REGSUBKEY_CTR subkeys;
858 WERROR result = WERR_OK;
860 /* initialize the REGISTRY_KEY structure */
862 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
863 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
867 pstrcpy( registry_key.name, topkeypath );
869 /* now start parsing the values and subkeys */
871 ZERO_STRUCT( values );
872 ZERO_STRUCT( subkeys );
874 regsubkey_ctr_init( &subkeys );
875 regval_ctr_init( &values );
877 /* copy values into the REGVAL_CTR */
879 for ( i=0; i<key->num_values; i++ ) {
880 regval_ctr_addvalue( &values, key->values[i].valuename, key->values[i].type,
881 key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
884 /* copy subkeys into the REGSUBKEY_CTR */
886 key->subkey_index = 0;
887 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
888 regsubkey_ctr_addkey( &subkeys, subkey->keyname );
891 /* write this key and values out */
893 if ( !store_reg_values( ®istry_key, &values )
894 || !store_reg_keys( ®istry_key, &subkeys ) )
896 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
897 result = WERR_REG_IO_FAILURE;
900 regval_ctr_destroy( &values );
901 regsubkey_ctr_destroy( &subkeys );
903 if ( !W_ERROR_IS_OK(result) )
906 /* now continue to load each subkey registry tree */
908 key->subkey_index = 0;
909 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
910 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
911 result = reg_load_tree( regfile, path, subkey );
912 if ( !W_ERROR_IS_OK(result) )
919 /*******************************************************************
920 ********************************************************************/
922 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
925 REGF_NK_REC *rootkey;
928 /* open the registry file....fail if the file already exists */
930 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
931 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
932 fname, strerror(errno) ));
933 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
936 /* get the rootkey from the regf file and then load the tree
937 via recursive calls */
939 if ( !(rootkey = regfio_rootkey( regfile )) )
940 return WERR_REG_FILE_INVALID;
942 result = reg_load_tree( regfile, krecord->name, rootkey );
946 regfio_close( regfile );
951 /*******************************************************************
952 ********************************************************************/
954 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
956 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
960 DEBUG(5,("_reg_restore_key: Enter\n"));
965 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
967 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
969 if ( (snum = validate_reg_filename( filename )) == -1 )
970 return WERR_OBJECT_PATH_INVALID;
972 /* user must posses SeRestorePrivilege for this this proceed */
974 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
975 return WERR_ACCESS_DENIED;
977 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
979 return restore_registry_key( regkey, filename );
982 /********************************************************************
983 ********************************************************************/
985 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
986 REGF_NK_REC *parent, SEC_DESC *sec_desc )
990 REGSUBKEY_CTR subkeys;
993 char *keyname, *parentpath;
996 REGISTRY_KEY registry_key;
997 WERROR result = WERR_OK;
1000 return WERR_GENERAL_FAILURE;
1003 return WERR_OBJECT_PATH_INVALID;
1005 /* split up the registry key path */
1007 pstrcpy( key_tmp, keypath );
1008 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
1009 return WERR_OBJECT_PATH_INVALID;
1012 keyname = parentpath;
1014 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
1016 ZERO_STRUCT( registry_key );
1017 pstrcpy( registry_key.name, keypath );
1018 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
1019 return WERR_BADFILE;
1022 /* lookup the values and subkeys */
1024 ZERO_STRUCT( values );
1025 ZERO_STRUCT( subkeys );
1027 regsubkey_ctr_init( &subkeys );
1028 regval_ctr_init( &values );
1030 fetch_reg_keys( ®istry_key, &subkeys );
1031 fetch_reg_values( ®istry_key, &values );
1033 /* write out this key */
1035 if ( !(key = regfio_write_key( regfile, keyname, &values, &subkeys, sec_desc, parent )) ) {
1036 result = WERR_CAN_NOT_COMPLETE;
1040 /* write each one of the subkeys out */
1042 num_subkeys = regsubkey_ctr_numkeys( &subkeys );
1043 for ( i=0; i<num_subkeys; i++ ) {
1044 subkeyname = regsubkey_ctr_specific_key( &subkeys, i );
1045 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1046 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1047 if ( !W_ERROR_IS_OK(result) )
1051 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1054 regval_ctr_destroy( &values );
1055 regsubkey_ctr_destroy( &subkeys );
1060 /*******************************************************************
1061 ********************************************************************/
1063 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1065 DOM_SID adm_sid, owner_sid;
1066 SEC_ACE ace[2]; /* at most 2 entries */
1068 SEC_ACL *psa = NULL;
1071 /* set the owner to BUILTIN\Administrator */
1073 sid_copy(&owner_sid, &global_sid_Builtin);
1074 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1077 /* basic access for Everyone */
1079 init_sec_access(&mask, reg_map.generic_execute | reg_map.generic_read );
1080 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1082 /* add Full Access 'BUILTIN\Administrators' */
1084 init_sec_access(&mask, reg_map.generic_all);
1085 sid_copy(&adm_sid, &global_sid_Builtin);
1086 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1087 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1089 /* create the security descriptor */
1091 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1094 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1100 /*******************************************************************
1101 ********************************************************************/
1103 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1107 SEC_DESC *sd = NULL;
1109 /* open the registry file....fail if the file already exists */
1111 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1112 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1113 fname, strerror(errno) ));
1114 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1117 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1118 regfio_close( regfile );
1122 /* write the registry tree to the file */
1124 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1128 regfio_close( regfile );
1133 /*******************************************************************
1134 ********************************************************************/
1136 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1138 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1142 DEBUG(5,("_reg_save_key: Enter\n"));
1147 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1149 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1151 if ( (snum = validate_reg_filename( filename )) == -1 )
1152 return WERR_OBJECT_PATH_INVALID;
1154 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1156 return backup_registry_key( regkey, filename );
1161 /*******************************************************************
1162 ********************************************************************/
1164 WERROR _reg_create_key(pipes_struct *p, REG_Q_CREATE_KEY *q_u, REG_R_CREATE_KEY *r_u)
1166 return WERR_ACCESS_DENIED;
1170 /*******************************************************************
1171 ********************************************************************/
1173 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1175 return WERR_ACCESS_DENIED;