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];
73 static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
75 struct lldb_private *lldb = module->private_data;
78 const char *parentdn = "";
79 TALLOC_CTX *mem_ctx = talloc_new(lldb);
81 /* ignore ltdb specials */
82 if (olddn[0] == '@' ||newdn[0] == '@') {
86 newrdn = talloc_strdup(mem_ctx, newdn);
91 p = strchr(newrdn, ',');
97 lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL);
98 if (lldb->last_rc != LDAP_SUCCESS) {
102 talloc_free(mem_ctx);
110 static int lldb_delete(struct ldb_module *module, const char *dn)
112 struct lldb_private *lldb = module->private_data;
115 /* ignore ltdb specials */
120 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
121 if (lldb->last_rc != LDAP_SUCCESS) {
129 add a single set of ldap message values to a ldb_message
131 static int lldb_add_msg_attr(struct ldb_context *ldb,
132 struct ldb_message *msg,
133 const char *attr, struct berval **bval)
136 struct ldb_message_element *el;
138 count = ldap_count_values_len(bval);
144 el = talloc_realloc(msg, msg->elements, struct ldb_message_element,
145 msg->num_elements + 1);
153 el = &msg->elements[msg->num_elements];
155 el->name = talloc_strdup(msg->elements, attr);
163 el->values = talloc_array(msg->elements, struct ldb_val, count);
169 for (i=0;i<count;i++) {
170 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
171 if (!el->values[i].data) {
174 el->values[i].length = bval[i]->bv_len;
184 search for matching records
186 static int lldb_search(struct ldb_module *module, const char *base,
187 enum ldb_scope scope, const char *expression,
188 const char * const *attrs, struct ldb_message ***res)
190 struct ldb_context *ldb = module->ldb;
191 struct lldb_private *lldb = module->private_data;
192 int count, msg_count;
193 LDAPMessage *ldapres, *msg;
199 if (expression == NULL || expression[0] == '\0') {
200 expression = "objectClass=*";
203 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
205 discard_const_p(char *, attrs),
207 if (lldb->last_rc != LDAP_SUCCESS) {
211 count = ldap_count_entries(lldb->ldap, ldapres);
212 if (count == -1 || count == 0) {
213 ldap_msgfree(ldapres);
217 (*res) = talloc_array(lldb, struct ldb_message *, count+1);
219 ldap_msgfree(ldapres);
228 /* loop over all messages */
229 for (msg=ldap_first_entry(lldb->ldap, ldapres);
231 msg=ldap_next_entry(lldb->ldap, msg)) {
232 BerElement *berptr = NULL;
235 if (msg_count == count) {
236 /* hmm, got too many? */
237 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
241 (*res)[msg_count] = talloc(*res, struct ldb_message);
242 if (!(*res)[msg_count]) {
245 (*res)[msg_count+1] = NULL;
247 dn = ldap_get_dn(lldb->ldap, msg);
252 (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
254 if (!(*res)[msg_count]->dn) {
259 (*res)[msg_count]->num_elements = 0;
260 (*res)[msg_count]->elements = NULL;
261 (*res)[msg_count]->private_data = NULL;
263 /* loop over all attributes */
264 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
266 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
267 struct berval **bval;
268 bval = ldap_get_values_len(lldb->ldap, msg, attr);
271 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
272 ldap_value_free_len(bval);
277 if (berptr) ber_free(berptr, 0);
282 ldap_msgfree(ldapres);
287 if (*res) talloc_free(*res);
293 search for matching records using a ldb_parse_tree
295 static int lldb_search_bytree(struct ldb_module *module, const char *base,
296 enum ldb_scope scope, struct ldb_parse_tree *tree,
297 const char * const *attrs, struct ldb_message ***res)
299 struct lldb_private *lldb = module->private_data;
303 expression = ldb_filter_from_tree(lldb, tree);
304 if (expression == NULL) {
307 ret = lldb_search(module, base, scope, expression, attrs, res);
308 talloc_free(expression);
314 convert a ldb_message structure to a list of LDAPMod structures
315 ready for ldap_add() or ldap_modify()
317 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
318 const struct ldb_message *msg, int use_flags)
324 /* allocate maximum number of elements needed */
325 mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
332 for (i=0;i<msg->num_elements;i++) {
333 const struct ldb_message_element *el = &msg->elements[i];
335 mods[num_mods] = talloc(ldb, LDAPMod);
336 if (!mods[num_mods]) {
339 mods[num_mods+1] = NULL;
340 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
342 switch (el->flags & LDB_FLAG_MOD_MASK) {
343 case LDB_FLAG_MOD_ADD:
344 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
346 case LDB_FLAG_MOD_DELETE:
347 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
349 case LDB_FLAG_MOD_REPLACE:
350 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
354 mods[num_mods]->mod_type = el->name;
355 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
358 if (!mods[num_mods]->mod_vals.modv_bvals) {
362 for (j=0;j<el->num_values;j++) {
363 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
365 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
368 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
369 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
371 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
386 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
388 struct ldb_context *ldb = module->ldb;
389 struct lldb_private *lldb = module->private_data;
393 /* ignore ltdb specials */
394 if (msg->dn[0] == '@') {
398 mods = lldb_msg_to_mods(ldb, msg, 0);
400 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
401 if (lldb->last_rc != LDAP_SUCCESS) {
414 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
416 struct ldb_context *ldb = module->ldb;
417 struct lldb_private *lldb = module->private_data;
421 /* ignore ltdb specials */
422 if (msg->dn[0] == '@') {
426 mods = lldb_msg_to_mods(ldb, msg, 1);
428 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
429 if (lldb->last_rc != LDAP_SUCCESS) {
438 static int lldb_lock(struct ldb_module *module, const char *lockname)
442 if (lockname == NULL) {
446 /* TODO implement a local locking mechanism here */
451 static int lldb_unlock(struct ldb_module *module, const char *lockname)
455 if (lockname == NULL) {
459 /* TODO implement a local unlocking mechanism here */
465 return extended error information
467 static const char *lldb_errstring(struct ldb_module *module)
469 struct lldb_private *lldb = module->private_data;
470 return ldap_err2string(lldb->last_rc);
474 static const struct ldb_module_ops lldb_ops = {
476 .search = lldb_search,
477 .search_bytree = lldb_search_bytree,
478 .add_record = lldb_add,
479 .modify_record = lldb_modify,
480 .delete_record = lldb_delete,
481 .rename_record = lldb_rename,
482 .named_lock = lldb_lock,
483 .named_unlock = lldb_unlock,
484 .errstring = lldb_errstring
488 static int lldb_destructor(void *p)
490 struct lldb_private *lldb = p;
491 ldap_unbind(lldb->ldap);
496 connect to the database
498 struct ldb_context *lldb_connect(const char *url,
500 const char *options[])
502 struct ldb_context *ldb = NULL;
503 struct lldb_private *lldb = NULL;
506 ldb = talloc(NULL, struct ldb_context);
512 ldb->debug_ops.debug = NULL;
514 lldb = talloc(ldb, struct lldb_private);
521 lldb->options = NULL;
523 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
524 if (lldb->last_rc != LDAP_SUCCESS) {
528 talloc_set_destructor(lldb, lldb_destructor);
530 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
531 if (lldb->last_rc != LDAP_SUCCESS) {
535 ldb->modules = talloc(ldb, struct ldb_module);
540 ldb->modules->ldb = ldb;
541 ldb->modules->prev = ldb->modules->next = NULL;
542 ldb->modules->private_data = lldb;
543 ldb->modules->ops = &lldb_ops;
546 /* take a copy of the options array, so we don't have to rely
547 on the caller keeping it around (it might be dynamic) */
548 for (i=0;options[i];i++) ;
550 lldb->options = talloc_array(lldb, char *, i+1);
551 if (!lldb->options) {
555 for (i=0;options[i];i++) {
556 lldb->options[i+1] = NULL;
557 lldb->options[i] = talloc_strdup(lldb->options, options[i]);
558 if (!lldb->options[i]) {