Line data Source code
1 : /*
2 : SSSD
3 :
4 : Async LDAP Helper routines
5 :
6 : Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
7 : Copyright (C) 2010, rhafer@suse.de, Novell Inc.
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include <unistd.h>
24 : #include <fcntl.h>
25 : #include <sasl/sasl.h>
26 : #include "util/util.h"
27 : #include "util/sss_krb5.h"
28 : #include "util/sss_ldap.h"
29 : #include "util/strtonum.h"
30 : #include "providers/ldap/sdap_async_private.h"
31 : #include "providers/ldap/ldap_common.h"
32 :
33 : /* ==Connect-to-LDAP-Server=============================================== */
34 :
35 : struct sdap_rebind_proc_params {
36 : struct sdap_options *opts;
37 : struct sdap_handle *sh;
38 : bool use_start_tls;
39 : };
40 :
41 : static int sdap_rebind_proc(LDAP *ldap, LDAP_CONST char *url, ber_tag_t request,
42 : ber_int_t msgid, void *params);
43 :
44 : struct sdap_connect_state {
45 : struct tevent_context *ev;
46 : struct sdap_options *opts;
47 : struct sdap_handle *sh;
48 : const char *uri;
49 : bool use_start_tls;
50 :
51 : struct sdap_op *op;
52 :
53 : struct sdap_msg *reply;
54 : int result;
55 : };
56 :
57 : static void sdap_sys_connect_done(struct tevent_req *subreq);
58 : static void sdap_connect_done(struct sdap_op *op,
59 : struct sdap_msg *reply,
60 : int error, void *pvt);
61 :
62 0 : struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
63 : struct tevent_context *ev,
64 : struct sdap_options *opts,
65 : const char *uri,
66 : struct sockaddr_storage *sockaddr,
67 : bool use_start_tls)
68 : {
69 : struct tevent_req *req;
70 : struct tevent_req *subreq;
71 : struct sdap_connect_state *state;
72 : int ret;
73 : int timeout;
74 :
75 0 : req = tevent_req_create(memctx, &state, struct sdap_connect_state);
76 0 : if (!req) return NULL;
77 :
78 0 : state->reply = talloc(state, struct sdap_msg);
79 0 : if (!state->reply) {
80 0 : talloc_zfree(req);
81 0 : return NULL;
82 : }
83 :
84 0 : state->ev = ev;
85 0 : state->opts = opts;
86 0 : state->use_start_tls = use_start_tls;
87 :
88 0 : state->uri = talloc_asprintf(state, "%s", uri);
89 0 : if (!state->uri) {
90 0 : talloc_zfree(req);
91 0 : return NULL;
92 : }
93 :
94 0 : state->sh = sdap_handle_create(state);
95 0 : if (!state->sh) {
96 0 : talloc_zfree(req);
97 0 : return NULL;
98 : }
99 :
100 0 : state->sh->page_size = dp_opt_get_int(state->opts->basic,
101 : SDAP_PAGE_SIZE);
102 :
103 0 : timeout = dp_opt_get_int(state->opts->basic, SDAP_NETWORK_TIMEOUT);
104 :
105 0 : subreq = sss_ldap_init_send(state, ev, state->uri, sockaddr,
106 : sizeof(struct sockaddr_storage),
107 : timeout);
108 0 : if (subreq == NULL) {
109 0 : ret = ENOMEM;
110 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldap_init_send failed.\n");
111 0 : goto fail;
112 : }
113 :
114 0 : tevent_req_set_callback(subreq, sdap_sys_connect_done, req);
115 0 : return req;
116 :
117 : fail:
118 0 : tevent_req_error(req, ret);
119 0 : tevent_req_post(req, ev);
120 0 : return req;
121 : }
122 :
123 0 : static void sdap_sys_connect_done(struct tevent_req *subreq)
124 : {
125 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
126 : struct tevent_req);
127 0 : struct sdap_connect_state *state = tevent_req_data(req,
128 : struct sdap_connect_state);
129 : struct timeval tv;
130 : int ver;
131 : int lret;
132 : int optret;
133 0 : int ret = EOK;
134 : int msgid;
135 0 : char *errmsg = NULL;
136 : bool ldap_referrals;
137 : const char *ldap_deref;
138 : int ldap_deref_val;
139 : struct sdap_rebind_proc_params *rebind_proc_params;
140 : int sd;
141 : bool sasl_nocanon;
142 : const char *sasl_mech;
143 : int sasl_minssf;
144 : ber_len_t ber_sasl_minssf;
145 :
146 0 : ret = sss_ldap_init_recv(subreq, &state->sh->ldap, &sd);
147 0 : talloc_zfree(subreq);
148 0 : if (ret != EOK) {
149 0 : DEBUG(SSSDBG_CRIT_FAILURE,
150 : "sdap_async_connect_call request failed: [%d]: %s.\n",
151 : ret, sss_strerror(ret));
152 0 : tevent_req_error(req, ret);
153 0 : return;
154 : }
155 :
156 0 : ret = setup_ldap_connection_callbacks(state->sh, state->ev);
157 0 : if (ret != EOK) {
158 0 : DEBUG(SSSDBG_CRIT_FAILURE,
159 : "setup_ldap_connection_callbacks failed: [%d]: %s.\n",
160 : ret, sss_strerror(ret));
161 0 : goto fail;
162 : }
163 :
164 : /* If sss_ldap_init_recv() does not return a valid file descriptor we have
165 : * to assume that the connection callback will be called by internally by
166 : * the OpenLDAP client library. */
167 0 : if (sd != -1) {
168 0 : ret = sdap_call_conn_cb(state->uri, sd, state->sh);
169 0 : if (ret != EOK) {
170 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_call_conn_cb failed.\n");
171 0 : goto fail;
172 : }
173 : }
174 :
175 : /* Force ldap version to 3 */
176 0 : ver = LDAP_VERSION3;
177 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_PROTOCOL_VERSION, &ver);
178 0 : if (lret != LDAP_OPT_SUCCESS) {
179 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set ldap version to 3\n");
180 0 : goto fail;
181 : }
182 :
183 : /* TODO: maybe this can be remove when we go async, currently we need it
184 : * to handle EINTR during poll(). */
185 0 : ret = ldap_set_option(state->sh->ldap, LDAP_OPT_RESTART, LDAP_OPT_ON);
186 0 : if (ret != LDAP_OPT_SUCCESS) {
187 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set restart option.\n");
188 : }
189 :
190 : /* Set Network Timeout */
191 0 : tv.tv_sec = dp_opt_get_int(state->opts->basic, SDAP_NETWORK_TIMEOUT);
192 0 : tv.tv_usec = 0;
193 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_NETWORK_TIMEOUT, &tv);
194 0 : if (lret != LDAP_OPT_SUCCESS) {
195 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set network timeout to %d\n",
196 : dp_opt_get_int(state->opts->basic, SDAP_NETWORK_TIMEOUT));
197 0 : goto fail;
198 : }
199 :
200 : /* Set Default Timeout */
201 0 : tv.tv_sec = dp_opt_get_int(state->opts->basic, SDAP_OPT_TIMEOUT);
202 0 : tv.tv_usec = 0;
203 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_TIMEOUT, &tv);
204 0 : if (lret != LDAP_OPT_SUCCESS) {
205 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set default timeout to %d\n",
206 : dp_opt_get_int(state->opts->basic, SDAP_OPT_TIMEOUT));
207 0 : goto fail;
208 : }
209 :
210 : /* Set Referral chasing */
211 0 : ldap_referrals = dp_opt_get_bool(state->opts->basic, SDAP_REFERRALS);
212 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_REFERRALS,
213 : (ldap_referrals ? LDAP_OPT_ON : LDAP_OPT_OFF));
214 0 : if (lret != LDAP_OPT_SUCCESS) {
215 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set referral chasing to %s\n",
216 : (ldap_referrals ? "LDAP_OPT_ON" : "LDAP_OPT_OFF"));
217 0 : goto fail;
218 : }
219 :
220 0 : if (ldap_referrals) {
221 0 : rebind_proc_params = talloc_zero(state->sh,
222 : struct sdap_rebind_proc_params);
223 0 : if (rebind_proc_params == NULL) {
224 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
225 0 : ret = ENOMEM;
226 0 : goto fail;
227 : }
228 :
229 0 : rebind_proc_params->opts = state->opts;
230 0 : rebind_proc_params->sh = state->sh;
231 0 : rebind_proc_params->use_start_tls = state->use_start_tls;
232 :
233 0 : lret = ldap_set_rebind_proc(state->sh->ldap, sdap_rebind_proc,
234 : rebind_proc_params);
235 0 : if (lret != LDAP_SUCCESS) {
236 0 : DEBUG(SSSDBG_CRIT_FAILURE, "ldap_set_rebind_proc failed.\n");
237 0 : goto fail;
238 : }
239 : }
240 :
241 : /* Set alias dereferencing */
242 0 : ldap_deref = dp_opt_get_string(state->opts->basic, SDAP_DEREF);
243 0 : if (ldap_deref != NULL) {
244 0 : ret = deref_string_to_val(ldap_deref, &ldap_deref_val);
245 0 : if (ret != EOK) {
246 0 : DEBUG(SSSDBG_CRIT_FAILURE, "deref_string_to_val failed.\n");
247 0 : goto fail;
248 : }
249 :
250 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_DEREF, &ldap_deref_val);
251 0 : if (lret != LDAP_OPT_SUCCESS) {
252 0 : DEBUG(SSSDBG_CRIT_FAILURE,
253 : "Failed to set deref option to %d\n", ldap_deref_val);
254 0 : goto fail;
255 : }
256 :
257 : }
258 :
259 : /* Set host name canonicalization for LDAP SASL bind */
260 0 : sasl_nocanon = !dp_opt_get_bool(state->opts->basic, SDAP_SASL_CANONICALIZE);
261 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_X_SASL_NOCANON,
262 : sasl_nocanon ? LDAP_OPT_ON : LDAP_OPT_OFF);
263 0 : if (lret != LDAP_OPT_SUCCESS) {
264 : /* Do not fail, just warn into both debug logs and syslog */
265 0 : DEBUG(SSSDBG_MINOR_FAILURE,
266 : "Failed to set LDAP SASL nocanon option to %s. If your system "
267 : "is configured to use SASL, LDAP operations might fail.\n",
268 : sasl_nocanon ? "true" : "false");
269 0 : sss_log(SSS_LOG_INFO,
270 : "Failed to set LDAP SASL nocanon option to %s. If your system "
271 : "is configured to use SASL, LDAP operations might fail.\n",
272 : sasl_nocanon ? "true" : "false");
273 : }
274 :
275 0 : sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
276 0 : if (sasl_mech != NULL) {
277 0 : sasl_minssf = dp_opt_get_int(state->opts->basic, SDAP_SASL_MINSSF);
278 0 : if (sasl_minssf >= 0) {
279 0 : ber_sasl_minssf = (ber_len_t)sasl_minssf;
280 0 : lret = ldap_set_option(state->sh->ldap, LDAP_OPT_X_SASL_SSF_MIN,
281 : &ber_sasl_minssf);
282 0 : if (lret != LDAP_OPT_SUCCESS) {
283 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set LDAP MIN SSF option "
284 : "to %d\n", sasl_minssf);
285 0 : goto fail;
286 : }
287 : }
288 : }
289 :
290 : /* if we do not use start_tls the connection is not really connected yet
291 : * just fake an async procedure and leave connection to the bind call */
292 0 : if (!state->use_start_tls) {
293 0 : tevent_req_done(req);
294 0 : return;
295 : }
296 :
297 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Executing START TLS\n");
298 :
299 0 : lret = ldap_start_tls(state->sh->ldap, NULL, NULL, &msgid);
300 0 : if (lret != LDAP_SUCCESS) {
301 0 : optret = sss_ldap_get_diagnostic_msg(state, state->sh->ldap,
302 : &errmsg);
303 0 : if (optret == LDAP_SUCCESS) {
304 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_start_tls failed: [%s] [%s]\n",
305 : sss_ldap_err2string(lret),
306 : errmsg);
307 0 : sss_log(SSS_LOG_ERR, "Could not start TLS. %s", errmsg);
308 : }
309 : else {
310 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_start_tls failed: [%s]\n",
311 : sss_ldap_err2string(lret));
312 0 : sss_log(SSS_LOG_ERR, "Could not start TLS. "
313 : "Check for certificate issues.");
314 : }
315 0 : goto fail;
316 : }
317 :
318 0 : ret = sdap_set_connected(state->sh, state->ev);
319 0 : if (ret) goto fail;
320 :
321 0 : ret = sdap_op_add(state, state->ev, state->sh, msgid,
322 : sdap_connect_done, req,
323 0 : dp_opt_get_int(state->opts->basic, SDAP_OPT_TIMEOUT),
324 : &state->op);
325 0 : if (ret) {
326 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set up operation!\n");
327 0 : goto fail;
328 : }
329 :
330 0 : return;
331 :
332 : fail:
333 0 : if (ret) {
334 0 : tevent_req_error(req, ret);
335 : } else {
336 0 : if (lret == LDAP_SERVER_DOWN) {
337 0 : tevent_req_error(req, ETIMEDOUT);
338 : } else {
339 0 : tevent_req_error(req, EIO);
340 : }
341 : }
342 0 : return;
343 : }
344 :
345 0 : static void sdap_connect_done(struct sdap_op *op,
346 : struct sdap_msg *reply,
347 : int error, void *pvt)
348 : {
349 0 : struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
350 0 : struct sdap_connect_state *state = tevent_req_data(req,
351 : struct sdap_connect_state);
352 0 : char *errmsg = NULL;
353 : char *tlserr;
354 : int ret;
355 : int optret;
356 :
357 0 : if (error) {
358 0 : tevent_req_error(req, error);
359 0 : return;
360 : }
361 :
362 0 : state->reply = talloc_steal(state, reply);
363 :
364 0 : ret = ldap_parse_result(state->sh->ldap, state->reply->msg,
365 : &state->result, NULL, &errmsg, NULL, NULL, 0);
366 0 : if (ret != LDAP_SUCCESS) {
367 0 : DEBUG(SSSDBG_OP_FAILURE,
368 : "ldap_parse_result failed (%d)\n", state->op->msgid);
369 0 : tevent_req_error(req, EIO);
370 0 : return;
371 : }
372 :
373 0 : DEBUG(SSSDBG_MINOR_FAILURE, "START TLS result: %s(%d), %s\n",
374 : sss_ldap_err2string(state->result), state->result, errmsg);
375 0 : ldap_memfree(errmsg);
376 :
377 0 : if (ldap_tls_inplace(state->sh->ldap)) {
378 0 : DEBUG(SSSDBG_TRACE_ALL, "SSL/TLS handler already in place.\n");
379 0 : tevent_req_done(req);
380 0 : return;
381 : }
382 :
383 : /* FIXME: take care that ldap_install_tls might block */
384 0 : ret = ldap_install_tls(state->sh->ldap);
385 0 : if (ret != LDAP_SUCCESS) {
386 :
387 0 : optret = sss_ldap_get_diagnostic_msg(state, state->sh->ldap,
388 : &tlserr);
389 0 : if (optret == LDAP_SUCCESS) {
390 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_install_tls failed: [%s] [%s]\n",
391 : sss_ldap_err2string(ret),
392 : tlserr);
393 0 : sss_log(SSS_LOG_ERR, "Could not start TLS encryption. %s", tlserr);
394 : }
395 : else {
396 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_install_tls failed: [%s]\n",
397 : sss_ldap_err2string(ret));
398 0 : sss_log(SSS_LOG_ERR, "Could not start TLS encryption. "
399 : "Check for certificate issues.");
400 : }
401 :
402 0 : state->result = ret;
403 0 : tevent_req_error(req, EIO);
404 0 : return;
405 : }
406 :
407 0 : tevent_req_done(req);
408 : }
409 :
410 0 : int sdap_connect_recv(struct tevent_req *req,
411 : TALLOC_CTX *memctx,
412 : struct sdap_handle **sh)
413 : {
414 0 : struct sdap_connect_state *state = tevent_req_data(req,
415 : struct sdap_connect_state);
416 :
417 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
418 :
419 0 : *sh = talloc_steal(memctx, state->sh);
420 0 : if (!*sh) {
421 0 : return ENOMEM;
422 : }
423 0 : return EOK;
424 : }
425 :
426 : struct sdap_connect_host_state {
427 : struct tevent_context *ev;
428 : struct sdap_options *opts;
429 : char *uri;
430 : char *protocol;
431 : char *host;
432 : int port;
433 : bool use_start_tls;
434 :
435 : struct sdap_handle *sh;
436 : };
437 :
438 : static void sdap_connect_host_resolv_done(struct tevent_req *subreq);
439 : static void sdap_connect_host_done(struct tevent_req *subreq);
440 :
441 0 : struct tevent_req *sdap_connect_host_send(TALLOC_CTX *mem_ctx,
442 : struct tevent_context *ev,
443 : struct sdap_options *opts,
444 : struct resolv_ctx *resolv_ctx,
445 : enum restrict_family family_order,
446 : enum host_database *host_db,
447 : const char *protocol,
448 : const char *host,
449 : int port,
450 : bool use_start_tls)
451 : {
452 0 : struct sdap_connect_host_state *state = NULL;
453 0 : struct tevent_req *req = NULL;
454 0 : struct tevent_req *subreq = NULL;
455 : errno_t ret;
456 :
457 0 : req = tevent_req_create(mem_ctx, &state,
458 : struct sdap_connect_host_state);
459 0 : if (req == NULL) {
460 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
461 0 : return NULL;
462 : }
463 :
464 0 : state->ev = ev;
465 0 : state->opts = opts;
466 0 : state->port = port;
467 0 : state->use_start_tls = use_start_tls;
468 :
469 0 : state->protocol = talloc_strdup(state, protocol);
470 0 : if (state->protocol == NULL) {
471 0 : ret = ENOMEM;
472 0 : goto immediately;
473 : }
474 :
475 0 : state->host = talloc_strdup(state, host);
476 0 : if (state->host == NULL) {
477 0 : ret = ENOMEM;
478 0 : goto immediately;
479 : }
480 :
481 0 : state->uri = talloc_asprintf(state, "%s://%s:%d", protocol, host, port);
482 0 : if (state->uri == NULL) {
483 0 : ret = ENOMEM;
484 0 : goto immediately;
485 : }
486 :
487 0 : DEBUG(SSSDBG_TRACE_FUNC, "Resolving host %s\n", host);
488 :
489 0 : subreq = resolv_gethostbyname_send(state, state->ev, resolv_ctx,
490 : host, family_order, host_db);
491 0 : if (subreq == NULL) {
492 0 : ret = ENOMEM;
493 0 : goto immediately;
494 : }
495 :
496 0 : tevent_req_set_callback(subreq, sdap_connect_host_resolv_done, req);
497 :
498 0 : return req;
499 :
500 : immediately:
501 0 : if (ret == EOK) {
502 0 : tevent_req_done(req);
503 : } else {
504 0 : tevent_req_error(req, ret);
505 : }
506 0 : tevent_req_post(req, ev);
507 :
508 0 : return req;
509 : }
510 :
511 0 : static void sdap_connect_host_resolv_done(struct tevent_req *subreq)
512 : {
513 0 : struct tevent_req *req = NULL;
514 0 : struct sdap_connect_host_state *state = NULL;
515 0 : struct resolv_hostent *hostent = NULL;
516 0 : struct sockaddr_storage *sockaddr = NULL;
517 : int status;
518 : errno_t ret;
519 :
520 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
521 0 : state = tevent_req_data(req, struct sdap_connect_host_state);
522 :
523 0 : ret = resolv_gethostbyname_recv(subreq, state, &status, NULL, &hostent);
524 0 : talloc_zfree(subreq);
525 0 : if (ret != EOK) {
526 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to resolve host %s: %s\n",
527 : state->host, resolv_strerror(status));
528 0 : goto done;
529 : }
530 :
531 0 : sockaddr = resolv_get_sockaddr_address(state, hostent, state->port);
532 0 : if (sockaddr == NULL) {
533 0 : DEBUG(SSSDBG_OP_FAILURE, "resolv_get_sockaddr_address() failed\n");
534 0 : ret = EIO;
535 0 : goto done;
536 : }
537 :
538 0 : DEBUG(SSSDBG_TRACE_FUNC, "Connecting to %s\n", state->uri);
539 :
540 0 : subreq = sdap_connect_send(state, state->ev, state->opts,
541 0 : state->uri, sockaddr, state->use_start_tls);
542 0 : if (subreq == NULL) {
543 0 : ret = ENOMEM;
544 0 : goto done;
545 : }
546 :
547 0 : tevent_req_set_callback(subreq, sdap_connect_host_done, req);
548 :
549 0 : ret = EAGAIN;
550 :
551 : done:
552 0 : if (ret == EOK) {
553 0 : tevent_req_done(req);
554 0 : } else if (ret != EAGAIN) {
555 0 : tevent_req_error(req, ret);
556 : }
557 :
558 0 : return;
559 : }
560 :
561 0 : static void sdap_connect_host_done(struct tevent_req *subreq)
562 : {
563 0 : struct sdap_connect_host_state *state = NULL;
564 0 : struct tevent_req *req = NULL;
565 : errno_t ret;
566 :
567 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
568 0 : state = tevent_req_data(req, struct sdap_connect_host_state);
569 :
570 0 : ret = sdap_connect_recv(subreq, state, &state->sh);
571 0 : talloc_zfree(subreq);
572 0 : if (ret != EOK) {
573 0 : goto done;
574 : }
575 :
576 : /* if TLS was used, the sdap handle is already marked as connected */
577 0 : if (!state->use_start_tls) {
578 : /* we need to mark handle as connected to allow anonymous bind */
579 0 : ret = sdap_set_connected(state->sh, state->ev);
580 0 : if (ret != EOK) {
581 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_set_connected() failed\n");
582 0 : goto done;
583 : }
584 : }
585 :
586 0 : DEBUG(SSSDBG_TRACE_FUNC, "Successful connection to %s\n", state->uri);
587 :
588 : done:
589 0 : if (ret != EOK) {
590 0 : tevent_req_error(req, ret);
591 0 : return;
592 : }
593 :
594 0 : tevent_req_done(req);
595 : }
596 :
597 0 : errno_t sdap_connect_host_recv(TALLOC_CTX *mem_ctx,
598 : struct tevent_req *req,
599 : struct sdap_handle **_sh)
600 : {
601 0 : struct sdap_connect_host_state *state = NULL;
602 0 : state = tevent_req_data(req, struct sdap_connect_host_state);
603 :
604 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
605 :
606 0 : *_sh = talloc_steal(mem_ctx, state->sh);
607 :
608 0 : return EOK;
609 : }
610 :
611 :
612 : /* ==Simple-Bind========================================================== */
613 :
614 : struct simple_bind_state {
615 : struct tevent_context *ev;
616 : struct sdap_handle *sh;
617 : const char *user_dn;
618 : struct berval *pw;
619 :
620 : struct sdap_op *op;
621 :
622 : struct sdap_msg *reply;
623 : struct sdap_ppolicy_data *ppolicy;
624 : };
625 :
626 : static void simple_bind_done(struct sdap_op *op,
627 : struct sdap_msg *reply,
628 : int error, void *pvt);
629 :
630 0 : static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
631 : struct tevent_context *ev,
632 : struct sdap_handle *sh,
633 : int timeout,
634 : const char *user_dn,
635 : struct berval *pw)
636 : {
637 : struct tevent_req *req;
638 : struct simple_bind_state *state;
639 0 : int ret = EOK;
640 : int msgid;
641 : int ldap_err;
642 0 : LDAPControl **request_controls = NULL;
643 0 : LDAPControl *ctrls[2] = { NULL, NULL };
644 :
645 0 : req = tevent_req_create(memctx, &state, struct simple_bind_state);
646 0 : if (!req) return NULL;
647 :
648 0 : state->reply = talloc(state, struct sdap_msg);
649 0 : if (!state->reply) {
650 0 : talloc_zfree(req);
651 0 : return NULL;
652 : }
653 :
654 0 : state->ev = ev;
655 0 : state->sh = sh;
656 0 : state->user_dn = user_dn;
657 0 : state->pw = pw;
658 :
659 0 : ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
660 : 0, NULL, 0, &ctrls[0]);
661 0 : if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
662 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldap_control_create failed to create "
663 : "Password Policy control.\n");
664 0 : goto fail;
665 : }
666 0 : request_controls = ctrls;
667 :
668 0 : DEBUG(SSSDBG_CONF_SETTINGS,
669 : "Executing simple bind as: %s\n", state->user_dn);
670 :
671 0 : ret = ldap_sasl_bind(state->sh->ldap, state->user_dn, LDAP_SASL_SIMPLE,
672 : pw, request_controls, NULL, &msgid);
673 0 : if (ctrls[0]) ldap_control_free(ctrls[0]);
674 0 : if (ret == -1 || msgid == -1) {
675 0 : ret = ldap_get_option(state->sh->ldap,
676 : LDAP_OPT_RESULT_CODE, &ldap_err);
677 0 : if (ret != LDAP_OPT_SUCCESS) {
678 0 : DEBUG(SSSDBG_CRIT_FAILURE,
679 : "ldap_bind failed (couldn't get ldap error)\n");
680 0 : ret = LDAP_LOCAL_ERROR;
681 : } else {
682 0 : DEBUG(SSSDBG_CRIT_FAILURE, "ldap_bind failed (%d)[%s]\n",
683 : ldap_err, sss_ldap_err2string(ldap_err));
684 0 : ret = ldap_err;
685 : }
686 0 : goto fail;
687 : }
688 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "ldap simple bind sent, msgid = %d\n", msgid);
689 :
690 0 : if (!sh->connected) {
691 0 : ret = sdap_set_connected(sh, ev);
692 0 : if (ret) goto fail;
693 : }
694 :
695 0 : ret = sdap_op_add(state, ev, sh, msgid,
696 0 : simple_bind_done, req, timeout, &state->op);
697 0 : if (ret) {
698 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set up operation!\n");
699 0 : goto fail;
700 : }
701 :
702 0 : return req;
703 :
704 : fail:
705 0 : if (ret == LDAP_SERVER_DOWN) {
706 0 : tevent_req_error(req, ETIMEDOUT);
707 : } else {
708 0 : tevent_req_error(req, ERR_NETWORK_IO);
709 : }
710 0 : tevent_req_post(req, ev);
711 0 : return req;
712 : }
713 :
714 0 : static void simple_bind_done(struct sdap_op *op,
715 : struct sdap_msg *reply,
716 : int error, void *pvt)
717 : {
718 0 : struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
719 0 : struct simple_bind_state *state = tevent_req_data(req,
720 : struct simple_bind_state);
721 0 : char *errmsg = NULL;
722 : char *nval;
723 0 : errno_t ret = ERR_INTERNAL;
724 : int lret;
725 : LDAPControl **response_controls;
726 : int c;
727 : ber_int_t pp_grace;
728 : ber_int_t pp_expire;
729 : LDAPPasswordPolicyError pp_error;
730 0 : int result = LDAP_OTHER;
731 :
732 0 : if (error) {
733 0 : tevent_req_error(req, error);
734 0 : return;
735 : }
736 :
737 0 : state->reply = talloc_steal(state, reply);
738 :
739 0 : lret = ldap_parse_result(state->sh->ldap, state->reply->msg,
740 : &result, NULL, &errmsg, NULL,
741 : &response_controls, 0);
742 0 : if (lret != LDAP_SUCCESS) {
743 0 : DEBUG(SSSDBG_MINOR_FAILURE,
744 : "ldap_parse_result failed (%d)\n", state->op->msgid);
745 0 : ret = ERR_INTERNAL;
746 0 : goto done;
747 : }
748 :
749 0 : if (result == LDAP_SUCCESS) {
750 0 : ret = EOK;
751 : } else {
752 0 : ret = ERR_AUTH_FAILED;
753 : }
754 :
755 0 : if (response_controls == NULL) {
756 0 : DEBUG(SSSDBG_TRACE_LIBS, "Server returned no controls.\n");
757 0 : state->ppolicy = NULL;
758 : } else {
759 0 : for (c = 0; response_controls[c] != NULL; c++) {
760 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
761 : "Server returned control [%s].\n",
762 : response_controls[c]->ldctl_oid);
763 0 : if (strcmp(response_controls[c]->ldctl_oid,
764 : LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
765 0 : lret = ldap_parse_passwordpolicy_control(state->sh->ldap,
766 0 : response_controls[c],
767 : &pp_expire, &pp_grace,
768 : &pp_error);
769 0 : if (lret != LDAP_SUCCESS) {
770 0 : DEBUG(SSSDBG_MINOR_FAILURE,
771 : "ldap_parse_passwordpolicy_control failed.\n");
772 0 : ret = ERR_INTERNAL;
773 0 : goto done;
774 : }
775 :
776 0 : DEBUG(SSSDBG_TRACE_LIBS,
777 : "Password Policy Response: expire [%d] grace [%d] "
778 : "error [%s].\n", pp_expire, pp_grace,
779 : ldap_passwordpolicy_err2txt(pp_error));
780 0 : if (!state->ppolicy)
781 0 : state->ppolicy = talloc_zero(state,
782 : struct sdap_ppolicy_data);
783 0 : if (state->ppolicy == NULL) {
784 0 : ret = ENOMEM;
785 0 : goto done;
786 : }
787 0 : state->ppolicy->grace = pp_grace;
788 0 : state->ppolicy->expire = pp_expire;
789 0 : if (result == LDAP_SUCCESS) {
790 :
791 0 : if (pp_error == PP_changeAfterReset) {
792 0 : DEBUG(SSSDBG_TRACE_LIBS,
793 : "Password was reset. "
794 : "User must set a new password.\n");
795 0 : ret = ERR_PASSWORD_EXPIRED;
796 0 : } else if (pp_grace >= 0) {
797 0 : DEBUG(SSSDBG_TRACE_LIBS,
798 : "Password expired. "
799 : "[%d] grace logins remaining.\n",
800 : pp_grace);
801 0 : } else if (pp_expire > 0) {
802 0 : DEBUG(SSSDBG_TRACE_LIBS,
803 : "Password will expire in [%d] seconds.\n",
804 : pp_expire);
805 : }
806 0 : } else if (result == LDAP_INVALID_CREDENTIALS &&
807 0 : pp_error == PP_passwordExpired) {
808 0 : DEBUG(SSSDBG_TRACE_LIBS,
809 : "Password expired user must set a new password.\n");
810 0 : ret = ERR_PASSWORD_EXPIRED;
811 : }
812 0 : } else if (strcmp(response_controls[c]->ldctl_oid,
813 : LDAP_CONTROL_PWEXPIRED) == 0) {
814 0 : DEBUG(SSSDBG_TRACE_LIBS,
815 : "Password expired user must set a new password.\n");
816 0 : ret = ERR_PASSWORD_EXPIRED;
817 0 : } else if (strcmp(response_controls[c]->ldctl_oid,
818 : LDAP_CONTROL_PWEXPIRING) == 0) {
819 : /* ignore controls with suspiciously long values */
820 0 : if (response_controls[c]->ldctl_value.bv_len > 32) {
821 0 : continue;
822 : }
823 :
824 0 : if (!state->ppolicy) {
825 0 : state->ppolicy = talloc(state, struct sdap_ppolicy_data);
826 : }
827 :
828 0 : if (state->ppolicy == NULL) {
829 0 : ret = ENOMEM;
830 0 : goto done;
831 : }
832 : /* ensure that bv_val is a null-terminated string */
833 0 : nval = talloc_strndup(NULL,
834 0 : response_controls[c]->ldctl_value.bv_val,
835 0 : response_controls[c]->ldctl_value.bv_len);
836 0 : if (nval == NULL) {
837 0 : ret = ENOMEM;
838 0 : goto done;
839 : }
840 0 : state->ppolicy->expire = strtouint32(nval, NULL, 10);
841 0 : lret = errno;
842 0 : talloc_zfree(nval);
843 0 : if (lret != EOK) {
844 0 : DEBUG(SSSDBG_MINOR_FAILURE,
845 : "Couldn't convert control response "
846 : "to an integer [%s].\n", strerror(lret));
847 0 : ret = ERR_INTERNAL;
848 0 : goto done;
849 : }
850 :
851 0 : DEBUG(SSSDBG_TRACE_LIBS,
852 : "Password will expire in [%d] seconds.\n",
853 : state->ppolicy->expire);
854 : }
855 : }
856 : }
857 :
858 0 : DEBUG(SSSDBG_TRACE_FUNC, "Bind result: %s(%d), %s\n",
859 : sss_ldap_err2string(result), result,
860 : errmsg ? errmsg : "no errmsg set");
861 :
862 0 : if (result != LDAP_SUCCESS && ret == EOK) {
863 0 : ret = ERR_AUTH_FAILED;
864 : }
865 :
866 : done:
867 0 : ldap_controls_free(response_controls);
868 0 : ldap_memfree(errmsg);
869 :
870 0 : if (ret == EOK) {
871 0 : tevent_req_done(req);
872 : } else {
873 0 : tevent_req_error(req, ret);
874 : }
875 : }
876 :
877 0 : static errno_t simple_bind_recv(struct tevent_req *req,
878 : TALLOC_CTX *memctx,
879 : struct sdap_ppolicy_data **ppolicy)
880 : {
881 0 : struct simple_bind_state *state = tevent_req_data(req,
882 : struct simple_bind_state);
883 :
884 0 : if (ppolicy != NULL) {
885 0 : *ppolicy = talloc_steal(memctx, state->ppolicy);
886 : }
887 :
888 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
889 :
890 0 : return EOK;
891 : }
892 :
893 : /* ==SASL-Bind============================================================ */
894 :
895 : struct sasl_bind_state {
896 : struct tevent_context *ev;
897 : struct sdap_handle *sh;
898 :
899 : const char *sasl_mech;
900 : const char *sasl_user;
901 : struct berval *sasl_cred;
902 : };
903 :
904 : static int sdap_sasl_interact(LDAP *ld, unsigned flags,
905 : void *defaults, void *interact);
906 :
907 0 : static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx,
908 : struct tevent_context *ev,
909 : struct sdap_handle *sh,
910 : const char *sasl_mech,
911 : const char *sasl_user,
912 : struct berval *sasl_cred)
913 : {
914 : struct tevent_req *req;
915 : struct sasl_bind_state *state;
916 0 : int ret = EOK;
917 : int optret;
918 0 : char *diag_msg = NULL;
919 :
920 0 : req = tevent_req_create(memctx, &state, struct sasl_bind_state);
921 0 : if (!req) return NULL;
922 :
923 0 : state->ev = ev;
924 0 : state->sh = sh;
925 0 : state->sasl_mech = sasl_mech;
926 0 : state->sasl_user = sasl_user;
927 0 : state->sasl_cred = sasl_cred;
928 :
929 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Executing sasl bind mech: %s, user: %s\n",
930 : sasl_mech, sasl_user);
931 :
932 : /* FIXME: Warning, this is a sync call!
933 : * No async variant exist in openldap libraries yet */
934 :
935 0 : if (state->sh == NULL || state->sh->ldap == NULL) {
936 0 : DEBUG(SSSDBG_CRIT_FAILURE,
937 : "Trying LDAP search while not connected.\n");
938 0 : ret = ERR_NETWORK_IO;
939 0 : goto fail;
940 : }
941 :
942 0 : ret = ldap_sasl_interactive_bind_s(state->sh->ldap, NULL,
943 : sasl_mech, NULL, NULL,
944 : LDAP_SASL_QUIET,
945 : (*sdap_sasl_interact), state);
946 0 : if (ret != LDAP_SUCCESS) {
947 0 : DEBUG(SSSDBG_CRIT_FAILURE,
948 : "ldap_sasl_bind failed (%d)[%s]\n",
949 : ret, sss_ldap_err2string(ret));
950 :
951 0 : optret = sss_ldap_get_diagnostic_msg(state, state->sh->ldap,
952 : &diag_msg);
953 0 : if (optret == EOK) {
954 0 : DEBUG(SSSDBG_MINOR_FAILURE,
955 : "Extended failure message: [%s]\n", diag_msg);
956 : }
957 0 : talloc_zfree(diag_msg);
958 :
959 0 : goto fail;
960 : }
961 :
962 0 : if (!sh->connected) {
963 0 : ret = sdap_set_connected(sh, ev);
964 0 : if (ret) goto fail;
965 : }
966 :
967 : /* This is a hack, relies on the fact that tevent_req_done() will always
968 : * set the state but will not complain if no callback has been set.
969 : * tevent_req_post() will only set the immediate event and then just call
970 : * the async callback set by the caller right after we return using the
971 : * state value set previously by tevent_req_done() */
972 0 : tevent_req_done(req);
973 0 : tevent_req_post(req, ev);
974 0 : return req;
975 :
976 : fail:
977 0 : if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) {
978 0 : tevent_req_error(req, ETIMEDOUT);
979 : } else {
980 0 : tevent_req_error(req, ERR_AUTH_FAILED);
981 : }
982 0 : tevent_req_post(req, ev);
983 0 : return req;
984 : }
985 :
986 0 : static int sdap_sasl_interact(LDAP *ld, unsigned flags,
987 : void *defaults, void *interact)
988 : {
989 0 : struct sasl_bind_state *state = talloc_get_type(defaults,
990 : struct sasl_bind_state);
991 0 : sasl_interact_t *in = (sasl_interact_t *)interact;
992 :
993 0 : if (!ld) return LDAP_PARAM_ERROR;
994 :
995 0 : while (in->id != SASL_CB_LIST_END) {
996 :
997 0 : switch (in->id) {
998 : case SASL_CB_GETREALM:
999 : case SASL_CB_USER:
1000 : case SASL_CB_PASS:
1001 0 : if (in->defresult) {
1002 0 : in->result = in->defresult;
1003 : } else {
1004 0 : in->result = "";
1005 : }
1006 0 : in->len = strlen(in->result);
1007 0 : break;
1008 : case SASL_CB_AUTHNAME:
1009 0 : if (state->sasl_user) {
1010 0 : in->result = state->sasl_user;
1011 0 : } else if (in->defresult) {
1012 0 : in->result = in->defresult;
1013 : } else {
1014 0 : in->result = "";
1015 : }
1016 0 : in->len = strlen(in->result);
1017 0 : break;
1018 : case SASL_CB_NOECHOPROMPT:
1019 : case SASL_CB_ECHOPROMPT:
1020 0 : goto fail;
1021 : }
1022 :
1023 0 : in++;
1024 : }
1025 :
1026 0 : return LDAP_SUCCESS;
1027 :
1028 : fail:
1029 0 : return LDAP_UNAVAILABLE;
1030 : }
1031 :
1032 0 : static errno_t sasl_bind_recv(struct tevent_req *req)
1033 : {
1034 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1035 :
1036 0 : return EOK;
1037 : }
1038 :
1039 : /* ==Perform-Kinit-given-keytab-and-principal============================= */
1040 :
1041 : struct sdap_kinit_state {
1042 : const char *keytab;
1043 : const char *principal;
1044 : const char *realm;
1045 : int timeout;
1046 : int lifetime;
1047 :
1048 : const char *krb_service_name;
1049 : struct tevent_context *ev;
1050 : struct be_ctx *be;
1051 :
1052 : struct fo_server *kdc_srv;
1053 : time_t expire_time;
1054 : };
1055 :
1056 : static void sdap_kinit_done(struct tevent_req *subreq);
1057 : static struct tevent_req *sdap_kinit_next_kdc(struct tevent_req *req);
1058 : static void sdap_kinit_kdc_resolved(struct tevent_req *subreq);
1059 :
1060 : static
1061 0 : struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx,
1062 : struct tevent_context *ev,
1063 : struct be_ctx *be,
1064 : struct sdap_handle *sh,
1065 : const char *krb_service_name,
1066 : int timeout,
1067 : const char *keytab,
1068 : const char *principal,
1069 : const char *realm,
1070 : bool canonicalize,
1071 : int lifetime)
1072 : {
1073 : struct tevent_req *req;
1074 : struct tevent_req *subreq;
1075 : struct sdap_kinit_state *state;
1076 : int ret;
1077 :
1078 0 : DEBUG(SSSDBG_TRACE_FUNC, "Attempting kinit (%s, %s, %s, %d)\n",
1079 : keytab ? keytab : "default",
1080 : principal, realm, lifetime);
1081 :
1082 0 : if (lifetime < 0 || lifetime > INT32_MAX) {
1083 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Ticket lifetime out of range.\n");
1084 0 : return NULL;
1085 : }
1086 :
1087 0 : req = tevent_req_create(memctx, &state, struct sdap_kinit_state);
1088 0 : if (!req) return NULL;
1089 :
1090 0 : state->keytab = keytab;
1091 0 : state->principal = principal;
1092 0 : state->realm = realm;
1093 0 : state->ev = ev;
1094 0 : state->be = be;
1095 0 : state->timeout = timeout;
1096 0 : state->lifetime = lifetime;
1097 0 : state->krb_service_name = krb_service_name;
1098 :
1099 0 : if (canonicalize) {
1100 0 : ret = setenv("KRB5_CANONICALIZE", "true", 1);
1101 : } else {
1102 0 : ret = setenv("KRB5_CANONICALIZE", "false", 1);
1103 : }
1104 0 : if (ret == -1) {
1105 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to set KRB5_CANONICALIZE to %s\n",
1106 : ((canonicalize)?"true":"false"));
1107 0 : talloc_free(req);
1108 0 : return NULL;
1109 : }
1110 :
1111 0 : subreq = sdap_kinit_next_kdc(req);
1112 0 : if (!subreq) {
1113 0 : talloc_free(req);
1114 0 : return NULL;
1115 : }
1116 :
1117 0 : return req;
1118 : }
1119 :
1120 0 : static struct tevent_req *sdap_kinit_next_kdc(struct tevent_req *req)
1121 : {
1122 : struct tevent_req *next_req;
1123 0 : struct sdap_kinit_state *state = tevent_req_data(req,
1124 : struct sdap_kinit_state);
1125 :
1126 0 : DEBUG(SSSDBG_TRACE_LIBS,
1127 : "Resolving next KDC for service %s\n", state->krb_service_name);
1128 :
1129 0 : next_req = be_resolve_server_send(state, state->ev,
1130 : state->be,
1131 : state->krb_service_name,
1132 0 : state->kdc_srv == NULL ? true : false);
1133 0 : if (next_req == NULL) {
1134 0 : DEBUG(SSSDBG_CRIT_FAILURE, "be_resolve_server_send failed.\n");
1135 0 : return NULL;
1136 : }
1137 0 : tevent_req_set_callback(next_req, sdap_kinit_kdc_resolved, req);
1138 :
1139 0 : return next_req;
1140 : }
1141 :
1142 0 : static void sdap_kinit_kdc_resolved(struct tevent_req *subreq)
1143 : {
1144 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1145 : struct tevent_req);
1146 0 : struct sdap_kinit_state *state = tevent_req_data(req,
1147 : struct sdap_kinit_state);
1148 : struct tevent_req *tgtreq;
1149 : int ret;
1150 :
1151 0 : ret = be_resolve_server_recv(subreq, &state->kdc_srv);
1152 0 : talloc_zfree(subreq);
1153 0 : if (ret != EOK) {
1154 : /* all servers have been tried and none
1155 : * was found good, go offline */
1156 0 : tevent_req_error(req, ERR_NETWORK_IO);
1157 0 : return;
1158 : }
1159 :
1160 0 : DEBUG(SSSDBG_TRACE_LIBS, "KDC resolved, attempting to get TGT...\n");
1161 :
1162 0 : tgtreq = sdap_get_tgt_send(state, state->ev, state->realm,
1163 : state->principal, state->keytab,
1164 : state->lifetime, state->timeout);
1165 0 : if (!tgtreq) {
1166 0 : tevent_req_error(req, ENOMEM);
1167 0 : return;
1168 : }
1169 0 : tevent_req_set_callback(tgtreq, sdap_kinit_done, req);
1170 : }
1171 :
1172 0 : static void sdap_kinit_done(struct tevent_req *subreq)
1173 : {
1174 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1175 : struct tevent_req);
1176 0 : struct sdap_kinit_state *state = tevent_req_data(req,
1177 : struct sdap_kinit_state);
1178 :
1179 : int ret;
1180 : int result;
1181 0 : char *ccname = NULL;
1182 0 : time_t expire_time = 0;
1183 : krb5_error_code kerr;
1184 : struct tevent_req *nextreq;
1185 :
1186 0 : ret = sdap_get_tgt_recv(subreq, state, &result,
1187 : &kerr, &ccname, &expire_time);
1188 0 : talloc_zfree(subreq);
1189 0 : if (ret == ETIMEDOUT) {
1190 : /* The child didn't even respond. Perhaps the KDC is too busy,
1191 : * retry with another KDC */
1192 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1193 : "Communication with KDC timed out, trying the next one\n");
1194 0 : be_fo_set_port_status(state->be, state->krb_service_name,
1195 : state->kdc_srv, PORT_NOT_WORKING);
1196 0 : nextreq = sdap_kinit_next_kdc(req);
1197 0 : if (!nextreq) {
1198 0 : tevent_req_error(req, ENOMEM);
1199 : }
1200 0 : return;
1201 0 : } else if (ret != EOK) {
1202 : /* A severe error while executing the child. Abort the operation. */
1203 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1204 : "child failed (%d [%s])\n", ret, strerror(ret));
1205 0 : tevent_req_error(req, ret);
1206 0 : return;
1207 : }
1208 :
1209 0 : if (result == EOK) {
1210 0 : ret = setenv("KRB5CCNAME", ccname, 1);
1211 0 : if (ret == -1) {
1212 0 : DEBUG(SSSDBG_OP_FAILURE,
1213 : "Unable to set env. variable KRB5CCNAME!\n");
1214 0 : tevent_req_error(req, ERR_AUTH_FAILED);
1215 0 : return;
1216 : }
1217 :
1218 0 : state->expire_time = expire_time;
1219 0 : tevent_req_done(req);
1220 0 : return;
1221 : } else {
1222 0 : if (kerr == KRB5_KDC_UNREACH) {
1223 0 : be_fo_set_port_status(state->be, state->krb_service_name,
1224 : state->kdc_srv, PORT_NOT_WORKING);
1225 0 : nextreq = sdap_kinit_next_kdc(req);
1226 0 : if (!nextreq) {
1227 0 : tevent_req_error(req, ENOMEM);
1228 : }
1229 0 : return;
1230 : }
1231 :
1232 : }
1233 :
1234 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1235 : "Could not get TGT: %d [%s]\n", result, sss_strerror(result));
1236 0 : tevent_req_error(req, ERR_AUTH_FAILED);
1237 : }
1238 :
1239 0 : static errno_t sdap_kinit_recv(struct tevent_req *req,
1240 : time_t *expire_time)
1241 : {
1242 0 : struct sdap_kinit_state *state = tevent_req_data(req,
1243 : struct sdap_kinit_state);
1244 : enum tevent_req_state tstate;
1245 0 : uint64_t err = ERR_INTERNAL;
1246 :
1247 0 : if (tevent_req_is_error(req, &tstate, &err)) {
1248 0 : if (tstate != TEVENT_REQ_IN_PROGRESS) {
1249 0 : return err;
1250 : }
1251 : }
1252 :
1253 0 : *expire_time = state->expire_time;
1254 0 : return EOK;
1255 : }
1256 :
1257 :
1258 : /* ==Authenticaticate-User-by-DN========================================== */
1259 :
1260 : struct sdap_auth_state {
1261 : struct sdap_ppolicy_data *ppolicy;
1262 : bool is_sasl;
1263 : };
1264 :
1265 : static void sdap_auth_done(struct tevent_req *subreq);
1266 :
1267 : /* TODO: handle sasl_cred */
1268 0 : struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
1269 : struct tevent_context *ev,
1270 : struct sdap_handle *sh,
1271 : const char *sasl_mech,
1272 : const char *sasl_user,
1273 : const char *user_dn,
1274 : struct sss_auth_token *authtok,
1275 : int simple_bind_timeout)
1276 : {
1277 : struct tevent_req *req, *subreq;
1278 : struct sdap_auth_state *state;
1279 :
1280 0 : req = tevent_req_create(memctx, &state, struct sdap_auth_state);
1281 0 : if (!req) return NULL;
1282 :
1283 0 : if (sasl_mech) {
1284 0 : state->is_sasl = true;
1285 0 : subreq = sasl_bind_send(state, ev, sh, sasl_mech, sasl_user, NULL);
1286 0 : if (!subreq) {
1287 0 : tevent_req_error(req, ENOMEM);
1288 0 : return tevent_req_post(req, ev);
1289 : }
1290 : } else {
1291 0 : const char *password = NULL;
1292 : struct berval pw;
1293 : size_t pwlen;
1294 : errno_t ret;
1295 :
1296 0 : ret = sss_authtok_get_password(authtok, &password, &pwlen);
1297 0 : if (ret != EOK) {
1298 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot parse authtok.\n");
1299 0 : tevent_req_error(req, ret);
1300 0 : return tevent_req_post(req, ev);
1301 : }
1302 : /* Treat a zero-length password as a failure */
1303 0 : if (*password == '\0') {
1304 0 : tevent_req_error(req, ENOENT);
1305 0 : return tevent_req_post(req, ev);
1306 : }
1307 0 : pw.bv_val = discard_const(password);
1308 0 : pw.bv_len = pwlen;
1309 :
1310 0 : state->is_sasl = false;
1311 0 : subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw);
1312 0 : if (!subreq) {
1313 0 : tevent_req_error(req, ENOMEM);
1314 0 : return tevent_req_post(req, ev);
1315 : }
1316 : }
1317 :
1318 0 : tevent_req_set_callback(subreq, sdap_auth_done, req);
1319 0 : return req;
1320 : }
1321 :
1322 0 : static int sdap_auth_get_authtok(const char *authtok_type,
1323 : struct dp_opt_blob authtok,
1324 : struct berval *pw)
1325 : {
1326 0 : if (!authtok_type) return EOK;
1327 0 : if (!pw) return EINVAL;
1328 :
1329 0 : if (strcasecmp(authtok_type,"password") == 0) {
1330 0 : pw->bv_len = authtok.length;
1331 0 : pw->bv_val = (char *) authtok.data;
1332 : } else {
1333 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1334 : "Authentication token type [%s] is not supported\n",
1335 : authtok_type);
1336 0 : return EINVAL;
1337 : }
1338 :
1339 0 : return EOK;
1340 : }
1341 :
1342 0 : static void sdap_auth_done(struct tevent_req *subreq)
1343 : {
1344 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1345 : struct tevent_req);
1346 0 : struct sdap_auth_state *state = tevent_req_data(req,
1347 : struct sdap_auth_state);
1348 : int ret;
1349 :
1350 0 : if (state->is_sasl) {
1351 0 : ret = sasl_bind_recv(subreq);
1352 0 : state->ppolicy = NULL;
1353 : } else {
1354 0 : ret = simple_bind_recv(subreq, state, &state->ppolicy);
1355 : }
1356 :
1357 0 : if (tevent_req_error(req, ret)) {
1358 0 : return;
1359 : }
1360 :
1361 0 : tevent_req_done(req);
1362 : }
1363 :
1364 0 : errno_t sdap_auth_recv(struct tevent_req *req,
1365 : TALLOC_CTX *memctx,
1366 : struct sdap_ppolicy_data **ppolicy)
1367 : {
1368 0 : struct sdap_auth_state *state = tevent_req_data(req,
1369 : struct sdap_auth_state);
1370 :
1371 0 : if (ppolicy != NULL) {
1372 0 : *ppolicy = talloc_steal(memctx, state->ppolicy);
1373 : }
1374 :
1375 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1376 :
1377 0 : return EOK;
1378 : }
1379 :
1380 : /* ==Client connect============================================ */
1381 :
1382 : struct sdap_cli_connect_state {
1383 : struct tevent_context *ev;
1384 : struct sdap_options *opts;
1385 : struct sdap_service *service;
1386 : struct be_ctx *be;
1387 :
1388 : bool use_rootdse;
1389 : struct sysdb_attrs *rootdse;
1390 :
1391 : struct sdap_handle *sh;
1392 :
1393 : struct fo_server *srv;
1394 :
1395 : struct sdap_server_opts *srv_opts;
1396 :
1397 : enum connect_tls force_tls;
1398 : bool do_auth;
1399 : bool use_tls;
1400 : };
1401 :
1402 : static int sdap_cli_resolve_next(struct tevent_req *req);
1403 : static void sdap_cli_resolve_done(struct tevent_req *subreq);
1404 : static void sdap_cli_connect_done(struct tevent_req *subreq);
1405 : static void sdap_cli_rootdse_step(struct tevent_req *req);
1406 : static void sdap_cli_rootdse_done(struct tevent_req *subreq);
1407 : static errno_t sdap_cli_use_rootdse(struct sdap_cli_connect_state *state);
1408 : static void sdap_cli_kinit_step(struct tevent_req *req);
1409 : static void sdap_cli_kinit_done(struct tevent_req *subreq);
1410 : static void sdap_cli_auth_step(struct tevent_req *req);
1411 : static void sdap_cli_auth_done(struct tevent_req *subreq);
1412 : static errno_t sdap_cli_auth_reconnect(struct tevent_req *subreq);
1413 : static void sdap_cli_auth_reconnect_done(struct tevent_req *subreq);
1414 : static void sdap_cli_rootdse_auth_done(struct tevent_req *subreq);
1415 :
1416 : static errno_t
1417 0 : decide_tls_usage(enum connect_tls force_tls, struct dp_option *basic,
1418 : const char *uri, bool *_use_tls)
1419 : {
1420 0 : bool use_tls = true;
1421 :
1422 0 : switch (force_tls) {
1423 : case CON_TLS_DFL:
1424 0 : use_tls = dp_opt_get_bool(basic, SDAP_ID_TLS);
1425 0 : break;
1426 : case CON_TLS_ON:
1427 0 : use_tls = true;
1428 0 : break;
1429 : case CON_TLS_OFF:
1430 0 : use_tls = false;
1431 0 : break;
1432 : default:
1433 0 : return EINVAL;
1434 : break;
1435 : }
1436 :
1437 0 : if (use_tls && sdap_is_secure_uri(uri)) {
1438 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
1439 : "[%s] is a secure channel. No need to run START_TLS\n", uri);
1440 0 : use_tls = false;
1441 : }
1442 :
1443 0 : *_use_tls = use_tls;
1444 0 : return EOK;
1445 : }
1446 :
1447 0 : struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
1448 : struct tevent_context *ev,
1449 : struct sdap_options *opts,
1450 : struct be_ctx *be,
1451 : struct sdap_service *service,
1452 : bool skip_rootdse,
1453 : enum connect_tls force_tls,
1454 : bool skip_auth)
1455 : {
1456 : struct sdap_cli_connect_state *state;
1457 : struct tevent_req *req;
1458 : int ret;
1459 :
1460 0 : req = tevent_req_create(memctx, &state, struct sdap_cli_connect_state);
1461 0 : if (!req) return NULL;
1462 :
1463 0 : state->ev = ev;
1464 0 : state->opts = opts;
1465 0 : state->service = service;
1466 0 : state->be = be;
1467 0 : state->srv = NULL;
1468 0 : state->srv_opts = NULL;
1469 0 : state->use_rootdse = !skip_rootdse;
1470 0 : state->force_tls = force_tls;
1471 0 : state->do_auth = !skip_auth;
1472 :
1473 0 : ret = sdap_cli_resolve_next(req);
1474 0 : if (ret) {
1475 0 : tevent_req_error(req, ret);
1476 0 : tevent_req_post(req, ev);
1477 : }
1478 0 : return req;
1479 : }
1480 :
1481 0 : static int sdap_cli_resolve_next(struct tevent_req *req)
1482 : {
1483 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1484 : struct sdap_cli_connect_state);
1485 : struct tevent_req *subreq;
1486 :
1487 : /* Before stepping to next server destroy any connection from previous attempt */
1488 0 : talloc_zfree(state->sh);
1489 :
1490 : /* NOTE: this call may cause service->uri to be refreshed
1491 : * with a new valid server. Do not use service->uri before */
1492 0 : subreq = be_resolve_server_send(state, state->ev,
1493 0 : state->be, state->service->name,
1494 0 : state->srv == NULL ? true : false);
1495 0 : if (!subreq) {
1496 0 : return ENOMEM;
1497 : }
1498 :
1499 0 : tevent_req_set_callback(subreq, sdap_cli_resolve_done, req);
1500 0 : return EOK;
1501 : }
1502 :
1503 0 : static void sdap_cli_resolve_done(struct tevent_req *subreq)
1504 : {
1505 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1506 : struct tevent_req);
1507 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1508 : struct sdap_cli_connect_state);
1509 : int ret;
1510 :
1511 0 : ret = be_resolve_server_recv(subreq, &state->srv);
1512 0 : talloc_zfree(subreq);
1513 0 : if (ret) {
1514 0 : state->srv = NULL;
1515 : /* all servers have been tried and none
1516 : * was found good, go offline */
1517 0 : tevent_req_error(req, EIO);
1518 0 : return;
1519 : }
1520 :
1521 0 : ret = decide_tls_usage(state->force_tls, state->opts->basic,
1522 0 : state->service->uri, &state->use_tls);
1523 :
1524 0 : if (ret != EOK) {
1525 0 : tevent_req_error(req, EINVAL);
1526 0 : return;
1527 : }
1528 :
1529 0 : subreq = sdap_connect_send(state, state->ev, state->opts,
1530 0 : state->service->uri,
1531 0 : state->service->sockaddr,
1532 0 : state->use_tls);
1533 0 : if (!subreq) {
1534 0 : tevent_req_error(req, ENOMEM);
1535 0 : return;
1536 : }
1537 0 : tevent_req_set_callback(subreq, sdap_cli_connect_done, req);
1538 : }
1539 :
1540 0 : static void sdap_cli_connect_done(struct tevent_req *subreq)
1541 : {
1542 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1543 : struct tevent_req);
1544 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1545 : struct sdap_cli_connect_state);
1546 : const char *sasl_mech;
1547 : int ret;
1548 :
1549 0 : talloc_zfree(state->sh);
1550 0 : ret = sdap_connect_recv(subreq, state, &state->sh);
1551 0 : talloc_zfree(subreq);
1552 0 : if (ret) {
1553 : /* retry another server */
1554 0 : be_fo_set_port_status(state->be, state->service->name,
1555 : state->srv, PORT_NOT_WORKING);
1556 0 : ret = sdap_cli_resolve_next(req);
1557 0 : if (ret != EOK) {
1558 0 : tevent_req_error(req, ret);
1559 : }
1560 0 : return;
1561 : }
1562 :
1563 0 : if (state->use_rootdse) {
1564 : /* fetch the rootDSE this time */
1565 0 : sdap_cli_rootdse_step(req);
1566 0 : return;
1567 : }
1568 :
1569 0 : sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
1570 :
1571 0 : if (state->do_auth && sasl_mech && state->use_rootdse) {
1572 : /* check if server claims to support GSSAPI */
1573 0 : if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
1574 0 : tevent_req_error(req, ENOTSUP);
1575 0 : return;
1576 : }
1577 : }
1578 :
1579 0 : if (state->do_auth && sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
1580 0 : if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) {
1581 0 : sdap_cli_kinit_step(req);
1582 0 : return;
1583 : }
1584 : }
1585 :
1586 0 : sdap_cli_auth_step(req);
1587 : }
1588 :
1589 0 : static void sdap_cli_rootdse_step(struct tevent_req *req)
1590 : {
1591 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1592 : struct sdap_cli_connect_state);
1593 : struct tevent_req *subreq;
1594 : int ret;
1595 :
1596 0 : subreq = sdap_get_rootdse_send(state, state->ev, state->opts, state->sh);
1597 0 : if (!subreq) {
1598 0 : tevent_req_error(req, ENOMEM);
1599 0 : return;
1600 : }
1601 0 : tevent_req_set_callback(subreq, sdap_cli_rootdse_done, req);
1602 :
1603 0 : if (!state->sh->connected) {
1604 : /* this rootdse search is performed before we actually do a bind,
1605 : * so we need to set up the callbacks or we will never get notified
1606 : * of a reply */
1607 :
1608 0 : ret = sdap_set_connected(state->sh, state->ev);
1609 0 : if (ret) {
1610 0 : tevent_req_error(req, ret);
1611 : }
1612 : }
1613 : }
1614 :
1615 0 : static void sdap_cli_rootdse_done(struct tevent_req *subreq)
1616 : {
1617 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1618 : struct tevent_req);
1619 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1620 : struct sdap_cli_connect_state);
1621 : const char *sasl_mech;
1622 : int ret;
1623 :
1624 0 : ret = sdap_get_rootdse_recv(subreq, state, &state->rootdse);
1625 0 : talloc_zfree(subreq);
1626 0 : if (ret) {
1627 0 : if (ret == ETIMEDOUT) { /* retry another server */
1628 0 : be_fo_set_port_status(state->be, state->service->name,
1629 : state->srv, PORT_NOT_WORKING);
1630 0 : ret = sdap_cli_resolve_next(req);
1631 0 : if (ret != EOK) {
1632 0 : tevent_req_error(req, ret);
1633 : }
1634 0 : return;
1635 : }
1636 :
1637 : /* RootDSE was not available on
1638 : * the server.
1639 : * Continue, and just assume that the
1640 : * features requested by the config
1641 : * work properly.
1642 : */
1643 0 : state->rootdse = NULL;
1644 : }
1645 :
1646 :
1647 0 : ret = sdap_cli_use_rootdse(state);
1648 0 : if (ret != EOK) {
1649 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_cli_use_rootdse failed\n");
1650 0 : tevent_req_error(req, ret);
1651 0 : return;
1652 : }
1653 :
1654 0 : sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
1655 :
1656 0 : if (state->do_auth && sasl_mech && state->rootdse) {
1657 : /* check if server claims to support GSSAPI */
1658 0 : if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
1659 0 : tevent_req_error(req, ENOTSUP);
1660 0 : return;
1661 : }
1662 : }
1663 :
1664 0 : if (state->do_auth && sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
1665 0 : if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) {
1666 0 : sdap_cli_kinit_step(req);
1667 0 : return;
1668 : }
1669 : }
1670 :
1671 0 : sdap_cli_auth_step(req);
1672 : }
1673 :
1674 0 : static errno_t sdap_cli_use_rootdse(struct sdap_cli_connect_state *state)
1675 : {
1676 : errno_t ret;
1677 :
1678 0 : if (state->rootdse) {
1679 : /* save rootdse data about supported features */
1680 0 : ret = sdap_set_rootdse_supported_lists(state->rootdse, state->sh);
1681 0 : if (ret) {
1682 0 : DEBUG(SSSDBG_OP_FAILURE,
1683 : "sdap_set_rootdse_supported_lists failed\n");
1684 0 : return ret;
1685 : }
1686 :
1687 0 : ret = sdap_set_config_options_with_rootdse(state->rootdse, state->opts,
1688 0 : state->opts->sdom);
1689 0 : if (ret) {
1690 0 : DEBUG(SSSDBG_OP_FAILURE,
1691 : "sdap_set_config_options_with_rootdse failed.\n");
1692 0 : return ret;
1693 : }
1694 :
1695 : }
1696 :
1697 0 : ret = sdap_get_server_opts_from_rootdse(state,
1698 0 : state->service->uri,
1699 : state->rootdse,
1700 : state->opts, &state->srv_opts);
1701 0 : if (ret) {
1702 0 : DEBUG(SSSDBG_OP_FAILURE,
1703 : "sdap_get_server_opts_from_rootdse failed.\n");
1704 0 : return ret;
1705 : }
1706 :
1707 0 : return EOK;
1708 : }
1709 :
1710 0 : static void sdap_cli_kinit_step(struct tevent_req *req)
1711 : {
1712 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1713 : struct sdap_cli_connect_state);
1714 : struct tevent_req *subreq;
1715 :
1716 0 : subreq = sdap_kinit_send(state, state->ev,
1717 : state->be,
1718 : state->sh,
1719 0 : state->service->kinit_service_name,
1720 0 : dp_opt_get_int(state->opts->basic,
1721 : SDAP_OPT_TIMEOUT),
1722 0 : dp_opt_get_string(state->opts->basic,
1723 : SDAP_KRB5_KEYTAB),
1724 0 : dp_opt_get_string(state->opts->basic,
1725 : SDAP_SASL_AUTHID),
1726 0 : sdap_gssapi_realm(state->opts->basic),
1727 0 : dp_opt_get_bool(state->opts->basic,
1728 : SDAP_KRB5_CANONICALIZE),
1729 0 : dp_opt_get_int(state->opts->basic,
1730 : SDAP_KRB5_TICKET_LIFETIME));
1731 0 : if (!subreq) {
1732 0 : tevent_req_error(req, ENOMEM);
1733 0 : return;
1734 : }
1735 0 : tevent_req_set_callback(subreq, sdap_cli_kinit_done, req);
1736 : }
1737 :
1738 0 : static void sdap_cli_kinit_done(struct tevent_req *subreq)
1739 : {
1740 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1741 : struct tevent_req);
1742 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1743 : struct sdap_cli_connect_state);
1744 0 : time_t expire_time = 0;
1745 : errno_t ret;
1746 :
1747 0 : ret = sdap_kinit_recv(subreq, &expire_time);
1748 0 : talloc_zfree(subreq);
1749 0 : if (ret != EOK) {
1750 : /* We're not able to authenticate to the LDAP server.
1751 : * There's not much we can do except for going offline */
1752 0 : DEBUG(SSSDBG_TRACE_FUNC,
1753 : "Cannot get a TGT: ret [%d](%s)\n", ret, sss_strerror(ret));
1754 0 : tevent_req_error(req, EACCES);
1755 0 : return;
1756 : }
1757 0 : state->sh->expire_time = expire_time;
1758 :
1759 0 : sdap_cli_auth_step(req);
1760 : }
1761 :
1762 0 : static void sdap_cli_auth_step(struct tevent_req *req)
1763 : {
1764 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1765 : struct sdap_cli_connect_state);
1766 : struct tevent_req *subreq;
1767 : time_t now;
1768 : int expire_timeout;
1769 0 : const char *sasl_mech = dp_opt_get_string(state->opts->basic,
1770 : SDAP_SASL_MECH);
1771 0 : const char *user_dn = dp_opt_get_string(state->opts->basic,
1772 : SDAP_DEFAULT_BIND_DN);
1773 : const char *authtok_type;
1774 : struct dp_opt_blob authtok_blob;
1775 : struct sss_auth_token *authtok;
1776 : errno_t ret;
1777 :
1778 : /* It's possible that connection was terminated by server (e.g. #2435),
1779 : to overcome this try to connect again. */
1780 0 : if (state->sh == NULL || !state->sh->connected) {
1781 0 : DEBUG(SSSDBG_TRACE_FUNC, "No connection available. "
1782 : "Trying to reconnect.\n");
1783 0 : ret = sdap_cli_auth_reconnect(req);
1784 0 : if (ret != EOK) {
1785 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1786 : "sdap_cli_auth_reconnect failed: %d:[%s]\n",
1787 : ret, sss_strerror(ret));
1788 0 : tevent_req_error(req, ret);
1789 : }
1790 0 : return;
1791 : }
1792 :
1793 : /* Set the LDAP expiration time
1794 : * If SASL has already set it, use the sooner of the two
1795 : */
1796 0 : now = time(NULL);
1797 0 : expire_timeout = dp_opt_get_int(state->opts->basic, SDAP_EXPIRE_TIMEOUT);
1798 0 : DEBUG(SSSDBG_CONF_SETTINGS, "expire timeout is %d\n", expire_timeout);
1799 0 : if (!state->sh->expire_time
1800 0 : || (state->sh->expire_time > (now + expire_timeout))) {
1801 0 : state->sh->expire_time = now + expire_timeout;
1802 0 : DEBUG(SSSDBG_TRACE_LIBS,
1803 : "the connection will expire at %ld\n", state->sh->expire_time);
1804 : }
1805 :
1806 0 : if (!state->do_auth ||
1807 0 : (sasl_mech == NULL && user_dn == NULL)) {
1808 0 : DEBUG(SSSDBG_TRACE_LIBS,
1809 : "No authentication requested or SASL auth forced off\n");
1810 0 : tevent_req_done(req);
1811 0 : return;
1812 : }
1813 :
1814 0 : authtok_type = dp_opt_get_string(state->opts->basic,
1815 : SDAP_DEFAULT_AUTHTOK_TYPE);
1816 0 : authtok = sss_authtok_new(state);
1817 0 : if(authtok == NULL) {
1818 0 : tevent_req_error(req, ENOMEM);
1819 0 : return;
1820 : }
1821 :
1822 0 : if (authtok_type != NULL) {
1823 0 : if (strcasecmp(authtok_type, "password") != 0) {
1824 0 : DEBUG(SSSDBG_TRACE_LIBS, "Invalid authtoken type\n");
1825 0 : tevent_req_error(req, EINVAL);
1826 0 : return;
1827 : }
1828 :
1829 0 : authtok_blob = dp_opt_get_blob(state->opts->basic,
1830 : SDAP_DEFAULT_AUTHTOK);
1831 0 : if (authtok_blob.data) {
1832 0 : ret = sss_authtok_set_password(authtok,
1833 0 : (const char *)authtok_blob.data,
1834 : authtok_blob.length);
1835 0 : if (ret) {
1836 0 : tevent_req_error(req, ret);
1837 0 : return;
1838 : }
1839 : }
1840 : }
1841 :
1842 0 : subreq = sdap_auth_send(state, state->ev,
1843 : state->sh, sasl_mech,
1844 0 : dp_opt_get_string(state->opts->basic,
1845 : SDAP_SASL_AUTHID),
1846 : user_dn, authtok,
1847 0 : dp_opt_get_int(state->opts->basic,
1848 : SDAP_OPT_TIMEOUT));
1849 0 : if (!subreq) {
1850 0 : tevent_req_error(req, ENOMEM);
1851 0 : return;
1852 : }
1853 0 : tevent_req_set_callback(subreq, sdap_cli_auth_done, req);
1854 : }
1855 :
1856 0 : static errno_t sdap_cli_auth_reconnect(struct tevent_req *req)
1857 : {
1858 : struct sdap_cli_connect_state *state;
1859 : struct tevent_req *subreq;
1860 : errno_t ret;
1861 :
1862 0 : state = tevent_req_data(req, struct sdap_cli_connect_state);
1863 :
1864 0 : ret = decide_tls_usage(state->force_tls, state->opts->basic,
1865 0 : state->service->uri, &state->use_tls);
1866 0 : if (ret != EOK) {
1867 0 : goto done;
1868 : }
1869 :
1870 0 : subreq = sdap_connect_send(state, state->ev, state->opts,
1871 0 : state->service->uri,
1872 0 : state->service->sockaddr,
1873 0 : state->use_tls);
1874 :
1875 0 : if (subreq == NULL) {
1876 0 : ret = ENOMEM;
1877 0 : goto done;
1878 : }
1879 :
1880 0 : tevent_req_set_callback(subreq, sdap_cli_auth_reconnect_done, req);
1881 :
1882 0 : ret = EOK;
1883 :
1884 : done:
1885 0 : return ret;
1886 : }
1887 :
1888 0 : static void sdap_cli_auth_reconnect_done(struct tevent_req *subreq)
1889 : {
1890 : struct sdap_cli_connect_state *state;
1891 : struct tevent_req *req;
1892 : errno_t ret;
1893 :
1894 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1895 0 : state = tevent_req_data(req, struct sdap_cli_connect_state);
1896 :
1897 0 : talloc_zfree(state->sh);
1898 :
1899 0 : ret = sdap_connect_recv(subreq, state, &state->sh);
1900 0 : talloc_zfree(subreq);
1901 0 : if (ret != EOK) {
1902 0 : goto done;
1903 : }
1904 :
1905 : /* if TLS was used, the sdap handle is already marked as connected */
1906 0 : if (!state->use_tls) {
1907 : /* we need to mark handle as connected to allow anonymous bind */
1908 0 : ret = sdap_set_connected(state->sh, state->ev);
1909 0 : if (ret != EOK) {
1910 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_set_connected() failed.\n");
1911 0 : goto done;
1912 : }
1913 : }
1914 :
1915 : /* End request if reconnecting failed to avoid endless loop */
1916 0 : if (state->sh == NULL || !state->sh->connected) {
1917 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to reconnect.\n");
1918 0 : ret = EIO;
1919 0 : goto done;
1920 : }
1921 :
1922 0 : sdap_cli_auth_step(req);
1923 :
1924 0 : ret = EOK;
1925 :
1926 : done:
1927 0 : if (ret != EOK) {
1928 0 : tevent_req_error(req, ret);
1929 : }
1930 0 : }
1931 :
1932 0 : static void sdap_cli_auth_done(struct tevent_req *subreq)
1933 : {
1934 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1935 : struct tevent_req);
1936 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1937 : struct sdap_cli_connect_state);
1938 : int ret;
1939 :
1940 0 : ret = sdap_auth_recv(subreq, NULL, NULL);
1941 0 : talloc_zfree(subreq);
1942 0 : if (ret) {
1943 0 : tevent_req_error(req, ret);
1944 0 : return;
1945 : }
1946 :
1947 0 : if (state->use_rootdse && !state->rootdse) {
1948 : /* We weren't able to read rootDSE during unauthenticated bind.
1949 : * Let's try again now that we are authenticated */
1950 0 : subreq = sdap_get_rootdse_send(state, state->ev,
1951 : state->opts, state->sh);
1952 0 : if (!subreq) {
1953 0 : tevent_req_error(req, ENOMEM);
1954 0 : return;
1955 : }
1956 0 : tevent_req_set_callback(subreq, sdap_cli_rootdse_auth_done, req);
1957 0 : return;
1958 : }
1959 :
1960 0 : tevent_req_done(req);
1961 : }
1962 :
1963 0 : static void sdap_cli_rootdse_auth_done(struct tevent_req *subreq)
1964 : {
1965 : errno_t ret;
1966 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1967 : struct tevent_req);
1968 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
1969 : struct sdap_cli_connect_state);
1970 :
1971 0 : ret = sdap_get_rootdse_recv(subreq, state, &state->rootdse);
1972 0 : talloc_zfree(subreq);
1973 0 : if (ret) {
1974 0 : if (ret == ETIMEDOUT) {
1975 : /* The server we authenticated against went down. Retry another
1976 : * one */
1977 0 : be_fo_set_port_status(state->be, state->service->name,
1978 : state->srv, PORT_NOT_WORKING);
1979 0 : ret = sdap_cli_resolve_next(req);
1980 0 : if (ret != EOK) {
1981 0 : tevent_req_error(req, ret);
1982 : }
1983 0 : return;
1984 : }
1985 :
1986 : /* RootDSE was not available on
1987 : * the server.
1988 : * Continue, and just assume that the
1989 : * features requested by the config
1990 : * work properly.
1991 : */
1992 0 : state->use_rootdse = false;
1993 0 : state->rootdse = NULL;
1994 0 : tevent_req_done(req);
1995 0 : return;
1996 : }
1997 :
1998 : /* We were able to get rootDSE after authentication */
1999 0 : ret = sdap_cli_use_rootdse(state);
2000 0 : if (ret != EOK) {
2001 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_cli_use_rootdse failed\n");
2002 0 : tevent_req_error(req, ret);
2003 0 : return;
2004 : }
2005 :
2006 0 : tevent_req_done(req);
2007 : }
2008 :
2009 0 : int sdap_cli_connect_recv(struct tevent_req *req,
2010 : TALLOC_CTX *memctx,
2011 : bool *can_retry,
2012 : struct sdap_handle **gsh,
2013 : struct sdap_server_opts **srv_opts)
2014 : {
2015 0 : struct sdap_cli_connect_state *state = tevent_req_data(req,
2016 : struct sdap_cli_connect_state);
2017 : enum tevent_req_state tstate;
2018 : uint64_t err;
2019 :
2020 0 : if (can_retry) {
2021 0 : *can_retry = true;
2022 : }
2023 0 : if (tevent_req_is_error(req, &tstate, &err)) {
2024 : /* mark the server as bad if connection failed */
2025 0 : if (state->srv) {
2026 0 : be_fo_set_port_status(state->be, state->service->name,
2027 : state->srv, PORT_NOT_WORKING);
2028 : } else {
2029 0 : if (can_retry) {
2030 0 : *can_retry = false;
2031 : }
2032 : }
2033 :
2034 0 : if (tstate == TEVENT_REQ_USER_ERROR) {
2035 0 : return err;
2036 : }
2037 0 : return EIO;
2038 0 : } else if (state->srv) {
2039 0 : be_fo_set_port_status(state->be, state->service->name,
2040 : state->srv, PORT_WORKING);
2041 : }
2042 :
2043 0 : if (gsh) {
2044 0 : if (*gsh) {
2045 0 : talloc_zfree(*gsh);
2046 : }
2047 0 : *gsh = talloc_steal(memctx, state->sh);
2048 0 : if (!*gsh) {
2049 0 : return ENOMEM;
2050 : }
2051 : } else {
2052 0 : talloc_zfree(state->sh);
2053 : }
2054 :
2055 0 : if (srv_opts) {
2056 0 : *srv_opts = talloc_steal(memctx, state->srv_opts);
2057 : }
2058 :
2059 0 : return EOK;
2060 : }
2061 :
2062 0 : static int synchronous_tls_setup(LDAP *ldap)
2063 : {
2064 : int lret;
2065 : int optret;
2066 : int ldaperr;
2067 : int msgid;
2068 0 : char *errmsg = NULL;
2069 : char *diag_msg;
2070 0 : LDAPMessage *result = NULL;
2071 : TALLOC_CTX *tmp_ctx;
2072 :
2073 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Executing START TLS\n");
2074 :
2075 0 : tmp_ctx = talloc_new(NULL);
2076 0 : if (!tmp_ctx) return LDAP_NO_MEMORY;
2077 :
2078 0 : lret = ldap_start_tls(ldap, NULL, NULL, &msgid);
2079 0 : if (lret != LDAP_SUCCESS) {
2080 0 : optret = sss_ldap_get_diagnostic_msg(tmp_ctx, ldap, &diag_msg);
2081 0 : if (optret == LDAP_SUCCESS) {
2082 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_start_tls failed: [%s] [%s]\n",
2083 : sss_ldap_err2string(lret), diag_msg);
2084 0 : sss_log(SSS_LOG_ERR, "Could not start TLS. %s", diag_msg);
2085 : } else {
2086 0 : DEBUG(SSSDBG_MINOR_FAILURE,
2087 : "ldap_start_tls failed: [%s]\n", sss_ldap_err2string(lret));
2088 0 : sss_log(SSS_LOG_ERR, "Could not start TLS. "
2089 : "Check for certificate issues.");
2090 : }
2091 0 : goto done;
2092 : }
2093 :
2094 0 : lret = ldap_result(ldap, msgid, 1, NULL, &result);
2095 0 : if (lret != LDAP_RES_EXTENDED) {
2096 0 : DEBUG(SSSDBG_OP_FAILURE,
2097 : "Unexpected ldap_result, expected [%lu] got [%d].\n",
2098 : LDAP_RES_EXTENDED, lret);
2099 0 : lret = LDAP_PARAM_ERROR;
2100 0 : goto done;
2101 : }
2102 :
2103 0 : lret = ldap_parse_result(ldap, result, &ldaperr, NULL, &errmsg, NULL, NULL,
2104 : 0);
2105 0 : if (lret != LDAP_SUCCESS) {
2106 0 : DEBUG(SSSDBG_OP_FAILURE,
2107 : "ldap_parse_result failed (%d) [%d][%s]\n", msgid, lret,
2108 : sss_ldap_err2string(lret));
2109 0 : goto done;
2110 : }
2111 :
2112 0 : DEBUG(SSSDBG_MINOR_FAILURE, "START TLS result: %s(%d), %s\n",
2113 : sss_ldap_err2string(ldaperr), ldaperr, errmsg);
2114 :
2115 0 : if (ldap_tls_inplace(ldap)) {
2116 0 : DEBUG(SSSDBG_TRACE_ALL, "SSL/TLS handler already in place.\n");
2117 0 : lret = LDAP_SUCCESS;
2118 0 : goto done;
2119 : }
2120 :
2121 0 : lret = ldap_install_tls(ldap);
2122 0 : if (lret != LDAP_SUCCESS) {
2123 :
2124 0 : optret = sss_ldap_get_diagnostic_msg(tmp_ctx, ldap, &diag_msg);
2125 0 : if (optret == LDAP_SUCCESS) {
2126 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_install_tls failed: [%s] [%s]\n",
2127 : sss_ldap_err2string(lret), diag_msg);
2128 0 : sss_log(SSS_LOG_ERR, "Could not start TLS encryption. %s", diag_msg);
2129 : } else {
2130 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ldap_install_tls failed: [%s]\n",
2131 : sss_ldap_err2string(lret));
2132 0 : sss_log(SSS_LOG_ERR, "Could not start TLS encryption. "
2133 : "Check for certificate issues.");
2134 : }
2135 :
2136 0 : goto done;
2137 : }
2138 :
2139 0 : lret = LDAP_SUCCESS;
2140 : done:
2141 0 : if (result) ldap_msgfree(result);
2142 0 : if (errmsg) ldap_memfree(errmsg);
2143 0 : talloc_zfree(tmp_ctx);
2144 0 : return lret;
2145 : }
2146 :
2147 0 : static int sdap_rebind_proc(LDAP *ldap, LDAP_CONST char *url, ber_tag_t request,
2148 : ber_int_t msgid, void *params)
2149 : {
2150 0 : struct sdap_rebind_proc_params *p = talloc_get_type(params,
2151 : struct sdap_rebind_proc_params);
2152 : const char *sasl_mech;
2153 : const char *user_dn;
2154 0 : struct berval password = {0, NULL};
2155 0 : LDAPControl **request_controls = NULL;
2156 0 : LDAPControl *ctrls[2] = { NULL, NULL };
2157 0 : TALLOC_CTX *tmp_ctx = NULL;
2158 : struct sasl_bind_state *sasl_bind_state;
2159 : int ret;
2160 :
2161 0 : if (ldap == NULL) {
2162 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2163 : "Trying LDAP rebind while not connected.\n");
2164 0 : return ERR_NETWORK_IO;
2165 : }
2166 :
2167 0 : if (p->use_start_tls) {
2168 0 : ret = synchronous_tls_setup(ldap);
2169 0 : if (ret != LDAP_SUCCESS) {
2170 0 : DEBUG(SSSDBG_CRIT_FAILURE, "synchronous_tls_setup failed.\n");
2171 0 : return ret;
2172 : }
2173 : }
2174 :
2175 0 : tmp_ctx = talloc_new(NULL);
2176 0 : if (tmp_ctx == NULL) {
2177 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
2178 0 : return LDAP_NO_MEMORY;
2179 : }
2180 :
2181 0 : sasl_mech = dp_opt_get_string(p->opts->basic, SDAP_SASL_MECH);
2182 :
2183 0 : if (sasl_mech == NULL) {
2184 0 : ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
2185 : 0, NULL, 0, &ctrls[0]);
2186 0 : if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
2187 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2188 : "sss_ldap_control_create failed to create "
2189 : "Password Policy control.\n");
2190 0 : goto done;
2191 : }
2192 0 : request_controls = ctrls;
2193 :
2194 0 : user_dn = dp_opt_get_string(p->opts->basic, SDAP_DEFAULT_BIND_DN);
2195 0 : if (user_dn != NULL) {
2196 0 : ret = sdap_auth_get_authtok(dp_opt_get_string(p->opts->basic,
2197 : SDAP_DEFAULT_AUTHTOK_TYPE),
2198 0 : dp_opt_get_blob(p->opts->basic,
2199 : SDAP_DEFAULT_AUTHTOK),
2200 : &password);
2201 0 : if (ret != EOK) {
2202 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2203 : "sdap_auth_get_authtok failed.\n");
2204 0 : ret = LDAP_LOCAL_ERROR;
2205 0 : goto done;
2206 : }
2207 : }
2208 :
2209 0 : ret = ldap_sasl_bind_s(ldap, user_dn, LDAP_SASL_SIMPLE, &password,
2210 : request_controls, NULL, NULL);
2211 0 : if (ret != LDAP_SUCCESS) {
2212 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2213 : "ldap_sasl_bind_s failed (%d)[%s]\n", ret,
2214 : sss_ldap_err2string(ret));
2215 : }
2216 : } else {
2217 0 : sasl_bind_state = talloc_zero(tmp_ctx, struct sasl_bind_state);
2218 0 : if (sasl_bind_state == NULL) {
2219 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
2220 0 : ret = LDAP_NO_MEMORY;
2221 0 : goto done;
2222 : }
2223 0 : sasl_bind_state->sasl_user = dp_opt_get_string(p->opts->basic,
2224 : SDAP_SASL_AUTHID);
2225 0 : ret = ldap_sasl_interactive_bind_s(ldap, NULL,
2226 : sasl_mech, NULL, NULL,
2227 : LDAP_SASL_QUIET,
2228 : (*sdap_sasl_interact),
2229 : sasl_bind_state);
2230 0 : if (ret != LDAP_SUCCESS) {
2231 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2232 : "ldap_sasl_interactive_bind_s failed (%d)[%s]\n", ret,
2233 : sss_ldap_err2string(ret));
2234 : }
2235 : }
2236 :
2237 0 : DEBUG(SSSDBG_TRACE_LIBS, "%s bind to [%s].\n",
2238 : (ret == LDAP_SUCCESS ? "Successfully" : "Failed to"), url);
2239 :
2240 : done:
2241 0 : if (ctrls[0]) ldap_control_free(ctrls[0]);
2242 0 : talloc_free(tmp_ctx);
2243 0 : return ret;
2244 : }
|