Line data Source code
1 : /*
2 : Samba Unix/Linux SMB implementation
3 : RPC backend for the registry library
4 : Copyright (C) 2003-2007 Jelmer Vernooij, jelmer@samba.org
5 : Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
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 : #include "includes.h"
21 : #include "registry.h"
22 : #include "librpc/gen_ndr/ndr_winreg_c.h"
23 :
24 : #define MAX_NAMESIZE 512
25 : #define MAX_VALSIZE 32768
26 :
27 : struct rpc_key {
28 : struct registry_key key;
29 : struct policy_handle pol;
30 : struct dcerpc_binding_handle *binding_handle;
31 : const char* classname;
32 : uint32_t num_subkeys;
33 : uint32_t max_subkeylen;
34 : uint32_t max_classlen;
35 : uint32_t num_values;
36 : uint32_t max_valnamelen;
37 : uint32_t max_valbufsize;
38 : uint32_t secdescsize;
39 : NTTIME last_changed_time;
40 : };
41 :
42 : struct rpc_registry_context {
43 : struct registry_context context;
44 : struct dcerpc_pipe *pipe;
45 : struct dcerpc_binding_handle *binding_handle;
46 : };
47 :
48 : static struct registry_operations reg_backend_rpc;
49 :
50 : /**
51 : * This is the RPC backend for the registry library.
52 : */
53 :
54 : #define openhive(u) static WERROR open_ ## u(struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
55 : { \
56 : struct winreg_Open ## u r; \
57 : NTSTATUS status; \
58 : \
59 : ZERO_STRUCT(r); \
60 : r.in.system_name = NULL; \
61 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
62 : r.out.handle = hnd;\
63 : \
64 : status = dcerpc_winreg_Open ## u ## _r(b, mem_ctx, &r); \
65 : \
66 : if (!NT_STATUS_IS_OK(status)) { \
67 : DEBUG(1, ("OpenHive failed - %s\n", nt_errstr(status))); \
68 : return ntstatus_to_werror(status); \
69 : } \
70 : \
71 : return r.out.result;\
72 : }
73 :
74 0 : openhive(HKLM)
75 0 : openhive(HKCU)
76 0 : openhive(HKPD)
77 0 : openhive(HKU)
78 0 : openhive(HKCR)
79 0 : openhive(HKDD)
80 0 : openhive(HKCC)
81 :
82 : static struct {
83 : uint32_t hkey;
84 : WERROR (*open) (struct dcerpc_binding_handle *b, TALLOC_CTX *,
85 : struct policy_handle *h);
86 : } known_hives[] = {
87 : { HKEY_LOCAL_MACHINE, open_HKLM },
88 : { HKEY_CURRENT_USER, open_HKCU },
89 : { HKEY_CLASSES_ROOT, open_HKCR },
90 : { HKEY_PERFORMANCE_DATA, open_HKPD },
91 : { HKEY_USERS, open_HKU },
92 : { HKEY_DYN_DATA, open_HKDD },
93 : { HKEY_CURRENT_CONFIG, open_HKCC },
94 : { 0, NULL }
95 : };
96 :
97 : static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k);
98 :
99 0 : static WERROR rpc_get_predefined_key(struct registry_context *ctx,
100 : uint32_t hkey_type,
101 : struct registry_key **k)
102 : {
103 0 : int n;
104 0 : struct rpc_key *mykeydata;
105 0 : struct rpc_registry_context *rctx = talloc_get_type(ctx, struct rpc_registry_context);
106 :
107 0 : *k = NULL;
108 :
109 0 : for(n = 0; known_hives[n].hkey; n++) {
110 0 : if(known_hives[n].hkey == hkey_type)
111 0 : break;
112 : }
113 :
114 0 : if (known_hives[n].open == NULL) {
115 0 : DEBUG(1, ("No such hive %d\n", hkey_type));
116 0 : return WERR_NO_MORE_ITEMS;
117 : }
118 :
119 0 : mykeydata = talloc_zero(ctx, struct rpc_key);
120 0 : W_ERROR_HAVE_NO_MEMORY(mykeydata);
121 0 : mykeydata->key.context = ctx;
122 0 : mykeydata->binding_handle = rctx->binding_handle;
123 0 : mykeydata->num_values = -1;
124 0 : mykeydata->num_subkeys = -1;
125 0 : *k = (struct registry_key *)mykeydata;
126 0 : return known_hives[n].open(mykeydata->binding_handle, mykeydata, &mykeydata->pol);
127 : }
128 :
129 : #if 0
130 : static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
131 : {
132 : struct winreg_OpenKey r;
133 : struct rpc_key_data *mykeydata;
134 :
135 : k->backend_data = mykeydata = talloc_zero(mem_ctx, struct rpc_key_data);
136 : mykeydata->num_values = -1;
137 : mykeydata->num_subkeys = -1;
138 :
139 : /* Then, open the handle using the hive */
140 :
141 : ZERO_STRUCT(r);
142 : r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol);
143 : r.in.keyname.name = k->path;
144 : r.in.unknown = 0x00000000;
145 : r.in.access_mask = 0x02000000;
146 : r.out.handle = &mykeydata->pol;
147 :
148 : dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data,
149 : mem_ctx, &r);
150 :
151 : return r.out.result;
152 : }
153 : #endif
154 :
155 0 : static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h,
156 : const char *name, struct registry_key **key)
157 : {
158 0 : struct rpc_key *parentkeydata = talloc_get_type(h, struct rpc_key),
159 : *mykeydata;
160 0 : struct winreg_OpenKey r;
161 0 : NTSTATUS status;
162 :
163 0 : mykeydata = talloc_zero(mem_ctx, struct rpc_key);
164 0 : W_ERROR_HAVE_NO_MEMORY(mykeydata);
165 0 : mykeydata->key.context = parentkeydata->key.context;
166 0 : mykeydata->binding_handle = parentkeydata->binding_handle;
167 0 : mykeydata->num_values = -1;
168 0 : mykeydata->num_subkeys = -1;
169 0 : *key = (struct registry_key *)mykeydata;
170 :
171 : /* Then, open the handle using the hive */
172 0 : ZERO_STRUCT(r);
173 0 : r.in.parent_handle = &parentkeydata->pol;
174 0 : r.in.keyname.name = name;
175 0 : r.in.options = 0x00000000;
176 0 : r.in.access_mask = 0x02000000;
177 0 : r.out.handle = &mykeydata->pol;
178 :
179 0 : status = dcerpc_winreg_OpenKey_r(mykeydata->binding_handle, mem_ctx, &r);
180 :
181 0 : if (!NT_STATUS_IS_OK(status)) {
182 0 : DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status)));
183 0 : return ntstatus_to_werror(status);
184 : }
185 :
186 0 : return r.out.result;
187 : }
188 :
189 0 : static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx,
190 : const struct registry_key *parent,
191 : uint32_t n,
192 : const char **value_name,
193 : uint32_t *type,
194 : DATA_BLOB *data)
195 : {
196 0 : struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
197 0 : struct winreg_EnumValue r;
198 0 : struct winreg_ValNameBuf name;
199 0 : uint8_t value;
200 0 : uint32_t val_size = MAX_VALSIZE;
201 0 : uint32_t zero = 0;
202 0 : WERROR error;
203 0 : NTSTATUS status;
204 :
205 0 : if (mykeydata->num_values == -1) {
206 0 : error = rpc_query_key(mem_ctx, parent);
207 0 : if(!W_ERROR_IS_OK(error)) return error;
208 : }
209 :
210 0 : name.name = "";
211 0 : name.size = MAX_NAMESIZE;
212 :
213 0 : ZERO_STRUCT(r);
214 0 : r.in.handle = &mykeydata->pol;
215 0 : r.in.enum_index = n;
216 0 : r.in.name = &name;
217 0 : r.in.type = (enum winreg_Type *) type;
218 0 : r.in.value = &value;
219 0 : r.in.size = &val_size;
220 0 : r.in.length = &zero;
221 0 : r.out.name = &name;
222 0 : r.out.type = (enum winreg_Type *) type;
223 0 : r.out.value = &value;
224 0 : r.out.size = &val_size;
225 0 : r.out.length = &zero;
226 :
227 0 : status = dcerpc_winreg_EnumValue_r(mykeydata->binding_handle, mem_ctx, &r);
228 :
229 0 : if (!NT_STATUS_IS_OK(status)) {
230 0 : DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status)));
231 0 : return ntstatus_to_werror(status);
232 : }
233 :
234 0 : *value_name = talloc_steal(mem_ctx, r.out.name->name);
235 0 : *type = *(r.out.type);
236 0 : *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
237 :
238 0 : return r.out.result;
239 : }
240 :
241 0 : static WERROR rpc_get_value_by_name(TALLOC_CTX *mem_ctx,
242 : const struct registry_key *parent,
243 : const char *value_name,
244 : uint32_t *type,
245 : DATA_BLOB *data)
246 : {
247 0 : struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
248 0 : struct winreg_QueryValue r;
249 0 : struct winreg_String name;
250 0 : uint8_t value;
251 0 : uint32_t val_size = MAX_VALSIZE;
252 0 : uint32_t zero = 0;
253 0 : WERROR error;
254 0 : NTSTATUS status;
255 :
256 0 : if (mykeydata->num_values == -1) {
257 0 : error = rpc_query_key(mem_ctx, parent);
258 0 : if(!W_ERROR_IS_OK(error)) return error;
259 : }
260 :
261 0 : name.name = value_name;
262 :
263 0 : ZERO_STRUCT(r);
264 0 : r.in.handle = &mykeydata->pol;
265 0 : r.in.value_name = &name;
266 0 : r.in.type = (enum winreg_Type *) type;
267 0 : r.in.data = &value;
268 0 : r.in.data_size = &val_size;
269 0 : r.in.data_length = &zero;
270 0 : r.out.type = (enum winreg_Type *) type;
271 0 : r.out.data = &value;
272 0 : r.out.data_size = &val_size;
273 0 : r.out.data_length = &zero;
274 :
275 0 : status = dcerpc_winreg_QueryValue_r(mykeydata->binding_handle, mem_ctx, &r);
276 :
277 0 : if (!NT_STATUS_IS_OK(status)) {
278 0 : DEBUG(1, ("QueryValue failed - %s\n", nt_errstr(status)));
279 0 : return ntstatus_to_werror(status);
280 : }
281 :
282 0 : *type = *(r.out.type);
283 0 : *data = data_blob_talloc(mem_ctx, r.out.data, *r.out.data_length);
284 :
285 0 : return r.out.result;
286 : }
287 :
288 0 : static WERROR rpc_set_value(struct registry_key *key, const char *value_name,
289 : uint32_t type, const DATA_BLOB data)
290 : {
291 0 : struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
292 0 : struct winreg_SetValue r;
293 0 : struct winreg_String name;
294 0 : NTSTATUS status;
295 :
296 0 : name = (struct winreg_String) { .name = value_name };
297 :
298 0 : ZERO_STRUCT(r);
299 0 : r.in.handle = &mykeydata->pol;
300 0 : r.in.name = name;
301 0 : r.in.type = (enum winreg_Type)type;
302 0 : r.in.data = data.data;
303 0 : r.in.size = data.length;
304 :
305 0 : status = dcerpc_winreg_SetValue_r(mykeydata->binding_handle, key, &r);
306 0 : if (!NT_STATUS_IS_OK(status)) {
307 0 : DEBUG(1, ("SetValue failed - %s\n", nt_errstr(status)));
308 0 : return ntstatus_to_werror(status);
309 : }
310 :
311 0 : return r.out.result;
312 : }
313 :
314 0 : static WERROR rpc_del_value(TALLOC_CTX *mem_ctx, struct registry_key *key,
315 : const char *value_name)
316 : {
317 0 : struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
318 0 : struct winreg_DeleteValue r;
319 0 : struct winreg_String name;
320 0 : NTSTATUS status;
321 :
322 0 : name = (struct winreg_String) { .name = value_name };
323 :
324 0 : ZERO_STRUCT(r);
325 0 : r.in.handle = &mykeydata->pol;
326 0 : r.in.value = name;
327 :
328 0 : status = dcerpc_winreg_DeleteValue_r(mykeydata->binding_handle,
329 : mem_ctx, &r);
330 0 : if (!NT_STATUS_IS_OK(status)) {
331 0 : DEBUG(1, ("DeleteValue failed - %s\n", nt_errstr(status)));
332 0 : return ntstatus_to_werror(status);
333 : }
334 :
335 0 : return r.out.result;
336 : }
337 :
338 0 : static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx,
339 : const struct registry_key *parent,
340 : uint32_t n,
341 : const char **name,
342 : const char **keyclass,
343 : NTTIME *last_changed_time)
344 : {
345 0 : struct winreg_EnumKey r;
346 0 : struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
347 0 : struct winreg_StringBuf namebuf, classbuf;
348 0 : NTTIME change_time = 0;
349 0 : NTSTATUS status;
350 :
351 0 : namebuf.name = "";
352 0 : namebuf.size = MAX_NAMESIZE;
353 0 : classbuf.name = NULL;
354 0 : classbuf.size = 0;
355 :
356 0 : ZERO_STRUCT(r);
357 0 : r.in.handle = &mykeydata->pol;
358 0 : r.in.enum_index = n;
359 0 : r.in.name = &namebuf;
360 0 : r.in.keyclass = &classbuf;
361 0 : r.in.last_changed_time = &change_time;
362 0 : r.out.name = &namebuf;
363 0 : r.out.keyclass = &classbuf;
364 0 : r.out.last_changed_time = &change_time;
365 :
366 0 : status = dcerpc_winreg_EnumKey_r(mykeydata->binding_handle, mem_ctx, &r);
367 :
368 0 : if (!NT_STATUS_IS_OK(status)) {
369 0 : DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status)));
370 0 : return ntstatus_to_werror(status);
371 : }
372 :
373 0 : if (name != NULL)
374 0 : *name = talloc_steal(mem_ctx, r.out.name->name);
375 0 : if (keyclass != NULL)
376 0 : *keyclass = talloc_steal(mem_ctx, r.out.keyclass->name);
377 0 : if (last_changed_time != NULL)
378 0 : *last_changed_time = *(r.out.last_changed_time);
379 :
380 0 : return r.out.result;
381 : }
382 :
383 0 : static WERROR rpc_add_key(TALLOC_CTX *mem_ctx,
384 : struct registry_key *parent, const char *path,
385 : const char *key_class,
386 : struct security_descriptor *sec,
387 : struct registry_key **key)
388 : {
389 0 : struct winreg_CreateKey r;
390 0 : struct rpc_key *parentkd = talloc_get_type(parent, struct rpc_key);
391 0 : struct rpc_key *rpck = talloc_zero(mem_ctx, struct rpc_key);
392 :
393 0 : NTSTATUS status;
394 :
395 0 : if (rpck == NULL) {
396 0 : return WERR_NOT_ENOUGH_MEMORY;
397 : }
398 :
399 0 : rpck->key.context = parentkd->key.context;
400 0 : rpck->binding_handle = parentkd->binding_handle;
401 0 : rpck->num_values = -1;
402 0 : rpck->num_subkeys = -1;
403 :
404 0 : ZERO_STRUCT(r);
405 0 : r.in.handle = &parentkd->pol;
406 0 : r.in.name.name = path;
407 0 : r.in.keyclass.name = NULL;
408 0 : r.in.options = 0;
409 0 : r.in.access_mask = 0x02000000;
410 0 : r.in.secdesc = NULL;
411 0 : r.in.action_taken = NULL;
412 0 : r.out.new_handle = &rpck->pol;
413 0 : r.out.action_taken = NULL;
414 :
415 0 : status = dcerpc_winreg_CreateKey_r(parentkd->binding_handle, mem_ctx, &r);
416 :
417 0 : if (!NT_STATUS_IS_OK(status)) {
418 0 : talloc_free(rpck);
419 0 : DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status)));
420 0 : return ntstatus_to_werror(status);
421 : }
422 :
423 0 : rpck->binding_handle = parentkd->binding_handle;
424 0 : *key = (struct registry_key *)rpck;
425 :
426 0 : return r.out.result;
427 : }
428 :
429 0 : static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k)
430 : {
431 0 : struct winreg_QueryInfoKey r;
432 0 : struct rpc_key *mykeydata = talloc_get_type(k, struct rpc_key);
433 0 : struct winreg_String classname;
434 0 : NTSTATUS status;
435 :
436 0 : classname.name = NULL;
437 :
438 0 : ZERO_STRUCT(r);
439 0 : r.in.handle = &mykeydata->pol;
440 0 : r.in.classname = &classname;
441 0 : r.out.classname = &classname;
442 0 : r.out.num_subkeys = &mykeydata->num_subkeys;
443 0 : r.out.max_subkeylen = &mykeydata->max_subkeylen;
444 0 : r.out.max_classlen = &mykeydata->max_classlen;
445 0 : r.out.num_values = &mykeydata->num_values;
446 0 : r.out.max_valnamelen = &mykeydata->max_valnamelen;
447 0 : r.out.max_valbufsize = &mykeydata->max_valbufsize;
448 0 : r.out.secdescsize = &mykeydata->secdescsize;
449 0 : r.out.last_changed_time = &mykeydata->last_changed_time;
450 :
451 0 : status = dcerpc_winreg_QueryInfoKey_r(mykeydata->binding_handle, mem_ctx, &r);
452 :
453 0 : if (!NT_STATUS_IS_OK(status)) {
454 0 : DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
455 0 : return ntstatus_to_werror(status);
456 : }
457 :
458 0 : mykeydata->classname = talloc_steal(mem_ctx, r.out.classname->name);
459 :
460 0 : return r.out.result;
461 : }
462 :
463 0 : static WERROR rpc_del_key(TALLOC_CTX *mem_ctx, struct registry_key *parent,
464 : const char *name)
465 : {
466 0 : NTSTATUS status;
467 0 : struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
468 0 : struct winreg_DeleteKey r;
469 :
470 0 : ZERO_STRUCT(r);
471 0 : r.in.handle = &mykeydata->pol;
472 0 : r.in.key.name = name;
473 :
474 0 : status = dcerpc_winreg_DeleteKey_r(mykeydata->binding_handle, mem_ctx, &r);
475 :
476 0 : if (!NT_STATUS_IS_OK(status)) {
477 0 : DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status)));
478 0 : return ntstatus_to_werror(status);
479 : }
480 :
481 0 : return r.out.result;
482 : }
483 :
484 0 : static WERROR rpc_get_info(TALLOC_CTX *mem_ctx, const struct registry_key *key,
485 : const char **classname,
486 : uint32_t *num_subkeys,
487 : uint32_t *num_values,
488 : NTTIME *last_changed_time,
489 : uint32_t *max_subkeylen,
490 : uint32_t *max_valnamelen,
491 : uint32_t *max_valbufsize)
492 : {
493 0 : struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
494 0 : WERROR error;
495 :
496 0 : if (mykeydata->num_values == -1) {
497 0 : error = rpc_query_key(mem_ctx, key);
498 0 : if(!W_ERROR_IS_OK(error)) return error;
499 : }
500 :
501 0 : if (classname != NULL)
502 0 : *classname = mykeydata->classname;
503 :
504 0 : if (num_subkeys != NULL)
505 0 : *num_subkeys = mykeydata->num_subkeys;
506 :
507 0 : if (num_values != NULL)
508 0 : *num_values = mykeydata->num_values;
509 :
510 0 : if (last_changed_time != NULL)
511 0 : *last_changed_time = mykeydata->last_changed_time;
512 :
513 0 : if (max_subkeylen != NULL)
514 0 : *max_subkeylen = mykeydata->max_subkeylen;
515 :
516 0 : if (max_valnamelen != NULL)
517 0 : *max_valnamelen = mykeydata->max_valnamelen;
518 :
519 0 : if (max_valbufsize != NULL)
520 0 : *max_valbufsize = mykeydata->max_valbufsize;
521 :
522 0 : return WERR_OK;
523 : }
524 :
525 : static struct registry_operations reg_backend_rpc = {
526 : .name = "rpc",
527 : .open_key = rpc_open_key,
528 : .get_predefined_key = rpc_get_predefined_key,
529 : .enum_key = rpc_get_subkey_by_index,
530 : .enum_value = rpc_get_value_by_index,
531 : .get_value = rpc_get_value_by_name,
532 : .set_value = rpc_set_value,
533 : .delete_value = rpc_del_value,
534 : .create_key = rpc_add_key,
535 : .delete_key = rpc_del_key,
536 : .get_key_info = rpc_get_info,
537 : };
538 :
539 0 : _PUBLIC_ WERROR reg_open_remote(TALLOC_CTX *mem_ctx,
540 : struct registry_context **ctx,
541 : struct cli_credentials *credentials,
542 : struct loadparm_context *lp_ctx,
543 : const char *location, struct tevent_context *ev)
544 : {
545 0 : NTSTATUS status;
546 0 : struct dcerpc_pipe *p;
547 0 : struct rpc_registry_context *rctx;
548 :
549 0 : dcerpc_init();
550 :
551 0 : rctx = talloc(mem_ctx, struct rpc_registry_context);
552 0 : W_ERROR_HAVE_NO_MEMORY(rctx);
553 :
554 : /* Default to local smbd if no connection is specified */
555 0 : if (!location) {
556 0 : location = talloc_strdup(rctx, "ncalrpc:");
557 : }
558 :
559 0 : status = dcerpc_pipe_connect(rctx /* TALLOC_CTX */,
560 : &p, location,
561 : &ndr_table_winreg,
562 : credentials, ev, lp_ctx);
563 0 : if(NT_STATUS_IS_ERR(status)) {
564 0 : DEBUG(1, ("Unable to open '%s': %s\n", location,
565 : nt_errstr(status)));
566 0 : talloc_free(rctx);
567 0 : *ctx = NULL;
568 0 : return ntstatus_to_werror(status);
569 : }
570 :
571 0 : rctx->pipe = p;
572 0 : rctx->binding_handle = p->binding_handle;
573 :
574 0 : *ctx = (struct registry_context *)rctx;
575 0 : (*ctx)->ops = ®_backend_rpc;
576 :
577 0 : return WERR_OK;
578 : }
|