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