69982dadc6e7ea8dc01e177d96ed08b4b7f310a9
[metze/samba/wip.git] / source3 / rpc_client / cli_winreg.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  WINREG client routines
5  *
6  *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "../librpc/gen_ndr/ndr_winreg_c.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "rpc_client/cli_winreg.h"
26 #include "../libcli/registry/util_reg.h"
27
28 NTSTATUS dcerpc_winreg_query_dword(TALLOC_CTX *mem_ctx,
29                                    struct dcerpc_binding_handle *h,
30                                    struct policy_handle *key_handle,
31                                    const char *value,
32                                    uint32_t *data,
33                                    WERROR *pwerr)
34 {
35         struct winreg_String wvalue;
36         enum winreg_Type type = REG_NONE;
37         uint32_t value_len = 0;
38         uint32_t data_size = 0;
39         NTSTATUS status;
40         DATA_BLOB blob;
41
42         wvalue.name = value;
43
44         status = dcerpc_winreg_QueryValue(h,
45                                           mem_ctx,
46                                           key_handle,
47                                           &wvalue,
48                                           &type,
49                                           NULL,
50                                           &data_size,
51                                           &value_len,
52                                           pwerr);
53         if (!NT_STATUS_IS_OK(status)) {
54                 return status;
55         }
56         if (!W_ERROR_IS_OK(*pwerr)) {
57                 return status;
58         }
59
60         if (type != REG_DWORD) {
61                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
62         }
63
64         if (data_size != 4) {
65                 return NT_STATUS_INVALID_PARAMETER;
66         }
67
68         blob = data_blob_talloc_zero(mem_ctx, data_size);
69         if (blob.data == NULL) {
70                 return NT_STATUS_NO_MEMORY;
71         }
72         value_len = 0;
73
74         status = dcerpc_winreg_QueryValue(h,
75                                           mem_ctx,
76                                           key_handle,
77                                           &wvalue,
78                                           &type,
79                                           blob.data,
80                                           &data_size,
81                                           &value_len,
82                                           pwerr);
83         if (!NT_STATUS_IS_OK(status)) {
84                 return status;
85         }
86         if (!W_ERROR_IS_OK(*pwerr)) {
87                 return status;
88         }
89
90         if (data) {
91                 *data = IVAL(blob.data, 0);
92         }
93
94         return status;
95 }
96
97 NTSTATUS dcerpc_winreg_query_binary(TALLOC_CTX *mem_ctx,
98                                     struct dcerpc_binding_handle *h,
99                                     struct policy_handle *key_handle,
100                                     const char *value,
101                                     DATA_BLOB *data,
102                                     WERROR *pwerr)
103 {
104         struct winreg_String wvalue;
105         enum winreg_Type type = REG_NONE;
106         uint32_t value_len = 0;
107         uint32_t data_size = 0;
108         NTSTATUS status;
109         DATA_BLOB blob;
110
111         ZERO_STRUCT(wvalue);
112         wvalue.name = value;
113
114         status = dcerpc_winreg_QueryValue(h,
115                                           mem_ctx,
116                                           key_handle,
117                                           &wvalue,
118                                           &type,
119                                           NULL,
120                                           &data_size,
121                                           &value_len,
122                                           pwerr);
123         if (!NT_STATUS_IS_OK(status)) {
124                 return status;
125         }
126         if (!W_ERROR_IS_OK(*pwerr)) {
127                 return status;
128         }
129
130         if (type != REG_BINARY) {
131                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
132         }
133
134         blob = data_blob_talloc_zero(mem_ctx, data_size);
135         if (blob.data == NULL) {
136                 return NT_STATUS_NO_MEMORY;
137         }
138         value_len = 0;
139
140         status = dcerpc_winreg_QueryValue(h,
141                                           mem_ctx,
142                                           key_handle,
143                                           &wvalue,
144                                           &type,
145                                           blob.data,
146                                           &data_size,
147                                           &value_len,
148                                           pwerr);
149         if (!NT_STATUS_IS_OK(status)) {
150                 return status;
151         }
152         if (!W_ERROR_IS_OK(*pwerr)) {
153                 return status;
154         }
155
156         if (data) {
157                 data->data = blob.data;
158                 data->length = blob.length;
159         }
160
161         return status;
162 }
163
164 NTSTATUS dcerpc_winreg_query_multi_sz(TALLOC_CTX *mem_ctx,
165                                       struct dcerpc_binding_handle *h,
166                                       struct policy_handle *key_handle,
167                                       const char *value,
168                                       const char ***data,
169                                       WERROR *pwerr)
170 {
171         struct winreg_String wvalue;
172         enum winreg_Type type = REG_NONE;
173         uint32_t value_len = 0;
174         uint32_t data_size = 0;
175         NTSTATUS status;
176         DATA_BLOB blob;
177
178         wvalue.name = value;
179
180         status = dcerpc_winreg_QueryValue(h,
181                                           mem_ctx,
182                                           key_handle,
183                                           &wvalue,
184                                           &type,
185                                           NULL,
186                                           &data_size,
187                                           &value_len,
188                                           pwerr);
189         if (!NT_STATUS_IS_OK(status)) {
190                 return status;
191         }
192         if (!W_ERROR_IS_OK(*pwerr)) {
193                 return status;
194         }
195
196         if (type != REG_MULTI_SZ) {
197                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
198         }
199
200         blob = data_blob_talloc_zero(mem_ctx, data_size);
201         if (blob.data == NULL) {
202                 return NT_STATUS_NO_MEMORY;
203         }
204         value_len = 0;
205
206         status = dcerpc_winreg_QueryValue(h,
207                                           mem_ctx,
208                                           key_handle,
209                                           &wvalue,
210                                           &type,
211                                           blob.data,
212                                           &data_size,
213                                           &value_len,
214                                           pwerr);
215         if (!NT_STATUS_IS_OK(status)) {
216                 return status;
217         }
218         if (!W_ERROR_IS_OK(*pwerr)) {
219                 return status;
220         }
221
222         if (data) {
223                 bool ok;
224
225                 ok = pull_reg_multi_sz(mem_ctx, &blob, data);
226                 if (!ok) {
227                         status = NT_STATUS_NO_MEMORY;
228                 }
229         }
230
231         return status;
232 }
233
234 NTSTATUS dcerpc_winreg_query_sz(TALLOC_CTX *mem_ctx,
235                                       struct dcerpc_binding_handle *h,
236                                       struct policy_handle *key_handle,
237                                       const char *value,
238                                       const char **data,
239                                       WERROR *pwerr)
240 {
241         struct winreg_String wvalue;
242         enum winreg_Type type = REG_NONE;
243         uint32_t value_len = 0;
244         uint32_t data_size = 0;
245         NTSTATUS status;
246         DATA_BLOB blob;
247
248         wvalue.name = value;
249
250         status = dcerpc_winreg_QueryValue(h,
251                                           mem_ctx,
252                                           key_handle,
253                                           &wvalue,
254                                           &type,
255                                           NULL,
256                                           &data_size,
257                                           &value_len,
258                                           pwerr);
259         if (!NT_STATUS_IS_OK(status)) {
260                 return status;
261         }
262         if (!W_ERROR_IS_OK(*pwerr)) {
263                 return status;
264         }
265
266         if (type != REG_SZ) {
267                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
268         }
269
270         blob = data_blob_talloc_zero(mem_ctx, data_size);
271         if (blob.data == NULL) {
272                 return NT_STATUS_NO_MEMORY;
273         }
274         value_len = 0;
275
276         status = dcerpc_winreg_QueryValue(h,
277                                           mem_ctx,
278                                           key_handle,
279                                           &wvalue,
280                                           &type,
281                                           blob.data,
282                                           &data_size,
283                                           &value_len,
284                                           pwerr);
285         if (!NT_STATUS_IS_OK(status)) {
286                 return status;
287         }
288         if (!W_ERROR_IS_OK(*pwerr)) {
289                 return status;
290         }
291
292         if (data) {
293                 bool ok;
294
295                 ok = pull_reg_sz(mem_ctx, &blob, data);
296                 if (!ok) {
297                         status = NT_STATUS_NO_MEMORY;
298                 }
299         }
300
301         return status;
302 }
303
304 NTSTATUS dcerpc_winreg_query_sd(TALLOC_CTX *mem_ctx,
305                                 struct dcerpc_binding_handle *h,
306                                 struct policy_handle *key_handle,
307                                 const char *value,
308                                 struct security_descriptor **data,
309                                 WERROR *pwerr)
310 {
311         NTSTATUS status;
312         DATA_BLOB blob;
313
314         status = dcerpc_winreg_query_binary(mem_ctx,
315                                             h,
316                                             key_handle,
317                                             value,
318                                             &blob,
319                                             pwerr);
320         if (!NT_STATUS_IS_OK(status)) {
321                 return status;
322         }
323         if (!W_ERROR_IS_OK(*pwerr)) {
324                 return status;
325         }
326
327         if (data) {
328                 struct security_descriptor *sd;
329                 enum ndr_err_code ndr_err;
330
331                 sd = talloc_zero(mem_ctx, struct security_descriptor);
332                 if (sd == NULL) {
333                         return NT_STATUS_NO_MEMORY;
334                 }
335
336                 ndr_err = ndr_pull_struct_blob(&blob,
337                                                sd,
338                                                sd,
339                                                (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
340                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341                         DEBUG(2, ("dcerpc_winreg_query_sd: Failed to marshall "
342                                   "security descriptor\n"));
343                         return NT_STATUS_NO_MEMORY;
344                 }
345
346                 *data = sd;
347         }
348
349         return status;
350 }
351
352 NTSTATUS dcerpc_winreg_set_dword(TALLOC_CTX *mem_ctx,
353                                  struct dcerpc_binding_handle *h,
354                                  struct policy_handle *key_handle,
355                                  const char *value,
356                                  uint32_t data,
357                                  WERROR *pwerr)
358 {
359         struct winreg_String wvalue;
360         DATA_BLOB blob;
361         NTSTATUS status;
362
363         ZERO_STRUCT(wvalue);
364         wvalue.name = value;
365         blob = data_blob_talloc_zero(mem_ctx, 4);
366         SIVAL(blob.data, 0, data);
367
368         status = dcerpc_winreg_SetValue(h,
369                                         mem_ctx,
370                                         key_handle,
371                                         wvalue,
372                                         REG_DWORD,
373                                         blob.data,
374                                         blob.length,
375                                         pwerr);
376
377         return status;
378 }
379
380 NTSTATUS dcerpc_winreg_set_sz(TALLOC_CTX *mem_ctx,
381                               struct dcerpc_binding_handle *h,
382                               struct policy_handle *key_handle,
383                               const char *value,
384                               const char *data,
385                               WERROR *pwerr)
386 {
387         struct winreg_String wvalue = { 0, };
388         DATA_BLOB blob;
389         NTSTATUS status;
390
391         wvalue.name = value;
392         if (data == NULL) {
393                 blob = data_blob_string_const("");
394         } else {
395                 if (!push_reg_sz(mem_ctx, &blob, data)) {
396                         DEBUG(2, ("dcerpc_winreg_set_sz: Could not marshall "
397                                   "string %s for %s\n",
398                                   data, wvalue.name));
399                         return NT_STATUS_NO_MEMORY;
400                 }
401         }
402
403         status = dcerpc_winreg_SetValue(h,
404                                         mem_ctx,
405                                         key_handle,
406                                         wvalue,
407                                         REG_SZ,
408                                         blob.data,
409                                         blob.length,
410                                         pwerr);
411
412         return status;
413 }
414
415 NTSTATUS dcerpc_winreg_set_expand_sz(TALLOC_CTX *mem_ctx,
416                                      struct dcerpc_binding_handle *h,
417                                      struct policy_handle *key_handle,
418                                      const char *value,
419                                      const char *data,
420                                      WERROR *pwerr)
421 {
422         struct winreg_String wvalue = { 0, };
423         DATA_BLOB blob;
424         NTSTATUS status;
425
426         wvalue.name = value;
427         if (data == NULL) {
428                 blob = data_blob_string_const("");
429         } else {
430                 if (!push_reg_sz(mem_ctx, &blob, data)) {
431                         DEBUG(2, ("dcerpc_winreg_set_expand_sz: Could not marshall "
432                                   "string %s for %s\n",
433                                   data, wvalue.name));
434                         return NT_STATUS_NO_MEMORY;
435                 }
436         }
437
438         status = dcerpc_winreg_SetValue(h,
439                                         mem_ctx,
440                                         key_handle,
441                                         wvalue,
442                                         REG_EXPAND_SZ,
443                                         blob.data,
444                                         blob.length,
445                                         pwerr);
446
447         return status;
448 }
449
450 NTSTATUS dcerpc_winreg_set_multi_sz(TALLOC_CTX *mem_ctx,
451                                     struct dcerpc_binding_handle *h,
452                                     struct policy_handle *key_handle,
453                                     const char *value,
454                                     const char **data,
455                                     WERROR *pwerr)
456 {
457         struct winreg_String wvalue = { 0, };
458         DATA_BLOB blob;
459         NTSTATUS status;
460
461         wvalue.name = value;
462         if (!push_reg_multi_sz(mem_ctx, &blob, data)) {
463                 DEBUG(2, ("dcerpc_winreg_set_multi_sz: Could not marshall "
464                           "string multi sz for %s\n",
465                           wvalue.name));
466                 return NT_STATUS_NO_MEMORY;
467         }
468
469         status = dcerpc_winreg_SetValue(h,
470                                         mem_ctx,
471                                         key_handle,
472                                         wvalue,
473                                         REG_MULTI_SZ,
474                                         blob.data,
475                                         blob.length,
476                                         pwerr);
477
478         return status;
479 }
480
481 NTSTATUS dcerpc_winreg_set_binary(TALLOC_CTX *mem_ctx,
482                                   struct dcerpc_binding_handle *h,
483                                   struct policy_handle *key_handle,
484                                   const char *value,
485                                   DATA_BLOB *data,
486                                   WERROR *pwerr)
487 {
488         struct winreg_String wvalue = { 0, };
489         NTSTATUS status;
490
491         wvalue.name = value;
492
493         status = dcerpc_winreg_SetValue(h,
494                                         mem_ctx,
495                                         key_handle,
496                                         wvalue,
497                                         REG_BINARY,
498                                         data->data,
499                                         data->length,
500                                         pwerr);
501
502         return status;
503 }
504
505 NTSTATUS dcerpc_winreg_set_sd(TALLOC_CTX *mem_ctx,
506                               struct dcerpc_binding_handle *h,
507                               struct policy_handle *key_handle,
508                               const char *value,
509                               const struct security_descriptor *data,
510                               WERROR *pwerr)
511 {
512         enum ndr_err_code ndr_err;
513         DATA_BLOB blob;
514
515         ndr_err = ndr_push_struct_blob(&blob,
516                                        mem_ctx,
517                                        data,
518                                        (ndr_push_flags_fn_t) ndr_push_security_descriptor);
519         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
520                 DEBUG(2, ("dcerpc_winreg_set_sd: Failed to marshall security "
521                           "descriptor\n"));
522                 return NT_STATUS_NO_MEMORY;
523         }
524
525         return dcerpc_winreg_set_binary(mem_ctx,
526                                         h,
527                                         key_handle,
528                                         value,
529                                         &blob,
530                                         pwerr);
531 }
532
533 NTSTATUS dcerpc_winreg_add_multi_sz(TALLOC_CTX *mem_ctx,
534                                     struct dcerpc_binding_handle *h,
535                                     struct policy_handle *key_handle,
536                                     const char *value,
537                                     const char *data,
538                                     WERROR *pwerr)
539 {
540         const char **a = NULL;
541         const char **p;
542         uint32_t i;
543         NTSTATUS status;
544
545         status = dcerpc_winreg_query_multi_sz(mem_ctx,
546                                               h,
547                                               key_handle,
548                                               value,
549                                               &a,
550                                               pwerr);
551
552         /* count the elements */
553         for (p = a, i = 0; p && *p; p++, i++);
554
555         p = talloc_realloc(mem_ctx, a, const char *, i + 2);
556         if (p == NULL) {
557                 return NT_STATUS_NO_MEMORY;
558         }
559
560         p[i] = data;
561         p[i + 1] = NULL;
562
563         status = dcerpc_winreg_set_multi_sz(mem_ctx,
564                                             h,
565                                             key_handle,
566                                             value,
567                                             p,
568                                             pwerr);
569
570         return status;
571 }
572
573 NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx,
574                                  struct dcerpc_binding_handle *h,
575                                  struct policy_handle *key_hnd,
576                                  uint32_t *pnum_subkeys,
577                                  const char ***psubkeys,
578                                  WERROR *pwerr)
579 {
580         const char **subkeys;
581         uint32_t num_subkeys, max_subkeylen, max_classlen;
582         uint32_t num_values, max_valnamelen, max_valbufsize;
583         uint32_t i;
584         NTTIME last_changed_time;
585         uint32_t secdescsize;
586         struct winreg_String classname;
587         NTSTATUS status;
588         TALLOC_CTX *tmp_ctx;
589
590         tmp_ctx = talloc_stackframe();
591         if (tmp_ctx == NULL) {
592                 return NT_STATUS_NO_MEMORY;
593         }
594
595         ZERO_STRUCT(classname);
596
597         status = dcerpc_winreg_QueryInfoKey(h,
598                                             tmp_ctx,
599                                             key_hnd,
600                                             &classname,
601                                             &num_subkeys,
602                                             &max_subkeylen,
603                                             &max_classlen,
604                                             &num_values,
605                                             &max_valnamelen,
606                                             &max_valbufsize,
607                                             &secdescsize,
608                                             &last_changed_time,
609                                             pwerr);
610         if (!NT_STATUS_IS_OK(status)) {
611                 goto error;
612         }
613         if (!W_ERROR_IS_OK(*pwerr)) {
614                 goto error;
615         }
616
617         subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
618         if (subkeys == NULL) {
619                 status = NT_STATUS_NO_MEMORY;
620                 goto error;
621         }
622
623         if (num_subkeys == 0) {
624                 subkeys[0] = talloc_strdup(subkeys, "");
625                 if (subkeys[0] == NULL) {
626                         status = NT_STATUS_NO_MEMORY;
627                         goto error;
628                 }
629                 *pnum_subkeys = 0;
630                 if (psubkeys) {
631                         *psubkeys = talloc_move(mem_ctx, &subkeys);
632                 }
633
634                 TALLOC_FREE(tmp_ctx);
635                 return NT_STATUS_OK;
636         }
637
638         for (i = 0; i < num_subkeys; i++) {
639                 char c = '\0';
640                 char n = '\0';
641                 char *name = NULL;
642                 struct winreg_StringBuf class_buf;
643                 struct winreg_StringBuf name_buf;
644                 NTTIME modtime;
645
646                 class_buf.name = &c;
647                 class_buf.size = max_classlen + 2;
648                 class_buf.length = 0;
649
650                 name_buf.name = &n;
651                 name_buf.size = max_subkeylen + 2;
652                 name_buf.length = 0;
653
654                 ZERO_STRUCT(modtime);
655
656                 status = dcerpc_winreg_EnumKey(h,
657                                                tmp_ctx,
658                                                key_hnd,
659                                                i,
660                                                &name_buf,
661                                                &class_buf,
662                                                &modtime,
663                                                pwerr);
664                 if (!NT_STATUS_IS_OK(status)) {
665                         DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
666                                   nt_errstr(status)));
667                         goto error;
668                 }
669
670                 if (W_ERROR_EQUAL(*pwerr, WERR_NO_MORE_ITEMS)) {
671                         *pwerr = WERR_OK;
672                         break;
673                 }
674                 if (!W_ERROR_IS_OK(*pwerr)) {
675                         DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
676                                   win_errstr(*pwerr)));
677                         goto error;
678                 }
679
680                 if (name_buf.name == NULL) {
681                         *pwerr = WERR_INVALID_PARAMETER;
682                         goto error;
683                 }
684
685                 name = talloc_strdup(subkeys, name_buf.name);
686                 if (name == NULL) {
687                         status = NT_STATUS_NO_MEMORY;
688                         goto error;
689                 }
690
691                 subkeys[i] = name;
692         }
693
694         *pnum_subkeys = num_subkeys;
695         if (psubkeys) {
696                 *psubkeys = talloc_move(mem_ctx, &subkeys);
697         }
698
699  error:
700         TALLOC_FREE(tmp_ctx);
701
702         return status;
703 }
704
705 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */