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 /* ignore ltdb specials */
105 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
106 if (lldb->last_rc != LDAP_SUCCESS) {
114 free a search message
116 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
120 for (i=0;i<msg->num_elements;i++) {
121 free(msg->elements[i].name);
122 for (j=0;j<msg->elements[i].num_values;j++) {
123 if (msg->elements[i].values[j].data) {
124 free(msg->elements[i].values[j].data);
127 free(msg->elements[i].values);
129 if (msg->elements) free(msg->elements);
137 static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res)
140 for (i=0;res[i];i++) {
141 if (lldb_msg_free(ldb, res[i]) != 0) {
151 add a single set of ldap message values to a ldb_message
153 static int lldb_add_msg_attr(struct ldb_message *msg,
154 const char *attr, struct berval **bval)
157 struct ldb_message_element *el;
159 count = ldap_count_values_len(bval);
165 el = realloc_p(msg->elements, struct ldb_message_element,
166 msg->num_elements + 1);
174 el = &msg->elements[msg->num_elements];
176 el->name = strdup(attr);
184 el->values = malloc_array_p(struct ldb_val, count);
190 for (i=0;i<count;i++) {
191 el->values[i].data = malloc(bval[i]->bv_len);
192 if (!el->values[i].data) {
195 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
196 el->values[i].length = bval[i]->bv_len;
206 search for matching records
208 static int lldb_search(struct ldb_context *ldb, const char *base,
209 enum ldb_scope scope, const char *expression,
210 const char * const *attrs, struct ldb_message ***res)
212 struct lldb_private *lldb = ldb->private_data;
213 int count, msg_count;
214 LDAPMessage *ldapres, *msg;
216 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
217 expression, attrs, 0, &ldapres);
218 if (lldb->last_rc != LDAP_SUCCESS) {
222 count = ldap_count_entries(lldb->ldap, ldapres);
223 if (count == -1 || count == 0) {
224 ldap_msgfree(ldapres);
228 (*res) = malloc_array_p(struct ldb_message *, count+1);
230 ldap_msgfree(ldapres);
239 /* loop over all messages */
240 for (msg=ldap_first_entry(lldb->ldap, ldapres);
242 msg=ldap_next_entry(lldb->ldap, msg)) {
243 BerElement *berptr = NULL;
246 if (msg_count == count) {
247 /* hmm, got too many? */
248 fprintf(stderr,"Too many messages?!\n");
252 (*res)[msg_count] = malloc_p(struct ldb_message);
253 if (!(*res)[msg_count]) {
256 (*res)[msg_count+1] = NULL;
258 dn = ldap_get_dn(lldb->ldap, msg);
263 (*res)[msg_count]->dn = strdup(dn);
265 if (!(*res)[msg_count]->dn) {
270 (*res)[msg_count]->num_elements = 0;
271 (*res)[msg_count]->elements = NULL;
272 (*res)[msg_count]->private_data = NULL;
274 /* loop over all attributes */
275 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
277 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
278 struct berval **bval;
279 bval = ldap_get_values_len(lldb->ldap, msg, attr);
282 lldb_add_msg_attr((*res)[msg_count], attr, bval);
283 ldap_value_free_len(bval);
288 if (berptr) ber_free(berptr, 0);
293 ldap_msgfree(ldapres);
298 if (*res) lldb_search_free(ldb, *res);
304 free a set of mods from lldb_msg_to_mods()
306 static void lldb_mods_free(LDAPMod **mods)
312 for (i=0;mods[i];i++) {
313 if (mods[i]->mod_vals.modv_bvals) {
314 for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
315 free(mods[i]->mod_vals.modv_bvals[j]);
317 free(mods[i]->mod_vals.modv_bvals);
326 convert a ldb_message structure to a list of LDAPMod structures
327 ready for ldap_add() or ldap_modify()
329 static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
332 int i, j, num_mods = 0;
334 /* allocate maximum number of elements needed */
335 mods = malloc_array_p(LDAPMod *, msg->num_elements+1);
342 for (i=0;i<msg->num_elements;i++) {
343 const struct ldb_message_element *el = &msg->elements[i];
345 mods[num_mods] = malloc_p(LDAPMod);
346 if (!mods[num_mods]) {
349 mods[num_mods+1] = NULL;
350 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
352 switch (el->flags & LDB_FLAG_MOD_MASK) {
353 case LDB_FLAG_MOD_ADD:
354 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
356 case LDB_FLAG_MOD_DELETE:
357 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
359 case LDB_FLAG_MOD_REPLACE:
360 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
364 mods[num_mods]->mod_type = el->name;
365 mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *,
367 if (!mods[num_mods]->mod_vals.modv_bvals) {
371 for (j=0;j<el->num_values;j++) {
372 mods[num_mods]->mod_vals.modv_bvals[j] = malloc_p(struct berval);
373 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
376 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
377 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
379 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
386 lldb_mods_free(mods);
394 static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
396 struct lldb_private *lldb = ldb->private_data;
400 /* ignore ltdb specials */
401 if (msg->dn[0] == '@') {
405 mods = lldb_msg_to_mods(msg, 0);
407 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
408 if (lldb->last_rc != LDAP_SUCCESS) {
412 lldb_mods_free(mods);
421 static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
423 struct lldb_private *lldb = ldb->private_data;
427 /* ignore ltdb specials */
428 if (msg->dn[0] == '@') {
432 mods = lldb_msg_to_mods(msg, 1);
434 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
435 if (lldb->last_rc != LDAP_SUCCESS) {
439 lldb_mods_free(mods);
446 return extended error information
448 static const char *lldb_errstring(struct ldb_context *ldb)
450 struct lldb_private *lldb = ldb->private_data;
451 return ldap_err2string(lldb->last_rc);
455 static const struct ldb_backend_ops lldb_ops = {
467 connect to the database
469 struct ldb_context *lldb_connect(const char *url,
471 const char *options[])
473 struct ldb_context *ldb = NULL;
474 struct lldb_private *lldb = NULL;
477 ldb = malloc_p(struct ldb_context);
483 lldb = malloc_p(struct lldb_private);
491 lldb->options = NULL;
493 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
494 if (lldb->last_rc != LDAP_SUCCESS) {
498 ldb->ops = &lldb_ops;
499 ldb->private_data = lldb;
502 /* take a copy of the options array, so we don't have to rely
503 on the caller keeping it around (it might be dynamic) */
504 for (i=0;options[i];i++) ;
506 lldb->options = malloc_array_p(char *, i+1);
507 if (!lldb->options) {
511 for (i=0;options[i];i++) {
512 lldb->options[i+1] = NULL;
513 lldb->options[i] = strdup(options[i]);
514 if (!lldb->options[i]) {
523 if (lldb && lldb->options) {
524 for (i=0;lldb->options[i];i++) {
525 free(lldb->options[i]);
529 if (lldb && lldb->ldap) {
530 ldap_unbind(lldb->ldap);
532 if (lldb) free(lldb);