r10299: remove the public (un)lock functions and introduce a transaction based
[kai/samba.git] / source4 / lib / ldb / ldb_ildap / ldb_ildap.c
1 /* 
2    ldb database library - ildap backend
3
4    Copyright (C) Andrew Tridgell  2005
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   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
28   library
29 */
30
31
32 #include "includes.h"
33 #include "ldb/include/ldb.h"
34 #include "ldb/include/ldb_private.h"
35 #include "libcli/ldap/ldap.h"
36 #include "libcli/ldap/ldap_client.h"
37 #include "lib/cmdline/popt_common.h"
38
39 struct ildb_private {
40         struct ldap_connection *ldap;
41         NTSTATUS last_rc;
42         struct ldb_message *rootDSE;
43 };
44
45 /*
46   rename a record
47 */
48 static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
49 {
50         TALLOC_CTX *local_ctx;
51         struct ildb_private *ildb = module->private_data;
52         int ret = 0;
53         char *old_dn;
54         char *newrdn, *parentdn;
55
56         /* ignore ltdb specials */
57         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
58                 return 0;
59         }
60
61         local_ctx = talloc_named(ildb, 0, "ildb_rename local context");
62         if (local_ctx == NULL) {
63                 return -1;
64         }
65
66         old_dn = ldb_dn_linearize(local_ctx, olddn);
67         if (old_dn == NULL) {
68                 goto failed;
69         }
70
71         newrdn = talloc_asprintf(local_ctx, "%s=%s",
72                                             newdn->components[0].name,
73                                             ldb_dn_escape_value(ildb, newdn->components[0].value));
74         if (newrdn == NULL) {
75                 goto failed;
76         }
77
78         parentdn = ldb_dn_linearize(local_ctx, ldb_dn_get_parent(ildb, newdn));
79         if (parentdn == NULL) {
80                 goto failed;
81         }
82
83         ildb->last_rc = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True);
84         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
85                 ret = -1;
86         }
87
88         talloc_free(local_ctx);
89         return ret;
90
91 failed:
92         talloc_free(local_ctx);
93         return -1;
94 }
95
96 /*
97   delete a record
98 */
99 static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn)
100 {
101         struct ildb_private *ildb = module->private_data;
102         char *del_dn;
103         int ret = 0;
104
105         /* ignore ltdb specials */
106         if (ldb_dn_is_special(dn)) {
107                 return 0;
108         }
109         
110         del_dn = ldb_dn_linearize(ildb, dn);
111
112         ildb->last_rc = ildap_delete(ildb->ldap, del_dn);
113         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
114                 ret = -1;
115         }
116
117         talloc_free(del_dn);
118
119         return ret;
120 }
121
122
123 static void ildb_rootdse(struct ldb_module *module);
124
125 /*
126   search for matching records
127 */
128 static int ildb_search(struct ldb_module *module, const struct ldb_dn *base,
129                        enum ldb_scope scope, const char *expression,
130                        const char * const *attrs, struct ldb_message ***res)
131 {
132         struct ildb_private *ildb = module->private_data;
133         int count, i;
134         struct ldap_message **ldapres, *msg;
135         char *search_base;
136
137         if (scope == LDB_SCOPE_DEFAULT) {
138                 scope = LDB_SCOPE_SUBTREE;
139         }
140         
141         if (base == NULL) {
142                 if (ildb->rootDSE == NULL) {
143                         ildb_rootdse(module);
144                 }
145                 if (ildb->rootDSE != NULL) {
146                         search_base = talloc_strdup(ildb,
147                                                 ldb_msg_find_string(ildb->rootDSE, 
148                                                                 "defaultNamingContext", ""));
149                 } else {
150                         search_base = talloc_strdup(ildb, "");
151                 }
152         } else {
153                 search_base = ldb_dn_linearize(ildb, base);
154         }
155         if (search_base == NULL) {
156                 return -1;
157         }
158
159         if (expression == NULL || expression[0] == '\0') {
160                 expression = "objectClass=*";
161         }
162
163         ildb->last_rc = ildap_search(ildb->ldap, search_base, scope, expression, attrs, 
164                                      0, &ldapres);
165         talloc_free(search_base);
166         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
167                 return -1;
168         }
169
170         count = ildap_count_entries(ildb->ldap, ldapres);
171         if (count == -1 || count == 0) {
172                 talloc_free(ldapres);
173                 return count;
174         }
175
176         (*res) = talloc_array(ildb, struct ldb_message *, count+1);
177         if (! *res) {
178                 talloc_free(ldapres);
179                 return -1;
180         }
181
182         (*res)[0] = NULL;
183
184         /* loop over all messages */
185         for (i=0;i<count;i++) {
186                 struct ldap_SearchResEntry *search;
187
188                 msg = ldapres[i];
189                 search = &msg->r.SearchResultEntry;
190
191                 (*res)[i] = talloc(*res, struct ldb_message);
192                 if (!(*res)[i]) {
193                         goto failed;
194                 }
195                 (*res)[i+1] = NULL;
196
197                 (*res)[i]->dn = ldb_dn_explode((*res)[i], search->dn);
198                 if ((*res)[i]->dn == NULL) {
199                         goto failed;
200                 }
201                 (*res)[i]->num_elements = search->num_attributes;
202                 (*res)[i]->elements = talloc_steal((*res)[i], search->attributes);
203                 (*res)[i]->private_data = NULL;
204         }
205
206         talloc_free(ldapres);
207
208         return count;
209
210 failed:
211         if (*res) talloc_free(*res);
212         return -1;
213 }
214
215
216 /*
217   search for matching records using a ldb_parse_tree
218 */
219 static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
220                               enum ldb_scope scope, struct ldb_parse_tree *tree,
221                               const char * const *attrs, struct ldb_message ***res)
222 {
223         struct ildb_private *ildb = module->private_data;
224         char *expression;
225         int ret;
226
227         expression = ldb_filter_from_tree(ildb, tree);
228         if (expression == NULL) {
229                 return -1;
230         }
231         ret = ildb_search(module, base, scope, expression, attrs, res);
232         talloc_free(expression);
233         return ret;
234 }
235
236
237 /*
238   convert a ldb_message structure to a list of ldap_mod structures
239   ready for ildap_add() or ildap_modify()
240 */
241 static struct ldap_mod **ildb_msg_to_mods(struct ldb_context *ldb,
242                                           const struct ldb_message *msg, int use_flags)
243 {
244         struct ldap_mod **mods;
245         unsigned int i;
246         int num_mods = 0;
247
248         /* allocate maximum number of elements needed */
249         mods = talloc_array(ldb, struct ldap_mod *, msg->num_elements+1);
250         if (!mods) {
251                 errno = ENOMEM;
252                 return NULL;
253         }
254         mods[0] = NULL;
255
256         for (i=0;i<msg->num_elements;i++) {
257                 const struct ldb_message_element *el = &msg->elements[i];
258
259                 mods[num_mods] = talloc(ldb, struct ldap_mod);
260                 if (!mods[num_mods]) {
261                         goto failed;
262                 }
263                 mods[num_mods+1] = NULL;
264                 mods[num_mods]->type = 0;
265                 mods[num_mods]->attrib = *el;
266                 if (use_flags) {
267                         switch (el->flags & LDB_FLAG_MOD_MASK) {
268                         case LDB_FLAG_MOD_ADD:
269                                 mods[num_mods]->type = LDAP_MODIFY_ADD;
270                                 break;
271                         case LDB_FLAG_MOD_DELETE:
272                                 mods[num_mods]->type = LDAP_MODIFY_DELETE;
273                                 break;
274                         case LDB_FLAG_MOD_REPLACE:
275                                 mods[num_mods]->type = LDAP_MODIFY_REPLACE;
276                                 break;
277                         }
278                 }
279                 num_mods++;
280         }
281
282         return mods;
283
284 failed:
285         talloc_free(mods);
286         return NULL;
287 }
288
289
290 /*
291   add a record
292 */
293 static int ildb_add(struct ldb_module *module, const struct ldb_message *msg)
294 {
295         struct ldb_context *ldb = module->ldb;
296         struct ildb_private *ildb = module->private_data;
297         struct ldap_mod **mods;
298         char *dn;
299         int ret = 0;
300
301         /* ignore ltdb specials */
302         if (ldb_dn_is_special(msg->dn)) {
303                 return 0;
304         }
305
306         mods = ildb_msg_to_mods(ldb, msg, 0);
307         if (mods == NULL) {
308                 return -1;
309         }
310
311         dn = ldb_dn_linearize(mods, msg->dn);
312         if (dn == NULL) {
313                 talloc_free(mods);
314                 return -1;
315         }
316
317         ildb->last_rc = ildap_add(ildb->ldap, dn, mods);
318         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
319                 ret = -1;
320         }
321
322         talloc_free(mods);
323
324         return ret;
325 }
326
327
328 /*
329   modify a record
330 */
331 static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg)
332 {
333         struct ldb_context *ldb = module->ldb;
334         struct ildb_private *ildb = module->private_data;
335         struct ldap_mod **mods;
336         char *dn;
337         int ret = 0;
338
339         /* ignore ltdb specials */
340         if (ldb_dn_is_special(msg->dn)) {
341                 return 0;
342         }
343
344         mods = ildb_msg_to_mods(ldb, msg, 1);
345         if (mods == NULL) {
346                 return -1;
347         }
348
349         dn = ldb_dn_linearize(mods, msg->dn);
350         if (dn == NULL) {
351                 talloc_free(mods);
352                 return -1;
353         }
354
355         ildb->last_rc = ildap_modify(ildb->ldap, dn, mods);
356         if (!NT_STATUS_IS_OK(ildb->last_rc)) {
357                 ret = -1;
358         }
359
360         talloc_free(mods);
361
362         return ret;
363 }
364
365 static int ildb_start_trans(struct ldb_module *module)
366 {
367         /* TODO implement a local locking mechanism here */
368
369         return 0;
370 }
371
372 static int ildb_end_trans(struct ldb_module *module, int status)
373 {
374         /* TODO implement a local transaction mechanism here */
375
376         return status;
377 }
378
379 /*
380   return extended error information
381 */
382 static const char *ildb_errstring(struct ldb_module *module)
383 {
384         struct ildb_private *ildb = talloc_get_type(module->private_data, 
385                                                     struct ildb_private);
386         if (ildb == NULL) {
387                 return "ildap not connected";
388         }
389         return ldap_errstr(ildb->ldap, ildb->last_rc);
390 }
391
392
393 static const struct ldb_module_ops ildb_ops = {
394         .name              = "ldap",
395         .search            = ildb_search,
396         .search_bytree     = ildb_search_bytree,
397         .add_record        = ildb_add,
398         .modify_record     = ildb_modify,
399         .delete_record     = ildb_delete,
400         .rename_record     = ildb_rename,
401         .start_transaction = ildb_start_trans,
402         .end_transaction   = ildb_end_trans,
403         .errstring         = ildb_errstring
404 };
405
406
407 /*
408   fetch the rootDSE
409 */
410 static void ildb_rootdse(struct ldb_module *module)
411 {
412         struct ildb_private *ildb = module->private_data;
413         struct ldb_message **res = NULL;
414         struct ldb_dn *empty_dn = ldb_dn_new(ildb);
415         int ret;
416         ret = ildb_search(module, empty_dn, LDB_SCOPE_BASE, "dn=dc=rootDSE", NULL, &res);
417         if (ret == 1) {
418                 ildb->rootDSE = talloc_steal(ildb, res[0]);
419         }
420         if (ret != -1) talloc_free(res);
421         talloc_free(empty_dn);
422 }
423
424
425 /*
426   connect to the database
427 */
428 int ildb_connect(struct ldb_context *ldb, const char *url, 
429                  unsigned int flags, const char *options[])
430 {
431         struct ildb_private *ildb = NULL;
432         NTSTATUS status;
433
434         ildb = talloc(ldb, struct ildb_private);
435         if (!ildb) {
436                 ldb_oom(ldb);
437                 goto failed;
438         }
439
440         ildb->rootDSE = NULL;
441
442         ildb->ldap = ldap_new_connection(ildb, ldb_get_opaque(ldb, "EventContext"));
443         if (!ildb->ldap) {
444                 ldb_oom(ldb);
445                 goto failed;
446         }
447
448         status = ldap_connect(ildb->ldap, url);
449         if (!NT_STATUS_IS_OK(status)) {
450                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s\n",
451                           url, ldap_errstr(ildb->ldap, status));
452                 goto failed;
453         }
454
455         ldb->modules = talloc(ldb, struct ldb_module);
456         if (!ldb->modules) {
457                 ldb_oom(ldb);
458                 goto failed;
459         }
460         ldb->modules->ldb = ldb;
461         ldb->modules->prev = ldb->modules->next = NULL;
462         ldb->modules->private_data = ildb;
463         ldb->modules->ops = &ildb_ops;
464
465         if (cmdline_credentials != NULL && cli_credentials_authentication_requested(cmdline_credentials)) {
466                 status = ldap_bind_sasl(ildb->ldap, cmdline_credentials);
467                 if (!NT_STATUS_IS_OK(status)) {
468                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
469                                   ldap_errstr(ildb->ldap, status));
470                         goto failed;
471                 }
472         }
473
474         return 0;
475
476 failed:
477         if (ldb->modules) {
478                 ldb->modules->private_data = NULL;
479         }
480         talloc_free(ildb);
481         return -1;
482 }
483