Fix bug #9098 - winbind does not refresh kerberos tickets.
[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 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* Implementation of registry functions. */
22
23 #include "includes.h"
24 #include "../librpc/gen_ndr/srv_winreg.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_SRV
28
29 /******************************************************************
30  Find a registry key handle and return a struct registry_key *
31  *****************************************************************/
32
33 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
34                                                struct policy_handle *hnd)
35 {
36         struct registry_key *regkey = NULL;
37
38         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
39                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
40                 return NULL;
41         }
42
43         return regkey;
44 }
45
46 /*******************************************************************
47  Function for open a new registry handle and creating a handle
48  Note that P should be valid & hnd should already have space
49
50  When we open a key, we store the full path to the key as
51  HK[LM|U]\<key>\<key>\...
52  *******************************************************************/
53
54 static WERROR open_registry_key( pipes_struct *p, struct policy_handle *hnd,
55                                  struct registry_key *parent,
56                                  const char *subkeyname,
57                                  uint32 access_desired  )
58 {
59         WERROR result = WERR_OK;
60         struct registry_key *key;
61
62         if (parent == NULL) {
63                 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
64                                       p->server_info->ptok, &key);
65         }
66         else {
67                 result = reg_openkey(p->mem_ctx, parent, subkeyname,
68                                      access_desired, &key);
69         }
70
71         if ( !W_ERROR_IS_OK(result) ) {
72                 return result;
73         }
74
75         if ( !create_policy_hnd( p, hnd, key ) ) {
76                 return WERR_BADFILE;
77         }
78
79         return WERR_OK;
80 }
81
82 /*******************************************************************
83  Function for open a new registry handle and creating a handle
84  Note that P should be valid & hnd should already have space
85  *******************************************************************/
86
87 static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
88 {
89         struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
90
91         if ( !regkey ) {
92                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
93                          OUR_HANDLE(hnd)));
94                 return False;
95         }
96
97         close_policy_hnd(p, hnd);
98
99         return True;
100 }
101
102 /********************************************************************
103  _winreg_CloseKey
104  ********************************************************************/
105
106 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
107 {
108         /* close the policy handle */
109
110         if (!close_registry_key(p, r->in.handle))
111                 return WERR_BADFID;
112
113         ZERO_STRUCTP(r->out.handle);
114
115         return WERR_OK;
116 }
117
118 /*******************************************************************
119  _winreg_OpenHKLM
120  ********************************************************************/
121
122 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
123 {
124         return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
125 }
126
127 /*******************************************************************
128  _winreg_OpenHKPD
129  ********************************************************************/
130
131 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
132 {
133         return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
134 }
135
136 /*******************************************************************
137  _winreg_OpenHKPT
138  ********************************************************************/
139
140 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
141 {
142         return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
143 }
144
145 /*******************************************************************
146  _winreg_OpenHKCR
147  ********************************************************************/
148
149 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
150 {
151         return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
152 }
153
154 /*******************************************************************
155  _winreg_OpenHKU
156  ********************************************************************/
157
158 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
159 {
160         return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
161 }
162
163 /*******************************************************************
164  _winreg_OpenHKCU
165  ********************************************************************/
166
167 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
168 {
169         return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
170 }
171
172 /*******************************************************************
173  _winreg_OpenHKCC
174  ********************************************************************/
175
176 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
177 {
178         return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
179 }
180
181 /*******************************************************************
182  _winreg_OpenHKDD
183  ********************************************************************/
184
185 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
186 {
187         return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
188 }
189
190 /*******************************************************************
191  _winreg_OpenHKPN
192  ********************************************************************/
193
194 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
195 {
196         return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
197 }
198
199 /*******************************************************************
200  _winreg_OpenKey
201  ********************************************************************/
202
203 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
204 {
205         struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
206
207         if ( !parent )
208                 return WERR_BADFID;
209
210         return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
211 }
212
213 /*******************************************************************
214  _winreg_QueryValue
215  ********************************************************************/
216
217 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
218 {
219         WERROR        status = WERR_BADFILE;
220         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
221         prs_struct    prs_hkpd;
222
223         uint8_t *outbuf = NULL;
224         uint32_t outbuf_size = 0;
225
226         DATA_BLOB val_blob;
227         bool free_buf = False;
228         bool free_prs = False;
229
230         if ( !regkey )
231                 return WERR_BADFID;
232
233         if (r->in.value_name->name == NULL) {
234                 return WERR_INVALID_PARAM;
235         }
236
237         if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
238                 return WERR_INVALID_PARAM;
239         }
240
241         DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
242         DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
243
244         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
245         if(regkey->key->type == REG_KEY_HKPD)
246         {
247                 if (strequal(r->in.value_name->name, "Global")) {
248                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
249                                 return WERR_NOMEM;
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                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
271                                 return WERR_NOMEM;
272                         status = reg_perfcount_get_hkpd(
273                                 &prs_hkpd, *r->in.data_size, &outbuf_size,
274                                 r->in.value_name->name);
275                         outbuf = (uint8_t *)prs_hkpd.data_p;
276                         free_prs = True;
277                 }
278                 else {
279                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
280                                  r->in.value_name->name));
281                         return WERR_BADFILE;
282                 }
283
284                 *r->out.type = REG_BINARY;
285         }
286         else {
287                 struct registry_value *val;
288
289                 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
290                                         &val);
291                 if (!W_ERROR_IS_OK(status)) {
292
293                         DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
294                                 win_errstr(status)));
295
296                         if (r->out.data_size) {
297                                 *r->out.data_size = 0;
298                         }
299                         if (r->out.data_length) {
300                                 *r->out.data_length = 0;
301                         }
302                         return status;
303                 }
304
305                 status = registry_push_value(p->mem_ctx, val, &val_blob);
306                 if (!W_ERROR_IS_OK(status)) {
307                         return status;
308                 }
309
310                 outbuf = val_blob.data;
311                 outbuf_size = val_blob.length;
312                 *r->out.type = val->type;
313         }
314
315         status = WERR_BADFILE;
316
317         if (*r->in.data_size < outbuf_size) {
318                 *r->out.data_size = outbuf_size;
319                 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
320         } else {
321                 *r->out.data_length = outbuf_size;
322                 *r->out.data_size = outbuf_size;
323                 if (r->out.data) {
324                         memcpy(r->out.data, outbuf, outbuf_size);
325                 }
326                 status = WERR_OK;
327         }
328
329         if (free_prs) prs_mem_free(&prs_hkpd);
330         if (free_buf) SAFE_FREE(outbuf);
331
332         return status;
333 }
334
335 /*****************************************************************************
336  _winreg_QueryInfoKey
337  ****************************************************************************/
338
339 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
340 {
341         WERROR  status = WERR_OK;
342         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
343
344         if ( !regkey )
345                 return WERR_BADFID;
346
347         r->out.classname->name = NULL;
348
349         status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
350                                   r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
351                                   r->out.max_valbufsize, r->out.secdescsize,
352                                   r->out.last_changed_time);
353         if (!W_ERROR_IS_OK(status)) {
354                 return status;
355         }
356
357         /*
358          * These calculations account for the registry buffers being
359          * UTF-16. They are inexact at best, but so far they worked.
360          */
361
362         *r->out.max_subkeylen *= 2;
363
364         *r->out.max_valnamelen += 1;
365         *r->out.max_valnamelen *= 2;
366
367         return WERR_OK;
368 }
369
370
371 /*****************************************************************************
372  _winreg_GetVersion
373  ****************************************************************************/
374
375 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
376 {
377         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
378
379         if ( !regkey )
380                 return WERR_BADFID;
381
382         return reg_getversion(r->out.version);
383 }
384
385
386 /*****************************************************************************
387  _winreg_EnumKey
388  ****************************************************************************/
389
390 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
391 {
392         WERROR err;
393         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
394
395         if ( !key )
396                 return WERR_BADFID;
397
398         if ( !r->in.name || !r->in.keyclass )
399                 return WERR_INVALID_PARAM;
400
401         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
402
403         err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
404                           r->out.last_changed_time);
405         if (!W_ERROR_IS_OK(err)) {
406                 return err;
407         }
408         r->out.keyclass->name = "";
409         return WERR_OK;
410 }
411
412 /*****************************************************************************
413  _winreg_EnumValue
414  ****************************************************************************/
415
416 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
417 {
418         WERROR err;
419         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
420         char *valname;
421         struct registry_value *val;
422         DATA_BLOB value_blob;
423
424         if ( !key )
425                 return WERR_BADFID;
426
427         if ( !r->in.name )
428                 return WERR_INVALID_PARAM;
429
430         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
431                  key->key->name));
432
433         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
434         if (!W_ERROR_IS_OK(err)) {
435                 return err;
436         }
437
438         err = registry_push_value(p->mem_ctx, val, &value_blob);
439         if (!W_ERROR_IS_OK(err)) {
440                 return err;
441         }
442
443         if (r->out.name != NULL) {
444                 r->out.name->name = valname;
445         }
446
447         if (r->out.type != NULL) {
448                 *r->out.type = val->type;
449         }
450
451         if (r->out.value != NULL) {
452                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
453                         return WERR_INVALID_PARAM;
454                 }
455
456                 if (value_blob.length > *r->out.size) {
457                         return WERR_MORE_DATA;
458                 }
459
460                 memcpy( r->out.value, value_blob.data, value_blob.length );
461         }
462
463         if (r->out.length != NULL) {
464                 *r->out.length = value_blob.length;
465         }
466         if (r->out.size != NULL) {
467                 *r->out.size = value_blob.length;
468         }
469
470         return WERR_OK;
471 }
472
473 /*******************************************************************
474  _winreg_InitiateSystemShutdown
475  ********************************************************************/
476
477 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
478 {
479         struct winreg_InitiateSystemShutdownEx s;
480
481         s.in.hostname = r->in.hostname;
482         s.in.message = r->in.message;
483         s.in.timeout = r->in.timeout;
484         s.in.force_apps = r->in.force_apps;
485         s.in.do_reboot = r->in.do_reboot;
486         s.in.reason = 0;
487
488         /* thunk down to _winreg_InitiateSystemShutdownEx()
489            (just returns a status) */
490
491         return _winreg_InitiateSystemShutdownEx( p, &s );
492 }
493
494 /*******************************************************************
495  _winreg_InitiateSystemShutdownEx
496  ********************************************************************/
497
498 #define SHUTDOWN_R_STRING "-r"
499 #define SHUTDOWN_F_STRING "-f"
500
501
502 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
503 {
504         char *shutdown_script = NULL;
505         char *msg = NULL;
506         char *chkmsg = NULL;
507         fstring str_timeout;
508         fstring str_reason;
509         fstring do_reboot;
510         fstring f;
511         int ret;
512         bool can_shutdown;
513
514         shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
515         if (!shutdown_script) {
516                 return WERR_NOMEM;
517         }
518         if (!*shutdown_script) {
519                 return WERR_ACCESS_DENIED;
520         }
521
522         /* pull the message string and perform necessary sanity checks on it */
523
524         if ( r->in.message && r->in.message->string ) {
525                 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
526                         return WERR_NOMEM;
527                 }
528                 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
529                 if (!chkmsg) {
530                         return WERR_NOMEM;
531                 }
532                 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
533         }
534
535         fstr_sprintf(str_timeout, "%d", r->in.timeout);
536         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
537         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
538         fstr_sprintf(str_reason, "%d", r->in.reason );
539
540         shutdown_script = talloc_all_string_sub(p->mem_ctx,
541                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
542         if (!shutdown_script) {
543                 return WERR_NOMEM;
544         }
545         shutdown_script = talloc_all_string_sub(p->mem_ctx,
546                                         shutdown_script, "%t", str_timeout);
547         if (!shutdown_script) {
548                 return WERR_NOMEM;
549         }
550         shutdown_script = talloc_all_string_sub(p->mem_ctx,
551                                                 shutdown_script, "%r", do_reboot);
552         if (!shutdown_script) {
553                 return WERR_NOMEM;
554         }
555         shutdown_script = talloc_all_string_sub(p->mem_ctx,
556                                                 shutdown_script, "%f", f);
557         if (!shutdown_script) {
558                 return WERR_NOMEM;
559         }
560         shutdown_script = talloc_all_string_sub(p->mem_ctx,
561                                         shutdown_script, "%x", str_reason);
562         if (!shutdown_script) {
563                 return WERR_NOMEM;
564         }
565
566         can_shutdown = user_has_privileges( p->server_info->ptok,
567                                             &se_remote_shutdown );
568
569         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
570            Take the error return from the script and provide it as the Windows return code. */
571
572         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
573
574         if ( can_shutdown )
575                 become_root();
576
577         ret = smbrun( shutdown_script, NULL );
578
579         if ( can_shutdown )
580                 unbecome_root();
581
582         /********** END SeRemoteShutdownPrivilege BLOCK **********/
583
584         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
585                 shutdown_script, ret));
586
587         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
588 }
589
590 /*******************************************************************
591  _winreg_AbortSystemShutdown
592  ********************************************************************/
593
594 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
595 {
596         const char *abort_shutdown_script;
597         int ret;
598         bool can_shutdown;
599
600         abort_shutdown_script = lp_abort_shutdown_script();
601
602         if (!*abort_shutdown_script)
603                 return WERR_ACCESS_DENIED;
604
605         can_shutdown = user_has_privileges( p->server_info->ptok,
606                                             &se_remote_shutdown );
607
608         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
609
610         if ( can_shutdown )
611                 become_root();
612
613         ret = smbrun( abort_shutdown_script, NULL );
614
615         if ( can_shutdown )
616                 unbecome_root();
617
618         /********** END SeRemoteShutdownPrivilege BLOCK **********/
619
620         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
621                 abort_shutdown_script, ret));
622
623         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
624 }
625
626 /*******************************************************************
627  ********************************************************************/
628
629 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
630 {
631         char *p = NULL;
632         int num_services = lp_numservices();
633         int snum = -1;
634         const char *share_path;
635         char *fname = *pp_fname;
636
637         /* convert to a unix path, stripping the C:\ along the way */
638
639         if (!(p = valid_share_pathname(ctx, fname))) {
640                 return -1;
641         }
642
643         /* has to exist within a valid file share */
644
645         for (snum=0; snum<num_services; snum++) {
646                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
647                         continue;
648                 }
649
650                 share_path = lp_pathname(snum);
651
652                 /* make sure we have a path (e.g. [homes] ) */
653                 if (strlen(share_path) == 0) {
654                         continue;
655                 }
656
657                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
658                         break;
659                 }
660         }
661
662         *pp_fname = p;
663         return (snum < num_services) ? snum : -1;
664 }
665
666 /*******************************************************************
667  _winreg_RestoreKey
668  ********************************************************************/
669
670 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
671 {
672         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
673         char *fname = NULL;
674         int             snum;
675
676         if ( !regkey )
677                 return WERR_BADFID;
678
679         if ( !r->in.filename || !r->in.filename->name )
680                 return WERR_INVALID_PARAM;
681
682         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
683         if (!fname) {
684                 return WERR_NOMEM;
685         }
686
687         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
688                  "\"%s\"\n", regkey->key->name, fname));
689
690         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
691                 return WERR_OBJECT_PATH_INVALID;
692
693         /* user must posses SeRestorePrivilege for this this proceed */
694
695         if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
696                 return WERR_ACCESS_DENIED;
697
698         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
699                  regkey->key->name, fname, lp_servicename(snum) ));
700
701         return reg_restorekey(regkey, fname);
702 }
703
704 /*******************************************************************
705  _winreg_SaveKey
706  ********************************************************************/
707
708 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
709 {
710         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
711         char *fname = NULL;
712         int snum = -1;
713
714         if ( !regkey )
715                 return WERR_BADFID;
716
717         if ( !r->in.filename || !r->in.filename->name )
718                 return WERR_INVALID_PARAM;
719
720         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
721         if (!fname) {
722                 return WERR_NOMEM;
723         }
724
725         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
726                  regkey->key->name, fname));
727
728         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
729                 return WERR_OBJECT_PATH_INVALID;
730
731         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
732                  regkey->key->name, fname, lp_servicename(snum) ));
733
734         return reg_savekey(regkey, fname);
735 }
736
737 /*******************************************************************
738  _winreg_SaveKeyEx
739  ********************************************************************/
740
741 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
742 {
743         /* fill in your code here if you think this call should
744            do anything */
745
746         p->rng_fault_state = True;
747         return WERR_NOT_SUPPORTED;
748 }
749
750 /*******************************************************************
751  _winreg_CreateKey
752  ********************************************************************/
753
754 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
755 {
756         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
757         struct registry_key *new_key;
758         WERROR result;
759
760         if ( !parent )
761                 return WERR_BADFID;
762
763         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
764                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
765
766         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
767                                &new_key, r->out.action_taken);
768         if (!W_ERROR_IS_OK(result)) {
769                 return result;
770         }
771
772         if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
773                 TALLOC_FREE(new_key);
774                 return WERR_BADFILE;
775         }
776
777         return WERR_OK;
778 }
779
780 /*******************************************************************
781  _winreg_SetValue
782  ********************************************************************/
783
784 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
785 {
786         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
787         struct registry_value *val;
788         WERROR status;
789
790         if ( !key )
791                 return WERR_BADFID;
792
793         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
794                          key->key->name, r->in.name.name));
795
796         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
797                                                                  r->in.size, r->in.size);
798         if (!W_ERROR_IS_OK(status)) {
799                 return status;
800         }
801
802         return reg_setvalue(key, r->in.name.name, val);
803 }
804
805 /*******************************************************************
806  _winreg_DeleteKey
807  ********************************************************************/
808
809 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
810 {
811         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
812
813         if ( !parent )
814                 return WERR_BADFID;
815
816         return reg_deletekey(parent, r->in.key.name);
817 }
818
819
820 /*******************************************************************
821  _winreg_DeleteValue
822  ********************************************************************/
823
824 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
825 {
826         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
827
828         if ( !key )
829                 return WERR_BADFID;
830
831         return reg_deletevalue(key, r->in.value.name);
832 }
833
834 /*******************************************************************
835  _winreg_GetKeySecurity
836  ********************************************************************/
837
838 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
839 {
840         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
841         WERROR err;
842         struct security_descriptor *secdesc;
843         uint8 *data;
844         size_t len;
845
846         if ( !key )
847                 return WERR_BADFID;
848
849         /* access checks first */
850
851         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
852                 return WERR_ACCESS_DENIED;
853
854         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
855         if (!W_ERROR_IS_OK(err)) {
856                 return err;
857         }
858
859         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
860                                                    &data, &len));
861         if (!W_ERROR_IS_OK(err)) {
862                 return err;
863         }
864
865         if (len > r->out.sd->size) {
866                 r->out.sd->size = len;
867                 return WERR_INSUFFICIENT_BUFFER;
868         }
869
870         r->out.sd->size = len;
871         r->out.sd->len = len;
872         r->out.sd->data = data;
873
874         return WERR_OK;
875 }
876
877 /*******************************************************************
878  _winreg_SetKeySecurity
879  ********************************************************************/
880
881 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
882 {
883         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
884         struct security_descriptor *secdesc;
885         WERROR err;
886
887         if ( !key )
888                 return WERR_BADFID;
889
890         /* access checks first */
891
892         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
893                 return WERR_ACCESS_DENIED;
894
895         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
896                                                      r->in.sd->len, &secdesc));
897         if (!W_ERROR_IS_OK(err)) {
898                 return err;
899         }
900
901         return reg_setkeysecurity(key, secdesc);
902 }
903
904 /*******************************************************************
905  _winreg_FlushKey
906  ********************************************************************/
907
908 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
909 {
910         /* I'm just replying OK because there's not a lot
911            here I see to do i  --jerry */
912
913         return WERR_OK;
914 }
915
916 /*******************************************************************
917  _winreg_UnLoadKey
918  ********************************************************************/
919
920 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
921 {
922         /* fill in your code here if you think this call should
923            do anything */
924
925         p->rng_fault_state = True;
926         return WERR_NOT_SUPPORTED;
927 }
928
929 /*******************************************************************
930  _winreg_ReplaceKey
931  ********************************************************************/
932
933 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
934 {
935         /* fill in your code here if you think this call should
936            do anything */
937
938         p->rng_fault_state = True;
939         return WERR_NOT_SUPPORTED;
940 }
941
942 /*******************************************************************
943  _winreg_LoadKey
944  ********************************************************************/
945
946 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
947 {
948         /* fill in your code here if you think this call should
949            do anything */
950
951         p->rng_fault_state = True;
952         return WERR_NOT_SUPPORTED;
953 }
954
955 /*******************************************************************
956  _winreg_NotifyChangeKeyValue
957  ********************************************************************/
958
959 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
960 {
961         return WERR_NOT_SUPPORTED;
962 }
963
964 /*******************************************************************
965  _winreg_QueryMultipleValues
966  ********************************************************************/
967
968 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *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  _winreg_QueryMultipleValues2
979  ********************************************************************/
980
981 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
982 {
983         /* fill in your code here if you think this call should
984            do anything */
985
986         p->rng_fault_state = True;
987         return WERR_NOT_SUPPORTED;
988 }
989