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