2 ldb database library - ildap backend
4 Copyright (C) Andrew Tridgell 2005
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
26 This is a ldb backend for the internal ldap client library in
27 Samba4. By using this backend we are independent of a system ldap
33 #include "ldb/include/ldb.h"
34 #include "ldb/include/ldb_private.h"
35 #include "ldb/include/ldb_errors.h"
36 #include "libcli/ldap/ldap.h"
37 #include "libcli/ldap/ldap_client.h"
38 #include "lib/cmdline/popt_common.h"
39 #include "auth/auth.h"
42 struct ldap_connection *ldap;
43 struct ldb_message *rootDSE;
44 struct ldb_context *ldb;
49 map an ildap NTSTATUS to a ldb error code
51 static int ildb_map_error(struct ildb_private *ildb, NTSTATUS status)
53 if (NT_STATUS_IS_OK(status)) {
56 talloc_free(ildb->ldb->err_string);
57 ildb->ldb->err_string = talloc_strdup(ildb, ldap_errstr(ildb->ldap, status));
58 if (NT_STATUS_IS_LDAP(status)) {
59 return NT_STATUS_LDAP_CODE(status);
61 return LDB_ERR_OPERATIONS_ERROR;
67 static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
69 TALLOC_CTX *local_ctx;
70 struct ildb_private *ildb = module->private_data;
73 char *newrdn, *parentdn;
76 /* ignore ltdb specials */
77 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
81 local_ctx = talloc_named(ildb, 0, "ildb_rename local context");
82 if (local_ctx == NULL) {
83 ret = LDB_ERR_OPERATIONS_ERROR;
87 old_dn = ldb_dn_linearize(local_ctx, olddn);
89 ret = LDB_ERR_INVALID_DN_SYNTAX;
93 newrdn = talloc_asprintf(local_ctx, "%s=%s",
94 newdn->components[0].name,
95 ldb_dn_escape_value(ildb, newdn->components[0].value));
97 ret = LDB_ERR_OPERATIONS_ERROR;
101 parentdn = ldb_dn_linearize(local_ctx, ldb_dn_get_parent(ildb, newdn));
102 if (parentdn == NULL) {
103 ret = LDB_ERR_INVALID_DN_SYNTAX;
107 status = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True);
108 ret = ildb_map_error(ildb, status);
111 talloc_free(local_ctx);
118 static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn)
120 struct ildb_private *ildb = module->private_data;
125 /* ignore ltdb specials */
126 if (ldb_dn_is_special(dn)) {
130 del_dn = ldb_dn_linearize(ildb, dn);
131 if (del_dn == NULL) {
132 return LDB_ERR_INVALID_DN_SYNTAX;
135 status = ildap_delete(ildb->ldap, del_dn);
136 ret = ildb_map_error(ildb, status);
144 static void ildb_rootdse(struct ldb_module *module);
147 search for matching records using a ldb_parse_tree
149 static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
150 enum ldb_scope scope, struct ldb_parse_tree *tree,
151 const char * const *attrs,
152 struct ldb_control **control_req,
153 struct ldb_result **res)
155 struct ildb_private *ildb = module->private_data;
157 struct ldap_message **ldapres, *msg;
158 struct ldap_Control **controls = NULL;
162 if (scope == LDB_SCOPE_DEFAULT) {
163 scope = LDB_SCOPE_SUBTREE;
167 if (ildb->rootDSE == NULL) {
168 ildb_rootdse(module);
170 if (ildb->rootDSE != NULL) {
171 search_base = talloc_strdup(ildb,
172 ldb_msg_find_string(ildb->rootDSE,
173 "defaultNamingContext", ""));
175 search_base = talloc_strdup(ildb, "");
178 search_base = ldb_dn_linearize(ildb, base);
180 if (search_base == NULL) {
181 ldb_set_errstring(module, talloc_asprintf(module, "Unable to determine baseDN"));
182 return LDB_ERR_OTHER;
185 ldb_set_errstring(module, talloc_asprintf(module, "Invalid expression parse tree"));
186 return LDB_ERR_OTHER;
189 (*res) = talloc(ildb, struct ldb_result);
191 return LDB_ERR_OTHER;
195 (*res)->controls = NULL;
197 status = ildap_search_bytree(ildb->ldap, search_base, scope, tree, attrs, 0,
198 (struct ldap_Control **)control_req,
201 talloc_free(search_base);
202 if (!NT_STATUS_IS_OK(status)) {
203 ildb_map_error(ildb, status);
204 return LDB_ERR_OTHER;
207 count = ildap_count_entries(ildb->ldap, ldapres);
209 talloc_free(ldapres);
210 return LDB_ERR_OTHER;
214 talloc_free(ldapres);
218 (*res)->msgs = talloc_array(*res, struct ldb_message *, count + 1);
219 if (! (*res)->msgs) {
220 talloc_free(ldapres);
221 return LDB_ERR_OTHER;
224 (*res)->msgs[0] = NULL;
226 /* loop over all messages */
227 for (i=0;i<count;i++) {
228 struct ldap_SearchResEntry *search;
231 search = &msg->r.SearchResultEntry;
233 (*res)->msgs[i] = talloc((*res)->msgs, struct ldb_message);
234 if (!(*res)->msgs[i]) {
237 (*res)->msgs[i+1] = NULL;
239 (*res)->msgs[i]->dn = ldb_dn_explode_or_special((*res)->msgs[i], search->dn);
240 if ((*res)->msgs[i]->dn == NULL) {
243 (*res)->msgs[i]->num_elements = search->num_attributes;
244 (*res)->msgs[i]->elements = talloc_steal((*res)->msgs[i], search->attributes);
245 (*res)->msgs[i]->private_data = NULL;
248 talloc_free(ldapres);
250 (*res)->count = count;
253 (*res)->controls = (struct ldb_control **)talloc_steal(*res, controls);
259 if (*res) talloc_free(*res);
260 return LDB_ERR_OTHER;
265 convert a ldb_message structure to a list of ldap_mod structures
266 ready for ildap_add() or ildap_modify()
268 static struct ldap_mod **ildb_msg_to_mods(struct ldb_context *ldb,
269 const struct ldb_message *msg, int use_flags)
271 struct ldap_mod **mods;
275 /* allocate maximum number of elements needed */
276 mods = talloc_array(ldb, struct ldap_mod *, msg->num_elements+1);
283 for (i=0;i<msg->num_elements;i++) {
284 const struct ldb_message_element *el = &msg->elements[i];
286 mods[num_mods] = talloc(ldb, struct ldap_mod);
287 if (!mods[num_mods]) {
290 mods[num_mods+1] = NULL;
291 mods[num_mods]->type = 0;
292 mods[num_mods]->attrib = *el;
294 switch (el->flags & LDB_FLAG_MOD_MASK) {
295 case LDB_FLAG_MOD_ADD:
296 mods[num_mods]->type = LDAP_MODIFY_ADD;
298 case LDB_FLAG_MOD_DELETE:
299 mods[num_mods]->type = LDAP_MODIFY_DELETE;
301 case LDB_FLAG_MOD_REPLACE:
302 mods[num_mods]->type = LDAP_MODIFY_REPLACE;
320 static int ildb_add(struct ldb_module *module, const struct ldb_message *msg)
322 struct ldb_context *ldb = module->ldb;
323 struct ildb_private *ildb = module->private_data;
324 struct ldap_mod **mods;
329 /* ignore ltdb specials */
330 if (ldb_dn_is_special(msg->dn)) {
334 mods = ildb_msg_to_mods(ldb, msg, 0);
336 return LDB_ERR_OPERATIONS_ERROR;
339 dn = ldb_dn_linearize(mods, msg->dn);
342 return LDB_ERR_INVALID_DN_SYNTAX;
345 status = ildap_add(ildb->ldap, dn, mods);
346 ret = ildb_map_error(ildb, status);
357 static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg)
359 struct ldb_context *ldb = module->ldb;
360 struct ildb_private *ildb = module->private_data;
361 struct ldap_mod **mods;
366 /* ignore ltdb specials */
367 if (ldb_dn_is_special(msg->dn)) {
371 mods = ildb_msg_to_mods(ldb, msg, 1);
373 return LDB_ERR_OPERATIONS_ERROR;
376 dn = ldb_dn_linearize(mods, msg->dn);
379 return LDB_ERR_INVALID_DN_SYNTAX;
382 status = ildap_modify(ildb->ldap, dn, mods);
383 ret = ildb_map_error(ildb, status);
390 static int ildb_start_trans(struct ldb_module *module)
392 /* TODO implement a local locking mechanism here */
397 static int ildb_end_trans(struct ldb_module *module)
399 /* TODO implement a local transaction mechanism here */
404 static int ildb_del_trans(struct ldb_module *module)
406 /* TODO implement a local locking mechanism here */
411 static int ildb_request(struct ldb_module *module, struct ldb_request *req)
413 switch (req->operation) {
416 return ildb_search_bytree(module,
418 req->op.search.scope,
420 req->op.search.attrs,
422 &req->op.search.res);
425 return ildb_add(module, req->op.add.message);
428 return ildb_modify(module, req->op.mod.message);
431 return ildb_delete(module, req->op.del.dn);
434 return ildb_rename(module,
435 req->op.rename.olddn,
436 req->op.rename.newdn);
444 static int ildb_init_2(struct ldb_module *module)
449 static const struct ldb_module_ops ildb_ops = {
451 .request = ildb_request,
452 .start_transaction = ildb_start_trans,
453 .end_transaction = ildb_end_trans,
454 .del_transaction = ildb_del_trans,
455 .second_stage_init = ildb_init_2
462 static void ildb_rootdse(struct ldb_module *module)
464 struct ildb_private *ildb = module->private_data;
465 struct ldb_result *res = NULL;
466 struct ldb_dn *empty_dn = ldb_dn_new(ildb);
468 ret = ildb_search_bytree(module, empty_dn, LDB_SCOPE_BASE,
469 ldb_parse_tree(empty_dn, "dn=dc=rootDSE"),
471 if (ret == LDB_SUCCESS && res->count == 1) {
472 ildb->rootDSE = talloc_steal(ildb, res->msgs[0]);
474 if (ret == LDB_SUCCESS) talloc_free(res);
475 talloc_free(empty_dn);
480 connect to the database
482 int ildb_connect(struct ldb_context *ldb, const char *url,
483 unsigned int flags, const char *options[])
485 struct ildb_private *ildb = NULL;
487 struct cli_credentials *creds;
489 ildb = talloc(ldb, struct ildb_private);
495 ildb->rootDSE = NULL;
498 ildb->ldap = ldap_new_connection(ildb, ldb_get_opaque(ldb, "EventContext"));
504 status = ldap_connect(ildb->ldap, url);
505 if (!NT_STATUS_IS_OK(status)) {
506 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s\n",
507 url, ldap_errstr(ildb->ldap, status));
511 ldb->modules = talloc(ldb, struct ldb_module);
516 ldb->modules->ldb = ldb;
517 ldb->modules->prev = ldb->modules->next = NULL;
518 ldb->modules->private_data = ildb;
519 ldb->modules->ops = &ildb_ops;
521 /* caller can optionally setup credentials using the opaque token 'credentials' */
522 creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
524 struct auth_session_info *session_info = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
526 creds = session_info->credentials;
530 if (creds != NULL && cli_credentials_authentication_requested(creds)) {
531 const char *bind_dn = cli_credentials_get_bind_dn(creds);
533 const char *password = cli_credentials_get_password(creds);
534 status = ldap_bind_simple(ildb->ldap, bind_dn, password);
535 if (!NT_STATUS_IS_OK(status)) {
536 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
537 ldap_errstr(ildb->ldap, status));
541 status = ldap_bind_sasl(ildb->ldap, creds);
542 if (!NT_STATUS_IS_OK(status)) {
543 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
544 ldap_errstr(ildb->ldap, status));
554 ldb->modules->private_data = NULL;