r11069: make sure to zero memory when allocating a a REGVAL_CTR struct
[Samba.git] / source / rpc_server / srv_reg_nt.c
blob4cd824c9ef998d0645eb9449708e351dfb7d4f2a
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 ( val->type == REG_MULTI_SZ ) {
544 DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
546 /* subkey has the string name now */
548 init_reg_r_enum_val( r_u, val );
550 done:
551 free_registry_value( val );
553 return status;
557 /*******************************************************************
558 reg_shutdwon
559 ********************************************************************/
561 WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
563 REG_Q_SHUTDOWN_EX q_u_ex;
564 REG_R_SHUTDOWN_EX r_u_ex;
566 /* copy fields (including stealing memory) */
568 q_u_ex.server = q_u->server;
569 q_u_ex.message = q_u->message;
570 q_u_ex.timeout = q_u->timeout;
571 q_u_ex.force = q_u->force;
572 q_u_ex.reboot = q_u->reboot;
573 q_u_ex.reason = 0x0; /* don't care for now */
575 /* thunk down to _reg_shutdown_ex() (just returns a status) */
577 return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
580 /*******************************************************************
581 reg_shutdown_ex
582 ********************************************************************/
584 #define SHUTDOWN_R_STRING "-r"
585 #define SHUTDOWN_F_STRING "-f"
588 WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
590 pstring shutdown_script;
591 pstring message;
592 pstring chkmsg;
593 fstring timeout;
594 fstring reason;
595 fstring r;
596 fstring f;
597 int ret;
598 BOOL can_shutdown;
601 pstrcpy(shutdown_script, lp_shutdown_script());
603 if ( !*shutdown_script )
604 return WERR_ACCESS_DENIED;
606 /* pull the message string and perform necessary sanity checks on it */
608 pstrcpy( message, "" );
609 if ( q_u->message ) {
610 UNISTR2 *msg_string = q_u->message->string;
612 rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
614 alpha_strcpy (chkmsg, message, NULL, sizeof(message));
616 fstr_sprintf(timeout, "%d", q_u->timeout);
617 fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
618 fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
619 fstr_sprintf( reason, "%d", q_u->reason );
621 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
622 all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
623 all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
624 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
625 all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
627 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
629 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
630 Take the error return from the script and provide it as the Windows return code. */
632 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
634 if ( can_shutdown )
635 become_root();
637 ret = smbrun( shutdown_script, NULL );
639 if ( can_shutdown )
640 unbecome_root();
642 /********** END SeRemoteShutdownPrivilege BLOCK **********/
644 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
645 shutdown_script, ret));
648 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
654 /*******************************************************************
655 reg_abort_shutdwon
656 ********************************************************************/
658 WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
660 pstring abort_shutdown_script;
661 int ret;
662 BOOL can_shutdown;
664 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
666 if ( !*abort_shutdown_script )
667 return WERR_ACCESS_DENIED;
669 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
671 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
673 if ( can_shutdown )
674 become_root();
676 ret = smbrun( abort_shutdown_script, NULL );
678 if ( can_shutdown )
679 unbecome_root();
681 /********** END SeRemoteShutdownPrivilege BLOCK **********/
683 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
684 abort_shutdown_script, ret));
687 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
690 /*******************************************************************
691 ********************************************************************/
693 static int validate_reg_filename( pstring fname )
695 char *p;
696 int num_services = lp_numservices();
697 int snum;
698 pstring share_path;
699 pstring unix_fname;
701 /* convert to a unix path, stripping the C:\ along the way */
703 if ( !(p = valid_share_pathname( fname ) ))
704 return -1;
706 /* has to exist within a valid file share */
708 for ( snum=0; snum<num_services; snum++ ) {
710 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
711 continue;
713 pstrcpy( share_path, lp_pathname(snum) );
715 /* make sure we have a path (e.g. [homes] ) */
717 if ( strlen( share_path ) == 0 )
718 continue;
720 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
721 break;
724 /* p and fname are overlapping memory so copy out and back in again */
726 pstrcpy( unix_fname, p );
727 pstrcpy( fname, unix_fname );
729 return (snum < num_services) ? snum : -1;
732 /*******************************************************************
733 Note: topkeypat is the *full* path that this *key will be
734 loaded into (including the name of the key)
735 ********************************************************************/
737 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
738 REGF_NK_REC *key )
740 REGF_NK_REC *subkey;
741 REGISTRY_KEY registry_key;
742 REGVAL_CTR *values;
743 REGSUBKEY_CTR *subkeys;
744 int i;
745 pstring path;
746 WERROR result = WERR_OK;
748 /* initialize the REGISTRY_KEY structure */
750 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
751 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
752 topkeypath ));
753 return WERR_BADFILE;
755 pstrcpy( registry_key.name, topkeypath );
757 /* now start parsing the values and subkeys */
759 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
760 return WERR_NOMEM;
762 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
763 return WERR_NOMEM;
765 /* copy values into the REGVAL_CTR */
767 for ( i=0; i<key->num_values; i++ ) {
768 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
769 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
772 /* copy subkeys into the REGSUBKEY_CTR */
774 key->subkey_index = 0;
775 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
776 regsubkey_ctr_addkey( subkeys, subkey->keyname );
779 /* write this key and values out */
781 if ( !store_reg_values( &registry_key, values )
782 || !store_reg_keys( &registry_key, subkeys ) )
784 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
785 result = WERR_REG_IO_FAILURE;
788 TALLOC_FREE( subkeys );
790 if ( !W_ERROR_IS_OK(result) )
791 return result;
793 /* now continue to load each subkey registry tree */
795 key->subkey_index = 0;
796 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
797 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
798 result = reg_load_tree( regfile, path, subkey );
799 if ( !W_ERROR_IS_OK(result) )
800 break;
803 return result;
806 /*******************************************************************
807 ********************************************************************/
809 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
811 REGF_FILE *regfile;
812 REGF_NK_REC *rootkey;
813 WERROR result;
815 /* open the registry file....fail if the file already exists */
817 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
818 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
819 fname, strerror(errno) ));
820 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
823 /* get the rootkey from the regf file and then load the tree
824 via recursive calls */
826 if ( !(rootkey = regfio_rootkey( regfile )) )
827 return WERR_REG_FILE_INVALID;
829 result = reg_load_tree( regfile, krecord->name, rootkey );
831 /* cleanup */
833 regfio_close( regfile );
835 return result;
838 /*******************************************************************
839 ********************************************************************/
841 WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
843 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
844 pstring filename;
845 int snum;
847 if ( !regkey )
848 return WERR_BADFID;
850 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
852 DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
854 if ( (snum = validate_reg_filename( filename )) == -1 )
855 return WERR_OBJECT_PATH_INVALID;
857 /* user must posses SeRestorePrivilege for this this proceed */
859 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
860 return WERR_ACCESS_DENIED;
862 DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
864 return restore_registry_key( regkey, filename );
867 /********************************************************************
868 ********************************************************************/
870 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
871 REGF_NK_REC *parent, SEC_DESC *sec_desc )
873 REGF_NK_REC *key;
874 REGVAL_CTR *values;
875 REGSUBKEY_CTR *subkeys;
876 int i, num_subkeys;
877 pstring key_tmp;
878 char *keyname, *parentpath;
879 pstring subkeypath;
880 char *subkeyname;
881 REGISTRY_KEY registry_key;
882 WERROR result = WERR_OK;
884 if ( !regfile )
885 return WERR_GENERAL_FAILURE;
887 if ( !keypath )
888 return WERR_OBJECT_PATH_INVALID;
890 /* split up the registry key path */
892 pstrcpy( key_tmp, keypath );
893 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
894 return WERR_OBJECT_PATH_INVALID;
896 if ( !keyname )
897 keyname = parentpath;
899 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
901 ZERO_STRUCT( registry_key );
902 pstrcpy( registry_key.name, keypath );
903 if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
904 return WERR_BADFILE;
907 /* lookup the values and subkeys */
909 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
910 return WERR_NOMEM;
912 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
913 return WERR_NOMEM;
915 fetch_reg_keys( &registry_key, subkeys );
916 fetch_reg_values( &registry_key, values );
918 /* write out this key */
920 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
921 result = WERR_CAN_NOT_COMPLETE;
922 goto done;
925 /* write each one of the subkeys out */
927 num_subkeys = regsubkey_ctr_numkeys( subkeys );
928 for ( i=0; i<num_subkeys; i++ ) {
929 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
930 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
931 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
932 if ( !W_ERROR_IS_OK(result) )
933 goto done;
936 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
938 done:
939 TALLOC_FREE( subkeys );
941 return result;
944 /*******************************************************************
945 ********************************************************************/
947 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
949 DOM_SID adm_sid, owner_sid;
950 SEC_ACE ace[2]; /* at most 2 entries */
951 SEC_ACCESS mask;
952 SEC_ACL *psa = NULL;
953 size_t sd_size;
955 /* set the owner to BUILTIN\Administrator */
957 sid_copy(&owner_sid, &global_sid_Builtin);
958 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
961 /* basic access for Everyone */
963 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
964 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
966 /* add Full Access 'BUILTIN\Administrators' */
968 init_sec_access(&mask, reg_generic_map.generic_all);
969 sid_copy(&adm_sid, &global_sid_Builtin);
970 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
971 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
973 /* create the security descriptor */
975 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
976 return WERR_NOMEM;
978 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
979 return WERR_NOMEM;
981 return WERR_OK;
984 /*******************************************************************
985 ********************************************************************/
987 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
989 REGF_FILE *regfile;
990 WERROR result;
991 SEC_DESC *sd = NULL;
993 /* open the registry file....fail if the file already exists */
995 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
996 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
997 fname, strerror(errno) ));
998 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1001 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1002 regfio_close( regfile );
1003 return result;
1006 /* write the registry tree to the file */
1008 result = reg_write_tree( regfile, krecord->name, NULL, sd );
1010 /* cleanup */
1012 regfio_close( regfile );
1014 return result;
1017 /*******************************************************************
1018 ********************************************************************/
1020 WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
1022 REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1023 pstring filename;
1024 int snum;
1026 if ( !regkey )
1027 return WERR_BADFID;
1029 rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1031 DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1033 if ( (snum = validate_reg_filename( filename )) == -1 )
1034 return WERR_OBJECT_PATH_INVALID;
1036 DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1038 return backup_registry_key( regkey, filename );
1041 /*******************************************************************
1042 ********************************************************************/
1044 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
1046 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1047 REGISTRY_KEY *newparentinfo, *keyinfo;
1048 POLICY_HND newparent_handle;
1049 REGSUBKEY_CTR *subkeys;
1050 BOOL write_result;
1051 pstring name;
1052 WERROR result;
1054 if ( !parent )
1055 return WERR_BADFID;
1057 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1059 /* ok. Here's what we do. */
1061 if ( strrchr( name, '\\' ) ) {
1062 pstring newkeyname;
1063 char *ptr;
1065 /* (1) check for enumerate rights on the parent handle. CLients can try
1066 create things like 'SOFTWARE\Samba' on the HKLM handle.
1067 (2) open the path to the child parent key if necessary */
1069 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1070 return WERR_ACCESS_DENIED;
1072 pstrcpy( newkeyname, name );
1073 ptr = strrchr( newkeyname, '\\' );
1074 *ptr = '\0';
1076 result = open_registry_key( p, &newparent_handle, &newparentinfo,
1077 parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1079 if ( !W_ERROR_IS_OK(result) )
1080 return result;
1082 /* copy the new key name (just the lower most keyname) */
1084 pstrcpy( name, ptr+1 );
1086 else {
1087 /* use the existing open key information */
1088 newparentinfo = parent;
1089 memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
1092 /* (3) check for create subkey rights on the correct parent */
1094 if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1095 result = WERR_ACCESS_DENIED;
1096 goto done;
1099 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1100 result = WERR_NOMEM;
1101 goto done;
1104 /* (4) lookup the current keys and add the new one */
1106 fetch_reg_keys( newparentinfo, subkeys );
1107 regsubkey_ctr_addkey( subkeys, name );
1109 /* now write to the registry backend */
1111 write_result = store_reg_keys( newparentinfo, subkeys );
1113 TALLOC_FREE( subkeys );
1115 if ( !write_result )
1116 return WERR_REG_IO_FAILURE;
1118 /* (5) open the new key and return the handle. Note that it is probably
1119 not correct to grant full access on this open handle. */
1121 result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1122 keyinfo->access_granted = REG_KEY_ALL;
1124 done:
1125 /* close any intermediate key handles */
1127 if ( newparentinfo != parent )
1128 close_registry_key( p, &newparent_handle );
1130 return result;
1134 /*******************************************************************
1135 ********************************************************************/
1137 WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r_u)
1139 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1140 REGVAL_CTR *values;
1141 BOOL write_result;
1142 fstring valuename;
1144 if ( !key )
1145 return WERR_BADFID;
1147 /* access checks first */
1149 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1150 return WERR_ACCESS_DENIED;
1152 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1154 /* verify the name */
1156 if ( !*valuename )
1157 return WERR_INVALID_PARAM;
1159 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1161 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1162 return WERR_NOMEM;
1164 /* lookup the current values and add the new one */
1166 fetch_reg_values( key, values );
1168 regval_ctr_addvalue( values, valuename, q_u->type, (char*)q_u->value.buffer, q_u->value.buf_len );
1170 /* now write to the registry backend */
1172 write_result = store_reg_values( key, values );
1174 TALLOC_FREE( values );
1176 if ( !write_result )
1177 return WERR_REG_IO_FAILURE;
1179 return WERR_OK;
1182 /*******************************************************************
1183 ********************************************************************/
1185 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
1187 REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
1188 REGISTRY_KEY *newparentinfo;
1189 POLICY_HND newparent_handle;
1190 REGSUBKEY_CTR *subkeys;
1191 BOOL write_result;
1192 pstring name;
1193 WERROR result;
1195 if ( !parent )
1196 return WERR_BADFID;
1198 /* MSDN says parent the handle must have been opened with DELETE access */
1200 /* (1) check for delete rights on the parent */
1202 if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1203 result = WERR_ACCESS_DENIED;
1204 goto done;
1207 rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
1209 /* ok. Here's what we do. */
1211 if ( strrchr( name, '\\' ) ) {
1212 pstring newkeyname;
1213 char *ptr;
1215 /* (2) open the path to the child parent key if necessary */
1216 /* split the registry path and save the subkeyname */
1218 pstrcpy( newkeyname, name );
1219 ptr = strrchr( newkeyname, '\\' );
1220 *ptr = '\0';
1221 pstrcpy( name, ptr+1 );
1223 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1224 if ( !W_ERROR_IS_OK(result) )
1225 return result;
1227 else {
1228 /* use the existing open key information */
1229 newparentinfo = parent;
1232 if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1233 result = WERR_NOMEM;
1234 goto done;
1237 /* lookup the current keys and delete the new one */
1239 fetch_reg_keys( newparentinfo, subkeys );
1241 regsubkey_ctr_delkey( subkeys, name );
1243 /* now write to the registry backend */
1245 write_result = store_reg_keys( newparentinfo, subkeys );
1247 TALLOC_FREE( subkeys );
1249 result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1251 done:
1252 /* close any intermediate key handles */
1254 if ( newparentinfo != parent )
1255 close_registry_key( p, &newparent_handle );
1257 return result;
1261 /*******************************************************************
1262 ********************************************************************/
1264 WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE *q_u, REG_R_DELETE_VALUE *r_u)
1266 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1267 REGVAL_CTR *values;
1268 BOOL write_result;
1269 fstring valuename;
1271 if ( !key )
1272 return WERR_BADFID;
1274 /* access checks first */
1276 if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1277 return WERR_ACCESS_DENIED;
1279 rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
1281 if ( !*valuename )
1282 return WERR_INVALID_PARAM;
1284 DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1286 if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1287 return WERR_NOMEM;
1289 /* lookup the current values and add the new one */
1291 fetch_reg_values( key, values );
1293 regval_ctr_delvalue( values, valuename );
1295 /* now write to the registry backend */
1297 write_result = store_reg_values( key, values );
1299 TALLOC_FREE( values );
1301 if ( !write_result )
1302 return WERR_REG_IO_FAILURE;
1304 return WERR_OK;
1307 /*******************************************************************
1308 ********************************************************************/
1310 WERROR _reg_get_key_sec(pipes_struct *p, REG_Q_GET_KEY_SEC *q_u, REG_R_GET_KEY_SEC *r_u)
1312 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1314 if ( !key )
1315 return WERR_BADFID;
1317 /* access checks first */
1319 if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1320 return WERR_ACCESS_DENIED;
1322 return WERR_ACCESS_DENIED;
1325 /*******************************************************************
1326 ********************************************************************/
1328 WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_SEC *r_u)
1330 REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
1332 if ( !key )
1333 return WERR_BADFID;
1335 /* access checks first */
1337 if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1338 return WERR_ACCESS_DENIED;
1340 return WERR_ACCESS_DENIED;