r3754: merge in ldb modules support from the tmp branch ldbPlugins
[metze/samba/wip.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/ldb_ldap/ldb_ldap.h"
37
38 #if 0
39 /*
40   we don't need this right now, but will once we add some backend 
41   options
42 */
43
44 /*
45   find an option in an option list (a null terminated list of strings)
46
47   this assumes the list is short. If it ever gets long then we really
48   should do this in some smarter way
49  */
50 static const char *lldb_option_find(const struct lldb_private *lldb, const char *name)
51 {
52         int i;
53         size_t len = strlen(name);
54
55         if (!lldb->options) return NULL;
56
57         for (i=0;lldb->options[i];i++) {                
58                 if (strncmp(lldb->options[i], name, len) == 0 &&
59                     lldb->options[i][len] == '=') {
60                         return &lldb->options[i][len+1];
61                 }
62         }
63
64         return NULL;
65 }
66 #endif
67
68 /*
69   close/free the connection
70 */
71 static int lldb_close(struct ldb_module *module)
72 {
73         int i, ret = 0;
74         struct ldb_context *ldb = module->ldb;
75         struct lldb_private *lldb = module->private_data;
76
77         if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
78                 ret = -1;
79         }
80
81         ldb_set_alloc(ldb, NULL, NULL);
82
83         if (lldb->options) {
84                 for (i=0;lldb->options[i];i++) {
85                         ldb_free(ldb, lldb->options[i]);
86                 }
87                 ldb_free(ldb, lldb->options);
88         }
89         ldb_free(ldb, lldb);
90         free(ldb);
91
92         return ret;
93 }
94
95 /*
96   rename a record
97 */
98 static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
99 {
100         struct ldb_context *ldb = module->ldb;
101         struct lldb_private *lldb = module->private_data;
102         int ret = 0;
103         char *newrdn, *p;
104         const char *parentdn = "";
105
106         /* ignore ltdb specials */
107         if (olddn[0] == '@' ||newdn[0] == '@') {
108                 return 0;
109         }
110
111         newrdn = ldb_strdup(ldb, newdn);
112         if (!newrdn) {
113                 return -1;
114         }
115
116         p = strchr(newrdn, ',');
117         if (p) {
118                 *p++ = '\0';
119                 parentdn = p;
120         }
121
122         lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL);
123         ldb_free(ldb, newrdn);
124         if (lldb->last_rc != LDAP_SUCCESS) {
125                 ret = -1;
126         }
127
128         return ret;
129 }
130
131 /*
132   delete a record
133 */
134 static int lldb_delete(struct ldb_module *module, const char *dn)
135 {
136         struct lldb_private *lldb = module->private_data;
137         int ret = 0;
138
139         /* ignore ltdb specials */
140         if (dn[0] == '@') {
141                 return 0;
142         }
143         
144         lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
145         if (lldb->last_rc != LDAP_SUCCESS) {
146                 ret = -1;
147         }
148
149         return ret;
150 }
151
152 /*
153   free a search message
154 */
155 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
156 {
157         unsigned int i, j;
158         ldb_free(ldb, msg->dn);
159         for (i=0;i<msg->num_elements;i++) {
160                 ldb_free(ldb, msg->elements[i].name);
161                 for (j=0;j<msg->elements[i].num_values;j++) {
162                         if (msg->elements[i].values[j].data) {
163                                 ldb_free(ldb, msg->elements[i].values[j].data);
164                         }
165                 }
166                 ldb_free(ldb, msg->elements[i].values);
167         }
168         if (msg->elements) ldb_free(ldb, msg->elements);
169         ldb_free(ldb, msg);
170         return 0;
171 }
172
173 /*
174   free a search result
175 */
176 static int lldb_search_free(struct ldb_module *module, struct ldb_message **res)
177 {
178         struct ldb_context *ldb = module->ldb;
179         int i;
180         for (i=0;res[i];i++) {
181                 if (lldb_msg_free(ldb, res[i]) != 0) {
182                         return -1;
183                 }
184         }
185         ldb_free(ldb, res);
186         return 0;
187 }
188
189
190 /*
191   add a single set of ldap message values to a ldb_message
192 */
193 static int lldb_add_msg_attr(struct ldb_context *ldb,
194                              struct ldb_message *msg, 
195                              const char *attr, struct berval **bval)
196 {
197         int count, i;
198         struct ldb_message_element *el;
199
200         count = ldap_count_values_len(bval);
201
202         if (count <= 0) {
203                 return -1;
204         }
205
206         el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, 
207                            msg->num_elements + 1);
208         if (!el) {
209                 errno = ENOMEM;
210                 return -1;
211         }
212
213         msg->elements = el;
214
215         el = &msg->elements[msg->num_elements];
216
217         el->name = ldb_strdup(ldb, attr);
218         if (!el->name) {
219                 errno = ENOMEM;
220                 return -1;
221         }
222         el->flags = 0;
223
224         el->num_values = 0;
225         el->values = ldb_malloc_array_p(ldb, struct ldb_val, count);
226         if (!el->values) {
227                 errno = ENOMEM;
228                 return -1;
229         }
230
231         for (i=0;i<count;i++) {
232                 el->values[i].data = ldb_malloc(ldb, bval[i]->bv_len);
233                 if (!el->values[i].data) {
234                         return -1;
235                 }
236                 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
237                 el->values[i].length = bval[i]->bv_len;
238                 el->num_values++;
239         }
240
241         msg->num_elements++;
242
243         return 0;
244 }
245
246 /*
247   search for matching records
248 */
249 static int lldb_search(struct ldb_module *module, const char *base,
250                        enum ldb_scope scope, const char *expression,
251                        const char * const *attrs, struct ldb_message ***res)
252 {
253         struct ldb_context *ldb = module->ldb;
254         struct lldb_private *lldb = module->private_data;
255         int count, msg_count;
256         LDAPMessage *ldapres, *msg;
257
258         lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, 
259                                       expression, 
260                                       discard_const_p(char *, attrs), 
261                                       0, &ldapres);
262         if (lldb->last_rc != LDAP_SUCCESS) {
263                 return -1;
264         }
265
266         count = ldap_count_entries(lldb->ldap, ldapres);
267         if (count == -1 || count == 0) {
268                 ldap_msgfree(ldapres);
269                 return count;
270         }
271
272         (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1);
273         if (! *res) {
274                 ldap_msgfree(ldapres);
275                 errno = ENOMEM;
276                 return -1;
277         }
278
279         (*res)[0] = NULL;
280
281         msg_count = 0;
282
283         /* loop over all messages */
284         for (msg=ldap_first_entry(lldb->ldap, ldapres); 
285              msg; 
286              msg=ldap_next_entry(lldb->ldap, msg)) {
287                 BerElement *berptr = NULL;
288                 char *attr, *dn;
289
290                 if (msg_count == count) {
291                         /* hmm, got too many? */
292                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
293                         break;
294                 }
295
296                 (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message);
297                 if (!(*res)[msg_count]) {
298                         goto failed;
299                 }
300                 (*res)[msg_count+1] = NULL;
301
302                 dn = ldap_get_dn(lldb->ldap, msg);
303                 if (!dn) {
304                         goto failed;
305                 }
306
307                 (*res)[msg_count]->dn = ldb_strdup(ldb, dn);
308                 ldap_memfree(dn);
309                 if (!(*res)[msg_count]->dn) {
310                         goto failed;
311                 }
312
313
314                 (*res)[msg_count]->num_elements = 0;
315                 (*res)[msg_count]->elements = NULL;
316                 (*res)[msg_count]->private_data = NULL;
317
318                 /* loop over all attributes */
319                 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
320                      attr;
321                      attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
322                         struct berval **bval;
323                         bval = ldap_get_values_len(lldb->ldap, msg, attr);
324
325                         if (bval) {
326                                 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
327                                 ldap_value_free_len(bval);
328                         }                                         
329                         
330                         ldap_memfree(attr);
331                 }
332                 if (berptr) ber_free(berptr, 0);
333
334                 msg_count++;
335         }
336
337         ldap_msgfree(ldapres);
338
339         return msg_count;
340
341 failed:
342         if (*res) lldb_search_free(module, *res);
343         return -1;
344 }
345
346
347 /*
348   free a set of mods from lldb_msg_to_mods()
349 */
350 static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods)
351 {
352         int i, j;
353
354         if (!mods) return;
355
356         for (i=0;mods[i];i++) {
357                 if (mods[i]->mod_vals.modv_bvals) {
358                         for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
359                                 ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]);
360                         }
361                         ldb_free(ldb, mods[i]->mod_vals.modv_bvals);
362                 }
363                 ldb_free(ldb, mods[i]);
364         }
365         ldb_free(ldb, mods);
366 }
367
368
369 /*
370   convert a ldb_message structure to a list of LDAPMod structures
371   ready for ldap_add() or ldap_modify()
372 */
373 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
374                                   const struct ldb_message *msg, int use_flags)
375 {
376         LDAPMod **mods;
377         unsigned int i, j;
378         int num_mods = 0;
379
380         /* allocate maximum number of elements needed */
381         mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1);
382         if (!mods) {
383                 errno = ENOMEM;
384                 return NULL;
385         }
386         mods[0] = NULL;
387
388         for (i=0;i<msg->num_elements;i++) {
389                 const struct ldb_message_element *el = &msg->elements[i];
390
391                 mods[num_mods] = ldb_malloc_p(ldb, LDAPMod);
392                 if (!mods[num_mods]) {
393                         goto failed;
394                 }
395                 mods[num_mods+1] = NULL;
396                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
397                 if (use_flags) {
398                         switch (el->flags & LDB_FLAG_MOD_MASK) {
399                         case LDB_FLAG_MOD_ADD:
400                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
401                                 break;
402                         case LDB_FLAG_MOD_DELETE:
403                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
404                                 break;
405                         case LDB_FLAG_MOD_REPLACE:
406                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
407                                 break;
408                         }
409                 }
410                 mods[num_mods]->mod_type = el->name;
411                 mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb, 
412                                                                          struct berval *,
413                                                                          1+el->num_values);
414                 if (!mods[num_mods]->mod_vals.modv_bvals) {
415                         goto failed;
416                 }
417
418                 for (j=0;j<el->num_values;j++) {
419                         mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval);
420                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
421                                 goto failed;
422                         }
423                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
424                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
425                 }
426                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
427                 num_mods++;
428         }
429
430         return mods;
431
432 failed:
433         lldb_mods_free(ldb, mods);
434         return NULL;
435 }
436
437
438 /*
439   add a record
440 */
441 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
442 {
443         struct ldb_context *ldb = module->ldb;
444         struct lldb_private *lldb = module->private_data;
445         LDAPMod **mods;
446         int ret = 0;
447
448         /* ignore ltdb specials */
449         if (msg->dn[0] == '@') {
450                 return 0;
451         }
452
453         mods = lldb_msg_to_mods(ldb, msg, 0);
454
455         lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
456         if (lldb->last_rc != LDAP_SUCCESS) {
457                 ret = -1;
458         }
459
460         lldb_mods_free(ldb, mods);
461
462         return ret;
463 }
464
465
466 /*
467   modify a record
468 */
469 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
470 {
471         struct ldb_context *ldb = module->ldb;
472         struct lldb_private *lldb = module->private_data;
473         LDAPMod **mods;
474         int ret = 0;
475
476         /* ignore ltdb specials */
477         if (msg->dn[0] == '@') {
478                 return 0;
479         }
480
481         mods = lldb_msg_to_mods(ldb, msg, 1);
482
483         lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
484         if (lldb->last_rc != LDAP_SUCCESS) {
485                 ret = -1;
486         }
487
488         lldb_mods_free(ldb, mods);
489
490         return ret;
491 }
492
493
494 /*
495   return extended error information
496 */
497 static const char *lldb_errstring(struct ldb_module *module)
498 {
499         struct lldb_private *lldb = module->private_data;
500         return ldap_err2string(lldb->last_rc);
501 }
502
503
504 static const struct ldb_module_ops lldb_ops = {
505         "ldap",
506         lldb_close, 
507         lldb_search,
508         lldb_search_free,
509         lldb_add,
510         lldb_modify,
511         lldb_delete,
512         lldb_rename,
513         lldb_errstring
514 };
515
516
517 /*
518   connect to the database
519 */
520 struct ldb_context *lldb_connect(const char *url, 
521                                  unsigned int flags, 
522                                  const char *options[])
523 {
524         struct ldb_context *ldb = NULL;
525         struct lldb_private *lldb = NULL;
526         int i, version = 3;
527
528         ldb = calloc(1, sizeof(struct ldb_context));
529         if (!ldb) {
530                 errno = ENOMEM;
531                 goto failed;
532         }
533
534         lldb = ldb_malloc_p(ldb, struct lldb_private);
535         if (!lldb) {
536                 ldb_free(ldb, ldb);
537                 errno = ENOMEM;
538                 goto failed;
539         }
540
541         lldb->ldap = NULL;
542         lldb->options = NULL;
543
544         lldb->last_rc = ldap_initialize(&lldb->ldap, url);
545         if (lldb->last_rc != LDAP_SUCCESS) {
546                 goto failed;
547         }
548
549         lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
550         if (lldb->last_rc != LDAP_SUCCESS) {
551                 goto failed;
552         }
553
554         ldb->modules = ldb_malloc_p(ldb, struct ldb_module);
555         if (!ldb->modules) {
556                 ldb_free(ldb, ldb);
557                 errno = ENOMEM;
558                 goto failed;
559         }
560         ldb->modules->ldb = ldb;
561         ldb->modules->prev = ldb->modules->next = NULL;
562         ldb->modules->private_data = lldb;
563         ldb->modules->ops = &lldb_ops;
564
565         if (options) {
566                 /* take a copy of the options array, so we don't have to rely
567                    on the caller keeping it around (it might be dynamic) */
568                 for (i=0;options[i];i++) ;
569
570                 lldb->options = ldb_malloc_array_p(ldb, char *, i+1);
571                 if (!lldb->options) {
572                         goto failed;
573                 }
574                 
575                 for (i=0;options[i];i++) {
576                         lldb->options[i+1] = NULL;
577                         lldb->options[i] = ldb_strdup(ldb, options[i]);
578                         if (!lldb->options[i]) {
579                                 goto failed;
580                         }
581                 }
582         }
583
584         return ldb;
585
586 failed:
587         if (lldb && lldb->options) {
588                 for (i=0;lldb->options[i];i++) {
589                         ldb_free(ldb, lldb->options[i]);
590                 }
591                 ldb_free(ldb, lldb->options);
592         }
593         if (lldb && lldb->ldap) {
594                 ldap_unbind(lldb->ldap);
595         }
596         ldb_free(ldb, lldb);
597         if (ldb) free(ldb);
598         return NULL;
599 }
600