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