r6470: Remove ldb_search_free() it is not needed anymore.
[samba.git] / source / lib / ldb / ldb_ldap / ldb_ldap.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
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
9    
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.
14
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.
19
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
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb ldap backend
29  *
30  *  Description: core files for LDAP backend
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_ldap/ldb_ldap.h"
39
40 #if 0
41 /*
42   we don't need this right now, but will once we add some backend 
43   options
44 */
45
46 /*
47   find an option in an option list (a null terminated list of strings)
48
49   this assumes the list is short. If it ever gets long then we really
50   should do this in some smarter way
51  */
52 static const char *lldb_option_find(const struct lldb_private *lldb, const char *name)
53 {
54         int i;
55         size_t len = strlen(name);
56
57         if (!lldb->options) return NULL;
58
59         for (i=0;lldb->options[i];i++) {                
60                 if (strncmp(lldb->options[i], name, len) == 0 &&
61                     lldb->options[i][len] == '=') {
62                         return &lldb->options[i][len+1];
63                 }
64         }
65
66         return NULL;
67 }
68 #endif
69
70 /*
71   rename a record
72 */
73 static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
74 {
75         struct lldb_private *lldb = module->private_data;
76         int ret = 0;
77         char *newrdn, *p;
78         const char *parentdn = "";
79         TALLOC_CTX *mem_ctx = talloc_new(lldb);
80
81         /* ignore ltdb specials */
82         if (olddn[0] == '@' ||newdn[0] == '@') {
83                 return 0;
84         }
85
86         newrdn = talloc_strdup(mem_ctx, newdn);
87         if (!newrdn) {
88                 return -1;
89         }
90
91         p = strchr(newrdn, ',');
92         if (p) {
93                 *p++ = '\0';
94                 parentdn = p;
95         }
96
97         lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL);
98         if (lldb->last_rc != LDAP_SUCCESS) {
99                 ret = -1;
100         }
101
102         talloc_free(mem_ctx);
103
104         return ret;
105 }
106
107 /*
108   delete a record
109 */
110 static int lldb_delete(struct ldb_module *module, const char *dn)
111 {
112         struct lldb_private *lldb = module->private_data;
113         int ret = 0;
114
115         /* ignore ltdb specials */
116         if (dn[0] == '@') {
117                 return 0;
118         }
119         
120         lldb->last_rc = ldap_delete_s(lldb->ldap, dn);
121         if (lldb->last_rc != LDAP_SUCCESS) {
122                 ret = -1;
123         }
124
125         return ret;
126 }
127
128 /*
129   add a single set of ldap message values to a ldb_message
130 */
131 static int lldb_add_msg_attr(struct ldb_context *ldb,
132                              struct ldb_message *msg, 
133                              const char *attr, struct berval **bval)
134 {
135         int count, i;
136         struct ldb_message_element *el;
137
138         count = ldap_count_values_len(bval);
139
140         if (count <= 0) {
141                 return -1;
142         }
143
144         el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
145                               msg->num_elements + 1);
146         if (!el) {
147                 errno = ENOMEM;
148                 return -1;
149         }
150
151         msg->elements = el;
152
153         el = &msg->elements[msg->num_elements];
154
155         el->name = talloc_strdup(msg->elements, attr);
156         if (!el->name) {
157                 errno = ENOMEM;
158                 return -1;
159         }
160         el->flags = 0;
161
162         el->num_values = 0;
163         el->values = talloc_array(msg->elements, struct ldb_val, count);
164         if (!el->values) {
165                 errno = ENOMEM;
166                 return -1;
167         }
168
169         for (i=0;i<count;i++) {
170                 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
171                 if (!el->values[i].data) {
172                         return -1;
173                 }
174                 el->values[i].length = bval[i]->bv_len;
175                 el->num_values++;
176         }
177
178         msg->num_elements++;
179
180         return 0;
181 }
182
183 /*
184   search for matching records
185 */
186 static int lldb_search(struct ldb_module *module, const char *base,
187                        enum ldb_scope scope, const char *expression,
188                        const char * const *attrs, struct ldb_message ***res)
189 {
190         struct ldb_context *ldb = module->ldb;
191         struct lldb_private *lldb = module->private_data;
192         int count, msg_count;
193         LDAPMessage *ldapres, *msg;
194
195         if (base == NULL) {
196                 base = "";
197         }
198
199         lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, 
200                                       expression, 
201                                       discard_const_p(char *, attrs), 
202                                       0, &ldapres);
203         if (lldb->last_rc != LDAP_SUCCESS) {
204                 return -1;
205         }
206
207         count = ldap_count_entries(lldb->ldap, ldapres);
208         if (count == -1 || count == 0) {
209                 ldap_msgfree(ldapres);
210                 return count;
211         }
212
213         (*res) = talloc_array(lldb, struct ldb_message *, count+1);
214         if (! *res) {
215                 ldap_msgfree(ldapres);
216                 errno = ENOMEM;
217                 return -1;
218         }
219
220         (*res)[0] = NULL;
221
222         msg_count = 0;
223
224         /* loop over all messages */
225         for (msg=ldap_first_entry(lldb->ldap, ldapres); 
226              msg; 
227              msg=ldap_next_entry(lldb->ldap, msg)) {
228                 BerElement *berptr = NULL;
229                 char *attr, *dn;
230
231                 if (msg_count == count) {
232                         /* hmm, got too many? */
233                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
234                         break;
235                 }
236
237                 (*res)[msg_count] = talloc(*res, struct ldb_message);
238                 if (!(*res)[msg_count]) {
239                         goto failed;
240                 }
241                 (*res)[msg_count+1] = NULL;
242
243                 dn = ldap_get_dn(lldb->ldap, msg);
244                 if (!dn) {
245                         goto failed;
246                 }
247
248                 (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
249                 ldap_memfree(dn);
250                 if (!(*res)[msg_count]->dn) {
251                         goto failed;
252                 }
253
254
255                 (*res)[msg_count]->num_elements = 0;
256                 (*res)[msg_count]->elements = NULL;
257                 (*res)[msg_count]->private_data = NULL;
258
259                 /* loop over all attributes */
260                 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
261                      attr;
262                      attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
263                         struct berval **bval;
264                         bval = ldap_get_values_len(lldb->ldap, msg, attr);
265
266                         if (bval) {
267                                 lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
268                                 ldap_value_free_len(bval);
269                         }                                         
270                         
271                         ldap_memfree(attr);
272                 }
273                 if (berptr) ber_free(berptr, 0);
274
275                 msg_count++;
276         }
277
278         ldap_msgfree(ldapres);
279
280         return msg_count;
281
282 failed:
283         if (*res) talloc_free(*res);
284         return -1;
285 }
286
287
288 /*
289   convert a ldb_message structure to a list of LDAPMod structures
290   ready for ldap_add() or ldap_modify()
291 */
292 static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
293                                   const struct ldb_message *msg, int use_flags)
294 {
295         LDAPMod **mods;
296         unsigned int i, j;
297         int num_mods = 0;
298
299         /* allocate maximum number of elements needed */
300         mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1);
301         if (!mods) {
302                 errno = ENOMEM;
303                 return NULL;
304         }
305         mods[0] = NULL;
306
307         for (i=0;i<msg->num_elements;i++) {
308                 const struct ldb_message_element *el = &msg->elements[i];
309
310                 mods[num_mods] = talloc(ldb, LDAPMod);
311                 if (!mods[num_mods]) {
312                         goto failed;
313                 }
314                 mods[num_mods+1] = NULL;
315                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
316                 if (use_flags) {
317                         switch (el->flags & LDB_FLAG_MOD_MASK) {
318                         case LDB_FLAG_MOD_ADD:
319                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
320                                 break;
321                         case LDB_FLAG_MOD_DELETE:
322                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
323                                 break;
324                         case LDB_FLAG_MOD_REPLACE:
325                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
326                                 break;
327                         }
328                 }
329                 mods[num_mods]->mod_type = el->name;
330                 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], 
331                                                                      struct berval *,
332                                                                      1+el->num_values);
333                 if (!mods[num_mods]->mod_vals.modv_bvals) {
334                         goto failed;
335                 }
336
337                 for (j=0;j<el->num_values;j++) {
338                         mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
339                                                                           struct berval);
340                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
341                                 goto failed;
342                         }
343                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
344                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
345                 }
346                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
347                 num_mods++;
348         }
349
350         return mods;
351
352 failed:
353         talloc_free(mods);
354         return NULL;
355 }
356
357
358 /*
359   add a record
360 */
361 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
362 {
363         struct ldb_context *ldb = module->ldb;
364         struct lldb_private *lldb = module->private_data;
365         LDAPMod **mods;
366         int ret = 0;
367
368         /* ignore ltdb specials */
369         if (msg->dn[0] == '@') {
370                 return 0;
371         }
372
373         mods = lldb_msg_to_mods(ldb, msg, 0);
374
375         lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
376         if (lldb->last_rc != LDAP_SUCCESS) {
377                 ret = -1;
378         }
379
380         talloc_free(mods);
381
382         return ret;
383 }
384
385
386 /*
387   modify a record
388 */
389 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
390 {
391         struct ldb_context *ldb = module->ldb;
392         struct lldb_private *lldb = module->private_data;
393         LDAPMod **mods;
394         int ret = 0;
395
396         /* ignore ltdb specials */
397         if (msg->dn[0] == '@') {
398                 return 0;
399         }
400
401         mods = lldb_msg_to_mods(ldb, msg, 1);
402
403         lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
404         if (lldb->last_rc != LDAP_SUCCESS) {
405                 ret = -1;
406         }
407
408         talloc_free(mods);
409
410         return ret;
411 }
412
413 static int lldb_lock(struct ldb_module *module, const char *lockname)
414 {
415         int ret = 0;
416
417         if (lockname == NULL) {
418                 return -1;
419         }
420
421         /* TODO implement a local locking mechanism here */
422
423         return ret;
424 }
425
426 static int lldb_unlock(struct ldb_module *module, const char *lockname)
427 {
428         int ret = 0;
429
430         if (lockname == NULL) {
431                 return -1;
432         }
433
434         /* TODO implement a local unlocking mechanism here */
435
436         return ret;
437 }
438
439 /*
440   return extended error information
441 */
442 static const char *lldb_errstring(struct ldb_module *module)
443 {
444         struct lldb_private *lldb = module->private_data;
445         return ldap_err2string(lldb->last_rc);
446 }
447
448
449 static const struct ldb_module_ops lldb_ops = {
450         "ldap",
451         lldb_search,
452         lldb_add,
453         lldb_modify,
454         lldb_delete,
455         lldb_rename,
456         lldb_lock,
457         lldb_unlock,
458         lldb_errstring
459 };
460
461
462 static int lldb_destructor(void *p)
463 {
464         struct lldb_private *lldb = p;
465         ldap_unbind(lldb->ldap);
466         return 0;
467 }
468
469 /*
470   connect to the database
471 */
472 struct ldb_context *lldb_connect(const char *url, 
473                                  unsigned int flags, 
474                                  const char *options[])
475 {
476         struct ldb_context *ldb = NULL;
477         struct lldb_private *lldb = NULL;
478         int i, version = 3;
479
480         ldb = talloc(NULL, struct ldb_context);
481         if (!ldb) {
482                 errno = ENOMEM;
483                 goto failed;
484         }
485
486         lldb = talloc(ldb, struct lldb_private);
487         if (!lldb) {
488                 errno = ENOMEM;
489                 goto failed;
490         }
491
492         lldb->ldap = NULL;
493         lldb->options = NULL;
494
495         lldb->last_rc = ldap_initialize(&lldb->ldap, url);
496         if (lldb->last_rc != LDAP_SUCCESS) {
497                 goto failed;
498         }
499
500         talloc_set_destructor(lldb, lldb_destructor);
501
502         lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
503         if (lldb->last_rc != LDAP_SUCCESS) {
504                 goto failed;
505         }
506
507         ldb->modules = talloc(ldb, struct ldb_module);
508         if (!ldb->modules) {
509                 errno = ENOMEM;
510                 goto failed;
511         }
512         ldb->modules->ldb = ldb;
513         ldb->modules->prev = ldb->modules->next = NULL;
514         ldb->modules->private_data = lldb;
515         ldb->modules->ops = &lldb_ops;
516
517         if (options) {
518                 /* take a copy of the options array, so we don't have to rely
519                    on the caller keeping it around (it might be dynamic) */
520                 for (i=0;options[i];i++) ;
521
522                 lldb->options = talloc_array(lldb, char *, i+1);
523                 if (!lldb->options) {
524                         goto failed;
525                 }
526                 
527                 for (i=0;options[i];i++) {
528                         lldb->options[i+1] = NULL;
529                         lldb->options[i] = talloc_strdup(lldb->options, options[i]);
530                         if (!lldb->options[i]) {
531                                 goto failed;
532                         }
533                 }
534         }
535
536         return ldb;
537
538 failed:
539         talloc_free(ldb);
540         return NULL;
541 }
542