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