r25055: Add file_id_string_tos
[Samba.git] / source / rpc_server / srv_winreg_nt.c
blobfe3295e7e9e87b1cb54fbb1b04796ebb7261da4b
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 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 = 0;
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 pstring shutdown_script;
498 char *msg = NULL;
499 pstring chkmsg;
500 fstring str_timeout;
501 fstring str_reason;
502 fstring reboot;
503 fstring f;
504 int ret;
505 BOOL can_shutdown;
508 pstrcpy(shutdown_script, lp_shutdown_script());
510 if ( !*shutdown_script )
511 return WERR_ACCESS_DENIED;
513 /* pull the message string and perform necessary sanity checks on it */
515 chkmsg[0] = '\0';
517 if ( r->in.message && r->in.message->name && r->in.message->name->name ) {
518 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->name->name )) == NULL ) {
519 return WERR_NOMEM;
521 alpha_strcpy (chkmsg, msg, NULL, sizeof(chkmsg));
524 fstr_sprintf(str_timeout, "%d", r->in.timeout);
525 fstr_sprintf(reboot, r->in.reboot ? SHUTDOWN_R_STRING : "");
526 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
527 fstr_sprintf(str_reason, "%d", r->in.reason );
529 all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
530 all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
531 all_string_sub( shutdown_script, "%r", reboot, sizeof(shutdown_script) );
532 all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
533 all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
535 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
537 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
538 Take the error return from the script and provide it as the Windows return code. */
540 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
542 if ( can_shutdown )
543 become_root();
545 ret = smbrun( shutdown_script, NULL );
547 if ( can_shutdown )
548 unbecome_root();
550 /********** END SeRemoteShutdownPrivilege BLOCK **********/
552 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
553 shutdown_script, ret));
556 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
562 /*******************************************************************
563 reg_abort_shutdwon
564 ********************************************************************/
566 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
568 pstring abort_shutdown_script;
569 int ret;
570 BOOL can_shutdown;
572 pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
574 if ( !*abort_shutdown_script )
575 return WERR_ACCESS_DENIED;
577 can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
579 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
581 if ( can_shutdown )
582 become_root();
584 ret = smbrun( abort_shutdown_script, NULL );
586 if ( can_shutdown )
587 unbecome_root();
589 /********** END SeRemoteShutdownPrivilege BLOCK **********/
591 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
592 abort_shutdown_script, ret));
595 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
598 /*******************************************************************
599 ********************************************************************/
601 static int validate_reg_filename( pstring fname )
603 char *p;
604 int num_services = lp_numservices();
605 int snum;
606 pstring share_path;
607 pstring unix_fname;
609 /* convert to a unix path, stripping the C:\ along the way */
611 if ( !(p = valid_share_pathname( fname ) ))
612 return -1;
614 /* has to exist within a valid file share */
616 for ( snum=0; snum<num_services; snum++ ) {
618 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
619 continue;
621 pstrcpy( share_path, lp_pathname(snum) );
623 /* make sure we have a path (e.g. [homes] ) */
625 if ( strlen( share_path ) == 0 )
626 continue;
628 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
629 break;
632 /* p and fname are overlapping memory so copy out and back in again */
634 pstrcpy( unix_fname, p );
635 pstrcpy( fname, unix_fname );
637 return (snum < num_services) ? snum : -1;
640 /*******************************************************************
641 Note: topkeypat is the *full* path that this *key will be
642 loaded into (including the name of the key)
643 ********************************************************************/
645 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
646 REGF_NK_REC *key )
648 REGF_NK_REC *subkey;
649 REGISTRY_KEY registry_key;
650 REGVAL_CTR *values;
651 REGSUBKEY_CTR *subkeys;
652 int i;
653 pstring path;
654 WERROR result = WERR_OK;
656 /* initialize the REGISTRY_KEY structure */
658 if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
659 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
660 topkeypath ));
661 return WERR_BADFILE;
664 registry_key.name = talloc_strdup( regfile->mem_ctx, topkeypath );
665 if ( !registry_key.name ) {
666 DEBUG(0,("reg_load_tree: Talloc failed for reg_key.name!\n"));
667 return WERR_NOMEM;
670 /* now start parsing the values and subkeys */
672 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
673 return WERR_NOMEM;
675 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
676 return WERR_NOMEM;
678 /* copy values into the REGVAL_CTR */
680 for ( i=0; i<key->num_values; i++ ) {
681 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
682 (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
685 /* copy subkeys into the REGSUBKEY_CTR */
687 key->subkey_index = 0;
688 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
689 regsubkey_ctr_addkey( subkeys, subkey->keyname );
692 /* write this key and values out */
694 if ( !store_reg_values( &registry_key, values )
695 || !store_reg_keys( &registry_key, subkeys ) )
697 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
698 result = WERR_REG_IO_FAILURE;
701 TALLOC_FREE( subkeys );
703 if ( !W_ERROR_IS_OK(result) )
704 return result;
706 /* now continue to load each subkey registry tree */
708 key->subkey_index = 0;
709 while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
710 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
711 result = reg_load_tree( regfile, path, subkey );
712 if ( !W_ERROR_IS_OK(result) )
713 break;
716 return result;
719 /*******************************************************************
720 ********************************************************************/
722 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
724 REGF_FILE *regfile;
725 REGF_NK_REC *rootkey;
726 WERROR result;
728 /* open the registry file....fail if the file already exists */
730 if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
731 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n",
732 fname, strerror(errno) ));
733 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
736 /* get the rootkey from the regf file and then load the tree
737 via recursive calls */
739 if ( !(rootkey = regfio_rootkey( regfile )) ) {
740 regfio_close( regfile );
741 return WERR_REG_FILE_INVALID;
744 result = reg_load_tree( regfile, krecord->name, rootkey );
746 /* cleanup */
748 regfio_close( regfile );
750 return result;
753 /*******************************************************************
754 ********************************************************************/
756 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
758 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
759 pstring fname;
760 int snum;
762 if ( !regkey )
763 return WERR_BADFID;
765 if ( !r->in.filename || !r->in.filename->name )
766 return WERR_INVALID_PARAM;
768 pstrcpy( fname, r->in.filename->name );
770 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
771 "\"%s\"\n", regkey->key->name, fname));
773 if ( (snum = validate_reg_filename( fname )) == -1 )
774 return WERR_OBJECT_PATH_INVALID;
776 /* user must posses SeRestorePrivilege for this this proceed */
778 if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
779 return WERR_ACCESS_DENIED;
781 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
782 regkey->key->name, fname, lp_servicename(snum) ));
784 return restore_registry_key( regkey->key, fname );
787 /********************************************************************
788 ********************************************************************/
790 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
791 REGF_NK_REC *parent, SEC_DESC *sec_desc )
793 REGF_NK_REC *key;
794 REGVAL_CTR *values;
795 REGSUBKEY_CTR *subkeys;
796 int i, num_subkeys;
797 pstring key_tmp;
798 char *keyname, *parentpath;
799 pstring subkeypath;
800 char *subkeyname;
801 REGISTRY_KEY registry_key;
802 WERROR result = WERR_OK;
804 if ( !regfile )
805 return WERR_GENERAL_FAILURE;
807 if ( !keypath )
808 return WERR_OBJECT_PATH_INVALID;
810 /* split up the registry key path */
812 pstrcpy( key_tmp, keypath );
813 if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
814 return WERR_OBJECT_PATH_INVALID;
816 if ( !keyname )
817 keyname = parentpath;
819 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
821 ZERO_STRUCT( registry_key );
823 if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
824 return WERR_NOMEM;
826 if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
827 return WERR_BADFILE;
829 /* lookup the values and subkeys */
831 if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
832 return WERR_NOMEM;
834 if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
835 return WERR_NOMEM;
837 fetch_reg_keys( &registry_key, subkeys );
838 fetch_reg_values( &registry_key, values );
840 /* write out this key */
842 if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
843 result = WERR_CAN_NOT_COMPLETE;
844 goto done;
847 /* write each one of the subkeys out */
849 num_subkeys = regsubkey_ctr_numkeys( subkeys );
850 for ( i=0; i<num_subkeys; i++ ) {
851 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
852 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
853 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
854 if ( !W_ERROR_IS_OK(result) )
855 goto done;
858 DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
860 done:
861 TALLOC_FREE( subkeys );
862 TALLOC_FREE( registry_key.name );
864 return result;
867 /*******************************************************************
868 ********************************************************************/
870 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
872 DOM_SID adm_sid, owner_sid;
873 SEC_ACE ace[2]; /* at most 2 entries */
874 SEC_ACCESS mask;
875 SEC_ACL *psa = NULL;
876 size_t sd_size;
878 /* set the owner to BUILTIN\Administrator */
880 sid_copy(&owner_sid, &global_sid_Builtin);
881 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
884 /* basic access for Everyone */
886 init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
887 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
889 /* add Full Access 'BUILTIN\Administrators' */
891 init_sec_access(&mask, reg_generic_map.generic_all);
892 sid_copy(&adm_sid, &global_sid_Builtin);
893 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
894 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
896 /* create the security descriptor */
898 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
899 return WERR_NOMEM;
901 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
902 return WERR_NOMEM;
904 return WERR_OK;
907 /*******************************************************************
908 ********************************************************************/
910 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
912 REGF_FILE *regfile;
913 WERROR result;
914 SEC_DESC *sd = NULL;
916 /* open the registry file....fail if the file already exists */
918 if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
919 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
920 fname, strerror(errno) ));
921 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
924 if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
925 regfio_close( regfile );
926 return result;
929 /* write the registry tree to the file */
931 result = reg_write_tree( regfile, krecord->name, NULL, sd );
933 /* cleanup */
935 regfio_close( regfile );
937 return result;
940 /*******************************************************************
941 ********************************************************************/
943 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
945 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
946 pstring fname;
947 int snum;
949 if ( !regkey )
950 return WERR_BADFID;
952 if ( !r->in.filename || !r->in.filename->name )
953 return WERR_INVALID_PARAM;
955 pstrcpy( fname, r->in.filename->name );
957 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
958 regkey->key->name, fname));
960 if ( (snum = validate_reg_filename( fname )) == -1 )
961 return WERR_OBJECT_PATH_INVALID;
963 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
964 regkey->key->name, fname, lp_servicename(snum) ));
966 return backup_registry_key( regkey->key, fname );
969 /*******************************************************************
970 ********************************************************************/
972 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
974 /* fill in your code here if you think this call should
975 do anything */
977 p->rng_fault_state = True;
978 return WERR_NOT_SUPPORTED;
981 /*******************************************************************
982 ********************************************************************/
984 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
986 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
987 struct registry_key *new_key;
988 WERROR result;
990 if ( !parent )
991 return WERR_BADFID;
993 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
994 &new_key, r->out.action_taken);
995 if (!W_ERROR_IS_OK(result)) {
996 return result;
999 if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
1000 TALLOC_FREE(new_key);
1001 return WERR_BADFILE;
1004 return WERR_OK;
1007 /*******************************************************************
1008 ********************************************************************/
1010 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
1012 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1013 struct registry_value *val;
1014 WERROR status;
1016 if ( !key )
1017 return WERR_BADFID;
1019 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
1020 key->key->name, r->in.name.name));
1022 status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
1023 r->in.size, r->in.size);
1024 if (!W_ERROR_IS_OK(status)) {
1025 return status;
1028 return reg_setvalue(key, r->in.name.name, val);
1031 /*******************************************************************
1032 ********************************************************************/
1034 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
1036 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1038 if ( !parent )
1039 return WERR_BADFID;
1041 return reg_deletekey(parent, r->in.key.name);
1045 /*******************************************************************
1046 ********************************************************************/
1048 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
1050 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1052 if ( !key )
1053 return WERR_BADFID;
1055 return reg_deletevalue(key, r->in.value.name);
1058 /*******************************************************************
1059 ********************************************************************/
1061 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
1063 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1064 WERROR err;
1065 struct security_descriptor *secdesc;
1066 uint8 *data;
1067 size_t len;
1069 if ( !key )
1070 return WERR_BADFID;
1072 /* access checks first */
1074 if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1075 return WERR_ACCESS_DENIED;
1077 err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1078 if (!W_ERROR_IS_OK(err)) {
1079 return err;
1082 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1083 &data, &len));
1084 if (!W_ERROR_IS_OK(err)) {
1085 return err;
1088 if (len > r->out.sd->size) {
1089 r->out.sd->size = len;
1090 return WERR_INSUFFICIENT_BUFFER;
1093 r->out.sd->size = len;
1094 r->out.sd->len = len;
1095 r->out.sd->data = data;
1097 return WERR_OK;
1100 /*******************************************************************
1101 ********************************************************************/
1103 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
1105 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1106 struct security_descriptor *secdesc;
1107 WERROR err;
1109 if ( !key )
1110 return WERR_BADFID;
1112 /* access checks first */
1114 if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1115 return WERR_ACCESS_DENIED;
1117 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
1118 r->in.sd->len, &secdesc));
1119 if (!W_ERROR_IS_OK(err)) {
1120 return err;
1123 return regkey_set_secdesc(key->key, secdesc);
1126 /*******************************************************************
1127 ********************************************************************/
1129 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
1131 /* I'm just replying OK because there's not a lot
1132 here I see to do i --jerry */
1134 return WERR_OK;
1137 /*******************************************************************
1138 ********************************************************************/
1140 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
1142 /* fill in your code here if you think this call should
1143 do anything */
1145 p->rng_fault_state = True;
1146 return WERR_NOT_SUPPORTED;
1149 /*******************************************************************
1150 ********************************************************************/
1152 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
1154 /* fill in your code here if you think this call should
1155 do anything */
1157 p->rng_fault_state = True;
1158 return WERR_NOT_SUPPORTED;
1161 /*******************************************************************
1162 ********************************************************************/
1164 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
1166 /* fill in your code here if you think this call should
1167 do anything */
1169 p->rng_fault_state = True;
1170 return WERR_NOT_SUPPORTED;
1173 /*******************************************************************
1174 ********************************************************************/
1176 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
1178 /* fill in your code here if you think this call should
1179 do anything */
1181 p->rng_fault_state = True;
1182 return WERR_NOT_SUPPORTED;
1185 /*******************************************************************
1186 ********************************************************************/
1188 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
1190 /* fill in your code here if you think this call should
1191 do anything */
1193 p->rng_fault_state = True;
1194 return WERR_NOT_SUPPORTED;
1197 /*******************************************************************
1198 ********************************************************************/
1200 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
1202 /* fill in your code here if you think this call should
1203 do anything */
1205 p->rng_fault_state = True;
1206 return WERR_NOT_SUPPORTED;