s3:rpcclient: use ndr_dfs_c.h instead of cli_dfs.h
[ab/samba.git/.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/cli_winreg.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
36         if (argc < 2) {
37                 printf("usage: %s [name]\n", argv[0]);
38                 return WERR_OK;
39         }
40
41         status = rpccli_winreg_OpenHKLM(cli, mem_ctx,
42                                         NULL,
43                                         SEC_FLAG_MAXIMUM_ALLOWED,
44                                         &handle,
45                                         &werr);
46         if (!NT_STATUS_IS_OK(status)) {
47                 return ntstatus_to_werror(status);
48         }
49         if (!W_ERROR_IS_OK(werr)) {
50                 return werr;
51         }
52
53         ZERO_STRUCT(name);
54
55         name.name = argv[1];
56         name.length = strlen_m_term_null(name.name)*2;
57         name.size = name.length;
58
59         status = rpccli_winreg_EnumKey(cli, mem_ctx,
60                                        &handle,
61                                        enum_index,
62                                        &name,
63                                        NULL,
64                                        NULL,
65                                        &werr);
66         if (!NT_STATUS_IS_OK(status)) {
67                 return ntstatus_to_werror(status);
68         }
69         if (!W_ERROR_IS_OK(werr)) {
70                 return werr;
71         }
72
73         return WERR_OK;
74 }
75
76 /****************************************************************************
77 ****************************************************************************/
78
79 static WERROR pull_winreg_Data(TALLOC_CTX *mem_ctx,
80                                const DATA_BLOB *blob,
81                                union winreg_Data *data,
82                                enum winreg_Type type)
83 {
84         enum ndr_err_code ndr_err;
85         ndr_err = ndr_pull_union_blob(blob, mem_ctx, data, type,
86                         (ndr_pull_flags_fn_t)ndr_pull_winreg_Data);
87         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
88                 return WERR_GENERAL_FAILURE;
89         }
90         return WERR_OK;
91 }
92
93 /****************************************************************************
94 ****************************************************************************/
95
96 static void display_winreg_data(const char *v,
97                                 enum winreg_Type type,
98                                 uint8_t *data,
99                                 uint32_t length)
100 {
101         int i;
102         union winreg_Data r;
103         DATA_BLOB blob = data_blob_const(data, length);
104         WERROR result;
105
106         result = pull_winreg_Data(talloc_tos(), &blob, &r, type);
107         if (!W_ERROR_IS_OK(result)) {
108                 return;
109         }
110
111         switch (type) {
112         case REG_DWORD:
113                 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
114                 break;
115         case REG_SZ:
116                 printf("%s: REG_SZ: %s\n", v, r.string);
117                 break;
118         case REG_BINARY: {
119                 char *hex = hex_encode_talloc(NULL,
120                         r.binary.data, r.binary.length);
121                 size_t len;
122                 printf("%s: REG_BINARY:", v);
123                 len = strlen(hex);
124                 for (i=0; i<len; i++) {
125                         if (hex[i] == '\0') {
126                                 break;
127                         }
128                         if (i%40 == 0) {
129                                 putchar('\n');
130                         }
131                         putchar(hex[i]);
132                 }
133                 TALLOC_FREE(hex);
134                 putchar('\n');
135                 break;
136         }
137         case REG_MULTI_SZ:
138                 printf("%s: REG_MULTI_SZ: ", v);
139                 for (i=0; r.string_array[i] != NULL; i++) {
140                         printf("%s ", r.string_array[i]);
141                 }
142                 printf("\n");
143                 break;
144         default:
145                 printf("%s: unknown type 0x%02x:\n", v, type);
146                 break;
147         }
148 }
149
150
151 static WERROR cmd_winreg_querymultiplevalues_ex(struct rpc_pipe_client *cli,
152                                                 TALLOC_CTX *mem_ctx, int argc,
153                                                 const char **argv, bool multiplevalues2)
154 {
155         NTSTATUS status;
156         WERROR werr;
157         struct policy_handle handle, key_handle;
158         struct winreg_String key_name;
159
160         struct QueryMultipleValue *values_in, *values_out;
161         uint32_t num_values;
162         uint8_t *buffer = NULL;
163         int i;
164
165
166         if (argc < 2) {
167                 printf("usage: %s [key] [value1] [value2] ...\n", argv[0]);
168                 return WERR_OK;
169         }
170
171         status = rpccli_winreg_OpenHKLM(cli, mem_ctx,
172                                         NULL,
173                                         SEC_FLAG_MAXIMUM_ALLOWED,
174                                         &handle,
175                                         &werr);
176         if (!NT_STATUS_IS_OK(status)) {
177                 return ntstatus_to_werror(status);
178         }
179         if (!W_ERROR_IS_OK(werr)) {
180                 return werr;
181         }
182
183         key_name.name = argv[1];
184
185         status = rpccli_winreg_OpenKey(cli, mem_ctx,
186                                        &handle,
187                                        key_name,
188                                        0, /* options */
189                                        SEC_FLAG_MAXIMUM_ALLOWED,
190                                        &key_handle,
191                                        &werr);
192         if (!NT_STATUS_IS_OK(status)) {
193                 return ntstatus_to_werror(status);
194         }
195         if (!W_ERROR_IS_OK(werr)) {
196                 return werr;
197         }
198
199         num_values = argc-2;
200
201         values_in = talloc_zero_array(mem_ctx, struct QueryMultipleValue, num_values);
202         if (values_in == NULL) {
203                 return WERR_NOMEM;
204         }
205
206         values_out = talloc_zero_array(mem_ctx, struct QueryMultipleValue, num_values);
207         if (values_out == NULL) {
208                 return WERR_NOMEM;
209         }
210
211         for (i=0; i < num_values; i++) {
212
213                 values_in[i].ve_valuename = talloc_zero(values_in, struct winreg_ValNameBuf);
214                 if (values_in[i].ve_valuename == NULL) {
215                         return WERR_NOMEM;
216                 }
217
218                 values_in[i].ve_valuename->name = talloc_strdup(values_in[i].ve_valuename, argv[i+2]);
219                 values_in[i].ve_valuename->length = strlen_m_term_null(values_in[i].ve_valuename->name)*2;
220                 values_in[i].ve_valuename->size = values_in[i].ve_valuename->length;
221         }
222
223         if (multiplevalues2) {
224
225                 uint32_t offered = 0, needed = 0;
226
227                 status = rpccli_winreg_QueryMultipleValues2(cli, mem_ctx,
228                                                            &key_handle,
229                                                            values_in,
230                                                            values_out,
231                                                            num_values,
232                                                            buffer,
233                                                            &offered,
234                                                            &needed,
235                                                            &werr);
236                 if (W_ERROR_EQUAL(werr, WERR_MORE_DATA)) {
237                         offered = needed;
238
239                         buffer = talloc_zero_array(mem_ctx, uint8_t, needed);
240                         if (buffer == NULL) {
241                                 return WERR_NOMEM;
242                         }
243
244                         status = rpccli_winreg_QueryMultipleValues2(cli, mem_ctx,
245                                                                     &key_handle,
246                                                                     values_in,
247                                                                     values_out,
248                                                                     num_values,
249                                                                     buffer,
250                                                                     &offered,
251                                                                     &needed,
252                                                                     &werr);
253                         if (!NT_STATUS_IS_OK(status)) {
254                                 return ntstatus_to_werror(status);
255                         }
256                         if (!W_ERROR_IS_OK(werr)) {
257                                 return werr;
258                         }
259                 }
260
261         } else {
262
263                 uint32_t buffer_size = 0xff;
264
265                 buffer = talloc_zero_array(mem_ctx, uint8_t, buffer_size);
266                 if (buffer == NULL) {
267                         return WERR_NOMEM;
268                 }
269
270                 status = rpccli_winreg_QueryMultipleValues(cli, mem_ctx,
271                                                            &key_handle,
272                                                            values_in,
273                                                            values_out,
274                                                            num_values,
275                                                            buffer,
276                                                            &buffer_size,
277                                                            &werr);
278                 if (!NT_STATUS_IS_OK(status)) {
279                         return ntstatus_to_werror(status);
280                 }
281                 if (!W_ERROR_IS_OK(werr)) {
282                         return werr;
283                 }
284         }
285
286         for (i=0; i < num_values; i++) {
287                 if (buffer) {
288                         display_winreg_data(values_in[i].ve_valuename->name,
289                                             values_out[i].ve_type,
290                                             buffer + values_out[i].ve_valueptr,
291                                             values_out[i].ve_valuelen);
292                 }
293         }
294
295         return WERR_OK;
296 }
297
298 static WERROR cmd_winreg_querymultiplevalues(struct rpc_pipe_client *cli,
299                                              TALLOC_CTX *mem_ctx, int argc,
300                                              const char **argv)
301 {
302         return cmd_winreg_querymultiplevalues_ex(cli, mem_ctx, argc, argv, false);
303 }
304
305 static WERROR cmd_winreg_querymultiplevalues2(struct rpc_pipe_client *cli,
306                                               TALLOC_CTX *mem_ctx, int argc,
307                                               const char **argv)
308 {
309         return cmd_winreg_querymultiplevalues_ex(cli, mem_ctx, argc, argv, true);
310 }
311
312 /* List of commands exported by this module */
313
314 struct cmd_set winreg_commands[] = {
315
316         { "WINREG" },
317         { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_winreg_enumkeys, &ndr_table_winreg.syntax_id, NULL, "Enumerate Keys", "" },
318         { "querymultiplevalues", RPC_RTYPE_WERROR, NULL, cmd_winreg_querymultiplevalues, &ndr_table_winreg.syntax_id, NULL, "Query multiple values", "" },
319         { "querymultiplevalues2", RPC_RTYPE_WERROR, NULL, cmd_winreg_querymultiplevalues2, &ndr_table_winreg.syntax_id, NULL, "Query multiple values", "" },
320         { NULL }
321 };