remove all '\n' from ldb_debug
[amitay/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    Copyright (C) Simo Sorce       2008
6
7      ** NOTE! The following LGPL license applies to the ldb
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 /*
26  *  Name: ldb_ildap
27  *
28  *  Component: ldb ildap backend
29  *
30  *  Description: This is a ldb backend for the internal ldap
31  *  client library in Samba4. By using this backend we are
32  *  independent of a system ldap library
33  *
34  *  Author: Andrew Tridgell
35  *
36  *  Modifications:
37  *
38  *  - description: make the module use asyncronous calls
39  *    date: Feb 2006
40  *    author: Simo Sorce
41  */
42
43 #include "includes.h"
44 #include "ldb_module.h"
45 #include "dlinklist.h"
46
47 #include "libcli/ldap/ldap.h"
48 #include "libcli/ldap/ldap_client.h"
49 #include "auth/auth.h"
50 #include "auth/credentials/credentials.h"
51
52 struct ildb_private {
53         struct ldap_connection *ldap;
54         struct tevent_context *event_ctx;
55 };
56
57 struct ildb_context {
58         struct ldb_module *module;
59         struct ldb_request *req;
60
61         struct ildb_private *ildb;
62         struct ldap_request *ireq;
63
64         bool done;
65
66         struct ildb_destructor_ctx *dc;
67 };
68
69 static void ildb_request_done(struct ildb_context *ctx,
70                               struct ldb_control **ctrls, int error)
71 {
72         struct ldb_context *ldb;
73         struct ldb_reply *ares;
74
75         ldb = ldb_module_get_ctx(ctx->module);
76
77         ctx->done = true;
78
79         if (ctx->req == NULL) {
80                 /* if the req has been freed already just return */
81                 return;
82         }
83
84         ares = talloc_zero(ctx->req, struct ldb_reply);
85         if (!ares) {
86                 ldb_oom(ldb);
87                 ctx->req->callback(ctx->req, NULL);
88                 return;
89         }
90         ares->type = LDB_REPLY_DONE;
91         ares->controls = talloc_steal(ares, ctrls);
92         ares->error = error;
93
94         ctx->req->callback(ctx->req, ares);
95 }
96
97 static void ildb_auto_done_callback(struct tevent_context *ev,
98                                     struct tevent_timer *te,
99                                     struct timeval t,
100                                     void *private_data)
101 {
102         struct ildb_context *ac;
103
104         ac = talloc_get_type(private_data, struct ildb_context);
105         ildb_request_done(ac, NULL, LDB_SUCCESS);
106 }
107
108 /*
109   convert a ldb_message structure to a list of ldap_mod structures
110   ready for ildap_add() or ildap_modify()
111 */
112 static struct ldap_mod **ildb_msg_to_mods(void *mem_ctx, int *num_mods,
113                                           const struct ldb_message *msg,
114                                           int use_flags)
115 {
116         struct ldap_mod **mods;
117         unsigned int i;
118         int n = 0;
119
120         /* allocate maximum number of elements needed */
121         mods = talloc_array(mem_ctx, struct ldap_mod *, msg->num_elements+1);
122         if (!mods) {
123                 errno = ENOMEM;
124                 return NULL;
125         }
126         mods[0] = NULL;
127
128         for (i = 0; i < msg->num_elements; i++) {
129                 const struct ldb_message_element *el = &msg->elements[i];
130
131                 mods[n] = talloc(mods, struct ldap_mod);
132                 if (!mods[n]) {
133                         goto failed;
134                 }
135                 mods[n + 1] = NULL;
136                 mods[n]->type = 0;
137                 mods[n]->attrib = *el;
138                 if (use_flags) {
139                         switch (el->flags & LDB_FLAG_MOD_MASK) {
140                         case LDB_FLAG_MOD_ADD:
141                                 mods[n]->type = LDAP_MODIFY_ADD;
142                                 break;
143                         case LDB_FLAG_MOD_DELETE:
144                                 mods[n]->type = LDAP_MODIFY_DELETE;
145                                 break;
146                         case LDB_FLAG_MOD_REPLACE:
147                                 mods[n]->type = LDAP_MODIFY_REPLACE;
148                                 break;
149                         }
150                 }
151                 n++;
152         }
153
154         *num_mods = n;
155         return mods;
156
157 failed:
158         talloc_free(mods);
159         return NULL;
160 }
161
162
163 /*
164   map an ildap NTSTATUS to a ldb error code
165 */
166 static int ildb_map_error(struct ldb_module *module, NTSTATUS status)
167 {
168         struct ildb_private *ildb;
169         struct ldb_context *ldb;
170         TALLOC_CTX *mem_ctx;
171
172         ildb = talloc_get_type(ldb_module_get_private(module), struct ildb_private);
173         ldb = ldb_module_get_ctx(module);
174
175         if (NT_STATUS_IS_OK(status)) {
176                 return LDB_SUCCESS;
177         }
178
179         mem_ctx = talloc_new(ildb);
180         if (!mem_ctx) {
181                 ldb_oom(ldb);
182                 return LDB_ERR_OPERATIONS_ERROR;
183         }
184         ldb_set_errstring(ldb,
185                           ldap_errstr(ildb->ldap, mem_ctx, status));
186         talloc_free(mem_ctx);
187         if (NT_STATUS_IS_LDAP(status)) {
188                 return NT_STATUS_LDAP_CODE(status);
189         }
190         return LDB_ERR_OPERATIONS_ERROR;
191 }
192
193 static void ildb_request_timeout(struct tevent_context *ev, struct tevent_timer *te,
194                                  struct timeval t, void *private_data)
195 {
196         struct ildb_context *ac = talloc_get_type(private_data, struct ildb_context);
197
198         if (ac->ireq->state == LDAP_REQUEST_PENDING) {
199                 DLIST_REMOVE(ac->ireq->conn->pending, ac->ireq);
200         }
201
202         ildb_request_done(ac, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED);
203 }
204
205 static void ildb_callback(struct ldap_request *req)
206 {
207         struct ldb_context *ldb;
208         struct ildb_context *ac;
209         NTSTATUS status;
210         struct ldap_SearchResEntry *search;
211         struct ldap_message *msg;
212         struct ldb_control **controls;
213         struct ldb_message *ldbmsg;
214         char *referral;
215         bool callback_failed;
216         bool request_done;
217         int ret;
218         int i;
219
220         ac = talloc_get_type(req->async.private_data, struct ildb_context);
221         ldb = ldb_module_get_ctx(ac->module);
222         callback_failed = false;
223         request_done = false;
224         controls = NULL;
225
226         if (!NT_STATUS_IS_OK(req->status)) {
227                 ret = ildb_map_error(ac->module, req->status);
228                 ildb_request_done(ac, NULL, ret);
229                 return;
230         }
231
232         if (req->num_replies < 1) {
233                 ret = LDB_ERR_OPERATIONS_ERROR;
234                 ildb_request_done(ac, NULL, ret);
235                 return;
236         }
237
238         switch (req->type) {
239
240         case LDAP_TAG_ModifyRequest:
241                 if (req->replies[0]->type != LDAP_TAG_ModifyResponse) {
242                         ret = LDB_ERR_PROTOCOL_ERROR;
243                         break;
244                 }
245                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
246                 ret = ildb_map_error(ac->module, status);
247                 request_done = true;
248                 break;
249
250         case LDAP_TAG_AddRequest:
251                 if (req->replies[0]->type != LDAP_TAG_AddResponse) {
252                         ret = LDB_ERR_PROTOCOL_ERROR;
253                         return;
254                 }
255                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
256                 ret = ildb_map_error(ac->module, status);
257                 request_done = true;
258                 break;
259
260         case LDAP_TAG_DelRequest:
261                 if (req->replies[0]->type != LDAP_TAG_DelResponse) {
262                         ret = LDB_ERR_PROTOCOL_ERROR;
263                         return;
264                 }
265                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
266                 ret = ildb_map_error(ac->module, status);
267                 request_done = true;
268                 break;
269
270         case LDAP_TAG_ModifyDNRequest:
271                 if (req->replies[0]->type != LDAP_TAG_ModifyDNResponse) {
272                         ret = LDB_ERR_PROTOCOL_ERROR;
273                         return;
274                 }
275                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
276                 ret = ildb_map_error(ac->module, status);
277                 request_done = true;
278                 break;
279
280         case LDAP_TAG_SearchRequest:
281                 /* loop over all messages */
282                 for (i = 0; i < req->num_replies; i++) {
283
284                         msg = req->replies[i];
285                         switch (msg->type) {
286
287                         case LDAP_TAG_SearchResultDone:
288
289                                 status = ldap_check_response(ac->ireq->conn, &msg->r.GeneralResult);
290                                 if (!NT_STATUS_IS_OK(status)) {
291                                         ret = ildb_map_error(ac->module, status);
292                                         break;
293                                 }
294
295                                 controls = talloc_steal(ac, msg->controls);
296                                 if (msg->r.SearchResultDone.resultcode) {
297                                         if (msg->r.SearchResultDone.errormessage) {
298                                                 ldb_set_errstring(ldb, msg->r.SearchResultDone.errormessage);
299                                         }
300                                 }
301
302                                 ret = msg->r.SearchResultDone.resultcode;
303                                 request_done = true;
304                                 break;
305
306                         case LDAP_TAG_SearchResultEntry:
307
308                                 ldbmsg = ldb_msg_new(ac);
309                                 if (!ldbmsg) {
310                                         ret = LDB_ERR_OPERATIONS_ERROR;
311                                         break;
312                                 }
313
314                                 search = &(msg->r.SearchResultEntry);
315
316                                 ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, search->dn);
317                                 if ( ! ldb_dn_validate(ldbmsg->dn)) {
318                                         ret = LDB_ERR_OPERATIONS_ERROR;
319                                         break;
320                                 }
321                                 ldbmsg->num_elements = search->num_attributes;
322                                 ldbmsg->elements = talloc_move(ldbmsg, &search->attributes);
323
324                                 controls = talloc_steal(ac, msg->controls);
325                                 
326                                 ret = ldb_module_send_entry(ac->req, ldbmsg, controls);
327                                 if (ret != LDB_SUCCESS) {
328                                         callback_failed = true;
329                                 }
330                                 break;
331
332                         case LDAP_TAG_SearchResultReference:
333
334                                 referral = talloc_strdup(ac, msg->r.SearchResultReference.referral);
335
336                                 ret = ldb_module_send_referral(ac->req, referral);
337                                 if (ret != LDB_SUCCESS) {
338                                         callback_failed = true;
339                                 }
340                                 break;
341
342                         default:
343                                 /* TAG not handled, fail ! */
344                                 ret = LDB_ERR_PROTOCOL_ERROR;
345                                 break;
346                         }
347
348                         if (ret != LDB_SUCCESS) {
349                                 break;
350                         }
351                 }
352
353                 talloc_free(req->replies);
354                 req->replies = NULL;
355                 req->num_replies = 0;
356
357                 break;
358
359         default:
360                 ret = LDB_ERR_PROTOCOL_ERROR;
361                 break;
362         }
363
364         if (ret != LDB_SUCCESS) {
365
366                 /* if the callback failed the caller will have freed the
367                  * request. Just return and don't try to use it */
368                 if ( ! callback_failed) {
369                         request_done = true;
370                 }
371         }
372
373         if (request_done) {
374                 ildb_request_done(ac, controls, ret);
375         }
376         return;
377 }
378
379 static int ildb_request_send(struct ildb_context *ac, struct ldap_message *msg)
380 {
381         struct ldb_context *ldb;
382         struct ldap_request *req;
383
384         if (!ac) {
385                 return LDB_ERR_OPERATIONS_ERROR;
386         }
387
388         ldb = ldb_module_get_ctx(ac->module);
389
390         req = ldap_request_send(ac->ildb->ldap, msg);
391         if (req == NULL) {
392                 ldb_set_errstring(ldb, "async send request failed");
393                 return LDB_ERR_OPERATIONS_ERROR;
394         }
395         ac->ireq = talloc_steal(ac, req);
396
397         if (!ac->ireq->conn) {
398                 ldb_set_errstring(ldb, "connection to remote LDAP server dropped?");
399                 return LDB_ERR_OPERATIONS_ERROR;
400         }
401
402         talloc_free(req->time_event);
403         req->time_event = NULL;
404         if (ac->req->timeout) {
405                 req->time_event = tevent_add_timer(ac->ildb->event_ctx, ac,
406                                                    timeval_current_ofs(ac->req->timeout, 0),
407                                                    ildb_request_timeout, ac);
408         }
409
410         req->async.fn = ildb_callback;
411         req->async.private_data = ac;
412
413         return LDB_SUCCESS;
414 }
415
416 /*
417   search for matching records using an asynchronous function
418  */
419 static int ildb_search(struct ildb_context *ac)
420 {
421         struct ldb_context *ldb;
422         struct ldb_request *req = ac->req;
423         struct ldap_message *msg;
424         int n;
425
426         ldb = ldb_module_get_ctx(ac->module);
427
428         if (!req->callback || !req->context) {
429                 ldb_set_errstring(ldb, "Async interface called with NULL callback function or NULL context");
430                 return LDB_ERR_OPERATIONS_ERROR;
431         }
432
433         if (req->op.search.tree == NULL) {
434                 ldb_set_errstring(ldb, "Invalid expression parse tree");
435                 return LDB_ERR_OPERATIONS_ERROR;
436         }
437
438         msg = new_ldap_message(req);
439         if (msg == NULL) {
440                 ldb_set_errstring(ldb, "Out of Memory");
441                 return LDB_ERR_OPERATIONS_ERROR;
442         }
443
444         msg->type = LDAP_TAG_SearchRequest;
445
446         if (req->op.search.base == NULL) {
447                 msg->r.SearchRequest.basedn = talloc_strdup(msg, "");
448         } else {
449                 msg->r.SearchRequest.basedn  = ldb_dn_get_extended_linearized(msg, req->op.search.base, 0);
450         }
451         if (msg->r.SearchRequest.basedn == NULL) {
452                 ldb_set_errstring(ldb, "Unable to determine baseDN");
453                 talloc_free(msg);
454                 return LDB_ERR_OPERATIONS_ERROR;
455         }
456
457         if (req->op.search.scope == LDB_SCOPE_DEFAULT) {
458                 msg->r.SearchRequest.scope = LDB_SCOPE_SUBTREE;
459         } else {
460                 msg->r.SearchRequest.scope = req->op.search.scope;
461         }
462
463         msg->r.SearchRequest.deref  = LDAP_DEREFERENCE_NEVER;
464         msg->r.SearchRequest.timelimit = 0;
465         msg->r.SearchRequest.sizelimit = 0;
466         msg->r.SearchRequest.attributesonly = 0;
467         msg->r.SearchRequest.tree = discard_const(req->op.search.tree);
468
469         for (n = 0; req->op.search.attrs && req->op.search.attrs[n]; n++) /* noop */ ;
470         msg->r.SearchRequest.num_attributes = n;
471         msg->r.SearchRequest.attributes = req->op.search.attrs;
472         msg->controls = req->controls;
473
474         return ildb_request_send(ac, msg);
475 }
476
477 /*
478   add a record
479 */
480 static int ildb_add(struct ildb_context *ac)
481 {
482         struct ldb_request *req = ac->req;
483         struct ldap_message *msg;
484         struct ldap_mod **mods;
485         int i,n;
486
487         msg = new_ldap_message(req);
488         if (msg == NULL) {
489                 return LDB_ERR_OPERATIONS_ERROR;
490         }
491
492         msg->type = LDAP_TAG_AddRequest;
493
494         msg->r.AddRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.add.message->dn, 0);
495         if (msg->r.AddRequest.dn == NULL) {
496                 talloc_free(msg);
497                 return LDB_ERR_INVALID_DN_SYNTAX;
498         }
499
500         mods = ildb_msg_to_mods(msg, &n, req->op.add.message, 0);
501         if (mods == NULL) {
502                 talloc_free(msg);
503                 return LDB_ERR_OPERATIONS_ERROR;
504         }
505
506         msg->r.AddRequest.num_attributes = n;
507         msg->r.AddRequest.attributes = talloc_array(msg, struct ldb_message_element, n);
508         if (msg->r.AddRequest.attributes == NULL) {
509                 talloc_free(msg);
510                 return LDB_ERR_OPERATIONS_ERROR;
511         }
512
513         for (i = 0; i < n; i++) {
514                 msg->r.AddRequest.attributes[i] = mods[i]->attrib;
515         }
516
517         return ildb_request_send(ac, msg);
518 }
519
520 /*
521   modify a record
522 */
523 static int ildb_modify(struct ildb_context *ac)
524 {
525         struct ldb_request *req = ac->req;
526         struct ldap_message *msg;
527         struct ldap_mod **mods;
528         int i,n;
529
530         msg = new_ldap_message(req);
531         if (msg == NULL) {
532                 return LDB_ERR_OPERATIONS_ERROR;
533         }
534
535         msg->type = LDAP_TAG_ModifyRequest;
536
537         msg->r.ModifyRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.mod.message->dn, 0);
538         if (msg->r.ModifyRequest.dn == NULL) {
539                 talloc_free(msg);
540                 return LDB_ERR_INVALID_DN_SYNTAX;
541         }
542
543         mods = ildb_msg_to_mods(msg, &n, req->op.mod.message, 1);
544         if (mods == NULL) {
545                 talloc_free(msg);
546                 return LDB_ERR_OPERATIONS_ERROR;
547         }
548
549         msg->r.ModifyRequest.num_mods = n;
550         msg->r.ModifyRequest.mods = talloc_array(msg, struct ldap_mod, n);
551         if (msg->r.ModifyRequest.mods == NULL) {
552                 talloc_free(msg);
553                 return LDB_ERR_OPERATIONS_ERROR;
554         }
555
556         for (i = 0; i < n; i++) {
557                 msg->r.ModifyRequest.mods[i] = *mods[i];
558         }
559
560         return ildb_request_send(ac, msg);
561 }
562
563 /*
564   delete a record
565 */
566 static int ildb_delete(struct ildb_context *ac)
567 {
568         struct ldb_request *req = ac->req;
569         struct ldap_message *msg;
570
571         msg = new_ldap_message(req);
572         if (msg == NULL) {
573                 return LDB_ERR_OPERATIONS_ERROR;
574         }
575
576         msg->type = LDAP_TAG_DelRequest;
577
578         msg->r.DelRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.del.dn, 0);
579         if (msg->r.DelRequest.dn == NULL) {
580                 talloc_free(msg);
581                 return LDB_ERR_INVALID_DN_SYNTAX;
582         }
583
584         return ildb_request_send(ac, msg);
585 }
586
587 /*
588   rename a record
589 */
590 static int ildb_rename(struct ildb_context *ac)
591 {
592         struct ldb_request *req = ac->req;
593         struct ldap_message *msg;
594
595         msg = new_ldap_message(req);
596         if (msg == NULL) {
597                 return LDB_ERR_OPERATIONS_ERROR;
598         }
599
600         msg->type = LDAP_TAG_ModifyDNRequest;
601         msg->r.ModifyDNRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.rename.olddn, 0);
602         if (msg->r.ModifyDNRequest.dn == NULL) {
603                 talloc_free(msg);
604                 return LDB_ERR_INVALID_DN_SYNTAX;
605         }
606
607         msg->r.ModifyDNRequest.newrdn =
608                 talloc_asprintf(msg, "%s=%s",
609                                 ldb_dn_get_rdn_name(req->op.rename.newdn),
610                                 ldb_dn_escape_value(msg, *ldb_dn_get_rdn_val(req->op.rename.newdn)));
611         if (msg->r.ModifyDNRequest.newrdn == NULL) {
612                 talloc_free(msg);
613                 return LDB_ERR_OPERATIONS_ERROR;
614         }
615
616         msg->r.ModifyDNRequest.newsuperior =
617                 ldb_dn_alloc_linearized(msg, ldb_dn_get_parent(msg, req->op.rename.newdn));
618         if (msg->r.ModifyDNRequest.newsuperior == NULL) {
619                 talloc_free(msg);
620                 return LDB_ERR_INVALID_DN_SYNTAX;
621         }
622
623         msg->r.ModifyDNRequest.deleteolddn = true;
624
625         return ildb_request_send(ac, msg);
626 }
627
628 static int ildb_start_trans(struct ldb_module *module)
629 {
630         /* TODO implement a local locking mechanism here */
631
632         return LDB_SUCCESS;
633 }
634
635 static int ildb_end_trans(struct ldb_module *module)
636 {
637         /* TODO implement a local transaction mechanism here */
638
639         return LDB_SUCCESS;
640 }
641
642 static int ildb_del_trans(struct ldb_module *module)
643 {
644         /* TODO implement a local locking mechanism here */
645
646         return LDB_SUCCESS;
647 }
648
649 static bool ildb_dn_is_special(struct ldb_request *req)
650 {
651         struct ldb_dn *dn = NULL;
652
653         switch (req->operation) {
654         case LDB_ADD:
655                 dn = req->op.add.message->dn;
656                 break;
657         case LDB_MODIFY:
658                 dn = req->op.mod.message->dn;
659                 break;
660         case LDB_DELETE:
661                 dn = req->op.del.dn;
662                 break;
663         case LDB_RENAME:
664                 dn = req->op.rename.olddn;
665                 break;
666         default:
667                 break;
668         }
669
670         if (dn && ldb_dn_is_special(dn)) {
671                 return true;
672         }
673         return false;
674 }
675
676 static int ildb_handle_request(struct ldb_module *module, struct ldb_request *req)
677 {
678         struct ldb_context *ldb;
679         struct ildb_private *ildb;
680         struct ildb_context *ac;
681         struct tevent_timer *te;
682         int ret;
683
684         ildb = talloc_get_type(ldb_module_get_private(module), struct ildb_private);
685         ldb = ldb_module_get_ctx(module);
686
687         if (req->starttime == 0 || req->timeout == 0) {
688                 ldb_set_errstring(ldb, "Invalid timeout settings");
689                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
690         }
691
692         ac = talloc_zero(req, struct ildb_context);
693         if (ac == NULL) {
694                 ldb_set_errstring(ldb, "Out of Memory");
695                 return LDB_ERR_OPERATIONS_ERROR;
696         }
697
698         ac->module = module;
699         ac->req = req;
700         ac->ildb = ildb;
701
702         if (ildb_dn_is_special(req)) {
703
704                 te = tevent_add_timer(ac->ildb->event_ctx,
705                                       ac, timeval_zero(),
706                                       ildb_auto_done_callback, ac);
707                 if (NULL == te) {
708                         return LDB_ERR_OPERATIONS_ERROR;
709                 }
710
711                 return LDB_SUCCESS;
712         }
713
714         switch (ac->req->operation) {
715         case LDB_SEARCH:
716                 ret = ildb_search(ac);
717                 break;
718         case LDB_ADD:
719                 ret = ildb_add(ac);
720                 break;
721         case LDB_MODIFY:
722                 ret = ildb_modify(ac);
723                 break;
724         case LDB_DELETE:
725                 ret = ildb_delete(ac);
726                 break;
727         case LDB_RENAME:
728                 ret = ildb_rename(ac);
729                 break;
730         default:
731                 /* no other op supported */
732                 ret = LDB_ERR_OPERATIONS_ERROR;
733                 break;
734         }
735
736         return ret;
737 }
738
739 static const struct ldb_module_ops ildb_ops = {
740         .name              = "ldap",
741         .search            = ildb_handle_request,
742         .add               = ildb_handle_request,
743         .modify            = ildb_handle_request,
744         .del               = ildb_handle_request,
745         .rename            = ildb_handle_request,
746 /*      .request           = ildb_handle_request, */
747         .start_transaction = ildb_start_trans,
748         .end_transaction   = ildb_end_trans,
749         .del_transaction   = ildb_del_trans,
750 };
751
752 /*
753   connect to the database
754 */
755 static int ildb_connect(struct ldb_context *ldb, const char *url,
756                         unsigned int flags, const char *options[],
757                         struct ldb_module **_module)
758 {
759         struct ldb_module *module;
760         struct ildb_private *ildb;
761         NTSTATUS status;
762         struct cli_credentials *creds;
763         struct loadparm_context *lp_ctx;
764
765         module = ldb_module_new(ldb, ldb, "ldb_ildap backend", &ildb_ops);
766         if (!module) return -1;
767
768         ildb = talloc(module, struct ildb_private);
769         if (!ildb) {
770                 ldb_oom(ldb);
771                 goto failed;
772         }
773         ldb_module_set_private(module, ildb);
774
775         ildb->event_ctx = ldb_get_event_context(ldb);
776
777         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
778                                  struct loadparm_context);
779
780         ildb->ldap = ldap4_new_connection(ildb, lp_ctx,
781                                           ildb->event_ctx);
782         if (!ildb->ldap) {
783                 ldb_oom(ldb);
784                 goto failed;
785         }
786
787         if (flags & LDB_FLG_RECONNECT) {
788                 ldap_set_reconn_params(ildb->ldap, 10);
789         }
790
791         status = ldap_connect(ildb->ldap, url);
792         if (!NT_STATUS_IS_OK(status)) {
793                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s",
794                           url, ldap_errstr(ildb->ldap, module, status));
795                 goto failed;
796         }
797
798         /* caller can optionally setup credentials using the opaque token 'credentials' */
799         creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
800         if (creds == NULL) {
801                 struct auth_session_info *session_info = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
802                 if (session_info) {
803                         creds = session_info->credentials;
804                 }
805         }
806
807         if (creds != NULL && cli_credentials_authentication_requested(creds)) {
808                 const char *bind_dn = cli_credentials_get_bind_dn(creds);
809                 if (bind_dn) {
810                         const char *password = cli_credentials_get_password(creds);
811                         status = ldap_bind_simple(ildb->ldap, bind_dn, password);
812                         if (!NT_STATUS_IS_OK(status)) {
813                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
814                                           ldap_errstr(ildb->ldap, module, status));
815                                 goto failed;
816                         }
817                 } else {
818                         status = ldap_bind_sasl(ildb->ldap, creds, lp_ctx);
819                         if (!NT_STATUS_IS_OK(status)) {
820                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
821                                           ldap_errstr(ildb->ldap, module, status));
822                                 goto failed;
823                         }
824                 }
825         }
826
827         *_module = module;
828         return 0;
829
830 failed:
831         talloc_free(module);
832         return -1;
833 }
834
835 _PUBLIC_ const struct ldb_backend_ops ldb_ldap_backend_ops = {
836         .name = "ldap",
837         .connect_fn = ildb_connect
838 };
839
840 _PUBLIC_ const struct ldb_backend_ops ldb_ldapi_backend_ops = {
841         .name = "ldapi",
842         .connect_fn = ildb_connect
843 };
844
845 _PUBLIC_ const struct ldb_backend_ops ldb_ldaps_backend_ops = {
846         .name = "ldaps",
847         .connect_fn = ildb_connect
848 };
849