summaryrefslogtreecommitdiffstats
path: root/lib/vtls/schannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vtls/schannel.c')
-rw-r--r--lib/vtls/schannel.c137
1 files changed, 73 insertions, 64 deletions
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 0668f98..2bcf11d 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -117,6 +117,10 @@
#define SP_PROT_TLS1_2_CLIENT 0x00000800
#endif
+#ifndef SCH_USE_STRONG_CRYPTO
+#define SCH_USE_STRONG_CRYPTO 0x00400000
+#endif
+
#ifndef SECBUFFER_ALERT
#define SECBUFFER_ALERT 17
#endif
@@ -324,17 +328,22 @@ get_alg_id_by_name(char *name)
}
static CURLcode
-set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
+set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
+ ALG_ID *algIds)
{
char *startCur = ciphers;
int algCount = 0;
- static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
- while(startCur && (0 != *startCur) && (algCount < 45)) {
+ while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) {
long alg = strtol(startCur, 0, 0);
if(!alg)
alg = get_alg_id_by_name(startCur);
if(alg)
algIds[algCount++] = alg;
+ else if(!strncmp(startCur, "USE_STRONG_CRYPTO",
+ sizeof("USE_STRONG_CRYPTO") - 1) ||
+ !strncmp(startCur, "SCH_USE_STRONG_CRYPTO",
+ sizeof("SCH_USE_STRONG_CRYPTO") - 1))
+ schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO;
else
return CURLE_SSL_CIPHER;
startCur = strchr(startCur, ':');
@@ -358,7 +367,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
size_t store_name_len;
sep = _tcschr(path, TEXT('\\'));
- if(sep == NULL)
+ if(!sep)
return CURLE_SSL_CERTPROBLEM;
store_name_len = sep - path;
@@ -388,7 +397,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
store_path_start = sep + 1;
sep = _tcschr(store_path_start, TEXT('\\'));
- if(sep == NULL)
+ if(!sep)
return CURLE_SSL_CERTPROBLEM;
*thumbprint = sep + 1;
@@ -398,7 +407,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
*sep = TEXT('\0');
*store_path = _tcsdup(store_path_start);
*sep = TEXT('\\');
- if(*store_path == NULL)
+ if(!*store_path)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -428,12 +437,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
TCHAR *host_name;
CURLcode result;
-#ifndef CURL_DISABLE_PROXY
- char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- char * const hostname = conn->host.name;
-#endif
+ char * const hostname = SSL_HOST_NAME();
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
@@ -469,7 +473,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
#else
#ifdef HAS_MANUAL_VERIFY_API
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
BACKEND->use_manual_cred_validation = true;
@@ -483,7 +487,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
else
BACKEND->use_manual_cred_validation = false;
#else
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
failf(data, "schannel: CA cert support not built in");
return CURLE_NOT_BUILT_IN;
}
@@ -496,6 +500,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
(void **)&old_cred, NULL, sockindex)) {
BACKEND->cred = old_cred;
DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
@@ -522,14 +527,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
- if(data->set.ssl.no_revoke) {
+ if(SSL_SET_OPTION(no_revoke)) {
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
DEBUGF(infof(data, "schannel: disabled server certificate revocation "
"checks\n"));
}
- else if(data->set.ssl.revoke_best_effort) {
+ else if(SSL_SET_OPTION(revoke_best_effort)) {
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
@@ -557,6 +562,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
"names in server certificates.\n"));
}
+ if(!SSL_SET_OPTION(auto_client_cert)) {
+ schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
+ schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+ infof(data, "schannel: disabled automatic use of client certificate\n");
+ }
+ else
+ infof(data, "schannel: enabled automatic use of client certificate\n");
+
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
@@ -571,18 +584,17 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
break;
}
case CURL_SSLVERSION_SSLv3:
- schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
- break;
case CURL_SSLVERSION_SSLv2:
- schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
- break;
+ failf(data, "SSL versions not supported");
+ return CURLE_NOT_BUILT_IN;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
if(SSL_CONN_CONFIG(cipher_list)) {
- result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
+ result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
+ BACKEND->algIds);
if(CURLE_OK != result) {
failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
return result;
@@ -699,7 +711,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
if(!blob)
free(certdata);
- if(cert_store == NULL) {
+ if(!cert_store) {
DWORD errorcode = GetLastError();
if(errorcode == ERROR_INVALID_PASSWORD)
failf(data, "schannel: Failed to import cert file %s, "
@@ -716,7 +728,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
CERT_FIND_ANY, NULL, NULL);
- if(client_certs[0] == NULL) {
+ if(!client_certs[0]) {
failf(data, "schannel: Failed to get certificate from file %s"
", last error is 0x%x",
cert_showfilename_error, GetLastError());
@@ -860,11 +872,11 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
list_start_index = cur;
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
- memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN);
- cur += NGHTTP2_PROTO_ALPN_LEN;
- infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
+ memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
+ cur += ALPN_H2_LENGTH;
+ infof(data, "schannel: ALPN, offering %s\n", ALPN_H2);
}
#endif
@@ -892,11 +904,15 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
- /* setup request flags */
+ /* security request flags */
BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM;
+ if(!SSL_SET_OPTION(auto_client_cert)) {
+ BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+ }
+
/* allocate memory for the security context handle */
BACKEND->ctxt = (struct Curl_schannel_ctxt *)
calloc(1, sizeof(struct Curl_schannel_ctxt));
@@ -996,12 +1012,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
bool doread;
-#ifndef CURL_DISABLE_PROXY
- char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- char * const hostname = conn->host.name;
-#endif
+ char * const hostname = SSL_HOST_NAME();
const char *pubkey_ptr;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -1014,23 +1025,23 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
/* buffer to store previously received and decrypted data */
- if(BACKEND->decdata_buffer == NULL) {
+ if(!BACKEND->decdata_buffer) {
BACKEND->decdata_offset = 0;
BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
- if(BACKEND->decdata_buffer == NULL) {
+ if(!BACKEND->decdata_buffer) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* buffer to store previously received and encrypted data */
- if(BACKEND->encdata_buffer == NULL) {
+ if(!BACKEND->encdata_buffer) {
BACKEND->encdata_is_incomplete = false;
BACKEND->encdata_offset = 0;
BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
- if(BACKEND->encdata_buffer == NULL) {
+ if(!BACKEND->encdata_buffer) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -1045,7 +1056,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
- if(reallocated_buffer == NULL) {
+ if(!reallocated_buffer) {
failf(data, "schannel: unable to re-allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -1100,7 +1111,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 3);
- if(inbuf[0].pvBuffer == NULL) {
+ if(!inbuf[0].pvBuffer) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -1250,9 +1261,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
}
- pubkey_ptr = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ pubkey_ptr = SSL_PINNED_PUB_KEY();
if(pubkey_ptr) {
result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
if(result) {
@@ -1337,9 +1346,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
+ bool isproxy = SSL_IS_PROXY();
#ifdef DEBUGBUILD
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
+ const char * const hostname = SSL_HOST_NAME();
#endif
#ifdef HAS_ALPN
SecPkgContext_ApplicationProtocol alpn_result;
@@ -1387,10 +1396,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
infof(data, "schannel: ALPN, server accepted to use %.*s\n",
alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
-#ifdef USE_NGHTTP2
- if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
+#ifdef USE_HTTP2
+ if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH &&
+ !memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) {
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
@@ -1414,8 +1422,8 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct Curl_schannel_cred *old_cred = NULL;
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL,
- sockindex));
+ incache = !(Curl_ssl_getsessionid(data, conn, isproxy, (void **)&old_cred,
+ NULL, sockindex));
if(incache) {
if(old_cred != BACKEND->cred) {
DEBUGF(infof(data,
@@ -1426,7 +1434,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred,
+ result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred,
sizeof(struct Curl_schannel_cred),
sockindex);
if(result) {
@@ -1451,7 +1459,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&ccert_context);
- if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
+ if((sspi_status != SEC_E_OK) || !ccert_context) {
failf(data, "schannel: failed to retrieve remote cert context");
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -1803,7 +1811,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
}
reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
- if(reallocated_buffer == NULL) {
+ if(!reallocated_buffer) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
@@ -1892,7 +1900,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
}
reallocated_buffer = realloc(BACKEND->decdata_buffer,
reallocated_length);
- if(reallocated_buffer == NULL) {
+ if(!reallocated_buffer) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
@@ -2126,12 +2134,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
* Shutting Down an Schannel Connection
*/
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-#ifndef CURL_DISABLE_PROXY
- char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- char * const hostname = conn->host.name;
-#endif
+ char * const hostname = SSL_HOST_NAME();
DEBUGASSERT(data);
@@ -2294,7 +2297,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer);
- if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ 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)));
@@ -2404,6 +2407,9 @@ const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
SSLSUPP_CERTINFO |
+#ifdef HAS_MANUAL_VERIFY_API
+ SSLSUPP_CAINFO_BLOB |
+#endif
SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
@@ -2418,6 +2424,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_cert_status_request, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2426,7 +2433,9 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- schannel_sha256sum /* sha256sum */
+ schannel_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_SCHANNEL */