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