diff options
Diffstat (limited to 'lib/vtls/openssl.c')
-rw-r--r-- | lib/vtls/openssl.c | 232 |
1 files changed, 134 insertions, 98 deletions
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index ae1a54f05..b8bc6c117 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -203,7 +203,7 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data) #ifndef RANDOM_FILE /* if RANDOM_FILE isn't defined, we only perform this if an option tells us to! */ - if(data->set.ssl.random_file) + if(data->set.str[STRING_SSL_RANDOM_FILE]) #define RANDOM_FILE "" /* doesn't matter won't be used */ #endif { @@ -331,7 +331,8 @@ int cert_stuff(struct connectdata *conn, char *cert_file, const char *cert_type, char *key_file, - const char *key_type) + const char *key_type, + char *key_passwd) { struct Curl_easy *data = conn->data; @@ -342,10 +343,9 @@ int cert_stuff(struct connectdata *conn, X509 *x509; int cert_done = 0; - if(data->set.str[STRING_KEY_PASSWD]) { + if(key_passwd) { /* set the password in the callback userdata */ - SSL_CTX_set_default_passwd_cb_userdata(ctx, - data->set.str[STRING_KEY_PASSWD]); + SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd); /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } @@ -456,7 +456,7 @@ int cert_stuff(struct connectdata *conn, PKCS12_PBE_add(); - if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509, + if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) { failf(data, "could not parse PKCS12 file, check password, " OSSL_PACKAGE @@ -568,7 +568,7 @@ int cert_stuff(struct connectdata *conn, priv_key = (EVP_PKEY *) ENGINE_load_private_key(data->state.engine, key_file, ui_method, - data->set.str[STRING_KEY_PASSWD]); + key_passwd); UI_destroy_method(ui_method); if(!priv_key) { failf(data, "failed to load private key from crypto engine"); @@ -899,13 +899,8 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) } -/* - * This function is called when an SSL connection is closed. - */ -void Curl_ossl_close(struct connectdata *conn, int sockindex) +static void ossl_close(struct ssl_connect_data *connssl) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - if(connssl->handle) { (void)SSL_shutdown(connssl->handle); SSL_set_connect_state(connssl->handle); @@ -920,6 +915,15 @@ void Curl_ossl_close(struct connectdata *conn, int sockindex) } /* + * This function is called when an SSL connection is closed. + */ +void Curl_ossl_close(struct connectdata *conn, int sockindex) +{ + ossl_close(&conn->ssl[sockindex]); + ossl_close(&conn->proxy_ssl[sockindex]); +} + +/* * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) */ @@ -1090,16 +1094,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) CURLcode result = CURLE_OK; bool dNSName = FALSE; /* if a dNSName field exists in the cert */ bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */ + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; #ifdef ENABLE_IPV6 if(conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, conn->host.name, &addr)) { + Curl_inet_pton(AF_INET6, hostname, &addr)) { target = GEN_IPADD; addrlen = sizeof(struct in6_addr); } else #endif - if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) { + if(Curl_inet_pton(AF_INET, hostname, &addr)) { target = GEN_IPADD; addrlen = sizeof(struct in_addr); } @@ -1148,11 +1156,11 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) if((altlen == strlen(altptr)) && /* if this isn't true, there was an embedded zero in the name string and we cannot match it. */ - Curl_cert_hostcheck(altptr, conn->host.name)) { + Curl_cert_hostcheck(altptr, hostname)) { dnsmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", - conn->host.dispname, altptr); + dispname, altptr); } break; @@ -1163,7 +1171,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) ipmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's IP address!\n", - conn->host.dispname); + dispname); } break; } @@ -1179,9 +1187,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) /* an alternative name matched */ ; else if(dNSName || iPAddress) { - infof(data, " subjectAltName does not match %s\n", conn->host.dispname); + infof(data, " subjectAltName does not match %s\n", dispname); failf(data, "SSL: no alternative certificate subject name matches " - "target host name '%s'", conn->host.dispname); + "target host name '%s'", dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -1255,9 +1263,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) "SSL: unable to obtain common name from peer certificate"); result = CURLE_PEER_FAILED_VERIFICATION; } - else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { + else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", peer_CN, conn->host.dispname); + "target host name '%s'", peer_CN, dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -1703,6 +1711,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) struct in_addr addr; #endif #endif + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const long int ssl_version = SSL_CONN_CONFIG(version); +#ifdef USE_TLS_SRP + const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); +#endif + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); @@ -1711,11 +1733,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if(result) return result; - data->set.ssl.certverifyresult = !X509_V_OK; + *certverifyresult = !X509_V_OK; /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { + switch(ssl_version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1_0: @@ -1737,7 +1759,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_NOT_BUILT_IN; #else #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + if(ssl_authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; #endif req_method = SSLv2_client_method(); @@ -1750,7 +1772,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_NOT_BUILT_IN; #else #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + if(ssl_authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; #endif req_method = SSLv3_client_method(); @@ -1838,14 +1860,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS /* unless the user explicitly ask to allow the protocol vulnerability we use the work-around */ - if(!conn->data->set.ssl_enable_beast) + if(!SSL_SET_OPTION(enable_beast)) ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif - switch(data->set.ssl.version) { + switch(ssl_version) { case CURL_SSLVERSION_SSLv3: #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + if(ssl_authtype == CURL_TLSAUTH_SRP) { infof(data, "Set version TLSv1.x for SRP authorisation\n"); } #endif @@ -1979,19 +2001,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } #endif - if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) { - if(!cert_stuff(conn, - connssl->ctx, - data->set.str[STRING_CERT], - data->set.str[STRING_CERT_TYPE], - data->set.str[STRING_KEY], - data->set.str[STRING_KEY_TYPE])) { + if(ssl_cert || ssl_cert_type) { + if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type, + SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), + SSL_SET_OPTION(key_passwd))) { /* failf() is already done in cert_stuff() */ return CURLE_SSL_CERTPROBLEM; } } - ciphers = data->set.str[STRING_SSL_CIPHER_LIST]; + ciphers = SSL_CONN_CONFIG(cipher_list); if(!ciphers) ciphers = (char *)DEFAULT_CIPHER_SELECTION; if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) { @@ -2001,18 +2020,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, "Cipher selection: %s\n", ciphers); #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + if(ssl_authtype == CURL_TLSAUTH_SRP) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s\n", ssl_username); - if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) { + if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) { failf(data, "Unable to set SRP user name"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) { + if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!data->set.str[STRING_SSL_CIPHER_LIST]) { + if(!SSL_CONN_CONFIG(cipher_list)) { infof(data, "Setting cipher list SRP\n"); if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) { @@ -2022,20 +2043,17 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } } #endif - if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) { + + if(ssl_cafile || ssl_capath) { /* tell SSL where to find CA certificates that are used to verify the servers certificate. */ - if(!SSL_CTX_load_verify_locations(connssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if(data->set.ssl.verifypeer) { + if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); return CURLE_SSL_CACERT_BADFILE; } else { @@ -2052,10 +2070,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, " CAfile: %s\n" " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: - "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: - "none"); + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); } #ifdef CURL_CA_FALLBACK else if(data->set.ssl.verifypeer) { @@ -2065,16 +2081,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } #endif - if(data->set.str[STRING_SSL_CRLFILE]) { + if(ssl_crlfile) { /* tell SSL where to find CRL file that is used to check certificate * revocation */ lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx), X509_LOOKUP_file()); if(!lookup || - (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE], - X509_FILETYPE_PEM)) ) { - failf(data, "error loading CRL file: %s", - data->set.str[STRING_SSL_CRLFILE]); + (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { + failf(data, "error loading CRL file: %s", ssl_crlfile); return CURLE_SSL_CRL_BADFILE; } else { @@ -2083,9 +2097,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); } - infof(data, - " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ? - data->set.str[STRING_SSL_CRLFILE]: "none"); + infof(data, " CRLfile: %s\n", ssl_crlfile ? ssl_crlfile: "none"); } /* Try building a chain using issuers in the trusted store first to avoid @@ -2107,8 +2119,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ SSL_CTX_set_verify(connssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, - NULL); + verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { @@ -2131,31 +2142,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(data->set.ssl.verifystatus) + if(SSL_CONN_CONFIG(verifystatus)) SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp); #endif SSL_set_connect_state(connssl->handle); connssl->server_cert = 0x0; - #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - !SSL_set_tlsext_host_name(connssl->handle, conn->host.name)) + !SSL_set_tlsext_host_name(connssl->handle, hostname)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); #endif /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(connssl->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); @@ -2169,8 +2179,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) Curl_ssl_sessionid_unlock(conn); } - /* pass the raw socket into the SSL layers */ - if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + if(conn->proxy_ssl[sockindex].use) { + BIO *const bio = BIO_new(BIO_f_ssl()); + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); + DEBUGASSERT(bio != NULL); + BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE); + SSL_set_bio(connssl->handle, bio, bio); + } + else if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + /* pass the raw socket into the SSL layers */ failf(data, "SSL: SSL_set_fd failed: %s", ERR_error_string(ERR_get_error(), NULL)); return CURLE_SSL_CONNECT_ERROR; @@ -2187,8 +2205,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) int err; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; DEBUGASSERT(ssl_connect_2 == connssl->connecting_state - || ssl_connect_2_reading == connssl->connecting_state - || ssl_connect_2_writing == connssl->connecting_state); + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); ERR_clear_error(); @@ -2257,8 +2275,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { + const char * const hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; failf(data, "Unknown SSL protocol error in connection to %s:%ld ", - conn->host.name, conn->remote_port); + hostname, port); return result; } @@ -2735,6 +2756,8 @@ static CURLcode servercert(struct connectdata *conn, FILE *fp; char *buffer = data->state.buffer; const char *ptr; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; BIO *mem = BIO_new(BIO_s_mem()); if(data->set.ssl.certinfo) @@ -2750,7 +2773,7 @@ static CURLcode servercert(struct connectdata *conn, return CURLE_PEER_FAILED_VERIFICATION; } - infof(data, "Server certificate:\n"); + infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert), buffer, BUFSIZE); @@ -2768,7 +2791,7 @@ static CURLcode servercert(struct connectdata *conn, BIO_free(mem); - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { result = verifyhost(conn, connssl->server_cert); if(result) { X509_free(connssl->server_cert); @@ -2791,12 +2814,12 @@ static CURLcode servercert(struct connectdata *conn, deallocating the certificate. */ /* e.g. match issuer name with provided issuer certificate */ - if(data->set.str[STRING_SSL_ISSUERCERT]) { - fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT); + if(SSL_SET_OPTION(issuercert)) { + fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT); if(!fp) { if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); connssl->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; @@ -2806,7 +2829,7 @@ static CURLcode servercert(struct connectdata *conn, if(!issuer) { if(strict) failf(data, "SSL: Unable to read issuer cert (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); X509_free(issuer); fclose(fp); @@ -2818,7 +2841,7 @@ static CURLcode servercert(struct connectdata *conn, if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); X509_free(issuer); connssl->server_cert = NULL; @@ -2826,15 +2849,14 @@ static CURLcode servercert(struct connectdata *conn, } infof(data, " SSL certificate issuer check ok (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(issuer); } - lerr = data->set.ssl.certverifyresult = - SSL_get_verify_result(connssl->handle); + lerr = *certverifyresult = SSL_get_verify_result(connssl->handle); - if(data->set.ssl.certverifyresult != X509_V_OK) { - if(data->set.ssl.verifypeer) { + if(*certverifyresult != X509_V_OK) { + if(SSL_CONN_CONFIG(verifypeer)) { /* We probably never reach this, because SSL_connect() will fail and we return earlier if verifypeer is set? */ if(strict) @@ -2853,7 +2875,7 @@ static CURLcode servercert(struct connectdata *conn, #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { result = verifystatus(conn, connssl); if(result) { X509_free(connssl->server_cert); @@ -2889,7 +2911,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { bool incache; SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -2901,7 +2923,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) regardless of its state. */ Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); @@ -2912,7 +2935,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) if(!incache) { result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); + 0 /* unknown size */, sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "failed to store ssl session"); @@ -2936,8 +2959,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) * operations. */ - result = servercert(conn, connssl, - (data->set.ssl.verifypeer || data->set.ssl.verifyhost)); + result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost))); if(!result) connssl->connecting_state = ssl_connect_done; @@ -3085,7 +3108,10 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex) { if(conn->ssl[connindex].handle) /* SSL is in use */ - return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; + return (0 != SSL_pending(conn->ssl[connindex].handle) || + (conn->proxy_ssl[connindex].handle && + 0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ? + TRUE : FALSE; else return FALSE; } @@ -3130,8 +3156,18 @@ static ssize_t ossl_send(struct connectdata *conn, /* A failure in the SSL library occurred, usually a protocol error. The OpenSSL error queue contains more information on the error. */ sslerror = ERR_get_error(); - failf(conn->data, "SSL_write() error: %s", - ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + if(sslerror == + ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_WRITE_PENDING, SSL_R_BIO_NOT_SET) && + conn->ssl[sockindex].state == ssl_connection_complete && + conn->proxy_ssl[sockindex].state == ssl_connection_complete) { + char ver[120]; + Curl_ossl_version(ver, 120); + failf(conn->data, "Error: %s does not support double SSL tunneling.", + ver); + } + else + failf(conn->data, "SSL_write() error: %s", + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); *curlcode = CURLE_SEND_ERROR; return -1; } |