r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / rpc_server / srv_winreg_nt.c
blob1fa61c27ca19c01bc4a02c9588616c1defce8006
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 *
5 * Copyright (C) Gerald Carter 2002-2006.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* Implementation of registry functions. */
24 #include "includes.h"
25 #include "regfio.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_SRV
30 static struct generic_mapping reg_generic_map =
31 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
33 /******************************************************************
34 free() function for struct registry_key
35 *****************************************************************/
37 static void free_regkey(void *ptr)
39 struct registry_key *key = (struct registry_key *)ptr;
40 TALLOC_FREE(key);
43 /******************************************************************
44 Find a registry key handle and return a REGISTRY_KEY
45 *****************************************************************/
47 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
48 POLICY_HND *hnd)
50 struct registry_key *regkey = NULL;
52 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
53 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
54 return NULL;
57 return regkey;
60 /*******************************************************************
61 Function for open a new registry handle and creating a handle
62 Note that P should be valid & hnd should already have space
64 When we open a key, we store the full path to the key as
65 HK[LM|U]\<key>\<key>\...
66 *******************************************************************/
68 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
69 struct registry_key *parent,
70 const char *subkeyname,
71 uint32 access_desired )
73 WERROR result = WERR_OK;
74 struct registry_key *key;
76 if (parent == NULL) {
77 result = reg_openhive(NULL, subkeyname, access_desired,
78 p->pipe_user.nt_user_token, &key);
80 else {
81 result = reg_openkey(NULL, parent, subkeyname, access_desired,
82 &key);
85 if ( !W_ERROR_IS_OK(result) ) {
86 return result;
89 if ( !create_policy_hnd( p, hnd, free_regkey, key ) ) {
90 return WERR_BADFILE;
93 return WERR_OK;
96 /*******************************************************************
97 Function for open a new registry handle and creating a handle
98 Note that P should be valid & hnd should already have space
99 *******************************************************************/
101 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
103 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
105 if ( !regkey ) {
106 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
107 OUR_HANDLE(hnd)));
108 return False;
111 close_policy_hnd(p, hnd);
113 return True;
116 /********************************************************************
117 reg_close
118 ********************************************************************/
120 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
122 /* close the policy handle */
124 if (!close_registry_key(p, r->in.handle))
125 return WERR_BADFID;
127 ZERO_STRUCTP(r->out.handle);
129 return WERR_OK;
132 /*******************************************************************
133 ********************************************************************/
135 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
137 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
140 /*******************************************************************
141 ********************************************************************/
143 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
145 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
148 /*******************************************************************
149 ********************************************************************/
151 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
153 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
156 /*******************************************************************
157 ********************************************************************/
159 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
161 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
164 /*******************************************************************
165 ********************************************************************/
167 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
169 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
172 /*******************************************************************
173 ********************************************************************/
175 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
177 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
180 /*******************************************************************
181 ********************************************************************/
183 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
185 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
188 /*******************************************************************
189 ********************************************************************/
191 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
193 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
196 /*******************************************************************
197 ********************************************************************/
199 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
201 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
204 /*******************************************************************
205 reg_reply_open_entry
206 ********************************************************************/
208 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
210 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
212 if ( !parent )
213 return WERR_BADFID;
215 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
218 /*******************************************************************
219 reg_reply_info
220 ********************************************************************/
222 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
224 WERROR status = WERR_BADFILE;
225 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
226 prs_struct prs_hkpd;
228 uint8_t *outbuf;
229 uint32_t outbuf_size;
231 DATA_BLOB val_blob;
232 BOOL free_buf = False;
233 BOOL free_prs = False;
235 if ( !regkey )
236 return WERR_BADFID;
238 *r->out.value_length = *r->out.type = 0;
240 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->key->name));
241 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->key->type));
243 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
244 if(regkey->key->type == REG_KEY_HKPD)
246 if(strequal(r->in.value_name.name, "Global")) {
247 prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL);
248 status = reg_perfcount_get_hkpd(
249 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
250 outbuf = (uint8_t *)prs_hkpd.data_p;
251 free_prs = True;
253 else if(strequal(r->in.value_name.name, "Counter 009")) {
254 outbuf_size = reg_perfcount_get_counter_names(
255 reg_perfcount_get_base_index(),
256 (char **)(void *)&outbuf);
257 free_buf = True;
259 else if(strequal(r->in.value_name.name, "Explain 009")) {
260 outbuf_size = reg_perfcount_get_counter_help(
261 reg_perfcount_get_base_index(),
262 (char **)(void *)&outbuf);
263 free_buf = True;
265 else if(isdigit(r->in.value_name.name[0])) {
266 /* we probably have a request for a specific object
267 * here */
268 prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL);
269 status = reg_perfcount_get_hkpd(
270 &prs_hkpd, *r->in.data_size, &outbuf_size,
271 r->in.value_name.name);
272 outbuf = (uint8_t *)prs_hkpd.data_p;
273 free_prs = True;
275 else {
276 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
277 r->in.value_name.name));
278 return WERR_BADFILE;
281 *r->out.type = REG_BINARY;
283 else {
284 struct registry_value *val;
286 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name.name,
287 &val);
288 if (!W_ERROR_IS_OK(status)) {
289 if (r->out.data_size) {
290 *r->out.data_size = 0;
292 if (r->out.value_length) {
293 *r->out.value_length = 0;
295 return status;
298 status = registry_push_value(p->mem_ctx, val, &val_blob);
299 if (!W_ERROR_IS_OK(status)) {
300 return status;
303 outbuf = val_blob.data;
304 outbuf_size = val_blob.length;
305 *r->out.type = val->type;
308 *r->out.value_length = outbuf_size;
310 if ( *r->in.data_size == 0 || !r->out.data ) {
311 status = WERR_OK;
312 } else if ( *r->out.value_length > *r->in.data_size ) {
313 status = WERR_MORE_DATA;
314 } else {
315 memcpy( r->out.data, outbuf, *r->out.value_length );
316 status = WERR_OK;
319 *r->out.data_size = *r->out.value_length;
321 if (free_prs) prs_mem_free(&prs_hkpd);
322 if (free_buf) SAFE_FREE(outbuf);
324 return status;
327 /*****************************************************************************
328 Implementation of REG_QUERY_KEY
329 ****************************************************************************/
331 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
333 WERROR status = WERR_OK;
334 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
336 if ( !regkey )
337 return WERR_BADFID;
339 r->out.classname->name = NULL;
341 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
342 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
343 r->out.max_valbufsize, r->out.secdescsize,
344 r->out.last_changed_time);
345 if (!W_ERROR_IS_OK(status)) {
346 return status;
350 * These calculations account for the registry buffers being
351 * UTF-16. They are inexact at best, but so far they worked.
354 *r->out.max_subkeylen *= 2;
356 *r->out.max_valnamelen += 1;
357 *r->out.max_valnamelen *= 2;
359 return WERR_OK;
363 /*****************************************************************************
364 Implementation of REG_GETVERSION
365 ****************************************************************************/
367 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
369 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
371 if ( !regkey )
372 return WERR_BADFID;
374 *r->out.version = 0x00000005; /* Windows 2000 registry API version */
376 return WERR_OK;
380 /*****************************************************************************
381 Implementation of REG_ENUM_KEY
382 ****************************************************************************/
384 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
386 WERROR err;
387 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
389 if ( !key )
390 return WERR_BADFID;
392 if ( !r->in.name || !r->in.keyclass )
393 return WERR_INVALID_PARAM;
395 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
397 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
398 r->out.last_changed_time);
399 if (!W_ERROR_IS_OK(err)) {
400 return err;
402 r->out.keyclass->name = "";
403 return WERR_OK;
406 /*****************************************************************************
407 Implementation of REG_ENUM_VALUE
408 ****************************************************************************/
410 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
412 WERROR err;
413 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
414 char *valname;
415 struct registry_value *val;
416 DATA_BLOB value_blob;
418 if ( !key )
419 return WERR_BADFID;
421 if ( !r->in.name )
422 return WERR_INVALID_PARAM;
424 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
425 key->key->name));
427 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
428 if (!W_ERROR_IS_OK(err)) {
429 return err;
432 err = registry_push_value(p->mem_ctx, val, &value_blob);
433 if (!W_ERROR_IS_OK(err)) {
434 return err;
437 if (r->out.name != NULL) {
438 r->out.name->name = valname;
441 if (r->out.type != NULL) {
442 *r->out.type = val->type;
445 if (r->out.value != NULL) {
446 if ((r->out.size == NULL) || (r->out.length == NULL)) {
447 return WERR_INVALID_PARAM;
450 if (value_blob.length > *r->out.size) {
451 return WERR_MORE_DATA;
454 memcpy( r->out.value, value_blob.data, value_blob.length );
457 if (r->out.length != NULL) {
458 *r->out.length = value_blob.length;
460 if (r->out.size != NULL) {
461 *r->out.size = value_blob.length;
464 return WERR_OK;
467 /*******************************************************************
468 reg_shutdwon
469 ********************************************************************/
471 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
473 struct winreg_InitiateSystemShutdownEx s;
475 s.in.hostname = r->in.hostname;
476 s.in.message = r->in.message;
477 s.in.timeout = r->in.timeout;
478 s.in.force_apps = r->in.force_apps;
479 s.in.reboot = r->in.reboot;
480 s.in.reason = 0;
482 /* thunk down to _winreg_InitiateSystemShutdownEx()
483 (just returns a status) */
485 return _winreg_InitiateSystemShutdownEx( p, &s );
488 /*******************************************************************
489 reg_shutdown_ex
490 ********************************************************************/
492 #define SHUTDOWN_R_STRING "-r"
493 #define SHUTDOWN_F_STRING "-f"
496 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
498 pstring shutdown_script;
499 char *msg = NULL;
500 pstring chkmsg;
501 fstring str_timeout;
502 fstring str_reason;
503 fstring reboot;
504 fstring f;
505 int ret;
506 BOOL can_shutdown;
509 pstrcpy(shutdown_script, lp_shutdown_script());
511 if ( !*shutdown_script )
512 return WERR_ACCESS_DENIED;
514 /* pull the message string and perform necessary sanity checks on it */
516 chkmsg[0] = '\0';
518 if ( r->in.message && r->in.message->name && r->in.message->name->name ) {
519 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->name->name )) == NULL ) {
520 return WERR_NOMEM;
522 alpha_strcpy (chkmsg, msg, NULL, sizeof(chkmsg));
525 fstr_sprintf(str_timeout, "%d", r->in.timeout);
526 fstr_sprintf(reboot, r->in.reboot ? SHUTDOWN_R_STRING : "");
527 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
528 fstr_sprintf(str_reason, "%d", r->in.reason );
530 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
531 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
532 all_string_sub( shutdown_script, "%r", reboot, sizeof(shutdown_script) );
533 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
534 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
536 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
538 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
539 Take the error return from the script and provide it as the Windows return code. */
541 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
543 if ( can_shutdown )
544 become_root();
546 ret = smbrun( shutdown_script, NULL );
548 if ( can_shutdown )
549 unbecome_root();
551 /********** END SeRemoteShutdownPrivilege BLOCK **********/
553 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
554 shutdown_script, ret));
557 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
563 /*******************************************************************
564 reg_abort_shutdwon
565 ********************************************************************/
567 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
569 pstring abort_shutdown_script;
570 int ret;
571 BOOL can_shutdown;
573 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
575 if ( !*abort_shutdown_script )
576 return WERR_ACCESS_DENIED;
578 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
580 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
582 if ( can_shutdown )
583 become_root();
585 ret = smbrun( abort_shutdown_script, NULL );
587 if ( can_shutdown )
588 unbecome_root();
590 /********** END SeRemoteShutdownPrivilege BLOCK **********/
592 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
593 abort_shutdown_script, ret));
596 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
599 /*******************************************************************
600 ********************************************************************/
602 static int validate_reg_filename( pstring fname )
604 char *p;
605 int num_services = lp_numservices();
606 int snum;
607 pstring share_path;
608 pstring unix_fname;
610 /* convert to a unix path, stripping the C:\ along the way */
612 if ( !(p = valid_share_pathname( fname ) ))
613 return -1;
615 /* has to exist within a valid file share */
617 for ( snum=0; snum<num_services; snum++ ) {
619 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
620 continue;
622 pstrcpy( share_path, lp_pathname(snum) );
624 /* make sure we have a path (e.g. [homes] ) */
626 if ( strlen( share_path ) == 0 )
627 continue;
629 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
630 break;
633 /* p and fname are overlapping memory so copy out and back in again */
635 pstrcpy( unix_fname, p );
636 pstrcpy( fname, unix_fname );
638 return (snum < num_services) ? snum : -1;
641 /*******************************************************************
642 Note: topkeypat is the *full* path that this *key will be
643 loaded into (including the name of the key)
644 ********************************************************************/
646 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
647 REGF_NK_REC *key )
649 REGF_NK_REC *subkey;
650 REGISTRY_KEY registry_key;
651 REGVAL_CTR *values;
652 REGSUBKEY_CTR *subkeys;
653 int i;
654 pstring path;
655 WERROR result = WERR_OK;
657 /* initialize the REGISTRY_KEY structure */
659 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
660 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
661 topkeypath ));
662 return WERR_BADFILE;
665 registry_key.name = talloc_strdup( regfile->mem_ctx, topkeypath );
666 if ( !registry_key.name ) {
667 DEBUG(0,("reg_load_tree: Talloc failed for reg_key.name!\n"));
668 return WERR_NOMEM;
671 /* now start parsing the values and subkeys */
673 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
674 return WERR_NOMEM;
676 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
677 return WERR_NOMEM;
679 /* copy values into the REGVAL_CTR */
681 for ( i=0; i<key->num_values; i++ ) {
682 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
683 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
686 /* copy subkeys into the REGSUBKEY_CTR */
688 key->subkey_index = 0;
689 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
690 regsubkey_ctr_addkey( subkeys, subkey->keyname );
693 /* write this key and values out */
695 if ( !store_reg_values( &registry_key, values )
696 || !store_reg_keys( &registry_key, subkeys ) )
698 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
699 result = WERR_REG_IO_FAILURE;
702 TALLOC_FREE( subkeys );
704 if ( !W_ERROR_IS_OK(result) )
705 return result;
707 /* now continue to load each subkey registry tree */
709 key->subkey_index = 0;
710 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
711 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
712 result = reg_load_tree( regfile, path, subkey );
713 if ( !W_ERROR_IS_OK(result) )
714 break;
717 return result;
720 /*******************************************************************
721 ********************************************************************/
723 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
725 REGF_FILE *regfile;
726 REGF_NK_REC *rootkey;
727 WERROR result;
729 /* open the registry file....fail if the file already exists */
731 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
732 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
733 fname, strerror(errno) ));
734 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
737 /* get the rootkey from the regf file and then load the tree
738 via recursive calls */
740 if ( !(rootkey = regfio_rootkey( regfile )) ) {
741 regfio_close( regfile );
742 return WERR_REG_FILE_INVALID;
745 result = reg_load_tree( regfile, krecord->name, rootkey );
747 /* cleanup */
749 regfio_close( regfile );
751 return result;
754 /*******************************************************************
755 ********************************************************************/
757 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
759 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
760 pstring fname;
761 int snum;
763 if ( !regkey )
764 return WERR_BADFID;
766 if ( !r->in.filename || !r->in.filename->name )
767 return WERR_INVALID_PARAM;
769 pstrcpy( fname, r->in.filename->name );
771 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
772 "\"%s\"\n", regkey->key->name, fname));
774 if ( (snum = validate_reg_filename( fname )) == -1 )
775 return WERR_OBJECT_PATH_INVALID;
777 /* user must posses SeRestorePrivilege for this this proceed */
779 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
780 return WERR_ACCESS_DENIED;
782 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
783 regkey->key->name, fname, lp_servicename(snum) ));
785 return restore_registry_key( regkey->key, fname );
788 /********************************************************************
789 ********************************************************************/
791 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
792 REGF_NK_REC *parent, SEC_DESC *sec_desc )
794 REGF_NK_REC *key;
795 REGVAL_CTR *values;
796 REGSUBKEY_CTR *subkeys;
797 int i, num_subkeys;
798 pstring key_tmp;
799 char *keyname, *parentpath;
800 pstring subkeypath;
801 char *subkeyname;
802 REGISTRY_KEY registry_key;
803 WERROR result = WERR_OK;
805 if ( !regfile )
806 return WERR_GENERAL_FAILURE;
808 if ( !keypath )
809 return WERR_OBJECT_PATH_INVALID;
811 /* split up the registry key path */
813 pstrcpy( key_tmp, keypath );
814 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
815 return WERR_OBJECT_PATH_INVALID;
817 if ( !keyname )
818 keyname = parentpath;
820 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
822 ZERO_STRUCT( registry_key );
824 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
825 return WERR_NOMEM;
827 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
828 return WERR_BADFILE;
830 /* lookup the values and subkeys */
832 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
833 return WERR_NOMEM;
835 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
836 return WERR_NOMEM;
838 fetch_reg_keys( &registry_key, subkeys );
839 fetch_reg_values( &registry_key, values );
841 /* write out this key */
843 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
844 result = WERR_CAN_NOT_COMPLETE;
845 goto done;
848 /* write each one of the subkeys out */
850 num_subkeys = regsubkey_ctr_numkeys( subkeys );
851 for ( i=0; i<num_subkeys; i++ ) {
852 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
853 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
854 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
855 if ( !W_ERROR_IS_OK(result) )
856 goto done;
859 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
861 done:
862 TALLOC_FREE( subkeys );
863 TALLOC_FREE( registry_key.name );
865 return result;
868 /*******************************************************************
869 ********************************************************************/
871 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
873 DOM_SID adm_sid, owner_sid;
874 SEC_ACE ace[2]; /* at most 2 entries */
875 SEC_ACCESS mask;
876 SEC_ACL *psa = NULL;
877 size_t sd_size;
879 /* set the owner to BUILTIN\Administrator */
881 sid_copy(&owner_sid, &global_sid_Builtin);
882 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
885 /* basic access for Everyone */
887 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
888 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
890 /* add Full Access 'BUILTIN\Administrators' */
892 init_sec_access(&mask, reg_generic_map.generic_all);
893 sid_copy(&adm_sid, &global_sid_Builtin);
894 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
895 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
897 /* create the security descriptor */
899 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
900 return WERR_NOMEM;
902 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
903 return WERR_NOMEM;
905 return WERR_OK;
908 /*******************************************************************
909 ********************************************************************/
911 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
913 REGF_FILE *regfile;
914 WERROR result;
915 SEC_DESC *sd = NULL;
917 /* open the registry file....fail if the file already exists */
919 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
920 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
921 fname, strerror(errno) ));
922 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
925 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
926 regfio_close( regfile );
927 return result;
930 /* write the registry tree to the file */
932 result = reg_write_tree( regfile, krecord->name, NULL, sd );
934 /* cleanup */
936 regfio_close( regfile );
938 return result;
941 /*******************************************************************
942 ********************************************************************/
944 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
946 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
947 pstring fname;
948 int snum;
950 if ( !regkey )
951 return WERR_BADFID;
953 if ( !r->in.filename || !r->in.filename->name )
954 return WERR_INVALID_PARAM;
956 pstrcpy( fname, r->in.filename->name );
958 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
959 regkey->key->name, fname));
961 if ( (snum = validate_reg_filename( fname )) == -1 )
962 return WERR_OBJECT_PATH_INVALID;
964 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
965 regkey->key->name, fname, lp_servicename(snum) ));
967 return backup_registry_key( regkey->key, fname );
970 /*******************************************************************
971 ********************************************************************/
973 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
975 /* fill in your code here if you think this call should
976 do anything */
978 p->rng_fault_state = True;
979 return WERR_NOT_SUPPORTED;
982 /*******************************************************************
983 ********************************************************************/
985 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
987 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
988 struct registry_key *new_key;
989 WERROR result;
991 if ( !parent )
992 return WERR_BADFID;
994 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
995 &new_key, r->out.action_taken);
996 if (!W_ERROR_IS_OK(result)) {
997 return result;
1000 if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
1001 TALLOC_FREE(new_key);
1002 return WERR_BADFILE;
1005 return WERR_OK;
1008 /*******************************************************************
1009 ********************************************************************/
1011 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
1013 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1014 struct registry_value *val;
1015 WERROR status;
1017 if ( !key )
1018 return WERR_BADFID;
1020 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
1021 key->key->name, r->in.name.name));
1023 status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
1024 r->in.size, r->in.size);
1025 if (!W_ERROR_IS_OK(status)) {
1026 return status;
1029 return reg_setvalue(key, r->in.name.name, val);
1032 /*******************************************************************
1033 ********************************************************************/
1035 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
1037 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1039 if ( !parent )
1040 return WERR_BADFID;
1042 return reg_deletekey(parent, r->in.key.name);
1046 /*******************************************************************
1047 ********************************************************************/
1049 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
1051 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1053 if ( !key )
1054 return WERR_BADFID;
1056 return reg_deletevalue(key, r->in.value.name);
1059 /*******************************************************************
1060 ********************************************************************/
1062 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
1064 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1065 WERROR err;
1066 struct security_descriptor *secdesc;
1067 uint8 *data;
1068 size_t len;
1070 if ( !key )
1071 return WERR_BADFID;
1073 /* access checks first */
1075 if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1076 return WERR_ACCESS_DENIED;
1078 err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1079 if (!W_ERROR_IS_OK(err)) {
1080 return err;
1083 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1084 &data, &len));
1085 if (!W_ERROR_IS_OK(err)) {
1086 return err;
1089 if (len > r->out.sd->size) {
1090 r->out.sd->size = len;
1091 return WERR_INSUFFICIENT_BUFFER;
1094 r->out.sd->size = len;
1095 r->out.sd->len = len;
1096 r->out.sd->data = data;
1098 return WERR_OK;
1101 /*******************************************************************
1102 ********************************************************************/
1104 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
1106 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1107 struct security_descriptor *secdesc;
1108 WERROR err;
1110 if ( !key )
1111 return WERR_BADFID;
1113 /* access checks first */
1115 if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1116 return WERR_ACCESS_DENIED;
1118 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
1119 r->in.sd->len, &secdesc));
1120 if (!W_ERROR_IS_OK(err)) {
1121 return err;
1124 return regkey_set_secdesc(key->key, secdesc);
1127 /*******************************************************************
1128 ********************************************************************/
1130 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
1132 /* I'm just replying OK because there's not a lot
1133 here I see to do i --jerry */
1135 return WERR_OK;
1138 /*******************************************************************
1139 ********************************************************************/
1141 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
1143 /* fill in your code here if you think this call should
1144 do anything */
1146 p->rng_fault_state = True;
1147 return WERR_NOT_SUPPORTED;
1150 /*******************************************************************
1151 ********************************************************************/
1153 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
1155 /* fill in your code here if you think this call should
1156 do anything */
1158 p->rng_fault_state = True;
1159 return WERR_NOT_SUPPORTED;
1162 /*******************************************************************
1163 ********************************************************************/
1165 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
1167 /* fill in your code here if you think this call should
1168 do anything */
1170 p->rng_fault_state = True;
1171 return WERR_NOT_SUPPORTED;
1174 /*******************************************************************
1175 ********************************************************************/
1177 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
1179 /* fill in your code here if you think this call should
1180 do anything */
1182 p->rng_fault_state = True;
1183 return WERR_NOT_SUPPORTED;
1186 /*******************************************************************
1187 ********************************************************************/
1189 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
1191 /* fill in your code here if you think this call should
1192 do anything */
1194 p->rng_fault_state = True;
1195 return WERR_NOT_SUPPORTED;
1198 /*******************************************************************
1199 ********************************************************************/
1201 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
1203 /* fill in your code here if you think this call should
1204 do anything */
1206 p->rng_fault_state = True;
1207 return WERR_NOT_SUPPORTED;