r11072: add routines for converting REG_MULTI_SZ to and from char**
[Samba/bb.git] / source3 / rpc_server / srv_reg_nt.c
blob35a060c38e3330bae1b0ca73747691656a2147f5
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())
36 static struct generic_mapping reg_generic_map =
37 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
40 /******************************************************************
41 free() function for REGISTRY_KEY
42 *****************************************************************/
44 static void free_regkey_info(void *ptr)
46 regkey_close_internal( (REGISTRY_KEY*)ptr );
49 /******************************************************************
50 Find a registry key handle and return a REGISTRY_KEY
51 *****************************************************************/
53 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
55 REGISTRY_KEY *regkey = NULL;
57 if(!find_policy_by_hnd(p,hnd,(void **)&regkey)) {
58 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
59 return NULL;
62 return regkey;
66 /*******************************************************************
67 Function for open a new registry handle and creating a handle
68 Note that P should be valid & hnd should already have space
70 When we open a key, we store the full path to the key as
71 HK[LM|U]\<key>\<key>\...
72 *******************************************************************/
74 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
75 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
76 const char *subkeyname, uint32 access_desired )
78 pstring keypath;
79 int path_len;
80 WERROR result = WERR_OK;
82 /* create a full registry path and strip any trailing '\'
83 characters */
85 pstr_sprintf( keypath, "%s%s%s",
86 parent ? parent->name : "",
87 parent ? "\\" : "",
88 subkeyname );
90 path_len = strlen( keypath );
91 if ( path_len && keypath[path_len-1] == '\\' )
92 keypath[path_len-1] = '\0';
94 /* now do the internal open */
96 result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
97 if ( !W_ERROR_IS_OK(result) )
98 return result;
100 if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
101 result = WERR_BADFILE;
102 regkey_close_internal( *keyinfo );
105 return result;
108 /*******************************************************************
109 Function for open a new registry handle and creating a handle
110 Note that P should be valid & hnd should already have space
111 *******************************************************************/
113 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
115 REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
117 if ( !regkey ) {
118 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
119 return False;
122 close_policy_hnd(p, hnd);
124 return True;
127 /********************************************************************
128 retrieve information about the subkeys
129 *******************************************************************/
131 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
133 int num_subkeys, i;
134 uint32 max_len;
135 REGSUBKEY_CTR *subkeys;
136 uint32 len;
138 if ( !key )
139 return False;
141 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
142 return False;
144 if ( fetch_reg_keys( key, subkeys ) == -1 )
145 return False;
147 /* find the longest string */
149 max_len = 0;
150 num_subkeys = regsubkey_ctr_numkeys( subkeys );
152 for ( i=0; i<num_subkeys; i++ ) {
153 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
154 max_len = MAX(max_len, len);
157 *maxnum = num_subkeys;
158 *maxlen = max_len*2;
160 TALLOC_FREE( subkeys );
162 return True;
165 /********************************************************************
166 retrieve information about the values.
167 *******************************************************************/
169 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
170 uint32 *maxlen, uint32 *maxsize )
172 REGVAL_CTR *values;
173 REGISTRY_VALUE *val;
174 uint32 sizemax, lenmax;
175 int i, num_values;
177 if ( !key )
178 return False;
180 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
181 return False;
183 if ( fetch_reg_values( key, values ) == -1 )
184 return False;
186 lenmax = sizemax = 0;
187 num_values = regval_ctr_numvals( values );
189 val = regval_ctr_specific_value( values, 0 );
191 for ( i=0; i<num_values && val; i++ )
193 lenmax = MAX(lenmax, val->valuename ? strlen(val->valuename)+1 : 0 );
194 sizemax = MAX(sizemax, val->size );
196 val = regval_ctr_specific_value( values, i );
199 *maxnum = num_values;
200 *maxlen = lenmax;
201 *maxsize = sizemax;
203 TALLOC_FREE( values );
205 return True;
209 /********************************************************************
210 reg_close
211 ********************************************************************/
213 WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
215 /* close the policy handle */
217 if (!close_registry_key(p, &q_u->pol))
218 return WERR_BADFID;
220 return WERR_OK;
223 /*******************************************************************
224 ********************************************************************/
226 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
228 REGISTRY_KEY *keyinfo;
230 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access );
233 /*******************************************************************
234 ********************************************************************/
236 WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
238 REGISTRY_KEY *keyinfo;
240 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access );
243 /*******************************************************************
244 ********************************************************************/
246 WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
248 REGISTRY_KEY *keyinfo;
250 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access );
253 /*******************************************************************
254 ********************************************************************/
256 WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
258 REGISTRY_KEY *keyinfo;
260 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access );
263 /*******************************************************************
264 ********************************************************************/
266 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
268 REGISTRY_KEY *keyinfo;
270 return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access );
273 /*******************************************************************
274 reg_reply_open_entry
275 ********************************************************************/
277 WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
279 fstring name;
280 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
281 REGISTRY_KEY *newkey = NULL;
282 uint32 check_rights;
284 if ( !parent )
285 return WERR_BADFID;
287 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
289 /* check granted access first; what is the correct mask here? */
291 check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
292 SEC_RIGHTS_CREATE_SUBKEY|
293 SEC_RIGHTS_QUERY_VALUE|
294 SEC_RIGHTS_SET_VALUE);
296 if ( !(parent->access_granted & check_rights) ) {
297 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
298 return WERR_ACCESS_DENIED;
302 * very crazy, but regedit.exe on Win2k will attempt to call
303 * REG_OPEN_ENTRY with a keyname of "". We should return a new
304 * (second) handle here on the key->name. regedt32.exe does
305 * not do this stupidity. --jerry
308 return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
311 /*******************************************************************
312 reg_reply_info
313 ********************************************************************/
315 WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VALUE *r_u)
317 WERROR status = WERR_BADFILE;
318 fstring name;
319 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
320 REGISTRY_VALUE *val = NULL;
321 REGVAL_CTR *regvals;
322 int i;
324 if ( !regkey )
325 return WERR_BADFID;
327 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
328 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
330 rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
332 DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
334 if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
335 return WERR_NOMEM;
337 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
338 if(regkey->type == REG_KEY_HKPD)
340 if(strequal(name, "Global"))
342 uint32 outbuf_len;
343 prs_struct prs_hkpd;
344 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
345 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
346 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
347 prs_hkpd.data_p, outbuf_len);
348 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
349 prs_mem_free(&prs_hkpd);
351 else if(strequal(name, "Counter 009"))
353 uint32 base_index;
354 uint32 buffer_size;
355 char *buffer;
357 buffer = NULL;
358 base_index = reg_perfcount_get_base_index();
359 buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
360 regval_ctr_addvalue(regvals, "Counter 009",
361 REG_MULTI_SZ, buffer, buffer_size);
363 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
365 if(buffer_size > 0)
367 SAFE_FREE(buffer);
368 status = WERR_OK;
371 else if(strequal(name, "Explain 009"))
373 uint32 base_index;
374 uint32 buffer_size;
375 char *buffer;
377 buffer = NULL;
378 base_index = reg_perfcount_get_base_index();
379 buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
380 regval_ctr_addvalue(regvals, "Explain 009",
381 REG_MULTI_SZ, buffer, buffer_size);
383 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
385 if(buffer_size > 0)
387 SAFE_FREE(buffer);
388 status = WERR_OK;
391 else if(isdigit(name[0]))
393 /* we probably have a request for a specific object here */
394 uint32 outbuf_len;
395 prs_struct prs_hkpd;
396 prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
397 status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
398 regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
399 prs_hkpd.data_p, outbuf_len);
401 val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
402 prs_mem_free(&prs_hkpd);
404 else
406 DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
407 return WERR_BADFILE;
410 /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
411 else
413 for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
415 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
416 if ( strequal( val->valuename, name ) ) {
417 DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
418 status = WERR_OK;
419 break;
422 free_registry_value( val );
426 init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
428 TALLOC_FREE( regvals );
429 free_registry_value( val );
431 return status;
434 /*****************************************************************************
435 Implementation of REG_QUERY_KEY
436 ****************************************************************************/
438 WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
440 WERROR status = WERR_OK;
441 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
443 if ( !regkey )
444 return WERR_BADFID;
446 if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) ) {
447 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
448 return WERR_ACCESS_DENIED;
451 if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) {
452 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
453 return WERR_ACCESS_DENIED;
457 r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
459 /* Win9x set this to 0x0 since it does not keep timestamps.
460 Doing the same here for simplicity --jerry */
462 ZERO_STRUCT(r_u->mod_time);
464 return status;
468 /*****************************************************************************
469 Implementation of REG_GETVERSION
470 ****************************************************************************/
472 WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
474 WERROR status = WERR_OK;
475 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
477 if ( !regkey )
478 return WERR_BADFID;
480 r_u->win_version = 0x00000005; /* Windows 2000 registry API version */
482 return status;
486 /*****************************************************************************
487 Implementation of REG_ENUM_KEY
488 ****************************************************************************/
490 WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
492 WERROR status = WERR_OK;
493 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
494 char *subkey = NULL;
497 if ( !regkey )
498 return WERR_BADFID;
500 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
502 if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
504 status = WERR_NO_MORE_ITEMS;
505 goto done;
508 DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
510 /* subkey has the string name now */
512 init_reg_r_enum_key( r_u, subkey );
514 done:
515 SAFE_FREE( subkey );
516 return status;
519 /*****************************************************************************
520 Implementation of REG_ENUM_VALUE
521 ****************************************************************************/
523 WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
525 WERROR status = WERR_OK;
526 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
527 REGISTRY_VALUE *val;
530 if ( !regkey )
531 return WERR_BADFID;
533 DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
535 if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) {
536 status = WERR_NO_MORE_ITEMS;
537 goto done;
540 #if 0 /* JERRY TEST CODE */
541 if ( val->type == REG_MULTI_SZ ) {
542 char **str;
543 int num_strings = regval_convert_multi_sz( (uint16*)regval_data_p(val), regval_size(val), &str );
544 uint16 *buffer;
545 size_t buf_size;
548 if ( num_strings )
549 buf_size = regval_build_multi_sz( str, &buffer );
551 TALLOC_FREE( str );
552 TALLOC_FREE( buffer );
554 #endif
556 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
558 /* subkey has the string name now */
560 init_reg_r_enum_val( r_u, val );
562 done:
563 free_registry_value( val );
565 return status;
569 /*******************************************************************
570 reg_shutdwon
571 ********************************************************************/
573 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
575 REG_Q_SHUTDOWN_EX q_u_ex;
576 REG_R_SHUTDOWN_EX r_u_ex;
578 /* copy fields (including stealing memory) */
580 q_u_ex.server = q_u->server;
581 q_u_ex.message = q_u->message;
582 q_u_ex.timeout = q_u->timeout;
583 q_u_ex.force = q_u->force;
584 q_u_ex.reboot = q_u->reboot;
585 q_u_ex.reason = 0x0; /* don't care for now */
587 /* thunk down to _reg_shutdown_ex() (just returns a status) */
589 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
592 /*******************************************************************
593 reg_shutdown_ex
594 ********************************************************************/
596 #define SHUTDOWN_R_STRING "-r"
597 #define SHUTDOWN_F_STRING "-f"
600 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
602 pstring shutdown_script;
603 pstring message;
604 pstring chkmsg;
605 fstring timeout;
606 fstring reason;
607 fstring r;
608 fstring f;
609 int ret;
610 BOOL can_shutdown;
613 pstrcpy(shutdown_script, lp_shutdown_script());
615 if ( !*shutdown_script )
616 return WERR_ACCESS_DENIED;
618 /* pull the message string and perform necessary sanity checks on it */
620 pstrcpy( message, "" );
621 if ( q_u->message ) {
622 UNISTR2 *msg_string = q_u->message->string;
624 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
626 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
628 fstr_sprintf(timeout, "%d", q_u->timeout);
629 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
630 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
631 fstr_sprintf( reason, "%d", q_u->reason );
633 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
634 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
635 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
636 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
637 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
639 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
641 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
642 Take the error return from the script and provide it as the Windows return code. */
644 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
646 if ( can_shutdown )
647 become_root();
649 ret = smbrun( shutdown_script, NULL );
651 if ( can_shutdown )
652 unbecome_root();
654 /********** END SeRemoteShutdownPrivilege BLOCK **********/
656 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
657 shutdown_script, ret));
660 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
666 /*******************************************************************
667 reg_abort_shutdwon
668 ********************************************************************/
670 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
672 pstring abort_shutdown_script;
673 int ret;
674 BOOL can_shutdown;
676 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
678 if ( !*abort_shutdown_script )
679 return WERR_ACCESS_DENIED;
681 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
683 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
685 if ( can_shutdown )
686 become_root();
688 ret = smbrun( abort_shutdown_script, NULL );
690 if ( can_shutdown )
691 unbecome_root();
693 /********** END SeRemoteShutdownPrivilege BLOCK **********/
695 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
696 abort_shutdown_script, ret));
699 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
702 /*******************************************************************
703 ********************************************************************/
705 static int validate_reg_filename( pstring fname )
707 char *p;
708 int num_services = lp_numservices();
709 int snum;
710 pstring share_path;
711 pstring unix_fname;
713 /* convert to a unix path, stripping the C:\ along the way */
715 if ( !(p = valid_share_pathname( fname ) ))
716 return -1;
718 /* has to exist within a valid file share */
720 for ( snum=0; snum<num_services; snum++ ) {
722 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
723 continue;
725 pstrcpy( share_path, lp_pathname(snum) );
727 /* make sure we have a path (e.g. [homes] ) */
729 if ( strlen( share_path ) == 0 )
730 continue;
732 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
733 break;
736 /* p and fname are overlapping memory so copy out and back in again */
738 pstrcpy( unix_fname, p );
739 pstrcpy( fname, unix_fname );
741 return (snum < num_services) ? snum : -1;
744 /*******************************************************************
745 Note: topkeypat is the *full* path that this *key will be
746 loaded into (including the name of the key)
747 ********************************************************************/
749 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
750 REGF_NK_REC *key )
752 REGF_NK_REC *subkey;
753 REGISTRY_KEY registry_key;
754 REGVAL_CTR *values;
755 REGSUBKEY_CTR *subkeys;
756 int i;
757 pstring path;
758 WERROR result = WERR_OK;
760 /* initialize the REGISTRY_KEY structure */
762 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
763 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
764 topkeypath ));
765 return WERR_BADFILE;
767 pstrcpy( registry_key.name, topkeypath );
769 /* now start parsing the values and subkeys */
771 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
772 return WERR_NOMEM;
774 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
775 return WERR_NOMEM;
777 /* copy values into the REGVAL_CTR */
779 for ( i=0; i<key->num_values; i++ ) {
780 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
781 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
784 /* copy subkeys into the REGSUBKEY_CTR */
786 key->subkey_index = 0;
787 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
788 regsubkey_ctr_addkey( subkeys, subkey->keyname );
791 /* write this key and values out */
793 if ( !store_reg_values( &registry_key, values )
794 || !store_reg_keys( &registry_key, subkeys ) )
796 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
797 result = WERR_REG_IO_FAILURE;
800 TALLOC_FREE( subkeys );
802 if ( !W_ERROR_IS_OK(result) )
803 return result;
805 /* now continue to load each subkey registry tree */
807 key->subkey_index = 0;
808 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
809 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
810 result = reg_load_tree( regfile, path, subkey );
811 if ( !W_ERROR_IS_OK(result) )
812 break;
815 return result;
818 /*******************************************************************
819 ********************************************************************/
821 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
823 REGF_FILE *regfile;
824 REGF_NK_REC *rootkey;
825 WERROR result;
827 /* open the registry file....fail if the file already exists */
829 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
830 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
831 fname, strerror(errno) ));
832 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
835 /* get the rootkey from the regf file and then load the tree
836 via recursive calls */
838 if ( !(rootkey = regfio_rootkey( regfile )) )
839 return WERR_REG_FILE_INVALID;
841 result = reg_load_tree( regfile, krecord->name, rootkey );
843 /* cleanup */
845 regfio_close( regfile );
847 return result;
850 /*******************************************************************
851 ********************************************************************/
853 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
855 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
856 pstring filename;
857 int snum;
859 if ( !regkey )
860 return WERR_BADFID;
862 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
864 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
866 if ( (snum = validate_reg_filename( filename )) == -1 )
867 return WERR_OBJECT_PATH_INVALID;
869 /* user must posses SeRestorePrivilege for this this proceed */
871 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
872 return WERR_ACCESS_DENIED;
874 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
876 return restore_registry_key( regkey, filename );
879 /********************************************************************
880 ********************************************************************/
882 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
883 REGF_NK_REC *parent, SEC_DESC *sec_desc )
885 REGF_NK_REC *key;
886 REGVAL_CTR *values;
887 REGSUBKEY_CTR *subkeys;
888 int i, num_subkeys;
889 pstring key_tmp;
890 char *keyname, *parentpath;
891 pstring subkeypath;
892 char *subkeyname;
893 REGISTRY_KEY registry_key;
894 WERROR result = WERR_OK;
896 if ( !regfile )
897 return WERR_GENERAL_FAILURE;
899 if ( !keypath )
900 return WERR_OBJECT_PATH_INVALID;
902 /* split up the registry key path */
904 pstrcpy( key_tmp, keypath );
905 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
906 return WERR_OBJECT_PATH_INVALID;
908 if ( !keyname )
909 keyname = parentpath;
911 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
913 ZERO_STRUCT( registry_key );
914 pstrcpy( registry_key.name, keypath );
915 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
916 return WERR_BADFILE;
919 /* lookup the values and subkeys */
921 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
922 return WERR_NOMEM;
924 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
925 return WERR_NOMEM;
927 fetch_reg_keys( &registry_key, subkeys );
928 fetch_reg_values( &registry_key, values );
930 /* write out this key */
932 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
933 result = WERR_CAN_NOT_COMPLETE;
934 goto done;
937 /* write each one of the subkeys out */
939 num_subkeys = regsubkey_ctr_numkeys( subkeys );
940 for ( i=0; i<num_subkeys; i++ ) {
941 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
942 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
943 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
944 if ( !W_ERROR_IS_OK(result) )
945 goto done;
948 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
950 done:
951 TALLOC_FREE( subkeys );
953 return result;
956 /*******************************************************************
957 ********************************************************************/
959 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
961 DOM_SID adm_sid, owner_sid;
962 SEC_ACE ace[2]; /* at most 2 entries */
963 SEC_ACCESS mask;
964 SEC_ACL *psa = NULL;
965 size_t sd_size;
967 /* set the owner to BUILTIN\Administrator */
969 sid_copy(&owner_sid, &global_sid_Builtin);
970 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
973 /* basic access for Everyone */
975 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
976 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
978 /* add Full Access 'BUILTIN\Administrators' */
980 init_sec_access(&mask, reg_generic_map.generic_all);
981 sid_copy(&adm_sid, &global_sid_Builtin);
982 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
983 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
985 /* create the security descriptor */
987 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
988 return WERR_NOMEM;
990 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
991 return WERR_NOMEM;
993 return WERR_OK;
996 /*******************************************************************
997 ********************************************************************/
999 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1001 REGF_FILE *regfile;
1002 WERROR result;
1003 SEC_DESC *sd = NULL;
1005 /* open the registry file....fail if the file already exists */
1007 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1008 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1009 fname, strerror(errno) ));
1010 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1013 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1014 regfio_close( regfile );
1015 return result;
1018 /* write the registry tree to the file */
1020 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1022 /* cleanup */
1024 regfio_close( regfile );
1026 return result;
1029 /*******************************************************************
1030 ********************************************************************/
1032 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1034 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1035 pstring filename;
1036 int snum;
1038 if ( !regkey )
1039 return WERR_BADFID;
1041 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1043 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1045 if ( (snum = validate_reg_filename( filename )) == -1 )
1046 return WERR_OBJECT_PATH_INVALID;
1048 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1050 return backup_registry_key( regkey, filename );
1053 /*******************************************************************
1054 ********************************************************************/
1056 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1058 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1059 REGISTRY_KEY *newparentinfo, *keyinfo;
1060 POLICY_HND newparent_handle;
1061 REGSUBKEY_CTR *subkeys;
1062 BOOL write_result;
1063 pstring name;
1064 WERROR result;
1066 if ( !parent )
1067 return WERR_BADFID;
1069 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1071 /* ok. Here's what we do. */
1073 if ( strrchr( name, '\\' ) ) {
1074 pstring newkeyname;
1075 char *ptr;
1077 /* (1) check for enumerate rights on the parent handle. CLients can try
1078 create things like 'SOFTWARE\Samba' on the HKLM handle.
1079 (2) open the path to the child parent key if necessary */
1081 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1082 return WERR_ACCESS_DENIED;
1084 pstrcpy( newkeyname, name );
1085 ptr = strrchr( newkeyname, '\\' );
1086 *ptr = '\0';
1088 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1089 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1091 if ( !W_ERROR_IS_OK(result) )
1092 return result;
1094 /* copy the new key name (just the lower most keyname) */
1096 pstrcpy( name, ptr+1 );
1098 else {
1099 /* use the existing open key information */
1100 newparentinfo = parent;
1101 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1104 /* (3) check for create subkey rights on the correct parent */
1106 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1107 result = WERR_ACCESS_DENIED;
1108 goto done;
1111 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1112 result = WERR_NOMEM;
1113 goto done;
1116 /* (4) lookup the current keys and add the new one */
1118 fetch_reg_keys( newparentinfo, subkeys );
1119 regsubkey_ctr_addkey( subkeys, name );
1121 /* now write to the registry backend */
1123 write_result = store_reg_keys( newparentinfo, subkeys );
1125 TALLOC_FREE( subkeys );
1127 if ( !write_result )
1128 return WERR_REG_IO_FAILURE;
1130 /* (5) open the new key and return the handle. Note that it is probably
1131 not correct to grant full access on this open handle. */
1133 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1134 keyinfo->access_granted = REG_KEY_ALL;
1136 done:
1137 /* close any intermediate key handles */
1139 if ( newparentinfo != parent )
1140 close_registry_key( p, &newparent_handle );
1142 return result;
1146 /*******************************************************************
1147 ********************************************************************/
1149 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1151 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1152 REGVAL_CTR *values;
1153 BOOL write_result;
1154 fstring valuename;
1156 if ( !key )
1157 return WERR_BADFID;
1159 /* access checks first */
1161 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1162 return WERR_ACCESS_DENIED;
1164 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1166 /* verify the name */
1168 if ( !*valuename )
1169 return WERR_INVALID_PARAM;
1171 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1173 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1174 return WERR_NOMEM;
1176 /* lookup the current values and add the new one */
1178 fetch_reg_values( key, values );
1180 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
1182 /* now write to the registry backend */
1184 write_result = store_reg_values( key, values );
1186 TALLOC_FREE( values );
1188 if ( !write_result )
1189 return WERR_REG_IO_FAILURE;
1191 return WERR_OK;
1194 /*******************************************************************
1195 ********************************************************************/
1197 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1199 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1200 REGISTRY_KEY *newparentinfo;
1201 POLICY_HND newparent_handle;
1202 REGSUBKEY_CTR *subkeys;
1203 BOOL write_result;
1204 pstring name;
1205 WERROR result;
1207 if ( !parent )
1208 return WERR_BADFID;
1210 /* MSDN says parent the handle must have been opened with DELETE access */
1212 /* (1) check for delete rights on the parent */
1214 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1215 result = WERR_ACCESS_DENIED;
1216 goto done;
1219 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1221 /* ok. Here's what we do. */
1223 if ( strrchr( name, '\\' ) ) {
1224 pstring newkeyname;
1225 char *ptr;
1227 /* (2) open the path to the child parent key if necessary */
1228 /* split the registry path and save the subkeyname */
1230 pstrcpy( newkeyname, name );
1231 ptr = strrchr( newkeyname, '\\' );
1232 *ptr = '\0';
1233 pstrcpy( name, ptr+1 );
1235 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1236 if ( !W_ERROR_IS_OK(result) )
1237 return result;
1239 else {
1240 /* use the existing open key information */
1241 newparentinfo = parent;
1244 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1245 result = WERR_NOMEM;
1246 goto done;
1249 /* lookup the current keys and delete the new one */
1251 fetch_reg_keys( newparentinfo, subkeys );
1253 regsubkey_ctr_delkey( subkeys, name );
1255 /* now write to the registry backend */
1257 write_result = store_reg_keys( newparentinfo, subkeys );
1259 TALLOC_FREE( subkeys );
1261 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1263 done:
1264 /* close any intermediate key handles */
1266 if ( newparentinfo != parent )
1267 close_registry_key( p, &newparent_handle );
1269 return result;
1273 /*******************************************************************
1274 ********************************************************************/
1276 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1278 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1279 REGVAL_CTR *values;
1280 BOOL write_result;
1281 fstring valuename;
1283 if ( !key )
1284 return WERR_BADFID;
1286 /* access checks first */
1288 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1289 return WERR_ACCESS_DENIED;
1291 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1293 if ( !*valuename )
1294 return WERR_INVALID_PARAM;
1296 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1298 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1299 return WERR_NOMEM;
1301 /* lookup the current values and add the new one */
1303 fetch_reg_values( key, values );
1305 regval_ctr_delvalue( values, valuename );
1307 /* now write to the registry backend */
1309 write_result = store_reg_values( key, values );
1311 TALLOC_FREE( values );
1313 if ( !write_result )
1314 return WERR_REG_IO_FAILURE;
1316 return WERR_OK;
1319 /*******************************************************************
1320 ********************************************************************/
1322 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1324 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1326 if ( !key )
1327 return WERR_BADFID;
1329 /* access checks first */
1331 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1332 return WERR_ACCESS_DENIED;
1334 return WERR_ACCESS_DENIED;
1337 /*******************************************************************
1338 ********************************************************************/
1340 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1342 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1344 if ( !key )
1345 return WERR_BADFID;
1347 /* access checks first */
1349 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1350 return WERR_ACCESS_DENIED;
1352 return WERR_ACCESS_DENIED;