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

Generated by: LCOV version 1.10