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