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