LCOV - code coverage report
Current view: top level - providers/ldap - sdap_async_connection.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1026 0.0 %
Date: 2016-06-29 Functions: 0 41 0.0 %

          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             : }

Generated by: LCOV version 1.10