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