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_errors.h"
38 #include "ldb/include/ldb_private.h"
39 #include "ldb/ldb_ldap/ldb_ldap.h"
44 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
46 TALLOC_CTX *local_ctx;
47 struct lldb_private *lldb = module->private_data;
51 const char *parentdn = "";
53 /* ignore ltdb specials */
54 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
58 local_ctx = talloc_named(lldb, 0, "lldb_rename local context");
59 if (local_ctx == NULL) {
63 old_dn = ldb_dn_linearize(local_ctx, olddn);
68 newrdn = talloc_asprintf(lldb, "%s=%s",
69 newdn->components[0].name,
70 ldb_dn_escape_value(lldb, newdn->components[0].value));
75 parentdn = ldb_dn_linearize(lldb, ldb_dn_get_parent(lldb, newdn));
80 lldb->last_rc = ldap_rename_s(lldb->ldap, old_dn, newrdn, parentdn, 1, NULL, NULL);
81 if (lldb->last_rc != LDAP_SUCCESS) {
82 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
86 talloc_free(local_ctx);
90 talloc_free(local_ctx);
97 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *edn)
99 struct lldb_private *lldb = module->private_data;
103 /* ignore ltdb specials */
104 if (ldb_dn_is_special(edn)) {
108 dn = ldb_dn_linearize(lldb, edn);
110 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
111 if (lldb->last_rc != LDAP_SUCCESS) {
112 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
121 add a single set of ldap message values to a ldb_message
123 static int lldb_add_msg_attr(struct ldb_context *ldb,
124 struct ldb_message *msg,
125 const char *attr, struct berval **bval)
128 struct ldb_message_element *el;
130 count = ldap_count_values_len(bval);
136 el = talloc_realloc(msg, msg->elements, struct ldb_message_element,
137 msg->num_elements + 1);
145 el = &msg->elements[msg->num_elements];
147 el->name = talloc_strdup(msg->elements, attr);
155 el->values = talloc_array(msg->elements, struct ldb_val, count);
161 for (i=0;i<count;i++) {
162 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
163 if (!el->values[i].data) {
166 el->values[i].length = bval[i]->bv_len;
176 search for matching records
178 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
179 enum ldb_scope scope, struct ldb_parse_tree *tree,
180 const char * const *attrs, struct ldb_result **res)
182 struct ldb_context *ldb = module->ldb;
183 struct lldb_private *lldb = module->private_data;
184 int count, msg_count, ldap_scope;
186 LDAPMessage *ldapres, *msg;
189 search_base = ldb_dn_linearize(ldb, base);
191 search_base = talloc_strdup(ldb, "");
193 if (search_base == NULL) {
197 expression = ldb_filter_from_tree(search_base, tree);
198 if (expression == NULL) {
199 talloc_free(search_base);
205 ldap_scope = LDAP_SCOPE_BASE;
207 case LDB_SCOPE_ONELEVEL:
208 ldap_scope = LDAP_SCOPE_ONELEVEL;
211 ldap_scope = LDAP_SCOPE_SUBTREE;
215 (*res) = talloc(lldb, struct ldb_result);
218 return LDB_ERR_OTHER;
222 (*res)->controls = NULL;
224 lldb->last_rc = ldap_search_s(lldb->ldap, search_base, ldap_scope,
226 discard_const_p(char *, attrs),
228 talloc_free(search_base);
229 if (lldb->last_rc != LDAP_SUCCESS) {
230 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
231 return lldb->last_rc;
234 count = ldap_count_entries(lldb->ldap, ldapres);
235 if (count == -1 || count == 0) {
236 ldap_msgfree(ldapres);
240 (*res)->msgs = talloc_array(*res, struct ldb_message *, count+1);
241 if (! (*res)->msgs) {
242 ldap_msgfree(ldapres);
245 return LDB_ERR_OTHER;
248 (*res)->msgs[0] = NULL;
252 /* loop over all messages */
253 for (msg=ldap_first_entry(lldb->ldap, ldapres);
255 msg=ldap_next_entry(lldb->ldap, msg)) {
256 BerElement *berptr = NULL;
259 if (msg_count == count) {
260 /* hmm, got too many? */
261 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
265 (*res)->msgs[msg_count] = talloc((*res)->msgs, struct ldb_message);
266 if (!(*res)->msgs[msg_count]) {
269 (*res)->msgs[msg_count+1] = NULL;
271 dn = ldap_get_dn(lldb->ldap, msg);
276 (*res)->msgs[msg_count]->dn = ldb_dn_explode_or_special((*res)->msgs[msg_count], dn);
278 if (!(*res)->msgs[msg_count]->dn) {
283 (*res)->msgs[msg_count]->num_elements = 0;
284 (*res)->msgs[msg_count]->elements = NULL;
285 (*res)->msgs[msg_count]->private_data = NULL;
287 /* loop over all attributes */
288 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
290 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
291 struct berval **bval;
292 bval = ldap_get_values_len(lldb->ldap, msg, attr);
295 lldb_add_msg_attr(ldb, (*res)->msgs[msg_count], attr, bval);
296 ldap_value_free_len(bval);
301 if (berptr) ber_free(berptr, 0);
306 ldap_msgfree(ldapres);
308 (*res)->count = msg_count;
312 if (*res) talloc_free(*res);
313 return LDB_ERR_OTHER;
318 convert a ldb_message structure to a list of LDAPMod structures
319 ready for ldap_add() or ldap_modify()
321 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
322 const struct ldb_message *msg, int use_flags)
328 /* allocate maximum number of elements needed */
329 mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
336 for (i=0;i<msg->num_elements;i++) {
337 const struct ldb_message_element *el = &msg->elements[i];
339 mods[num_mods] = talloc(ldb, LDAPMod);
340 if (!mods[num_mods]) {
343 mods[num_mods+1] = NULL;
344 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
346 switch (el->flags & LDB_FLAG_MOD_MASK) {
347 case LDB_FLAG_MOD_ADD:
348 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
350 case LDB_FLAG_MOD_DELETE:
351 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
353 case LDB_FLAG_MOD_REPLACE:
354 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
358 mods[num_mods]->mod_type = discard_const_p(char, el->name);
359 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
362 if (!mods[num_mods]->mod_vals.modv_bvals) {
366 for (j=0;j<el->num_values;j++) {
367 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
369 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
372 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
373 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
375 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
390 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
392 struct ldb_context *ldb = module->ldb;
393 struct lldb_private *lldb = module->private_data;
398 /* ignore ltdb specials */
399 if (ldb_dn_is_special(msg->dn)) {
403 mods = lldb_msg_to_mods(ldb, msg, 0);
408 dn = ldb_dn_linearize(mods, msg->dn);
414 lldb->last_rc = ldap_add_s(lldb->ldap, dn, mods);
415 if (lldb->last_rc != LDAP_SUCCESS) {
416 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
429 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
431 struct ldb_context *ldb = module->ldb;
432 struct lldb_private *lldb = module->private_data;
437 /* ignore ltdb specials */
438 if (ldb_dn_is_special(msg->dn)) {
442 mods = lldb_msg_to_mods(ldb, msg, 1);
447 dn = ldb_dn_linearize(mods, msg->dn);
453 lldb->last_rc = ldap_modify_s(lldb->ldap, dn, mods);
454 if (lldb->last_rc != LDAP_SUCCESS) {
455 ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc)));
464 static int lldb_start_trans(struct ldb_module *module)
466 /* TODO implement a local transaction mechanism here */
471 static int lldb_end_trans(struct ldb_module *module)
473 /* TODO implement a local transaction mechanism here */
478 static int lldb_del_trans(struct ldb_module *module)
480 /* TODO implement a local transaction mechanism here */
485 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
487 switch (req->operation) {
490 return lldb_search_bytree(module,
492 req->op.search.scope,
494 req->op.search.attrs,
498 return lldb_add(module, req->op.add.message);
501 return lldb_modify(module, req->op.mod.message);
504 return lldb_delete(module, req->op.del.dn);
507 return lldb_rename(module,
508 req->op.rename.olddn,
509 req->op.rename.newdn);
517 static const struct ldb_module_ops lldb_ops = {
519 .request = lldb_request,
520 .start_transaction = lldb_start_trans,
521 .end_transaction = lldb_end_trans,
522 .del_transaction = lldb_del_trans
526 static int lldb_destructor(void *p)
528 struct lldb_private *lldb = p;
529 ldap_unbind(lldb->ldap);
534 connect to the database
536 int lldb_connect(struct ldb_context *ldb,
539 const char *options[])
541 struct lldb_private *lldb = NULL;
544 lldb = talloc(ldb, struct lldb_private);
551 lldb->options = NULL;
553 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
554 if (lldb->last_rc != LDAP_SUCCESS) {
555 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
556 url, ldap_err2string(lldb->last_rc));
560 talloc_set_destructor(lldb, lldb_destructor);
562 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
563 if (lldb->last_rc != LDAP_SUCCESS) {
564 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
565 ldap_err2string(lldb->last_rc));
568 ldb->modules = talloc(ldb, struct ldb_module);
573 ldb->modules->ldb = ldb;
574 ldb->modules->prev = ldb->modules->next = NULL;
575 ldb->modules->private_data = lldb;
576 ldb->modules->ops = &lldb_ops;