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 9369 : 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 9 : const struct ldb_val *val;
50 9 : uint32_t value_type;
51 :
52 9369 : if (name != NULL) {
53 1925 : *name = talloc_strdup(mem_ctx,
54 : ldb_msg_find_attr_as_string(msg, "value",
55 : ""));
56 : }
57 :
58 9369 : value_type = ldb_msg_find_attr_as_uint(msg, "type", 0);
59 9369 : *type = value_type;
60 :
61 9369 : val = ldb_msg_find_ldb_val(msg, "data");
62 :
63 9369 : switch (value_type)
64 : {
65 643 : case REG_SZ:
66 : case REG_EXPAND_SZ:
67 643 : if (val != NULL) {
68 : /* The data should be provided as UTF16 string */
69 643 : convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16,
70 643 : val->data, val->length,
71 643 : (void **)&data->data, &data->length);
72 : } else {
73 0 : data->data = NULL;
74 0 : data->length = 0;
75 : }
76 640 : break;
77 :
78 806 : case REG_DWORD:
79 : case REG_DWORD_BIG_ENDIAN:
80 806 : if (val != NULL) {
81 806 : int error = 0;
82 : /* The data is a plain DWORD */
83 6 : uint32_t tmp;
84 :
85 806 : tmp = smb_strtoul((char *)val->data,
86 : NULL,
87 : 0,
88 : &error,
89 : SMB_STR_STANDARD);
90 806 : if (error != 0) {
91 0 : data->data = NULL;
92 0 : data->length = 0;
93 0 : break;
94 : }
95 806 : data->data = talloc_size(mem_ctx, sizeof(uint32_t));
96 806 : if (data->data != NULL) {
97 806 : SIVAL(data->data, 0, tmp);
98 : }
99 806 : 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 0 : 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 7520 : case REG_BINARY:
134 : default:
135 7520 : if (val != NULL) {
136 7520 : data->data = talloc_memdup(mem_ctx, val->data,
137 : val->length);
138 7520 : data->length = val->length;
139 : } else {
140 0 : data->data = NULL;
141 0 : data->length = 0;
142 : }
143 7520 : break;
144 : }
145 9369 : }
146 :
147 3037 : 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 91 : struct ldb_message *msg;
153 91 : char *name_dup, *type_str;
154 91 : int ret;
155 :
156 3037 : msg = ldb_msg_new(mem_ctx);
157 3037 : if (msg == NULL) {
158 0 : return NULL;
159 : }
160 :
161 3037 : name_dup = talloc_strdup(msg, name);
162 3037 : if (name_dup == NULL) {
163 0 : talloc_free(msg);
164 0 : return NULL;
165 : }
166 :
167 3037 : ret = ldb_msg_add_string(msg, "value", name_dup);
168 3037 : if (ret != LDB_SUCCESS) {
169 0 : talloc_free(msg);
170 0 : return NULL;
171 : }
172 :
173 3037 : switch (type) {
174 497 : case REG_SZ:
175 : case REG_EXPAND_SZ:
176 941 : if ((data.length > 0) && (data.data != NULL)) {
177 53 : struct ldb_val *val;
178 497 : bool ret2 = false;
179 :
180 497 : val = talloc_zero(msg, struct ldb_val);
181 497 : if (val == NULL) {
182 0 : talloc_free(msg);
183 0 : return NULL;
184 : }
185 :
186 : /* The data is provided as UTF16 string */
187 550 : ret2 = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8,
188 497 : (void *)data.data, data.length,
189 497 : (void **)&val->data, &val->length);
190 497 : if (ret2) {
191 497 : 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 444 : break;
200 :
201 380 : case REG_DWORD:
202 : case REG_DWORD_BIG_ENDIAN:
203 380 : if ((data.length > 0) && (data.data != NULL)) {
204 380 : if (data.length == sizeof(uint32_t)) {
205 38 : char *conv_str;
206 :
207 418 : conv_str = talloc_asprintf(msg, "0x%8.8x",
208 380 : IVAL(data.data, 0));
209 380 : if (conv_str == NULL) {
210 0 : talloc_free(msg);
211 0 : return NULL;
212 : }
213 380 : 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 342 : break;
223 :
224 80 : case REG_QWORD:
225 80 : if ((data.length > 0) && (data.data != NULL)) {
226 80 : if (data.length == sizeof(uint64_t)) {
227 0 : 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 2080 : case REG_BINARY:
248 : default:
249 2080 : if ((data.length > 0) && (data.data != NULL)) {
250 2080 : 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 2080 : break;
255 : }
256 :
257 3037 : if (ret != LDB_SUCCESS) {
258 0 : talloc_free(msg);
259 0 : return NULL;
260 : }
261 :
262 3037 : type_str = talloc_asprintf(mem_ctx, "%u", type);
263 3037 : if (type_str == NULL) {
264 0 : talloc_free(msg);
265 0 : return NULL;
266 : }
267 :
268 3037 : ret = ldb_msg_add_string(msg, "type", type_str);
269 3037 : if (ret != LDB_SUCCESS) {
270 0 : talloc_free(msg);
271 0 : return NULL;
272 : }
273 :
274 2946 : return msg;
275 : }
276 :
277 51926 : static char *reg_ldb_escape(TALLOC_CTX *mem_ctx, const char *value)
278 : {
279 3731 : struct ldb_val val;
280 :
281 51926 : val.data = discard_const_p(uint8_t, value);
282 51926 : val.length = strlen(value);
283 :
284 51926 : return ldb_dn_escape_value(mem_ctx, val);
285 : }
286 :
287 1512 : static int reg_close_ldb_key(struct ldb_key_data *key)
288 : {
289 1512 : if (key->subkeys != NULL) {
290 3 : talloc_free(key->subkeys);
291 3 : key->subkeys = NULL;
292 : }
293 :
294 1512 : if (key->values != NULL) {
295 1 : talloc_free(key->values);
296 1 : key->values = NULL;
297 : }
298 1512 : return 0;
299 : }
300 :
301 42247 : 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 3638 : struct ldb_dn *ret;
306 3638 : char *mypath;
307 3638 : char *begin;
308 42247 : struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data);
309 42247 : struct ldb_context *ldb = kd->ldb;
310 :
311 42247 : mypath = talloc_strdup(mem_ctx, path);
312 42247 : if (mypath == NULL) {
313 0 : return NULL;
314 : }
315 :
316 42247 : ret = ldb_dn_new(mem_ctx, ldb, add);
317 42247 : if (!ldb_dn_validate(ret)) {
318 0 : talloc_free(ret);
319 0 : return NULL;
320 : }
321 :
322 42247 : if (!ldb_dn_add_base(ret, kd->dn)) {
323 0 : talloc_free(ret);
324 0 : return NULL;
325 : }
326 :
327 46487 : while (mypath[0] != '\0') {
328 46487 : begin = strchr(mypath, '\\');
329 46487 : if (begin != NULL) {
330 4240 : *begin = '\0';
331 : }
332 :
333 46487 : 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 46487 : if (begin != NULL) {
340 4240 : mypath = begin + 1;
341 : } else {
342 38609 : break;
343 : }
344 : }
345 :
346 38609 : return ret;
347 : }
348 :
349 512 : static WERROR cache_subkeys(struct ldb_key_data *kd)
350 : {
351 512 : struct ldb_context *c = kd->ldb;
352 31 : struct ldb_result *res;
353 31 : int ret;
354 :
355 512 : ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL,
356 : NULL, "(key=*)");
357 512 : 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 512 : kd->subkey_count = res->count;
364 512 : kd->subkeys = talloc_steal(kd, res->msgs);
365 512 : talloc_free(res);
366 :
367 512 : return WERR_OK;
368 : }
369 :
370 3000 : static WERROR cache_values(struct ldb_key_data *kd)
371 : {
372 3000 : struct ldb_context *c = kd->ldb;
373 38 : struct ldb_result *res;
374 38 : int ret;
375 :
376 3000 : ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL,
377 : NULL, "(value=*)");
378 3000 : 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 3000 : kd->value_count = res->count;
385 3000 : kd->values = talloc_steal(kd, res->msgs);
386 3000 : talloc_free(res);
387 :
388 3000 : return WERR_OK;
389 : }
390 :
391 :
392 260 : 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 260 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
399 :
400 : /* Initialization */
401 260 : if (name != NULL)
402 257 : *name = NULL;
403 260 : if (classname != NULL)
404 241 : *classname = NULL;
405 260 : if (last_mod_time != NULL)
406 241 : *last_mod_time = 0; /* TODO: we need to add this to the
407 : ldb backend properly */
408 :
409 : /* Do a search if necessary */
410 260 : if (kd->subkeys == NULL) {
411 242 : W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
412 : }
413 :
414 260 : if (idx >= kd->subkey_count)
415 242 : return WERR_NO_MORE_ITEMS;
416 :
417 18 : if (name != NULL)
418 17 : *name = talloc_strdup(mem_ctx,
419 17 : ldb_msg_find_attr_as_string(kd->subkeys[idx], "key", NULL));
420 18 : if (classname != NULL)
421 1 : *classname = talloc_strdup(mem_ctx,
422 1 : ldb_msg_find_attr_as_string(kd->subkeys[idx], "classname", NULL));
423 :
424 18 : return WERR_OK;
425 : }
426 :
427 3398 : 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 3398 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
433 3398 : struct ldb_context *c = kd->ldb;
434 3398 : const char* attrs[] = { "data", "type", NULL };
435 37 : struct ldb_result *res;
436 37 : int ret;
437 :
438 3398 : ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_BASE, attrs,
439 : NULL);
440 :
441 3398 : 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 3398 : if (res->count == 0 || res->msgs[0]->num_elements == 0) {
448 3395 : talloc_free(res);
449 3395 : return WERR_FILE_NOT_FOUND;
450 : }
451 :
452 3 : if ((data_type != NULL) && (data != NULL)) {
453 3 : reg_ldb_unpack_value(mem_ctx, res->msgs[0], name, data_type,
454 : data);
455 : }
456 :
457 3 : talloc_free(res);
458 :
459 3 : return WERR_OK;
460 : }
461 :
462 2887 : 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 2887 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
467 :
468 : /* if the default value exists, give it back */
469 2887 : if (W_ERROR_IS_OK(ldb_get_default_value(mem_ctx, k, name, data_type,
470 : data))) {
471 1 : if (idx == 0)
472 1 : return WERR_OK;
473 : else
474 0 : --idx;
475 : }
476 :
477 : /* Do the search if necessary */
478 2886 : if (kd->values == NULL) {
479 962 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
480 : }
481 :
482 2886 : if (idx >= kd->value_count)
483 962 : return WERR_NO_MORE_ITEMS;
484 :
485 1924 : reg_ldb_unpack_value(mem_ctx, kd->values[idx], name, data_type, data);
486 :
487 1924 : return WERR_OK;
488 : }
489 :
490 7928 : 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 7928 : struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
495 8 : const char *res_name;
496 8 : uint32_t idx;
497 :
498 : /* the default value was requested, give it back */
499 7928 : if (name[0] == '\0') {
500 241 : return ldb_get_default_value(mem_ctx, k, NULL, data_type, data);
501 : }
502 :
503 : /* Do the search if necessary */
504 7687 : if (kd->values == NULL) {
505 1527 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
506 : }
507 :
508 7927 : for (idx = 0; idx < kd->value_count; idx++) {
509 7682 : res_name = ldb_msg_find_attr_as_string(kd->values[idx], "value",
510 : "");
511 7682 : if (ldb_attr_cmp(name, res_name) == 0) {
512 7442 : reg_ldb_unpack_value(mem_ctx, kd->values[idx], NULL,
513 : data_type, data);
514 7442 : return WERR_OK;
515 : }
516 : }
517 :
518 245 : return WERR_FILE_NOT_FOUND;
519 : }
520 :
521 35596 : static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct hive_key *h,
522 : const char *name, struct hive_key **key)
523 : {
524 3230 : struct ldb_result *res;
525 3230 : struct ldb_dn *ldb_path;
526 3230 : int ret;
527 3230 : struct ldb_key_data *newkd;
528 35596 : struct ldb_key_data *kd = talloc_get_type(h, struct ldb_key_data);
529 35596 : struct ldb_context *c = kd->ldb;
530 :
531 35596 : ldb_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
532 35596 : W_ERROR_HAVE_NO_MEMORY(ldb_path);
533 :
534 35596 : ret = ldb_search(c, mem_ctx, &res, ldb_path, LDB_SCOPE_BASE, NULL,
535 : NULL);
536 :
537 35596 : 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 35596 : } else if (res->count == 0) {
542 6001 : DEBUG(3, ("Key '%s' not found\n",
543 : ldb_dn_get_linearized(ldb_path)));
544 6001 : talloc_free(res);
545 6001 : return WERR_FILE_NOT_FOUND;
546 : }
547 :
548 29595 : newkd = talloc_zero(mem_ctx, struct ldb_key_data);
549 29595 : W_ERROR_HAVE_NO_MEMORY(newkd);
550 29595 : newkd->key.ops = ®_backend_ldb;
551 29595 : newkd->ldb = talloc_reference(newkd, kd->ldb);
552 29595 : newkd->dn = ldb_dn_copy(newkd, res->msgs[0]->dn);
553 29595 : newkd->classname = talloc_steal(newkd,
554 : ldb_msg_find_attr_as_string(res->msgs[0], "classname", NULL));
555 :
556 29595 : talloc_free(res);
557 :
558 29595 : *key = (struct hive_key *)newkd;
559 :
560 29595 : return WERR_OK;
561 : }
562 :
563 1512 : 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 38 : struct ldb_key_data *kd;
571 38 : struct ldb_context *wrap;
572 38 : struct ldb_message *attrs_msg;
573 :
574 1512 : if (location == NULL)
575 0 : return WERR_INVALID_PARAMETER;
576 :
577 1512 : wrap = ldb_wrap_connect(parent_ctx, ev_ctx, lp_ctx,
578 : location, session_info, credentials, 0);
579 :
580 1512 : if (wrap == NULL) {
581 0 : DEBUG(1, (__FILE__": unable to connect\n"));
582 0 : return WERR_FOOBAR;
583 : }
584 :
585 1512 : attrs_msg = ldb_msg_new(wrap);
586 1512 : W_ERROR_HAVE_NO_MEMORY(attrs_msg);
587 1512 : attrs_msg->dn = ldb_dn_new(attrs_msg, wrap, "@ATTRIBUTES");
588 1512 : W_ERROR_HAVE_NO_MEMORY(attrs_msg->dn);
589 1512 : ldb_msg_add_string(attrs_msg, "key", "CASE_INSENSITIVE");
590 1512 : ldb_msg_add_string(attrs_msg, "value", "CASE_INSENSITIVE");
591 :
592 1512 : ldb_add(wrap, attrs_msg);
593 :
594 1512 : ldb_set_debug_stderr(wrap);
595 :
596 1512 : kd = talloc_zero(parent_ctx, struct ldb_key_data);
597 1512 : kd->key.ops = ®_backend_ldb;
598 1512 : kd->ldb = talloc_reference(kd, wrap);
599 1512 : talloc_set_destructor (kd, reg_close_ldb_key);
600 1512 : kd->dn = ldb_dn_new(kd, wrap, "hive=NONE");
601 :
602 1512 : *k = (struct hive_key *)kd;
603 :
604 1512 : return WERR_OK;
605 : }
606 :
607 4882 : 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 4882 : struct ldb_key_data *parentkd = discard_const_p(struct ldb_key_data, parent);
613 399 : struct ldb_dn *ldb_path;
614 399 : struct ldb_message *msg;
615 399 : struct ldb_key_data *newkd;
616 399 : int ret;
617 :
618 4882 : ldb_path = reg_path_to_ldb(mem_ctx, parent, name, NULL);
619 4882 : W_ERROR_HAVE_NO_MEMORY(ldb_path);
620 :
621 4882 : msg = ldb_msg_new(mem_ctx);
622 4882 : W_ERROR_HAVE_NO_MEMORY(msg);
623 :
624 4882 : msg->dn = ldb_path;
625 :
626 4882 : ldb_msg_add_string(msg, "key", name);
627 4882 : if (classname != NULL) {
628 0 : ldb_msg_add_string(msg, "classname", classname);
629 : }
630 :
631 4882 : ret = ldb_add(parentkd->ldb, msg);
632 :
633 4882 : talloc_free(msg);
634 :
635 4882 : if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
636 0 : return WERR_ALREADY_EXISTS;
637 : }
638 :
639 4882 : if (ret != LDB_SUCCESS) {
640 0 : DEBUG(1, ("ldb_add: %s\n", ldb_errstring(parentkd->ldb)));
641 0 : return WERR_FOOBAR;
642 : }
643 :
644 4882 : DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(ldb_path)));
645 :
646 4882 : newkd = talloc_zero(mem_ctx, struct ldb_key_data);
647 4882 : W_ERROR_HAVE_NO_MEMORY(newkd);
648 4882 : newkd->ldb = talloc_reference(newkd, parentkd->ldb);
649 4882 : newkd->key.ops = ®_backend_ldb;
650 4882 : newkd->dn = talloc_steal(newkd, ldb_path);
651 4882 : newkd->classname = talloc_steal(newkd, classname);
652 :
653 4882 : *newkey = (struct hive_key *)newkd;
654 :
655 : /* reset cache */
656 4882 : talloc_free(parentkd->subkeys);
657 4882 : parentkd->subkeys = NULL;
658 :
659 4882 : return WERR_OK;
660 : }
661 :
662 2408 : static WERROR ldb_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
663 : const char *child)
664 : {
665 8 : int ret;
666 2408 : struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
667 8 : struct ldb_message *msg;
668 8 : struct ldb_dn *childdn;
669 :
670 2408 : if (child[0] == '\0') {
671 : /* default value */
672 2 : msg = ldb_msg_new(mem_ctx);
673 2 : W_ERROR_HAVE_NO_MEMORY(msg);
674 2 : msg->dn = ldb_dn_copy(msg, kd->dn);
675 2 : W_ERROR_HAVE_NO_MEMORY(msg->dn);
676 2 : ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
677 2 : if (ret != LDB_SUCCESS) {
678 0 : return WERR_FOOBAR;
679 : }
680 2 : ret = ldb_msg_add_empty(msg, "type", LDB_FLAG_MOD_DELETE,
681 : NULL);
682 2 : if (ret != LDB_SUCCESS) {
683 0 : return WERR_FOOBAR;
684 : }
685 :
686 2 : ret = ldb_modify(kd->ldb, msg);
687 :
688 2 : talloc_free(msg);
689 :
690 2 : if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
691 1 : return WERR_FILE_NOT_FOUND;
692 1 : } 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 2406 : childdn = ldb_dn_copy(kd->ldb, kd->dn);
699 2406 : 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 2406 : ret = ldb_delete(kd->ldb, childdn);
707 :
708 2406 : talloc_free(childdn);
709 :
710 2406 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
711 2 : return WERR_FILE_NOT_FOUND;
712 2404 : } 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 2405 : talloc_free(kd->values);
720 2405 : kd->values = NULL;
721 :
722 2405 : return WERR_OK;
723 : }
724 :
725 2572 : static WERROR ldb_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *key,
726 : const char *name)
727 : {
728 12 : unsigned int i;
729 12 : int ret;
730 2572 : struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
731 12 : struct ldb_dn *ldb_path;
732 2572 : struct ldb_context *c = parentkd->ldb;
733 12 : struct ldb_result *res_keys;
734 12 : struct ldb_result *res_vals;
735 12 : WERROR werr;
736 12 : struct hive_key *hk;
737 :
738 : /* Verify key exists by opening it */
739 2572 : werr = ldb_open_key(mem_ctx, key, name, &hk);
740 2572 : if (!W_ERROR_IS_OK(werr)) {
741 803 : return werr;
742 : }
743 :
744 1769 : ldb_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
745 1769 : W_ERROR_HAVE_NO_MEMORY(ldb_path);
746 :
747 : /* Search for subkeys */
748 1769 : ret = ldb_search(c, mem_ctx, &res_keys, ldb_path, LDB_SCOPE_ONELEVEL,
749 : NULL, "(key=*)");
750 :
751 1769 : 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 1769 : ret = ldb_search(c, mem_ctx, &res_vals, ldb_path, LDB_SCOPE_ONELEVEL,
759 : NULL, "(value=*)");
760 :
761 1769 : 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 1769 : ret = ldb_transaction_start(c);
769 :
770 1769 : if (ret != LDB_SUCCESS) {
771 0 : DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c)));
772 0 : return WERR_FOOBAR;
773 : }
774 :
775 1769 : if (res_keys->count || res_vals->count)
776 : {
777 : /* Delete any subkeys */
778 7 : for (i = 0; i < res_keys->count; i++)
779 : {
780 3 : werr = ldb_del_key(mem_ctx, hk,
781 : ldb_msg_find_attr_as_string(
782 3 : res_keys->msgs[i],
783 : "key", NULL));
784 3 : 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 5 : for (i = 0; i < res_vals->count; i++)
792 : {
793 1 : werr = ldb_del_value(mem_ctx, hk,
794 : ldb_msg_find_attr_as_string(
795 1 : res_vals->msgs[i],
796 : "value", NULL));
797 1 : if (!W_ERROR_IS_OK(werr)) {
798 0 : ret = ldb_transaction_cancel(c);
799 0 : return werr;
800 : }
801 : }
802 : }
803 1769 : talloc_free(res_keys);
804 1769 : talloc_free(res_vals);
805 :
806 : /* Delete the key itself */
807 1769 : ret = ldb_delete(c, ldb_path);
808 :
809 1769 : 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 1769 : ret = ldb_transaction_commit(c);
818 :
819 1769 : 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 1769 : talloc_free(parentkd->subkeys);
828 1769 : parentkd->subkeys = NULL;
829 :
830 1769 : return WERR_OK;
831 : }
832 :
833 3037 : static WERROR ldb_set_value(struct hive_key *parent,
834 : const char *name, uint32_t type,
835 : const DATA_BLOB data)
836 : {
837 91 : struct ldb_message *msg;
838 3037 : struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data);
839 91 : unsigned int i;
840 91 : int ret;
841 3037 : TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
842 :
843 3037 : msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data);
844 3037 : W_ERROR_HAVE_NO_MEMORY(msg);
845 :
846 3037 : msg->dn = ldb_dn_copy(msg, kd->dn);
847 3037 : W_ERROR_HAVE_NO_MEMORY(msg->dn);
848 :
849 3037 : 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 3033 : 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 12144 : for (i = 0; i < msg->num_elements; i++) {
862 9107 : if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) != LDB_FLAG_MOD_DELETE) {
863 9107 : msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
864 : }
865 : }
866 3037 : ret = ldb_modify(kd->ldb, msg);
867 3037 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
868 2943 : i = 0;
869 12120 : while (i < msg->num_elements) {
870 9090 : 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 9090 : ++i;
874 : }
875 : }
876 3030 : ret = ldb_add(kd->ldb, msg);
877 : }
878 3037 : 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 3037 : talloc_free(msg);
884 :
885 3037 : 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 3037 : talloc_free(kd->values);
893 3037 : kd->values = NULL;
894 :
895 3037 : talloc_free(mem_ctx);
896 3037 : return WERR_OK;
897 : }
898 :
899 270 : 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 270 : struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
910 270 : uint32_t default_value_type = REG_NONE;
911 270 : DATA_BLOB default_value = { NULL, 0 };
912 29 : WERROR werr;
913 :
914 : /* Initialization */
915 270 : if (classname != NULL)
916 243 : *classname = NULL;
917 270 : if (num_subkeys != NULL)
918 270 : *num_subkeys = 0;
919 270 : if (num_values != NULL)
920 270 : *num_values = 0;
921 270 : if (last_change_time != NULL)
922 243 : *last_change_time = 0;
923 270 : if (max_subkeynamelen != NULL)
924 241 : *max_subkeynamelen = 0;
925 270 : if (max_valnamelen != NULL)
926 241 : *max_valnamelen = 0;
927 270 : 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 270 : werr = ldb_get_default_value(mem_ctx, key, NULL, &default_value_type,
935 : &default_value);
936 270 : if ((!W_ERROR_IS_OK(werr)) && (!W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND))) {
937 0 : return werr;
938 : }
939 :
940 270 : if (kd->subkeys == NULL) {
941 270 : W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
942 : }
943 270 : if (kd->values == NULL) {
944 270 : W_ERROR_NOT_OK_RETURN(cache_values(kd));
945 : }
946 :
947 270 : if (classname != NULL) {
948 243 : *classname = kd->classname;
949 : }
950 :
951 270 : if (num_subkeys != NULL) {
952 270 : *num_subkeys = kd->subkey_count;
953 : }
954 270 : if (num_values != NULL) {
955 270 : *num_values = kd->value_count;
956 : /* also consider the default value if it exists */
957 270 : if (default_value.data != NULL) {
958 1 : ++(*num_values);
959 : }
960 : }
961 :
962 :
963 270 : 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 270 : if (max_valnamelen != NULL || max_valbufsize != NULL) {
974 0 : unsigned int i;
975 0 : 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 0 : uint32_t data_type;
992 0 : 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 270 : talloc_free(default_value.data);
1003 :
1004 270 : 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 : };
|