r7602: fix some compiler warnings
[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         if (expression == NULL || expression[0] == '\0') {
200                 expression = "objectClass=*";
201         }
202
203         lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, 
204                                       expression, 
205                                       discard_const_p(char *, attrs), 
206                                       0, &ldapres);
207         if (lldb->last_rc != LDAP_SUCCESS) {
208                 return -1;
209         }
210
211         count = ldap_count_entries(lldb->ldap, ldapres);
212         if (count == -1 || count == 0) {
213                 ldap_msgfree(ldapres);
214                 return count;
215         }
216
217         (*res) = talloc_array(lldb, struct ldb_message *, count+1);
218         if (! *res) {
219                 ldap_msgfree(ldapres);
220                 errno = ENOMEM;
221                 return -1;
222         }
223
224         (*res)[0] = NULL;
225
226         msg_count = 0;
227
228         /* loop over all messages */
229         for (msg=ldap_first_entry(lldb->ldap, ldapres); 
230              msg; 
231              msg=ldap_next_entry(lldb->ldap, msg)) {
232                 BerElement *berptr = NULL;
233                 char *attr, *dn;
234
235                 if (msg_count == count) {
236                         /* hmm, got too many? */
237                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
238                         break;
239                 }
240
241                 (*res)[msg_count] = talloc(*res, struct ldb_message);
242                 if (!(*res)[msg_count]) {
243                         goto failed;
244                 }
245                 (*res)[msg_count+1] = NULL;
246
247                 dn = ldap_get_dn(lldb->ldap, msg);
248                 if (!dn) {
249                         goto failed;
250                 }
251
252                 (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
253                 ldap_memfree(dn);
254                 if (!(*res)[msg_count]->dn) {
255                         goto failed;
256                 }
257
258
259                 (*res)[msg_count]->num_elements = 0;
260                 (*res)[msg_count]->elements = NULL;
261                 (*res)[msg_count]->private_data = NULL;
262
263                 /* loop over all attributes */
264                 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
265                      attr;
266                      attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
267                         struct berval **bval;
268                         bval = ldap_get_values_len(lldb->ldap, msg, attr);
269
270                         if (bval) {
271                                 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
272                                 ldap_value_free_len(bval);
273                         }                                         
274                         
275                         ldap_memfree(attr);
276                 }
277                 if (berptr) ber_free(berptr, 0);
278
279                 msg_count++;
280         }
281
282         ldap_msgfree(ldapres);
283
284         return msg_count;
285
286 failed:
287         if (*res) talloc_free(*res);
288         return -1;
289 }
290
291
292 /*
293   search for matching records using a ldb_parse_tree
294 */
295 static int lldb_search_bytree(struct ldb_module *module, const char *base,
296                               enum ldb_scope scope, struct ldb_parse_tree *tree,
297                               const char * const *attrs, struct ldb_message ***res)
298 {
299         struct lldb_private *lldb = module->private_data;
300         char *expression;
301         int ret;
302
303         expression = ldb_filter_from_tree(lldb, tree);
304         if (expression == NULL) {
305                 return -1;
306         }
307         ret = lldb_search(module, base, scope, expression, attrs, res);
308         talloc_free(expression);
309         return ret;
310 }
311
312
313 /*
314   convert a ldb_message structure to a list of LDAPMod structures
315   ready for ldap_add() or ldap_modify()
316 */
317 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
318                                   const struct ldb_message *msg, int use_flags)
319 {
320         LDAPMod **mods;
321         unsigned int i, j;
322         int num_mods = 0;
323
324         /* allocate maximum number of elements needed */
325         mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
326         if (!mods) {
327                 errno = ENOMEM;
328                 return NULL;
329         }
330         mods[0] = NULL;
331
332         for (i=0;i<msg->num_elements;i++) {
333                 const struct ldb_message_element *el = &msg->elements[i];
334
335                 mods[num_mods] = talloc(ldb, LDAPMod);
336                 if (!mods[num_mods]) {
337                         goto failed;
338                 }
339                 mods[num_mods+1] = NULL;
340                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
341                 if (use_flags) {
342                         switch (el->flags & LDB_FLAG_MOD_MASK) {
343                         case LDB_FLAG_MOD_ADD:
344                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
345                                 break;
346                         case LDB_FLAG_MOD_DELETE:
347                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
348                                 break;
349                         case LDB_FLAG_MOD_REPLACE:
350                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
351                                 break;
352                         }
353                 }
354                 mods[num_mods]->mod_type = discard_const_p(char, el->name);
355                 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], 
356                                                                      struct berval *,
357                                                                      1+el->num_values);
358                 if (!mods[num_mods]->mod_vals.modv_bvals) {
359                         goto failed;
360                 }
361
362                 for (j=0;j<el->num_values;j++) {
363                         mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
364                                                                           struct berval);
365                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
366                                 goto failed;
367                         }
368                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
369                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
370                 }
371                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
372                 num_mods++;
373         }
374
375         return mods;
376
377 failed:
378         talloc_free(mods);
379         return NULL;
380 }
381
382
383 /*
384   add a record
385 */
386 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
387 {
388         struct ldb_context *ldb = module->ldb;
389         struct lldb_private *lldb = module->private_data;
390         LDAPMod **mods;
391         int ret = 0;
392
393         /* ignore ltdb specials */
394         if (msg->dn[0] == '@') {
395                 return 0;
396         }
397
398         mods = lldb_msg_to_mods(ldb, msg, 0);
399
400         lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
401         if (lldb->last_rc != LDAP_SUCCESS) {
402                 ret = -1;
403         }
404
405         talloc_free(mods);
406
407         return ret;
408 }
409
410
411 /*
412   modify a record
413 */
414 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
415 {
416         struct ldb_context *ldb = module->ldb;
417         struct lldb_private *lldb = module->private_data;
418         LDAPMod **mods;
419         int ret = 0;
420
421         /* ignore ltdb specials */
422         if (msg->dn[0] == '@') {
423                 return 0;
424         }
425
426         mods = lldb_msg_to_mods(ldb, msg, 1);
427
428         lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
429         if (lldb->last_rc != LDAP_SUCCESS) {
430                 ret = -1;
431         }
432
433         talloc_free(mods);
434
435         return ret;
436 }
437
438 static int lldb_lock(struct ldb_module *module, const char *lockname)
439 {
440         int ret = 0;
441
442         if (lockname == NULL) {
443                 return -1;
444         }
445
446         /* TODO implement a local locking mechanism here */
447
448         return ret;
449 }
450
451 static int lldb_unlock(struct ldb_module *module, const char *lockname)
452 {
453         int ret = 0;
454
455         if (lockname == NULL) {
456                 return -1;
457         }
458
459         /* TODO implement a local unlocking mechanism here */
460
461         return ret;
462 }
463
464 /*
465   return extended error information
466 */
467 static const char *lldb_errstring(struct ldb_module *module)
468 {
469         struct lldb_private *lldb = module->private_data;
470         return ldap_err2string(lldb->last_rc);
471 }
472
473
474 static const struct ldb_module_ops lldb_ops = {
475         .name          = "ldap",
476         .search        = lldb_search,
477         .search_bytree = lldb_search_bytree,
478         .add_record    = lldb_add,
479         .modify_record = lldb_modify,
480         .delete_record = lldb_delete,
481         .rename_record = lldb_rename,
482         .named_lock    = lldb_lock,
483         .named_unlock  = lldb_unlock,
484         .errstring     = lldb_errstring
485 };
486
487
488 static int lldb_destructor(void *p)
489 {
490         struct lldb_private *lldb = p;
491         ldap_unbind(lldb->ldap);
492         return 0;
493 }
494
495 /*
496   connect to the database
497 */
498 struct ldb_context *lldb_connect(const char *url, 
499                                  unsigned int flags, 
500                                  const char *options[])
501 {
502         struct ldb_context *ldb = NULL;
503         struct lldb_private *lldb = NULL;
504         int i, version = 3;
505
506         ldb = talloc(NULL, struct ldb_context);
507         if (!ldb) {
508                 errno = ENOMEM;
509                 goto failed;
510         }
511
512         ldb->debug_ops.debug = NULL;
513
514         lldb = talloc(ldb, struct lldb_private);
515         if (!lldb) {
516                 errno = ENOMEM;
517                 goto failed;
518         }
519
520         lldb->ldap = NULL;
521         lldb->options = NULL;
522
523         lldb->last_rc = ldap_initialize(&lldb->ldap, url);
524         if (lldb->last_rc != LDAP_SUCCESS) {
525                 goto failed;
526         }
527
528         talloc_set_destructor(lldb, lldb_destructor);
529
530         lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
531         if (lldb->last_rc != LDAP_SUCCESS) {
532                 goto failed;
533         }
534
535         ldb->modules = talloc(ldb, struct ldb_module);
536         if (!ldb->modules) {
537                 errno = ENOMEM;
538                 goto failed;
539         }
540         ldb->modules->ldb = ldb;
541         ldb->modules->prev = ldb->modules->next = NULL;
542         ldb->modules->private_data = lldb;
543         ldb->modules->ops = &lldb_ops;
544
545         if (options) {
546                 /* take a copy of the options array, so we don't have to rely
547                    on the caller keeping it around (it might be dynamic) */
548                 for (i=0;options[i];i++) ;
549
550                 lldb->options = talloc_array(lldb, char *, i+1);
551                 if (!lldb->options) {
552                         goto failed;
553                 }
554                 
555                 for (i=0;options[i];i++) {
556                         lldb->options[i+1] = NULL;
557                         lldb->options[i] = talloc_strdup(lldb->options, options[i]);
558                         if (!lldb->options[i]) {
559                                 goto failed;
560                         }
561                 }
562         }
563
564         return ldb;
565
566 failed:
567         talloc_free(ldb);
568         return NULL;
569 }
570