r3757: Some fixes for ldb_ldap
[Samba/gebeck_regimport.git] / source4 / lib / ldb / ldb_ldap / ldb_ldap.c
blob7fb6a0b3f7bb7cc748ec8b8d204ede42fe04aed3
1 /*
2 ldb database library
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
8 ** under the LGPL
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 * Name: ldb
28 * Component: ldb ldap backend
30 * Description: core files for LDAP backend
32 * Author: Andrew Tridgell
35 #include "includes.h"
36 #include "ldb/ldb_ldap/ldb_ldap.h"
38 #if 0
40 we don't need this right now, but will once we add some backend
41 options
45 find an option in an option list (a null terminated list of strings)
47 this assumes the list is short. If it ever gets long then we really
48 should do this in some smarter way
50 static const char *lldb_option_find(const struct lldb_private *lldb, const char *name)
52 int i;
53 size_t len = strlen(name);
55 if (!lldb->options) return NULL;
57 for (i=0;lldb->options[i];i++) {
58 if (strncmp(lldb->options[i], name, len) == 0 &&
59 lldb->options[i][len] == '=') {
60 return &lldb->options[i][len+1];
64 return NULL;
66 #endif
69 close/free the connection
71 static int lldb_close(struct ldb_module *module)
73 int i, ret = 0;
74 struct ldb_context *ldb = module->ldb;
75 struct lldb_private *lldb = module->private_data;
77 if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
78 ret = -1;
81 ldb_set_alloc(ldb, NULL, NULL);
83 if (lldb->options) {
84 for (i=0;lldb->options[i];i++) {
85 ldb_free(ldb, lldb->options[i]);
87 ldb_free(ldb, lldb->options);
89 ldb_free(ldb, lldb);
90 free(ldb);
92 return ret;
96 rename a record
98 static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
100 struct ldb_context *ldb = module->ldb;
101 struct lldb_private *lldb = module->private_data;
102 int ret = 0;
103 char *newrdn, *p;
104 const char *parentdn = "";
106 /* ignore ltdb specials */
107 if (olddn[0] == '@' ||newdn[0] == '@') {
108 return 0;
111 newrdn = ldb_strdup(ldb, newdn);
112 if (!newrdn) {
113 return -1;
116 p = strchr(newrdn, ',');
117 if (p) {
118 *p++ = '\0';
119 parentdn = p;
122 lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL);
123 ldb_free(ldb, newrdn);
124 if (lldb->last_rc != LDAP_SUCCESS) {
125 ret = -1;
128 return ret;
132 delete a record
134 static int lldb_delete(struct ldb_module *module, const char *dn)
136 struct lldb_private *lldb = module->private_data;
137 int ret = 0;
139 /* ignore ltdb specials */
140 if (dn[0] == '@') {
141 return 0;
144 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
145 if (lldb->last_rc != LDAP_SUCCESS) {
146 ret = -1;
149 return ret;
153 free a search message
155 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
157 unsigned int i, j;
158 ldb_free(ldb, msg->dn);
159 for (i=0;i<msg->num_elements;i++) {
160 ldb_free(ldb, msg->elements[i].name);
161 for (j=0;j<msg->elements[i].num_values;j++) {
162 if (msg->elements[i].values[j].data) {
163 ldb_free(ldb, msg->elements[i].values[j].data);
166 ldb_free(ldb, msg->elements[i].values);
168 if (msg->elements) ldb_free(ldb, msg->elements);
169 ldb_free(ldb, msg);
170 return 0;
174 free a search result
176 static int lldb_search_free(struct ldb_module *module, struct ldb_message **res)
178 struct ldb_context *ldb = module->ldb;
179 int i;
180 for (i=0;res[i];i++) {
181 if (lldb_msg_free(ldb, res[i]) != 0) {
182 return -1;
185 ldb_free(ldb, res);
186 return 0;
191 add a single set of ldap message values to a ldb_message
193 static int lldb_add_msg_attr(struct ldb_context *ldb,
194 struct ldb_message *msg,
195 const char *attr, struct berval **bval)
197 int count, i;
198 struct ldb_message_element *el;
200 count = ldap_count_values_len(bval);
202 if (count <= 0) {
203 return -1;
206 el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element,
207 msg->num_elements + 1);
208 if (!el) {
209 errno = ENOMEM;
210 return -1;
213 msg->elements = el;
215 el = &msg->elements[msg->num_elements];
217 el->name = ldb_strdup(ldb, attr);
218 if (!el->name) {
219 errno = ENOMEM;
220 return -1;
222 el->flags = 0;
224 el->num_values = 0;
225 el->values = ldb_malloc_array_p(ldb, struct ldb_val, count);
226 if (!el->values) {
227 errno = ENOMEM;
228 return -1;
231 for (i=0;i<count;i++) {
232 el->values[i].data = ldb_malloc(ldb, bval[i]->bv_len);
233 if (!el->values[i].data) {
234 return -1;
236 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
237 el->values[i].length = bval[i]->bv_len;
238 el->num_values++;
241 msg->num_elements++;
243 return 0;
247 search for matching records
249 static int lldb_search(struct ldb_module *module, const char *base,
250 enum ldb_scope scope, const char *expression,
251 const char * const *attrs, struct ldb_message ***res)
253 struct ldb_context *ldb = module->ldb;
254 struct lldb_private *lldb = module->private_data;
255 int count, msg_count;
256 LDAPMessage *ldapres, *msg;
258 if (base == NULL) {
259 base = "";
262 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
263 expression,
264 discard_const_p(char *, attrs),
265 0, &ldapres);
266 if (lldb->last_rc != LDAP_SUCCESS) {
267 return -1;
270 count = ldap_count_entries(lldb->ldap, ldapres);
271 if (count == -1 || count == 0) {
272 ldap_msgfree(ldapres);
273 return count;
276 (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1);
277 if (! *res) {
278 ldap_msgfree(ldapres);
279 errno = ENOMEM;
280 return -1;
283 (*res)[0] = NULL;
285 msg_count = 0;
287 /* loop over all messages */
288 for (msg=ldap_first_entry(lldb->ldap, ldapres);
289 msg;
290 msg=ldap_next_entry(lldb->ldap, msg)) {
291 BerElement *berptr = NULL;
292 char *attr, *dn;
294 if (msg_count == count) {
295 /* hmm, got too many? */
296 ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
297 break;
300 (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message);
301 if (!(*res)[msg_count]) {
302 goto failed;
304 (*res)[msg_count+1] = NULL;
306 dn = ldap_get_dn(lldb->ldap, msg);
307 if (!dn) {
308 goto failed;
311 (*res)[msg_count]->dn = ldb_strdup(ldb, dn);
312 ldap_memfree(dn);
313 if (!(*res)[msg_count]->dn) {
314 goto failed;
318 (*res)[msg_count]->num_elements = 0;
319 (*res)[msg_count]->elements = NULL;
320 (*res)[msg_count]->private_data = NULL;
322 /* loop over all attributes */
323 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
324 attr;
325 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
326 struct berval **bval;
327 bval = ldap_get_values_len(lldb->ldap, msg, attr);
329 if (bval) {
330 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
331 ldap_value_free_len(bval);
334 ldap_memfree(attr);
336 if (berptr) ber_free(berptr, 0);
338 msg_count++;
341 ldap_msgfree(ldapres);
343 return msg_count;
345 failed:
346 if (*res) lldb_search_free(module, *res);
347 return -1;
352 free a set of mods from lldb_msg_to_mods()
354 static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods)
356 int i, j;
358 if (!mods) return;
360 for (i=0;mods[i];i++) {
361 if (mods[i]->mod_vals.modv_bvals) {
362 for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
363 ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]);
365 ldb_free(ldb, mods[i]->mod_vals.modv_bvals);
367 ldb_free(ldb, mods[i]);
369 ldb_free(ldb, mods);
374 convert a ldb_message structure to a list of LDAPMod structures
375 ready for ldap_add() or ldap_modify()
377 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
378 const struct ldb_message *msg, int use_flags)
380 LDAPMod **mods;
381 unsigned int i, j;
382 int num_mods = 0;
384 /* allocate maximum number of elements needed */
385 mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1);
386 if (!mods) {
387 errno = ENOMEM;
388 return NULL;
390 mods[0] = NULL;
392 for (i=0;i<msg->num_elements;i++) {
393 const struct ldb_message_element *el = &msg->elements[i];
395 mods[num_mods] = ldb_malloc_p(ldb, LDAPMod);
396 if (!mods[num_mods]) {
397 goto failed;
399 mods[num_mods+1] = NULL;
400 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
401 if (use_flags) {
402 switch (el->flags & LDB_FLAG_MOD_MASK) {
403 case LDB_FLAG_MOD_ADD:
404 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
405 break;
406 case LDB_FLAG_MOD_DELETE:
407 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
408 break;
409 case LDB_FLAG_MOD_REPLACE:
410 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
411 break;
414 mods[num_mods]->mod_type = el->name;
415 mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb,
416 struct berval *,
417 1+el->num_values);
418 if (!mods[num_mods]->mod_vals.modv_bvals) {
419 goto failed;
422 for (j=0;j<el->num_values;j++) {
423 mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval);
424 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
425 goto failed;
427 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
428 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
430 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
431 num_mods++;
434 return mods;
436 failed:
437 lldb_mods_free(ldb, mods);
438 return NULL;
443 add a record
445 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
447 struct ldb_context *ldb = module->ldb;
448 struct lldb_private *lldb = module->private_data;
449 LDAPMod **mods;
450 int ret = 0;
452 /* ignore ltdb specials */
453 if (msg->dn[0] == '@') {
454 return 0;
457 mods = lldb_msg_to_mods(ldb, msg, 0);
459 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
460 if (lldb->last_rc != LDAP_SUCCESS) {
461 ret = -1;
464 lldb_mods_free(ldb, mods);
466 return ret;
471 modify a record
473 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
475 struct ldb_context *ldb = module->ldb;
476 struct lldb_private *lldb = module->private_data;
477 LDAPMod **mods;
478 int ret = 0;
480 /* ignore ltdb specials */
481 if (msg->dn[0] == '@') {
482 return 0;
485 mods = lldb_msg_to_mods(ldb, msg, 1);
487 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
488 if (lldb->last_rc != LDAP_SUCCESS) {
489 ret = -1;
492 lldb_mods_free(ldb, mods);
494 return ret;
499 return extended error information
501 static const char *lldb_errstring(struct ldb_module *module)
503 struct lldb_private *lldb = module->private_data;
504 return ldap_err2string(lldb->last_rc);
508 static const struct ldb_module_ops lldb_ops = {
509 "ldap",
510 lldb_close,
511 lldb_search,
512 lldb_search_free,
513 lldb_add,
514 lldb_modify,
515 lldb_delete,
516 lldb_rename,
517 lldb_errstring
522 connect to the database
524 struct ldb_context *lldb_connect(const char *url,
525 unsigned int flags,
526 const char *options[])
528 struct ldb_context *ldb = NULL;
529 struct lldb_private *lldb = NULL;
530 int i, version = 3;
532 ldb = calloc(1, sizeof(struct ldb_context));
533 if (!ldb) {
534 errno = ENOMEM;
535 goto failed;
538 lldb = ldb_malloc_p(ldb, struct lldb_private);
539 if (!lldb) {
540 ldb_free(ldb, ldb);
541 errno = ENOMEM;
542 goto failed;
545 lldb->ldap = NULL;
546 lldb->options = NULL;
548 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
549 if (lldb->last_rc != LDAP_SUCCESS) {
550 goto failed;
553 lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
554 if (lldb->last_rc != LDAP_SUCCESS) {
555 goto failed;
558 ldb->modules = ldb_malloc_p(ldb, struct ldb_module);
559 if (!ldb->modules) {
560 ldb_free(ldb, ldb);
561 errno = ENOMEM;
562 goto failed;
564 ldb->modules->ldb = ldb;
565 ldb->modules->prev = ldb->modules->next = NULL;
566 ldb->modules->private_data = lldb;
567 ldb->modules->ops = &lldb_ops;
569 if (options) {
570 /* take a copy of the options array, so we don't have to rely
571 on the caller keeping it around (it might be dynamic) */
572 for (i=0;options[i];i++) ;
574 lldb->options = ldb_malloc_array_p(ldb, char *, i+1);
575 if (!lldb->options) {
576 goto failed;
579 for (i=0;options[i];i++) {
580 lldb->options[i+1] = NULL;
581 lldb->options[i] = ldb_strdup(ldb, options[i]);
582 if (!lldb->options[i]) {
583 goto failed;
588 return ldb;
590 failed:
591 if (lldb && lldb->options) {
592 for (i=0;lldb->options[i];i++) {
593 ldb_free(ldb, lldb->options[i]);
595 ldb_free(ldb, lldb->options);
597 if (lldb && lldb->ldap) {
598 ldap_unbind(lldb->ldap);
600 ldb_free(ldb, lldb);
601 if (ldb) free(ldb);
602 return NULL;