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