r23633: Fix a couple of crash bugs pointed out by Volker caused by an old
[ira/wip.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 registry_key
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
665         registry_key.name = talloc_strdup( regfile->mem_ctx, topkeypath );
666         if ( !registry_key.name ) {
667                 DEBUG(0,("reg_load_tree: Talloc failed for reg_key.name!\n"));
668                 return WERR_NOMEM;
669         }
670         
671         /* now start parsing the values and subkeys */
672
673         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
674                 return WERR_NOMEM;
675         
676         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
677                 return WERR_NOMEM;
678
679         /* copy values into the REGVAL_CTR */
680         
681         for ( i=0; i<key->num_values; i++ ) {
682                 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
683                         (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
684         }
685
686         /* copy subkeys into the REGSUBKEY_CTR */
687         
688         key->subkey_index = 0;
689         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
690                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
691         }
692         
693         /* write this key and values out */
694         
695         if ( !store_reg_values( &registry_key, values ) 
696                 || !store_reg_keys( &registry_key, subkeys ) )
697         {
698                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
699                 result = WERR_REG_IO_FAILURE;
700         }
701         
702         TALLOC_FREE( subkeys );
703         
704         if ( !W_ERROR_IS_OK(result) )
705                 return result;
706         
707         /* now continue to load each subkey registry tree */
708
709         key->subkey_index = 0;
710         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
711                 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
712                 result = reg_load_tree( regfile, path, subkey );
713                 if ( !W_ERROR_IS_OK(result) )
714                         break;
715         }
716
717         return result;
718 }
719
720 /*******************************************************************
721  ********************************************************************/
722
723 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
724 {
725         REGF_FILE *regfile;
726         REGF_NK_REC *rootkey;
727         WERROR result;
728                 
729         /* open the registry file....fail if the file already exists */
730         
731         if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
732                 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n", 
733                         fname, strerror(errno) ));
734                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
735         }
736         
737         /* get the rootkey from the regf file and then load the tree
738            via recursive calls */
739            
740         if ( !(rootkey = regfio_rootkey( regfile )) ) {
741                 regfio_close( regfile );
742                 return WERR_REG_FILE_INVALID;
743         }
744         
745         result = reg_load_tree( regfile, krecord->name, rootkey );
746                 
747         /* cleanup */
748         
749         regfio_close( regfile );
750         
751         return result;
752 }
753
754 /*******************************************************************
755  ********************************************************************/
756
757 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
758 {
759         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
760         pstring         fname;
761         int             snum;
762         
763         if ( !regkey )
764                 return WERR_BADFID; 
765
766         if ( !r->in.filename || !r->in.filename->name )
767                 return WERR_INVALID_PARAM;
768
769         pstrcpy( fname, r->in.filename->name );
770
771         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
772                  "\"%s\"\n", regkey->key->name, fname));
773
774         if ( (snum = validate_reg_filename( fname )) == -1 )
775                 return WERR_OBJECT_PATH_INVALID;
776                 
777         /* user must posses SeRestorePrivilege for this this proceed */
778         
779         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
780                 return WERR_ACCESS_DENIED;
781                 
782         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
783                  regkey->key->name, fname, lp_servicename(snum) ));
784
785         return restore_registry_key( regkey->key, fname );
786 }
787
788 /********************************************************************
789 ********************************************************************/
790
791 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
792                               REGF_NK_REC *parent, SEC_DESC *sec_desc )
793 {
794         REGF_NK_REC *key;
795         REGVAL_CTR *values;
796         REGSUBKEY_CTR *subkeys;
797         int i, num_subkeys;
798         pstring key_tmp;
799         char *keyname, *parentpath;
800         pstring subkeypath;
801         char *subkeyname;
802         REGISTRY_KEY registry_key;
803         WERROR result = WERR_OK;
804         
805         if ( !regfile )
806                 return WERR_GENERAL_FAILURE;
807                 
808         if ( !keypath )
809                 return WERR_OBJECT_PATH_INVALID;
810                 
811         /* split up the registry key path */
812         
813         pstrcpy( key_tmp, keypath );
814         if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
815                 return WERR_OBJECT_PATH_INVALID;
816
817         if ( !keyname )
818                 keyname = parentpath;
819
820         /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
821         
822         ZERO_STRUCT( registry_key );
823
824         if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
825                 return WERR_NOMEM;
826
827         if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
828                 return WERR_BADFILE;
829
830         /* lookup the values and subkeys */
831         
832         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) ) 
833                 return WERR_NOMEM;
834
835         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
836                 return WERR_NOMEM;
837
838         fetch_reg_keys( &registry_key, subkeys );
839         fetch_reg_values( &registry_key, values );
840
841         /* write out this key */
842                 
843         if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
844                 result = WERR_CAN_NOT_COMPLETE;
845                 goto done;
846         }
847
848         /* write each one of the subkeys out */
849
850         num_subkeys = regsubkey_ctr_numkeys( subkeys );
851         for ( i=0; i<num_subkeys; i++ ) {
852                 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
853                 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
854                 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
855                 if ( !W_ERROR_IS_OK(result) )
856                         goto done;
857         }
858
859         DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
860
861 done:
862         TALLOC_FREE( subkeys );
863         TALLOC_FREE( registry_key.name );
864
865         return result;
866 }
867
868 /*******************************************************************
869  ********************************************************************/
870
871 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
872 {
873         DOM_SID adm_sid, owner_sid;
874         SEC_ACE ace[2];         /* at most 2 entries */
875         SEC_ACCESS mask;
876         SEC_ACL *psa = NULL;
877         size_t sd_size;
878
879         /* set the owner to BUILTIN\Administrator */
880
881         sid_copy(&owner_sid, &global_sid_Builtin);
882         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
883         
884
885         /* basic access for Everyone */
886
887         init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
888         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
889
890         /* add Full Access 'BUILTIN\Administrators' */
891
892         init_sec_access(&mask, reg_generic_map.generic_all);
893         sid_copy(&adm_sid, &global_sid_Builtin);
894         sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
895         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
896
897         /* create the security descriptor */
898
899         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
900                 return WERR_NOMEM;
901
902         if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
903                 return WERR_NOMEM;
904
905         return WERR_OK;
906 }
907
908 /*******************************************************************
909  ********************************************************************/
910
911 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
912 {
913         REGF_FILE *regfile;
914         WERROR result;
915         SEC_DESC *sd = NULL;
916         
917         /* open the registry file....fail if the file already exists */
918         
919         if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
920                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n", 
921                         fname, strerror(errno) ));
922                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
923         }
924         
925         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
926                 regfio_close( regfile );
927                 return result;
928         }
929                 
930         /* write the registry tree to the file  */
931         
932         result = reg_write_tree( regfile, krecord->name, NULL, sd );
933                 
934         /* cleanup */
935         
936         regfio_close( regfile );
937         
938         return result;
939 }
940
941 /*******************************************************************
942  ********************************************************************/
943
944 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
945 {
946         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
947         pstring         fname;
948         int             snum;
949         
950         if ( !regkey )
951                 return WERR_BADFID; 
952
953         if ( !r->in.filename || !r->in.filename->name )
954                 return WERR_INVALID_PARAM;
955
956         pstrcpy( fname, r->in.filename->name );
957
958         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
959                  regkey->key->name, fname));
960         
961         if ( (snum = validate_reg_filename( fname )) == -1 )
962                 return WERR_OBJECT_PATH_INVALID;
963                 
964         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
965                  regkey->key->name, fname, lp_servicename(snum) ));
966                 
967         return backup_registry_key( regkey->key, fname );
968 }
969
970 /*******************************************************************
971  ********************************************************************/
972
973 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
974 {
975         /* fill in your code here if you think this call should
976            do anything */
977
978         p->rng_fault_state = True;
979         return WERR_NOT_SUPPORTED;
980 }
981
982 /*******************************************************************
983  ********************************************************************/
984
985 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
986 {
987         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
988         struct registry_key *new_key;
989         WERROR result;
990
991         if ( !parent )
992                 return WERR_BADFID;
993
994         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
995                                &new_key, r->out.action_taken);
996         if (!W_ERROR_IS_OK(result)) {
997                 return result;
998         }
999
1000         if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
1001                 TALLOC_FREE(new_key);
1002                 return WERR_BADFILE;
1003         }
1004
1005         return WERR_OK;
1006 }
1007
1008 /*******************************************************************
1009  ********************************************************************/
1010
1011 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
1012 {
1013         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1014         struct registry_value *val;
1015         WERROR status;
1016
1017         if ( !key )
1018                 return WERR_BADFID;
1019
1020         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", 
1021                          key->key->name, r->in.name.name));
1022
1023         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data, 
1024                                                                  r->in.size, r->in.size);
1025         if (!W_ERROR_IS_OK(status)) {
1026                 return status;
1027         }
1028
1029         return reg_setvalue(key, r->in.name.name, val);
1030 }
1031
1032 /*******************************************************************
1033  ********************************************************************/
1034
1035 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
1036 {
1037         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
1038
1039         if ( !parent )
1040                 return WERR_BADFID;
1041
1042         return reg_deletekey(parent, r->in.key.name);
1043 }
1044
1045
1046 /*******************************************************************
1047  ********************************************************************/
1048
1049 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
1050 {
1051         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1052         
1053         if ( !key )
1054                 return WERR_BADFID;
1055
1056         return reg_deletevalue(key, r->in.value.name);
1057 }
1058
1059 /*******************************************************************
1060  ********************************************************************/
1061
1062 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
1063 {
1064         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1065         WERROR err;
1066         struct security_descriptor *secdesc;
1067         uint8 *data;
1068         size_t len;
1069
1070         if ( !key )
1071                 return WERR_BADFID;
1072                 
1073         /* access checks first */
1074         
1075         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1076                 return WERR_ACCESS_DENIED;
1077
1078         err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1079         if (!W_ERROR_IS_OK(err)) {
1080                 return err;
1081         }
1082
1083         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1084                                                    &data, &len));
1085         if (!W_ERROR_IS_OK(err)) {
1086                 return err;
1087         }
1088
1089         if (len > r->out.sd->size) {
1090                 r->out.sd->size = len;
1091                 return WERR_INSUFFICIENT_BUFFER;
1092         }
1093
1094         r->out.sd->size = len;
1095         r->out.sd->len = len;
1096         r->out.sd->data = data;
1097                 
1098         return WERR_OK;
1099 }
1100
1101 /*******************************************************************
1102  ********************************************************************/
1103
1104 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
1105 {
1106         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
1107         struct security_descriptor *secdesc;
1108         WERROR err;
1109
1110         if ( !key )
1111                 return WERR_BADFID;
1112                 
1113         /* access checks first */
1114         
1115         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1116                 return WERR_ACCESS_DENIED;
1117
1118         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
1119                                                      r->in.sd->len, &secdesc));
1120         if (!W_ERROR_IS_OK(err)) {
1121                 return err;
1122         }
1123
1124         return regkey_set_secdesc(key->key, secdesc);
1125 }
1126
1127 /*******************************************************************
1128  ********************************************************************/
1129
1130 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
1131 {
1132         /* I'm just replying OK because there's not a lot 
1133            here I see to do i  --jerry */
1134         
1135         return WERR_OK;
1136 }
1137
1138 /*******************************************************************
1139  ********************************************************************/
1140
1141 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
1142 {
1143         /* fill in your code here if you think this call should
1144            do anything */
1145
1146         p->rng_fault_state = True;
1147         return WERR_NOT_SUPPORTED;
1148 }
1149
1150 /*******************************************************************
1151  ********************************************************************/
1152
1153 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
1154 {
1155         /* fill in your code here if you think this call should
1156            do anything */
1157
1158         p->rng_fault_state = True;
1159         return WERR_NOT_SUPPORTED;
1160 }
1161
1162 /*******************************************************************
1163  ********************************************************************/
1164
1165 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
1166 {
1167         /* fill in your code here if you think this call should
1168            do anything */
1169
1170         p->rng_fault_state = True;
1171         return WERR_NOT_SUPPORTED;
1172 }
1173
1174 /*******************************************************************
1175  ********************************************************************/
1176
1177 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
1178 {
1179         /* fill in your code here if you think this call should
1180            do anything */
1181
1182         p->rng_fault_state = True;
1183         return WERR_NOT_SUPPORTED;
1184 }
1185
1186 /*******************************************************************
1187  ********************************************************************/
1188
1189 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
1190 {
1191         /* fill in your code here if you think this call should
1192            do anything */
1193
1194         p->rng_fault_state = True;
1195         return WERR_NOT_SUPPORTED;
1196 }
1197
1198 /*******************************************************************
1199  ********************************************************************/
1200
1201 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
1202 {
1203         /* fill in your code here if you think this call should
1204            do anything */
1205
1206         p->rng_fault_state = True;
1207         return WERR_NOT_SUPPORTED;
1208 }
1209