summaryrefslogtreecommitdiffstats
path: root/lib/vtls/schannel_verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vtls/schannel_verify.c')
-rw-r--r--lib/vtls/schannel_verify.c49
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);
}
}