r10913: This patch isn't as big as it looks ...
[kamenim/samba.git] / source4 / lib / registry / reg_backend_ldb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Registry interface
4    Copyright (C) Jelmer Vernooij  2004.
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "registry.h"
23 #include "lib/ldb/include/ldb.h"
24 #include "db_wrap.h"
25 #include "librpc/gen_ndr/winreg.h"
26
27 struct ldb_key_data 
28 {
29         const struct ldb_dn *dn;
30         struct ldb_message **subkeys, **values;
31         int subkey_count, value_count;
32 };
33
34 static int ldb_free_hive (void *_hive)
35 {
36         struct registry_hive *hive = _hive;
37         talloc_free(hive->backend_data);
38         return 0;
39 }
40
41 static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32_t *type, DATA_BLOB *data)
42 {
43         const struct ldb_val *val;
44         *name = talloc_strdup(mem_ctx, ldb_msg_find_string(msg, "value", NULL));
45         *type = ldb_msg_find_uint(msg, "type", 0);
46         val = ldb_msg_find_ldb_val(msg, "data");
47
48         switch (*type)
49         {
50         case REG_SZ:
51         case REG_EXPAND_SZ:
52                 data->length = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, (void **)&data->data);
53                 break;
54
55         case REG_DWORD: {
56                 uint32_t tmp = strtoul((char *)val->data, NULL, 0);
57                 *data = data_blob_talloc(mem_ctx, &tmp, 4);
58                 }
59                 break;
60
61         default:
62                 *data = data_blob_talloc(mem_ctx, val->data, val->length);
63                 break;
64         }
65 }
66
67 static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, DATA_BLOB data)
68 {
69         struct ldb_val val;
70         struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
71         char *type_s;
72
73         ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
74
75         switch (type) {
76         case REG_SZ:
77         case REG_EXPAND_SZ:
78                 val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, (void *)data.data, data.length, (void **)&val.data);
79                 ldb_msg_add_value(msg, "data", &val);
80                 break;
81
82         case REG_DWORD:
83                 ldb_msg_add_string(msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data.data, 0)));
84                 break;
85         default:
86                 ldb_msg_add_value(msg, "data", &data);
87         }
88
89
90         type_s = talloc_asprintf(mem_ctx, "%u", type);
91         ldb_msg_add_string(msg, "type", type_s); 
92
93         return msg;
94 }
95
96
97 static int reg_close_ldb_key (void *data)
98 {
99         struct registry_key *key = data;
100         struct ldb_key_data *kd = key->backend_data;
101 /*      struct ldb_context *c = key->hive->backend_data; */
102
103         if (kd->subkeys) {
104                 talloc_free(kd->subkeys); 
105                 kd->subkeys = NULL;
106         }
107
108         if (kd->values) {
109                 talloc_free(kd->values); 
110                 kd->values = NULL;
111         }
112         return 0;
113 }
114
115 static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const struct registry_key *from, const char *path, const char *add)
116 {
117         TALLOC_CTX *local_ctx;
118         struct ldb_dn *ret = ldb_dn_new(mem_ctx);
119         char *mypath = talloc_strdup(mem_ctx, path);
120         char *begin;
121         struct ldb_key_data *kd = from->backend_data;
122
123         local_ctx = talloc_named(mem_ctx, 0, "reg_path_to_ldb context");
124
125         if (add) 
126                 ret = ldb_dn_compose(local_ctx, ret, ldb_dn_explode(mem_ctx, add));
127
128         while(mypath) {
129                 char *keyname;
130
131                 begin = strrchr(mypath, '\\');
132
133                 if (begin) keyname = begin + 1;
134                 else keyname = mypath;
135
136                 if(strlen(keyname)) {
137                         struct ldb_dn *base;
138
139                         base = ldb_dn_build_child(local_ctx, "key", keyname, NULL);
140                         ret = ldb_dn_compose(local_ctx, ret, base);
141                 }
142
143                 if(begin) {
144                         *begin = '\0';
145                 } else {
146                         break;
147                 }
148         }
149
150         ret = ldb_dn_compose(local_ctx, ret, kd->dn);
151
152         return ret;
153 }
154
155
156 static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **subkey)
157 {
158         struct ldb_context *c = k->hive->backend_data;
159         struct ldb_message_element *el;
160         struct ldb_key_data *kd = k->backend_data, *newkd;
161
162         /* Do a search if necessary */
163         if (kd->subkeys == NULL) {
164                 kd->subkey_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &kd->subkeys);
165
166                 if(kd->subkey_count < 0) {
167                         DEBUG(0, ("Error getting subkeys for '%s': %s\n", ldb_dn_linearize(mem_ctx, kd->dn), ldb_errstring(c)));
168                         return WERR_FOOBAR;
169                 }
170         } 
171
172         if (idx >= kd->subkey_count) return WERR_NO_MORE_ITEMS;
173
174         el = ldb_msg_find_element(kd->subkeys[idx], "key");
175         
176         *subkey = talloc(mem_ctx, struct registry_key);
177         talloc_set_destructor(*subkey, reg_close_ldb_key);
178         (*subkey)->name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
179         (*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data);
180         (*subkey)->last_mod = 0; /* TODO: we need to add this to the
181                                     ldb backend properly */
182         newkd->dn = ldb_dn_copy(mem_ctx, kd->subkeys[idx]->dn);
183
184         return WERR_OK;
185 }
186
187 static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value)
188 {
189         struct ldb_context *c = k->hive->backend_data;
190         struct ldb_key_data *kd = k->backend_data;
191
192         /* Do the search if necessary */
193         if (kd->values == NULL) {
194                 kd->value_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&kd->values);
195
196                 if(kd->value_count < 0) {
197                         DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_linearize(mem_ctx, kd->dn), ldb_errstring(c)));
198                         return WERR_FOOBAR;
199                 }
200         }
201
202         if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS;
203
204         *value = talloc(mem_ctx, struct registry_value);
205
206         reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data);
207
208         return WERR_OK;
209 }
210
211 static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
212 {
213         struct ldb_context *c = h->hive->backend_data;
214         struct ldb_message **msg;
215         struct ldb_dn *ldap_path;
216         int ret;
217         struct ldb_key_data *newkd;
218
219         ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
220
221         ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &msg);
222
223         if(ret == 0) {
224                 return WERR_BADFILE;
225         } else if(ret < 0) {
226                 DEBUG(0, ("Error opening key '%s': %s\n", ldb_dn_linearize(ldap_path, ldap_path), ldb_errstring(c)));
227                 return WERR_FOOBAR;
228         }
229
230         *key = talloc(mem_ctx, struct registry_key);
231         talloc_set_destructor(*key, reg_close_ldb_key);
232         (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name);
233         (*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data);
234         newkd->dn = ldb_dn_copy(mem_ctx, msg[0]->dn); 
235
236         talloc_free(msg);
237
238         return WERR_OK;
239 }
240
241 static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k)
242 {
243         struct ldb_key_data *kd;
244         struct ldb_context *wrap;
245
246         if (!hive->location) return WERR_INVALID_PARAM;
247         wrap = ldb_wrap_connect(hive, hive->location, 0, NULL);
248
249         if(!wrap) {
250                 DEBUG(1, ("ldb_open_hive: unable to connect\n"));
251                 return WERR_FOOBAR;
252         }
253
254         ldb_set_debug_stderr(wrap);
255         hive->backend_data = wrap;
256
257         *k = talloc_zero(hive, struct registry_key);
258         talloc_set_destructor (*k, reg_close_ldb_key);
259         talloc_set_destructor (hive, ldb_free_hive);
260         (*k)->name = talloc_strdup(*k, "");
261         (*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data);
262         kd->dn = ldb_dn_explode(*k, "hive=NONE");
263         
264
265         return WERR_OK;
266 }
267
268 static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey)
269 {
270         struct ldb_context *ctx = parent->hive->backend_data;
271         struct ldb_message *msg;
272         struct ldb_key_data *newkd;
273         int ret;
274
275         msg = ldb_msg_new(mem_ctx);
276
277         msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
278
279         ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
280
281         ret = ldb_add(ctx, msg);
282         if (ret < 0) {
283                 DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data)));
284                 return WERR_FOOBAR;
285         }
286
287         *newkey = talloc_zero(mem_ctx, struct registry_key);
288         (*newkey)->name = talloc_strdup(mem_ctx, name);
289
290         (*newkey)->backend_data = newkd = talloc_zero(*newkey, struct ldb_key_data);
291         newkd->dn = talloc_steal(newkd, msg->dn);
292
293         return WERR_OK;
294 }
295
296 static WERROR ldb_del_key (const struct registry_key *key, const char *child)
297 {
298         int ret;
299         struct ldb_key_data *kd = key->backend_data;
300         TALLOC_CTX *local_ctx = talloc_named(NULL, 0, "ldb_del_key mem ctx");
301         struct ldb_dn *childdn = ldb_dn_build_child(local_ctx, "key", child, kd->dn);
302
303         ret = ldb_delete(key->hive->backend_data, childdn);
304
305         talloc_free(local_ctx);
306
307         if (ret < 0) {
308                 DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data)));
309                 return WERR_FOOBAR;
310         }
311
312         return WERR_OK;
313 }
314
315 static WERROR ldb_del_value (const struct registry_key *key, const char *child)
316 {
317         int ret;
318         struct ldb_key_data *kd = key->backend_data;
319         TALLOC_CTX *local_ctx = talloc_named(NULL, 0, "ldb_del_value mem ctx");
320         struct ldb_dn *childdn = ldb_dn_build_child(local_ctx, "value", child, kd->dn);
321
322         ret = ldb_delete(key->hive->backend_data, childdn);
323
324         talloc_free(local_ctx);
325
326         if (ret < 0) {
327                 DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data)));
328                 return WERR_FOOBAR;
329         }
330
331         return WERR_OK;
332 }
333
334 static WERROR ldb_set_value (const struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data)
335 {
336         struct ldb_context *ctx = parent->hive->backend_data;
337         struct ldb_message *msg;
338         struct ldb_key_data *kd = parent->backend_data;
339         int ret;
340         TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
341
342         msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data);
343
344         msg->dn = ldb_dn_build_child(msg, "value", name, kd->dn);
345
346         ret = ldb_add(ctx, msg);
347         if (ret < 0) {
348                 ret = ldb_modify(ctx, msg);
349                 if (ret < 0) {
350                         DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data)));
351                         talloc_free(mem_ctx);
352                         return WERR_FOOBAR;
353                 }
354         }
355         
356         talloc_free(mem_ctx);
357         return WERR_OK;
358 }
359
360 static struct hive_operations reg_backend_ldb = {
361         .name = "ldb",
362         .add_key = ldb_add_key,
363         .del_key = ldb_del_key,
364         .open_hive = ldb_open_hive,
365         .open_key = ldb_open_key,
366         .get_value_by_index = ldb_get_value_by_id,
367         .get_subkey_by_index = ldb_get_subkey_by_id,
368         .set_value = ldb_set_value,
369         .del_value = ldb_del_value,
370 };
371
372 NTSTATUS registry_ldb_init(void)
373 {
374         return registry_register(&reg_backend_ldb);
375 }