Some C++ warnings
[Samba.git] / source / rpc_server / srv_winreg_nt.c
blob7dd5268088c075e4a9f25ab3638586d5df274500
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 3 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, see <http://www.gnu.org/licenses/>.
21 /* Implementation of registry functions. */
23 #include "includes.h"
24 #include "regfio.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_SRV
29 static const struct generic_mapping reg_generic_map =
30 { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
32 /******************************************************************
33 free() function for struct registry_key
34 *****************************************************************/
36 static void free_regkey(void *ptr)
38 struct registry_key *key = (struct registry_key *)ptr;
39 TALLOC_FREE(key);
42 /******************************************************************
43 Find a registry key handle and return a REGISTRY_KEY
44 *****************************************************************/
46 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
47 POLICY_HND *hnd)
49 struct registry_key *regkey = NULL;
51 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
52 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
53 return NULL;
56 return regkey;
59 /*******************************************************************
60 Function for open a new registry handle and creating a handle
61 Note that P should be valid & hnd should already have space
63 When we open a key, we store the full path to the key as
64 HK[LM|U]\<key>\<key>\...
65 *******************************************************************/
67 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
68 struct registry_key *parent,
69 const char *subkeyname,
70 uint32 access_desired )
72 WERROR result = WERR_OK;
73 struct registry_key *key;
75 if (parent == NULL) {
76 result = reg_openhive(NULL, subkeyname, access_desired,
77 p->pipe_user.nt_user_token, &key);
79 else {
80 result = reg_openkey(NULL, parent, subkeyname, access_desired,
81 &key);
84 if ( !W_ERROR_IS_OK(result) ) {
85 return result;
88 if ( !create_policy_hnd( p, hnd, free_regkey, key ) ) {
89 return WERR_BADFILE;
92 return WERR_OK;
95 /*******************************************************************
96 Function for open a new registry handle and creating a handle
97 Note that P should be valid & hnd should already have space
98 *******************************************************************/
100 static bool close_registry_key(pipes_struct *p, POLICY_HND *hnd)
102 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
104 if ( !regkey ) {
105 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
106 OUR_HANDLE(hnd)));
107 return False;
110 close_policy_hnd(p, hnd);
112 return True;
115 /********************************************************************
116 reg_close
117 ********************************************************************/
119 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
121 /* close the policy handle */
123 if (!close_registry_key(p, r->in.handle))
124 return WERR_BADFID;
126 ZERO_STRUCTP(r->out.handle);
128 return WERR_OK;
131 /*******************************************************************
132 ********************************************************************/
134 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
136 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
139 /*******************************************************************
140 ********************************************************************/
142 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
144 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
147 /*******************************************************************
148 ********************************************************************/
150 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
152 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
155 /*******************************************************************
156 ********************************************************************/
158 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
160 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
163 /*******************************************************************
164 ********************************************************************/
166 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
168 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
171 /*******************************************************************
172 ********************************************************************/
174 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
176 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
179 /*******************************************************************
180 ********************************************************************/
182 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
184 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
187 /*******************************************************************
188 ********************************************************************/
190 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
192 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
195 /*******************************************************************
196 ********************************************************************/
198 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
200 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
203 /*******************************************************************
204 reg_reply_open_entry
205 ********************************************************************/
207 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
209 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
211 if ( !parent )
212 return WERR_BADFID;
214 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
217 /*******************************************************************
218 reg_reply_info
219 ********************************************************************/
221 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
223 WERROR status = WERR_BADFILE;
224 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
225 prs_struct prs_hkpd;
227 uint8_t *outbuf;
228 uint32_t outbuf_size;
230 DATA_BLOB val_blob;
231 bool free_buf = False;
232 bool free_prs = False;
234 if ( !regkey )
235 return WERR_BADFID;
237 *r->out.value_length = *r->out.type = REG_NONE;
239 DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->key->name));
240 DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->key->type));
242 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
243 if(regkey->key->type == REG_KEY_HKPD)
245 if(strequal(r->in.value_name.name, "Global")) {
246 prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL);
247 status = reg_perfcount_get_hkpd(
248 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
249 outbuf = (uint8_t *)prs_hkpd.data_p;
250 free_prs = True;
252 else if(strequal(r->in.value_name.name, "Counter 009")) {
253 outbuf_size = reg_perfcount_get_counter_names(
254 reg_perfcount_get_base_index(),
255 (char **)(void *)&outbuf);
256 free_buf = True;
258 else if(strequal(r->in.value_name.name, "Explain 009")) {
259 outbuf_size = reg_perfcount_get_counter_help(
260 reg_perfcount_get_base_index(),
261 (char **)(void *)&outbuf);
262 free_buf = True;
264 else if(isdigit(r->in.value_name.name[0])) {
265 /* we probably have a request for a specific object
266 * here */
267 prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL);
268 status = reg_perfcount_get_hkpd(
269 &prs_hkpd, *r->in.data_size, &outbuf_size,
270 r->in.value_name.name);
271 outbuf = (uint8_t *)prs_hkpd.data_p;
272 free_prs = True;
274 else {
275 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
276 r->in.value_name.name));
277 return WERR_BADFILE;
280 *r->out.type = REG_BINARY;
282 else {
283 struct registry_value *val;
285 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name.name,
286 &val);
287 if (!W_ERROR_IS_OK(status)) {
288 if (r->out.data_size) {
289 *r->out.data_size = 0;
291 if (r->out.value_length) {
292 *r->out.value_length = 0;
294 return status;
297 status = registry_push_value(p->mem_ctx, val, &val_blob);
298 if (!W_ERROR_IS_OK(status)) {
299 return status;
302 outbuf = val_blob.data;
303 outbuf_size = val_blob.length;
304 *r->out.type = val->type;
307 *r->out.value_length = outbuf_size;
309 if ( *r->in.data_size == 0 || !r->out.data ) {
310 status = WERR_OK;
311 } else if ( *r->out.value_length > *r->in.data_size ) {
312 status = WERR_MORE_DATA;
313 } else {
314 memcpy( r->out.data, outbuf, *r->out.value_length );
315 status = WERR_OK;
318 *r->out.data_size = *r->out.value_length;
320 if (free_prs) prs_mem_free(&prs_hkpd);
321 if (free_buf) SAFE_FREE(outbuf);
323 return status;
326 /*****************************************************************************
327 Implementation of REG_QUERY_KEY
328 ****************************************************************************/
330 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
332 WERROR status = WERR_OK;
333 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
335 if ( !regkey )
336 return WERR_BADFID;
338 r->out.classname->name = NULL;
340 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
341 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
342 r->out.max_valbufsize, r->out.secdescsize,
343 r->out.last_changed_time);
344 if (!W_ERROR_IS_OK(status)) {
345 return status;
349 * These calculations account for the registry buffers being
350 * UTF-16. They are inexact at best, but so far they worked.
353 *r->out.max_subkeylen *= 2;
355 *r->out.max_valnamelen += 1;
356 *r->out.max_valnamelen *= 2;
358 return WERR_OK;
362 /*****************************************************************************
363 Implementation of REG_GETVERSION
364 ****************************************************************************/
366 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
368 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
370 if ( !regkey )
371 return WERR_BADFID;
373 *r->out.version = 0x00000005; /* Windows 2000 registry API version */
375 return WERR_OK;
379 /*****************************************************************************
380 Implementation of REG_ENUM_KEY
381 ****************************************************************************/
383 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
385 WERROR err;
386 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
388 if ( !key )
389 return WERR_BADFID;
391 if ( !r->in.name || !r->in.keyclass )
392 return WERR_INVALID_PARAM;
394 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
396 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
397 r->out.last_changed_time);
398 if (!W_ERROR_IS_OK(err)) {
399 return err;
401 r->out.keyclass->name = "";
402 return WERR_OK;
405 /*****************************************************************************
406 Implementation of REG_ENUM_VALUE
407 ****************************************************************************/
409 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
411 WERROR err;
412 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
413 char *valname;
414 struct registry_value *val;
415 DATA_BLOB value_blob;
417 if ( !key )
418 return WERR_BADFID;
420 if ( !r->in.name )
421 return WERR_INVALID_PARAM;
423 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
424 key->key->name));
426 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
427 if (!W_ERROR_IS_OK(err)) {
428 return err;
431 err = registry_push_value(p->mem_ctx, val, &value_blob);
432 if (!W_ERROR_IS_OK(err)) {
433 return err;
436 if (r->out.name != NULL) {
437 r->out.name->name = valname;
440 if (r->out.type != NULL) {
441 *r->out.type = val->type;
444 if (r->out.value != NULL) {
445 if ((r->out.size == NULL) || (r->out.length == NULL)) {
446 return WERR_INVALID_PARAM;
449 if (value_blob.length > *r->out.size) {
450 return WERR_MORE_DATA;
453 memcpy( r->out.value, value_blob.data, value_blob.length );
456 if (r->out.length != NULL) {
457 *r->out.length = value_blob.length;
459 if (r->out.size != NULL) {
460 *r->out.size = value_blob.length;
463 return WERR_OK;
466 /*******************************************************************
467 reg_shutdwon
468 ********************************************************************/
470 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
472 struct winreg_InitiateSystemShutdownEx s;
474 s.in.hostname = r->in.hostname;
475 s.in.message = r->in.message;
476 s.in.timeout = r->in.timeout;
477 s.in.force_apps = r->in.force_apps;
478 s.in.reboot = r->in.reboot;
479 s.in.reason = 0;
481 /* thunk down to _winreg_InitiateSystemShutdownEx()
482 (just returns a status) */
484 return _winreg_InitiateSystemShutdownEx( p, &s );
487 /*******************************************************************
488 reg_shutdown_ex
489 ********************************************************************/
491 #define SHUTDOWN_R_STRING "-r"
492 #define SHUTDOWN_F_STRING "-f"
495 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
497 char *shutdown_script = NULL;
498 char *msg = NULL;
499 char *chkmsg = NULL;
500 fstring str_timeout;
501 fstring str_reason;
502 fstring reboot;
503 fstring f;
504 int ret;
505 bool can_shutdown;
507 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
508 if (!shutdown_script) {
509 return WERR_NOMEM;
511 if (!*shutdown_script) {
512 return WERR_ACCESS_DENIED;
515 /* pull the message string and perform necessary sanity checks on it */
517 chkmsg[0] = '\0';
519 if ( r->in.message && r->in.message->name && r->in.message->name->name ) {
520 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->name->name )) == NULL ) {
521 return WERR_NOMEM;
523 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
524 if (!chkmsg) {
525 return WERR_NOMEM;
527 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
530 fstr_sprintf(str_timeout, "%d", r->in.timeout);
531 fstr_sprintf(reboot, r->in.reboot ? SHUTDOWN_R_STRING : "");
532 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
533 fstr_sprintf(str_reason, "%d", r->in.reason );
535 shutdown_script = talloc_all_string_sub(p->mem_ctx,
536 shutdown_script, "%z", chkmsg ? chkmsg : "");
537 if (!shutdown_script) {
538 return WERR_NOMEM;
540 shutdown_script = talloc_all_string_sub(p->mem_ctx,
541 shutdown_script, "%t", str_timeout);
542 if (!shutdown_script) {
543 return WERR_NOMEM;
545 shutdown_script = talloc_all_string_sub(p->mem_ctx,
546 shutdown_script, "%r", reboot);
547 if (!shutdown_script) {
548 return WERR_NOMEM;
550 shutdown_script = talloc_all_string_sub(p->mem_ctx,
551 shutdown_script, "%f", f);
552 if (!shutdown_script) {
553 return WERR_NOMEM;
555 shutdown_script = talloc_all_string_sub(p->mem_ctx,
556 shutdown_script, "%x", str_reason);
557 if (!shutdown_script) {
558 return WERR_NOMEM;
561 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
563 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
564 Take the error return from the script and provide it as the Windows return code. */
566 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
568 if ( can_shutdown )
569 become_root();
571 ret = smbrun( shutdown_script, NULL );
573 if ( can_shutdown )
574 unbecome_root();
576 /********** END SeRemoteShutdownPrivilege BLOCK **********/
578 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
579 shutdown_script, ret));
581 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
584 /*******************************************************************
585 reg_abort_shutdwon
586 ********************************************************************/
588 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
590 const char *abort_shutdown_script;
591 int ret;
592 bool can_shutdown;
594 abort_shutdown_script = lp_abort_shutdown_script();
596 if (!*abort_shutdown_script)
597 return WERR_ACCESS_DENIED;
599 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
601 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
603 if ( can_shutdown )
604 become_root();
606 ret = smbrun( abort_shutdown_script, NULL );
608 if ( can_shutdown )
609 unbecome_root();
611 /********** END SeRemoteShutdownPrivilege BLOCK **********/
613 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
614 abort_shutdown_script, ret));
616 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
619 /*******************************************************************
620 ********************************************************************/
622 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
624 char *p = NULL;
625 int num_services = lp_numservices();
626 int snum = -1;
627 const char *share_path;
628 char *fname = *pp_fname;
630 /* convert to a unix path, stripping the C:\ along the way */
632 if (!(p = valid_share_pathname(ctx, fname))) {
633 return -1;
636 /* has to exist within a valid file share */
638 for (snum=0; snum<num_services; snum++) {
639 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
640 continue;
643 share_path = lp_pathname(snum);
645 /* make sure we have a path (e.g. [homes] ) */
646 if (strlen(share_path) == 0) {
647 continue;
650 if (strncmp(share_path, p, strlen(share_path)) == 0) {
651 break;
655 *pp_fname = p;
656 return (snum < num_services) ? snum : -1;
659 /*******************************************************************
660 Note: topkeypat is the *full* path that this *key will be
661 loaded into (including the name of the key)
662 ********************************************************************/
664 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
665 REGF_NK_REC *key )
667 REGF_NK_REC *subkey;
668 REGISTRY_KEY registry_key;
669 REGVAL_CTR *values;
670 REGSUBKEY_CTR *subkeys;
671 int i;
672 char *path = NULL;
673 WERROR result = WERR_OK;
675 /* initialize the REGISTRY_KEY structure */
677 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
678 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
679 topkeypath ));
680 return WERR_BADFILE;
683 registry_key.name = talloc_strdup( regfile->mem_ctx, topkeypath );
684 if ( !registry_key.name ) {
685 DEBUG(0,("reg_load_tree: Talloc failed for reg_key.name!\n"));
686 return WERR_NOMEM;
689 /* now start parsing the values and subkeys */
691 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
692 return WERR_NOMEM;
694 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
695 return WERR_NOMEM;
697 /* copy values into the REGVAL_CTR */
699 for ( i=0; i<key->num_values; i++ ) {
700 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
701 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
704 /* copy subkeys into the REGSUBKEY_CTR */
706 key->subkey_index = 0;
707 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
708 regsubkey_ctr_addkey( subkeys, subkey->keyname );
711 /* write this key and values out */
713 if ( !store_reg_values( &registry_key, values )
714 || !store_reg_keys( &registry_key, subkeys ) )
716 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
717 result = WERR_REG_IO_FAILURE;
720 TALLOC_FREE( subkeys );
722 if ( !W_ERROR_IS_OK(result) )
723 return result;
725 /* now continue to load each subkey registry tree */
727 key->subkey_index = 0;
728 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
729 path = talloc_asprintf(regfile->mem_ctx,
730 "%s\\%s",
731 topkeypath,
732 subkey->keyname);
733 if (!path) {
734 return WERR_NOMEM;
736 result = reg_load_tree( regfile, path, subkey );
737 if ( !W_ERROR_IS_OK(result) )
738 break;
741 return result;
744 /*******************************************************************
745 ********************************************************************/
747 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
749 REGF_FILE *regfile;
750 REGF_NK_REC *rootkey;
751 WERROR result;
753 /* open the registry file....fail if the file already exists */
755 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
756 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
757 fname, strerror(errno) ));
758 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
761 /* get the rootkey from the regf file and then load the tree
762 via recursive calls */
764 if ( !(rootkey = regfio_rootkey( regfile )) ) {
765 regfio_close( regfile );
766 return WERR_REG_FILE_INVALID;
769 result = reg_load_tree( regfile, krecord->name, rootkey );
771 /* cleanup */
773 regfio_close( regfile );
775 return result;
778 /*******************************************************************
779 ********************************************************************/
781 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
783 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
784 char *fname = NULL;
785 int snum;
787 if ( !regkey )
788 return WERR_BADFID;
790 if ( !r->in.filename || !r->in.filename->name )
791 return WERR_INVALID_PARAM;
793 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
794 if (!fname) {
795 return WERR_NOMEM;
798 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
799 "\"%s\"\n", regkey->key->name, fname));
801 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
802 return WERR_OBJECT_PATH_INVALID;
804 /* user must posses SeRestorePrivilege for this this proceed */
806 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
807 return WERR_ACCESS_DENIED;
809 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
810 regkey->key->name, fname, lp_servicename(snum) ));
812 return restore_registry_key( regkey->key, fname );
815 /********************************************************************
816 ********************************************************************/
818 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
819 REGF_NK_REC *parent, SEC_DESC *sec_desc )
821 REGF_NK_REC *key;
822 REGVAL_CTR *values;
823 REGSUBKEY_CTR *subkeys;
824 int i, num_subkeys;
825 char *key_tmp = NULL;
826 char *keyname, *parentpath;
827 char *subkeypath = NULL;
828 char *subkeyname;
829 REGISTRY_KEY registry_key;
830 WERROR result = WERR_OK;
832 if (!regfile)
833 return WERR_GENERAL_FAILURE;
835 if (!keypath)
836 return WERR_OBJECT_PATH_INVALID;
838 /* split up the registry key path */
840 key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
841 if (!key_tmp) {
842 return WERR_NOMEM;
844 if (!reg_split_key( key_tmp, &parentpath, &keyname ) )
845 return WERR_OBJECT_PATH_INVALID;
847 if ( !keyname )
848 keyname = parentpath;
850 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
852 ZERO_STRUCT( registry_key );
854 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
855 return WERR_NOMEM;
857 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
858 return WERR_BADFILE;
860 /* lookup the values and subkeys */
862 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
863 return WERR_NOMEM;
865 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
866 return WERR_NOMEM;
868 fetch_reg_keys( &registry_key, subkeys );
869 fetch_reg_values( &registry_key, values );
871 /* write out this key */
873 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
874 result = WERR_CAN_NOT_COMPLETE;
875 goto done;
878 /* write each one of the subkeys out */
880 num_subkeys = regsubkey_ctr_numkeys( subkeys );
881 for ( i=0; i<num_subkeys; i++ ) {
882 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
883 subkeypath = talloc_asprintf(regfile->mem_ctx,
884 "%s\\%s", keypath, subkeyname);
885 if (!subkeypath) {
886 result = WERR_NOMEM;
887 goto done;
889 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
890 if ( !W_ERROR_IS_OK(result) )
891 goto done;
894 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
896 done:
897 TALLOC_FREE( subkeys );
898 TALLOC_FREE( registry_key.name );
900 return result;
903 /*******************************************************************
904 ********************************************************************/
906 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
908 DOM_SID adm_sid, owner_sid;
909 SEC_ACE ace[2]; /* at most 2 entries */
910 SEC_ACCESS mask;
911 SEC_ACL *psa = NULL;
912 size_t sd_size;
914 /* set the owner to BUILTIN\Administrator */
916 sid_copy(&owner_sid, &global_sid_Builtin);
917 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
920 /* basic access for Everyone */
922 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
923 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
925 /* add Full Access 'BUILTIN\Administrators' */
927 init_sec_access(&mask, reg_generic_map.generic_all);
928 sid_copy(&adm_sid, &global_sid_Builtin);
929 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
930 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
932 /* create the security descriptor */
934 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
935 return WERR_NOMEM;
937 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
938 return WERR_NOMEM;
940 return WERR_OK;
943 /*******************************************************************
944 ********************************************************************/
946 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
948 REGF_FILE *regfile;
949 WERROR result;
950 SEC_DESC *sd = NULL;
952 /* open the registry file....fail if the file already exists */
954 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
955 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
956 fname, strerror(errno) ));
957 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
960 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
961 regfio_close( regfile );
962 return result;
965 /* write the registry tree to the file */
967 result = reg_write_tree( regfile, krecord->name, NULL, sd );
969 /* cleanup */
971 regfio_close( regfile );
973 return result;
976 /*******************************************************************
977 ********************************************************************/
979 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
981 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
982 char *fname = NULL;
983 int snum = -1;
985 if ( !regkey )
986 return WERR_BADFID;
988 if ( !r->in.filename || !r->in.filename->name )
989 return WERR_INVALID_PARAM;
991 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
992 if (!fname) {
993 return WERR_NOMEM;
996 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
997 regkey->key->name, fname));
999 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
1000 return WERR_OBJECT_PATH_INVALID;
1002 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
1003 regkey->key->name, fname, lp_servicename(snum) ));
1005 return backup_registry_key( regkey->key, fname );
1008 /*******************************************************************
1009 ********************************************************************/
1011 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
1013 /* fill in your code here if you think this call should
1014 do anything */
1016 p->rng_fault_state = True;
1017 return WERR_NOT_SUPPORTED;
1020 /*******************************************************************
1021 ********************************************************************/
1023 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
1025 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1026 struct registry_key *new_key;
1027 WERROR result;
1029 if ( !parent )
1030 return WERR_BADFID;
1032 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
1033 &new_key, r->out.action_taken);
1034 if (!W_ERROR_IS_OK(result)) {
1035 return result;
1038 if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
1039 TALLOC_FREE(new_key);
1040 return WERR_BADFILE;
1043 return WERR_OK;
1046 /*******************************************************************
1047 ********************************************************************/
1049 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
1051 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1052 struct registry_value *val;
1053 WERROR status;
1055 if ( !key )
1056 return WERR_BADFID;
1058 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
1059 key->key->name, r->in.name.name));
1061 status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
1062 r->in.size, r->in.size);
1063 if (!W_ERROR_IS_OK(status)) {
1064 return status;
1067 return reg_setvalue(key, r->in.name.name, val);
1070 /*******************************************************************
1071 ********************************************************************/
1073 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
1075 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1077 if ( !parent )
1078 return WERR_BADFID;
1080 return reg_deletekey(parent, r->in.key.name);
1084 /*******************************************************************
1085 ********************************************************************/
1087 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
1089 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1091 if ( !key )
1092 return WERR_BADFID;
1094 return reg_deletevalue(key, r->in.value.name);
1097 /*******************************************************************
1098 ********************************************************************/
1100 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
1102 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1103 WERROR err;
1104 struct security_descriptor *secdesc;
1105 uint8 *data;
1106 size_t len;
1108 if ( !key )
1109 return WERR_BADFID;
1111 /* access checks first */
1113 if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1114 return WERR_ACCESS_DENIED;
1116 err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1117 if (!W_ERROR_IS_OK(err)) {
1118 return err;
1121 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1122 &data, &len));
1123 if (!W_ERROR_IS_OK(err)) {
1124 return err;
1127 if (len > r->out.sd->size) {
1128 r->out.sd->size = len;
1129 return WERR_INSUFFICIENT_BUFFER;
1132 r->out.sd->size = len;
1133 r->out.sd->len = len;
1134 r->out.sd->data = data;
1136 return WERR_OK;
1139 /*******************************************************************
1140 ********************************************************************/
1142 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
1144 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1145 struct security_descriptor *secdesc;
1146 WERROR err;
1148 if ( !key )
1149 return WERR_BADFID;
1151 /* access checks first */
1153 if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1154 return WERR_ACCESS_DENIED;
1156 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
1157 r->in.sd->len, &secdesc));
1158 if (!W_ERROR_IS_OK(err)) {
1159 return err;
1162 return regkey_set_secdesc(key->key, secdesc);
1165 /*******************************************************************
1166 ********************************************************************/
1168 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
1170 /* I'm just replying OK because there's not a lot
1171 here I see to do i --jerry */
1173 return WERR_OK;
1176 /*******************************************************************
1177 ********************************************************************/
1179 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
1181 /* fill in your code here if you think this call should
1182 do anything */
1184 p->rng_fault_state = True;
1185 return WERR_NOT_SUPPORTED;
1188 /*******************************************************************
1189 ********************************************************************/
1191 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
1193 /* fill in your code here if you think this call should
1194 do anything */
1196 p->rng_fault_state = True;
1197 return WERR_NOT_SUPPORTED;
1200 /*******************************************************************
1201 ********************************************************************/
1203 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
1205 /* fill in your code here if you think this call should
1206 do anything */
1208 p->rng_fault_state = True;
1209 return WERR_NOT_SUPPORTED;
1212 /*******************************************************************
1213 ********************************************************************/
1215 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
1217 /* fill in your code here if you think this call should
1218 do anything */
1220 p->rng_fault_state = True;
1221 return WERR_NOT_SUPPORTED;
1224 /*******************************************************************
1225 ********************************************************************/
1227 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
1229 /* fill in your code here if you think this call should
1230 do anything */
1232 p->rng_fault_state = True;
1233 return WERR_NOT_SUPPORTED;
1236 /*******************************************************************
1237 ********************************************************************/
1239 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
1241 /* fill in your code here if you think this call should
1242 do anything */
1244 p->rng_fault_state = True;
1245 return WERR_NOT_SUPPORTED;