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