3731fc7e799ef1e59ae16737a68ebd4321783c95
[nivanova/samba-autobuild/.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;
37         uint32_t value_len = 0;
38         uint32_t data_size = 0;
39         WERROR result = WERR_OK;
40         NTSTATUS status;
41         DATA_BLOB blob;
42
43         wvalue.name = value;
44
45         status = dcerpc_winreg_QueryValue(h,
46                                           mem_ctx,
47                                           key_handle,
48                                           &wvalue,
49                                           &type,
50                                           NULL,
51                                           &data_size,
52                                           &value_len,
53                                           &result);
54         if (!NT_STATUS_IS_OK(status)) {
55                 return status;
56         }
57         if (!W_ERROR_IS_OK(result)) {
58                 *pwerr = result;
59                 return status;
60         }
61
62         if (type != REG_DWORD) {
63                 *pwerr = WERR_INVALID_DATATYPE;
64                 return status;
65         }
66
67         if (data_size != 4) {
68                 *pwerr = WERR_INVALID_DATA;
69                 return status;
70         }
71
72         blob = data_blob_talloc(mem_ctx, NULL, data_size);
73         if (blob.data == NULL) {
74                 *pwerr = WERR_NOMEM;
75                 return status;
76         }
77         value_len = 0;
78
79         status = dcerpc_winreg_QueryValue(h,
80                                           mem_ctx,
81                                           key_handle,
82                                           &wvalue,
83                                           &type,
84                                           blob.data,
85                                           &data_size,
86                                           &value_len,
87                                           &result);
88         if (!NT_STATUS_IS_OK(status)) {
89                 return status;
90         }
91         if (!W_ERROR_IS_OK(result)) {
92                 *pwerr = result;
93                 return status;
94         }
95
96         if (data) {
97                 *data = IVAL(blob.data, 0);
98         }
99
100         return status;
101 }
102
103 NTSTATUS dcerpc_winreg_query_binary(TALLOC_CTX *mem_ctx,
104                                     struct dcerpc_binding_handle *h,
105                                     struct policy_handle *key_handle,
106                                     const char *value,
107                                     DATA_BLOB *data,
108                                     WERROR *pwerr)
109 {
110         struct winreg_String wvalue;
111         enum winreg_Type type;
112         WERROR result = WERR_OK;
113         uint32_t value_len = 0;
114         uint32_t data_size = 0;
115         NTSTATUS status;
116         DATA_BLOB blob;
117
118         wvalue.name = value;
119
120         status = dcerpc_winreg_QueryValue(h,
121                                           mem_ctx,
122                                           key_handle,
123                                           &wvalue,
124                                           &type,
125                                           NULL,
126                                           &data_size,
127                                           &value_len,
128                                           &result);
129         if (!NT_STATUS_IS_OK(status)) {
130                 return status;
131         }
132         if (!W_ERROR_IS_OK(result)) {
133                 *pwerr = result;
134                 return status;
135         }
136
137         if (type != REG_BINARY) {
138                 *pwerr = WERR_INVALID_DATATYPE;
139                 return status;
140         }
141
142         blob = data_blob_talloc(mem_ctx, NULL, data_size);
143         if (blob.data == NULL) {
144                 *pwerr = WERR_NOMEM;
145                 return status;
146         }
147         value_len = 0;
148
149         status = dcerpc_winreg_QueryValue(h,
150                                           mem_ctx,
151                                           key_handle,
152                                           &wvalue,
153                                           &type,
154                                           blob.data,
155                                           &data_size,
156                                           &value_len,
157                                           &result);
158         if (!NT_STATUS_IS_OK(status)) {
159                 return status;
160         }
161         if (!W_ERROR_IS_OK(result)) {
162                 *pwerr = result;
163                 return status;
164         }
165
166         if (data) {
167                 data->data = blob.data;
168                 data->length = blob.length;
169         }
170
171         return status;
172 }
173
174 NTSTATUS dcerpc_winreg_query_multi_sz(TALLOC_CTX *mem_ctx,
175                                       struct dcerpc_binding_handle *h,
176                                       struct policy_handle *key_handle,
177                                       const char *value,
178                                       const char ***data,
179                                       WERROR *pwerr)
180 {
181         struct winreg_String wvalue;
182         enum winreg_Type type;
183         WERROR result = WERR_OK;
184         uint32_t value_len = 0;
185         uint32_t data_size = 0;
186         NTSTATUS status;
187         DATA_BLOB blob;
188
189         wvalue.name = value;
190
191         status = dcerpc_winreg_QueryValue(h,
192                                           mem_ctx,
193                                           key_handle,
194                                           &wvalue,
195                                           &type,
196                                           NULL,
197                                           &data_size,
198                                           &value_len,
199                                           &result);
200         if (!NT_STATUS_IS_OK(status)) {
201                 return status;
202         }
203         if (!W_ERROR_IS_OK(result)) {
204                 *pwerr = result;
205                 return status;
206         }
207
208         if (type != REG_MULTI_SZ) {
209                 *pwerr = WERR_INVALID_DATATYPE;
210                 return status;
211         }
212
213         blob = data_blob_talloc(mem_ctx, NULL, data_size);
214         if (blob.data == NULL) {
215                 *pwerr = WERR_NOMEM;
216                 return status;
217         }
218         value_len = 0;
219
220         status = dcerpc_winreg_QueryValue(h,
221                                           mem_ctx,
222                                           key_handle,
223                                           &wvalue,
224                                           &type,
225                                           blob.data,
226                                           &data_size,
227                                           &value_len,
228                                           &result);
229         if (!NT_STATUS_IS_OK(status)) {
230                 return status;
231         }
232         if (!W_ERROR_IS_OK(result)) {
233                 *pwerr = result;
234                 return status;
235         }
236
237         if (data) {
238                 bool ok;
239
240                 ok = pull_reg_multi_sz(mem_ctx, &blob, data);
241                 if (!ok) {
242                         *pwerr = WERR_NOMEM;
243                 }
244         }
245
246         return status;
247 }
248
249 NTSTATUS dcerpc_winreg_query_sz(TALLOC_CTX *mem_ctx,
250                                       struct dcerpc_binding_handle *h,
251                                       struct policy_handle *key_handle,
252                                       const char *value,
253                                       const char **data,
254                                       WERROR *pwerr)
255 {
256         struct winreg_String wvalue;
257         enum winreg_Type type;
258         WERROR result = WERR_OK;
259         uint32_t value_len = 0;
260         uint32_t data_size = 0;
261         NTSTATUS status;
262         DATA_BLOB blob;
263
264         wvalue.name = value;
265
266         status = dcerpc_winreg_QueryValue(h,
267                                           mem_ctx,
268                                           key_handle,
269                                           &wvalue,
270                                           &type,
271                                           NULL,
272                                           &data_size,
273                                           &value_len,
274                                           &result);
275         if (!NT_STATUS_IS_OK(status)) {
276                 return status;
277         }
278         if (!W_ERROR_IS_OK(result)) {
279                 *pwerr = result;
280                 return status;
281         }
282
283         if (type != REG_SZ) {
284                 *pwerr = WERR_INVALID_DATATYPE;
285                 return status;
286         }
287
288         blob = data_blob_talloc(mem_ctx, NULL, data_size);
289         if (blob.data == NULL) {
290                 *pwerr = WERR_NOMEM;
291                 return status;
292         }
293         value_len = 0;
294
295         status = dcerpc_winreg_QueryValue(h,
296                                           mem_ctx,
297                                           key_handle,
298                                           &wvalue,
299                                           &type,
300                                           blob.data,
301                                           &data_size,
302                                           &value_len,
303                                           &result);
304         if (!NT_STATUS_IS_OK(status)) {
305                 return status;
306         }
307         if (!W_ERROR_IS_OK(result)) {
308                 *pwerr = result;
309                 return status;
310         }
311
312         if (data) {
313                 bool ok;
314
315                 ok = pull_reg_sz(mem_ctx, &blob, data);
316                 if (!ok) {
317                         *pwerr = WERR_NOMEM;
318                 }
319         }
320
321         return status;
322 }
323
324 NTSTATUS dcerpc_winreg_query_sd(TALLOC_CTX *mem_ctx,
325                                 struct dcerpc_binding_handle *h,
326                                 struct policy_handle *key_handle,
327                                 const char *value,
328                                 struct security_descriptor **data,
329                                 WERROR *pwerr)
330 {
331         WERROR result = WERR_OK;
332         NTSTATUS status;
333         DATA_BLOB blob;
334
335         status = dcerpc_winreg_query_binary(mem_ctx,
336                                             h,
337                                             key_handle,
338                                             value,
339                                             &blob,
340                                             &result);
341         if (!NT_STATUS_IS_OK(status)) {
342                 return status;
343         }
344         if (!W_ERROR_IS_OK(result)) {
345                 *pwerr = result;
346                 return status;
347         }
348
349         if (data) {
350                 struct security_descriptor *sd;
351                 enum ndr_err_code ndr_err;
352
353                 sd = talloc_zero(mem_ctx, struct security_descriptor);
354                 if (sd == NULL) {
355                         *pwerr = WERR_NOMEM;
356                         return NT_STATUS_OK;
357                 }
358
359                 ndr_err = ndr_pull_struct_blob(&blob,
360                                                sd,
361                                                sd,
362                                                (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
363                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
364                         DEBUG(2, ("dcerpc_winreg_query_sd: Failed to marshall "
365                                   "security descriptor\n"));
366                         *pwerr = WERR_NOMEM;
367                         return NT_STATUS_OK;
368                 }
369
370                 *data = sd;
371         }
372
373         return status;
374 }
375
376 NTSTATUS dcerpc_winreg_set_dword(TALLOC_CTX *mem_ctx,
377                                  struct dcerpc_binding_handle *h,
378                                  struct policy_handle *key_handle,
379                                  const char *value,
380                                  uint32_t data,
381                                  WERROR *pwerr)
382 {
383         struct winreg_String wvalue = { 0, };
384         DATA_BLOB blob;
385         WERROR result = WERR_OK;
386         NTSTATUS status;
387
388         wvalue.name = value;
389         blob = data_blob_talloc(mem_ctx, NULL, 4);
390         SIVAL(blob.data, 0, data);
391
392         status = dcerpc_winreg_SetValue(h,
393                                         mem_ctx,
394                                         key_handle,
395                                         wvalue,
396                                         REG_DWORD,
397                                         blob.data,
398                                         blob.length,
399                                         &result);
400         if (!NT_STATUS_IS_OK(status)) {
401                 return status;
402         }
403         if (!W_ERROR_IS_OK(result)) {
404                 *pwerr = result;
405         }
406
407         return status;
408 }
409
410 NTSTATUS dcerpc_winreg_set_sz(TALLOC_CTX *mem_ctx,
411                               struct dcerpc_binding_handle *h,
412                               struct policy_handle *key_handle,
413                               const char *value,
414                               const char *data,
415                               WERROR *pwerr)
416 {
417         struct winreg_String wvalue = { 0, };
418         DATA_BLOB blob;
419         WERROR result = WERR_OK;
420         NTSTATUS status;
421
422         wvalue.name = value;
423         if (data == NULL) {
424                 blob = data_blob_string_const("");
425         } else {
426                 if (!push_reg_sz(mem_ctx, &blob, data)) {
427                         DEBUG(2, ("dcerpc_winreg_set_sz: Could not marshall "
428                                   "string %s for %s\n",
429                                   data, wvalue.name));
430                         *pwerr = WERR_NOMEM;
431                         return NT_STATUS_OK;
432                 }
433         }
434
435         status = dcerpc_winreg_SetValue(h,
436                                         mem_ctx,
437                                         key_handle,
438                                         wvalue,
439                                         REG_SZ,
440                                         blob.data,
441                                         blob.length,
442                                         &result);
443         if (!NT_STATUS_IS_OK(status)) {
444                 return status;
445         }
446         if (!W_ERROR_IS_OK(result)) {
447                 *pwerr = result;
448         }
449
450         return status;
451 }
452
453 NTSTATUS dcerpc_winreg_set_expand_sz(TALLOC_CTX *mem_ctx,
454                                      struct dcerpc_binding_handle *h,
455                                      struct policy_handle *key_handle,
456                                      const char *value,
457                                      const char *data,
458                                      WERROR *pwerr)
459 {
460         struct winreg_String wvalue = { 0, };
461         DATA_BLOB blob;
462         WERROR result = WERR_OK;
463         NTSTATUS status;
464
465         wvalue.name = value;
466         if (data == NULL) {
467                 blob = data_blob_string_const("");
468         } else {
469                 if (!push_reg_sz(mem_ctx, &blob, data)) {
470                         DEBUG(2, ("dcerpc_winreg_set_expand_sz: Could not marshall "
471                                   "string %s for %s\n",
472                                   data, wvalue.name));
473                         *pwerr = WERR_NOMEM;
474                         return NT_STATUS_OK;
475                 }
476         }
477
478         status = dcerpc_winreg_SetValue(h,
479                                         mem_ctx,
480                                         key_handle,
481                                         wvalue,
482                                         REG_EXPAND_SZ,
483                                         blob.data,
484                                         blob.length,
485                                         &result);
486         if (!NT_STATUS_IS_OK(status)) {
487                 return status;
488         }
489         if (!W_ERROR_IS_OK(result)) {
490                 *pwerr = result;
491         }
492
493         return status;
494 }
495
496 NTSTATUS dcerpc_winreg_set_multi_sz(TALLOC_CTX *mem_ctx,
497                                     struct dcerpc_binding_handle *h,
498                                     struct policy_handle *key_handle,
499                                     const char *value,
500                                     const char **data,
501                                     WERROR *pwerr)
502 {
503         struct winreg_String wvalue = { 0, };
504         DATA_BLOB blob;
505         WERROR result = WERR_OK;
506         NTSTATUS status;
507
508         wvalue.name = value;
509         if (!push_reg_multi_sz(mem_ctx, &blob, data)) {
510                 DEBUG(2, ("dcerpc_winreg_set_multi_sz: Could not marshall "
511                           "string multi sz for %s\n",
512                           wvalue.name));
513                 *pwerr = WERR_NOMEM;
514                 return NT_STATUS_OK;
515         }
516
517         status = dcerpc_winreg_SetValue(h,
518                                         mem_ctx,
519                                         key_handle,
520                                         wvalue,
521                                         REG_MULTI_SZ,
522                                         blob.data,
523                                         blob.length,
524                                         &result);
525         if (!NT_STATUS_IS_OK(status)) {
526                 return status;
527         }
528         if (!W_ERROR_IS_OK(result)) {
529                 *pwerr = result;
530         }
531
532         return status;
533 }
534
535 NTSTATUS dcerpc_winreg_set_binary(TALLOC_CTX *mem_ctx,
536                                   struct dcerpc_binding_handle *h,
537                                   struct policy_handle *key_handle,
538                                   const char *value,
539                                   DATA_BLOB *data,
540                                   WERROR *pwerr)
541 {
542         struct winreg_String wvalue = { 0, };
543         WERROR result = WERR_OK;
544         NTSTATUS status;
545
546         wvalue.name = value;
547
548         status = dcerpc_winreg_SetValue(h,
549                                         mem_ctx,
550                                         key_handle,
551                                         wvalue,
552                                         REG_BINARY,
553                                         data->data,
554                                         data->length,
555                                         &result);
556         if (!NT_STATUS_IS_OK(status)) {
557                 return status;
558         }
559         if (!W_ERROR_IS_OK(result)) {
560                 *pwerr = result;
561         }
562
563         return status;
564 }
565
566 NTSTATUS dcerpc_winreg_set_sd(TALLOC_CTX *mem_ctx,
567                               struct dcerpc_binding_handle *h,
568                               struct policy_handle *key_handle,
569                               const char *value,
570                               const struct security_descriptor *data,
571                               WERROR *pwerr)
572 {
573         enum ndr_err_code ndr_err;
574         DATA_BLOB blob;
575
576         ndr_err = ndr_push_struct_blob(&blob,
577                                        mem_ctx,
578                                        data,
579                                        (ndr_push_flags_fn_t) ndr_push_security_descriptor);
580         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
581                 DEBUG(2, ("dcerpc_winreg_set_sd: Failed to marshall security "
582                           "descriptor\n"));
583                 *pwerr = WERR_NOMEM;
584                 return NT_STATUS_OK;
585         }
586
587         return dcerpc_winreg_set_binary(mem_ctx,
588                                         h,
589                                         key_handle,
590                                         value,
591                                         &blob,
592                                         pwerr);
593 }
594
595 NTSTATUS dcerpc_winreg_add_multi_sz(TALLOC_CTX *mem_ctx,
596                                     struct dcerpc_binding_handle *h,
597                                     struct policy_handle *key_handle,
598                                     const char *value,
599                                     const char *data,
600                                     WERROR *pwerr)
601 {
602         const char **a = NULL;
603         const char **p;
604         uint32_t i;
605         WERROR result = WERR_OK;
606         NTSTATUS status;
607
608         status = dcerpc_winreg_query_multi_sz(mem_ctx,
609                                               h,
610                                               key_handle,
611                                               value,
612                                               &a,
613                                               &result);
614
615         /* count the elements */
616         for (p = a, i = 0; p && *p; p++, i++);
617
618         p = talloc_realloc(mem_ctx, a, const char *, i + 2);
619         if (p == NULL) {
620                 *pwerr = WERR_NOMEM;
621                 return NT_STATUS_OK;
622         }
623
624         p[i] = data;
625         p[i + 1] = NULL;
626
627         status = dcerpc_winreg_set_multi_sz(mem_ctx,
628                                             h,
629                                             key_handle,
630                                             value,
631                                             p,
632                                             pwerr);
633
634         return status;
635 }
636
637 NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx,
638                                  struct dcerpc_binding_handle *h,
639                                  struct policy_handle *key_hnd,
640                                  uint32_t *pnum_subkeys,
641                                  const char ***psubkeys,
642                                  WERROR *pwerr)
643 {
644         const char **subkeys;
645         uint32_t num_subkeys, max_subkeylen, max_classlen;
646         uint32_t num_values, max_valnamelen, max_valbufsize;
647         uint32_t i;
648         NTTIME last_changed_time;
649         uint32_t secdescsize;
650         struct winreg_String classname;
651         WERROR result = WERR_OK;
652         NTSTATUS status;
653         TALLOC_CTX *tmp_ctx;
654
655         tmp_ctx = talloc_stackframe();
656         if (tmp_ctx == NULL) {
657                 return NT_STATUS_NO_MEMORY;
658         }
659
660         ZERO_STRUCT(classname);
661
662         status = dcerpc_winreg_QueryInfoKey(h,
663                                             tmp_ctx,
664                                             key_hnd,
665                                             &classname,
666                                             &num_subkeys,
667                                             &max_subkeylen,
668                                             &max_classlen,
669                                             &num_values,
670                                             &max_valnamelen,
671                                             &max_valbufsize,
672                                             &secdescsize,
673                                             &last_changed_time,
674                                             &result);
675         if (!NT_STATUS_IS_OK(status)) {
676                 goto error;
677         }
678         if (!W_ERROR_IS_OK(result)) {
679                 *pwerr = result;
680                 goto error;
681         }
682
683         subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
684         if (subkeys == NULL) {
685                 *pwerr = WERR_NOMEM;
686                 goto error;
687         }
688
689         if (num_subkeys == 0) {
690                 subkeys[0] = talloc_strdup(subkeys, "");
691                 if (subkeys[0] == NULL) {
692                         *pwerr = WERR_NOMEM;
693                         goto error;
694                 }
695                 *pnum_subkeys = 0;
696                 if (psubkeys) {
697                         *psubkeys = talloc_move(mem_ctx, &subkeys);
698                 }
699
700                 TALLOC_FREE(tmp_ctx);
701                 return NT_STATUS_OK;
702         }
703
704         for (i = 0; i < num_subkeys; i++) {
705                 char c = '\0';
706                 char n = '\0';
707                 char *name = NULL;
708                 struct winreg_StringBuf class_buf;
709                 struct winreg_StringBuf name_buf;
710                 NTTIME modtime;
711
712                 class_buf.name = &c;
713                 class_buf.size = max_classlen + 2;
714                 class_buf.length = 0;
715
716                 name_buf.name = &n;
717                 name_buf.size = max_subkeylen + 2;
718                 name_buf.length = 0;
719
720                 ZERO_STRUCT(modtime);
721
722                 status = dcerpc_winreg_EnumKey(h,
723                                                tmp_ctx,
724                                                key_hnd,
725                                                i,
726                                                &name_buf,
727                                                &class_buf,
728                                                &modtime,
729                                                &result);
730                 if (!NT_STATUS_IS_OK(status)) {
731                         DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
732                                   nt_errstr(status)));
733                         goto error;
734                 }
735
736                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
737                         *pwerr = WERR_OK;
738                         break;
739                 }
740                 if (!W_ERROR_IS_OK(result)) {
741                         DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
742                                   win_errstr(result)));
743                         *pwerr = result;
744                         goto error;
745                 }
746
747                 if (name_buf.name == NULL) {
748                         *pwerr = WERR_INVALID_PARAMETER;
749                         goto error;
750                 }
751
752                 name = talloc_strdup(subkeys, name_buf.name);
753                 if (name == NULL) {
754                         *pwerr = WERR_NOMEM;
755                         goto error;
756                 }
757
758                 subkeys[i] = name;
759         }
760
761         *pnum_subkeys = num_subkeys;
762         if (psubkeys) {
763                 *psubkeys = talloc_move(mem_ctx, &subkeys);
764         }
765
766  error:
767         TALLOC_FREE(tmp_ctx);
768
769         return status;
770 }
771
772 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */