r12829: fix ldb headers, to not include '<...>' files in .c files
[abartlet/samba.git/.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/includes.h"
34
35 #include "libcli/ldap/ldap.h"
36 #include "libcli/ldap/ldap_client.h"
37 #include "lib/cmdline/popt_common.h"
38 #include "auth/auth.h"
39
40 struct ildb_private {
41         struct ldap_connection *ldap;
42         struct ldb_message *rootDSE;
43         struct ldb_context *ldb;
44 };
45
46
47 /*
48   map an ildap NTSTATUS to a ldb error code
49 */
50 static int ildb_map_error(struct ildb_private *ildb, NTSTATUS status)
51 {
52         if (NT_STATUS_IS_OK(status)) {
53                 return LDB_SUCCESS;
54         }
55         talloc_free(ildb->ldb->err_string);
56         ildb->ldb->err_string = talloc_strdup(ildb, ldap_errstr(ildb->ldap, status));
57         if (NT_STATUS_IS_LDAP(status)) {
58                 return NT_STATUS_LDAP_CODE(status);
59         }
60         return LDB_ERR_OPERATIONS_ERROR;
61 }
62
63 /*
64   rename a record
65 */
66 static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
67 {
68         TALLOC_CTX *local_ctx;
69         struct ildb_private *ildb = module->private_data;
70         int ret = 0;
71         char *old_dn;
72         char *newrdn, *parentdn;
73         NTSTATUS status;
74
75         /* ignore ltdb specials */
76         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
77                 return LDB_SUCCESS;
78         }
79
80         local_ctx = talloc_named(ildb, 0, "ildb_rename local context");
81         if (local_ctx == NULL) {
82                 ret = LDB_ERR_OPERATIONS_ERROR;
83                 goto failed;
84         }
85
86         old_dn = ldb_dn_linearize(local_ctx, olddn);
87         if (old_dn == NULL) {
88                 ret = LDB_ERR_INVALID_DN_SYNTAX;
89                 goto failed;
90         }
91
92         newrdn = talloc_asprintf(local_ctx, "%s=%s",
93                                             newdn->components[0].name,
94                                             ldb_dn_escape_value(ildb, newdn->components[0].value));
95         if (newrdn == NULL) {
96                 ret = LDB_ERR_OPERATIONS_ERROR;
97                 goto failed;
98         }
99
100         parentdn = ldb_dn_linearize(local_ctx, ldb_dn_get_parent(ildb, newdn));
101         if (parentdn == NULL) {
102                 ret = LDB_ERR_INVALID_DN_SYNTAX;
103                 goto failed;
104         }
105
106         status = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True);
107         ret = ildb_map_error(ildb, status);
108
109 failed:
110         talloc_free(local_ctx);
111         return ret;
112 }
113
114 /*
115   delete a record
116 */
117 static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn)
118 {
119         struct ildb_private *ildb = module->private_data;
120         char *del_dn;
121         int ret = 0;
122         NTSTATUS status;
123
124         /* ignore ltdb specials */
125         if (ldb_dn_is_special(dn)) {
126                 return LDB_SUCCESS;
127         }
128         
129         del_dn = ldb_dn_linearize(ildb, dn);
130         if (del_dn == NULL) {
131                 return LDB_ERR_INVALID_DN_SYNTAX;
132         }
133
134         status = ildap_delete(ildb->ldap, del_dn);
135         ret = ildb_map_error(ildb, status);
136
137         talloc_free(del_dn);
138
139         return ret;
140 }
141
142
143 static void ildb_rootdse(struct ldb_module *module);
144
145 /*
146   search for matching records using a ldb_parse_tree
147 */
148 static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
149                               enum ldb_scope scope, struct ldb_parse_tree *tree,
150                               const char * const *attrs,
151                               struct ldb_control **control_req,
152                               struct ldb_result **res)
153 {
154         struct ildb_private *ildb = module->private_data;
155         int count, i;
156         struct ldap_message **ldapres, *msg;
157         struct ldap_Control **controls = NULL;
158         char *search_base;
159         NTSTATUS status;
160
161         if (scope == LDB_SCOPE_DEFAULT) {
162                 scope = LDB_SCOPE_SUBTREE;
163         }
164         
165         if (base == NULL) {
166                 if (ildb->rootDSE == NULL) {
167                         ildb_rootdse(module);
168                 }
169                 if (ildb->rootDSE != NULL) {
170                         search_base = talloc_strdup(ildb,
171                                                 ldb_msg_find_string(ildb->rootDSE, 
172                                                                 "defaultNamingContext", ""));
173                 } else {
174                         search_base = talloc_strdup(ildb, "");
175                 }
176         } else {
177                 search_base = ldb_dn_linearize(ildb, base);
178         }
179         if (search_base == NULL) {
180                 ldb_set_errstring(module, talloc_asprintf(module, "Unable to determine baseDN"));
181                 return LDB_ERR_OTHER;
182         }
183         if (tree == NULL) {
184                 ldb_set_errstring(module, talloc_asprintf(module, "Invalid expression parse tree"));
185                 return LDB_ERR_OTHER;
186         }
187
188         (*res) = talloc(ildb, struct ldb_result);
189         if (! *res) {
190                 return LDB_ERR_OTHER;
191         }
192         (*res)->count = 0;
193         (*res)->msgs = NULL;
194         (*res)->controls = NULL;
195
196         status = ildap_search_bytree(ildb->ldap, search_base, scope, tree, attrs, 0,
197                                      (struct ldap_Control **)control_req,
198                                      &controls,
199                                      &ldapres);
200         talloc_free(search_base);
201         if (!NT_STATUS_IS_OK(status)) {
202                 ildb_map_error(ildb, status);
203                 return LDB_ERR_OTHER;
204         }
205
206         count = ildap_count_entries(ildb->ldap, ldapres);
207         if (count == -1) {
208                 talloc_free(ldapres);
209                 return LDB_ERR_OTHER;
210         }
211
212         if (count == 0) {
213                 talloc_free(ldapres);
214                 return LDB_SUCCESS;
215         }
216
217         (*res)->msgs = talloc_array(*res, struct ldb_message *, count + 1);
218         if (! (*res)->msgs) {
219                 talloc_free(ldapres);
220                 return LDB_ERR_OTHER;
221         }
222
223         (*res)->msgs[0] = NULL;
224
225         /* loop over all messages */
226         for (i=0;i<count;i++) {
227                 struct ldap_SearchResEntry *search;
228
229                 msg = ldapres[i];
230                 search = &msg->r.SearchResultEntry;
231
232                 (*res)->msgs[i] = talloc((*res)->msgs, struct ldb_message);
233                 if (!(*res)->msgs[i]) {
234                         goto failed;
235                 }
236                 (*res)->msgs[i+1] = NULL;
237
238                 (*res)->msgs[i]->dn = ldb_dn_explode_or_special((*res)->msgs[i], search->dn);
239                 if ((*res)->msgs[i]->dn == NULL) {
240                         goto failed;
241                 }
242                 (*res)->msgs[i]->num_elements = search->num_attributes;
243                 (*res)->msgs[i]->elements = talloc_steal((*res)->msgs[i], search->attributes);
244                 (*res)->msgs[i]->private_data = NULL;
245         }
246
247         talloc_free(ldapres);
248
249         (*res)->count = count;
250
251         if (controls) {
252                 (*res)->controls = (struct ldb_control **)talloc_steal(*res, controls);
253         }
254
255         return LDB_SUCCESS;
256
257 failed:
258         if (*res) talloc_free(*res);
259         return LDB_ERR_OTHER;
260 }
261
262
263 /*
264   convert a ldb_message structure to a list of ldap_mod structures
265   ready for ildap_add() or ildap_modify()
266 */
267 static struct ldap_mod **ildb_msg_to_mods(struct ldb_context *ldb,
268                                           const struct ldb_message *msg, int use_flags)
269 {
270         struct ldap_mod **mods;
271         unsigned int i;
272         int num_mods = 0;
273
274         /* allocate maximum number of elements needed */
275         mods = talloc_array(ldb, struct ldap_mod *, msg->num_elements+1);
276         if (!mods) {
277                 errno = ENOMEM;
278                 return NULL;
279         }
280         mods[0] = NULL;
281
282         for (i=0;i<msg->num_elements;i++) {
283                 const struct ldb_message_element *el = &msg->elements[i];
284
285                 mods[num_mods] = talloc(ldb, struct ldap_mod);
286                 if (!mods[num_mods]) {
287                         goto failed;
288                 }
289                 mods[num_mods+1] = NULL;
290                 mods[num_mods]->type = 0;
291                 mods[num_mods]->attrib = *el;
292                 if (use_flags) {
293                         switch (el->flags & LDB_FLAG_MOD_MASK) {
294                         case LDB_FLAG_MOD_ADD:
295                                 mods[num_mods]->type = LDAP_MODIFY_ADD;
296                                 break;
297                         case LDB_FLAG_MOD_DELETE:
298                                 mods[num_mods]->type = LDAP_MODIFY_DELETE;
299                                 break;
300                         case LDB_FLAG_MOD_REPLACE:
301                                 mods[num_mods]->type = LDAP_MODIFY_REPLACE;
302                                 break;
303                         }
304                 }
305                 num_mods++;
306         }
307
308         return mods;
309
310 failed:
311         talloc_free(mods);
312         return NULL;
313 }
314
315
316 /*
317   add a record
318 */
319 static int ildb_add(struct ldb_module *module, const struct ldb_message *msg)
320 {
321         struct ldb_context *ldb = module->ldb;
322         struct ildb_private *ildb = module->private_data;
323         struct ldap_mod **mods;
324         char *dn;
325         int ret = 0;
326         NTSTATUS status;
327
328         /* ignore ltdb specials */
329         if (ldb_dn_is_special(msg->dn)) {
330                 return LDB_SUCCESS;
331         }
332
333         mods = ildb_msg_to_mods(ldb, msg, 0);
334         if (mods == NULL) {
335                 return LDB_ERR_OPERATIONS_ERROR;
336         }
337
338         dn = ldb_dn_linearize(mods, msg->dn);
339         if (dn == NULL) {
340                 talloc_free(mods);
341                 return LDB_ERR_INVALID_DN_SYNTAX;
342         }
343
344         status = ildap_add(ildb->ldap, dn, mods);
345         ret = ildb_map_error(ildb, status);
346
347         talloc_free(mods);
348
349         return ret;
350 }
351
352
353 /*
354   modify a record
355 */
356 static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg)
357 {
358         struct ldb_context *ldb = module->ldb;
359         struct ildb_private *ildb = module->private_data;
360         struct ldap_mod **mods;
361         char *dn;
362         int ret = 0;
363         NTSTATUS status;
364
365         /* ignore ltdb specials */
366         if (ldb_dn_is_special(msg->dn)) {
367                 return LDB_SUCCESS;
368         }
369
370         mods = ildb_msg_to_mods(ldb, msg, 1);
371         if (mods == NULL) {
372                 return LDB_ERR_OPERATIONS_ERROR;
373         }
374
375         dn = ldb_dn_linearize(mods, msg->dn);
376         if (dn == NULL) {
377                 talloc_free(mods);
378                 return LDB_ERR_INVALID_DN_SYNTAX;
379         }
380
381         status = ildap_modify(ildb->ldap, dn, mods);
382         ret = ildb_map_error(ildb, status);
383
384         talloc_free(mods);
385
386         return ret;
387 }
388
389 static int ildb_start_trans(struct ldb_module *module)
390 {
391         /* TODO implement a local locking mechanism here */
392
393         return 0;
394 }
395
396 static int ildb_end_trans(struct ldb_module *module)
397 {
398         /* TODO implement a local transaction mechanism here */
399
400         return 0;
401 }
402
403 static int ildb_del_trans(struct ldb_module *module)
404 {
405         /* TODO implement a local locking mechanism here */
406
407         return 0;
408 }
409
410 static int ildb_request(struct ldb_module *module, struct ldb_request *req)
411 {
412         switch (req->operation) {
413
414         case LDB_REQ_SEARCH:
415                 return ildb_search_bytree(module,
416                                           req->op.search.base,
417                                           req->op.search.scope, 
418                                           req->op.search.tree, 
419                                           req->op.search.attrs, 
420                                           req->controls,
421                                           &req->op.search.res);
422
423         case LDB_REQ_ADD:
424                 return ildb_add(module, req->op.add.message);
425
426         case LDB_REQ_MODIFY:
427                 return ildb_modify(module, req->op.mod.message);
428
429         case LDB_REQ_DELETE:
430                 return ildb_delete(module, req->op.del.dn);
431
432         case LDB_REQ_RENAME:
433                 return ildb_rename(module,
434                                         req->op.rename.olddn,
435                                         req->op.rename.newdn);
436
437         default:
438                 return -1;
439
440         }
441 }
442
443 static int ildb_init_2(struct ldb_module *module)
444 {
445         return LDB_SUCCESS;
446 }
447
448 static const struct ldb_module_ops ildb_ops = {
449         .name              = "ldap",
450         .request           = ildb_request,
451         .start_transaction = ildb_start_trans,
452         .end_transaction   = ildb_end_trans,
453         .del_transaction   = ildb_del_trans,
454         .second_stage_init = ildb_init_2
455 };
456
457
458 /*
459   fetch the rootDSE
460 */
461 static void ildb_rootdse(struct ldb_module *module)
462 {
463         struct ildb_private *ildb = module->private_data;
464         struct ldb_result *res = NULL;
465         struct ldb_dn *empty_dn = ldb_dn_new(ildb);
466         int ret;
467         ret = ildb_search_bytree(module, empty_dn, LDB_SCOPE_BASE, 
468                                  ldb_parse_tree(empty_dn, "dn=dc=rootDSE"), 
469                                  NULL, NULL, &res);
470         if (ret == LDB_SUCCESS && res->count == 1) {
471                 ildb->rootDSE = talloc_steal(ildb, res->msgs[0]);
472         }
473         if (ret == LDB_SUCCESS) talloc_free(res);
474         talloc_free(empty_dn);
475 }
476
477
478 /*
479   connect to the database
480 */
481 int ildb_connect(struct ldb_context *ldb, const char *url, 
482                  unsigned int flags, const char *options[])
483 {
484         struct ildb_private *ildb = NULL;
485         NTSTATUS status;
486         struct cli_credentials *creds;
487
488         ildb = talloc(ldb, struct ildb_private);
489         if (!ildb) {
490                 ldb_oom(ldb);
491                 goto failed;
492         }
493
494         ildb->rootDSE = NULL;
495         ildb->ldb     = ldb;
496
497         ildb->ldap = ldap_new_connection(ildb, ldb_get_opaque(ldb, "EventContext"));
498         if (!ildb->ldap) {
499                 ldb_oom(ldb);
500                 goto failed;
501         }
502
503         status = ldap_connect(ildb->ldap, url);
504         if (!NT_STATUS_IS_OK(status)) {
505                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s\n",
506                           url, ldap_errstr(ildb->ldap, status));
507                 goto failed;
508         }
509
510         ldb->modules = talloc(ldb, struct ldb_module);
511         if (!ldb->modules) {
512                 ldb_oom(ldb);
513                 goto failed;
514         }
515         ldb->modules->ldb = ldb;
516         ldb->modules->prev = ldb->modules->next = NULL;
517         ldb->modules->private_data = ildb;
518         ldb->modules->ops = &ildb_ops;
519
520         /* caller can optionally setup credentials using the opaque token 'credentials' */
521         creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
522         if (creds == NULL) {
523                 struct auth_session_info *session_info = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
524                 if (session_info) {
525                         creds = session_info->credentials;
526                 }
527         }
528
529         if (creds != NULL && cli_credentials_authentication_requested(creds)) {
530                 const char *bind_dn = cli_credentials_get_bind_dn(creds);
531                 if (bind_dn) {
532                         const char *password = cli_credentials_get_password(creds);
533                         status = ldap_bind_simple(ildb->ldap, bind_dn, password);
534                         if (!NT_STATUS_IS_OK(status)) {
535                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
536                                           ldap_errstr(ildb->ldap, status));
537                                 goto failed;
538                         }
539                 } else {
540                         status = ldap_bind_sasl(ildb->ldap, creds);
541                         if (!NT_STATUS_IS_OK(status)) {
542                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
543                                           ldap_errstr(ildb->ldap, status));
544                                 goto failed;
545                         }
546                 }
547         }
548
549         return 0;
550
551 failed:
552         if (ldb->modules) {
553                 ldb->modules->private_data = NULL;
554         }
555         talloc_free(ildb);
556         return -1;
557 }
558