7dd5268088c075e4a9f25ab3638586d5df274500
[samba.git] / source / rpc_server / srv_winreg_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  * 
5  *  Copyright (C) Gerald Carter                 2002-2006.
6  *
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.
11  *  
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.
16  *  
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/>.
19  */
20
21 /* Implementation of registry functions. */
22
23 #include "includes.h"
24 #include "regfio.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_SRV
28
29 static const struct generic_mapping reg_generic_map =
30         { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
31
32 /******************************************************************
33  free() function for struct registry_key
34  *****************************************************************/
35  
36 static void free_regkey(void *ptr)
37 {
38         struct registry_key *key = (struct registry_key *)ptr;
39         TALLOC_FREE(key);
40 }
41
42 /******************************************************************
43  Find a registry key handle and return a REGISTRY_KEY
44  *****************************************************************/
45
46 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
47                                                POLICY_HND *hnd)
48 {
49         struct registry_key *regkey = NULL;
50
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;
54         }
55
56         return regkey;
57 }
58
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
62  
63  When we open a key, we store the full path to the key as 
64  HK[LM|U]\<key>\<key>\...
65  *******************************************************************/
66  
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  )
71 {
72         WERROR result = WERR_OK;
73         struct registry_key *key;
74
75         if (parent == NULL) {
76                 result = reg_openhive(NULL, subkeyname, access_desired,
77                                       p->pipe_user.nt_user_token, &key);
78         }
79         else {
80                 result = reg_openkey(NULL, parent, subkeyname, access_desired,
81                                      &key);
82         }
83
84         if ( !W_ERROR_IS_OK(result) ) {
85                 return result;
86         }
87         
88         if ( !create_policy_hnd( p, hnd, free_regkey, key ) ) {
89                 return WERR_BADFILE; 
90         }
91         
92         return WERR_OK;
93 }
94
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  *******************************************************************/
99
100 static bool close_registry_key(pipes_struct *p, POLICY_HND *hnd)
101 {
102         struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
103         
104         if ( !regkey ) {
105                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
106                          OUR_HANDLE(hnd)));
107                 return False;
108         }
109         
110         close_policy_hnd(p, hnd);
111         
112         return True;
113 }
114
115 /********************************************************************
116  reg_close
117  ********************************************************************/
118
119 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
120 {
121         /* close the policy handle */
122
123         if (!close_registry_key(p, r->in.handle))
124                 return WERR_BADFID; 
125
126         ZERO_STRUCTP(r->out.handle);
127
128         return WERR_OK;
129 }
130
131 /*******************************************************************
132  ********************************************************************/
133
134 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
135 {
136         return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
137 }
138
139 /*******************************************************************
140  ********************************************************************/
141
142 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
143 {
144         return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
145 }
146
147 /*******************************************************************
148  ********************************************************************/
149
150 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
151 {
152         return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
153 }
154
155 /*******************************************************************
156  ********************************************************************/
157
158 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
159 {
160         return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
161 }
162
163 /*******************************************************************
164  ********************************************************************/
165
166 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
167 {
168         return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
169 }
170
171 /*******************************************************************
172  ********************************************************************/
173
174 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
175 {
176         return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
177 }
178
179 /*******************************************************************
180  ********************************************************************/
181
182 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
183 {
184         return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
185 }
186
187 /*******************************************************************
188  ********************************************************************/
189
190 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
191 {
192         return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
193 }
194
195 /*******************************************************************
196  ********************************************************************/
197
198 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
199 {
200         return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
201 }
202
203 /*******************************************************************
204  reg_reply_open_entry
205  ********************************************************************/
206
207 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
208 {
209         struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
210
211         if ( !parent )
212                 return WERR_BADFID;
213
214         return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
215 }
216
217 /*******************************************************************
218  reg_reply_info
219  ********************************************************************/
220
221 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
222 {
223         WERROR        status = WERR_BADFILE;
224         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
225         prs_struct    prs_hkpd;
226
227         uint8_t *outbuf;
228         uint32_t outbuf_size;
229
230         DATA_BLOB val_blob;
231         bool free_buf = False;
232         bool free_prs = False;
233
234         if ( !regkey )
235                 return WERR_BADFID;
236
237         *r->out.value_length = *r->out.type = REG_NONE;
238         
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));
241         
242         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
243         if(regkey->key->type == REG_KEY_HKPD) 
244         {
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;
251                 }
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;
257                 }
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;
263                 }
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;
273                 }
274                 else {
275                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
276                                  r->in.value_name.name));
277                         return WERR_BADFILE;
278                 }
279
280                 *r->out.type = REG_BINARY;
281         }
282         else {
283                 struct registry_value *val;
284
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;
290                         }
291                         if (r->out.value_length) {
292                                 *r->out.value_length = 0;
293                         }
294                         return status;
295                 }
296
297                 status = registry_push_value(p->mem_ctx, val, &val_blob);
298                 if (!W_ERROR_IS_OK(status)) {
299                         return status;
300                 }
301
302                 outbuf = val_blob.data;
303                 outbuf_size = val_blob.length;
304                 *r->out.type = val->type;
305         }
306
307         *r->out.value_length = outbuf_size;
308
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;
316         }
317
318         *r->out.data_size = *r->out.value_length;
319
320         if (free_prs) prs_mem_free(&prs_hkpd);
321         if (free_buf) SAFE_FREE(outbuf);
322
323         return status;
324 }
325
326 /*****************************************************************************
327  Implementation of REG_QUERY_KEY
328  ****************************************************************************/
329
330 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
331 {
332         WERROR  status = WERR_OK;
333         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
334         
335         if ( !regkey )
336                 return WERR_BADFID;
337
338         r->out.classname->name = NULL;
339
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;
346         }
347
348         /*
349          * These calculations account for the registry buffers being
350          * UTF-16. They are inexact at best, but so far they worked.
351          */
352
353         *r->out.max_subkeylen *= 2;
354
355         *r->out.max_valnamelen += 1;
356         *r->out.max_valnamelen *= 2;
357         
358         return WERR_OK;
359 }
360
361
362 /*****************************************************************************
363  Implementation of REG_GETVERSION
364  ****************************************************************************/
365  
366 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
367 {
368         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
369         
370         if ( !regkey )
371                 return WERR_BADFID;
372         
373         *r->out.version = 0x00000005;   /* Windows 2000 registry API version */
374         
375         return WERR_OK;
376 }
377
378
379 /*****************************************************************************
380  Implementation of REG_ENUM_KEY
381  ****************************************************************************/
382  
383 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
384 {
385         WERROR err;
386         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
387         
388         if ( !key )
389                 return WERR_BADFID; 
390
391         if ( !r->in.name || !r->in.keyclass )
392                 return WERR_INVALID_PARAM;
393
394         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
395
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;
400         }
401         r->out.keyclass->name = "";
402         return WERR_OK;
403 }
404
405 /*****************************************************************************
406  Implementation of REG_ENUM_VALUE
407  ****************************************************************************/
408
409 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
410 {
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;
416         
417         if ( !key )
418                 return WERR_BADFID;
419
420         if ( !r->in.name )
421                 return WERR_INVALID_PARAM;
422
423         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
424                  key->key->name));
425
426         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
427         if (!W_ERROR_IS_OK(err)) {
428                 return err;
429         }
430
431         err = registry_push_value(p->mem_ctx, val, &value_blob);
432         if (!W_ERROR_IS_OK(err)) {
433                 return err;
434         }
435
436         if (r->out.name != NULL) {
437                 r->out.name->name = valname;
438         }
439
440         if (r->out.type != NULL) {
441                 *r->out.type = val->type;
442         }
443
444         if (r->out.value != NULL) {
445                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
446                         return WERR_INVALID_PARAM;
447                 }
448
449                 if (value_blob.length > *r->out.size) {
450                         return WERR_MORE_DATA;
451                 }
452
453                 memcpy( r->out.value, value_blob.data, value_blob.length );
454         }
455
456         if (r->out.length != NULL) {
457                 *r->out.length = value_blob.length;
458         }
459         if (r->out.size != NULL) {
460                 *r->out.size = value_blob.length;
461         }
462
463         return WERR_OK;
464 }
465
466 /*******************************************************************
467  reg_shutdwon
468  ********************************************************************/
469
470 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
471 {
472         struct winreg_InitiateSystemShutdownEx s;
473
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;
480
481         /* thunk down to _winreg_InitiateSystemShutdownEx() 
482            (just returns a status) */
483         
484         return _winreg_InitiateSystemShutdownEx( p, &s );
485 }
486
487 /*******************************************************************
488  reg_shutdown_ex
489  ********************************************************************/
490
491 #define SHUTDOWN_R_STRING "-r"
492 #define SHUTDOWN_F_STRING "-f"
493
494
495 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
496 {
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;
506
507         shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
508         if (!shutdown_script) {
509                 return WERR_NOMEM;
510         }
511         if (!*shutdown_script) {
512                 return WERR_ACCESS_DENIED;
513         }
514
515         /* pull the message string and perform necessary sanity checks on it */
516
517         chkmsg[0] = '\0';
518
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;
522                 }
523                 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
524                 if (!chkmsg) {
525                         return WERR_NOMEM;
526                 }
527                 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
528         }
529
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 );
534
535         shutdown_script = talloc_all_string_sub(p->mem_ctx,
536                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
537         if (!shutdown_script) {
538                 return WERR_NOMEM;
539         }
540         shutdown_script = talloc_all_string_sub(p->mem_ctx,
541                                         shutdown_script, "%t", str_timeout);
542         if (!shutdown_script) {
543                 return WERR_NOMEM;
544         }
545         shutdown_script = talloc_all_string_sub(p->mem_ctx,
546                                                 shutdown_script, "%r", reboot);
547         if (!shutdown_script) {
548                 return WERR_NOMEM;
549         }
550         shutdown_script = talloc_all_string_sub(p->mem_ctx,
551                                                 shutdown_script, "%f", f);
552         if (!shutdown_script) {
553                 return WERR_NOMEM;
554         }
555         shutdown_script = talloc_all_string_sub(p->mem_ctx,
556                                         shutdown_script, "%x", str_reason);
557         if (!shutdown_script) {
558                 return WERR_NOMEM;
559         }
560
561         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
562
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. */
565
566         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
567
568         if ( can_shutdown )
569                 become_root();
570
571         ret = smbrun( shutdown_script, NULL );
572
573         if ( can_shutdown )
574                 unbecome_root();
575
576         /********** END SeRemoteShutdownPrivilege BLOCK **********/
577
578         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
579                 shutdown_script, ret));
580
581         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
582 }
583
584 /*******************************************************************
585  reg_abort_shutdwon
586  ********************************************************************/
587
588 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
589 {
590         const char *abort_shutdown_script;
591         int ret;
592         bool can_shutdown;
593
594         abort_shutdown_script = lp_abort_shutdown_script();
595
596         if (!*abort_shutdown_script)
597                 return WERR_ACCESS_DENIED;
598
599         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
600
601         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
602
603         if ( can_shutdown )
604                 become_root();
605
606         ret = smbrun( abort_shutdown_script, NULL );
607
608         if ( can_shutdown )
609                 unbecome_root();
610
611         /********** END SeRemoteShutdownPrivilege BLOCK **********/
612
613         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
614                 abort_shutdown_script, ret));
615
616         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
617 }
618
619 /*******************************************************************
620  ********************************************************************/
621
622 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
623 {
624         char *p = NULL;
625         int num_services = lp_numservices();
626         int snum = -1;
627         const char *share_path;
628         char *fname = *pp_fname;
629
630         /* convert to a unix path, stripping the C:\ along the way */
631
632         if (!(p = valid_share_pathname(ctx, fname))) {
633                 return -1;
634         }
635
636         /* has to exist within a valid file share */
637
638         for (snum=0; snum<num_services; snum++) {
639                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
640                         continue;
641                 }
642
643                 share_path = lp_pathname(snum);
644
645                 /* make sure we have a path (e.g. [homes] ) */
646                 if (strlen(share_path) == 0) {
647                         continue;
648                 }
649
650                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
651                         break;
652                 }
653         }
654
655         *pp_fname = p;
656         return (snum < num_services) ? snum : -1;
657 }
658
659 /*******************************************************************
660  Note: topkeypat is the *full* path that this *key will be
661  loaded into (including the name of the key)
662  ********************************************************************/
663
664 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
665                              REGF_NK_REC *key )
666 {
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;
674
675         /* initialize the REGISTRY_KEY structure */
676
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;
681         }
682
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;
687         }
688
689         /* now start parsing the values and subkeys */
690
691         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
692                 return WERR_NOMEM;
693
694         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
695                 return WERR_NOMEM;
696
697         /* copy values into the REGVAL_CTR */
698
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) );
702         }
703
704         /* copy subkeys into the REGSUBKEY_CTR */
705
706         key->subkey_index = 0;
707         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
708                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
709         }
710
711         /* write this key and values out */
712
713         if ( !store_reg_values( &registry_key, values )
714                 || !store_reg_keys( &registry_key, subkeys ) )
715         {
716                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
717                 result = WERR_REG_IO_FAILURE;
718         }
719
720         TALLOC_FREE( subkeys );
721
722         if ( !W_ERROR_IS_OK(result) )
723                 return result;
724
725         /* now continue to load each subkey registry tree */
726
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;
735                 }
736                 result = reg_load_tree( regfile, path, subkey );
737                 if ( !W_ERROR_IS_OK(result) )
738                         break;
739         }
740
741         return result;
742 }
743
744 /*******************************************************************
745  ********************************************************************/
746
747 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
748 {
749         REGF_FILE *regfile;
750         REGF_NK_REC *rootkey;
751         WERROR result;
752                 
753         /* open the registry file....fail if the file already exists */
754         
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 )) );
759         }
760         
761         /* get the rootkey from the regf file and then load the tree
762            via recursive calls */
763            
764         if ( !(rootkey = regfio_rootkey( regfile )) ) {
765                 regfio_close( regfile );
766                 return WERR_REG_FILE_INVALID;
767         }
768
769         result = reg_load_tree( regfile, krecord->name, rootkey );
770
771         /* cleanup */
772
773         regfio_close( regfile );
774
775         return result;
776 }
777
778 /*******************************************************************
779  ********************************************************************/
780
781 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
782 {
783         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
784         char *fname = NULL;
785         int             snum;
786
787         if ( !regkey )
788                 return WERR_BADFID;
789
790         if ( !r->in.filename || !r->in.filename->name )
791                 return WERR_INVALID_PARAM;
792
793         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
794         if (!fname) {
795                 return WERR_NOMEM;
796         }
797
798         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
799                  "\"%s\"\n", regkey->key->name, fname));
800
801         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
802                 return WERR_OBJECT_PATH_INVALID;
803
804         /* user must posses SeRestorePrivilege for this this proceed */
805
806         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
807                 return WERR_ACCESS_DENIED;
808
809         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
810                  regkey->key->name, fname, lp_servicename(snum) ));
811
812         return restore_registry_key( regkey->key, fname );
813 }
814
815 /********************************************************************
816 ********************************************************************/
817
818 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
819                               REGF_NK_REC *parent, SEC_DESC *sec_desc )
820 {
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;
831
832         if (!regfile)
833                 return WERR_GENERAL_FAILURE;
834
835         if (!keypath)
836                 return WERR_OBJECT_PATH_INVALID;
837
838         /* split up the registry key path */
839
840         key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
841         if (!key_tmp) {
842                 return WERR_NOMEM;
843         }
844         if (!reg_split_key( key_tmp, &parentpath, &keyname ) )
845                 return WERR_OBJECT_PATH_INVALID;
846
847         if ( !keyname )
848                 keyname = parentpath;
849
850         /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
851
852         ZERO_STRUCT( registry_key );
853
854         if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
855                 return WERR_NOMEM;
856
857         if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
858                 return WERR_BADFILE;
859
860         /* lookup the values and subkeys */
861
862         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
863                 return WERR_NOMEM;
864
865         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
866                 return WERR_NOMEM;
867
868         fetch_reg_keys( &registry_key, subkeys );
869         fetch_reg_values( &registry_key, values );
870
871         /* write out this key */
872
873         if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
874                 result = WERR_CAN_NOT_COMPLETE;
875                 goto done;
876         }
877
878         /* write each one of the subkeys out */
879
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;
888                 }
889                 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
890                 if ( !W_ERROR_IS_OK(result) )
891                         goto done;
892         }
893
894         DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
895
896 done:
897         TALLOC_FREE( subkeys );
898         TALLOC_FREE( registry_key.name );
899
900         return result;
901 }
902
903 /*******************************************************************
904  ********************************************************************/
905
906 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
907 {
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;
913
914         /* set the owner to BUILTIN\Administrator */
915
916         sid_copy(&owner_sid, &global_sid_Builtin);
917         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
918         
919
920         /* basic access for Everyone */
921
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);
924
925         /* add Full Access 'BUILTIN\Administrators' */
926
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);
931
932         /* create the security descriptor */
933
934         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
935                 return WERR_NOMEM;
936
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;
939
940         return WERR_OK;
941 }
942
943 /*******************************************************************
944  ********************************************************************/
945
946 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
947 {
948         REGF_FILE *regfile;
949         WERROR result;
950         SEC_DESC *sd = NULL;
951         
952         /* open the registry file....fail if the file already exists */
953
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 )) );
958         }
959
960         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
961                 regfio_close( regfile );
962                 return result;
963         }
964
965         /* write the registry tree to the file  */
966
967         result = reg_write_tree( regfile, krecord->name, NULL, sd );
968
969         /* cleanup */
970
971         regfio_close( regfile );
972
973         return result;
974 }
975
976 /*******************************************************************
977  ********************************************************************/
978
979 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
980 {
981         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
982         char *fname = NULL;
983         int snum = -1;
984
985         if ( !regkey )
986                 return WERR_BADFID;
987
988         if ( !r->in.filename || !r->in.filename->name )
989                 return WERR_INVALID_PARAM;
990
991         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
992         if (!fname) {
993                 return WERR_NOMEM;
994         }
995
996         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
997                  regkey->key->name, fname));
998
999         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
1000                 return WERR_OBJECT_PATH_INVALID;
1001
1002         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
1003                  regkey->key->name, fname, lp_servicename(snum) ));
1004
1005         return backup_registry_key( regkey->key, fname );
1006 }
1007
1008 /*******************************************************************
1009  ********************************************************************/
1010
1011 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
1012 {
1013         /* fill in your code here if you think this call should
1014            do anything */
1015
1016         p->rng_fault_state = True;
1017         return WERR_NOT_SUPPORTED;
1018 }
1019
1020 /*******************************************************************
1021  ********************************************************************/
1022
1023 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
1024 {
1025         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1026         struct registry_key *new_key;
1027         WERROR result;
1028
1029         if ( !parent )
1030                 return WERR_BADFID;
1031
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;
1036         }
1037
1038         if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
1039                 TALLOC_FREE(new_key);
1040                 return WERR_BADFILE;
1041         }
1042
1043         return WERR_OK;
1044 }
1045
1046 /*******************************************************************
1047  ********************************************************************/
1048
1049 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
1050 {
1051         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1052         struct registry_value *val;
1053         WERROR status;
1054
1055         if ( !key )
1056                 return WERR_BADFID;
1057
1058         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", 
1059                          key->key->name, r->in.name.name));
1060
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;
1065         }
1066
1067         return reg_setvalue(key, r->in.name.name, val);
1068 }
1069
1070 /*******************************************************************
1071  ********************************************************************/
1072
1073 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
1074 {
1075         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1076
1077         if ( !parent )
1078                 return WERR_BADFID;
1079
1080         return reg_deletekey(parent, r->in.key.name);
1081 }
1082
1083
1084 /*******************************************************************
1085  ********************************************************************/
1086
1087 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
1088 {
1089         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1090         
1091         if ( !key )
1092                 return WERR_BADFID;
1093
1094         return reg_deletevalue(key, r->in.value.name);
1095 }
1096
1097 /*******************************************************************
1098  ********************************************************************/
1099
1100 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
1101 {
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;
1107
1108         if ( !key )
1109                 return WERR_BADFID;
1110                 
1111         /* access checks first */
1112         
1113         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1114                 return WERR_ACCESS_DENIED;
1115
1116         err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1117         if (!W_ERROR_IS_OK(err)) {
1118                 return err;
1119         }
1120
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;
1125         }
1126
1127         if (len > r->out.sd->size) {
1128                 r->out.sd->size = len;
1129                 return WERR_INSUFFICIENT_BUFFER;
1130         }
1131
1132         r->out.sd->size = len;
1133         r->out.sd->len = len;
1134         r->out.sd->data = data;
1135                 
1136         return WERR_OK;
1137 }
1138
1139 /*******************************************************************
1140  ********************************************************************/
1141
1142 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
1143 {
1144         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1145         struct security_descriptor *secdesc;
1146         WERROR err;
1147
1148         if ( !key )
1149                 return WERR_BADFID;
1150                 
1151         /* access checks first */
1152         
1153         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1154                 return WERR_ACCESS_DENIED;
1155
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;
1160         }
1161
1162         return regkey_set_secdesc(key->key, secdesc);
1163 }
1164
1165 /*******************************************************************
1166  ********************************************************************/
1167
1168 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
1169 {
1170         /* I'm just replying OK because there's not a lot 
1171            here I see to do i  --jerry */
1172         
1173         return WERR_OK;
1174 }
1175
1176 /*******************************************************************
1177  ********************************************************************/
1178
1179 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
1180 {
1181         /* fill in your code here if you think this call should
1182            do anything */
1183
1184         p->rng_fault_state = True;
1185         return WERR_NOT_SUPPORTED;
1186 }
1187
1188 /*******************************************************************
1189  ********************************************************************/
1190
1191 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
1192 {
1193         /* fill in your code here if you think this call should
1194            do anything */
1195
1196         p->rng_fault_state = True;
1197         return WERR_NOT_SUPPORTED;
1198 }
1199
1200 /*******************************************************************
1201  ********************************************************************/
1202
1203 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
1204 {
1205         /* fill in your code here if you think this call should
1206            do anything */
1207
1208         p->rng_fault_state = True;
1209         return WERR_NOT_SUPPORTED;
1210 }
1211
1212 /*******************************************************************
1213  ********************************************************************/
1214
1215 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
1216 {
1217         /* fill in your code here if you think this call should
1218            do anything */
1219
1220         p->rng_fault_state = True;
1221         return WERR_NOT_SUPPORTED;
1222 }
1223
1224 /*******************************************************************
1225  ********************************************************************/
1226
1227 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
1228 {
1229         /* fill in your code here if you think this call should
1230            do anything */
1231
1232         p->rng_fault_state = True;
1233         return WERR_NOT_SUPPORTED;
1234 }
1235
1236 /*******************************************************************
1237  ********************************************************************/
1238
1239 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
1240 {
1241         /* fill in your code here if you think this call should
1242            do anything */
1243
1244         p->rng_fault_state = True;
1245         return WERR_NOT_SUPPORTED;
1246 }
1247