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