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