6006cab1ac62fda406e738b4a0ee3c32c014cd02
[vlendec/samba-autobuild/.git] / source3 / rpcclient / cmd_winreg.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Guenther Deschner 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "rpcclient.h"
23 #include "../librpc/gen_ndr/ndr_winreg_c.h"
24 #include "../librpc/gen_ndr/ndr_misc.h"
25
26 static WERROR cmd_winreg_enumkeys(struct rpc_pipe_client *cli,
27                                   TALLOC_CTX *mem_ctx, int argc,
28                                   const char **argv)
29 {
30         NTSTATUS status;
31         WERROR werr;
32         struct policy_handle handle;
33         uint32_t enum_index = 0;
34         struct winreg_StringBuf name;
35         struct dcerpc_binding_handle *b = cli->binding_handle;
36
37         if (argc < 2) {
38                 printf("usage: %s [name]\n", argv[0]);
39                 return WERR_OK;
40         }
41
42         status = dcerpc_winreg_OpenHKLM(b, mem_ctx,
43                                         NULL,
44                                         SEC_FLAG_MAXIMUM_ALLOWED,
45                                         &handle,
46                                         &werr);
47         if (!NT_STATUS_IS_OK(status)) {
48                 return ntstatus_to_werror(status);
49         }
50         if (!W_ERROR_IS_OK(werr)) {
51                 return werr;
52         }
53
54         ZERO_STRUCT(name);
55
56         name.name = argv[1];
57         name.length = strlen_m_term_null(name.name)*2;
58         name.size = name.length;
59
60         status = dcerpc_winreg_EnumKey(b, mem_ctx,
61                                        &handle,
62                                        enum_index,
63                                        &name,
64                                        NULL,
65                                        NULL,
66                                        &werr);
67         if (!NT_STATUS_IS_OK(status)) {
68                 return ntstatus_to_werror(status);
69         }
70         if (!W_ERROR_IS_OK(werr)) {
71                 return werr;
72         }
73
74         return WERR_OK;
75 }
76
77 /****************************************************************************
78 ****************************************************************************/
79
80 static WERROR pull_winreg_Data(TALLOC_CTX *mem_ctx,
81                                const DATA_BLOB *blob,
82                                union winreg_Data *data,
83                                enum winreg_Type type)
84 {
85         enum ndr_err_code ndr_err;
86         ndr_err = ndr_pull_union_blob(blob, mem_ctx, data, type,
87                         (ndr_pull_flags_fn_t)ndr_pull_winreg_Data);
88         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
89                 return WERR_GEN_FAILURE;
90         }
91         return WERR_OK;
92 }
93
94 /****************************************************************************
95 ****************************************************************************/
96
97 static void display_winreg_data(const char *v,
98                                 enum winreg_Type type,
99                                 uint8_t *data,
100                                 uint32_t length)
101 {
102         int i;
103         union winreg_Data r;
104         DATA_BLOB blob = data_blob_const(data, length);
105         WERROR result;
106
107         result = pull_winreg_Data(talloc_tos(), &blob, &r, type);
108         if (!W_ERROR_IS_OK(result)) {
109                 return;
110         }
111
112         switch (type) {
113         case REG_DWORD:
114                 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
115                 break;
116         case REG_SZ:
117                 printf("%s: REG_SZ: %s\n", v, r.string);
118                 break;
119         case REG_BINARY: {
120                 char *hex = hex_encode_talloc(NULL,
121                         r.binary.data, r.binary.length);
122                 size_t len;
123                 printf("%s: REG_BINARY:", v);
124                 len = strlen(hex);
125                 for (i=0; i<len; i++) {
126                         if (hex[i] == '\0') {
127                                 break;
128                         }
129                         if (i%40 == 0) {
130                                 putchar('\n');
131                         }
132                         putchar(hex[i]);
133                 }
134                 TALLOC_FREE(hex);
135                 putchar('\n');
136                 break;
137         }
138         case REG_MULTI_SZ:
139                 printf("%s: REG_MULTI_SZ: ", v);
140                 for (i=0; r.string_array[i] != NULL; i++) {
141                         printf("%s ", r.string_array[i]);
142                 }
143                 printf("\n");
144                 break;
145         default:
146                 printf("%s: unknown type 0x%02x:\n", v, type);
147                 break;
148         }
149 }
150
151
152 static WERROR cmd_winreg_querymultiplevalues_ex(struct rpc_pipe_client *cli,
153                                                 TALLOC_CTX *mem_ctx, int argc,
154                                                 const char **argv, bool multiplevalues2)
155 {
156         NTSTATUS status;
157         WERROR werr;
158         struct policy_handle handle, key_handle;
159         struct winreg_String key_name = { 0, };
160         struct dcerpc_binding_handle *b = cli->binding_handle;
161
162         struct QueryMultipleValue *values_in, *values_out;
163         uint32_t num_values;
164         uint8_t *buffer = NULL;
165         int i;
166
167
168         if (argc < 2) {
169                 printf("usage: %s [key] [value1] [value2] ...\n", argv[0]);
170                 return WERR_OK;
171         }
172
173         status = dcerpc_winreg_OpenHKLM(b, mem_ctx,
174                                         NULL,
175                                         SEC_FLAG_MAXIMUM_ALLOWED,
176                                         &handle,
177                                         &werr);
178         if (!NT_STATUS_IS_OK(status)) {
179                 return ntstatus_to_werror(status);
180         }
181         if (!W_ERROR_IS_OK(werr)) {
182                 return werr;
183         }
184
185         key_name.name = argv[1];
186
187         status = dcerpc_winreg_OpenKey(b, mem_ctx,
188                                        &handle,
189                                        key_name,
190                                        0, /* options */
191                                        SEC_FLAG_MAXIMUM_ALLOWED,
192                                        &key_handle,
193                                        &werr);
194         if (!NT_STATUS_IS_OK(status)) {
195                 return ntstatus_to_werror(status);
196         }
197         if (!W_ERROR_IS_OK(werr)) {
198                 return werr;
199         }
200
201         num_values = argc-2;
202
203         values_in = talloc_zero_array(mem_ctx, struct QueryMultipleValue, num_values);
204         if (values_in == NULL) {
205                 return WERR_NOT_ENOUGH_MEMORY;
206         }
207
208         values_out = talloc_zero_array(mem_ctx, struct QueryMultipleValue, num_values);
209         if (values_out == NULL) {
210                 return WERR_NOT_ENOUGH_MEMORY;
211         }
212
213         for (i=0; i < num_values; i++) {
214
215                 values_in[i].ve_valuename = talloc_zero(values_in, struct winreg_ValNameBuf);
216                 if (values_in[i].ve_valuename == NULL) {
217                         return WERR_NOT_ENOUGH_MEMORY;
218                 }
219
220                 values_in[i].ve_valuename->name = talloc_strdup(values_in[i].ve_valuename, argv[i+2]);
221                 values_in[i].ve_valuename->length = strlen_m_term_null(values_in[i].ve_valuename->name)*2;
222                 values_in[i].ve_valuename->size = values_in[i].ve_valuename->length;
223         }
224
225         if (multiplevalues2) {
226
227                 uint32_t offered = 0, needed = 0;
228
229                 status = dcerpc_winreg_QueryMultipleValues2(b, mem_ctx,
230                                                            &key_handle,
231                                                            values_in,
232                                                            values_out,
233                                                            num_values,
234                                                            buffer,
235                                                            &offered,
236                                                            &needed,
237                                                            &werr);
238                 if (!NT_STATUS_IS_OK(status)) {
239                         return ntstatus_to_werror(status);
240                 }
241                 if (W_ERROR_EQUAL(werr, WERR_MORE_DATA)) {
242                         offered = needed;
243
244                         buffer = talloc_zero_array(mem_ctx, uint8_t, needed);
245                         if (buffer == NULL) {
246                                 return WERR_NOT_ENOUGH_MEMORY;
247                         }
248
249                         status = dcerpc_winreg_QueryMultipleValues2(b, mem_ctx,
250                                                                     &key_handle,
251                                                                     values_in,
252                                                                     values_out,
253                                                                     num_values,
254                                                                     buffer,
255                                                                     &offered,
256                                                                     &needed,
257                                                                     &werr);
258                         if (!NT_STATUS_IS_OK(status)) {
259                                 return ntstatus_to_werror(status);
260                         }
261                         if (!W_ERROR_IS_OK(werr)) {
262                                 return werr;
263                         }
264                 }
265
266         } else {
267
268                 uint32_t buffer_size = 0xff;
269
270                 buffer = talloc_zero_array(mem_ctx, uint8_t, buffer_size);
271                 if (buffer == NULL) {
272                         return WERR_NOT_ENOUGH_MEMORY;
273                 }
274
275                 status = dcerpc_winreg_QueryMultipleValues(b, mem_ctx,
276                                                            &key_handle,
277                                                            values_in,
278                                                            values_out,
279                                                            num_values,
280                                                            buffer,
281                                                            &buffer_size,
282                                                            &werr);
283                 if (!NT_STATUS_IS_OK(status)) {
284                         return ntstatus_to_werror(status);
285                 }
286                 if (!W_ERROR_IS_OK(werr)) {
287                         return werr;
288                 }
289         }
290
291         for (i=0; i < num_values; i++) {
292                 if (buffer) {
293                         display_winreg_data(values_in[i].ve_valuename->name,
294                                             values_out[i].ve_type,
295                                             buffer + values_out[i].ve_valueptr,
296                                             values_out[i].ve_valuelen);
297                 }
298         }
299
300         return WERR_OK;
301 }
302
303 static WERROR cmd_winreg_querymultiplevalues(struct rpc_pipe_client *cli,
304                                              TALLOC_CTX *mem_ctx, int argc,
305                                              const char **argv)
306 {
307         return cmd_winreg_querymultiplevalues_ex(cli, mem_ctx, argc, argv, false);
308 }
309
310 static WERROR cmd_winreg_querymultiplevalues2(struct rpc_pipe_client *cli,
311                                               TALLOC_CTX *mem_ctx, int argc,
312                                               const char **argv)
313 {
314         return cmd_winreg_querymultiplevalues_ex(cli, mem_ctx, argc, argv, true);
315 }
316
317 /* List of commands exported by this module */
318
319 struct cmd_set winreg_commands[] = {
320
321         { "WINREG" },
322         { "winreg_enumkey", RPC_RTYPE_WERROR, NULL, cmd_winreg_enumkeys, &ndr_table_winreg, NULL, "Enumerate Keys", "" },
323         { "querymultiplevalues", RPC_RTYPE_WERROR, NULL, cmd_winreg_querymultiplevalues, &ndr_table_winreg, NULL, "Query multiple values", "" },
324         { "querymultiplevalues2", RPC_RTYPE_WERROR, NULL, cmd_winreg_querymultiplevalues2, &ndr_table_winreg, NULL, "Query multiple values", "" },
325         { NULL }
326 };