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"
43 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
45 TALLOC_CTX *local_ctx;
46 struct lldb_private *lldb = module->private_data;
50 const char *parentdn = "";
52 /* ignore ltdb specials */
53 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
57 local_ctx = talloc_named(lldb, 0, "lldb_rename local context");
58 if (local_ctx == NULL) {
62 old_dn = ldb_dn_linearize(local_ctx, olddn);
67 newrdn = talloc_asprintf(lldb, "%s=%s",
68 newdn->components[0].name,
69 ldb_dn_escape_value(lldb, newdn->components[0].value));
74 parentdn = ldb_dn_linearize(lldb, ldb_dn_get_parent(lldb, newdn));
79 lldb->last_rc = ldap_rename_s(lldb->ldap, old_dn, newrdn, parentdn, 1, NULL, NULL);
80 if (lldb->last_rc != LDAP_SUCCESS) {
81 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
85 talloc_free(local_ctx);
89 talloc_free(local_ctx);
96 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *edn)
98 struct lldb_private *lldb = module->private_data;
102 /* ignore ltdb specials */
103 if (ldb_dn_is_special(edn)) {
107 dn = ldb_dn_linearize(lldb, edn);
109 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
110 if (lldb->last_rc != LDAP_SUCCESS) {
111 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
120 add a single set of ldap message values to a ldb_message
122 static int lldb_add_msg_attr(struct ldb_context *ldb,
123 struct ldb_message *msg,
124 const char *attr, struct berval **bval)
127 struct ldb_message_element *el;
129 count = ldap_count_values_len(bval);
135 el = talloc_realloc(msg, msg->elements, struct ldb_message_element,
136 msg->num_elements + 1);
144 el = &msg->elements[msg->num_elements];
146 el->name = talloc_strdup(msg->elements, attr);
154 el->values = talloc_array(msg->elements, struct ldb_val, count);
160 for (i=0;i<count;i++) {
161 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
162 if (!el->values[i].data) {
165 el->values[i].length = bval[i]->bv_len;
175 search for matching records
177 static int lldb_search(struct ldb_module *module, const struct ldb_dn *base,
178 enum ldb_scope scope, const char *expression,
179 const char * const *attrs, struct ldb_message ***res)
181 struct ldb_context *ldb = module->ldb;
182 struct lldb_private *lldb = module->private_data;
183 int count, msg_count;
185 LDAPMessage *ldapres, *msg;
187 search_base = ldb_dn_linearize(ldb, base);
189 search_base = talloc_strdup(ldb, "");
191 if (search_base == NULL) {
195 if (expression == NULL || expression[0] == '\0') {
196 expression = "objectClass=*";
199 lldb->last_rc = ldap_search_s(lldb->ldap, search_base, (int)scope,
201 discard_const_p(char *, attrs),
203 talloc_free(search_base);
204 if (lldb->last_rc != LDAP_SUCCESS) {
205 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
209 count = ldap_count_entries(lldb->ldap, ldapres);
210 if (count == -1 || count == 0) {
211 ldap_msgfree(ldapres);
215 (*res) = talloc_array(lldb, struct ldb_message *, count+1);
217 ldap_msgfree(ldapres);
226 /* loop over all messages */
227 for (msg=ldap_first_entry(lldb->ldap, ldapres);
229 msg=ldap_next_entry(lldb->ldap, msg)) {
230 BerElement *berptr = NULL;
233 if (msg_count == count) {
234 /* hmm, got too many? */
235 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
239 (*res)[msg_count] = talloc(*res, struct ldb_message);
240 if (!(*res)[msg_count]) {
243 (*res)[msg_count+1] = NULL;
245 dn = ldap_get_dn(lldb->ldap, msg);
250 (*res)[msg_count]->dn = ldb_dn_explode((*res)[msg_count], dn);
252 if (!(*res)[msg_count]->dn) {
257 (*res)[msg_count]->num_elements = 0;
258 (*res)[msg_count]->elements = NULL;
259 (*res)[msg_count]->private_data = NULL;
261 /* loop over all attributes */
262 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
264 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
265 struct berval **bval;
266 bval = ldap_get_values_len(lldb->ldap, msg, attr);
269 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
270 ldap_value_free_len(bval);
275 if (berptr) ber_free(berptr, 0);
280 ldap_msgfree(ldapres);
285 if (*res) talloc_free(*res);
291 search for matching records using a ldb_parse_tree
293 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
294 enum ldb_scope scope, struct ldb_parse_tree *tree,
295 const char * const *attrs, struct ldb_message ***res)
297 struct lldb_private *lldb = module->private_data;
301 expression = ldb_filter_from_tree(lldb, tree);
302 if (expression == NULL) {
305 ret = lldb_search(module, base, scope, expression, attrs, res);
306 talloc_free(expression);
312 convert a ldb_message structure to a list of LDAPMod structures
313 ready for ldap_add() or ldap_modify()
315 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
316 const struct ldb_message *msg, int use_flags)
322 /* allocate maximum number of elements needed */
323 mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
330 for (i=0;i<msg->num_elements;i++) {
331 const struct ldb_message_element *el = &msg->elements[i];
333 mods[num_mods] = talloc(ldb, LDAPMod);
334 if (!mods[num_mods]) {
337 mods[num_mods+1] = NULL;
338 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
340 switch (el->flags & LDB_FLAG_MOD_MASK) {
341 case LDB_FLAG_MOD_ADD:
342 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
344 case LDB_FLAG_MOD_DELETE:
345 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
347 case LDB_FLAG_MOD_REPLACE:
348 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
352 mods[num_mods]->mod_type = discard_const_p(char, el->name);
353 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
356 if (!mods[num_mods]->mod_vals.modv_bvals) {
360 for (j=0;j<el->num_values;j++) {
361 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
363 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
366 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
367 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
369 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
384 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
386 struct ldb_context *ldb = module->ldb;
387 struct lldb_private *lldb = module->private_data;
392 /* ignore ltdb specials */
393 if (ldb_dn_is_special(msg->dn)) {
397 mods = lldb_msg_to_mods(ldb, msg, 0);
402 dn = ldb_dn_linearize(mods, msg->dn);
408 lldb->last_rc = ldap_add_s(lldb->ldap, dn, mods);
409 if (lldb->last_rc != LDAP_SUCCESS) {
410 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
423 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
425 struct ldb_context *ldb = module->ldb;
426 struct lldb_private *lldb = module->private_data;
431 /* ignore ltdb specials */
432 if (ldb_dn_is_special(msg->dn)) {
436 mods = lldb_msg_to_mods(ldb, msg, 1);
441 dn = ldb_dn_linearize(mods, msg->dn);
447 lldb->last_rc = ldap_modify_s(lldb->ldap, dn, mods);
448 if (lldb->last_rc != LDAP_SUCCESS) {
449 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
458 static int lldb_start_trans(struct ldb_module *module)
460 /* TODO implement a local transaction mechanism here */
465 static int lldb_end_trans(struct ldb_module *module)
467 /* TODO implement a local transaction mechanism here */
472 static int lldb_del_trans(struct ldb_module *module)
474 /* TODO implement a local transaction mechanism here */
479 static const struct ldb_module_ops lldb_ops = {
481 .search = lldb_search,
482 .search_bytree = lldb_search_bytree,
483 .add_record = lldb_add,
484 .modify_record = lldb_modify,
485 .delete_record = lldb_delete,
486 .rename_record = lldb_rename,
487 .start_transaction = lldb_start_trans,
488 .end_transaction = lldb_end_trans,
489 .del_transaction = lldb_del_trans
493 static int lldb_destructor(void *p)
495 struct lldb_private *lldb = p;
496 ldap_unbind(lldb->ldap);
501 connect to the database
503 int lldb_connect(struct ldb_context *ldb,
506 const char *options[])
508 struct lldb_private *lldb = NULL;
511 lldb = talloc(ldb, struct lldb_private);
518 lldb->options = NULL;
520 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
521 if (lldb->last_rc != LDAP_SUCCESS) {
522 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
523 url, ldap_err2string(lldb->last_rc));
527 talloc_set_destructor(lldb, lldb_destructor);
529 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
530 if (lldb->last_rc != LDAP_SUCCESS) {
531 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
532 ldap_err2string(lldb->last_rc));
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;