Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : LDAP protocol helper functions for SAMBA
4 :
5 : Copyright (C) Andrew Tridgell 2004
6 : Copyright (C) Volker Lendecke 2004
7 : Copyright (C) Stefan Metzmacher 2004
8 : Copyright (C) Simo Sorce 2004
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program 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
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 :
23 : */
24 :
25 : #include "includes.h"
26 : #include <tevent.h>
27 : #include "lib/socket/socket.h"
28 : #include "lib/tsocket/tsocket.h"
29 : #include "libcli/util/tstream.h"
30 : #include "../lib/util/asn1.h"
31 : #include "../lib/util/dlinklist.h"
32 : #include "libcli/ldap/libcli_ldap.h"
33 : #include "libcli/ldap/ldap_proto.h"
34 : #include "libcli/ldap/ldap_client.h"
35 : #include "libcli/composite/composite.h"
36 : #include "lib/tls/tls.h"
37 : #include "auth/gensec/gensec.h"
38 : #include "system/time.h"
39 : #include "param/param.h"
40 : #include "libcli/resolve/resolve.h"
41 : #include "librpc/gen_ndr/ads.h"
42 :
43 : static void ldap_connection_dead(struct ldap_connection *conn, NTSTATUS status);
44 :
45 26898 : static int ldap_connection_destructor(struct ldap_connection *conn)
46 : {
47 : /*
48 : * NT_STATUS_OK means that callbacks of pending requests are not
49 : * triggered
50 : */
51 26898 : ldap_connection_dead(conn, NT_STATUS_OK);
52 26898 : return 0;
53 : }
54 :
55 : /**
56 : create a new ldap_connection structure. The event context is optional
57 : */
58 :
59 26898 : _PUBLIC_ struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
60 : struct loadparm_context *lp_ctx,
61 : struct tevent_context *ev)
62 : {
63 122 : struct ldap_connection *conn;
64 :
65 26898 : if (ev == NULL) {
66 0 : return NULL;
67 : }
68 :
69 26898 : if (lp_ctx == NULL) {
70 0 : return NULL;
71 : }
72 :
73 26898 : conn = talloc_zero(mem_ctx, struct ldap_connection);
74 26898 : if (conn == NULL) {
75 0 : return NULL;
76 : }
77 :
78 26898 : conn->next_messageid = 1;
79 26898 : conn->event.event_ctx = ev;
80 :
81 26898 : conn->sockets.send_queue = tevent_queue_create(conn,
82 : "ldap_connection send_queue");
83 26898 : if (conn->sockets.send_queue == NULL) {
84 0 : TALLOC_FREE(conn);
85 0 : return NULL;
86 : }
87 :
88 26898 : conn->lp_ctx = lp_ctx;
89 :
90 : /* set a reasonable request timeout */
91 26898 : conn->timeout = 60;
92 :
93 : /* explicitly avoid reconnections by default */
94 26898 : conn->reconnect.max_retries = 0;
95 :
96 26898 : talloc_set_destructor(conn, ldap_connection_destructor);
97 26898 : return conn;
98 : }
99 :
100 : /*
101 : the connection is dead
102 : */
103 26898 : static void ldap_connection_dead(struct ldap_connection *conn, NTSTATUS status)
104 : {
105 122 : struct ldap_request *req;
106 :
107 26898 : tevent_queue_stop(conn->sockets.send_queue);
108 26898 : TALLOC_FREE(conn->sockets.recv_subreq);
109 26898 : conn->sockets.active = NULL;
110 26898 : TALLOC_FREE(conn->sockets.sasl);
111 26898 : TALLOC_FREE(conn->sockets.tls);
112 26898 : TALLOC_FREE(conn->sockets.raw);
113 :
114 : /* return an error for any pending request ... */
115 26964 : while (conn->pending) {
116 66 : req = conn->pending;
117 66 : DLIST_REMOVE(req->conn->pending, req);
118 66 : req->conn = NULL;
119 66 : req->state = LDAP_REQUEST_DONE;
120 66 : if (NT_STATUS_IS_OK(status)) {
121 66 : continue;
122 : }
123 0 : req->status = status;
124 0 : if (req->async.fn) {
125 0 : req->async.fn(req);
126 : }
127 : }
128 26898 : }
129 :
130 : static void ldap_reconnect(struct ldap_connection *conn);
131 :
132 : /*
133 : handle packet errors
134 : */
135 0 : static void ldap_error_handler(struct ldap_connection *conn, NTSTATUS status)
136 : {
137 0 : ldap_connection_dead(conn, status);
138 :
139 : /* but try to reconnect so that the ldb client can go on */
140 0 : ldap_reconnect(conn);
141 0 : }
142 :
143 :
144 : /*
145 : match up with a pending message, adding to the replies list
146 : */
147 1344923 : static void ldap_match_message(struct ldap_connection *conn, struct ldap_message *msg)
148 : {
149 872 : struct ldap_request *req;
150 872 : int i;
151 :
152 1345436 : for (req=conn->pending; req; req=req->next) {
153 1345435 : if (req->messageid == msg->messageid) break;
154 : }
155 : /* match a zero message id to the last request sent.
156 : It seems that servers send 0 if unable to parse */
157 1344923 : if (req == NULL && msg->messageid == 0) {
158 1 : req = conn->pending;
159 : }
160 1344923 : if (req == NULL) {
161 0 : DEBUG(0,("ldap: no matching message id for %u\n",
162 : msg->messageid));
163 0 : TALLOC_FREE(msg);
164 0 : return;
165 : }
166 :
167 : /* Check for undecoded critical extensions */
168 1465949 : for (i=0; msg->controls && msg->controls[i]; i++) {
169 121026 : if (!msg->controls_decoded[i] &&
170 0 : msg->controls[i]->critical) {
171 0 : TALLOC_FREE(msg);
172 0 : req->status = NT_STATUS_LDAP(LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
173 0 : req->state = LDAP_REQUEST_DONE;
174 0 : DLIST_REMOVE(conn->pending, req);
175 0 : if (req->async.fn) {
176 0 : req->async.fn(req);
177 : }
178 0 : return;
179 : }
180 : }
181 :
182 : /* add to the list of replies received */
183 1344923 : req->replies = talloc_realloc(req, req->replies,
184 : struct ldap_message *, req->num_replies+1);
185 1344923 : if (req->replies == NULL) {
186 0 : TALLOC_FREE(msg);
187 0 : req->status = NT_STATUS_NO_MEMORY;
188 0 : req->state = LDAP_REQUEST_DONE;
189 0 : DLIST_REMOVE(conn->pending, req);
190 0 : if (req->async.fn) {
191 0 : req->async.fn(req);
192 : }
193 0 : return;
194 : }
195 :
196 1344923 : req->replies[req->num_replies] = talloc_steal(req->replies, msg);
197 1344923 : req->num_replies++;
198 :
199 1344923 : if (msg->type != LDAP_TAG_SearchResultEntry &&
200 737328 : msg->type != LDAP_TAG_SearchResultReference) {
201 : /* currently only search results expect multiple
202 : replies */
203 604720 : req->state = LDAP_REQUEST_DONE;
204 604720 : DLIST_REMOVE(conn->pending, req);
205 : }
206 :
207 1344923 : if (req->async.fn) {
208 1308527 : req->async.fn(req);
209 : }
210 : }
211 :
212 : static void ldap_connection_recv_done(struct tevent_req *subreq);
213 :
214 1949722 : static void ldap_connection_recv_next(struct ldap_connection *conn)
215 : {
216 1949722 : struct tevent_req *subreq = NULL;
217 :
218 1949722 : if (conn->sockets.recv_subreq != NULL) {
219 4794 : return;
220 : }
221 :
222 1944928 : if (conn->sockets.active == NULL) {
223 0 : return;
224 : }
225 :
226 1944928 : if (conn->pending == NULL) {
227 599352 : return;
228 : }
229 :
230 : /*
231 : * The minimum size of a LDAP pdu is 7 bytes
232 : *
233 : * dumpasn1 -hh ldap-unbind-min.dat
234 : *
235 : * <30 05 02 01 09 42 00>
236 : * 0 5: SEQUENCE {
237 : * <02 01 09>
238 : * 2 1: INTEGER 9
239 : * <42 00>
240 : * 5 0: [APPLICATION 2]
241 : * : Error: Object has zero length.
242 : * : }
243 : *
244 : * dumpasn1 -hh ldap-unbind-windows.dat
245 : *
246 : * <30 84 00 00 00 05 02 01 09 42 00>
247 : * 0 5: SEQUENCE {
248 : * <02 01 09>
249 : * 6 1: INTEGER 9
250 : * <42 00>
251 : * 9 0: [APPLICATION 2]
252 : * : Error: Object has zero length.
253 : * : }
254 : *
255 : * This means using an initial read size
256 : * of 7 is ok.
257 : */
258 1344989 : subreq = tstream_read_pdu_blob_send(conn,
259 : conn->event.event_ctx,
260 : conn->sockets.active,
261 : 7, /* initial_read_size */
262 : ldap_full_packet,
263 : conn);
264 1344989 : if (subreq == NULL) {
265 0 : ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
266 0 : return;
267 : }
268 1344989 : tevent_req_set_callback(subreq, ldap_connection_recv_done, conn);
269 1344989 : conn->sockets.recv_subreq = subreq;
270 1344989 : return;
271 : }
272 :
273 : /*
274 : decode/process LDAP data
275 : */
276 1344923 : static void ldap_connection_recv_done(struct tevent_req *subreq)
277 : {
278 872 : NTSTATUS status;
279 872 : struct ldap_connection *conn =
280 1344923 : tevent_req_callback_data(subreq,
281 : struct ldap_connection);
282 872 : struct ldap_message *msg;
283 872 : struct asn1_data *asn1;
284 872 : DATA_BLOB blob;
285 1344923 : struct ldap_request_limits limits = {0};
286 :
287 1344923 : msg = talloc_zero(conn, struct ldap_message);
288 1344923 : if (msg == NULL) {
289 0 : ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
290 0 : return;
291 : }
292 :
293 1344923 : asn1 = asn1_init(conn, ASN1_MAX_TREE_DEPTH);
294 1344923 : if (asn1 == NULL) {
295 0 : TALLOC_FREE(msg);
296 0 : ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
297 0 : return;
298 : }
299 :
300 1344923 : conn->sockets.recv_subreq = NULL;
301 :
302 1344923 : status = tstream_read_pdu_blob_recv(subreq,
303 : asn1,
304 : &blob);
305 1344923 : TALLOC_FREE(subreq);
306 1344923 : if (!NT_STATUS_IS_OK(status)) {
307 0 : TALLOC_FREE(msg);
308 0 : asn1_free(asn1);
309 0 : ldap_error_handler(conn, status);
310 0 : return;
311 : }
312 :
313 1344923 : asn1_load_nocopy(asn1, blob.data, blob.length);
314 :
315 1344923 : status = ldap_decode(asn1, &limits, samba_ldap_control_handlers(), msg);
316 1344923 : asn1_free(asn1);
317 1344923 : if (!NT_STATUS_IS_OK(status)) {
318 0 : TALLOC_FREE(msg);
319 0 : ldap_error_handler(conn, status);
320 0 : return;
321 : }
322 :
323 1344923 : ldap_match_message(conn, msg);
324 1344923 : ldap_connection_recv_next(conn);
325 :
326 1344923 : return;
327 : }
328 :
329 : enum ldap_proto {
330 : LDAP_PROTO_NONE,
331 : LDAP_PROTO_LDAP,
332 : LDAP_PROTO_LDAPS,
333 : LDAP_PROTO_LDAPI
334 : };
335 :
336 26898 : static int ldap_parse_basic_url(
337 : const char *url,
338 : enum ldap_proto *pproto,
339 : TALLOC_CTX *mem_ctx,
340 : char **pdest, /* path for ldapi, host for ldap[s] */
341 : uint16_t *pport) /* Not set for ldapi */
342 : {
343 26898 : enum ldap_proto proto = LDAP_PROTO_NONE;
344 26898 : char *host = NULL;
345 122 : int ret, port;
346 :
347 26898 : if (url == NULL) {
348 0 : return EINVAL;
349 : }
350 :
351 26898 : if (strncasecmp_m(url, "ldapi://", strlen("ldapi://")) == 0) {
352 108 : char *path = NULL, *end = NULL;
353 :
354 108 : path = talloc_strdup(mem_ctx, url+8);
355 108 : if (path == NULL) {
356 0 : return ENOMEM;
357 : }
358 108 : end = rfc1738_unescape(path);
359 108 : if (end == NULL) {
360 0 : TALLOC_FREE(path);
361 0 : return EINVAL;
362 : }
363 :
364 108 : *pproto = LDAP_PROTO_LDAPI;
365 108 : *pdest = path;
366 108 : return 0;
367 : }
368 :
369 26790 : if (strncasecmp_m(url, "ldap://", strlen("ldap://")) == 0) {
370 26256 : url += 7;
371 26256 : proto = LDAP_PROTO_LDAP;
372 26256 : port = 389;
373 : }
374 26790 : if (strncasecmp_m(url, "ldaps://", strlen("ldaps://")) == 0) {
375 534 : url += 8;
376 534 : port = 636;
377 534 : proto = LDAP_PROTO_LDAPS;
378 : }
379 :
380 26790 : if (proto == LDAP_PROTO_NONE) {
381 0 : return EPROTONOSUPPORT;
382 : }
383 :
384 26790 : if (url[0] == '[') {
385 : /*
386 : * IPv6 with [aa:bb:cc..]:port
387 : */
388 0 : const char *end = NULL;
389 :
390 0 : url +=1;
391 :
392 0 : end = strchr(url, ']');
393 0 : if (end == NULL) {
394 0 : return EINVAL;
395 : }
396 :
397 0 : ret = sscanf(end+1, ":%d", &port);
398 0 : if (ret < 0) {
399 0 : return EINVAL;
400 : }
401 :
402 0 : *pdest = talloc_strndup(mem_ctx, url, end-url);
403 0 : if (*pdest == NULL) {
404 0 : return ENOMEM;
405 : }
406 0 : *pproto = proto;
407 0 : *pport = port;
408 0 : return 0;
409 : }
410 :
411 26790 : ret = sscanf(url, "%m[^:/]:%d", &host, &port);
412 26790 : if (ret < 1) {
413 0 : return EINVAL;
414 : }
415 :
416 26790 : *pdest = talloc_strdup(mem_ctx, host);
417 26790 : SAFE_FREE(host);
418 26790 : if (*pdest == NULL) {
419 0 : return ENOMEM;
420 : }
421 26790 : *pproto = proto;
422 26790 : *pport = port;
423 :
424 26790 : return 0;
425 : }
426 :
427 : /*
428 : connect to a ldap server
429 : */
430 :
431 : struct ldap_connect_state {
432 : struct composite_context *ctx;
433 : struct ldap_connection *conn;
434 : struct socket_context *sock;
435 : struct tstream_context *raw;
436 : struct tstream_tls_params *tls_params;
437 : struct tstream_context *tls;
438 : };
439 :
440 : static void ldap_connect_recv_unix_conn(struct composite_context *ctx);
441 : static void ldap_connect_recv_tcp_conn(struct composite_context *ctx);
442 :
443 26898 : _PUBLIC_ struct composite_context *ldap_connect_send(struct ldap_connection *conn,
444 : const char *url)
445 : {
446 122 : struct composite_context *result, *ctx;
447 122 : struct ldap_connect_state *state;
448 122 : enum ldap_proto proto;
449 26898 : char *dest = NULL;
450 122 : uint16_t port;
451 122 : int ret;
452 :
453 26898 : result = talloc_zero(conn, struct composite_context);
454 26898 : if (result == NULL) goto failed;
455 26898 : result->state = COMPOSITE_STATE_IN_PROGRESS;
456 26898 : result->async.fn = NULL;
457 26898 : result->event_ctx = conn->event.event_ctx;
458 :
459 26898 : state = talloc(result, struct ldap_connect_state);
460 26898 : if (state == NULL) goto failed;
461 26898 : state->ctx = result;
462 26898 : result->private_data = state;
463 :
464 26898 : state->conn = conn;
465 :
466 26898 : if (conn->reconnect.url == NULL) {
467 26898 : conn->reconnect.url = talloc_strdup(conn, url);
468 26898 : if (conn->reconnect.url == NULL) goto failed;
469 : }
470 :
471 26898 : ret = ldap_parse_basic_url(url, &proto, conn, &dest, &port);
472 26898 : if (ret != 0) {
473 0 : composite_error(result, map_nt_error_from_unix_common(ret));
474 0 : return result;
475 : }
476 :
477 26898 : if (proto == LDAP_PROTO_LDAPI) {
478 0 : struct socket_address *unix_addr;
479 108 : NTSTATUS status = socket_create(state, "unix",
480 : SOCKET_TYPE_STREAM,
481 : &state->sock, 0);
482 108 : if (!NT_STATUS_IS_OK(status)) {
483 0 : return NULL;
484 : }
485 :
486 108 : conn->host = talloc_asprintf(conn, "%s.%s",
487 : lpcfg_netbios_name(conn->lp_ctx),
488 : lpcfg_dnsdomain(conn->lp_ctx));
489 108 : if (composite_nomem(conn->host, state->ctx)) {
490 0 : return result;
491 : }
492 :
493 108 : unix_addr = socket_address_from_strings(state, state->sock->backend_name,
494 : dest, 0);
495 108 : if (composite_nomem(unix_addr, result)) {
496 0 : return result;
497 : }
498 :
499 108 : ctx = socket_connect_send(state->sock, NULL, unix_addr,
500 : 0, result->event_ctx);
501 108 : ctx->async.fn = ldap_connect_recv_unix_conn;
502 108 : ctx->async.private_data = state;
503 108 : return result;
504 : }
505 :
506 26790 : if ((proto == LDAP_PROTO_LDAP) || (proto == LDAP_PROTO_LDAPS)) {
507 26790 : int wrap_flags = lpcfg_client_ldap_sasl_wrapping(conn->lp_ctx);
508 :
509 26790 : conn->ldaps = (proto == LDAP_PROTO_LDAPS);
510 :
511 26790 : if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
512 0 : if (proto == LDAP_PROTO_LDAP) {
513 0 : if (port == 389) {
514 0 : port = 636;
515 0 : proto = LDAP_PROTO_LDAPS;
516 0 : } else if (port == 3268) {
517 0 : port = 3269;
518 0 : proto = LDAP_PROTO_LDAPS;
519 : } else {
520 0 : conn->starttls = true;
521 : }
522 : }
523 0 : conn->ldaps = true;
524 26790 : } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
525 60 : if (proto == LDAP_PROTO_LDAP) {
526 60 : conn->starttls = true;
527 : }
528 60 : conn->ldaps = true;
529 : }
530 :
531 26790 : conn->host = talloc_move(conn, &dest);
532 26790 : conn->port = port;
533 :
534 26790 : if (conn->ldaps) {
535 0 : NTSTATUS status;
536 :
537 594 : status = tstream_tls_params_client_lpcfg(state,
538 : conn->lp_ctx,
539 594 : conn->host,
540 : &state->tls_params);
541 594 : if (!NT_STATUS_IS_OK(status)) {
542 6 : composite_error(result, status);
543 6 : return result;
544 : }
545 : }
546 :
547 26784 : ctx = socket_connect_multi_send(state, conn->host, 1, &conn->port,
548 : lpcfg_resolve_context(conn->lp_ctx),
549 : result->event_ctx);
550 26784 : if (composite_nomem(ctx, result)) {
551 0 : return result;
552 : }
553 :
554 26784 : ctx->async.fn = ldap_connect_recv_tcp_conn;
555 26784 : ctx->async.private_data = state;
556 26784 : return result;
557 : }
558 0 : failed:
559 0 : talloc_free(result);
560 0 : return NULL;
561 : }
562 :
563 : static void ldap_connect_starttls_done(struct ldap_request *ldap_req);
564 : static void ldap_connect_got_tls(struct tevent_req *subreq);
565 :
566 26892 : static void ldap_connect_got_sock(struct composite_context *ctx,
567 : struct ldap_connection *conn)
568 : {
569 122 : struct ldap_connect_state *state =
570 26892 : talloc_get_type_abort(ctx->private_data,
571 : struct ldap_connect_state);
572 26892 : struct tevent_req *subreq = NULL;
573 122 : int fd;
574 122 : int ret;
575 :
576 26892 : socket_set_flags(state->sock, SOCKET_FLAG_NOCLOSE);
577 26892 : fd = socket_get_fd(state->sock);
578 26892 : TALLOC_FREE(state->sock);
579 :
580 26892 : smb_set_close_on_exec(fd);
581 :
582 26892 : ret = set_blocking(fd, false);
583 26892 : if (ret == -1) {
584 0 : NTSTATUS status = map_nt_error_from_unix_common(errno);
585 0 : composite_error(state->ctx, status);
586 0 : return;
587 : }
588 :
589 26892 : ret = tstream_bsd_existing_socket(state, fd, &state->raw);
590 26892 : if (ret == -1) {
591 0 : NTSTATUS status = map_nt_error_from_unix_common(errno);
592 0 : composite_error(state->ctx, status);
593 0 : return;
594 : }
595 :
596 26892 : conn->sockets.raw = talloc_move(conn, &state->raw);
597 26892 : conn->sockets.active = conn->sockets.raw;
598 :
599 26892 : if (!conn->ldaps) {
600 26304 : composite_done(state->ctx);
601 26304 : return;
602 : }
603 :
604 588 : if (conn->starttls) {
605 60 : struct ldap_message msg = {
606 : .type = LDAP_TAG_ExtendedRequest,
607 : .r.ExtendedRequest.oid = LDB_EXTENDED_START_TLS_OID,
608 : };
609 60 : struct ldap_request *ldap_req = NULL;
610 :
611 60 : ldap_req = ldap_request_send(conn, &msg);
612 60 : if (composite_nomem(ldap_req, state->ctx)) {
613 0 : return;
614 : }
615 60 : ldap_req->async.fn = ldap_connect_starttls_done;
616 60 : ldap_req->async.private_data = state;
617 60 : return;
618 : }
619 :
620 528 : subreq = tstream_tls_connect_send(state, state->ctx->event_ctx,
621 : conn->sockets.raw, state->tls_params);
622 528 : if (composite_nomem(subreq, state->ctx)) {
623 0 : return;
624 : }
625 528 : tevent_req_set_callback(subreq, ldap_connect_got_tls, state);
626 : }
627 :
628 60 : static void ldap_connect_starttls_done(struct ldap_request *ldap_req)
629 : {
630 0 : struct ldap_connect_state *state =
631 60 : talloc_get_type_abort(ldap_req->async.private_data,
632 : struct ldap_connect_state);
633 60 : struct ldap_connection *conn = state->conn;
634 60 : NTSTATUS status = ldap_req->status;
635 60 : struct tevent_req *subreq = NULL;
636 :
637 60 : if (!NT_STATUS_IS_OK(status)) {
638 0 : TALLOC_FREE(ldap_req);
639 0 : composite_error(state->ctx, status);
640 0 : return;
641 : }
642 :
643 60 : if (ldap_req->num_replies != 1) {
644 0 : TALLOC_FREE(ldap_req);
645 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
646 0 : composite_error(state->ctx, status);
647 0 : return;
648 : }
649 :
650 60 : if (ldap_req->replies[0]->type != LDAP_TAG_ExtendedResponse) {
651 0 : TALLOC_FREE(ldap_req);
652 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
653 0 : composite_error(state->ctx, status);
654 0 : return;
655 : }
656 :
657 60 : status = ldap_check_response(conn,
658 60 : &ldap_req->replies[0]->r.GeneralResult);
659 60 : if (!NT_STATUS_IS_OK(status)) {
660 0 : TALLOC_FREE(ldap_req);
661 0 : composite_error(state->ctx, status);
662 0 : return;
663 : }
664 :
665 60 : subreq = tstream_tls_connect_send(state, state->ctx->event_ctx,
666 : conn->sockets.raw, state->tls_params);
667 60 : if (composite_nomem(subreq, state->ctx)) {
668 0 : return;
669 : }
670 60 : tevent_req_set_callback(subreq, ldap_connect_got_tls, state);
671 : }
672 :
673 588 : static void ldap_connect_got_tls(struct tevent_req *subreq)
674 : {
675 0 : struct ldap_connect_state *state =
676 588 : tevent_req_callback_data(subreq,
677 : struct ldap_connect_state);
678 0 : int err;
679 0 : int ret;
680 :
681 588 : ret = tstream_tls_connect_recv(subreq, &err, state, &state->tls);
682 588 : TALLOC_FREE(subreq);
683 588 : if (ret == -1) {
684 13 : NTSTATUS status = map_nt_error_from_unix_common(err);
685 13 : composite_error(state->ctx, status);
686 13 : return;
687 : }
688 :
689 575 : talloc_steal(state->tls, state->tls_params);
690 :
691 575 : state->conn->sockets.tls = talloc_move(state->conn->sockets.raw,
692 : &state->tls);
693 575 : state->conn->sockets.active = state->conn->sockets.tls;
694 575 : composite_done(state->ctx);
695 : }
696 :
697 26784 : static void ldap_connect_recv_tcp_conn(struct composite_context *ctx)
698 : {
699 122 : struct ldap_connect_state *state =
700 26784 : talloc_get_type_abort(ctx->async.private_data,
701 : struct ldap_connect_state);
702 26784 : struct ldap_connection *conn = state->conn;
703 122 : uint16_t port;
704 26784 : NTSTATUS status = socket_connect_multi_recv(ctx, state, &state->sock,
705 : &port);
706 26784 : if (!NT_STATUS_IS_OK(status)) {
707 0 : composite_error(state->ctx, status);
708 0 : return;
709 : }
710 :
711 26784 : ldap_connect_got_sock(state->ctx, conn);
712 : }
713 :
714 108 : static void ldap_connect_recv_unix_conn(struct composite_context *ctx)
715 : {
716 0 : struct ldap_connect_state *state =
717 108 : talloc_get_type_abort(ctx->async.private_data,
718 : struct ldap_connect_state);
719 108 : struct ldap_connection *conn = state->conn;
720 :
721 108 : NTSTATUS status = socket_connect_recv(ctx);
722 :
723 108 : if (!NT_STATUS_IS_OK(state->ctx->status)) {
724 0 : composite_error(state->ctx, status);
725 0 : return;
726 : }
727 :
728 108 : ldap_connect_got_sock(state->ctx, conn);
729 : }
730 :
731 26898 : _PUBLIC_ NTSTATUS ldap_connect_recv(struct composite_context *ctx)
732 : {
733 26898 : NTSTATUS status = composite_wait(ctx);
734 26898 : talloc_free(ctx);
735 26898 : return status;
736 : }
737 :
738 26898 : _PUBLIC_ NTSTATUS ldap_connect(struct ldap_connection *conn, const char *url)
739 : {
740 26898 : struct composite_context *ctx = ldap_connect_send(conn, url);
741 26898 : return ldap_connect_recv(ctx);
742 : }
743 :
744 : /* set reconnect parameters */
745 :
746 0 : _PUBLIC_ void ldap_set_reconn_params(struct ldap_connection *conn, int max_retries)
747 : {
748 0 : if (conn) {
749 0 : conn->reconnect.max_retries = max_retries;
750 0 : conn->reconnect.retries = 0;
751 0 : conn->reconnect.previous = time_mono(NULL);
752 : }
753 0 : }
754 :
755 : /* Actually this function is NOT ASYNC safe, FIXME? */
756 0 : static void ldap_reconnect(struct ldap_connection *conn)
757 : {
758 0 : NTSTATUS status;
759 0 : time_t now = time_mono(NULL);
760 :
761 : /* do we have set up reconnect ? */
762 0 : if (conn->reconnect.max_retries == 0) return;
763 :
764 : /* is the retry time expired ? */
765 0 : if (now > conn->reconnect.previous + 30) {
766 0 : conn->reconnect.retries = 0;
767 0 : conn->reconnect.previous = now;
768 : }
769 :
770 : /* are we reconnectind too often and too fast? */
771 0 : if (conn->reconnect.retries > conn->reconnect.max_retries) return;
772 :
773 : /* keep track of the number of reconnections */
774 0 : conn->reconnect.retries++;
775 :
776 : /* reconnect */
777 0 : status = ldap_connect(conn, conn->reconnect.url);
778 0 : if ( ! NT_STATUS_IS_OK(status)) {
779 0 : return;
780 : }
781 :
782 : /* rebind */
783 0 : status = ldap_rebind(conn);
784 0 : if ( ! NT_STATUS_IS_OK(status)) {
785 0 : ldap_connection_dead(conn, status);
786 : }
787 : }
788 :
789 13 : static void ldap_request_destructor_abandon(struct ldap_request *abandon)
790 : {
791 13 : TALLOC_FREE(abandon);
792 13 : }
793 :
794 : /* destroy an open ldap request */
795 604880 : static int ldap_request_destructor(struct ldap_request *req)
796 : {
797 604880 : if (req->state == LDAP_REQUEST_PENDING) {
798 79 : struct ldap_message msg = {
799 : .type = LDAP_TAG_AbandonRequest,
800 79 : .r.AbandonRequest.messageid = req->messageid,
801 : };
802 79 : struct ldap_request *abandon = NULL;
803 :
804 79 : DLIST_REMOVE(req->conn->pending, req);
805 :
806 79 : abandon = ldap_request_send(req->conn, &msg);
807 79 : if (abandon == NULL) {
808 0 : ldap_error_handler(req->conn, NT_STATUS_NO_MEMORY);
809 0 : return 0;
810 : }
811 79 : abandon->async.fn = ldap_request_destructor_abandon;
812 79 : abandon->async.private_data = NULL;
813 : }
814 :
815 604293 : return 0;
816 : }
817 :
818 0 : static void ldap_request_timeout_abandon(struct ldap_request *abandon)
819 : {
820 0 : struct ldap_request *req =
821 0 : talloc_get_type_abort(abandon->async.private_data,
822 : struct ldap_request);
823 :
824 0 : if (req->state == LDAP_REQUEST_PENDING) {
825 0 : DLIST_REMOVE(req->conn->pending, req);
826 : }
827 0 : req->state = LDAP_REQUEST_DONE;
828 0 : if (req->async.fn) {
829 0 : req->async.fn(req);
830 : }
831 0 : }
832 :
833 : /*
834 : called on timeout of a ldap request
835 : */
836 0 : static void ldap_request_timeout(struct tevent_context *ev, struct tevent_timer *te,
837 : struct timeval t, void *private_data)
838 : {
839 0 : struct ldap_request *req =
840 0 : talloc_get_type_abort(private_data,
841 : struct ldap_request);
842 :
843 0 : req->status = NT_STATUS_IO_TIMEOUT;
844 0 : if (req->state == LDAP_REQUEST_PENDING) {
845 0 : struct ldap_message msg = {
846 : .type = LDAP_TAG_AbandonRequest,
847 0 : .r.AbandonRequest.messageid = req->messageid,
848 : };
849 0 : struct ldap_request *abandon = NULL;
850 :
851 0 : abandon = ldap_request_send(req->conn, &msg);
852 0 : if (abandon == NULL) {
853 0 : ldap_error_handler(req->conn, NT_STATUS_NO_MEMORY);
854 0 : return;
855 : }
856 0 : talloc_reparent(req->conn, req, abandon);
857 0 : abandon->async.fn = ldap_request_timeout_abandon;
858 0 : abandon->async.private_data = req;
859 0 : DLIST_REMOVE(req->conn->pending, req);
860 0 : return;
861 : }
862 0 : req->state = LDAP_REQUEST_DONE;
863 0 : if (req->async.fn) {
864 0 : req->async.fn(req);
865 : }
866 : }
867 :
868 :
869 : /*
870 : called on completion of a failed ldap request
871 : */
872 0 : static void ldap_request_failed_complete(struct tevent_context *ev, struct tevent_timer *te,
873 : struct timeval t, void *private_data)
874 : {
875 0 : struct ldap_request *req =
876 0 : talloc_get_type_abort(private_data,
877 : struct ldap_request);
878 :
879 0 : if (req->async.fn) {
880 0 : req->async.fn(req);
881 : }
882 0 : }
883 :
884 : static void ldap_request_written(struct tevent_req *subreq);
885 :
886 : /*
887 : send a ldap message - async interface
888 : */
889 604880 : _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
890 : struct ldap_message *msg)
891 : {
892 587 : struct ldap_request *req;
893 604880 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
894 604880 : struct tevent_req *subreq = NULL;
895 :
896 604880 : req = talloc_zero(conn, struct ldap_request);
897 604880 : if (req == NULL) return NULL;
898 :
899 604880 : if (conn->sockets.active == NULL) {
900 0 : status = NT_STATUS_INVALID_CONNECTION;
901 0 : goto failed;
902 : }
903 :
904 604880 : req->state = LDAP_REQUEST_SEND;
905 604880 : req->conn = conn;
906 604880 : req->messageid = conn->next_messageid++;
907 604880 : if (conn->next_messageid == 0) {
908 0 : conn->next_messageid = 1;
909 : }
910 604880 : req->type = msg->type;
911 604880 : if (req->messageid == -1) {
912 0 : goto failed;
913 : }
914 :
915 604880 : talloc_set_destructor(req, ldap_request_destructor);
916 :
917 604880 : msg->messageid = req->messageid;
918 :
919 604880 : if (!ldap_encode(msg, samba_ldap_control_handlers(), &req->data, req)) {
920 0 : status = NT_STATUS_INTERNAL_ERROR;
921 0 : goto failed;
922 : }
923 :
924 : /* put a timeout on the request */
925 604880 : req->time_event = tevent_add_timer(conn->event.event_ctx, req,
926 : timeval_current_ofs(conn->timeout, 0),
927 : ldap_request_timeout, req);
928 604880 : if (req->time_event == NULL) {
929 0 : status = NT_STATUS_NO_MEMORY;
930 0 : goto failed;
931 : }
932 :
933 604880 : req->write_iov.iov_base = req->data.data;
934 604880 : req->write_iov.iov_len = req->data.length;
935 :
936 605467 : subreq = tstream_writev_queue_send(req, conn->event.event_ctx,
937 : conn->sockets.active,
938 : conn->sockets.send_queue,
939 604880 : &req->write_iov, 1);
940 604880 : if (subreq == NULL) {
941 0 : status = NT_STATUS_NO_MEMORY;
942 0 : goto failed;
943 : }
944 604880 : tevent_req_set_callback(subreq, ldap_request_written, req);
945 :
946 604880 : req->state = LDAP_REQUEST_PENDING;
947 604880 : DLIST_ADD(conn->pending, req);
948 :
949 604293 : return req;
950 :
951 0 : failed:
952 0 : req->status = status;
953 0 : req->state = LDAP_REQUEST_ERROR;
954 0 : tevent_add_timer(conn->event.event_ctx, req, timeval_zero(),
955 : ldap_request_failed_complete, req);
956 :
957 0 : return req;
958 : }
959 :
960 604814 : static void ldap_request_written(struct tevent_req *subreq)
961 : {
962 587 : struct ldap_request *req =
963 604814 : tevent_req_callback_data(subreq,
964 : struct ldap_request);
965 587 : int err;
966 587 : ssize_t ret;
967 :
968 604814 : ret = tstream_writev_queue_recv(subreq, &err);
969 604814 : TALLOC_FREE(subreq);
970 604814 : if (ret == -1) {
971 0 : NTSTATUS error = map_nt_error_from_unix_common(err);
972 0 : ldap_error_handler(req->conn, error);
973 0 : return;
974 : }
975 :
976 604814 : if (req->type == LDAP_TAG_AbandonRequest ||
977 604213 : req->type == LDAP_TAG_UnbindRequest)
978 : {
979 15 : if (req->state == LDAP_REQUEST_PENDING) {
980 15 : DLIST_REMOVE(req->conn->pending, req);
981 : }
982 15 : req->state = LDAP_REQUEST_DONE;
983 15 : if (req->async.fn) {
984 13 : req->async.fn(req);
985 : }
986 15 : return;
987 : }
988 :
989 604799 : ldap_connection_recv_next(req->conn);
990 : }
991 :
992 :
993 : /*
994 : wait for a request to complete
995 : note that this does not destroy the request
996 : */
997 450 : _PUBLIC_ NTSTATUS ldap_request_wait(struct ldap_request *req)
998 : {
999 2606 : while (req->state < LDAP_REQUEST_DONE) {
1000 2156 : if (tevent_loop_once(req->conn->event.event_ctx) != 0) {
1001 0 : req->state = LDAP_REQUEST_ERROR;
1002 0 : req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1003 0 : break;
1004 : }
1005 : }
1006 450 : return req->status;
1007 : }
1008 :
1009 :
1010 : /*
1011 : a mapping of ldap response code to strings
1012 : */
1013 : static const struct {
1014 : enum ldap_result_code code;
1015 : const char *str;
1016 : } ldap_code_map[] = {
1017 : #define _LDAP_MAP_CODE(c) { c, #c }
1018 : _LDAP_MAP_CODE(LDAP_SUCCESS),
1019 : _LDAP_MAP_CODE(LDAP_OPERATIONS_ERROR),
1020 : _LDAP_MAP_CODE(LDAP_PROTOCOL_ERROR),
1021 : _LDAP_MAP_CODE(LDAP_TIME_LIMIT_EXCEEDED),
1022 : _LDAP_MAP_CODE(LDAP_SIZE_LIMIT_EXCEEDED),
1023 : _LDAP_MAP_CODE(LDAP_COMPARE_FALSE),
1024 : _LDAP_MAP_CODE(LDAP_COMPARE_TRUE),
1025 : _LDAP_MAP_CODE(LDAP_AUTH_METHOD_NOT_SUPPORTED),
1026 : _LDAP_MAP_CODE(LDAP_STRONG_AUTH_REQUIRED),
1027 : _LDAP_MAP_CODE(LDAP_REFERRAL),
1028 : _LDAP_MAP_CODE(LDAP_ADMIN_LIMIT_EXCEEDED),
1029 : _LDAP_MAP_CODE(LDAP_UNAVAILABLE_CRITICAL_EXTENSION),
1030 : _LDAP_MAP_CODE(LDAP_CONFIDENTIALITY_REQUIRED),
1031 : _LDAP_MAP_CODE(LDAP_SASL_BIND_IN_PROGRESS),
1032 : _LDAP_MAP_CODE(LDAP_NO_SUCH_ATTRIBUTE),
1033 : _LDAP_MAP_CODE(LDAP_UNDEFINED_ATTRIBUTE_TYPE),
1034 : _LDAP_MAP_CODE(LDAP_INAPPROPRIATE_MATCHING),
1035 : _LDAP_MAP_CODE(LDAP_CONSTRAINT_VIOLATION),
1036 : _LDAP_MAP_CODE(LDAP_ATTRIBUTE_OR_VALUE_EXISTS),
1037 : _LDAP_MAP_CODE(LDAP_INVALID_ATTRIBUTE_SYNTAX),
1038 : _LDAP_MAP_CODE(LDAP_NO_SUCH_OBJECT),
1039 : _LDAP_MAP_CODE(LDAP_ALIAS_PROBLEM),
1040 : _LDAP_MAP_CODE(LDAP_INVALID_DN_SYNTAX),
1041 : _LDAP_MAP_CODE(LDAP_ALIAS_DEREFERENCING_PROBLEM),
1042 : _LDAP_MAP_CODE(LDAP_INAPPROPRIATE_AUTHENTICATION),
1043 : _LDAP_MAP_CODE(LDAP_INVALID_CREDENTIALS),
1044 : _LDAP_MAP_CODE(LDAP_INSUFFICIENT_ACCESS_RIGHTS),
1045 : _LDAP_MAP_CODE(LDAP_BUSY),
1046 : _LDAP_MAP_CODE(LDAP_UNAVAILABLE),
1047 : _LDAP_MAP_CODE(LDAP_UNWILLING_TO_PERFORM),
1048 : _LDAP_MAP_CODE(LDAP_LOOP_DETECT),
1049 : _LDAP_MAP_CODE(LDAP_NAMING_VIOLATION),
1050 : _LDAP_MAP_CODE(LDAP_OBJECT_CLASS_VIOLATION),
1051 : _LDAP_MAP_CODE(LDAP_NOT_ALLOWED_ON_NON_LEAF),
1052 : _LDAP_MAP_CODE(LDAP_NOT_ALLOWED_ON_RDN),
1053 : _LDAP_MAP_CODE(LDAP_ENTRY_ALREADY_EXISTS),
1054 : _LDAP_MAP_CODE(LDAP_OBJECT_CLASS_MODS_PROHIBITED),
1055 : _LDAP_MAP_CODE(LDAP_AFFECTS_MULTIPLE_DSAS),
1056 : _LDAP_MAP_CODE(LDAP_OTHER)
1057 : };
1058 :
1059 : /*
1060 : used to setup the status code from a ldap response
1061 : */
1062 569343 : _PUBLIC_ NTSTATUS ldap_check_response(struct ldap_connection *conn, struct ldap_Result *r)
1063 : {
1064 465 : size_t i;
1065 569343 : const char *codename = "unknown";
1066 :
1067 569343 : if (r->resultcode == LDAP_SUCCESS) {
1068 517242 : return NT_STATUS_OK;
1069 : }
1070 :
1071 52101 : if (conn->last_error) {
1072 42042 : talloc_free(conn->last_error);
1073 : }
1074 :
1075 1118266 : for (i=0;i<ARRAY_SIZE(ldap_code_map);i++) {
1076 1118266 : if ((enum ldap_result_code)r->resultcode == ldap_code_map[i].code) {
1077 52101 : codename = ldap_code_map[i].str;
1078 52101 : break;
1079 : }
1080 : }
1081 :
1082 156303 : conn->last_error = talloc_asprintf(conn, "LDAP error %u %s - %s <%s> <%s>",
1083 : r->resultcode,
1084 : codename,
1085 52101 : r->dn?r->dn:"(NULL)",
1086 52101 : r->errormessage?r->errormessage:"",
1087 52101 : r->referral?r->referral:"");
1088 :
1089 52101 : return NT_STATUS_LDAP(r->resultcode);
1090 : }
1091 :
1092 : /*
1093 : return error string representing the last error
1094 : */
1095 53087 : _PUBLIC_ const char *ldap_errstr(struct ldap_connection *conn,
1096 : TALLOC_CTX *mem_ctx,
1097 : NTSTATUS status)
1098 : {
1099 53087 : if (NT_STATUS_IS_LDAP(status) && conn->last_error != NULL) {
1100 52489 : return talloc_strdup(mem_ctx, conn->last_error);
1101 : }
1102 598 : return talloc_asprintf(mem_ctx, "LDAP client internal error: %s", nt_errstr(status));
1103 : }
1104 :
1105 :
1106 : /*
1107 : return the Nth result message, waiting if necessary
1108 : */
1109 35946 : _PUBLIC_ NTSTATUS ldap_result_n(struct ldap_request *req, int n, struct ldap_message **msg)
1110 : {
1111 35946 : *msg = NULL;
1112 :
1113 35946 : NT_STATUS_HAVE_NO_MEMORY(req);
1114 :
1115 161006 : while (req->state < LDAP_REQUEST_DONE && n >= req->num_replies) {
1116 125060 : if (tevent_loop_once(req->conn->event.event_ctx) != 0) {
1117 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1118 : }
1119 : }
1120 :
1121 35946 : if (n < req->num_replies) {
1122 35946 : *msg = req->replies[n];
1123 35946 : return NT_STATUS_OK;
1124 : }
1125 :
1126 0 : if (!NT_STATUS_IS_OK(req->status)) {
1127 0 : return req->status;
1128 : }
1129 :
1130 0 : return NT_STATUS_NO_MORE_ENTRIES;
1131 : }
1132 :
1133 :
1134 : /*
1135 : return a single result message, checking if it is of the expected LDAP type
1136 : */
1137 14 : _PUBLIC_ NTSTATUS ldap_result_one(struct ldap_request *req, struct ldap_message **msg, int type)
1138 : {
1139 0 : NTSTATUS status;
1140 14 : status = ldap_result_n(req, 0, msg);
1141 14 : if (!NT_STATUS_IS_OK(status)) {
1142 0 : return status;
1143 : }
1144 14 : if ((*msg) != NULL && (*msg)->type != (enum ldap_request_tag)type) {
1145 0 : *msg = NULL;
1146 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1147 : }
1148 14 : return status;
1149 : }
|