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 regsubkey_ctr_init( &subkeys );
184 if ( fetch_reg_keys( regkey, &subkeys ) == -1 ) {
185 result = WERR_BADFILE;
189 if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) ) {
190 result = WERR_BADFILE;
194 /* save the access mask */
196 regkey->access_granted = access_granted;
201 regsubkey_ctr_destroy( &subkeys );
203 if ( ! NT_STATUS_IS_OK(result) )
206 DEBUG(7,("open_registry_key: exit\n"));
211 /*******************************************************************
212 Function for open a new registry handle and creating a handle
213 Note that P should be valid & hnd should already have space
214 *******************************************************************/
216 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
218 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
221 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
225 close_policy_hnd(p, hnd);
230 /********************************************************************
231 retrieve information about the subkeys
232 *******************************************************************/
234 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
238 REGSUBKEY_CTR subkeys;
244 regsubkey_ctr_init( &subkeys );
246 if ( fetch_reg_keys( key, &subkeys ) == -1 )
249 /* find the longest string */
252 num_subkeys = regsubkey_ctr_numkeys( &subkeys );
254 for ( i=0; i<num_subkeys; i++ ) {
255 len = strlen( regsubkey_ctr_specific_key(&subkeys, i) );
256 max_len = MAX(max_len, len);
259 *maxnum = num_subkeys;
262 regsubkey_ctr_destroy( &subkeys );
267 /********************************************************************
268 retrieve information about the values. We don't store values
269 here. The registry tdb is intended to be a frontend to oether
270 Samba tdb's (such as ntdrivers.tdb).
271 *******************************************************************/
273 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
274 uint32 *maxlen, uint32 *maxsize )
278 uint32 sizemax, lenmax;
284 regval_ctr_init( &values );
286 if ( fetch_reg_values( key, &values ) == -1 )
289 lenmax = sizemax = 0;
290 num_values = regval_ctr_numvals( &values );
292 val = regval_ctr_specific_value( &values, 0 );
294 for ( i=0; i<num_values && val; i++ )
296 lenmax = MAX(lenmax, strlen(val->valuename)+1 );
297 sizemax = MAX(sizemax, val->size );
299 val = regval_ctr_specific_value( &values, i );
302 *maxnum = num_values;
306 regval_ctr_destroy( &values );
312 /********************************************************************
314 ********************************************************************/
316 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
318 /* close the policy handle */
320 if (!close_registry_key(p, &q_u->pol))
326 /*******************************************************************
327 ********************************************************************/
329 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
332 uint32 access_granted = 0;
335 /* perform access checks */
336 /* top level keys are done here without passing through the REGISTRY_HOOK api */
338 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
341 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
342 if ( !NT_STATUS_IS_OK(status) )
343 return ntstatus_to_werror( status );
345 return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, access_granted );
348 /*******************************************************************
349 ********************************************************************/
351 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
354 uint32 access_granted = 0;
357 /* perform access checks */
358 /* top level keys are done here without passing through the REGISTRY_HOOK api */
360 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
363 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
364 if ( !NT_STATUS_IS_OK(status) )
365 return ntstatus_to_werror( status );
367 return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, access_granted );
370 /*******************************************************************
371 ********************************************************************/
373 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
376 uint32 access_granted = 0;
379 /* perform access checks */
380 /* top level keys are done here without passing through the REGISTRY_HOOK api */
382 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
385 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
386 if ( !NT_STATUS_IS_OK(status) )
387 return ntstatus_to_werror( status );
389 return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, access_granted );
392 /*******************************************************************
394 ********************************************************************/
396 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
399 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
400 REGISTRY_KEY *newkey;
401 uint32 access_granted;
404 DEBUG(5,("reg_open_entry: Enter\n"));
409 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
411 /* check granted access first; what is the correct mask here? */
413 if ( !(parent->access_granted & (SEC_RIGHTS_ENUM_SUBKEYS|SEC_RIGHTS_CREATE_SUBKEY)) )
414 return WERR_ACCESS_DENIED;
416 /* open the key first to get the appropriate REGISTRY_HOOK
417 and then check the premissions */
419 if ( !W_ERROR_IS_OK(result = open_registry_key( p, &r_u->handle, parent, name, 0 )) )
422 newkey = find_regkey_index_by_hnd(p, &r_u->handle);
424 /* finally allow the backend to check the access for the requested key */
426 if ( !regkey_access_check( newkey, q_u->access, &access_granted, p->pipe_user.nt_user_token ) ) {
427 close_registry_key( p, &r_u->handle );
428 return WERR_ACCESS_DENIED;
431 /* if successful, save the granted access mask */
433 newkey->access_granted = access_granted;
438 /*******************************************************************
440 ********************************************************************/
442 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
444 WERROR status = WERR_BADFILE;
446 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
447 REGISTRY_VALUE *val = NULL;
451 DEBUG(5,("_reg_info: Enter\n"));
456 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
458 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
460 DEBUG(5,("reg_info: looking up value: [%s]\n", name));
462 regval_ctr_init( ®vals );
464 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
466 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
467 if ( strequal( val->valuename, name ) ) {
468 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
473 free_registry_value( val );
476 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
478 regval_ctr_destroy( ®vals );
479 free_registry_value( val );
481 DEBUG(5,("_reg_info: Exit\n"));
487 /*****************************************************************************
488 Implementation of REG_QUERY_KEY
489 ****************************************************************************/
491 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
493 WERROR status = WERR_OK;
494 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
496 DEBUG(5,("_reg_query_key: Enter\n"));
501 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) )
502 return WERR_ACCESS_DENIED;
504 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) )
505 return WERR_ACCESS_DENIED;
508 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
510 /* Win9x set this to 0x0 since it does not keep timestamps.
511 Doing the same here for simplicity --jerry */
513 ZERO_STRUCT(r_u->mod_time);
515 DEBUG(5,("_reg_query_key: Exit\n"));
521 /*****************************************************************************
522 Implementation of REG_GETVERSION
523 ****************************************************************************/
525 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
527 WERROR status = WERR_OK;
528 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
530 DEBUG(5,("_reg_getversion: Enter\n"));
535 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
537 DEBUG(5,("_reg_getversion: Exit\n"));
543 /*****************************************************************************
544 Implementation of REG_ENUM_KEY
545 ****************************************************************************/
547 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
549 WERROR status = WERR_OK;
550 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
554 DEBUG(5,("_reg_enum_key: Enter\n"));
559 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
561 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
563 status = WERR_NO_MORE_ITEMS;
567 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
569 /* subkey has the string name now */
571 init_reg_r_enum_key( r_u, subkey );
573 DEBUG(5,("_reg_enum_key: Exit\n"));
580 /*****************************************************************************
581 Implementation of REG_ENUM_VALUE
582 ****************************************************************************/
584 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
586 WERROR status = WERR_OK;
587 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
591 DEBUG(5,("_reg_enum_value: Enter\n"));
596 DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey->name));
598 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
599 status = WERR_NO_MORE_ITEMS;
603 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
605 /* subkey has the string name now */
607 init_reg_r_enum_val( r_u, val );
610 DEBUG(5,("_reg_enum_value: Exit\n"));
613 free_registry_value( val );
619 /*******************************************************************
621 ********************************************************************/
623 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
625 REG_Q_SHUTDOWN_EX q_u_ex;
626 REG_R_SHUTDOWN_EX r_u_ex;
628 /* copy fields (including stealing memory) */
630 q_u_ex.server = q_u->server;
631 q_u_ex.message = q_u->message;
632 q_u_ex.timeout = q_u->timeout;
633 q_u_ex.force = q_u->force;
634 q_u_ex.reboot = q_u->reboot;
635 q_u_ex.reason = 0x0; /* don't care for now */
637 /* thunk down to _reg_shutdown_ex() (just returns a status) */
639 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
642 /*******************************************************************
644 ********************************************************************/
646 #define SHUTDOWN_R_STRING "-r"
647 #define SHUTDOWN_F_STRING "-f"
650 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
652 pstring shutdown_script;
663 pstrcpy(shutdown_script, lp_shutdown_script());
665 if ( !*shutdown_script )
666 return WERR_ACCESS_DENIED;
668 /* pull the message string and perform necessary sanity checks on it */
670 pstrcpy( message, "" );
671 if ( q_u->message ) {
672 UNISTR2 *msg_string = q_u->message->string;
674 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
676 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
678 fstr_sprintf(timeout, "%d", q_u->timeout);
679 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
680 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
681 fstr_sprintf( reason, "%d", q_u->reason );
683 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
684 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
685 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
686 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
687 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
689 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
691 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
692 Take the error return from the script and provide it as the Windows return code. */
694 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
699 ret = smbrun( shutdown_script, NULL );
704 /********** END SeRemoteShutdownPrivilege BLOCK **********/
706 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
707 shutdown_script, ret));
710 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
716 /*******************************************************************
718 ********************************************************************/
720 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
722 pstring abort_shutdown_script;
726 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
728 if ( !*abort_shutdown_script )
729 return WERR_ACCESS_DENIED;
731 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
733 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
738 ret = smbrun( abort_shutdown_script, NULL );
743 /********** END SeRemoteShutdownPrivilege BLOCK **********/
745 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
746 abort_shutdown_script, ret));
749 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
752 /*******************************************************************
753 ********************************************************************/
755 static int validate_reg_filename( pstring fname )
758 int num_services = lp_numservices();
763 /* convert to a unix path, stripping the C:\ along the way */
765 if ( !(p = valid_share_pathname( fname ) ))
768 /* has to exist within a valid file share */
770 for ( snum=0; snum<num_services; snum++ ) {
772 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
775 pstrcpy( share_path, lp_pathname(snum) );
777 /* make sure we have a path (e.g. [homes] ) */
779 if ( strlen( share_path ) == 0 )
782 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
786 /* p and fname are overlapping memory so copy out and back in again */
788 pstrcpy( unix_fname, p );
789 pstrcpy( fname, unix_fname );
791 return (snum < num_services) ? snum : -1;
794 /*******************************************************************
795 Note: topkeypat is the *full* path that this *key will be
796 loaded into (including the name of the key)
797 ********************************************************************/
799 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
803 REGISTRY_KEY registry_key;
805 REGSUBKEY_CTR subkeys;
808 WERROR result = WERR_OK;
810 /* initialize the REGISTRY_KEY structure */
812 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
813 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
817 pstrcpy( registry_key.name, topkeypath );
819 /* now start parsing the values and subkeys */
821 regsubkey_ctr_init( &subkeys );
822 regval_ctr_init( &values );
824 /* copy values into the REGVAL_CTR */
826 for ( i=0; i<key->num_values; i++ ) {
827 regval_ctr_addvalue( &values, key->values[i].valuename, key->values[i].type,
828 key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
831 /* copy subkeys into the REGSUBKEY_CTR */
833 key->subkey_index = 0;
834 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
835 regsubkey_ctr_addkey( &subkeys, subkey->keyname );
838 /* write this key and values out */
840 if ( !store_reg_values( ®istry_key, &values )
841 || !store_reg_keys( ®istry_key, &subkeys ) )
843 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
844 result = WERR_REG_IO_FAILURE;
847 regval_ctr_destroy( &values );
848 regsubkey_ctr_destroy( &subkeys );
850 if ( !W_ERROR_IS_OK(result) )
853 /* now continue to load each subkey registry tree */
855 key->subkey_index = 0;
856 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
857 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
858 result = reg_load_tree( regfile, path, subkey );
859 if ( !W_ERROR_IS_OK(result) )
866 /*******************************************************************
867 ********************************************************************/
869 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
872 REGF_NK_REC *rootkey;
875 /* open the registry file....fail if the file already exists */
877 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
878 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
879 fname, strerror(errno) ));
880 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
883 /* get the rootkey from the regf file and then load the tree
884 via recursive calls */
886 if ( !(rootkey = regfio_rootkey( regfile )) )
887 return WERR_REG_FILE_INVALID;
889 result = reg_load_tree( regfile, krecord->name, rootkey );
893 regfio_close( regfile );
898 /*******************************************************************
899 ********************************************************************/
901 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
903 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
907 DEBUG(5,("_reg_restore_key: Enter\n"));
912 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
914 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
916 if ( (snum = validate_reg_filename( filename )) == -1 )
917 return WERR_OBJECT_PATH_INVALID;
919 /* user must posses SeRestorePrivilege for this this proceed */
921 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
922 return WERR_ACCESS_DENIED;
924 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
926 return restore_registry_key( regkey, filename );
929 /********************************************************************
930 ********************************************************************/
932 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
933 REGF_NK_REC *parent, SEC_DESC *sec_desc )
937 REGSUBKEY_CTR subkeys;
940 char *keyname, *parentpath;
943 REGISTRY_KEY registry_key;
944 WERROR result = WERR_OK;
947 return WERR_GENERAL_FAILURE;
950 return WERR_OBJECT_PATH_INVALID;
952 /* split up the registry key path */
954 pstrcpy( key_tmp, keypath );
955 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
956 return WERR_OBJECT_PATH_INVALID;
959 keyname = parentpath;
961 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
963 ZERO_STRUCT( registry_key );
964 pstrcpy( registry_key.name, keypath );
965 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
969 /* lookup the values and subkeys */
971 regsubkey_ctr_init( &subkeys );
972 regval_ctr_init( &values );
974 fetch_reg_keys( ®istry_key, &subkeys );
975 fetch_reg_values( ®istry_key, &values );
977 /* write out this key */
979 if ( !(key = regfio_write_key( regfile, keyname, &values, &subkeys, sec_desc, parent )) ) {
980 result = WERR_CAN_NOT_COMPLETE;
984 /* write each one of the subkeys out */
986 num_subkeys = regsubkey_ctr_numkeys( &subkeys );
987 for ( i=0; i<num_subkeys; i++ ) {
988 subkeyname = regsubkey_ctr_specific_key( &subkeys, i );
989 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
990 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
991 if ( !W_ERROR_IS_OK(result) )
995 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
998 regval_ctr_destroy( &values );
999 regsubkey_ctr_destroy( &subkeys );
1004 /*******************************************************************
1005 ********************************************************************/
1007 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1009 DOM_SID adm_sid, owner_sid;
1010 SEC_ACE ace[2]; /* at most 2 entries */
1012 SEC_ACL *psa = NULL;
1015 /* set the owner to BUILTIN\Administrator */
1017 sid_copy(&owner_sid, &global_sid_Builtin);
1018 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1021 /* basic access for Everyone */
1023 init_sec_access(&mask, reg_map.generic_execute | reg_map.generic_read );
1024 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1026 /* add Full Access 'BUILTIN\Administrators' */
1028 init_sec_access(&mask, reg_map.generic_all);
1029 sid_copy(&adm_sid, &global_sid_Builtin);
1030 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1031 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1033 /* create the security descriptor */
1035 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1038 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1044 /*******************************************************************
1045 ********************************************************************/
1047 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1051 SEC_DESC *sd = NULL;
1053 /* open the registry file....fail if the file already exists */
1055 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1056 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1057 fname, strerror(errno) ));
1058 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1061 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1062 regfio_close( regfile );
1066 /* write the registry tree to the file */
1068 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1072 regfio_close( regfile );
1077 /*******************************************************************
1078 ********************************************************************/
1080 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1082 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1086 DEBUG(5,("_reg_save_key: Enter\n"));
1091 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1093 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1095 if ( (snum = validate_reg_filename( filename )) == -1 )
1096 return WERR_OBJECT_PATH_INVALID;
1098 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1100 return backup_registry_key( regkey, filename );
1105 /*******************************************************************
1106 ********************************************************************/
1108 WERROR _reg_create_key(pipes_struct *p, REG_Q_CREATE_KEY *q_u, REG_R_CREATE_KEY *r_u)
1110 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1111 REGISTRY_KEY *newparent;
1112 POLICY_HND newparent_handle;
1113 REGSUBKEY_CTR subkeys;
1121 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1123 /* ok. Here's what we do. */
1125 if ( strrchr( name, '\\' ) ) {
1128 uint32 access_granted;
1130 /* (1) check for enumerate rights on the parent handle. CLients can try
1131 create things like 'SOFTWARE\Samba' on the HKLM handle.
1132 (2) open the path to the child parent key if necessary */
1134 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1135 return WERR_ACCESS_DENIED;
1137 pstrcpy( newkeyname, name );
1138 ptr = strrchr( newkeyname, '\\' );
1141 result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
1142 if ( !W_ERROR_IS_OK(result) )
1145 newparent = find_regkey_index_by_hnd(p, &newparent_handle);
1146 SMB_ASSERT( newparent != NULL );
1148 if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
1149 result = WERR_ACCESS_DENIED;
1153 newparent->access_granted = access_granted;
1155 /* copy the new key name (just the lower most keyname) */
1157 pstrcpy( name, ptr+1 );
1160 /* use the existing open key information */
1162 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1165 /* (3) check for create subkey rights on the correct parent */
1167 if ( !(newparent->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1168 result = WERR_ACCESS_DENIED;
1172 regsubkey_ctr_init( &subkeys );
1174 /* (4) lookup the current keys and add the new one */
1176 fetch_reg_keys( newparent, &subkeys );
1177 regsubkey_ctr_addkey( &subkeys, name );
1179 /* now write to the registry backend */
1181 write_result = store_reg_keys( newparent, &subkeys );
1183 regsubkey_ctr_destroy( &subkeys );
1185 if ( !write_result )
1186 return WERR_REG_IO_FAILURE;
1188 /* (5) open the new key and return the handle. Note that it is probably
1189 not correct to grant full access on this open handle. We should pass
1190 the new open through the regkey_access_check() like we do for
1191 _reg_open_entry() but this is ok for now. */
1193 result = open_registry_key( p, &r_u->handle, newparent, name, REG_KEY_ALL );
1196 /* close any intermediate key handles */
1198 if ( newparent != parent )
1199 close_registry_key( p, &newparent_handle );
1205 /*******************************************************************
1206 ********************************************************************/
1208 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1210 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1218 /* access checks first */
1220 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1221 return WERR_ACCESS_DENIED;
1223 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1226 regval_ctr_init( &values );
1228 /* lookup the current values and add the new one */
1230 fetch_reg_values( key, &values );
1232 regval_ctr_addvalue( &values, valuename, q_u->type, q_u->value.buffer, q_u->value.buf_len );
1234 /* now write to the registry backend */
1236 write_result = store_reg_values( key, &values );
1238 regval_ctr_destroy( &values );
1240 if ( !write_result )
1241 return WERR_REG_IO_FAILURE;
1246 /*******************************************************************
1247 ********************************************************************/
1249 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1251 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1252 REGISTRY_KEY *newparent;
1253 POLICY_HND newparent_handle;
1254 REGSUBKEY_CTR subkeys;
1262 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1264 /* ok. Here's what we do. */
1266 if ( strrchr( name, '\\' ) ) {
1269 uint32 access_granted;
1271 /* (1) check for enumerate rights on the parent handle. CLients can try
1272 create things like 'SOFTWARE\Samba' on the HKLM handle.
1273 (2) open the path to the child parent key if necessary */
1275 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1276 return WERR_ACCESS_DENIED;
1278 pstrcpy( newkeyname, name );
1279 ptr = strrchr( newkeyname, '\\' );
1282 result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
1283 if ( !W_ERROR_IS_OK(result) )
1286 newparent = find_regkey_index_by_hnd(p, &newparent_handle);
1287 SMB_ASSERT( newparent != NULL );
1289 if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
1290 result = WERR_ACCESS_DENIED;
1294 newparent->access_granted = access_granted;
1296 /* copy the new key name (just the lower most keyname) */
1298 pstrcpy( name, ptr+1 );
1301 /* use the existing open key information */
1303 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1306 /* (3) check for create subkey rights on the correct parent */
1308 if ( !(newparent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1309 result = WERR_ACCESS_DENIED;
1313 regsubkey_ctr_init( &subkeys );
1315 /* lookup the current keys and delete the new one */
1317 fetch_reg_keys( newparent, &subkeys );
1319 regsubkey_ctr_delkey( &subkeys, name );
1321 /* now write to the registry backend */
1323 write_result = store_reg_keys( newparent, &subkeys );
1325 regsubkey_ctr_destroy( &subkeys );
1327 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1330 /* close any intermediate key handles */
1332 if ( newparent != parent )
1333 close_registry_key( p, &newparent_handle );
1339 /*******************************************************************
1340 ********************************************************************/
1342 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1344 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1352 /* access checks first */
1354 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1355 return WERR_ACCESS_DENIED;
1357 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1359 regval_ctr_init( &values );
1361 /* lookup the current values and add the new one */
1363 fetch_reg_values( key, &values );
1365 regval_ctr_delvalue( &values, valuename );
1367 /* now write to the registry backend */
1369 write_result = store_reg_values( key, &values );
1371 regval_ctr_destroy( &values );
1373 if ( !write_result )
1374 return WERR_REG_IO_FAILURE;
1379 /*******************************************************************
1380 ********************************************************************/
1382 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1384 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1389 /* access checks first */
1391 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1392 return WERR_ACCESS_DENIED;
1394 return WERR_ACCESS_DENIED;
1397 /*******************************************************************
1398 ********************************************************************/
1400 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1402 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1407 /* access checks first */
1409 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1410 return WERR_ACCESS_DENIED;
1412 return WERR_ACCESS_DENIED;