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