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_context *ldb)
74 struct lldb_private *lldb = ldb->private_data;
76 if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
81 for (i=0;lldb->options[i];i++) {
82 free(lldb->options[i]);
95 static int lldb_delete(struct ldb_context *ldb, const char *dn)
97 struct lldb_private *lldb = ldb->private_data;
100 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
101 if (lldb->last_rc != LDAP_SUCCESS) {
109 free a search message
111 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
115 for (i=0;i<msg->num_elements;i++) {
116 free(msg->elements[i].name);
117 for (j=0;j<msg->elements[i].num_values;j++) {
118 if (msg->elements[i].values[j].data) {
119 free(msg->elements[i].values[j].data);
122 free(msg->elements[i].values);
124 if (msg->elements) free(msg->elements);
132 static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res)
135 for (i=0;res[i];i++) {
136 if (lldb_msg_free(ldb, res[i]) != 0) {
146 add a single set of ldap message values to a ldb_message
148 static int lldb_add_msg_attr(struct ldb_message *msg,
149 const char *attr, struct berval **bval)
152 struct ldb_message_element *el;
154 count = ldap_count_values_len(bval);
160 el = realloc_p(msg->elements, struct ldb_message_element,
161 msg->num_elements + 1);
169 el = &msg->elements[msg->num_elements];
171 el->name = strdup(attr);
179 el->values = malloc_array_p(struct ldb_val, count);
185 for (i=0;i<count;i++) {
186 el->values[i].data = malloc(bval[i]->bv_len);
187 if (!el->values[i].data) {
190 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
191 el->values[i].length = bval[i]->bv_len;
201 search for matching records
203 static int lldb_search(struct ldb_context *ldb, const char *base,
204 enum ldb_scope scope, const char *expression,
205 const char **attrs, struct ldb_message ***res)
207 struct lldb_private *lldb = ldb->private_data;
208 int count, msg_count;
209 LDAPMessage *ldapres, *msg;
211 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
212 expression, attrs, 0, &ldapres);
213 if (lldb->last_rc != LDAP_SUCCESS) {
217 count = ldap_count_entries(lldb->ldap, ldapres);
218 if (count == -1 || count == 0) {
219 ldap_msgfree(ldapres);
223 (*res) = malloc_array_p(struct ldb_message *, count+1);
225 ldap_msgfree(ldapres);
234 /* loop over all messages */
235 for (msg=ldap_first_entry(lldb->ldap, ldapres);
237 msg=ldap_next_entry(lldb->ldap, msg)) {
238 BerElement *berptr = NULL;
241 if (msg_count == count) {
242 /* hmm, got too many? */
243 fprintf(stderr,"Too many messages?!\n");
247 (*res)[msg_count] = malloc_p(struct ldb_message);
248 if (!(*res)[msg_count]) {
251 (*res)[msg_count+1] = NULL;
253 dn = ldap_get_dn(lldb->ldap, msg);
258 (*res)[msg_count]->dn = strdup(dn);
260 if (!(*res)[msg_count]->dn) {
265 (*res)[msg_count]->num_elements = 0;
266 (*res)[msg_count]->elements = NULL;
267 (*res)[msg_count]->private_data = NULL;
269 /* loop over all attributes */
270 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
272 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
273 struct berval **bval;
274 bval = ldap_get_values_len(lldb->ldap, msg, attr);
277 lldb_add_msg_attr((*res)[msg_count], attr, bval);
278 ldap_value_free_len(bval);
283 if (berptr) ber_free(berptr, 0);
288 ldap_msgfree(ldapres);
293 if (*res) lldb_search_free(ldb, *res);
299 free a set of mods from lldb_msg_to_mods()
301 static void lldb_mods_free(LDAPMod **mods)
307 for (i=0;mods[i];i++) {
308 if (mods[i]->mod_vals.modv_bvals) {
309 for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
310 free(mods[i]->mod_vals.modv_bvals[j]);
312 free(mods[i]->mod_vals.modv_bvals);
321 convert a ldb_message structure to a list of LDAPMod structures
322 ready for ldap_add() or ldap_modify()
324 static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
327 int i, j, num_mods = 0;
329 /* allocate maximum number of elements needed */
330 mods = malloc_array_p(LDAPMod *, msg->num_elements+1);
337 for (i=0;i<msg->num_elements;i++) {
338 const struct ldb_message_element *el = &msg->elements[i];
340 mods[num_mods] = malloc_p(LDAPMod);
341 if (!mods[num_mods]) {
344 mods[num_mods+1] = NULL;
345 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
347 switch (el->flags & LDB_FLAG_MOD_MASK) {
348 case LDB_FLAG_MOD_ADD:
349 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
351 case LDB_FLAG_MOD_DELETE:
352 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
354 case LDB_FLAG_MOD_REPLACE:
355 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
359 mods[num_mods]->mod_type = el->name;
360 mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *,
362 if (!mods[num_mods]->mod_vals.modv_bvals) {
366 for (j=0;j<el->num_values;j++) {
367 mods[num_mods]->mod_vals.modv_bvals[j] = malloc_p(struct berval);
368 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
371 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
372 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
374 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
381 lldb_mods_free(mods);
389 static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
391 struct lldb_private *lldb = ldb->private_data;
395 mods = lldb_msg_to_mods(msg, 0);
397 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
398 if (lldb->last_rc != LDAP_SUCCESS) {
402 lldb_mods_free(mods);
411 static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
413 struct lldb_private *lldb = ldb->private_data;
417 mods = lldb_msg_to_mods(msg, 1);
419 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
420 if (lldb->last_rc != LDAP_SUCCESS) {
424 lldb_mods_free(mods);
431 return extended error information
433 static const char *lldb_errstring(struct ldb_context *ldb)
435 struct lldb_private *lldb = ldb->private_data;
436 return ldap_err2string(lldb->last_rc);
440 static const struct ldb_backend_ops lldb_ops = {
452 connect to the database
454 struct ldb_context *lldb_connect(const char *url,
456 const char *options[])
458 struct ldb_context *ldb = NULL;
459 struct lldb_private *lldb = NULL;
462 ldb = malloc_p(struct ldb_context);
468 lldb = malloc_p(struct lldb_private);
476 lldb->options = NULL;
478 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
479 if (lldb->last_rc != LDAP_SUCCESS) {
483 ldb->ops = &lldb_ops;
484 ldb->private_data = lldb;
487 /* take a copy of the options array, so we don't have to rely
488 on the caller keeping it around (it might be dynamic) */
489 for (i=0;options[i];i++) ;
491 lldb->options = malloc_array_p(char *, i+1);
492 if (!lldb->options) {
496 for (i=0;options[i];i++) {
497 lldb->options[i+1] = NULL;
498 lldb->options[i] = strdup(options[i]);
499 if (!lldb->options[i]) {
508 if (lldb && lldb->options) {
509 for (i=0;lldb->options[i];i++) {
510 free(lldb->options[i]);
514 if (lldb && lldb->ldap) {
515 ldap_unbind(lldb->ldap);
517 if (lldb) free(lldb);