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