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/ldb_ldap/ldb_ldap.h"
40 we don't need this right now, but will once we add some backend
45 find an option in an option list (a null terminated list of strings)
47 this assumes the list is short. If it ever gets long then we really
48 should do this in some smarter way
50 static const char *lldb_option_find(const struct lldb_private *lldb, const char *name)
53 size_t len = strlen(name);
55 if (!lldb->options) return NULL;
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];
69 close/free the connection
71 static int lldb_close(struct ldb_module *module)
74 struct ldb_context *ldb = module->ldb;
75 struct lldb_private *lldb = module->private_data;
77 if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
81 ldb_set_alloc(ldb, NULL, NULL);
84 for (i=0;lldb->options[i];i++) {
85 ldb_free(ldb, lldb->options[i]);
87 ldb_free(ldb, lldb->options);
98 static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
100 struct ldb_context *ldb = module->ldb;
101 struct lldb_private *lldb = module->private_data;
104 const char *parentdn = "";
106 /* ignore ltdb specials */
107 if (olddn[0] == '@' ||newdn[0] == '@') {
111 newrdn = ldb_strdup(ldb, newdn);
116 p = strchr(newrdn, ',');
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) {
134 static int lldb_delete(struct ldb_module *module, const char *dn)
136 struct lldb_private *lldb = module->private_data;
139 /* ignore ltdb specials */
144 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
145 if (lldb->last_rc != LDAP_SUCCESS) {
153 free a search message
155 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
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);
166 ldb_free(ldb, msg->elements[i].values);
168 if (msg->elements) ldb_free(ldb, msg->elements);
176 static int lldb_search_free(struct ldb_module *module, struct ldb_message **res)
178 struct ldb_context *ldb = module->ldb;
180 for (i=0;res[i];i++) {
181 if (lldb_msg_free(ldb, res[i]) != 0) {
191 add a single set of ldap message values to a ldb_message
193 static int lldb_add_msg_attr(struct ldb_context *ldb,
194 struct ldb_message *msg,
195 const char *attr, struct berval **bval)
198 struct ldb_message_element *el;
200 count = ldap_count_values_len(bval);
206 el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element,
207 msg->num_elements + 1);
215 el = &msg->elements[msg->num_elements];
217 el->name = ldb_strdup(ldb, attr);
225 el->values = ldb_malloc_array_p(ldb, struct ldb_val, count);
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) {
236 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
237 el->values[i].length = bval[i]->bv_len;
247 search for matching records
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)
253 struct ldb_context *ldb = module->ldb;
254 struct lldb_private *lldb = module->private_data;
255 int count, msg_count;
256 LDAPMessage *ldapres, *msg;
258 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
260 discard_const_p(char *, attrs),
262 if (lldb->last_rc != LDAP_SUCCESS) {
266 count = ldap_count_entries(lldb->ldap, ldapres);
267 if (count == -1 || count == 0) {
268 ldap_msgfree(ldapres);
272 (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1);
274 ldap_msgfree(ldapres);
283 /* loop over all messages */
284 for (msg=ldap_first_entry(lldb->ldap, ldapres);
286 msg=ldap_next_entry(lldb->ldap, msg)) {
287 BerElement *berptr = NULL;
290 if (msg_count == count) {
291 /* hmm, got too many? */
292 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
296 (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message);
297 if (!(*res)[msg_count]) {
300 (*res)[msg_count+1] = NULL;
302 dn = ldap_get_dn(lldb->ldap, msg);
307 (*res)[msg_count]->dn = ldb_strdup(ldb, dn);
309 if (!(*res)[msg_count]->dn) {
314 (*res)[msg_count]->num_elements = 0;
315 (*res)[msg_count]->elements = NULL;
316 (*res)[msg_count]->private_data = NULL;
318 /* loop over all attributes */
319 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
321 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
322 struct berval **bval;
323 bval = ldap_get_values_len(lldb->ldap, msg, attr);
326 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
327 ldap_value_free_len(bval);
332 if (berptr) ber_free(berptr, 0);
337 ldap_msgfree(ldapres);
342 if (*res) lldb_search_free(module, *res);
348 free a set of mods from lldb_msg_to_mods()
350 static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods)
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]);
361 ldb_free(ldb, mods[i]->mod_vals.modv_bvals);
363 ldb_free(ldb, mods[i]);
370 convert a ldb_message structure to a list of LDAPMod structures
371 ready for ldap_add() or ldap_modify()
373 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
374 const struct ldb_message *msg, int use_flags)
380 /* allocate maximum number of elements needed */
381 mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1);
388 for (i=0;i<msg->num_elements;i++) {
389 const struct ldb_message_element *el = &msg->elements[i];
391 mods[num_mods] = ldb_malloc_p(ldb, LDAPMod);
392 if (!mods[num_mods]) {
395 mods[num_mods+1] = NULL;
396 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
398 switch (el->flags & LDB_FLAG_MOD_MASK) {
399 case LDB_FLAG_MOD_ADD:
400 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
402 case LDB_FLAG_MOD_DELETE:
403 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
405 case LDB_FLAG_MOD_REPLACE:
406 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
410 mods[num_mods]->mod_type = el->name;
411 mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb,
414 if (!mods[num_mods]->mod_vals.modv_bvals) {
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]) {
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;
426 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
433 lldb_mods_free(ldb, mods);
441 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
443 struct ldb_context *ldb = module->ldb;
444 struct lldb_private *lldb = module->private_data;
448 /* ignore ltdb specials */
449 if (msg->dn[0] == '@') {
453 mods = lldb_msg_to_mods(ldb, msg, 0);
455 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
456 if (lldb->last_rc != LDAP_SUCCESS) {
460 lldb_mods_free(ldb, mods);
469 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
471 struct ldb_context *ldb = module->ldb;
472 struct lldb_private *lldb = module->private_data;
476 /* ignore ltdb specials */
477 if (msg->dn[0] == '@') {
481 mods = lldb_msg_to_mods(ldb, msg, 1);
483 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
484 if (lldb->last_rc != LDAP_SUCCESS) {
488 lldb_mods_free(ldb, mods);
495 return extended error information
497 static const char *lldb_errstring(struct ldb_module *module)
499 struct lldb_private *lldb = module->private_data;
500 return ldap_err2string(lldb->last_rc);
504 static const struct ldb_module_ops lldb_ops = {
518 connect to the database
520 struct ldb_context *lldb_connect(const char *url,
522 const char *options[])
524 struct ldb_context *ldb = NULL;
525 struct lldb_private *lldb = NULL;
528 ldb = calloc(1, sizeof(struct ldb_context));
534 lldb = ldb_malloc_p(ldb, struct lldb_private);
542 lldb->options = NULL;
544 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
545 if (lldb->last_rc != LDAP_SUCCESS) {
549 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
550 if (lldb->last_rc != LDAP_SUCCESS) {
554 ldb->modules = ldb_malloc_p(ldb, struct ldb_module);
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;
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++) ;
570 lldb->options = ldb_malloc_array_p(ldb, char *, i+1);
571 if (!lldb->options) {
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]) {
587 if (lldb && lldb->options) {
588 for (i=0;lldb->options[i];i++) {
589 ldb_free(ldb, lldb->options[i]);
591 ldb_free(ldb, lldb->options);
593 if (lldb && lldb->ldap) {
594 ldap_unbind(lldb->ldap);