4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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
28 * Component: ldb ldap backend
30 * Description: core files for LDAP backend
32 * Author: Andrew Tridgell
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_ldap/ldb_ldap.h"
42 we don't need this right now, but will once we add some backend
47 find an option in an option list (a null terminated list of strings)
49 this assumes the list is short. If it ever gets long then we really
50 should do this in some smarter way
52 static const char *lldb_option_find(const struct lldb_private *lldb, const char *name)
55 size_t len = strlen(name);
57 if (!lldb->options) return NULL;
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];
71 close/free the connection
73 static int lldb_close(struct ldb_module *module)
76 struct ldb_context *ldb = module->ldb;
77 struct lldb_private *lldb = module->private_data;
79 if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
83 ldb_set_alloc(ldb, NULL, NULL);
86 for (i=0;lldb->options[i];i++) {
87 ldb_free(ldb, lldb->options[i]);
89 ldb_free(ldb, lldb->options);
100 static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
102 struct ldb_context *ldb = module->ldb;
103 struct lldb_private *lldb = module->private_data;
106 const char *parentdn = "";
108 /* ignore ltdb specials */
109 if (olddn[0] == '@' ||newdn[0] == '@') {
113 newrdn = ldb_strdup(ldb, newdn);
118 p = strchr(newrdn, ',');
124 lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL);
125 ldb_free(ldb, newrdn);
126 if (lldb->last_rc != LDAP_SUCCESS) {
136 static int lldb_delete(struct ldb_module *module, const char *dn)
138 struct lldb_private *lldb = module->private_data;
141 /* ignore ltdb specials */
146 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
147 if (lldb->last_rc != LDAP_SUCCESS) {
155 free a search message
157 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
160 ldb_free(ldb, msg->dn);
161 for (i=0;i<msg->num_elements;i++) {
162 ldb_free(ldb, msg->elements[i].name);
163 for (j=0;j<msg->elements[i].num_values;j++) {
164 if (msg->elements[i].values[j].data) {
165 ldb_free(ldb, msg->elements[i].values[j].data);
168 ldb_free(ldb, msg->elements[i].values);
170 if (msg->elements) ldb_free(ldb, msg->elements);
178 static int lldb_search_free(struct ldb_module *module, struct ldb_message **res)
180 struct ldb_context *ldb = module->ldb;
182 for (i=0;res[i];i++) {
183 if (lldb_msg_free(ldb, res[i]) != 0) {
193 add a single set of ldap message values to a ldb_message
195 static int lldb_add_msg_attr(struct ldb_context *ldb,
196 struct ldb_message *msg,
197 const char *attr, struct berval **bval)
200 struct ldb_message_element *el;
202 count = ldap_count_values_len(bval);
208 el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element,
209 msg->num_elements + 1);
217 el = &msg->elements[msg->num_elements];
219 el->name = ldb_strdup(ldb, attr);
227 el->values = ldb_malloc_array_p(ldb, struct ldb_val, count);
233 for (i=0;i<count;i++) {
234 el->values[i].data = ldb_malloc(ldb, bval[i]->bv_len);
235 if (!el->values[i].data) {
238 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
239 el->values[i].length = bval[i]->bv_len;
249 search for matching records
251 static int lldb_search(struct ldb_module *module, const char *base,
252 enum ldb_scope scope, const char *expression,
253 const char * const *attrs, struct ldb_message ***res)
255 struct ldb_context *ldb = module->ldb;
256 struct lldb_private *lldb = module->private_data;
257 int count, msg_count;
258 LDAPMessage *ldapres, *msg;
264 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
266 discard_const_p(char *, attrs),
268 if (lldb->last_rc != LDAP_SUCCESS) {
272 count = ldap_count_entries(lldb->ldap, ldapres);
273 if (count == -1 || count == 0) {
274 ldap_msgfree(ldapres);
278 (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1);
280 ldap_msgfree(ldapres);
289 /* loop over all messages */
290 for (msg=ldap_first_entry(lldb->ldap, ldapres);
292 msg=ldap_next_entry(lldb->ldap, msg)) {
293 BerElement *berptr = NULL;
296 if (msg_count == count) {
297 /* hmm, got too many? */
298 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
302 (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message);
303 if (!(*res)[msg_count]) {
306 (*res)[msg_count+1] = NULL;
308 dn = ldap_get_dn(lldb->ldap, msg);
313 (*res)[msg_count]->dn = ldb_strdup(ldb, dn);
315 if (!(*res)[msg_count]->dn) {
320 (*res)[msg_count]->num_elements = 0;
321 (*res)[msg_count]->elements = NULL;
322 (*res)[msg_count]->private_data = NULL;
324 /* loop over all attributes */
325 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
327 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
328 struct berval **bval;
329 bval = ldap_get_values_len(lldb->ldap, msg, attr);
332 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
333 ldap_value_free_len(bval);
338 if (berptr) ber_free(berptr, 0);
343 ldap_msgfree(ldapres);
348 if (*res) lldb_search_free(module, *res);
354 free a set of mods from lldb_msg_to_mods()
356 static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods)
362 for (i=0;mods[i];i++) {
363 if (mods[i]->mod_vals.modv_bvals) {
364 for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
365 ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]);
367 ldb_free(ldb, mods[i]->mod_vals.modv_bvals);
369 ldb_free(ldb, mods[i]);
376 convert a ldb_message structure to a list of LDAPMod structures
377 ready for ldap_add() or ldap_modify()
379 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
380 const struct ldb_message *msg, int use_flags)
386 /* allocate maximum number of elements needed */
387 mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1);
394 for (i=0;i<msg->num_elements;i++) {
395 const struct ldb_message_element *el = &msg->elements[i];
397 mods[num_mods] = ldb_malloc_p(ldb, LDAPMod);
398 if (!mods[num_mods]) {
401 mods[num_mods+1] = NULL;
402 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
404 switch (el->flags & LDB_FLAG_MOD_MASK) {
405 case LDB_FLAG_MOD_ADD:
406 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
408 case LDB_FLAG_MOD_DELETE:
409 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
411 case LDB_FLAG_MOD_REPLACE:
412 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
416 mods[num_mods]->mod_type = el->name;
417 mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb,
420 if (!mods[num_mods]->mod_vals.modv_bvals) {
424 for (j=0;j<el->num_values;j++) {
425 mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval);
426 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
429 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
430 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
432 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
439 lldb_mods_free(ldb, mods);
447 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
449 struct ldb_context *ldb = module->ldb;
450 struct lldb_private *lldb = module->private_data;
454 /* ignore ltdb specials */
455 if (msg->dn[0] == '@') {
459 mods = lldb_msg_to_mods(ldb, msg, 0);
461 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
462 if (lldb->last_rc != LDAP_SUCCESS) {
466 lldb_mods_free(ldb, mods);
475 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
477 struct ldb_context *ldb = module->ldb;
478 struct lldb_private *lldb = module->private_data;
482 /* ignore ltdb specials */
483 if (msg->dn[0] == '@') {
487 mods = lldb_msg_to_mods(ldb, msg, 1);
489 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
490 if (lldb->last_rc != LDAP_SUCCESS) {
494 lldb_mods_free(ldb, mods);
499 static int lldb_lock(struct ldb_module *module, const char *lockname)
503 if (lockname == NULL) {
507 /* TODO implement a local locking mechanism here */
512 static int lldb_unlock(struct ldb_module *module, const char *lockname)
516 if (lockname == NULL) {
520 /* TODO implement a local unlocking mechanism here */
526 return extended error information
528 static const char *lldb_errstring(struct ldb_module *module)
530 struct lldb_private *lldb = module->private_data;
531 return ldap_err2string(lldb->last_rc);
535 static const struct ldb_module_ops lldb_ops = {
551 connect to the database
553 struct ldb_context *lldb_connect(const char *url,
555 const char *options[])
557 struct ldb_context *ldb = NULL;
558 struct lldb_private *lldb = NULL;
561 ldb = calloc(1, sizeof(struct ldb_context));
567 lldb = ldb_malloc_p(ldb, struct lldb_private);
575 lldb->options = NULL;
577 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
578 if (lldb->last_rc != LDAP_SUCCESS) {
582 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
583 if (lldb->last_rc != LDAP_SUCCESS) {
587 ldb->modules = ldb_malloc_p(ldb, struct ldb_module);
593 ldb->modules->ldb = ldb;
594 ldb->modules->prev = ldb->modules->next = NULL;
595 ldb->modules->private_data = lldb;
596 ldb->modules->ops = &lldb_ops;
599 /* take a copy of the options array, so we don't have to rely
600 on the caller keeping it around (it might be dynamic) */
601 for (i=0;options[i];i++) ;
603 lldb->options = ldb_malloc_array_p(ldb, char *, i+1);
604 if (!lldb->options) {
608 for (i=0;options[i];i++) {
609 lldb->options[i+1] = NULL;
610 lldb->options[i] = ldb_strdup(ldb, options[i]);
611 if (!lldb->options[i]) {
620 if (lldb && lldb->options) {
621 for (i=0;lldb->options[i];i++) {
622 ldb_free(ldb, lldb->options[i]);
624 ldb_free(ldb, lldb->options);
626 if (lldb && lldb->ldap) {
627 ldap_unbind(lldb->ldap);