Merge commit 'release-4-0-0alpha2' into v4-0-test
[kai/samba.git] / source4 / 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         if (name != NULL)
45                 *name = talloc_strdup(mem_ctx,
46                                       ldb_msg_find_attr_as_string(msg, "value",
47                                       NULL));
48
49         if (type != NULL)
50                 *type = ldb_msg_find_attr_as_uint(msg, "type", 0);
51         val = ldb_msg_find_ldb_val(msg, "data");
52
53         switch (*type)
54         {
55         case REG_SZ:
56         case REG_EXPAND_SZ:
57                 data->length = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF8, CH_UTF16,
58                                                      val->data, val->length,
59                                                      (void **)&data->data);
60                 break;
61
62         case REG_DWORD: {
63                 uint32_t tmp = strtoul((char *)val->data, NULL, 0);
64                 *data = data_blob_talloc(mem_ctx, &tmp, 4);
65                 }
66                 break;
67
68         default:
69                 *data = data_blob_talloc(mem_ctx, val->data, val->length);
70                 break;
71         }
72 }
73
74 static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx,
75                                               TALLOC_CTX *mem_ctx,
76                                               const char *name,
77                                               uint32_t type, DATA_BLOB data)
78 {
79         struct ldb_val val;
80         struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
81         char *type_s;
82
83         ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
84
85         switch (type) {
86         case REG_SZ:
87         case REG_EXPAND_SZ:
88                 val.length = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX,
89                                                    (void *)data.data,
90                                                    data.length,
91                                                    (void **)&val.data);
92                 ldb_msg_add_value(msg, "data", &val, NULL);
93                 break;
94
95         case REG_DWORD:
96                 ldb_msg_add_string(msg, "data",
97                                    talloc_asprintf(mem_ctx, "0x%x",
98                                                    IVAL(data.data, 0)));
99                 break;
100         default:
101                 ldb_msg_add_value(msg, "data", &data, NULL);
102         }
103
104
105         type_s = talloc_asprintf(mem_ctx, "%u", type);
106         ldb_msg_add_string(msg, "type", type_s);
107
108         return msg;
109 }
110
111
112 static int reg_close_ldb_key(struct ldb_key_data *key)
113 {
114         if (key->subkeys != NULL) {
115                 talloc_free(key->subkeys);
116                 key->subkeys = NULL;
117         }
118
119         if (key->values != NULL) {
120                 talloc_free(key->values);
121                 key->values = NULL;
122         }
123         return 0;
124 }
125
126 static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx,
127                                       const struct hive_key *from,
128                                       const char *path, const char *add)
129 {
130         TALLOC_CTX *local_ctx;
131         struct ldb_dn *ret;
132         char *mypath = talloc_strdup(mem_ctx, path);
133         char *begin;
134         struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data);
135         struct ldb_context *ldb = kd->ldb;
136
137         local_ctx = talloc_new(mem_ctx);
138
139         if (add) {
140                 ret = ldb_dn_new(mem_ctx, ldb, add);
141         } else {
142                 ret = ldb_dn_new(mem_ctx, ldb, NULL);
143         }
144         if (!ldb_dn_validate(ret)) {
145                 talloc_free(ret);
146                 talloc_free(local_ctx);
147                 return NULL;
148         }
149
150         while (mypath) {
151                 char *keyname;
152
153                 begin = strrchr(mypath, '\\');
154
155                 if (begin) keyname = begin + 1;
156                 else keyname = mypath;
157
158                 if(strlen(keyname)) {
159                         ldb_dn_add_base_fmt(ret, "key=%s", keyname);
160                 }
161
162                 if(begin) {
163                         *begin = '\0';
164                 } else {
165                         break;
166                 }
167         }
168
169         ldb_dn_add_base(ret, kd->dn);
170
171         talloc_free(local_ctx);
172
173         return ret;
174 }
175
176 static WERROR cache_subkeys(struct ldb_key_data *kd)
177 {
178         struct ldb_context *c = kd->ldb;
179         struct ldb_result *res;
180         int ret;
181
182         ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &res);
183
184         if (ret != LDB_SUCCESS) {
185                 DEBUG(0, ("Error getting subkeys for '%s': %s\n",
186                         ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
187                 return WERR_FOOBAR;
188         }
189
190         kd->subkey_count = res->count;
191         kd->subkeys = talloc_steal(kd, res->msgs);
192         talloc_free(res);
193
194         return WERR_OK;
195 }
196
197 static WERROR cache_values(struct ldb_key_data *kd)
198 {
199         struct ldb_context *c = kd->ldb;
200         struct ldb_result *res;
201         int ret;
202
203         ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL,
204                          "(value=*)", NULL, &res);
205
206         if (ret != LDB_SUCCESS) {
207                 DEBUG(0, ("Error getting values for '%s': %s\n",
208                         ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
209                 return WERR_FOOBAR;
210         }
211         kd->value_count = res->count;
212         kd->values = talloc_steal(kd, res->msgs);
213         talloc_free(res);
214         return WERR_OK;
215 }
216
217
218 static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx,
219                                    const struct hive_key *k, uint32_t idx,
220                                    const char **name,
221                                    const char **classname,
222                                    NTTIME *last_mod_time)
223 {
224         struct ldb_message_element *el;
225         struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
226
227         /* Do a search if necessary */
228         if (kd->subkeys == NULL) {
229                 W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
230         }
231
232         if (idx >= kd->subkey_count)
233                 return WERR_NO_MORE_ITEMS;
234
235         el = ldb_msg_find_element(kd->subkeys[idx], "key");
236         SMB_ASSERT(el != NULL);
237         SMB_ASSERT(el->num_values != 0);
238
239         if (name != NULL)
240                 *name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
241
242         if (classname != NULL)
243                 *classname = NULL; /* TODO: Store properly */
244
245         if (last_mod_time != NULL)
246                 *last_mod_time = 0; /* TODO: we need to add this to the
247                                                 ldb backend properly */
248
249         return WERR_OK;
250 }
251
252 static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct hive_key *k,
253                                   int idx, const char **name,
254                                   uint32_t *data_type, DATA_BLOB *data)
255 {
256         struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
257
258         /* Do the search if necessary */
259         if (kd->values == NULL) {
260                 W_ERROR_NOT_OK_RETURN(cache_values(kd));
261         }
262
263         if (idx >= kd->value_count)
264                 return WERR_NO_MORE_ITEMS;
265
266         reg_ldb_unpack_value(mem_ctx, kd->values[idx],
267                              name, data_type, data);
268
269         return WERR_OK;
270 }
271
272 static WERROR ldb_get_value(TALLOC_CTX *mem_ctx, struct hive_key *k,
273                             const char *name, uint32_t *data_type,
274                             DATA_BLOB *data)
275 {
276         struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
277         struct ldb_context *c = kd->ldb;
278         struct ldb_result *res;
279         int ret;
280         char *query = talloc_asprintf(mem_ctx, "(value=%s)", name);
281
282         ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, query, NULL, &res);
283
284         talloc_free(query);
285
286         if (ret != LDB_SUCCESS) {
287                 DEBUG(0, ("Error getting values for '%s': %s\n",
288                         ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
289                 return WERR_FOOBAR;
290         }
291
292         if (res->count == 0)
293                 return WERR_NOT_FOUND;
294
295         reg_ldb_unpack_value(mem_ctx, res->msgs[0], NULL, data_type, data);
296
297         return WERR_OK;
298 }
299
300 static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct hive_key *h,
301                            const char *name, struct hive_key **key)
302 {
303         struct ldb_result *res;
304         struct ldb_dn *ldap_path;
305         int ret;
306         struct ldb_key_data *newkd;
307         struct ldb_key_data *kd = talloc_get_type(h, struct ldb_key_data);
308         struct ldb_context *c = kd->ldb;
309
310         ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
311
312         ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &res);
313
314         if (ret != LDB_SUCCESS) {
315                 DEBUG(3, ("Error opening key '%s': %s\n",
316                         ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
317                 return WERR_FOOBAR;
318         } else if (res->count == 0) {
319                 DEBUG(3, ("Key '%s' not found\n",
320                         ldb_dn_get_linearized(ldap_path)));
321                 talloc_free(res);
322                 return WERR_NOT_FOUND;
323         }
324
325         newkd = talloc_zero(mem_ctx, struct ldb_key_data);
326         newkd->key.ops = &reg_backend_ldb;
327         newkd->ldb = talloc_reference(newkd, kd->ldb);
328         newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn);
329
330         *key = (struct hive_key *)newkd;
331
332         talloc_free(res);
333
334         return WERR_OK;
335 }
336
337 WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location,
338                          struct auth_session_info *session_info,
339                          struct cli_credentials *credentials,
340                          struct loadparm_context *lp_ctx,
341                          struct hive_key **k)
342 {
343         struct ldb_key_data *kd;
344         struct ldb_context *wrap;
345
346         if (location == NULL)
347                 return WERR_INVALID_PARAM;
348
349         wrap = ldb_wrap_connect(parent_ctx, lp_ctx,
350                                 location, session_info, credentials, 0, NULL);
351
352         if (wrap == NULL) {
353                 DEBUG(1, (__FILE__": unable to connect\n"));
354                 return WERR_FOOBAR;
355         }
356
357         ldb_set_debug_stderr(wrap);
358
359         kd = talloc_zero(parent_ctx, struct ldb_key_data);
360         kd->key.ops = &reg_backend_ldb;
361         kd->ldb = talloc_reference(kd, wrap);
362         talloc_set_destructor (kd, reg_close_ldb_key);
363         kd->dn = ldb_dn_new(kd, wrap, "hive=NONE");
364
365         *k = (struct hive_key *)kd;
366
367         return WERR_OK;
368 }
369
370 static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
371                           const char *name, const char *classname,
372                           struct security_descriptor *sd,
373                           struct hive_key **newkey)
374 {
375         const struct ldb_key_data *parentkd = (const struct ldb_key_data *)parent;
376         struct ldb_message *msg;
377         struct ldb_key_data *newkd;
378         int ret;
379
380         msg = ldb_msg_new(mem_ctx);
381
382         msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
383
384         ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
385         if (classname != NULL)
386                 ldb_msg_add_string(msg, "classname",
387                                    talloc_strdup(mem_ctx, classname));
388
389         ret = ldb_add(parentkd->ldb, msg);
390         if (ret < 0) {
391                 DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parentkd->ldb)));
392                 return WERR_FOOBAR;
393         }
394
395         DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(msg->dn)));
396
397         newkd = talloc_zero(mem_ctx, struct ldb_key_data);
398         newkd->ldb = talloc_reference(newkd, parentkd->ldb);
399         newkd->key.ops = &reg_backend_ldb;
400         newkd->dn = talloc_steal(newkd, msg->dn);
401
402         *newkey = (struct hive_key *)newkd;
403
404         return WERR_OK;
405 }
406
407 static WERROR ldb_del_key(const struct hive_key *key, const char *child)
408 {
409         int ret;
410         struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
411         struct ldb_dn *childdn;
412
413         childdn = ldb_dn_copy(parentkd->ldb, parentkd->dn);
414         ldb_dn_add_child_fmt(childdn, "key=%s", child);
415
416         ret = ldb_delete(parentkd->ldb, childdn);
417
418         talloc_free(childdn);
419
420         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
421                 return WERR_NOT_FOUND;
422         } else if (ret < 0) {
423                 DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(parentkd->ldb)));
424                 return WERR_FOOBAR;
425         }
426
427         return WERR_OK;
428 }
429
430 static WERROR ldb_del_value (struct hive_key *key, const char *child)
431 {
432         int ret;
433         struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
434         struct ldb_dn *childdn;
435
436         childdn = ldb_dn_copy(kd->ldb, kd->dn);
437         ldb_dn_add_child_fmt(childdn, "value=%s", child);
438
439         ret = ldb_delete(kd->ldb, childdn);
440
441         talloc_free(childdn);
442
443         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
444                 return WERR_NOT_FOUND;
445         } else if (ret < 0) {
446                 DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb)));
447                 return WERR_FOOBAR;
448         }
449
450         return WERR_OK;
451 }
452
453 static WERROR ldb_set_value(struct hive_key *parent,
454                             const char *name, uint32_t type,
455                             const DATA_BLOB data)
456 {
457         struct ldb_message *msg;
458         struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data);
459         int ret;
460         TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
461
462         msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data);
463
464         msg->dn = ldb_dn_copy(msg, kd->dn);
465         ldb_dn_add_child_fmt(msg->dn, "value=%s", name);
466
467         ret = ldb_add(kd->ldb, msg);
468         if (ret < 0) {
469                 ret = ldb_modify(kd->ldb, msg);
470                 if (ret < 0) {
471                         DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(kd->ldb)));
472                         talloc_free(mem_ctx);
473                         return WERR_FOOBAR;
474                 }
475         }
476
477         talloc_free(mem_ctx);
478         return WERR_OK;
479 }
480
481 static WERROR ldb_get_key_info(TALLOC_CTX *mem_ctx,
482                                const struct hive_key *key,
483                                const char **classname,
484                                uint32_t *num_subkeys,
485                                uint32_t *num_values,
486                                NTTIME *last_change_time)
487 {
488         struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
489
490         /* FIXME */
491         if (classname != NULL)
492                 *classname = NULL;
493
494         if (num_subkeys != NULL) {
495                 W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
496                 *num_subkeys = kd->subkey_count;
497         }
498
499         if (num_values != NULL) {
500                 W_ERROR_NOT_OK_RETURN(cache_values(kd));
501                 *num_values = kd->value_count;
502         }
503
504         if (last_change_time != NULL)
505                 *last_change_time = 0;
506
507         return WERR_OK;
508 }
509
510 static struct hive_operations reg_backend_ldb = {
511         .name = "ldb",
512         .add_key = ldb_add_key,
513         .del_key = ldb_del_key,
514         .get_key_by_name = ldb_open_key,
515         .enum_value = ldb_get_value_by_id,
516         .enum_key = ldb_get_subkey_by_id,
517         .set_value = ldb_set_value,
518         .get_value_by_name = ldb_get_value,
519         .delete_value = ldb_del_value,
520         .get_key_info = ldb_get_key_info,
521 };