r8027: driver information is now back via winreg
[Samba/gbeck.git] / source / rpc_server / srv_reg_nt.c
blobdb199634c502eee88b54e42aa2a691718be8262a
1 /*
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. */
27 #include "includes.h"
28 #include "regfio.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
34 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
37 static struct generic_mapping reg_generic_map = { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
39 /********************************************************************
40 ********************************************************************/
42 NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
43 uint32 access_desired, uint32 *access_granted )
45 NTSTATUS result;
47 se_map_generic( &access_desired, &reg_generic_map );
48 se_access_check( sec_desc, token, access_desired, access_granted, &result );
50 return result;
53 /********************************************************************
54 ********************************************************************/
56 SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
58 SEC_ACE ace[2];
59 SEC_ACCESS mask;
60 size_t i = 0;
61 SEC_DESC *sd;
62 SEC_ACL *acl;
63 uint32 sd_size;
65 /* basic access for Everyone */
67 init_sec_access(&mask, REG_KEY_READ );
68 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
70 /* Full Access 'BUILTIN\Administrators' */
72 init_sec_access(&mask, REG_KEY_ALL );
73 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
76 /* create the security descriptor */
78 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
79 return NULL;
81 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
82 return NULL;
84 return sd;
87 /******************************************************************
88 free() function for REGISTRY_KEY
89 *****************************************************************/
91 static void free_regkey_info(void *ptr)
93 REGISTRY_KEY *info = (REGISTRY_KEY*)ptr;
95 SAFE_FREE(info);
98 /******************************************************************
99 Find a registry key handle and return a REGISTRY_KEY
100 *****************************************************************/
102 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
104 REGISTRY_KEY *regkey = NULL;
106 if(!find_policy_by_hnd(p,hnd,(void **)&regkey)) {
107 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
108 return NULL;
111 return regkey;
115 /*******************************************************************
116 Function for open a new registry handle and creating a handle
117 Note that P should be valid & hnd should already have space
119 When we open a key, we store the full path to the key as
120 HK[LM|U]\<key>\<key>\...
121 *******************************************************************/
123 static WERROR open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent,
124 const char *subkeyname, uint32 access_granted )
126 REGISTRY_KEY *regkey = NULL;
127 WERROR result = WERR_OK;
128 REGSUBKEY_CTR subkeys;
129 pstring subkeyname2;
130 int subkey_len;
132 DEBUG(7,("open_registry_key: name = [%s][%s]\n",
133 parent ? parent->name : "NULL", subkeyname));
135 /* strip any trailing '\'s */
136 pstrcpy( subkeyname2, subkeyname );
137 subkey_len = strlen ( subkeyname2 );
138 if ( subkey_len && subkeyname2[subkey_len-1] == '\\' )
139 subkeyname2[subkey_len-1] = '\0';
141 if ((regkey=SMB_MALLOC_P(REGISTRY_KEY)) == NULL)
142 return WERR_NOMEM;
144 ZERO_STRUCTP( regkey );
147 * very crazy, but regedit.exe on Win2k will attempt to call
148 * REG_OPEN_ENTRY with a keyname of "". We should return a new
149 * (second) handle here on the key->name. regedt32.exe does
150 * not do this stupidity. --jerry
153 if ( !subkey_len ) {
154 pstrcpy( regkey->name, parent->name );
156 else {
157 pstrcpy( regkey->name, "" );
158 if ( parent ) {
159 pstrcat( regkey->name, parent->name );
160 pstrcat( regkey->name, "\\" );
162 pstrcat( regkey->name, subkeyname2 );
165 /* Look up the table of registry I/O operations */
167 if ( !(regkey->hook = reghook_cache_find( regkey->name )) ) {
168 DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
169 regkey->name ));
170 return WERR_BADFILE;
173 /* check if the path really exists; failed is indicated by -1 */
174 /* if the subkey count failed, bail out */
176 regsubkey_ctr_init( &subkeys );
178 if ( fetch_reg_keys( regkey, &subkeys ) == -1 ) {
179 result = WERR_BADFILE;
180 goto done;
183 if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) ) {
184 result = WERR_BADFILE;
185 goto done;
188 /* save the access mask */
190 regkey->access_granted = access_granted;
192 done:
193 /* clean up */
195 regsubkey_ctr_destroy( &subkeys );
197 if ( ! NT_STATUS_IS_OK(result) )
198 SAFE_FREE( regkey );
200 DEBUG(7,("open_registry_key: exit\n"));
202 return result;
205 /*******************************************************************
206 Function for open a new registry handle and creating a handle
207 Note that P should be valid & hnd should already have space
208 *******************************************************************/
210 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
212 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
214 if ( !regkey ) {
215 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
216 return False;
219 close_policy_hnd(p, hnd);
221 return True;
224 /********************************************************************
225 retrieve information about the subkeys
226 *******************************************************************/
228 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
230 int num_subkeys, i;
231 uint32 max_len;
232 REGSUBKEY_CTR subkeys;
233 uint32 len;
235 if ( !key )
236 return False;
238 regsubkey_ctr_init( &subkeys );
240 if ( fetch_reg_keys( key, &subkeys ) == -1 )
241 return False;
243 /* find the longest string */
245 max_len = 0;
246 num_subkeys = regsubkey_ctr_numkeys( &subkeys );
248 for ( i=0; i<num_subkeys; i++ ) {
249 len = strlen( regsubkey_ctr_specific_key(&subkeys, i) );
250 max_len = MAX(max_len, len);
253 *maxnum = num_subkeys;
254 *maxlen = max_len*2;
256 regsubkey_ctr_destroy( &subkeys );
258 return True;
261 /********************************************************************
262 retrieve information about the values.
263 *******************************************************************/
265 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
266 uint32 *maxlen, uint32 *maxsize )
268 REGVAL_CTR values;
269 REGISTRY_VALUE *val;
270 uint32 sizemax, lenmax;
271 int i, num_values;
273 if ( !key )
274 return False;
276 regval_ctr_init( &values );
278 if ( fetch_reg_values( key, &values ) == -1 )
279 return False;
281 lenmax = sizemax = 0;
282 num_values = regval_ctr_numvals( &values );
284 val = regval_ctr_specific_value( &values, 0 );
286 for ( i=0; i<num_values && val; i++ )
288 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
289 sizemax = MAX(sizemax, val->size );
291 val = regval_ctr_specific_value( &values, i );
294 *maxnum = num_values;
295 *maxlen = lenmax;
296 *maxsize = sizemax;
298 regval_ctr_destroy( &values );
300 return True;
304 /********************************************************************
305 reg_close
306 ********************************************************************/
308 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
310 /* close the policy handle */
312 if (!close_registry_key(p, &q_u->pol))
313 return WERR_BADFID;
315 return WERR_OK;
318 /*******************************************************************
319 ********************************************************************/
321 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
323 SEC_DESC *sec_desc;
324 uint32 access_granted = 0;
325 NTSTATUS status;
327 /* perform access checks */
328 /* top level keys are done here without passing through the REGISTRY_HOOK api */
330 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
331 return WERR_NOMEM;
333 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
334 if ( !NT_STATUS_IS_OK(status) )
335 return ntstatus_to_werror( status );
337 return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, access_granted );
340 /*******************************************************************
341 ********************************************************************/
343 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
345 SEC_DESC *sec_desc;
346 uint32 access_granted = 0;
347 NTSTATUS status;
349 /* perform access checks */
350 /* top level keys are done here without passing through the REGISTRY_HOOK api */
352 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
353 return WERR_NOMEM;
355 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
356 if ( !NT_STATUS_IS_OK(status) )
357 return ntstatus_to_werror( status );
359 return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, access_granted );
362 /*******************************************************************
363 ********************************************************************/
365 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
367 SEC_DESC *sec_desc;
368 uint32 access_granted = 0;
369 NTSTATUS status;
371 /* perform access checks */
372 /* top level keys are done here without passing through the REGISTRY_HOOK api */
374 if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
375 return WERR_NOMEM;
377 status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
378 if ( !NT_STATUS_IS_OK(status) )
379 return ntstatus_to_werror( status );
381 return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, access_granted );
384 /*******************************************************************
385 reg_reply_open_entry
386 ********************************************************************/
388 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
390 fstring name;
391 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
392 REGISTRY_KEY *newkey;
393 uint32 access_granted;
394 WERROR result;
396 DEBUG(5,("reg_open_entry: Enter\n"));
398 if ( !parent )
399 return WERR_BADFID;
401 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
403 /* check granted access first; what is the correct mask here? */
405 if ( !(parent->access_granted & (SEC_RIGHTS_ENUM_SUBKEYS|SEC_RIGHTS_CREATE_SUBKEY)) )
406 return WERR_ACCESS_DENIED;
408 /* open the key first to get the appropriate REGISTRY_HOOK
409 and then check the premissions */
411 if ( !W_ERROR_IS_OK(result = open_registry_key( p, &r_u->handle, parent, name, 0 )) )
412 return result;
414 newkey = find_regkey_index_by_hnd(p, &r_u->handle);
416 /* finally allow the backend to check the access for the requested key */
418 if ( !regkey_access_check( newkey, q_u->access, &access_granted, p->pipe_user.nt_user_token ) ) {
419 close_registry_key( p, &r_u->handle );
420 return WERR_ACCESS_DENIED;
423 /* if successful, save the granted access mask */
425 newkey->access_granted = access_granted;
427 return WERR_OK;
430 /*******************************************************************
431 reg_reply_info
432 ********************************************************************/
434 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
436 WERROR status = WERR_BADFILE;
437 fstring name;
438 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
439 REGISTRY_VALUE *val = NULL;
440 REGVAL_CTR regvals;
441 int i;
443 DEBUG(5,("_reg_info: Enter\n"));
445 if ( !regkey )
446 return WERR_BADFID;
448 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
450 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
452 DEBUG(5,("reg_info: looking up value: [%s]\n", name));
454 regval_ctr_init( &regvals );
456 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
458 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
459 if ( strequal( val->valuename, name ) ) {
460 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
461 status = WERR_OK;
462 break;
465 free_registry_value( val );
468 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
470 regval_ctr_destroy( &regvals );
471 free_registry_value( val );
473 DEBUG(5,("_reg_info: Exit\n"));
475 return status;
479 /*****************************************************************************
480 Implementation of REG_QUERY_KEY
481 ****************************************************************************/
483 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
485 WERROR status = WERR_OK;
486 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
488 DEBUG(5,("_reg_query_key: Enter\n"));
490 if ( !regkey )
491 return WERR_BADFID;
493 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
494 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
495 return WERR_ACCESS_DENIED;
498 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
499 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
500 return WERR_ACCESS_DENIED;
504 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
506 /* Win9x set this to 0x0 since it does not keep timestamps.
507 Doing the same here for simplicity --jerry */
509 ZERO_STRUCT(r_u->mod_time);
511 DEBUG(5,("_reg_query_key: Exit\n"));
513 return status;
517 /*****************************************************************************
518 Implementation of REG_GETVERSION
519 ****************************************************************************/
521 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
523 WERROR status = WERR_OK;
524 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
526 DEBUG(5,("_reg_getversion: Enter\n"));
528 if ( !regkey )
529 return WERR_BADFID;
531 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
533 DEBUG(5,("_reg_getversion: Exit\n"));
535 return status;
539 /*****************************************************************************
540 Implementation of REG_ENUM_KEY
541 ****************************************************************************/
543 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
545 WERROR status = WERR_OK;
546 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
547 char *subkey = NULL;
550 DEBUG(5,("_reg_enum_key: Enter\n"));
552 if ( !regkey )
553 return WERR_BADFID;
555 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
557 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
559 status = WERR_NO_MORE_ITEMS;
560 goto done;
563 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
565 /* subkey has the string name now */
567 init_reg_r_enum_key( r_u, subkey );
569 DEBUG(5,("_reg_enum_key: Exit\n"));
571 done:
572 SAFE_FREE( subkey );
573 return status;
576 /*****************************************************************************
577 Implementation of REG_ENUM_VALUE
578 ****************************************************************************/
580 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
582 WERROR status = WERR_OK;
583 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
584 REGISTRY_VALUE *val;
587 DEBUG(5,("_reg_enum_value: Enter\n"));
589 if ( !regkey )
590 return WERR_BADFID;
592 DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey->name));
594 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
595 status = WERR_NO_MORE_ITEMS;
596 goto done;
599 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
601 /* subkey has the string name now */
603 init_reg_r_enum_val( r_u, val );
606 DEBUG(5,("_reg_enum_value: Exit\n"));
608 done:
609 free_registry_value( val );
611 return status;
615 /*******************************************************************
616 reg_shutdwon
617 ********************************************************************/
619 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
621 REG_Q_SHUTDOWN_EX q_u_ex;
622 REG_R_SHUTDOWN_EX r_u_ex;
624 /* copy fields (including stealing memory) */
626 q_u_ex.server = q_u->server;
627 q_u_ex.message = q_u->message;
628 q_u_ex.timeout = q_u->timeout;
629 q_u_ex.force = q_u->force;
630 q_u_ex.reboot = q_u->reboot;
631 q_u_ex.reason = 0x0; /* don't care for now */
633 /* thunk down to _reg_shutdown_ex() (just returns a status) */
635 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
638 /*******************************************************************
639 reg_shutdown_ex
640 ********************************************************************/
642 #define SHUTDOWN_R_STRING "-r"
643 #define SHUTDOWN_F_STRING "-f"
646 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
648 pstring shutdown_script;
649 pstring message;
650 pstring chkmsg;
651 fstring timeout;
652 fstring reason;
653 fstring r;
654 fstring f;
655 int ret;
656 BOOL can_shutdown;
659 pstrcpy(shutdown_script, lp_shutdown_script());
661 if ( !*shutdown_script )
662 return WERR_ACCESS_DENIED;
664 /* pull the message string and perform necessary sanity checks on it */
666 pstrcpy( message, "" );
667 if ( q_u->message ) {
668 UNISTR2 *msg_string = q_u->message->string;
670 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
672 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
674 fstr_sprintf(timeout, "%d", q_u->timeout);
675 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
676 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
677 fstr_sprintf( reason, "%d", q_u->reason );
679 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
680 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
681 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
682 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
683 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
685 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
687 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
688 Take the error return from the script and provide it as the Windows return code. */
690 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
692 if ( can_shutdown )
693 become_root();
695 ret = smbrun( shutdown_script, NULL );
697 if ( can_shutdown )
698 unbecome_root();
700 /********** END SeRemoteShutdownPrivilege BLOCK **********/
702 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
703 shutdown_script, ret));
706 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
712 /*******************************************************************
713 reg_abort_shutdwon
714 ********************************************************************/
716 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
718 pstring abort_shutdown_script;
719 int ret;
720 BOOL can_shutdown;
722 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
724 if ( !*abort_shutdown_script )
725 return WERR_ACCESS_DENIED;
727 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
729 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
731 if ( can_shutdown )
732 become_root();
734 ret = smbrun( abort_shutdown_script, NULL );
736 if ( can_shutdown )
737 unbecome_root();
739 /********** END SeRemoteShutdownPrivilege BLOCK **********/
741 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
742 abort_shutdown_script, ret));
745 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
748 /*******************************************************************
749 ********************************************************************/
751 static int validate_reg_filename( pstring fname )
753 char *p;
754 int num_services = lp_numservices();
755 int snum;
756 pstring share_path;
757 pstring unix_fname;
759 /* convert to a unix path, stripping the C:\ along the way */
761 if ( !(p = valid_share_pathname( fname ) ))
762 return -1;
764 /* has to exist within a valid file share */
766 for ( snum=0; snum<num_services; snum++ ) {
768 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
769 continue;
771 pstrcpy( share_path, lp_pathname(snum) );
773 /* make sure we have a path (e.g. [homes] ) */
775 if ( strlen( share_path ) == 0 )
776 continue;
778 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
779 break;
782 /* p and fname are overlapping memory so copy out and back in again */
784 pstrcpy( unix_fname, p );
785 pstrcpy( fname, unix_fname );
787 return (snum < num_services) ? snum : -1;
790 /*******************************************************************
791 Note: topkeypat is the *full* path that this *key will be
792 loaded into (including the name of the key)
793 ********************************************************************/
795 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
796 REGF_NK_REC *key )
798 REGF_NK_REC *subkey;
799 REGISTRY_KEY registry_key;
800 REGVAL_CTR values;
801 REGSUBKEY_CTR subkeys;
802 int i;
803 pstring path;
804 WERROR result = WERR_OK;
806 /* initialize the REGISTRY_KEY structure */
808 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
809 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
810 topkeypath ));
811 return WERR_BADFILE;
813 pstrcpy( registry_key.name, topkeypath );
815 /* now start parsing the values and subkeys */
817 regsubkey_ctr_init( &subkeys );
818 regval_ctr_init( &values );
820 /* copy values into the REGVAL_CTR */
822 for ( i=0; i<key->num_values; i++ ) {
823 regval_ctr_addvalue( &values, key->values[i].valuename, key->values[i].type,
824 key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
827 /* copy subkeys into the REGSUBKEY_CTR */
829 key->subkey_index = 0;
830 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
831 regsubkey_ctr_addkey( &subkeys, subkey->keyname );
834 /* write this key and values out */
836 if ( !store_reg_values( &registry_key, &values )
837 || !store_reg_keys( &registry_key, &subkeys ) )
839 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
840 result = WERR_REG_IO_FAILURE;
843 regval_ctr_destroy( &values );
844 regsubkey_ctr_destroy( &subkeys );
846 if ( !W_ERROR_IS_OK(result) )
847 return result;
849 /* now continue to load each subkey registry tree */
851 key->subkey_index = 0;
852 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
853 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
854 result = reg_load_tree( regfile, path, subkey );
855 if ( !W_ERROR_IS_OK(result) )
856 break;
859 return result;
862 /*******************************************************************
863 ********************************************************************/
865 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
867 REGF_FILE *regfile;
868 REGF_NK_REC *rootkey;
869 WERROR result;
871 /* open the registry file....fail if the file already exists */
873 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
874 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
875 fname, strerror(errno) ));
876 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
879 /* get the rootkey from the regf file and then load the tree
880 via recursive calls */
882 if ( !(rootkey = regfio_rootkey( regfile )) )
883 return WERR_REG_FILE_INVALID;
885 result = reg_load_tree( regfile, krecord->name, rootkey );
887 /* cleanup */
889 regfio_close( regfile );
891 return result;
894 /*******************************************************************
895 ********************************************************************/
897 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
899 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
900 pstring filename;
901 int snum;
903 DEBUG(5,("_reg_restore_key: Enter\n"));
905 if ( !regkey )
906 return WERR_BADFID;
908 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
910 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
912 if ( (snum = validate_reg_filename( filename )) == -1 )
913 return WERR_OBJECT_PATH_INVALID;
915 /* user must posses SeRestorePrivilege for this this proceed */
917 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
918 return WERR_ACCESS_DENIED;
920 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
922 return restore_registry_key( regkey, filename );
925 /********************************************************************
926 ********************************************************************/
928 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
929 REGF_NK_REC *parent, SEC_DESC *sec_desc )
931 REGF_NK_REC *key;
932 REGVAL_CTR values;
933 REGSUBKEY_CTR subkeys;
934 int i, num_subkeys;
935 pstring key_tmp;
936 char *keyname, *parentpath;
937 pstring subkeypath;
938 char *subkeyname;
939 REGISTRY_KEY registry_key;
940 WERROR result = WERR_OK;
942 if ( !regfile )
943 return WERR_GENERAL_FAILURE;
945 if ( !keypath )
946 return WERR_OBJECT_PATH_INVALID;
948 /* split up the registry key path */
950 pstrcpy( key_tmp, keypath );
951 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
952 return WERR_OBJECT_PATH_INVALID;
954 if ( !keyname )
955 keyname = parentpath;
957 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
959 ZERO_STRUCT( registry_key );
960 pstrcpy( registry_key.name, keypath );
961 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
962 return WERR_BADFILE;
965 /* lookup the values and subkeys */
967 regsubkey_ctr_init( &subkeys );
968 regval_ctr_init( &values );
970 fetch_reg_keys( &registry_key, &subkeys );
971 fetch_reg_values( &registry_key, &values );
973 /* write out this key */
975 if ( !(key = regfio_write_key( regfile, keyname, &values, &subkeys, sec_desc, parent )) ) {
976 result = WERR_CAN_NOT_COMPLETE;
977 goto done;
980 /* write each one of the subkeys out */
982 num_subkeys = regsubkey_ctr_numkeys( &subkeys );
983 for ( i=0; i<num_subkeys; i++ ) {
984 subkeyname = regsubkey_ctr_specific_key( &subkeys, i );
985 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
986 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
987 if ( !W_ERROR_IS_OK(result) )
988 goto done;
991 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
993 done:
994 regval_ctr_destroy( &values );
995 regsubkey_ctr_destroy( &subkeys );
997 return result;
1000 /*******************************************************************
1001 ********************************************************************/
1003 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1005 DOM_SID adm_sid, owner_sid;
1006 SEC_ACE ace[2]; /* at most 2 entries */
1007 SEC_ACCESS mask;
1008 SEC_ACL *psa = NULL;
1009 uint32 sd_size;
1011 /* set the owner to BUILTIN\Administrator */
1013 sid_copy(&owner_sid, &global_sid_Builtin);
1014 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1017 /* basic access for Everyone */
1019 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1020 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1022 /* add Full Access 'BUILTIN\Administrators' */
1024 init_sec_access(&mask, reg_generic_map.generic_all);
1025 sid_copy(&adm_sid, &global_sid_Builtin);
1026 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1027 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1029 /* create the security descriptor */
1031 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1032 return WERR_NOMEM;
1034 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1035 return WERR_NOMEM;
1037 return WERR_OK;
1040 /*******************************************************************
1041 ********************************************************************/
1043 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1045 REGF_FILE *regfile;
1046 WERROR result;
1047 SEC_DESC *sd = NULL;
1049 /* open the registry file....fail if the file already exists */
1051 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1052 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1053 fname, strerror(errno) ));
1054 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1057 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1058 regfio_close( regfile );
1059 return result;
1062 /* write the registry tree to the file */
1064 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1066 /* cleanup */
1068 regfio_close( regfile );
1070 return result;
1073 /*******************************************************************
1074 ********************************************************************/
1076 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1078 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1079 pstring filename;
1080 int snum;
1082 DEBUG(5,("_reg_save_key: Enter\n"));
1084 if ( !regkey )
1085 return WERR_BADFID;
1087 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1089 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1091 if ( (snum = validate_reg_filename( filename )) == -1 )
1092 return WERR_OBJECT_PATH_INVALID;
1094 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1096 return backup_registry_key( regkey, filename );
1098 return WERR_OK;
1101 /*******************************************************************
1102 ********************************************************************/
1104 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1106 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1107 REGISTRY_KEY *newparent;
1108 POLICY_HND newparent_handle;
1109 REGSUBKEY_CTR subkeys;
1110 BOOL write_result;
1111 pstring name;
1112 WERROR result;
1114 if ( !parent )
1115 return WERR_BADFID;
1117 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1119 /* ok. Here's what we do. */
1121 if ( strrchr( name, '\\' ) ) {
1122 pstring newkeyname;
1123 char *ptr;
1124 uint32 access_granted;
1126 /* (1) check for enumerate rights on the parent handle. CLients can try
1127 create things like 'SOFTWARE\Samba' on the HKLM handle.
1128 (2) open the path to the child parent key if necessary */
1130 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1131 return WERR_ACCESS_DENIED;
1133 pstrcpy( newkeyname, name );
1134 ptr = strrchr( newkeyname, '\\' );
1135 *ptr = '\0';
1137 result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
1138 if ( !W_ERROR_IS_OK(result) )
1139 return result;
1141 newparent = find_regkey_index_by_hnd(p, &newparent_handle);
1142 SMB_ASSERT( newparent != NULL );
1144 if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
1145 result = WERR_ACCESS_DENIED;
1146 goto done;
1149 newparent->access_granted = access_granted;
1151 /* copy the new key name (just the lower most keyname) */
1153 pstrcpy( name, ptr+1 );
1155 else {
1156 /* use the existing open key information */
1157 newparent = parent;
1158 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1161 /* (3) check for create subkey rights on the correct parent */
1163 if ( !(newparent->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1164 result = WERR_ACCESS_DENIED;
1165 goto done;
1168 regsubkey_ctr_init( &subkeys );
1170 /* (4) lookup the current keys and add the new one */
1172 fetch_reg_keys( newparent, &subkeys );
1173 regsubkey_ctr_addkey( &subkeys, name );
1175 /* now write to the registry backend */
1177 write_result = store_reg_keys( newparent, &subkeys );
1179 regsubkey_ctr_destroy( &subkeys );
1181 if ( !write_result )
1182 return WERR_REG_IO_FAILURE;
1184 /* (5) open the new key and return the handle. Note that it is probably
1185 not correct to grant full access on this open handle. We should pass
1186 the new open through the regkey_access_check() like we do for
1187 _reg_open_entry() but this is ok for now. */
1189 result = open_registry_key( p, &r_u->handle, newparent, name, REG_KEY_ALL );
1191 done:
1192 /* close any intermediate key handles */
1194 if ( newparent != parent )
1195 close_registry_key( p, &newparent_handle );
1197 return result;
1201 /*******************************************************************
1202 ********************************************************************/
1204 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1206 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1207 REGVAL_CTR values;
1208 BOOL write_result;
1209 fstring valuename;
1211 if ( !key )
1212 return WERR_BADFID;
1214 /* access checks first */
1216 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1217 return WERR_ACCESS_DENIED;
1219 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1221 /* verify the name */
1223 if ( !*valuename )
1224 return WERR_INVALID_PARAM;
1226 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1228 regval_ctr_init( &values );
1230 /* lookup the current values and add the new one */
1232 fetch_reg_values( key, &values );
1234 regval_ctr_addvalue( &values, valuename, q_u->type, q_u->value.buffer, q_u->value.buf_len );
1236 /* now write to the registry backend */
1238 write_result = store_reg_values( key, &values );
1240 regval_ctr_destroy( &values );
1242 if ( !write_result )
1243 return WERR_REG_IO_FAILURE;
1245 return WERR_OK;
1248 /*******************************************************************
1249 ********************************************************************/
1251 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1253 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1254 REGISTRY_KEY *newparent;
1255 POLICY_HND newparent_handle;
1256 REGSUBKEY_CTR subkeys;
1257 BOOL write_result;
1258 pstring name;
1259 WERROR result;
1261 if ( !parent )
1262 return WERR_BADFID;
1264 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1266 /* ok. Here's what we do. */
1268 if ( strrchr( name, '\\' ) ) {
1269 pstring newkeyname;
1270 char *ptr;
1271 uint32 access_granted;
1273 /* (1) check for enumerate rights on the parent handle. CLients can try
1274 create things like 'SOFTWARE\Samba' on the HKLM handle.
1275 (2) open the path to the child parent key if necessary */
1277 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1278 return WERR_ACCESS_DENIED;
1280 pstrcpy( newkeyname, name );
1281 ptr = strrchr( newkeyname, '\\' );
1282 *ptr = '\0';
1284 result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
1285 if ( !W_ERROR_IS_OK(result) )
1286 return result;
1288 newparent = find_regkey_index_by_hnd(p, &newparent_handle);
1289 SMB_ASSERT( newparent != NULL );
1291 if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
1292 result = WERR_ACCESS_DENIED;
1293 goto done;
1296 newparent->access_granted = access_granted;
1298 /* copy the new key name (just the lower most keyname) */
1300 pstrcpy( name, ptr+1 );
1302 else {
1303 /* use the existing open key information */
1304 newparent = parent;
1305 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1308 /* (3) check for create subkey rights on the correct parent */
1310 if ( !(newparent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1311 result = WERR_ACCESS_DENIED;
1312 goto done;
1315 regsubkey_ctr_init( &subkeys );
1317 /* lookup the current keys and delete the new one */
1319 fetch_reg_keys( newparent, &subkeys );
1321 regsubkey_ctr_delkey( &subkeys, name );
1323 /* now write to the registry backend */
1325 write_result = store_reg_keys( newparent, &subkeys );
1327 regsubkey_ctr_destroy( &subkeys );
1329 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1331 done:
1332 /* close any intermediate key handles */
1334 if ( newparent != parent )
1335 close_registry_key( p, &newparent_handle );
1337 return result;
1341 /*******************************************************************
1342 ********************************************************************/
1344 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1346 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1347 REGVAL_CTR values;
1348 BOOL write_result;
1349 fstring valuename;
1351 if ( !key )
1352 return WERR_BADFID;
1354 /* access checks first */
1356 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1357 return WERR_ACCESS_DENIED;
1359 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1361 if ( !*valuename )
1362 return WERR_INVALID_PARAM;
1364 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1366 regval_ctr_init( &values );
1368 /* lookup the current values and add the new one */
1370 fetch_reg_values( key, &values );
1372 regval_ctr_delvalue( &values, valuename );
1374 /* now write to the registry backend */
1376 write_result = store_reg_values( key, &values );
1378 regval_ctr_destroy( &values );
1380 if ( !write_result )
1381 return WERR_REG_IO_FAILURE;
1383 return WERR_OK;
1386 /*******************************************************************
1387 ********************************************************************/
1389 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1391 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1393 if ( !key )
1394 return WERR_BADFID;
1396 /* access checks first */
1398 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1399 return WERR_ACCESS_DENIED;
1401 return WERR_ACCESS_DENIED;
1404 /*******************************************************************
1405 ********************************************************************/
1407 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1409 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1411 if ( !key )
1412 return WERR_BADFID;
1414 /* access checks first */
1416 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1417 return WERR_ACCESS_DENIED;
1419 return WERR_ACCESS_DENIED;