r10641: fixed the error handling on search errors in the ildap backend
[metze/samba/wip.git] / source / lib / ldb / ldb_ildap / ldb_ildap.c
1 /* 
2    ldb database library - ildap backend
3
4    Copyright (C) Andrew Tridgell  2005
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26   This is a ldb backend for the internal ldap client library in
27   Samba4. By using this backend we are independent of a system ldap
28   library
29 */
30
31
32 #include "includes.h"
33 #include "ldb/include/ldb.h"
34 #include "ldb/include/ldb_private.h"
35 #include "libcli/ldap/ldap.h"
36 #include "libcli/ldap/ldap_client.h"
37 #include "lib/cmdline/popt_common.h"
38
39 struct ildb_private {
40         struct ldap_connection *ldap;
41         NTSTATUS last_rc;
42         struct ldb_message *rootDSE;
43 };
44
45 /*
46   rename a record
47 */
48 static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
49 {
50         TALLOC_CTX *local_ctx;
51         struct ildb_private *ildb = module->private_data;
52         int ret = 0;
53         char *old_dn;
54         char *newrdn, *parentdn;
55
56         /* ignore ltdb specials */
57         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
58                 return 0;
59         }
60
61         local_ctx = talloc_named(ildb, 0, "ildb_rename local context");
62         if (local_ctx == NULL) {
63                 return -1;
64         }
65
66         old_dn = ldb_dn_linearize(local_ctx, olddn);
67         if (old_dn == NULL) {
68                 goto failed;
69         }
70
71         newrdn = talloc_asprintf(local_ctx, "%s=%s",
72                                             newdn->components[0].name,
73                                             ldb_dn_escape_value(ildb, newdn->components[0].value));
74         if (newrdn == NULL) {
75                 goto failed;
76         }
77
78         parentdn = ldb_dn_linearize(local_ctx, ldb_dn_get_parent(ildb, newdn));
79         if (parentdn == NULL) {
80                 goto failed;
81         }
82
83         ildb->last_rc = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True);
84         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
85                 ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc)));
86                 ret = -1;
87         }
88
89         talloc_free(local_ctx);
90         return ret;
91
92 failed:
93         talloc_free(local_ctx);
94         return -1;
95 }
96
97 /*
98   delete a record
99 */
100 static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn)
101 {
102         struct ildb_private *ildb = module->private_data;
103         char *del_dn;
104         int ret = 0;
105
106         /* ignore ltdb specials */
107         if (ldb_dn_is_special(dn)) {
108                 return 0;
109         }
110         
111         del_dn = ldb_dn_linearize(ildb, dn);
112
113         ildb->last_rc = ildap_delete(ildb->ldap, del_dn);
114         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
115                 ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc)));
116                 ret = -1;
117         }
118
119         talloc_free(del_dn);
120
121         return ret;
122 }
123
124
125 static void ildb_rootdse(struct ldb_module *module);
126
127 /*
128   search for matching records
129 */
130 static int ildb_search(struct ldb_module *module, const struct ldb_dn *base,
131                        enum ldb_scope scope, const char *expression,
132                        const char * const *attrs, struct ldb_message ***res)
133 {
134         struct ildb_private *ildb = module->private_data;
135         int count, i;
136         struct ldap_message **ldapres, *msg;
137         char *search_base;
138
139         if (scope == LDB_SCOPE_DEFAULT) {
140                 scope = LDB_SCOPE_SUBTREE;
141         }
142         
143         if (base == NULL) {
144                 if (ildb->rootDSE == NULL) {
145                         ildb_rootdse(module);
146                 }
147                 if (ildb->rootDSE != NULL) {
148                         search_base = talloc_strdup(ildb,
149                                                 ldb_msg_find_string(ildb->rootDSE, 
150                                                                 "defaultNamingContext", ""));
151                 } else {
152                         search_base = talloc_strdup(ildb, "");
153                 }
154         } else {
155                 search_base = ldb_dn_linearize(ildb, base);
156         }
157         if (search_base == NULL) {
158                 return -1;
159         }
160
161         if (expression == NULL || expression[0] == '\0') {
162                 expression = "objectClass=*";
163         }
164
165         ildb->last_rc = ildap_search(ildb->ldap, search_base, scope, expression, attrs, 
166                                      0, &ldapres);
167         talloc_free(search_base);
168         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
169                 ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc)));
170                 return -1;
171         }
172
173         count = ildap_count_entries(ildb->ldap, ldapres);
174         if (count == -1 || count == 0) {
175                 talloc_free(ldapres);
176                 return count;
177         }
178
179         (*res) = talloc_array(ildb, struct ldb_message *, count+1);
180         if (! *res) {
181                 talloc_free(ldapres);
182                 return -1;
183         }
184
185         (*res)[0] = NULL;
186
187         /* loop over all messages */
188         for (i=0;i<count;i++) {
189                 struct ldap_SearchResEntry *search;
190
191                 msg = ldapres[i];
192                 search = &msg->r.SearchResultEntry;
193
194                 (*res)[i] = talloc(*res, struct ldb_message);
195                 if (!(*res)[i]) {
196                         goto failed;
197                 }
198                 (*res)[i+1] = NULL;
199
200                 (*res)[i]->dn = ldb_dn_explode((*res)[i], search->dn);
201                 if ((*res)[i]->dn == NULL) {
202                         goto failed;
203                 }
204                 (*res)[i]->num_elements = search->num_attributes;
205                 (*res)[i]->elements = talloc_steal((*res)[i], search->attributes);
206                 (*res)[i]->private_data = NULL;
207         }
208
209         talloc_free(ldapres);
210
211         return count;
212
213 failed:
214         if (*res) talloc_free(*res);
215         return -1;
216 }
217
218
219 /*
220   search for matching records using a ldb_parse_tree
221 */
222 static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
223                               enum ldb_scope scope, struct ldb_parse_tree *tree,
224                               const char * const *attrs, struct ldb_message ***res)
225 {
226         struct ildb_private *ildb = module->private_data;
227         char *expression;
228         int ret;
229
230         expression = ldb_filter_from_tree(ildb, tree);
231         if (expression == NULL) {
232                 return -1;
233         }
234         ret = ildb_search(module, base, scope, expression, attrs, res);
235         talloc_free(expression);
236         return ret;
237 }
238
239
240 /*
241   convert a ldb_message structure to a list of ldap_mod structures
242   ready for ildap_add() or ildap_modify()
243 */
244 static struct ldap_mod **ildb_msg_to_mods(struct ldb_context *ldb,
245                                           const struct ldb_message *msg, int use_flags)
246 {
247         struct ldap_mod **mods;
248         unsigned int i;
249         int num_mods = 0;
250
251         /* allocate maximum number of elements needed */
252         mods = talloc_array(ldb, struct ldap_mod *, msg->num_elements+1);
253         if (!mods) {
254                 errno = ENOMEM;
255                 return NULL;
256         }
257         mods[0] = NULL;
258
259         for (i=0;i<msg->num_elements;i++) {
260                 const struct ldb_message_element *el = &msg->elements[i];
261
262                 mods[num_mods] = talloc(ldb, struct ldap_mod);
263                 if (!mods[num_mods]) {
264                         goto failed;
265                 }
266                 mods[num_mods+1] = NULL;
267                 mods[num_mods]->type = 0;
268                 mods[num_mods]->attrib = *el;
269                 if (use_flags) {
270                         switch (el->flags & LDB_FLAG_MOD_MASK) {
271                         case LDB_FLAG_MOD_ADD:
272                                 mods[num_mods]->type = LDAP_MODIFY_ADD;
273                                 break;
274                         case LDB_FLAG_MOD_DELETE:
275                                 mods[num_mods]->type = LDAP_MODIFY_DELETE;
276                                 break;
277                         case LDB_FLAG_MOD_REPLACE:
278                                 mods[num_mods]->type = LDAP_MODIFY_REPLACE;
279                                 break;
280                         }
281                 }
282                 num_mods++;
283         }
284
285         return mods;
286
287 failed:
288         talloc_free(mods);
289         return NULL;
290 }
291
292
293 /*
294   add a record
295 */
296 static int ildb_add(struct ldb_module *module, const struct ldb_message *msg)
297 {
298         struct ldb_context *ldb = module->ldb;
299         struct ildb_private *ildb = module->private_data;
300         struct ldap_mod **mods;
301         char *dn;
302         int ret = 0;
303
304         /* ignore ltdb specials */
305         if (ldb_dn_is_special(msg->dn)) {
306                 return 0;
307         }
308
309         mods = ildb_msg_to_mods(ldb, msg, 0);
310         if (mods == NULL) {
311                 return -1;
312         }
313
314         dn = ldb_dn_linearize(mods, msg->dn);
315         if (dn == NULL) {
316                 talloc_free(mods);
317                 return -1;
318         }
319
320         ildb->last_rc = ildap_add(ildb->ldap, dn, mods);
321         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
322                 ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc)));
323                 ret = -1;
324         }
325
326         talloc_free(mods);
327
328         return ret;
329 }
330
331
332 /*
333   modify a record
334 */
335 static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg)
336 {
337         struct ldb_context *ldb = module->ldb;
338         struct ildb_private *ildb = module->private_data;
339         struct ldap_mod **mods;
340         char *dn;
341         int ret = 0;
342
343         /* ignore ltdb specials */
344         if (ldb_dn_is_special(msg->dn)) {
345                 return 0;
346         }
347
348         mods = ildb_msg_to_mods(ldb, msg, 1);
349         if (mods == NULL) {
350                 return -1;
351         }
352
353         dn = ldb_dn_linearize(mods, msg->dn);
354         if (dn == NULL) {
355                 talloc_free(mods);
356                 return -1;
357         }
358
359         ildb->last_rc = ildap_modify(ildb->ldap, dn, mods);
360         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
361                 ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc)));
362                 ret = -1;
363         }
364
365         talloc_free(mods);
366
367         return ret;
368 }
369
370 static int ildb_start_trans(struct ldb_module *module)
371 {
372         /* TODO implement a local locking mechanism here */
373
374         return 0;
375 }
376
377 static int ildb_end_trans(struct ldb_module *module)
378 {
379         /* TODO implement a local transaction mechanism here */
380
381         return 0;
382 }
383
384 static int ildb_del_trans(struct ldb_module *module)
385 {
386         /* TODO implement a local locking mechanism here */
387
388         return 0;
389 }
390
391 static const struct ldb_module_ops ildb_ops = {
392         .name              = "ldap",
393         .search            = ildb_search,
394         .search_bytree     = ildb_search_bytree,
395         .add_record        = ildb_add,
396         .modify_record     = ildb_modify,
397         .delete_record     = ildb_delete,
398         .rename_record     = ildb_rename,
399         .start_transaction = ildb_start_trans,
400         .end_transaction   = ildb_end_trans,
401         .del_transaction   = ildb_del_trans
402 };
403
404
405 /*
406   fetch the rootDSE
407 */
408 static void ildb_rootdse(struct ldb_module *module)
409 {
410         struct ildb_private *ildb = module->private_data;
411         struct ldb_message **res = NULL;
412         struct ldb_dn *empty_dn = ldb_dn_new(ildb);
413         int ret;
414         ret = ildb_search(module, empty_dn, LDB_SCOPE_BASE, "dn=dc=rootDSE", NULL, &res);
415         if (ret == 1) {
416                 ildb->rootDSE = talloc_steal(ildb, res[0]);
417         }
418         if (ret != -1) talloc_free(res);
419         talloc_free(empty_dn);
420 }
421
422
423 /*
424   connect to the database
425 */
426 int ildb_connect(struct ldb_context *ldb, const char *url, 
427                  unsigned int flags, const char *options[])
428 {
429         struct ildb_private *ildb = NULL;
430         NTSTATUS status;
431
432         ildb = talloc(ldb, struct ildb_private);
433         if (!ildb) {
434                 ldb_oom(ldb);
435                 goto failed;
436         }
437
438         ildb->rootDSE = NULL;
439
440         ildb->ldap = ldap_new_connection(ildb, ldb_get_opaque(ldb, "EventContext"));
441         if (!ildb->ldap) {
442                 ldb_oom(ldb);
443                 goto failed;
444         }
445
446         status = ldap_connect(ildb->ldap, url);
447         if (!NT_STATUS_IS_OK(status)) {
448                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s\n",
449                           url, ldap_errstr(ildb->ldap, status));
450                 goto failed;
451         }
452
453         ldb->modules = talloc(ldb, struct ldb_module);
454         if (!ldb->modules) {
455                 ldb_oom(ldb);
456                 goto failed;
457         }
458         ldb->modules->ldb = ldb;
459         ldb->modules->prev = ldb->modules->next = NULL;
460         ldb->modules->private_data = ildb;
461         ldb->modules->ops = &ildb_ops;
462
463         if (cmdline_credentials != NULL && cli_credentials_authentication_requested(cmdline_credentials)) {
464                 status = ldap_bind_sasl(ildb->ldap, cmdline_credentials);
465                 if (!NT_STATUS_IS_OK(status)) {
466                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
467                                   ldap_errstr(ildb->ldap, status));
468                         goto failed;
469                 }
470         }
471
472         return 0;
473
474 failed:
475         if (ldb->modules) {
476                 ldb->modules->private_data = NULL;
477         }
478         talloc_free(ildb);
479         return -1;
480 }
481