static CURLcode polarssl_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; const char *capath = SSL_CONN_CONFIG(CApath); 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; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy, NULL, 0)) != 0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else entropy_init(&BACKEND->entropy); if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy, NULL, 0)) != 0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&BACKEND->cacert, 0, sizeof(x509_crt)); if(SSL_CONN_CONFIG(CAfile)) { ret = x509_crt_parse_file(&BACKEND->cacert, SSL_CONN_CONFIG(CAfile)); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", SSL_CONN_CONFIG(CAfile), -ret, errorbuf); if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } if(capath) { ret = x509_crt_parse_path(&BACKEND->cacert, capath); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", capath, -ret, errorbuf); if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&BACKEND->clicert, 0, sizeof(x509_crt)); if(SSL_SET_OPTION(cert)) { ret = x509_crt_parse_file(&BACKEND->clicert, SSL_SET_OPTION(cert)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", SSL_SET_OPTION(cert), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(SSL_SET_OPTION(key)) { pk_context pk; pk_init(&pk); ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) rsa_copy(&BACKEND->rsa, pk_rsa(pk)); else rsa_free(&BACKEND->rsa); pk_free(&pk); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&BACKEND->crl, 0, sizeof(x509_crl)); if(SSL_SET_OPTION(CRLfile)) { ret = x509_crl_parse_file(&BACKEND->crl, SSL_SET_OPTION(CRLfile)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", SSL_SET_OPTION(CRLfile), -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); if(ssl_init(&BACKEND->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { CURLcode result = set_ssl_version_min_max(conn, sockindex); if(result != CURLE_OK) return result; break; } default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT); ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(&BACKEND->ssl, ctr_drbg_random, &BACKEND->ctr_drbg); ssl_set_bio(&BACKEND->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = ssl_set_session(&BACKEND->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); failf(data, "ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "PolarSSL re-using session\n"); } Curl_ssl_sessionid_unlock(conn); } ssl_set_ca_chain(&BACKEND->ssl, &BACKEND->cacert, &BACKEND->crl, hostname); ssl_set_own_cert_rsa(&BACKEND->ssl, &BACKEND->clicert, &BACKEND->rsa); if(ssl_set_hostname(&BACKEND->ssl, hostname)) { /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ failf(data, "couldn't set hostname in PolarSSL"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { static const char *protocols[3]; int cur = 0; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif protocols[cur++] = ALPN_HTTP_1_1; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); protocols[cur] = NULL; ssl_set_alpn_protocols(&BACKEND->ssl, protocols); } #endif #ifdef POLARSSL_DEBUG ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
static CURLcode polarssl_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy, NULL, 0)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else entropy_init(&connssl->entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy, NULL, 0)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(x509_crt)); if(data->set.str[STRING_SSL_CAFILE]) { ret = x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(data->set.str[STRING_SSL_CAPATH]) { ret = x509_crt_parse_path(&connssl->cacert, data->set.str[STRING_SSL_CAPATH]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(x509_crt)); if(data->set.str[STRING_CERT]) { ret = x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_CERT], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(data->set.str[STRING_KEY]) { pk_context pk; pk_init(&pk); ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) rsa_copy(&connssl->rsa, pk_rsa(pk)); else rsa_free(&connssl->rsa); pk_free(&pk); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_KEY], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&connssl->crl, 0, sizeof(x509_crl)); if(data->set.str[STRING_SSL_CRLFILE]) { ret = x509_crl_parse_file(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "PolarSSL: Connecting to %s:%d\n", conn->host.name, conn->remote_port); if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } switch(data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); break; } ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(&connssl->ssl, ctr_drbg_random, &connssl->ctr_drbg); ssl_set_bio(&connssl->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ if(conn->ssl_config.sessionid) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { ret = ssl_set_session(&connssl->ssl, old_session); Curl_ssl_sessionid_unlock(conn); if(ret) { failf(data, "ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "PolarSSL re-using session\n"); } } ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, &connssl->crl, conn->host.name); ssl_set_own_cert_rsa(&connssl->ssl, &connssl->clicert, &connssl->rsa); if(ssl_set_hostname(&connssl->ssl, conn->host.name)) { /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ failf(data, "couldn't set hostname in PolarSSL"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { static const char* protocols[3]; int cur = 0; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif protocols[cur++] = ALPN_HTTP_1_1; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); protocols[cur] = NULL; ssl_set_alpn_protocols(&connssl->ssl, protocols); } #endif #ifdef POLARSSL_DEBUG ssl_set_dbg(&connssl->ssl, polarssl_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
static CURLcode polarssl_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif void *old_session = NULL; size_t old_session_size = 0; char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy, connssl->ssn.id, connssl->ssn.length)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else entropy_init(&connssl->entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy, connssl->ssn.id, connssl->ssn.length)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(x509_crt)); if(data->set.str[STRING_SSL_CAFILE]) { ret = x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(data->set.str[STRING_SSL_CAPATH]) { ret = x509_crt_parse_path(&connssl->cacert, data->set.str[STRING_SSL_CAPATH]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(x509_crt)); if(data->set.str[STRING_CERT]) { ret = x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_CERT], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(data->set.str[STRING_KEY]) { pk_context pk; pk_init(&pk); ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) rsa_copy(&connssl->rsa, pk_rsa(pk)); else rsa_free(&connssl->rsa); pk_free(&pk); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_KEY], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&connssl->crl, 0, sizeof(x509_crl)); if(data->set.str[STRING_SSL_CRLFILE]) { ret = x509_crl_parse_file(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "PolarSSL: Connecting to %s:%d\n", conn->host.name, conn->remote_port); if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } switch(data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); break; } ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(&connssl->ssl, ctr_drbg_random, &connssl->ctr_drbg); ssl_set_bio(&connssl->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { memcpy(&connssl->ssn, old_session, old_session_size); infof(data, "PolarSSL re-using session\n"); } ssl_set_session(&connssl->ssl, &connssl->ssn); ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, &connssl->crl, conn->host.name); ssl_set_own_cert_rsa(&connssl->ssl, &connssl->clicert, &connssl->rsa); if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && #ifdef ENABLE_IPV6 !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && #endif sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) { infof(data, "WARNING: failed to configure " "server name indication (SNI) TLS extension\n"); } #ifdef HAS_ALPN if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { if(data->set.ssl_enable_alpn) { static const char* protocols[] = { NGHTTP2_PROTO_VERSION_ID, ALPN_HTTP_1_1, NULL }; ssl_set_alpn_protocols(&connssl->ssl, protocols); infof(data, "ALPN, offering %s, %s\n", protocols[0], protocols[1]); } } #endif #ifdef POLARSSL_DEBUG ssl_set_dbg(&connssl->ssl, polarssl_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
LWS_VISIBLE int lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) { struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n, m; #if !defined(USE_WOLFSSL) && !defined(LWS_USE_POLARSSL) && !defined(LWS_USE_MBEDTLS) BIO *bio; #endif if (!LWS_SSL_ENABLED(wsi->vhost)) return 0; switch (wsi->mode) { case LWSCM_SSL_INIT: if (wsi->ssl) lwsl_err("%s: leaking ssl\n", __func__); if (accept_fd == LWS_SOCK_INVALID) assert(0); #if defined(LWS_USE_POLARSSL) { ssl_session *ssn; int rc; wsi->ssl = lws_zalloc(sizeof(ssl_context)); ssn = lws_zalloc(sizeof(ssl_session)); rc = ssl_init(wsi->ssl); if (rc) { lwsl_err("ssl_init failed\n"); goto fail; } ssl_set_endpoint(wsi->ssl, SSL_IS_SERVER); ssl_set_authmode(wsi->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(wsi->ssl, urandom_bytes, NULL); ssl_set_dbg(wsi->ssl, pssl_debug, NULL); ssl_set_bio(wsi->ssl, net_recv, &wsi->sock, net_send, &wsi->sock); ssl_set_ciphersuites(wsi->ssl, ciphers); ssl_set_session(wsi->ssl, ssn); ssl_set_ca_chain(wsi->ssl, &wsi->vhost->ssl_ctx->ca, NULL, NULL); ssl_set_own_cert_rsa(wsi->ssl, &wsi->vhost->ssl_ctx->certificate, &wsi->vhost->ssl_ctx->key); // ssl_set_dh_param(wsi->ssl, my_dhm_P, my_dhm_G); lwsl_err("%s: polarssl init done\n", __func__); } #else #if defined(LWS_USE_MBEDTLS) #else wsi->ssl = SSL_new(wsi->vhost->ssl_ctx); if (wsi->ssl == NULL) { lwsl_err("SSL_new failed: %s\n", ERR_error_string(lws_ssl_get_error(wsi, 0), NULL)); lws_decode_ssl_error(); if (accept_fd != LWS_SOCK_INVALID) compatible_close(accept_fd); goto fail; } SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index, wsi->vhost); SSL_set_fd(wsi->ssl, accept_fd); #endif #endif #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL CyaSSL_set_using_nonblock(wsi->ssl, 1); #else wolfSSL_set_using_nonblock(wsi->ssl, 1); #endif #else #if defined(LWS_USE_POLARSSL) #else #if defined(LWS_USE_MBEDTLS) #else SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); bio = SSL_get_rbio(wsi->ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); bio = SSL_get_wbio(wsi->ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); #endif #endif #endif /* * we are not accepted yet, but we need to enter ourselves * as a live connection. That way we can retry when more * pieces come if we're not sorted yet */ wsi->mode = LWSCM_SSL_ACK_PENDING; if (insert_wsi_socket_into_fds(context, wsi)) { lwsl_err("%s: failed to insert into fds\n", __func__); goto fail; } lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT, context->timeout_secs); lwsl_info("inserted SSL accept into fds, trying SSL_accept\n"); /* fallthru */ case LWSCM_SSL_ACK_PENDING: if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { lwsl_err("%s: lws_change_pollfd failed\n", __func__); goto fail; } lws_latency_pre(context, wsi); n = recv(wsi->sock, (char *)pt->serv_buf, context->pt_serv_buf_size, MSG_PEEK); /* * optionally allow non-SSL connect on SSL listening socket * This is disabled by default, if enabled it goes around any * SSL-level access control (eg, client-side certs) so leave * it disabled unless you know it's not a problem for you */ if (wsi->vhost->allow_non_ssl_on_ssl_port) { if (n >= 1 && pt->serv_buf[0] >= ' ') { /* * TLS content-type for Handshake is 0x16, and * for ChangeCipherSpec Record, it's 0x14 * * A non-ssl session will start with the HTTP * method in ASCII. If we see it's not a legit * SSL handshake kill the SSL for this * connection and try to handle as a HTTP * connection upgrade directly. */ wsi->use_ssl = 0; #if defined(LWS_USE_POLARSSL) ssl_close_notify(wsi->ssl); ssl_free(wsi->ssl); #else #if defined(LWS_USE_MBEDTLS) #else SSL_shutdown(wsi->ssl); SSL_free(wsi->ssl); #endif #endif wsi->ssl = NULL; if (lws_check_opt(context->options, LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)) wsi->redirect_to_https = 1; goto accepted; } if (!n) /* * connection is gone, or nothing to read * if it's gone, we will timeout on * PENDING_TIMEOUT_SSL_ACCEPT */ break; if (n < 0 && (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK)) { /* * well, we get no way to know ssl or not * so go around again waiting for something * to come and give us a hint, or timeout the * connection. */ m = SSL_ERROR_WANT_READ; goto go_again; } } /* normal SSL connection processing path */ #if defined(LWS_USE_POLARSSL) n = ssl_handshake(wsi->ssl); #else #if defined(LWS_USE_MBEDTLS) #else n = SSL_accept(wsi->ssl); #endif #endif lws_latency(context, wsi, "SSL_accept LWSCM_SSL_ACK_PENDING\n", n, n == 1); if (n == 1) goto accepted; m = lws_ssl_get_error(wsi, n); lwsl_debug("SSL_accept failed %d / %s\n", m, ERR_error_string(m, NULL)); go_again: if (m == SSL_ERROR_WANT_READ) { if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { lwsl_err("%s: WANT_READ change_pollfd failed\n", __func__); goto fail; } lwsl_info("SSL_ERROR_WANT_READ\n"); break; } if (m == SSL_ERROR_WANT_WRITE) { if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) { lwsl_err("%s: WANT_WRITE change_pollfd failed\n", __func__); goto fail; } break; } lwsl_err("SSL_accept failed skt %u: %s\n", wsi->sock, ERR_error_string(m, NULL)); lws_ssl_elaborate_error(); goto fail; accepted: /* OK, we are accepted... give him some time to negotiate */ lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, context->timeout_secs); wsi->mode = LWSCM_HTTP_SERVING; lws_http2_configure_if_upgraded(wsi); lwsl_debug("accepted new SSL conn\n"); break; } return 0; fail: return 1; }