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 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
201 discard_const_p(char *, attrs),
203 if (lldb->last_rc != LDAP_SUCCESS) {
207 count = ldap_count_entries(lldb->ldap, ldapres);
208 if (count == -1 || count == 0) {
209 ldap_msgfree(ldapres);
213 (*res) = talloc_array(lldb, struct ldb_message *, count+1);
215 ldap_msgfree(ldapres);
224 /* loop over all messages */
225 for (msg=ldap_first_entry(lldb->ldap, ldapres);
227 msg=ldap_next_entry(lldb->ldap, msg)) {
228 BerElement *berptr = NULL;
231 if (msg_count == count) {
232 /* hmm, got too many? */
233 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
237 (*res)[msg_count] = talloc(*res, struct ldb_message);
238 if (!(*res)[msg_count]) {
241 (*res)[msg_count+1] = NULL;
243 dn = ldap_get_dn(lldb->ldap, msg);
248 (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
250 if (!(*res)[msg_count]->dn) {
255 (*res)[msg_count]->num_elements = 0;
256 (*res)[msg_count]->elements = NULL;
257 (*res)[msg_count]->private_data = NULL;
259 /* loop over all attributes */
260 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
262 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
263 struct berval **bval;
264 bval = ldap_get_values_len(lldb->ldap, msg, attr);
267 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
268 ldap_value_free_len(bval);
273 if (berptr) ber_free(berptr, 0);
278 ldap_msgfree(ldapres);
283 if (*res) talloc_free(*res);
289 search for matching records using a ldb_parse_tree
291 static int lldb_search_bytree(struct ldb_module *module, const char *base,
292 enum ldb_scope scope, struct ldb_parse_tree *tree,
293 const char * const *attrs, struct ldb_message ***res)
295 struct lldb_private *lldb = module->private_data;
299 expression = ldb_filter_from_tree(lldb, tree);
300 if (expression == NULL) {
303 ret = lldb_search(module, base, scope, expression, attrs, res);
304 talloc_free(expression);
310 convert a ldb_message structure to a list of LDAPMod structures
311 ready for ldap_add() or ldap_modify()
313 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
314 const struct ldb_message *msg, int use_flags)
320 /* allocate maximum number of elements needed */
321 mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
328 for (i=0;i<msg->num_elements;i++) {
329 const struct ldb_message_element *el = &msg->elements[i];
331 mods[num_mods] = talloc(ldb, LDAPMod);
332 if (!mods[num_mods]) {
335 mods[num_mods+1] = NULL;
336 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
338 switch (el->flags & LDB_FLAG_MOD_MASK) {
339 case LDB_FLAG_MOD_ADD:
340 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
342 case LDB_FLAG_MOD_DELETE:
343 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
345 case LDB_FLAG_MOD_REPLACE:
346 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
350 mods[num_mods]->mod_type = el->name;
351 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
354 if (!mods[num_mods]->mod_vals.modv_bvals) {
358 for (j=0;j<el->num_values;j++) {
359 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
361 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
364 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
365 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
367 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
382 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
384 struct ldb_context *ldb = module->ldb;
385 struct lldb_private *lldb = module->private_data;
389 /* ignore ltdb specials */
390 if (msg->dn[0] == '@') {
394 mods = lldb_msg_to_mods(ldb, msg, 0);
396 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
397 if (lldb->last_rc != LDAP_SUCCESS) {
410 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
412 struct ldb_context *ldb = module->ldb;
413 struct lldb_private *lldb = module->private_data;
417 /* ignore ltdb specials */
418 if (msg->dn[0] == '@') {
422 mods = lldb_msg_to_mods(ldb, msg, 1);
424 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
425 if (lldb->last_rc != LDAP_SUCCESS) {
434 static int lldb_lock(struct ldb_module *module, const char *lockname)
438 if (lockname == NULL) {
442 /* TODO implement a local locking mechanism here */
447 static int lldb_unlock(struct ldb_module *module, const char *lockname)
451 if (lockname == NULL) {
455 /* TODO implement a local unlocking mechanism here */
461 return extended error information
463 static const char *lldb_errstring(struct ldb_module *module)
465 struct lldb_private *lldb = module->private_data;
466 return ldap_err2string(lldb->last_rc);
470 static const struct ldb_module_ops lldb_ops = {
472 .search = lldb_search,
473 .search_bytree = lldb_search_bytree,
474 .add_record = lldb_add,
475 .modify_record = lldb_modify,
476 .delete_record = lldb_delete,
477 .rename_record = lldb_rename,
478 .named_lock = lldb_lock,
479 .named_unlock = lldb_unlock,
480 .errstring = lldb_errstring
484 static int lldb_destructor(void *p)
486 struct lldb_private *lldb = p;
487 ldap_unbind(lldb->ldap);
492 connect to the database
494 struct ldb_context *lldb_connect(const char *url,
496 const char *options[])
498 struct ldb_context *ldb = NULL;
499 struct lldb_private *lldb = NULL;
502 ldb = talloc(NULL, struct ldb_context);
508 ldb->debug_ops.debug = NULL;
510 lldb = talloc(ldb, struct lldb_private);
517 lldb->options = NULL;
519 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
520 if (lldb->last_rc != LDAP_SUCCESS) {
524 talloc_set_destructor(lldb, lldb_destructor);
526 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
527 if (lldb->last_rc != LDAP_SUCCESS) {
531 ldb->modules = talloc(ldb, struct ldb_module);
536 ldb->modules->ldb = ldb;
537 ldb->modules->prev = ldb->modules->next = NULL;
538 ldb->modules->private_data = lldb;
539 ldb->modules->ops = &lldb_ops;
542 /* take a copy of the options array, so we don't have to rely
543 on the caller keeping it around (it might be dynamic) */
544 for (i=0;options[i];i++) ;
546 lldb->options = talloc_array(lldb, char *, i+1);
547 if (!lldb->options) {
551 for (i=0;options[i];i++) {
552 lldb->options[i+1] = NULL;
553 lldb->options[i] = talloc_strdup(lldb->options, options[i]);
554 if (!lldb->options[i]) {