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) {
80 ldb_set_alloc(ldb, NULL, NULL);
83 for (i=0;lldb->options[i];i++) {
84 ldb_free(ldb, lldb->options[i]);
86 ldb_free(ldb, lldb->options);
97 static int lldb_delete(struct ldb_context *ldb, const char *dn)
99 struct lldb_private *lldb = ldb->private_data;
102 /* ignore ltdb specials */
107 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
108 if (lldb->last_rc != LDAP_SUCCESS) {
116 free a search message
118 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
121 ldb_free(ldb, msg->dn);
122 for (i=0;i<msg->num_elements;i++) {
123 ldb_free(ldb, msg->elements[i].name);
124 for (j=0;j<msg->elements[i].num_values;j++) {
125 if (msg->elements[i].values[j].data) {
126 ldb_free(ldb, msg->elements[i].values[j].data);
129 ldb_free(ldb, msg->elements[i].values);
131 if (msg->elements) ldb_free(ldb, msg->elements);
139 static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res)
142 for (i=0;res[i];i++) {
143 if (lldb_msg_free(ldb, res[i]) != 0) {
153 add a single set of ldap message values to a ldb_message
155 static int lldb_add_msg_attr(struct ldb_context *ldb,
156 struct ldb_message *msg,
157 const char *attr, struct berval **bval)
160 struct ldb_message_element *el;
162 count = ldap_count_values_len(bval);
168 el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element,
169 msg->num_elements + 1);
177 el = &msg->elements[msg->num_elements];
179 el->name = ldb_strdup(ldb, attr);
187 el->values = ldb_malloc_array_p(ldb, struct ldb_val, count);
193 for (i=0;i<count;i++) {
194 el->values[i].data = ldb_malloc(ldb, bval[i]->bv_len);
195 if (!el->values[i].data) {
198 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
199 el->values[i].length = bval[i]->bv_len;
209 search for matching records
211 static int lldb_search(struct ldb_context *ldb, const char *base,
212 enum ldb_scope scope, const char *expression,
213 char * const *attrs, struct ldb_message ***res)
215 struct lldb_private *lldb = ldb->private_data;
216 int count, msg_count;
217 LDAPMessage *ldapres, *msg;
219 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
220 expression, attrs, 0, &ldapres);
221 if (lldb->last_rc != LDAP_SUCCESS) {
225 count = ldap_count_entries(lldb->ldap, ldapres);
226 if (count == -1 || count == 0) {
227 ldap_msgfree(ldapres);
231 (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1);
233 ldap_msgfree(ldapres);
242 /* loop over all messages */
243 for (msg=ldap_first_entry(lldb->ldap, ldapres);
245 msg=ldap_next_entry(lldb->ldap, msg)) {
246 BerElement *berptr = NULL;
249 if (msg_count == count) {
250 /* hmm, got too many? */
251 fprintf(stderr,"Too many messages?!\n");
255 (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message);
256 if (!(*res)[msg_count]) {
259 (*res)[msg_count+1] = NULL;
261 dn = ldap_get_dn(lldb->ldap, msg);
266 (*res)[msg_count]->dn = ldb_strdup(ldb, dn);
268 if (!(*res)[msg_count]->dn) {
273 (*res)[msg_count]->num_elements = 0;
274 (*res)[msg_count]->elements = NULL;
275 (*res)[msg_count]->private_data = NULL;
277 /* loop over all attributes */
278 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
280 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
281 struct berval **bval;
282 bval = ldap_get_values_len(lldb->ldap, msg, attr);
285 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
286 ldap_value_free_len(bval);
291 if (berptr) ber_free(berptr, 0);
296 ldap_msgfree(ldapres);
301 if (*res) lldb_search_free(ldb, *res);
307 free a set of mods from lldb_msg_to_mods()
309 static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods)
315 for (i=0;mods[i];i++) {
316 if (mods[i]->mod_vals.modv_bvals) {
317 for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
318 ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]);
320 ldb_free(ldb, mods[i]->mod_vals.modv_bvals);
322 ldb_free(ldb, mods[i]);
329 convert a ldb_message structure to a list of LDAPMod structures
330 ready for ldap_add() or ldap_modify()
332 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
333 const struct ldb_message *msg, int use_flags)
336 int i, j, num_mods = 0;
338 /* allocate maximum number of elements needed */
339 mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1);
346 for (i=0;i<msg->num_elements;i++) {
347 const struct ldb_message_element *el = &msg->elements[i];
349 mods[num_mods] = ldb_malloc_p(ldb, LDAPMod);
350 if (!mods[num_mods]) {
353 mods[num_mods+1] = NULL;
354 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
356 switch (el->flags & LDB_FLAG_MOD_MASK) {
357 case LDB_FLAG_MOD_ADD:
358 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
360 case LDB_FLAG_MOD_DELETE:
361 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
363 case LDB_FLAG_MOD_REPLACE:
364 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
368 mods[num_mods]->mod_type = el->name;
369 mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb,
372 if (!mods[num_mods]->mod_vals.modv_bvals) {
376 for (j=0;j<el->num_values;j++) {
377 mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval);
378 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
381 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
382 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
384 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
391 lldb_mods_free(ldb, mods);
399 static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
401 struct lldb_private *lldb = ldb->private_data;
405 /* ignore ltdb specials */
406 if (msg->dn[0] == '@') {
410 mods = lldb_msg_to_mods(ldb, msg, 0);
412 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
413 if (lldb->last_rc != LDAP_SUCCESS) {
417 lldb_mods_free(ldb, mods);
426 static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
428 struct lldb_private *lldb = ldb->private_data;
432 /* ignore ltdb specials */
433 if (msg->dn[0] == '@') {
437 mods = lldb_msg_to_mods(ldb, msg, 1);
439 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
440 if (lldb->last_rc != LDAP_SUCCESS) {
444 lldb_mods_free(ldb, mods);
451 return extended error information
453 static const char *lldb_errstring(struct ldb_context *ldb)
455 struct lldb_private *lldb = ldb->private_data;
456 return ldap_err2string(lldb->last_rc);
460 static const struct ldb_backend_ops lldb_ops = {
472 connect to the database
474 struct ldb_context *lldb_connect(const char *url,
476 const char *options[])
478 struct ldb_context *ldb = NULL;
479 struct lldb_private *lldb = NULL;
482 ldb = calloc(1, sizeof(struct ldb_context));
488 lldb = ldb_malloc_p(ldb, struct lldb_private);
496 lldb->options = NULL;
498 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
499 if (lldb->last_rc != LDAP_SUCCESS) {
503 ldb->ops = &lldb_ops;
504 ldb->private_data = lldb;
507 /* take a copy of the options array, so we don't have to rely
508 on the caller keeping it around (it might be dynamic) */
509 for (i=0;options[i];i++) ;
511 lldb->options = ldb_malloc_array_p(ldb, char *, i+1);
512 if (!lldb->options) {
516 for (i=0;options[i];i++) {
517 lldb->options[i+1] = NULL;
518 lldb->options[i] = ldb_strdup(ldb, options[i]);
519 if (!lldb->options[i]) {
528 if (lldb && lldb->options) {
529 for (i=0;lldb->options[i];i++) {
530 ldb_free(ldb, lldb->options[i]);
532 ldb_free(ldb, lldb->options);
534 if (lldb && lldb->ldap) {
535 ldap_unbind(lldb->ldap);