diff options
Diffstat (limited to 'lib/vtls/schannel_verify.c')
-rw-r--r-- | lib/vtls/schannel_verify.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index c582ee4..a5d5c98 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -39,8 +39,6 @@ #include "schannel.h" #include "schannel_int.h" -#ifdef HAS_MANUAL_VERIFY_API - #include "vtls.h" #include "vtls_int.h" #include "sendf.h" @@ -56,6 +54,9 @@ #define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend) + +#ifdef HAS_MANUAL_VERIFY_API + #define MAX_CAFILE_SIZE 1048576 /* 1 MiB */ #define BEGIN_CERT "-----BEGIN CERTIFICATE-----" #define END_CERT "\n-----END CERTIFICATE-----" @@ -330,6 +331,8 @@ cleanup: return result; } +#endif /* HAS_MANUAL_VERIFY_API */ + /* * Returns the number of characters necessary to populate all the host_names. * If host_names is not NULL, populate it with all the host names. Each string @@ -353,10 +356,10 @@ static DWORD cert_get_name_string(struct Curl_easy *data, LPTSTR current_pos = NULL; DWORD i; +#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */ if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { -#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG /* CertGetNameString will provide the 8-bit character string without * any decoding */ DWORD name_flags = @@ -368,8 +371,8 @@ static DWORD cert_get_name_string(struct Curl_easy *data, host_names, length); return actual_length; -#endif } +#endif compute_content = host_names != NULL && length != 0; @@ -457,17 +460,34 @@ static DWORD cert_get_name_string(struct Curl_easy *data, return actual_length; } -static CURLcode verify_host(struct Curl_easy *data, - CERT_CONTEXT *pCertContextServer, - const char *conn_hostname) +/* Verify the server's hostname */ +CURLcode Curl_verify_host(struct Curl_cfilter *cf, + struct Curl_easy *data) { + struct ssl_connect_data *connssl = cf->ctx; + SECURITY_STATUS sspi_status; CURLcode result = CURLE_PEER_FAILED_VERIFICATION; + CERT_CONTEXT *pCertContextServer = NULL; TCHAR *cert_hostname_buff = NULL; size_t cert_hostname_buff_index = 0; + const char *conn_hostname = connssl->hostname; size_t hostlen = strlen(conn_hostname); DWORD len = 0; DWORD actual_len = 0; + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((sspi_status != SEC_E_OK) || !pCertContextServer) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: Failed to read remote certificate context: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + result = CURLE_PEER_FAILED_VERIFICATION; + goto cleanup; + } + /* Determine the size of the string needed for the cert hostname */ len = cert_get_name_string(data, pCertContextServer, NULL, 0); if(len == 0) { @@ -498,10 +518,9 @@ static CURLcode verify_host(struct Curl_easy *data, goto cleanup; } - /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output - * will contain all DNS names, where each name is null-terminated - * and the last DNS name is double null-terminated. Due to this - * encoding, use the length of the buffer to iterate over all names. + /* cert_hostname_buff contains all DNS names, where each name is + * null-terminated and the last DNS name is double null-terminated. Due to + * this encoding, use the length of the buffer to iterate over all names. */ result = CURLE_PEER_FAILED_VERIFICATION; while(cert_hostname_buff_index < len && @@ -560,9 +579,15 @@ static CURLcode verify_host(struct Curl_easy *data, cleanup: Curl_safefree(cert_hostname_buff); + if(pCertContextServer) + CertFreeCertificateContext(pCertContextServer); + return result; } + +#ifdef HAS_MANUAL_VERIFY_API +/* Verify the server's certificate and hostname */ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, struct Curl_easy *data) { @@ -721,7 +746,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, if(result == CURLE_OK) { if(conn_config->verifyhost) { - result = verify_host(data, pCertContextServer, connssl->hostname); + result = Curl_verify_host(cf, data); } } |