r141: A number of changes to get things working on FreeBSD and reduce the breakage
[Samba/gebeck_regimport.git] / source4 / lib / ldb / ldb_ldap / ldb_ldap.c
blob25dad914da44a75755d1f1b0af3af34fa73e7693
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 #if HAVE_LDAP
37 #include "ldb_ldap.h"
39 #if 0
41 we don't need this right now, but will once we add some backend
42 options
46 find an option in an option list (a null terminated list of strings)
48 this assumes the list is short. If it ever gets long then we really
49 should do this in some smarter way
51 static const char *lldb_option_find(const struct lldb_private *lldb, const char *name)
53 int i;
54 size_t len = strlen(name);
56 if (!lldb->options) return NULL;
58 for (i=0;lldb->options[i];i++) {
59 if (strncmp(lldb->options[i], name, len) == 0 &&
60 lldb->options[i][len] == '=') {
61 return &lldb->options[i][len+1];
65 return NULL;
67 #endif
70 close/free the connection
72 static int lldb_close(struct ldb_context *ldb)
74 int i, ret = 0;
75 struct lldb_private *lldb = ldb->private;
77 if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
78 ret = -1;
81 if (lldb->options) {
82 for (i=0;lldb->options[i];i++) {
83 free(lldb->options[i]);
85 free(lldb->options);
87 free(lldb);
88 free(ldb);
90 return ret;
94 delete a record
96 static int lldb_delete(struct ldb_context *ldb, const char *dn)
98 struct lldb_private *lldb = ldb->private;
99 int ret = 0;
101 lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
102 if (lldb->last_rc != LDAP_SUCCESS) {
103 ret = -1;
106 return ret;
110 free a search message
112 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
114 int i, j;
115 free(msg->dn);
116 for (i=0;i<msg->num_elements;i++) {
117 free(msg->elements[i].name);
118 for (j=0;j<msg->elements[i].num_values;j++) {
119 if (msg->elements[i].values[j].data) {
120 free(msg->elements[i].values[j].data);
123 free(msg->elements[i].values);
125 if (msg->elements) free(msg->elements);
126 free(msg);
127 return 0;
131 free a search result
133 static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res)
135 int i;
136 for (i=0;res[i];i++) {
137 if (lldb_msg_free(ldb, res[i]) != 0) {
138 return -1;
141 free(res);
142 return 0;
147 add a single set of ldap message values to a ldb_message
149 static int lldb_add_msg_attr(struct ldb_message *msg,
150 const char *attr, struct berval **bval)
152 int count, i;
153 struct ldb_message_element *el;
155 count = ldap_count_values_len(bval);
157 if (count <= 0) {
158 return -1;
161 el = realloc_p(msg->elements, struct ldb_message_element,
162 msg->num_elements + 1);
163 if (!el) {
164 errno = ENOMEM;
165 return -1;
168 msg->elements = el;
170 el = &msg->elements[msg->num_elements];
172 el->name = strdup(attr);
173 if (!el->name) {
174 errno = ENOMEM;
175 return -1;
177 el->flags = 0;
179 el->num_values = 0;
180 el->values = malloc_array_p(struct ldb_val, count);
181 if (!el->values) {
182 errno = ENOMEM;
183 return -1;
186 for (i=0;i<count;i++) {
187 el->values[i].data = malloc(bval[i]->bv_len);
188 if (!el->values[i].data) {
189 return -1;
191 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
192 el->values[i].length = bval[i]->bv_len;
193 el->num_values++;
196 msg->num_elements++;
198 return 0;
202 search for matching records
204 static int lldb_search(struct ldb_context *ldb, const char *base,
205 enum ldb_scope scope, const char *expression,
206 const char **attrs, struct ldb_message ***res)
208 struct lldb_private *lldb = ldb->private;
209 int count, msg_count;
210 LDAPMessage *ldapres, *msg;
212 lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope,
213 expression, attrs, 0, &ldapres);
214 if (lldb->last_rc != LDAP_SUCCESS) {
215 return -1;
218 count = ldap_count_entries(lldb->ldap, ldapres);
219 if (count == -1 || count == 0) {
220 ldap_msgfree(ldapres);
221 return count;
224 (*res) = malloc_array_p(struct ldb_message *, count+1);
225 if (! *res) {
226 ldap_msgfree(ldapres);
227 errno = ENOMEM;
228 return -1;
231 (*res)[0] = NULL;
233 msg_count = 0;
235 /* loop over all messages */
236 for (msg=ldap_first_entry(lldb->ldap, ldapres);
237 msg;
238 msg=ldap_next_entry(lldb->ldap, msg)) {
239 BerElement *berptr = NULL;
240 char *attr, *dn;
242 if (msg_count == count) {
243 /* hmm, got too many? */
244 fprintf(stderr,"Too many messages?!\n");
245 break;
248 (*res)[msg_count] = malloc_p(struct ldb_message);
249 if (!(*res)[msg_count]) {
250 goto failed;
252 (*res)[msg_count+1] = NULL;
254 dn = ldap_get_dn(lldb->ldap, msg);
255 if (!dn) {
256 goto failed;
259 (*res)[msg_count]->dn = strdup(dn);
260 ldap_memfree(dn);
261 if (!(*res)[msg_count]->dn) {
262 goto failed;
266 (*res)[msg_count]->num_elements = 0;
267 (*res)[msg_count]->elements = NULL;
268 (*res)[msg_count]->private = NULL;
270 /* loop over all attributes */
271 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
272 attr;
273 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
274 struct berval **bval;
275 bval = ldap_get_values_len(lldb->ldap, msg, attr);
277 if (bval) {
278 lldb_add_msg_attr((*res)[msg_count], attr, bval);
279 ldap_value_free_len(bval);
282 ldap_memfree(attr);
284 if (berptr) ber_free(berptr, 0);
286 msg_count++;
289 ldap_msgfree(ldapres);
291 return msg_count;
293 failed:
294 if (*res) lldb_search_free(ldb, *res);
295 return -1;
300 free a set of mods from lldb_msg_to_mods()
302 static void lldb_mods_free(LDAPMod **mods)
304 int i, j;
306 if (!mods) return;
308 for (i=0;mods[i];i++) {
309 if (mods[i]->mod_vals.modv_bvals) {
310 for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
311 free(mods[i]->mod_vals.modv_bvals[j]);
313 free(mods[i]->mod_vals.modv_bvals);
315 free(mods[i]);
317 free(mods);
322 convert a ldb_message structure to a list of LDAPMod structures
323 ready for ldap_add() or ldap_modify()
325 static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
327 LDAPMod **mods;
328 int i, j, num_mods = 0;
330 /* allocate maximum number of elements needed */
331 mods = malloc_array_p(LDAPMod *, msg->num_elements+1);
332 if (!mods) {
333 errno = ENOMEM;
334 return NULL;
336 mods[0] = NULL;
338 for (i=0;i<msg->num_elements;i++) {
339 const struct ldb_message_element *el = &msg->elements[i];
341 mods[num_mods] = malloc_p(LDAPMod);
342 if (!mods[num_mods]) {
343 goto failed;
345 mods[num_mods+1] = NULL;
346 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
347 if (use_flags) {
348 switch (el->flags & LDB_FLAG_MOD_MASK) {
349 case LDB_FLAG_MOD_ADD:
350 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
351 break;
352 case LDB_FLAG_MOD_DELETE:
353 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
354 break;
355 case LDB_FLAG_MOD_REPLACE:
356 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
357 break;
360 mods[num_mods]->mod_type = el->name;
361 mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *,
362 1+el->num_values);
363 if (!mods[num_mods]->mod_vals.modv_bvals) {
364 goto failed;
367 for (j=0;j<el->num_values;j++) {
368 mods[num_mods]->mod_vals.modv_bvals[j] = malloc_p(struct berval);
369 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
370 goto failed;
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;
376 num_mods++;
379 return mods;
381 failed:
382 lldb_mods_free(mods);
383 return NULL;
388 add a record
390 static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
392 struct lldb_private *lldb = ldb->private;
393 LDAPMod **mods;
394 int ret = 0;
396 mods = lldb_msg_to_mods(msg, 0);
398 lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
399 if (lldb->last_rc != LDAP_SUCCESS) {
400 ret = -1;
403 lldb_mods_free(mods);
405 return ret;
410 modify a record
412 static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
414 struct lldb_private *lldb = ldb->private;
415 LDAPMod **mods;
416 int ret = 0;
418 mods = lldb_msg_to_mods(msg, 1);
420 lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
421 if (lldb->last_rc != LDAP_SUCCESS) {
422 ret = -1;
425 lldb_mods_free(mods);
427 return ret;
432 return extended error information
434 static const char *lldb_errstring(struct ldb_context *ldb)
436 struct lldb_private *lldb = ldb->private;
437 return ldap_err2string(lldb->last_rc);
441 static const struct ldb_backend_ops lldb_ops = {
442 lldb_close,
443 lldb_search,
444 lldb_search_free,
445 lldb_add,
446 lldb_modify,
447 lldb_delete,
448 lldb_errstring
453 connect to the database
455 struct ldb_context *lldb_connect(const char *url,
456 unsigned int flags,
457 const char *options[])
459 struct ldb_context *ldb = NULL;
460 struct lldb_private *lldb = NULL;
461 int i;
463 ldb = malloc_p(struct ldb_context);
464 if (!ldb) {
465 errno = ENOMEM;
466 goto failed;
469 lldb = malloc_p(struct lldb_private);
470 if (!lldb) {
471 free(ldb);
472 errno = ENOMEM;
473 goto failed;
476 lldb->ldap = NULL;
477 lldb->options = NULL;
479 lldb->last_rc = ldap_initialize(&lldb->ldap, url);
480 if (lldb->last_rc != LDAP_SUCCESS) {
481 goto failed;
484 ldb->ops = &lldb_ops;
485 ldb->private = lldb;
487 if (options) {
488 /* take a copy of the options array, so we don't have to rely
489 on the caller keeping it around (it might be dynamic) */
490 for (i=0;options[i];i++) ;
492 lldb->options = malloc_array_p(char *, i+1);
493 if (!lldb->options) {
494 goto failed;
497 for (i=0;options[i];i++) {
498 lldb->options[i+1] = NULL;
499 lldb->options[i] = strdup(options[i]);
500 if (!lldb->options[i]) {
501 goto failed;
506 return ldb;
508 failed:
509 if (lldb && lldb->options) {
510 for (i=0;lldb->options[i];i++) {
511 free(lldb->options[i]);
513 free(lldb->options);
515 if (lldb && lldb->ldap) {
516 ldap_unbind(lldb->ldap);
518 if (lldb) free(lldb);
519 if (ldb) free(ldb);
520 return NULL;
522 #endif /*HAVE_LDAP*/