static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct sss_ldap_init_state *state = tevent_req_data(req, struct sss_ldap_init_state); int ret; int lret; ret = sssd_async_socket_init_recv(subreq, &state->sd); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init request failed: [%d]: %s.\n", ret, sss_strerror(ret)); goto fail; } /* Initialize LDAP handler */ lret = ldap_init_fd(state->sd, LDAP_PROTO_TCP, state->uri, &state->ldap); if (lret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_init_fd failed: %s. [%d][%s]\n", sss_ldap_err2string(lret), state->sd, state->uri); ret = lret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO; goto fail; } if (ldap_is_ldaps_url(state->uri)) { lret = ldap_install_tls(state->ldap); if (lret != LDAP_SUCCESS) { if (lret == LDAP_LOCAL_ERROR) { DEBUG(SSSDBG_FUNC_DATA, "TLS/SSL already in place.\n"); } else { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_install_tls failed: %s\n", sss_ldap_err2string(lret)); ret = EIO; goto fail; } } } tevent_req_done(req); return; fail: tevent_req_error(req, ret); }
/* * Opes connection to an LDAP server * uri must be one URI */ static int do_open (LDAP **ld, const char* uri, int defport, ldap_ssl_options_t ssl_on_local) { #if defined(LDAP_OPT_NETWORK_TIMEOUT) || defined(HAVE_LDAP_START_TLS) struct timeval tv; #endif #ifdef HAVE_LDAP_START_TLS struct timeval *tvp; LDAPMessage *res = NULL; int msgid; #endif int rc; rc = do_init (ld, uri, defport); if (rc != LDAP_SUCCESS) { DBG("do_open(): do_init failed"); return rc; } if( ! *ld) { DBG("do_open(): internal error - assert (*ld != NULL)"); return(-2); } #if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_PROTOCOL_VERSION) ldap_set_option (*ld, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion); #endif /* LDAP_OPT_PROTOCOL_VERSION */ #if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) /* ldap_set_option (*ld, LDAP_OPT_NETWORK_TIMEOUT, &timeout); */ rc = ldap_set_option(*ld, LDAP_OPT_NETWORK_TIMEOUT, &timeout); if ( rc != LDAP_SUCCESS ) { DBG2("Warning: failed to set connection timeout to %d: %s", timeout, ldap_err2string(rc)); } else DBG1("Set connection timeout to %d", timeout); #endif /* LDAP_OPT_NETWORK_TIMEOUT */ #if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) tv.tv_sec = bind_timelimit; tv.tv_usec = 0; ldap_set_option (*ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); #endif /* LDAP_OPT_NETWORK_TIMEOUT */ #if defined(HAVE_LDAP_START_TLS_S) || defined(HAVE_LDAP_START_TLS) if (ssl_on_local == SSL_START_TLS) { int version; /* we need V3 at least */ if (ldap_get_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { if (ldapVersion < LDAP_VERSION3) { ldapVersion = LDAP_VERSION3; ldap_set_option (*ld, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion); } } /* set up SSL context */ if (do_ssl_options (*ld) != LDAP_SUCCESS) { ldap_unbind (*ld); DBG("do_open(): SSL setup failed"); return LDAP_UNAVAILABLE; } #ifdef HAVE_LDAP_START_TLS DBG("do_open(): do_start_tls"); rc = ldap_start_tls (*ld, NULL, NULL, &msgid); if (rc != LDAP_SUCCESS) { DBG1("do_open(): ldap_start_tls failed: %s", ldap_err2string (rc)); return rc; } if (bind_timelimit == LDAP_NO_LIMIT) { tvp = NULL; } else { tv.tv_sec = bind_timelimit; tv.tv_usec = 0; tvp = &tv; } rc = ldap_result (*ld, msgid, 1, tvp, &res); if (rc == -1) { #if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) if (ldap_get_option (*ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS) { rc = LDAP_UNAVAILABLE; } #else rc = ld->ld_errno; #endif /* LDAP_OPT_ERROR_NUMBER */ DBG1("do_open(): ldap_start_tls failed: %s", ldap_err2string (rc)); return rc; } rc = ldap_result2error (*ld, res, 1); if (rc != LDAP_SUCCESS) { DBG1("do_open(): ldap_result2error failed: %s)", ldap_err2string (rc)); return rc; } rc = ldap_install_tls (*ld); #else rc = ldap_start_tls_s (*ld, NULL, NULL); #endif /* HAVE_LDAP_START_TLS */ if (rc == LDAP_SUCCESS) { DBG("do_open(): TLS startup succeeded"); } else { ldap_unbind (*ld); DBG2("do_open(): TLS startup failed for LDAP server %s: %s", uri, ldap_err2string (rc)); return rc; } } else #endif /* HAVE_LDAP_START_TLS_S || HAVE_LDAP_START_TLS */ /* * If SSL is desired, then enable it. */ if (ssl_on_local == SSL_LDAPS) { #if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS) int tls = LDAP_OPT_X_TLS_HARD; if (ldap_set_option (*ld, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) { ldap_unbind (*ld); DBG("do_open(): TLS setup failed"); return LDAP_UNAVAILABLE; } /* set up SSL context */ if (do_ssl_options (*ld) != LDAP_SUCCESS) { ldap_unbind (*ld); DBG("do_open(): SSL setup failed"); return LDAP_UNAVAILABLE; } #endif } rc = do_bind (*ld, bind_timelimit); if (rc != LDAP_SUCCESS) { DBG2("do_open(): failed to bind to LDAP server %s: %s", uri, ldap_err2string (rc)); ldap_unbind (*ld); } return rc; }
static int ldap_connection_connect_parse(struct ldap_connection *conn, struct ldap_op_queue_entry *req, LDAPMessage *message, bool *finished_r) { int ret, result_err; char *retoid, *result_errmsg; int msgtype = ldap_msgtype(message); *finished_r = TRUE; ret = ldap_parse_result(conn->conn, message, &result_err, NULL, &result_errmsg, NULL, NULL, 0); switch(conn->state) { case LDAP_STATE_TLS: if (msgtype != LDAP_RES_EXTENDED) { *finished_r = FALSE; return LDAP_SUCCESS; } if (ret != 0) { ldap_connection_result_failure(conn, req, ret, t_strdup_printf( "ldap_start_tls(uri=%s) failed: %s", conn->set.uri, ldap_err2string(ret))); return ret; } else if (result_err != 0) { if (conn->set.require_ssl) { ldap_connection_result_failure(conn, req, result_err, t_strdup_printf( "ldap_start_tls(uri=%s) failed: %s", conn->set.uri, result_errmsg)); ldap_memfree(result_errmsg); return LDAP_INVALID_CREDENTIALS; /* make sure it disconnects */ } } else { ret = ldap_parse_extended_result(conn->conn, message, &retoid, NULL, 0); /* retoid can be NULL even if ret == 0 */ if (ret == 0) { ret = ldap_install_tls(conn->conn); if (ret != 0) { // if this fails we have to abort ldap_connection_result_failure(conn, req, ret, t_strdup_printf( "ldap_start_tls(uri=%s) failed: %s", conn->set.uri, ldap_err2string(ret))); return LDAP_INVALID_CREDENTIALS; } } if (ret != LDAP_SUCCESS) { if (conn->set.require_ssl) { ldap_connection_result_failure(conn, req, ret, t_strdup_printf( "ldap_start_tls(uri=%s) failed: %s", conn->set.uri, ldap_err2string(ret))); return LDAP_UNAVAILABLE; } } else { if (conn->set.debug > 0) i_debug("Using TLS connection to remote LDAP server"); } ldap_memfree(retoid); } conn->state = LDAP_STATE_AUTH; return ldap_connect_next_message(conn, req, finished_r); case LDAP_STATE_AUTH: if (ret != LDAP_SUCCESS) { ldap_connection_result_failure(conn, req, ret, t_strdup_printf( "ldap_parse_result() failed for connect: %s", ldap_err2string(ret))); return ret; } if (result_err != LDAP_SUCCESS) { const char *error = result_errmsg != NULL ? result_errmsg : ldap_err2string(result_err); ldap_connection_result_failure(conn, req, result_err, t_strdup_printf( "Connect failed: %s", error)); ldap_memfree(result_errmsg); return result_err; } if (msgtype != LDAP_RES_BIND) return 0; ret = ldap_parse_sasl_bind_result(conn->conn, message, &(conn->scred), 0); if (ret != LDAP_SUCCESS) { const char *error = t_strdup_printf( "Cannot bind with server: %s", ldap_err2string(ret)); ldap_connection_result_failure(conn, req, ret, error); return 1; } conn->state = LDAP_STATE_CONNECT; return ldap_connect_next_message(conn, req, finished_r); default: i_unreached(); } return LDAP_SUCCESS; }