registry: Check for more specific LDB return codes, handle changing existing values...
[ira/wip.git] / source / lib / registry / ldb.c
1 /*
2    Unix SMB/CIFS implementation.
3    Registry interface
4    Copyright (C) Jelmer Vernooij  2004-2007.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "registry.h"
22 #include "lib/ldb/include/ldb.h"
23 #include "lib/ldb/include/ldb_errors.h"
24 #include "ldb_wrap.h"
25 #include "librpc/gen_ndr/winreg.h"
26 #include "param/param.h"
27
28 static struct hive_operations reg_backend_ldb;
29
30 struct ldb_key_data
31 {
32         struct hive_key key;
33         struct ldb_context *ldb;
34         struct ldb_dn *dn;
35         struct ldb_message **subkeys, **values;
36         int subkey_count, value_count;
37 };
38
39 static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
40                                  const char **name, uint32_t *type,
41                                  DATA_BLOB *data)
42 {
43         const struct ldb_val *val;
44         uint32_t value_type;
45
46         if (name != NULL)
47                 *name = talloc_strdup(mem_ctx,
48                                       ldb_msg_find_attr_as_string(msg, "value",
49                                       NULL));
50
51         value_type = ldb_msg_find_attr_as_uint(msg, "type", 0);
52         if (type != NULL)
53                 *type = value_type; 
54         val = ldb_msg_find_ldb_val(msg, "data");
55
56         switch (value_type)
57         {
58         case REG_SZ:
59         case REG_EXPAND_SZ:
60                 data->length = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF8, CH_UTF16,
61                                                      val->data, val->length,
62                                                      (void **)&data->data);
63                 break;
64
65         case REG_DWORD: {
66                 uint32_t tmp = strtoul((char *)val->data, NULL, 0);
67                 *data = data_blob_talloc(mem_ctx, &tmp, 4);
68                 }
69                 break;
70
71         default:
72                 *data = data_blob_talloc(mem_ctx, val->data, val->length);
73                 break;
74         }
75 }
76
77 static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx,
78                                               TALLOC_CTX *mem_ctx,
79                                               const char *name,
80                                               uint32_t type, DATA_BLOB data)
81 {
82         struct ldb_val val;
83         struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
84         char *type_s;
85
86         ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
87
88         switch (type) {
89         case REG_SZ:
90         case REG_EXPAND_SZ:
91                 val.length = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX,
92                                                    (void *)data.data,
93                                                    data.length,
94                                                    (void **)&val.data);
95                 ldb_msg_add_value(msg, "data", &val, NULL);
96                 break;
97
98         case REG_DWORD:
99                 ldb_msg_add_string(msg, "data",
100                                    talloc_asprintf(mem_ctx, "0x%x",
101                                                    IVAL(data.data, 0)));
102                 break;
103         default:
104                 ldb_msg_add_value(msg, "data", &data, NULL);
105         }
106
107
108         type_s = talloc_asprintf(mem_ctx, "%u", type);
109         ldb_msg_add_string(msg, "type", type_s);
110
111         return msg;
112 }
113
114
115 static int reg_close_ldb_key(struct ldb_key_data *key)
116 {
117         if (key->subkeys != NULL) {
118                 talloc_free(key->subkeys);
119                 key->subkeys = NULL;
120         }
121
122         if (key->values != NULL) {
123                 talloc_free(key->values);
124                 key->values = NULL;
125         }
126         return 0;
127 }
128
129 static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx,
130                                       const struct hive_key *from,
131                                       const char *path, const char *add)
132 {
133         TALLOC_CTX *local_ctx;
134         struct ldb_dn *ret;
135         char *mypath = talloc_strdup(mem_ctx, path);
136         char *begin;
137         struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data);
138         struct ldb_context *ldb = kd->ldb;
139
140         local_ctx = talloc_new(mem_ctx);
141
142         if (add) {
143                 ret = ldb_dn_new(mem_ctx, ldb, add);
144         } else {
145                 ret = ldb_dn_new(mem_ctx, ldb, NULL);
146         }
147         if (!ldb_dn_validate(ret)) {
148                 talloc_free(ret);
149                 talloc_free(local_ctx);
150                 return NULL;
151         }
152
153         while (mypath) {
154                 char *keyname;
155
156                 begin = strrchr(mypath, '\\');
157
158                 if (begin) keyname = begin + 1;
159                 else keyname = mypath;
160
161                 if(strlen(keyname)) {
162                         ldb_dn_add_base_fmt(ret, "key=%s", keyname);
163                 }
164
165                 if(begin) {
166                         *begin = '\0';
167                 } else {
168                         break;
169                 }
170         }
171
172         ldb_dn_add_base(ret, kd->dn);
173
174         talloc_free(local_ctx);
175
176         return ret;
177 }
178
179 static WERROR cache_subkeys(struct ldb_key_data *kd)
180 {
181         struct ldb_context *c = kd->ldb;
182         struct ldb_result *res;
183         int ret;
184
185         ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &res);
186
187         if (ret != LDB_SUCCESS) {
188                 DEBUG(0, ("Error getting subkeys for '%s': %s\n",
189                         ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
190                 return WERR_FOOBAR;
191         }
192
193         kd->subkey_count = res->count;
194         kd->subkeys = talloc_steal(kd, res->msgs);
195         talloc_free(res);
196
197         return WERR_OK;
198 }
199
200 static WERROR cache_values(struct ldb_key_data *kd)
201 {
202         struct ldb_context *c = kd->ldb;
203         struct ldb_result *res;
204         int ret;
205
206         ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL,
207                          "(value=*)", NULL, &res);
208
209         if (ret != LDB_SUCCESS) {
210                 DEBUG(0, ("Error getting values for '%s': %s\n",
211                         ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
212                 return WERR_FOOBAR;
213         }
214         kd->value_count = res->count;
215         kd->values = talloc_steal(kd, res->msgs);
216         talloc_free(res);
217         return WERR_OK;
218 }
219
220
221 static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx,
222                                    const struct hive_key *k, uint32_t idx,
223                                    const char **name,
224                                    const char **classname,
225                                    NTTIME *last_mod_time)
226 {
227         struct ldb_message_element *el;
228         struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
229
230         /* Do a search if necessary */
231         if (kd->subkeys == NULL) {
232                 W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
233         }
234
235         if (idx >= kd->subkey_count)
236                 return WERR_NO_MORE_ITEMS;
237
238         el = ldb_msg_find_element(kd->subkeys[idx], "key");
239         SMB_ASSERT(el != NULL);
240         SMB_ASSERT(el->num_values != 0);
241
242         if (name != NULL)
243                 *name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
244
245         if (classname != NULL)
246                 *classname = NULL; /* TODO: Store properly */
247
248         if (last_mod_time != NULL)
249                 *last_mod_time = 0; /* TODO: we need to add this to the
250                                                 ldb backend properly */
251
252         return WERR_OK;
253 }
254
255 static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct hive_key *k,
256                                   int idx, const char **name,
257                                   uint32_t *data_type, DATA_BLOB *data)
258 {
259         struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
260
261         /* Do the search if necessary */
262         if (kd->values == NULL) {
263                 W_ERROR_NOT_OK_RETURN(cache_values(kd));
264         }
265
266         if (idx >= kd->value_count)
267                 return WERR_NO_MORE_ITEMS;
268
269         reg_ldb_unpack_value(mem_ctx, kd->values[idx],
270                              name, data_type, data);
271
272         return WERR_OK;
273 }
274
275 static WERROR ldb_get_value(TALLOC_CTX *mem_ctx, struct hive_key *k,
276                             const char *name, uint32_t *data_type,
277                             DATA_BLOB *data)
278 {
279         struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
280         struct ldb_context *c = kd->ldb;
281         struct ldb_result *res;
282         int ret;
283         char *query = talloc_asprintf(mem_ctx, "(value=%s)", name);
284
285         ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, query, NULL, &res);
286
287         talloc_free(query);
288
289         if (ret != LDB_SUCCESS) {
290                 DEBUG(0, ("Error getting values for '%s': %s\n",
291                         ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
292                 return WERR_FOOBAR;
293         }
294
295         if (res->count == 0)
296                 return WERR_NOT_FOUND;
297
298         reg_ldb_unpack_value(mem_ctx, res->msgs[0], NULL, data_type, data);
299
300         return WERR_OK;
301 }
302
303 static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct hive_key *h,
304                            const char *name, struct hive_key **key)
305 {
306         struct ldb_result *res;
307         struct ldb_dn *ldap_path;
308         int ret;
309         struct ldb_key_data *newkd;
310         struct ldb_key_data *kd = talloc_get_type(h, struct ldb_key_data);
311         struct ldb_context *c = kd->ldb;
312
313         ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
314
315         ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &res);
316
317         if (ret != LDB_SUCCESS) {
318                 DEBUG(3, ("Error opening key '%s': %s\n",
319                         ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
320                 return WERR_FOOBAR;
321         } else if (res->count == 0) {
322                 DEBUG(3, ("Key '%s' not found\n",
323                         ldb_dn_get_linearized(ldap_path)));
324                 talloc_free(res);
325                 return WERR_NOT_FOUND;
326         }
327
328         newkd = talloc_zero(mem_ctx, struct ldb_key_data);
329         newkd->key.ops = &reg_backend_ldb;
330         newkd->ldb = talloc_reference(newkd, kd->ldb);
331         newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn);
332
333         *key = (struct hive_key *)newkd;
334
335         talloc_free(res);
336
337         return WERR_OK;
338 }
339
340 WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location,
341                          struct auth_session_info *session_info,
342                          struct cli_credentials *credentials,
343                          struct loadparm_context *lp_ctx,
344                          struct hive_key **k)
345 {
346         struct ldb_key_data *kd;
347         struct ldb_context *wrap;
348         struct ldb_message *attrs_msg;
349
350         if (location == NULL)
351                 return WERR_INVALID_PARAM;
352
353         wrap = ldb_wrap_connect(parent_ctx, lp_ctx,
354                                 location, session_info, credentials, 0, NULL);
355
356         if (wrap == NULL) {
357                 DEBUG(1, (__FILE__": unable to connect\n"));
358                 return WERR_FOOBAR;
359         }
360
361         attrs_msg = ldb_msg_new(wrap);
362         W_ERROR_HAVE_NO_MEMORY(attrs_msg);
363         attrs_msg->dn = ldb_dn_new(attrs_msg, wrap, "@ATTRIBUTES");
364         W_ERROR_HAVE_NO_MEMORY(attrs_msg->dn);
365         ldb_msg_add_string(attrs_msg, "key", "CASE_INSENSITIVE");
366         ldb_msg_add_string(attrs_msg, "value", "CASE_INSENSITIVE");
367
368         ldb_add(wrap, attrs_msg);
369
370         ldb_set_debug_stderr(wrap);
371
372         kd = talloc_zero(parent_ctx, struct ldb_key_data);
373         kd->key.ops = &reg_backend_ldb;
374         kd->ldb = talloc_reference(kd, wrap);
375         talloc_set_destructor (kd, reg_close_ldb_key);
376         kd->dn = ldb_dn_new(kd, wrap, "hive=NONE");
377
378         *k = (struct hive_key *)kd;
379
380         return WERR_OK;
381 }
382
383 static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
384                           const char *name, const char *classname,
385                           struct security_descriptor *sd,
386                           struct hive_key **newkey)
387 {
388         const struct ldb_key_data *parentkd = (const struct ldb_key_data *)parent;
389         struct ldb_message *msg;
390         struct ldb_key_data *newkd;
391         int ret;
392
393         msg = ldb_msg_new(mem_ctx);
394
395         msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
396
397         ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
398         if (classname != NULL)
399                 ldb_msg_add_string(msg, "classname",
400                                    talloc_strdup(mem_ctx, classname));
401
402         ret = ldb_add(parentkd->ldb, msg);
403         if (ret < 0) {
404                 DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parentkd->ldb)));
405                 return WERR_FOOBAR;
406         }
407
408         DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(msg->dn)));
409
410         newkd = talloc_zero(mem_ctx, struct ldb_key_data);
411         newkd->ldb = talloc_reference(newkd, parentkd->ldb);
412         newkd->key.ops = &reg_backend_ldb;
413         newkd->dn = talloc_steal(newkd, msg->dn);
414
415         *newkey = (struct hive_key *)newkd;
416
417         return WERR_OK;
418 }
419
420 static WERROR ldb_del_key(const struct hive_key *key, const char *child)
421 {
422         int ret;
423         struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
424         struct ldb_dn *childdn;
425
426         childdn = ldb_dn_copy(parentkd->ldb, parentkd->dn);
427         ldb_dn_add_child_fmt(childdn, "key=%s", child);
428
429         ret = ldb_delete(parentkd->ldb, childdn);
430
431         talloc_free(childdn);
432
433         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
434                 return WERR_NOT_FOUND;
435         } else if (ret < 0) {
436                 DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(parentkd->ldb)));
437                 return WERR_FOOBAR;
438         }
439
440         return WERR_OK;
441 }
442
443 static WERROR ldb_del_value (struct hive_key *key, const char *child)
444 {
445         int ret;
446         struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
447         struct ldb_dn *childdn;
448
449         childdn = ldb_dn_copy(kd->ldb, kd->dn);
450         ldb_dn_add_child_fmt(childdn, "value=%s", child);
451
452         ret = ldb_delete(kd->ldb, childdn);
453
454         talloc_free(childdn);
455
456         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
457                 return WERR_NOT_FOUND;
458         } else if (ret < 0) {
459                 DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb)));
460                 return WERR_FOOBAR;
461         }
462
463         return WERR_OK;
464 }
465
466 static WERROR ldb_set_value(struct hive_key *parent,
467                             const char *name, uint32_t type,
468                             const DATA_BLOB data)
469 {
470         struct ldb_message *msg;
471         struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data);
472         int ret;
473         TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
474
475         msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data);
476
477         msg->dn = ldb_dn_copy(msg, kd->dn);
478         ldb_dn_add_child_fmt(msg->dn, "value=%s", name);
479
480         ret = ldb_add(kd->ldb, msg);
481         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
482                 int i;
483                 for (i = 0; i < msg->num_elements; i++) {
484                         msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
485                 }
486                 ret = ldb_modify(kd->ldb, msg);
487         }
488
489         if (ret != LDB_SUCCESS) {
490                 DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(kd->ldb)));
491                 talloc_free(mem_ctx);
492                 return WERR_FOOBAR;
493         }
494
495         talloc_free(mem_ctx);
496         return WERR_OK;
497 }
498
499 static WERROR ldb_get_key_info(TALLOC_CTX *mem_ctx,
500                                const struct hive_key *key,
501                                const char **classname,
502                                uint32_t *num_subkeys,
503                                uint32_t *num_values,
504                                NTTIME *last_change_time,
505                                uint32_t *max_subkeynamelen,
506                                uint32_t *max_valnamelen,
507                                uint32_t *max_valbufsize)
508 {
509         struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
510
511         /* FIXME */
512         if (classname != NULL)
513                 *classname = NULL;
514
515         if (num_subkeys != NULL) {
516                 W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
517                 *num_subkeys = kd->subkey_count;
518         }
519
520         if (num_values != NULL) {
521                 W_ERROR_NOT_OK_RETURN(cache_values(kd));
522                 *num_values = kd->value_count;
523         }
524
525         if (last_change_time != NULL)
526                 *last_change_time = 0;
527
528         if (max_subkeynamelen != NULL) {
529                 int i;
530                 struct ldb_message_element *el;
531                 W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
532
533                 *max_subkeynamelen = 0;
534
535                 for (i = 0; i < kd->subkey_count; i++) {
536                         el = ldb_msg_find_element(kd->subkeys[i], "key");
537                         *max_subkeynamelen = MAX(*max_subkeynamelen, el->values[0].length);
538                 }
539         }
540
541         if (max_valnamelen != NULL || max_valbufsize != NULL) {
542                 int i;
543                 struct ldb_message_element *el;
544                 W_ERROR_NOT_OK_RETURN(cache_values(kd));
545
546                 if (max_valbufsize != NULL)
547                         *max_valbufsize = 0;
548
549                 if (max_valnamelen != NULL)
550                         *max_valnamelen = 0;
551
552                 for (i = 0; i < kd->value_count; i++) {
553                         if (max_valnamelen != NULL) {
554                                 el = ldb_msg_find_element(kd->values[i], "value");
555                                 *max_valnamelen = MAX(*max_valnamelen, el->values[0].length);
556                         }
557
558                         if (max_valbufsize != NULL) {
559                                 DATA_BLOB data;
560                                 reg_ldb_unpack_value(mem_ctx, kd->values[i], NULL, 
561                                                      NULL, &data);
562                                 *max_valbufsize = MAX(*max_valbufsize, data.length);
563                                 talloc_free(data.data);
564                         }
565                 }
566         }
567
568         return WERR_OK;
569 }
570
571 static struct hive_operations reg_backend_ldb = {
572         .name = "ldb",
573         .add_key = ldb_add_key,
574         .del_key = ldb_del_key,
575         .get_key_by_name = ldb_open_key,
576         .enum_value = ldb_get_value_by_id,
577         .enum_key = ldb_get_subkey_by_id,
578         .set_value = ldb_set_value,
579         .get_value_by_name = ldb_get_value,
580         .delete_value = ldb_del_value,
581         .get_key_info = ldb_get_key_info,
582 };