Some C++ fixes
[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, SECURITY_DESCRIPTOR_REVISION_1,
938                                   SEC_DESC_SELF_RELATIVE, &owner_sid, NULL,
939                                   NULL, psa, &sd_size)) == NULL)
940                 return WERR_NOMEM;
941
942         return WERR_OK;
943 }
944
945 /*******************************************************************
946  ********************************************************************/
947
948 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
949 {
950         REGF_FILE *regfile;
951         WERROR result;
952         SEC_DESC *sd = NULL;
953         
954         /* open the registry file....fail if the file already exists */
955
956         if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
957                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
958                         fname, strerror(errno) ));
959                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
960         }
961
962         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
963                 regfio_close( regfile );
964                 return result;
965         }
966
967         /* write the registry tree to the file  */
968
969         result = reg_write_tree( regfile, krecord->name, NULL, sd );
970
971         /* cleanup */
972
973         regfio_close( regfile );
974
975         return result;
976 }
977
978 /*******************************************************************
979  ********************************************************************/
980
981 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
982 {
983         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
984         char *fname = NULL;
985         int snum = -1;
986
987         if ( !regkey )
988                 return WERR_BADFID;
989
990         if ( !r->in.filename || !r->in.filename->name )
991                 return WERR_INVALID_PARAM;
992
993         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
994         if (!fname) {
995                 return WERR_NOMEM;
996         }
997
998         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
999                  regkey->key->name, fname));
1000
1001         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
1002                 return WERR_OBJECT_PATH_INVALID;
1003
1004         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
1005                  regkey->key->name, fname, lp_servicename(snum) ));
1006
1007         return backup_registry_key( regkey->key, fname );
1008 }
1009
1010 /*******************************************************************
1011  ********************************************************************/
1012
1013 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
1014 {
1015         /* fill in your code here if you think this call should
1016            do anything */
1017
1018         p->rng_fault_state = True;
1019         return WERR_NOT_SUPPORTED;
1020 }
1021
1022 /*******************************************************************
1023  ********************************************************************/
1024
1025 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
1026 {
1027         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1028         struct registry_key *new_key;
1029         WERROR result;
1030
1031         if ( !parent )
1032                 return WERR_BADFID;
1033
1034         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
1035                                &new_key, r->out.action_taken);
1036         if (!W_ERROR_IS_OK(result)) {
1037                 return result;
1038         }
1039
1040         if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
1041                 TALLOC_FREE(new_key);
1042                 return WERR_BADFILE;
1043         }
1044
1045         return WERR_OK;
1046 }
1047
1048 /*******************************************************************
1049  ********************************************************************/
1050
1051 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
1052 {
1053         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1054         struct registry_value *val;
1055         WERROR status;
1056
1057         if ( !key )
1058                 return WERR_BADFID;
1059
1060         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", 
1061                          key->key->name, r->in.name.name));
1062
1063         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data, 
1064                                                                  r->in.size, r->in.size);
1065         if (!W_ERROR_IS_OK(status)) {
1066                 return status;
1067         }
1068
1069         return reg_setvalue(key, r->in.name.name, val);
1070 }
1071
1072 /*******************************************************************
1073  ********************************************************************/
1074
1075 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
1076 {
1077         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1078
1079         if ( !parent )
1080                 return WERR_BADFID;
1081
1082         return reg_deletekey(parent, r->in.key.name);
1083 }
1084
1085
1086 /*******************************************************************
1087  ********************************************************************/
1088
1089 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
1090 {
1091         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1092         
1093         if ( !key )
1094                 return WERR_BADFID;
1095
1096         return reg_deletevalue(key, r->in.value.name);
1097 }
1098
1099 /*******************************************************************
1100  ********************************************************************/
1101
1102 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
1103 {
1104         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1105         WERROR err;
1106         struct security_descriptor *secdesc;
1107         uint8 *data;
1108         size_t len;
1109
1110         if ( !key )
1111                 return WERR_BADFID;
1112                 
1113         /* access checks first */
1114         
1115         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1116                 return WERR_ACCESS_DENIED;
1117
1118         err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1119         if (!W_ERROR_IS_OK(err)) {
1120                 return err;
1121         }
1122
1123         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1124                                                    &data, &len));
1125         if (!W_ERROR_IS_OK(err)) {
1126                 return err;
1127         }
1128
1129         if (len > r->out.sd->size) {
1130                 r->out.sd->size = len;
1131                 return WERR_INSUFFICIENT_BUFFER;
1132         }
1133
1134         r->out.sd->size = len;
1135         r->out.sd->len = len;
1136         r->out.sd->data = data;
1137                 
1138         return WERR_OK;
1139 }
1140
1141 /*******************************************************************
1142  ********************************************************************/
1143
1144 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
1145 {
1146         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1147         struct security_descriptor *secdesc;
1148         WERROR err;
1149
1150         if ( !key )
1151                 return WERR_BADFID;
1152                 
1153         /* access checks first */
1154         
1155         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1156                 return WERR_ACCESS_DENIED;
1157
1158         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
1159                                                      r->in.sd->len, &secdesc));
1160         if (!W_ERROR_IS_OK(err)) {
1161                 return err;
1162         }
1163
1164         return regkey_set_secdesc(key->key, secdesc);
1165 }
1166
1167 /*******************************************************************
1168  ********************************************************************/
1169
1170 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
1171 {
1172         /* I'm just replying OK because there's not a lot 
1173            here I see to do i  --jerry */
1174         
1175         return WERR_OK;
1176 }
1177
1178 /*******************************************************************
1179  ********************************************************************/
1180
1181 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
1182 {
1183         /* fill in your code here if you think this call should
1184            do anything */
1185
1186         p->rng_fault_state = True;
1187         return WERR_NOT_SUPPORTED;
1188 }
1189
1190 /*******************************************************************
1191  ********************************************************************/
1192
1193 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
1194 {
1195         /* fill in your code here if you think this call should
1196            do anything */
1197
1198         p->rng_fault_state = True;
1199         return WERR_NOT_SUPPORTED;
1200 }
1201
1202 /*******************************************************************
1203  ********************************************************************/
1204
1205 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
1206 {
1207         /* fill in your code here if you think this call should
1208            do anything */
1209
1210         p->rng_fault_state = True;
1211         return WERR_NOT_SUPPORTED;
1212 }
1213
1214 /*******************************************************************
1215  ********************************************************************/
1216
1217 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
1218 {
1219         /* fill in your code here if you think this call should
1220            do anything */
1221
1222         p->rng_fault_state = True;
1223         return WERR_NOT_SUPPORTED;
1224 }
1225
1226 /*******************************************************************
1227  ********************************************************************/
1228
1229 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
1230 {
1231         /* fill in your code here if you think this call should
1232            do anything */
1233
1234         p->rng_fault_state = True;
1235         return WERR_NOT_SUPPORTED;
1236 }
1237
1238 /*******************************************************************
1239  ********************************************************************/
1240
1241 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
1242 {
1243         /* fill in your code here if you think this call should
1244            do anything */
1245
1246         p->rng_fault_state = True;
1247         return WERR_NOT_SUPPORTED;
1248 }
1249