static int ldap_connect_next_message(struct ldap_connection *conn, struct ldap_op_queue_entry *req, bool *finished_r) { int ret; *finished_r = TRUE; switch(conn->state) { case LDAP_STATE_DISCONNECT: /* if we should not disable SSL, and the URI is not ldaps:// */ if (!conn->set.start_tls || strstr(conn->set.uri, "ldaps://") == NULL) { ret = ldap_start_tls(conn->conn, NULL, NULL, &(req->msgid)); if (ret != LDAP_SUCCESS) { 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; } conn->state = LDAP_STATE_TLS; break; } else { conn->state = LDAP_STATE_AUTH; /* we let it slide intentionally to next case */ } case LDAP_STATE_AUTH: ret = ldap_sasl_bind(conn->conn, conn->set.bind_dn, LDAP_SASL_SIMPLE, &(conn->cred), NULL, NULL, &(req->msgid)); if (ret != LDAP_SUCCESS) { ldap_connection_result_failure(conn, req, ret, t_strdup_printf( "ldap_sasl_bind(uri=%s, dn=%s) failed: %s", conn->set.uri, conn->set.bind_dn, ldap_err2string(ret))); return ret; } break; case LDAP_STATE_CONNECT: ldap_connection_result_success(conn, req); return LDAP_SUCCESS; /* we are done here */ default: i_unreached(); }; req->conn = conn; *finished_r = FALSE; return LDAP_SUCCESS; }
/* * 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; }