diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/schannel.c')
-rw-r--r-- | Utilities/cmcurl/lib/vtls/schannel.c | 81 |
1 files changed, 62 insertions, 19 deletions
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c index ac8b705..c9b5132 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.c +++ b/Utilities/cmcurl/lib/vtls/schannel.c @@ -7,7 +7,7 @@ * * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de> * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com> - * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -103,6 +103,41 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, } static CURLcode +set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_1: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_2: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Schannel: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +} + +static CURLcode schannel_connect_step1(struct connectdata *conn, int sockindex) { ssize_t written = -1; @@ -124,12 +159,20 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) #endif TCHAR *host_name; CURLcode result; - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", hostname, conn->remote_port); + if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, + VERSION_LESS_THAN_EQUAL)) { + /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and + algorithms that may not be supported by all servers. */ + infof(data, "schannel: WinSSL version is old and may not be able to " + "connect to some servers due to lack of SNI, algorithms, etc.\n"); + } + #ifdef HAS_ALPN /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. Also it doesn't seem to be supported for Wine, see curl bug #983. */ @@ -145,7 +188,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) connssl->cred = NULL; /* check for an existing re-usable credential handle */ - if(data->set.general_ssl.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { connssl->cred = old_cred; @@ -197,7 +240,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; infof(data, "schannel: verifyhost setting prevents Schannel from " "comparing the supplied target name with the subject " - "names in server certificates. Also disables SNI.\n"); + "names in server certificates.\n"); } switch(conn->ssl_config.version) { @@ -208,17 +251,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) SP_PROT_TLS1_2_CLIENT; break; case CURL_SSLVERSION_TLSv1_0: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT; - break; case CURL_SSLVERSION_TLSv1_1: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT; - break; case CURL_SSLVERSION_TLSv1_2: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; - break; case CURL_SSLVERSION_TLSv1_3: - failf(data, "Schannel: TLS 1.3 is not yet supported"); - return CURLE_SSL_CONNECT_ERROR; + { + result = set_ssl_version_min_max(&schannel_cred, conn); + if(result != CURLE_OK) + return result; + break; + } case CURL_SSLVERSION_SSLv3: schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; break; @@ -415,7 +456,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) TCHAR *host_name; CURLcode result; bool doread; - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; @@ -649,8 +690,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; +#ifndef CURL_DISABLE_VERBOSE_STRINGS const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; +#endif #ifdef HAS_ALPN SecPkgContext_ApplicationProtocol alpn_result; #endif @@ -714,7 +757,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) #endif /* save the current session data for possible re-use */ - if(data->set.general_ssl.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { bool incache; struct curl_schannel_cred *old_cred = NULL; @@ -1391,7 +1434,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) */ struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", @@ -1516,21 +1559,21 @@ size_t Curl_schannel_version(char *buffer, size_t size) return size; } -int Curl_schannel_random(unsigned char *entropy, size_t length) +CURLcode Curl_schannel_random(unsigned char *entropy, size_t length) { HCRYPTPROV hCryptProv = 0; if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - return 1; + return CURLE_FAILED_INIT; if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { CryptReleaseContext(hCryptProv, 0UL); - return 1; + return CURLE_FAILED_INIT; } CryptReleaseContext(hCryptProv, 0UL); - return 0; + return CURLE_OK; } #ifdef _WIN32_WCE |