268e2b0291fe70545bf86dc06c8ec80e2c06f727
[kai/samba-autobuild/.git] / source4 / lib / ldb / ldb_ldap / ldb_ldap.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
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  *  Name: ldb
27  *
28  *  Component: ldb ldap backend
29  *
30  *  Description: core files for LDAP backend
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_ldap/ldb_ldap.h"
39
40 /*
41   rename a record
42 */
43 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
44 {
45         TALLOC_CTX *local_ctx;
46         struct lldb_private *lldb = module->private_data;
47         int ret = 0;
48         char *old_dn;
49         char *newrdn;
50         const char *parentdn = "";
51
52         /* ignore ltdb specials */
53         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
54                 return 0;
55         }
56
57         local_ctx = talloc_named(lldb, 0, "lldb_rename local context");
58         if (local_ctx == NULL) {
59                 return -1;
60         }
61
62         old_dn = ldb_dn_linearize(local_ctx, olddn);
63         if (old_dn == NULL) {
64                 goto failed;
65         }
66
67         newrdn = talloc_asprintf(lldb, "%s=%s",
68                                       newdn->components[0].name,
69                                       ldb_dn_escape_value(lldb, newdn->components[0].value));
70         if (!newrdn) {
71                 goto failed;
72         }
73
74         parentdn = ldb_dn_linearize(lldb, ldb_dn_get_parent(lldb, newdn));
75         if (!parentdn) {
76                 goto failed;
77         }
78
79         lldb->last_rc = ldap_rename_s(lldb->ldap, old_dn, newrdn, parentdn, 1, NULL, NULL);
80         if (lldb->last_rc != LDAP_SUCCESS) {
81                 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
82                 ret = -1;
83         }
84
85         talloc_free(local_ctx);
86         return ret;
87
88 failed:
89         talloc_free(local_ctx);
90         return -1;
91 }
92
93 /*
94   delete a record
95 */
96 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *edn)
97 {
98         struct lldb_private *lldb = module->private_data;
99         char *dn;
100         int ret = 0;
101
102         /* ignore ltdb specials */
103         if (ldb_dn_is_special(edn)) {
104                 return 0;
105         }
106
107         dn = ldb_dn_linearize(lldb, edn);
108
109         lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
110         if (lldb->last_rc != LDAP_SUCCESS) {
111                 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
112                 ret = -1;
113         }
114
115         talloc_free(dn);
116         return ret;
117 }
118
119 /*
120   add a single set of ldap message values to a ldb_message
121 */
122 static int lldb_add_msg_attr(struct ldb_context *ldb,
123                              struct ldb_message *msg, 
124                              const char *attr, struct berval **bval)
125 {
126         int count, i;
127         struct ldb_message_element *el;
128
129         count = ldap_count_values_len(bval);
130
131         if (count <= 0) {
132                 return -1;
133         }
134
135         el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
136                               msg->num_elements + 1);
137         if (!el) {
138                 errno = ENOMEM;
139                 return -1;
140         }
141
142         msg->elements = el;
143
144         el = &msg->elements[msg->num_elements];
145
146         el->name = talloc_strdup(msg->elements, attr);
147         if (!el->name) {
148                 errno = ENOMEM;
149                 return -1;
150         }
151         el->flags = 0;
152
153         el->num_values = 0;
154         el->values = talloc_array(msg->elements, struct ldb_val, count);
155         if (!el->values) {
156                 errno = ENOMEM;
157                 return -1;
158         }
159
160         for (i=0;i<count;i++) {
161                 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
162                 if (!el->values[i].data) {
163                         return -1;
164                 }
165                 el->values[i].length = bval[i]->bv_len;
166                 el->num_values++;
167         }
168
169         msg->num_elements++;
170
171         return 0;
172 }
173
174 /*
175   search for matching records
176 */
177 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
178                               enum ldb_scope scope, struct ldb_parse_tree *tree,
179                               const char * const *attrs, struct ldb_message ***res)
180 {
181         struct ldb_context *ldb = module->ldb;
182         struct lldb_private *lldb = module->private_data;
183         int count, msg_count, ldap_scope;
184         char *search_base;
185         LDAPMessage *ldapres, *msg;
186         char *expression;
187
188         search_base = ldb_dn_linearize(ldb, base);
189         if (base == NULL) {
190                 search_base = talloc_strdup(ldb, "");
191         }
192         if (search_base == NULL) {
193                 return -1;
194         }
195
196         expression = ldb_filter_from_tree(search_base, tree);
197         if (expression == NULL) {
198                 talloc_free(search_base);
199                 return -1;
200         }
201
202         switch (scope) {
203         case LDB_SCOPE_BASE:
204                 ldap_scope = LDAP_SCOPE_BASE;
205                 break;
206         case LDB_SCOPE_ONELEVEL:
207                 ldap_scope = LDAP_SCOPE_ONELEVEL;
208                 break;
209         default:
210                 ldap_scope = LDAP_SCOPE_SUBTREE;
211                 break;
212         }
213
214         lldb->last_rc = ldap_search_s(lldb->ldap, search_base, ldap_scope, 
215                                       expression, 
216                                       discard_const_p(char *, attrs), 
217                                       0, &ldapres);
218         talloc_free(search_base);
219         if (lldb->last_rc != LDAP_SUCCESS) {
220                 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
221                 return -1;
222         }
223
224         count = ldap_count_entries(lldb->ldap, ldapres);
225         if (count == -1 || count == 0) {
226                 ldap_msgfree(ldapres);
227                 return count;
228         }
229
230         (*res) = talloc_array(lldb, struct ldb_message *, count+1);
231         if (! *res) {
232                 ldap_msgfree(ldapres);
233                 errno = ENOMEM;
234                 return -1;
235         }
236
237         (*res)[0] = NULL;
238
239         msg_count = 0;
240
241         /* loop over all messages */
242         for (msg=ldap_first_entry(lldb->ldap, ldapres); 
243              msg; 
244              msg=ldap_next_entry(lldb->ldap, msg)) {
245                 BerElement *berptr = NULL;
246                 char *attr, *dn;
247
248                 if (msg_count == count) {
249                         /* hmm, got too many? */
250                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
251                         break;
252                 }
253
254                 (*res)[msg_count] = talloc(*res, struct ldb_message);
255                 if (!(*res)[msg_count]) {
256                         goto failed;
257                 }
258                 (*res)[msg_count+1] = NULL;
259
260                 dn = ldap_get_dn(lldb->ldap, msg);
261                 if (!dn) {
262                         goto failed;
263                 }
264
265                 (*res)[msg_count]->dn = ldb_dn_explode((*res)[msg_count], dn);
266                 ldap_memfree(dn);
267                 if (!(*res)[msg_count]->dn) {
268                         goto failed;
269                 }
270
271
272                 (*res)[msg_count]->num_elements = 0;
273                 (*res)[msg_count]->elements = NULL;
274                 (*res)[msg_count]->private_data = NULL;
275
276                 /* loop over all attributes */
277                 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
278                      attr;
279                      attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
280                         struct berval **bval;
281                         bval = ldap_get_values_len(lldb->ldap, msg, attr);
282
283                         if (bval) {
284                                 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
285                                 ldap_value_free_len(bval);
286                         }                                         
287                         
288                         ldap_memfree(attr);
289                 }
290                 if (berptr) ber_free(berptr, 0);
291
292                 msg_count++;
293         }
294
295         ldap_msgfree(ldapres);
296
297         return msg_count;
298
299 failed:
300         if (*res) talloc_free(*res);
301         return -1;
302 }
303
304
305 /*
306   convert a ldb_message structure to a list of LDAPMod structures
307   ready for ldap_add() or ldap_modify()
308 */
309 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
310                                   const struct ldb_message *msg, int use_flags)
311 {
312         LDAPMod **mods;
313         unsigned int i, j;
314         int num_mods = 0;
315
316         /* allocate maximum number of elements needed */
317         mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
318         if (!mods) {
319                 errno = ENOMEM;
320                 return NULL;
321         }
322         mods[0] = NULL;
323
324         for (i=0;i<msg->num_elements;i++) {
325                 const struct ldb_message_element *el = &msg->elements[i];
326
327                 mods[num_mods] = talloc(ldb, LDAPMod);
328                 if (!mods[num_mods]) {
329                         goto failed;
330                 }
331                 mods[num_mods+1] = NULL;
332                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
333                 if (use_flags) {
334                         switch (el->flags & LDB_FLAG_MOD_MASK) {
335                         case LDB_FLAG_MOD_ADD:
336                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
337                                 break;
338                         case LDB_FLAG_MOD_DELETE:
339                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
340                                 break;
341                         case LDB_FLAG_MOD_REPLACE:
342                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
343                                 break;
344                         }
345                 }
346                 mods[num_mods]->mod_type = discard_const_p(char, el->name);
347                 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], 
348                                                                      struct berval *,
349                                                                      1+el->num_values);
350                 if (!mods[num_mods]->mod_vals.modv_bvals) {
351                         goto failed;
352                 }
353
354                 for (j=0;j<el->num_values;j++) {
355                         mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
356                                                                           struct berval);
357                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
358                                 goto failed;
359                         }
360                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
361                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
362                 }
363                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
364                 num_mods++;
365         }
366
367         return mods;
368
369 failed:
370         talloc_free(mods);
371         return NULL;
372 }
373
374
375 /*
376   add a record
377 */
378 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
379 {
380         struct ldb_context *ldb = module->ldb;
381         struct lldb_private *lldb = module->private_data;
382         LDAPMod **mods;
383         char *dn;
384         int ret = 0;
385
386         /* ignore ltdb specials */
387         if (ldb_dn_is_special(msg->dn)) {
388                 return 0;
389         }
390
391         mods = lldb_msg_to_mods(ldb, msg, 0);
392         if (mods == NULL) {
393                 return -1;
394         }
395
396         dn = ldb_dn_linearize(mods, msg->dn);
397         if (dn == NULL) {
398                 talloc_free(mods);
399                 return -1;
400         }
401
402         lldb->last_rc = ldap_add_s(lldb->ldap, dn, mods);
403         if (lldb->last_rc != LDAP_SUCCESS) {
404                 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
405                 ret = -1;
406         }
407
408         talloc_free(mods);
409
410         return ret;
411 }
412
413
414 /*
415   modify a record
416 */
417 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
418 {
419         struct ldb_context *ldb = module->ldb;
420         struct lldb_private *lldb = module->private_data;
421         LDAPMod **mods;
422         char *dn;
423         int ret = 0;
424
425         /* ignore ltdb specials */
426         if (ldb_dn_is_special(msg->dn)) {
427                 return 0;
428         }
429
430         mods = lldb_msg_to_mods(ldb, msg, 1);
431         if (mods == NULL) {
432                 return -1;
433         }
434
435         dn = ldb_dn_linearize(mods, msg->dn);
436         if (dn == NULL) {
437                 talloc_free(mods);
438                 return -1;
439         }
440
441         lldb->last_rc = ldap_modify_s(lldb->ldap, dn, mods);
442         if (lldb->last_rc != LDAP_SUCCESS) {
443                 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
444                 ret = -1;
445         }
446
447         talloc_free(mods);
448
449         return ret;
450 }
451
452 static int lldb_start_trans(struct ldb_module *module)
453 {
454         /* TODO implement a local transaction mechanism here */
455
456         return 0;
457 }
458
459 static int lldb_end_trans(struct ldb_module *module)
460 {
461         /* TODO implement a local transaction mechanism here */
462
463         return 0;
464 }
465
466 static int lldb_del_trans(struct ldb_module *module)
467 {
468         /* TODO implement a local transaction mechanism here */
469
470         return 0;
471 }
472
473 static const struct ldb_module_ops lldb_ops = {
474         .name              = "ldap",
475         .search_bytree     = lldb_search_bytree,
476         .add_record        = lldb_add,
477         .modify_record     = lldb_modify,
478         .delete_record     = lldb_delete,
479         .rename_record     = lldb_rename,
480         .start_transaction = lldb_start_trans,
481         .end_transaction   = lldb_end_trans,
482         .del_transaction   = lldb_del_trans
483 };
484
485
486 static int lldb_destructor(void *p)
487 {
488         struct lldb_private *lldb = p;
489         ldap_unbind(lldb->ldap);
490         return 0;
491 }
492
493 /*
494   connect to the database
495 */
496 int lldb_connect(struct ldb_context *ldb,
497                  const char *url, 
498                  unsigned int flags, 
499                  const char *options[])
500 {
501         struct lldb_private *lldb = NULL;
502         int version = 3;
503
504         lldb = talloc(ldb, struct lldb_private);
505         if (!lldb) {
506                 ldb_oom(ldb);
507                 goto failed;
508         }
509
510         lldb->ldap = NULL;
511         lldb->options = NULL;
512
513         lldb->last_rc = ldap_initialize(&lldb->ldap, url);
514         if (lldb->last_rc != LDAP_SUCCESS) {
515                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
516                           url, ldap_err2string(lldb->last_rc));
517                 goto failed;
518         }
519
520         talloc_set_destructor(lldb, lldb_destructor);
521
522         lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
523         if (lldb->last_rc != LDAP_SUCCESS) {
524                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
525                           ldap_err2string(lldb->last_rc));
526         }
527
528         ldb->modules = talloc(ldb, struct ldb_module);
529         if (!ldb->modules) {
530                 ldb_oom(ldb);
531                 goto failed;
532         }
533         ldb->modules->ldb = ldb;
534         ldb->modules->prev = ldb->modules->next = NULL;
535         ldb->modules->private_data = lldb;
536         ldb->modules->ops = &lldb_ops;
537
538         return 0;
539
540 failed:
541         talloc_free(lldb);
542         return -1;
543 }
544