Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Registry interface
4 : Copyright (C) 2004-2007, Jelmer Vernooij, jelmer@samba.org
5 : Copyright (C) 2008-2010, Matthias Dieter Wallnöfer, mdw@samba.org
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 "registry.h"
23 : #include <ldb.h>
24 : #include <ldb_errors.h>
25 : #include "ldb_wrap.h"
26 : #include "librpc/gen_ndr/winreg.h"
27 : #include "param/param.h"
28 : #include "lib/util/smb_strtox.h"
29 :
30 : #undef strcasecmp
31 :
32 : static struct hive_operations reg_backend_ldb;
33 :
34 : struct ldb_key_data
35 : {
36 : struct hive_key key;
37 : struct ldb_context *ldb;
38 : struct ldb_dn *dn;
39 : struct ldb_message **subkeys, **values;
40 : unsigned int subkey_count, value_count;
41 : const char *classname;
42 : };
43 :
44 7440 : static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx,
45 : struct ldb_message *msg,
46 : const char **name, uint32_t *type,
47 : DATA_BLOB *data)
48 : {
49 : const struct ldb_val *val;
50 : uint32_t value_type;
51 :
52 7440 : if (name != NULL) {
53 0 : *name = talloc_strdup(mem_ctx,
54 : ldb_msg_find_attr_as_string(msg, "value",
55 : ""));
56 : }
57 :
58 7440 : value_type = ldb_msg_find_attr_as_uint(msg, "type", 0);
59 7440 : *type = value_type;
60 :
61 7440 : val = ldb_msg_find_ldb_val(msg, "data");
62 :
63 7440 : switch (value_type)
64 : {
65 640 : case REG_SZ:
66 : case REG_EXPAND_SZ:
67 640 : if (val != NULL) {
68 : /* The data should be provided as UTF16 string */
69 1280 : convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16,
70 640 : val->data, val->length,
71 640 : (void **)&data->data, &data->length);
72 : } else {
73 0 : data->data = NULL;
74 0 : data->length = 0;
75 : }
76 640 : break;
77 :
78 800 : case REG_DWORD:
79 : case REG_DWORD_BIG_ENDIAN:
80 800 : if (val != NULL) {
81 800 : int error = 0;
82 : /* The data is a plain DWORD */
83 : uint32_t tmp;
84 :
85 800 : tmp = smb_strtoul((char *)val->data,
86 : NULL,
87 : 0,
88 : &error,
89 : SMB_STR_STANDARD);
90 800 : if (error != 0) {
91 0 : data->data = NULL;
92 0 : data->length = 0;
93 0 : break;
94 : }
95 800 : data->data = talloc_size(mem_ctx, sizeof(uint32_t));
96 800 : if (data->data != NULL) {
97 800 : SIVAL(data->data, 0, tmp);
98 : }
99 800 : data->length = sizeof(uint32_t);
100 : } else {
101 0 : data->data = NULL;
102 0 : data->length = 0;
103 : }
104 800 : break;
105 :
106 400 : case REG_QWORD:
107 400 : if (val != NULL) {
108 400 : int error = 0;
109 : /* The data is a plain QWORD */
110 : uint64_t tmp;
111 :
112 400 : tmp = smb_strtoull((char *)val->data,
113 : NULL,
114 : 0,
115 : &error,
116 : SMB_STR_STANDARD);
117 400 : if (error != 0) {
118 0 : data->data = NULL;
119 0 : data->length = 0;
120 0 : break;
121 : }
122 400 : data->data = talloc_size(mem_ctx, sizeof(uint64_t));
123 400 : if (data->data != NULL) {
124 400 : SBVAL(data->data, 0, tmp);
125 : }
126 400 : data->length = sizeof(uint64_t);
127 : } else {
128 0 : data->data = NULL;
129 0 : data->length = 0;
130 : }
131 400 : break;
132 :
133 5600 : case REG_BINARY:
134 : default:
135 5600 : if (val != NULL) {
136 5600 : data->data = talloc_memdup(mem_ctx, val->data,
137 : val->length);
138 5600 : data->length = val->length;
139 : } else {
140 0 : data->data = NULL;
141 0 : data->length = 0;
142 : }
143 5600 : break;
144 : }
145 7440 : }
146 :
147 1881 : static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx,
148 : TALLOC_CTX *mem_ctx,
149 : const char *name,
150 : uint32_t type, DATA_BLOB data)
151 : {
152 : struct ldb_message *msg;
153 : char *name_dup, *type_str;
154 : int ret;
155 :
156 1881 : msg = ldb_msg_new(mem_ctx);
157 1881 : if (msg == NULL) {
158 0 : return NULL;
159 : }
160 :
161 1881 : name_dup = talloc_strdup(msg, name);
162 1881 : if (name_dup == NULL) {
163 0 : talloc_free(msg);
164 0 : return NULL;
165 : }
166 :
167 1881 : ret = ldb_msg_add_string(msg, "value", name_dup);
168 1881 : if (ret != LDB_SUCCESS) {
169 0 : talloc_free(msg);
170 0 : return NULL;
171 : }
172 :
173 1881 : switch (type) {
174 374 : case REG_SZ:
175 : case REG_EXPAND_SZ:
176 748 : if ((data.length > 0) && (data.data != NULL)) {
177 : struct ldb_val *val;
178 374 : bool ret2 = false;
179 :
180 374 : val = talloc_zero(msg, struct ldb_val);
181 374 : if (val == NULL) {
182 0 : talloc_free(msg);
183 0 : return NULL;
184 : }
185 :
186 : /* The data is provided as UTF16 string */
187 974 : ret2 = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8,
188 374 : (void *)data.data, data.length,
189 374 : (void **)&val->data, &val->length);
190 374 : if (ret2) {
191 374 : ret = ldb_msg_add_value(msg, "data", val, NULL);
192 : } else {
193 : /* workaround for non-standard data */
194 0 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
195 : }
196 : } else {
197 0 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
198 : }
199 374 : break;
200 :
201 307 : case REG_DWORD:
202 : case REG_DWORD_BIG_ENDIAN:
203 307 : if ((data.length > 0) && (data.data != NULL)) {
204 517 : if (data.length == sizeof(uint32_t)) {
205 : char *conv_str;
206 :
207 307 : conv_str = talloc_asprintf(msg, "0x%8.8x",
208 307 : IVAL(data.data, 0));
209 307 : if (conv_str == NULL) {
210 0 : talloc_free(msg);
211 0 : return NULL;
212 : }
213 307 : ret = ldb_msg_add_string(msg, "data", conv_str);
214 : } else {
215 : /* workaround for non-standard data */
216 0 : talloc_free(msg);
217 0 : return NULL;
218 : }
219 : } else {
220 0 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
221 : }
222 307 : break;
223 :
224 80 : case REG_QWORD:
225 80 : if ((data.length > 0) && (data.data != NULL)) {
226 120 : if (data.length == sizeof(uint64_t)) {
227 : char *conv_str;
228 :
229 80 : conv_str = talloc_asprintf(msg, "0x%16.16llx",
230 80 : (unsigned long long)BVAL(data.data, 0));
231 80 : if (conv_str == NULL) {
232 0 : talloc_free(msg);
233 0 : return NULL;
234 : }
235 80 : ret = ldb_msg_add_string(msg, "data", conv_str);
236 : } else {
237 : /* workaround for non-standard data */
238 0 : talloc_free(msg);
239 0 : return NULL;
240 :
241 : }
242 : } else {
243 0 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
244 : }
245 80 : break;
246 :
247 1120 : case REG_BINARY:
248 : default:
249 1120 : if ((data.length > 0) && (data.data != NULL)) {
250 1120 : ret = ldb_msg_add_value(msg, "data", &data, NULL);
251 : } else {
252 0 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
253 : }
254 1120 : break;
255 : }
256 :
257 1881 : if (ret != LDB_SUCCESS) {
258 0 : talloc_free(msg);
259 0 : return NULL;
260 : }
261 :
262 1881 : type_str = talloc_asprintf(mem_ctx, "%u", type);
263 1881 : if (type_str == NULL) {
264 0 : talloc_free(msg);
265 0 : return NULL;
266 : }
267 :
268 1881 : ret = ldb_msg_add_string(msg, "type", type_str);
269 1881 : if (ret != LDB_SUCCESS) {
270 0 : talloc_free(msg);
271 0 : return NULL;
272 : }
273 :
274 1881 : return msg;
275 : }
276 :
277 40990 : static char *reg_ldb_escape(TALLOC_CTX *mem_ctx, const char *value)
278 : {
279 : struct ldb_val val;
280 :
281 40990 : val.data = discard_const_p(uint8_t, value);
282 40990 : val.length = strlen(value);
283 :
284 40990 : return ldb_dn_escape_value(mem_ctx, val);
285 : }
286 :
287 1439 : static int reg_close_ldb_key(struct ldb_key_data *key)
288 : {
289 1439 : if (key->subkeys != NULL) {
290 1 : talloc_free(key->subkeys);
291 1 : key->subkeys = NULL;
292 : }
293 :
294 1439 : if (key->values != NULL) {
295 0 : talloc_free(key->values);
296 0 : key->values = NULL;
297 : }
298 1439 : return 0;
299 : }
300 :
301 33429 : static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx,
302 : const struct hive_key *from,
303 : const char *path, const char *add)
304 : {
305 : struct ldb_dn *ret;
306 : char *mypath;
307 : char *begin;
308 33429 : struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data);
309 33429 : struct ldb_context *ldb = kd->ldb;
310 :
311 33429 : mypath = talloc_strdup(mem_ctx, path);
312 33429 : if (mypath == NULL) {
313 0 : return NULL;
314 : }
315 :
316 33429 : ret = ldb_dn_new(mem_ctx, ldb, add);
317 33429 : if (!ldb_dn_validate(ret)) {
318 0 : talloc_free(ret);
319 0 : return NULL;
320 : }
321 :
322 33429 : if (!ldb_dn_add_base(ret, kd->dn)) {
323 0 : talloc_free(ret);
324 0 : return NULL;
325 : }
326 :
327 62738 : while (mypath[0] != '\0') {
328 37669 : begin = strchr(mypath, '\\');
329 37669 : if (begin != NULL) {
330 4240 : *begin = '\0';
331 : }
332 :
333 37669 : if (!ldb_dn_add_child_fmt(ret, "key=%s",
334 : reg_ldb_escape(mem_ctx, mypath))) {
335 0 : talloc_free(ret);
336 0 : return NULL;
337 : }
338 :
339 37669 : if (begin != NULL) {
340 4240 : mypath = begin + 1;
341 : } else {
342 33429 : break;
343 : }
344 : }
345 :
346 33429 : return ret;
347 : }
348 :
349 481 : static WERROR cache_subkeys(struct ldb_key_data *kd)
350 : {
351 481 : struct ldb_context *c = kd->ldb;
352 : struct ldb_result *res;
353 : int ret;
354 :
355 481 : ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL,
356 : NULL, "(key=*)");
357 481 : if (ret != LDB_SUCCESS) {
358 0 : DEBUG(0, ("Error getting subkeys for '%s': %s\n",
359 : ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
360 0 : return WERR_FOOBAR;
361 : }
362 :
363 481 : kd->subkey_count = res->count;
364 481 : kd->subkeys = talloc_steal(kd, res->msgs);
365 481 : talloc_free(res);
366 :
367 481 : return WERR_OK;
368 : }
369 :
370 2482 : static WERROR cache_values(struct ldb_key_data *kd)
371 : {
372 2482 : struct ldb_context *c = kd->ldb;
373 : struct ldb_result *res;
374 : int ret;
375 :
376 2482 : ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL,
377 : NULL, "(value=*)");
378 2482 : if (ret != LDB_SUCCESS) {
379 0 : DEBUG(0, ("Error getting values for '%s': %s\n",
380 : ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
381 0 : return WERR_FOOBAR;
382 : }
383 :
384 2482 : kd->value_count = res->count;
385 2482 : kd->values = talloc_steal(kd, res->msgs);
386 2482 : talloc_free(res);
387 :
388 2482 : return WERR_OK;
389 : }
390 :
391 :
392 240 : static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx,
393 : const struct hive_key *k, uint32_t idx,
394 : const char **name,
395 : const char **classname,
396 : NTTIME *last_mod_time)
397 : {
398 240 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
399 :
400 : /* Initialization */
401 240 : if (name != NULL)
402 240 : *name = NULL;
403 240 : if (classname != NULL)
404 240 : *classname = NULL;
405 240 : if (last_mod_time != NULL)
406 240 : *last_mod_time = 0; /* TODO: we need to add this to the
407 : ldb backend properly */
408 :
409 : /* Do a search if necessary */
410 240 : if (kd->subkeys == NULL) {
411 240 : W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
412 : }
413 :
414 240 : if (idx >= kd->subkey_count)
415 240 : return WERR_NO_MORE_ITEMS;
416 :
417 0 : if (name != NULL)
418 0 : *name = talloc_strdup(mem_ctx,
419 0 : ldb_msg_find_attr_as_string(kd->subkeys[idx], "key", NULL));
420 0 : if (classname != NULL)
421 0 : *classname = talloc_strdup(mem_ctx,
422 0 : ldb_msg_find_attr_as_string(kd->subkeys[idx], "classname", NULL));
423 :
424 0 : return WERR_OK;
425 : }
426 :
427 961 : static WERROR ldb_get_default_value(TALLOC_CTX *mem_ctx,
428 : const struct hive_key *k,
429 : const char **name, uint32_t *data_type,
430 : DATA_BLOB *data)
431 : {
432 961 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
433 961 : struct ldb_context *c = kd->ldb;
434 961 : const char* attrs[] = { "data", "type", NULL };
435 : struct ldb_result *res;
436 : int ret;
437 :
438 961 : ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_BASE, attrs,
439 : NULL);
440 :
441 961 : if (ret != LDB_SUCCESS) {
442 0 : DEBUG(0, ("Error getting default value for '%s': %s\n",
443 : ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
444 0 : return WERR_FOOBAR;
445 : }
446 :
447 961 : if (res->count == 0 || res->msgs[0]->num_elements == 0) {
448 961 : talloc_free(res);
449 961 : return WERR_FILE_NOT_FOUND;
450 : }
451 :
452 0 : if ((data_type != NULL) && (data != NULL)) {
453 0 : reg_ldb_unpack_value(mem_ctx, res->msgs[0], name, data_type,
454 : data);
455 : }
456 :
457 0 : talloc_free(res);
458 :
459 0 : return WERR_OK;
460 : }
461 :
462 480 : static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct hive_key *k,
463 : uint32_t idx, const char **name,
464 : uint32_t *data_type, DATA_BLOB *data)
465 : {
466 480 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
467 :
468 : /* if the default value exists, give it back */
469 480 : if (W_ERROR_IS_OK(ldb_get_default_value(mem_ctx, k, name, data_type,
470 : data))) {
471 0 : if (idx == 0)
472 0 : return WERR_OK;
473 : else
474 0 : --idx;
475 : }
476 :
477 : /* Do the search if necessary */
478 480 : if (kd->values == NULL) {
479 480 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
480 : }
481 :
482 480 : if (idx >= kd->value_count)
483 480 : return WERR_NO_MORE_ITEMS;
484 :
485 0 : reg_ldb_unpack_value(mem_ctx, kd->values[idx], name, data_type, data);
486 :
487 0 : return WERR_OK;
488 : }
489 :
490 7920 : static WERROR ldb_get_value(TALLOC_CTX *mem_ctx, struct hive_key *k,
491 : const char *name, uint32_t *data_type,
492 : DATA_BLOB *data)
493 : {
494 7920 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
495 : const char *res_name;
496 : uint32_t idx;
497 :
498 : /* the default value was requested, give it back */
499 7920 : if (name[0] == '\0') {
500 240 : return ldb_get_default_value(mem_ctx, k, NULL, data_type, data);
501 : }
502 :
503 : /* Do the search if necessary */
504 7680 : if (kd->values == NULL) {
505 1520 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
506 : }
507 :
508 7920 : for (idx = 0; idx < kd->value_count; idx++) {
509 7680 : res_name = ldb_msg_find_attr_as_string(kd->values[idx], "value",
510 : "");
511 7680 : if (ldb_attr_cmp(name, res_name) == 0) {
512 7440 : reg_ldb_unpack_value(mem_ctx, kd->values[idx], NULL,
513 : data_type, data);
514 7440 : return WERR_OK;
515 : }
516 : }
517 :
518 240 : return WERR_FILE_NOT_FOUND;
519 : }
520 :
521 27711 : static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct hive_key *h,
522 : const char *name, struct hive_key **key)
523 : {
524 : struct ldb_result *res;
525 : struct ldb_dn *ldb_path;
526 : int ret;
527 : struct ldb_key_data *newkd;
528 27711 : struct ldb_key_data *kd = talloc_get_type(h, struct ldb_key_data);
529 27711 : struct ldb_context *c = kd->ldb;
530 :
531 27711 : ldb_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
532 27711 : W_ERROR_HAVE_NO_MEMORY(ldb_path);
533 :
534 27711 : ret = ldb_search(c, mem_ctx, &res, ldb_path, LDB_SCOPE_BASE, NULL,
535 : NULL);
536 :
537 27711 : if (ret != LDB_SUCCESS) {
538 0 : DEBUG(3, ("Error opening key '%s': %s\n",
539 : ldb_dn_get_linearized(ldb_path), ldb_errstring(c)));
540 0 : return WERR_FOOBAR;
541 27711 : } else if (res->count == 0) {
542 5078 : DEBUG(3, ("Key '%s' not found\n",
543 : ldb_dn_get_linearized(ldb_path)));
544 5078 : talloc_free(res);
545 5078 : return WERR_FILE_NOT_FOUND;
546 : }
547 :
548 22633 : newkd = talloc_zero(mem_ctx, struct ldb_key_data);
549 22633 : W_ERROR_HAVE_NO_MEMORY(newkd);
550 22633 : newkd->key.ops = ®_backend_ldb;
551 22633 : newkd->ldb = talloc_reference(newkd, kd->ldb);
552 22633 : newkd->dn = ldb_dn_copy(newkd, res->msgs[0]->dn);
553 22633 : newkd->classname = talloc_steal(newkd,
554 : ldb_msg_find_attr_as_string(res->msgs[0], "classname", NULL));
555 :
556 22633 : talloc_free(res);
557 :
558 22633 : *key = (struct hive_key *)newkd;
559 :
560 22633 : return WERR_OK;
561 : }
562 :
563 1439 : WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location,
564 : struct auth_session_info *session_info,
565 : struct cli_credentials *credentials,
566 : struct tevent_context *ev_ctx,
567 : struct loadparm_context *lp_ctx,
568 : struct hive_key **k)
569 : {
570 : struct ldb_key_data *kd;
571 : struct ldb_context *wrap;
572 : struct ldb_message *attrs_msg;
573 :
574 1439 : if (location == NULL)
575 0 : return WERR_INVALID_PARAMETER;
576 :
577 1439 : wrap = ldb_wrap_connect(parent_ctx, ev_ctx, lp_ctx,
578 : location, session_info, credentials, 0);
579 :
580 1439 : if (wrap == NULL) {
581 0 : DEBUG(1, (__FILE__": unable to connect\n"));
582 0 : return WERR_FOOBAR;
583 : }
584 :
585 1439 : attrs_msg = ldb_msg_new(wrap);
586 1439 : W_ERROR_HAVE_NO_MEMORY(attrs_msg);
587 1439 : attrs_msg->dn = ldb_dn_new(attrs_msg, wrap, "@ATTRIBUTES");
588 1439 : W_ERROR_HAVE_NO_MEMORY(attrs_msg->dn);
589 1439 : ldb_msg_add_string(attrs_msg, "key", "CASE_INSENSITIVE");
590 1439 : ldb_msg_add_string(attrs_msg, "value", "CASE_INSENSITIVE");
591 :
592 1439 : ldb_add(wrap, attrs_msg);
593 :
594 1439 : ldb_set_debug_stderr(wrap);
595 :
596 1439 : kd = talloc_zero(parent_ctx, struct ldb_key_data);
597 1439 : kd->key.ops = ®_backend_ldb;
598 1439 : kd->ldb = talloc_reference(kd, wrap);
599 1439 : talloc_set_destructor (kd, reg_close_ldb_key);
600 1439 : kd->dn = ldb_dn_new(kd, wrap, "hive=NONE");
601 :
602 1439 : *k = (struct hive_key *)kd;
603 :
604 1439 : return WERR_OK;
605 : }
606 :
607 3958 : static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
608 : const char *name, const char *classname,
609 : struct security_descriptor *sd,
610 : struct hive_key **newkey)
611 : {
612 3958 : struct ldb_key_data *parentkd = discard_const_p(struct ldb_key_data, parent);
613 : struct ldb_dn *ldb_path;
614 : struct ldb_message *msg;
615 : struct ldb_key_data *newkd;
616 : int ret;
617 :
618 3958 : ldb_path = reg_path_to_ldb(mem_ctx, parent, name, NULL);
619 3958 : W_ERROR_HAVE_NO_MEMORY(ldb_path);
620 :
621 3958 : msg = ldb_msg_new(mem_ctx);
622 3958 : W_ERROR_HAVE_NO_MEMORY(msg);
623 :
624 3958 : msg->dn = ldb_path;
625 :
626 3958 : ldb_msg_add_string(msg, "key", name);
627 3958 : if (classname != NULL) {
628 0 : ldb_msg_add_string(msg, "classname", classname);
629 : }
630 :
631 3958 : ret = ldb_add(parentkd->ldb, msg);
632 :
633 3958 : talloc_free(msg);
634 :
635 3958 : if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
636 0 : return WERR_ALREADY_EXISTS;
637 : }
638 :
639 3958 : if (ret != LDB_SUCCESS) {
640 0 : DEBUG(1, ("ldb_add: %s\n", ldb_errstring(parentkd->ldb)));
641 0 : return WERR_FOOBAR;
642 : }
643 :
644 3958 : DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(ldb_path)));
645 :
646 3958 : newkd = talloc_zero(mem_ctx, struct ldb_key_data);
647 3958 : W_ERROR_HAVE_NO_MEMORY(newkd);
648 3958 : newkd->ldb = talloc_reference(newkd, parentkd->ldb);
649 3958 : newkd->key.ops = ®_backend_ldb;
650 3958 : newkd->dn = talloc_steal(newkd, ldb_path);
651 3958 : newkd->classname = talloc_steal(newkd, classname);
652 :
653 3958 : *newkey = (struct hive_key *)newkd;
654 :
655 : /* reset cache */
656 3958 : talloc_free(parentkd->subkeys);
657 3958 : parentkd->subkeys = NULL;
658 :
659 3958 : return WERR_OK;
660 : }
661 :
662 1440 : static WERROR ldb_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
663 : const char *child)
664 : {
665 : int ret;
666 1440 : struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
667 : struct ldb_message *msg;
668 : struct ldb_dn *childdn;
669 :
670 1440 : if (child[0] == '\0') {
671 : /* default value */
672 0 : msg = ldb_msg_new(mem_ctx);
673 0 : W_ERROR_HAVE_NO_MEMORY(msg);
674 0 : msg->dn = ldb_dn_copy(msg, kd->dn);
675 0 : W_ERROR_HAVE_NO_MEMORY(msg->dn);
676 0 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
677 0 : if (ret != LDB_SUCCESS) {
678 0 : return WERR_FOOBAR;
679 : }
680 0 : ret = ldb_msg_add_empty(msg, "type", LDB_FLAG_MOD_DELETE,
681 : NULL);
682 0 : if (ret != LDB_SUCCESS) {
683 0 : return WERR_FOOBAR;
684 : }
685 :
686 0 : ret = ldb_modify(kd->ldb, msg);
687 :
688 0 : talloc_free(msg);
689 :
690 0 : if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
691 0 : return WERR_FILE_NOT_FOUND;
692 0 : } else if (ret != LDB_SUCCESS) {
693 0 : DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb)));
694 0 : return WERR_FOOBAR;
695 : }
696 : } else {
697 : /* normal value */
698 1440 : childdn = ldb_dn_copy(kd->ldb, kd->dn);
699 1440 : if (!ldb_dn_add_child_fmt(childdn, "value=%s",
700 : reg_ldb_escape(childdn, child)))
701 : {
702 0 : talloc_free(childdn);
703 0 : return WERR_FOOBAR;
704 : }
705 :
706 1440 : ret = ldb_delete(kd->ldb, childdn);
707 :
708 1440 : talloc_free(childdn);
709 :
710 1440 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
711 0 : return WERR_FILE_NOT_FOUND;
712 1440 : } else if (ret != LDB_SUCCESS) {
713 0 : DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb)));
714 0 : return WERR_FOOBAR;
715 : }
716 : }
717 :
718 : /* reset cache */
719 1440 : talloc_free(kd->values);
720 1440 : kd->values = NULL;
721 :
722 1440 : return WERR_OK;
723 : }
724 :
725 2560 : static WERROR ldb_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *key,
726 : const char *name)
727 : {
728 : unsigned int i;
729 : int ret;
730 2560 : struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
731 : struct ldb_dn *ldb_path;
732 2560 : struct ldb_context *c = parentkd->ldb;
733 : struct ldb_result *res_keys;
734 : struct ldb_result *res_vals;
735 : WERROR werr;
736 : struct hive_key *hk;
737 :
738 : /* Verify key exists by opening it */
739 2560 : werr = ldb_open_key(mem_ctx, key, name, &hk);
740 2560 : if (!W_ERROR_IS_OK(werr)) {
741 800 : return werr;
742 : }
743 :
744 1760 : ldb_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
745 1760 : W_ERROR_HAVE_NO_MEMORY(ldb_path);
746 :
747 : /* Search for subkeys */
748 1760 : ret = ldb_search(c, mem_ctx, &res_keys, ldb_path, LDB_SCOPE_ONELEVEL,
749 : NULL, "(key=*)");
750 :
751 1760 : if (ret != LDB_SUCCESS) {
752 0 : DEBUG(0, ("Error getting subkeys for '%s': %s\n",
753 : ldb_dn_get_linearized(ldb_path), ldb_errstring(c)));
754 0 : return WERR_FOOBAR;
755 : }
756 :
757 : /* Search for values */
758 1760 : ret = ldb_search(c, mem_ctx, &res_vals, ldb_path, LDB_SCOPE_ONELEVEL,
759 : NULL, "(value=*)");
760 :
761 1760 : if (ret != LDB_SUCCESS) {
762 0 : DEBUG(0, ("Error getting values for '%s': %s\n",
763 : ldb_dn_get_linearized(ldb_path), ldb_errstring(c)));
764 0 : return WERR_FOOBAR;
765 : }
766 :
767 : /* Start an explicit transaction */
768 1760 : ret = ldb_transaction_start(c);
769 :
770 1760 : if (ret != LDB_SUCCESS) {
771 0 : DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c)));
772 0 : return WERR_FOOBAR;
773 : }
774 :
775 1760 : if (res_keys->count || res_vals->count)
776 : {
777 : /* Delete any subkeys */
778 0 : for (i = 0; i < res_keys->count; i++)
779 : {
780 0 : werr = ldb_del_key(mem_ctx, hk,
781 : ldb_msg_find_attr_as_string(
782 0 : res_keys->msgs[i],
783 : "key", NULL));
784 0 : if (!W_ERROR_IS_OK(werr)) {
785 0 : ret = ldb_transaction_cancel(c);
786 0 : return werr;
787 : }
788 : }
789 :
790 : /* Delete any values */
791 0 : for (i = 0; i < res_vals->count; i++)
792 : {
793 0 : werr = ldb_del_value(mem_ctx, hk,
794 : ldb_msg_find_attr_as_string(
795 0 : res_vals->msgs[i],
796 : "value", NULL));
797 0 : if (!W_ERROR_IS_OK(werr)) {
798 0 : ret = ldb_transaction_cancel(c);
799 0 : return werr;
800 : }
801 : }
802 : }
803 1760 : talloc_free(res_keys);
804 1760 : talloc_free(res_vals);
805 :
806 : /* Delete the key itself */
807 1760 : ret = ldb_delete(c, ldb_path);
808 :
809 1760 : if (ret != LDB_SUCCESS)
810 : {
811 0 : DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(c)));
812 0 : ret = ldb_transaction_cancel(c);
813 0 : return WERR_FOOBAR;
814 : }
815 :
816 : /* Commit the transaction */
817 1760 : ret = ldb_transaction_commit(c);
818 :
819 1760 : if (ret != LDB_SUCCESS)
820 : {
821 0 : DEBUG(0, ("ldb_transaction_commit: %s\n", ldb_errstring(c)));
822 0 : ret = ldb_transaction_cancel(c);
823 0 : return WERR_FOOBAR;
824 : }
825 :
826 : /* reset cache */
827 1760 : talloc_free(parentkd->subkeys);
828 1760 : parentkd->subkeys = NULL;
829 :
830 1760 : return WERR_OK;
831 : }
832 :
833 1881 : static WERROR ldb_set_value(struct hive_key *parent,
834 : const char *name, uint32_t type,
835 : const DATA_BLOB data)
836 : {
837 : struct ldb_message *msg;
838 1881 : struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data);
839 : unsigned int i;
840 : int ret;
841 1881 : TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
842 :
843 1881 : msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data);
844 1881 : W_ERROR_HAVE_NO_MEMORY(msg);
845 :
846 1881 : msg->dn = ldb_dn_copy(msg, kd->dn);
847 1881 : W_ERROR_HAVE_NO_MEMORY(msg->dn);
848 :
849 1881 : if (name[0] != '\0') {
850 : /* For a default value, we add/overwrite the attributes to/of the hive.
851 : For a normal value, we create a new child. */
852 1881 : if (!ldb_dn_add_child_fmt(msg->dn, "value=%s",
853 : reg_ldb_escape(mem_ctx, name)))
854 : {
855 0 : talloc_free(mem_ctx);
856 0 : return WERR_FOOBAR;
857 : }
858 : }
859 :
860 : /* Try first a "modify" and if this doesn't work do try an "add" */
861 7524 : for (i = 0; i < msg->num_elements; i++) {
862 5643 : if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) != LDB_FLAG_MOD_DELETE) {
863 5643 : msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
864 : }
865 : }
866 1881 : ret = ldb_modify(kd->ldb, msg);
867 1881 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
868 1878 : i = 0;
869 8619 : while (i < msg->num_elements) {
870 5634 : if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE) {
871 0 : ldb_msg_remove_element(msg, &msg->elements[i]);
872 : } else {
873 5634 : ++i;
874 : }
875 : }
876 1878 : ret = ldb_add(kd->ldb, msg);
877 : }
878 1881 : if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
879 : /* ignore this -> the value didn't exist and also now doesn't */
880 0 : ret = LDB_SUCCESS;
881 : }
882 :
883 1881 : talloc_free(msg);
884 :
885 1881 : if (ret != LDB_SUCCESS) {
886 0 : DEBUG(1, ("ldb_set_value: %s\n", ldb_errstring(kd->ldb)));
887 0 : talloc_free(mem_ctx);
888 0 : return WERR_FOOBAR;
889 : }
890 :
891 : /* reset cache */
892 1881 : talloc_free(kd->values);
893 1881 : kd->values = NULL;
894 :
895 1881 : talloc_free(mem_ctx);
896 1881 : return WERR_OK;
897 : }
898 :
899 241 : static WERROR ldb_get_key_info(TALLOC_CTX *mem_ctx,
900 : const struct hive_key *key,
901 : const char **classname,
902 : uint32_t *num_subkeys,
903 : uint32_t *num_values,
904 : NTTIME *last_change_time,
905 : uint32_t *max_subkeynamelen,
906 : uint32_t *max_valnamelen,
907 : uint32_t *max_valbufsize)
908 : {
909 241 : struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
910 241 : uint32_t default_value_type = REG_NONE;
911 241 : DATA_BLOB default_value = { NULL, 0 };
912 : WERROR werr;
913 :
914 : /* Initialization */
915 241 : if (classname != NULL)
916 241 : *classname = NULL;
917 241 : if (num_subkeys != NULL)
918 241 : *num_subkeys = 0;
919 241 : if (num_values != NULL)
920 241 : *num_values = 0;
921 241 : if (last_change_time != NULL)
922 241 : *last_change_time = 0;
923 241 : if (max_subkeynamelen != NULL)
924 241 : *max_subkeynamelen = 0;
925 241 : if (max_valnamelen != NULL)
926 241 : *max_valnamelen = 0;
927 241 : if (max_valbufsize != NULL)
928 241 : *max_valbufsize = 0;
929 :
930 : /* We need this to get the default value (if it exists) for counting
931 : * the values under the key and for finding out the longest value buffer
932 : * size. If no default value exists the DATA_BLOB "default_value" will
933 : * remain { NULL, 0 }. */
934 241 : werr = ldb_get_default_value(mem_ctx, key, NULL, &default_value_type,
935 : &default_value);
936 241 : if ((!W_ERROR_IS_OK(werr)) && (!W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND))) {
937 0 : return werr;
938 : }
939 :
940 241 : if (kd->subkeys == NULL) {
941 241 : W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
942 : }
943 241 : if (kd->values == NULL) {
944 241 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
945 : }
946 :
947 241 : if (classname != NULL) {
948 241 : *classname = kd->classname;
949 : }
950 :
951 241 : if (num_subkeys != NULL) {
952 241 : *num_subkeys = kd->subkey_count;
953 : }
954 241 : if (num_values != NULL) {
955 241 : *num_values = kd->value_count;
956 : /* also consider the default value if it exists */
957 241 : if (default_value.data != NULL) {
958 0 : ++(*num_values);
959 : }
960 : }
961 :
962 :
963 241 : if (max_subkeynamelen != NULL) {
964 : unsigned int i;
965 : struct ldb_message_element *el;
966 :
967 243 : for (i = 0; i < kd->subkey_count; i++) {
968 2 : el = ldb_msg_find_element(kd->subkeys[i], "key");
969 2 : *max_subkeynamelen = MAX(*max_subkeynamelen, el->values[0].length);
970 : }
971 : }
972 :
973 241 : if (max_valnamelen != NULL || max_valbufsize != NULL) {
974 : unsigned int i;
975 : struct ldb_message_element *el;
976 241 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
977 :
978 : /* also consider the default value if it exists */
979 241 : if ((max_valbufsize != NULL) && (default_value.data != NULL)) {
980 0 : *max_valbufsize = MAX(*max_valbufsize,
981 : default_value.length);
982 : }
983 :
984 241 : for (i = 0; i < kd->value_count; i++) {
985 0 : if (max_valnamelen != NULL) {
986 0 : el = ldb_msg_find_element(kd->values[i], "value");
987 0 : *max_valnamelen = MAX(*max_valnamelen, el->values[0].length);
988 : }
989 :
990 0 : if (max_valbufsize != NULL) {
991 : uint32_t data_type;
992 : DATA_BLOB data;
993 0 : reg_ldb_unpack_value(mem_ctx,
994 0 : kd->values[i], NULL,
995 : &data_type, &data);
996 0 : *max_valbufsize = MAX(*max_valbufsize, data.length);
997 0 : talloc_free(data.data);
998 : }
999 : }
1000 : }
1001 :
1002 241 : talloc_free(default_value.data);
1003 :
1004 241 : return WERR_OK;
1005 : }
1006 :
1007 : static struct hive_operations reg_backend_ldb = {
1008 : .name = "ldb",
1009 : .add_key = ldb_add_key,
1010 : .del_key = ldb_del_key,
1011 : .get_key_by_name = ldb_open_key,
1012 : .enum_value = ldb_get_value_by_id,
1013 : .enum_key = ldb_get_subkey_by_id,
1014 : .set_value = ldb_set_value,
1015 : .get_value_by_name = ldb_get_value,
1016 : .delete_value = ldb_del_value,
1017 : .get_key_info = ldb_get_key_info,
1018 : };
|