summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/vtls/schannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/schannel.c')
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 0a8e606..dfec66d 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
*
@@ -325,13 +325,15 @@ get_alg_id_by_name(char *name)
return 0;
}
+#define NUM_CIPHERS 47 /* There are 47 options listed above */
+
static CURLcode
set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
ALG_ID *algIds)
{
char *startCur = ciphers;
int algCount = 0;
- while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) {
+ while(startCur && (0 != *startCur) && (algCount < NUM_CIPHERS)) {
long alg = strtol(startCur, 0, 0);
if(!alg)
alg = get_alg_id_by_name(startCur);
@@ -418,11 +420,14 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SCHANNEL_CRED schannel_cred;
+ ALG_ID algIds[NUM_CIPHERS];
PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
+
/* setup Schannel API options */
memset(&schannel_cred, 0, sizeof(schannel_cred));
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
@@ -502,7 +507,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
if(SSL_CONN_CONFIG(cipher_list)) {
result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
- backend->algIds);
+ algIds);
if(CURLE_OK != result) {
failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
return result;
@@ -765,11 +770,12 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
- TCHAR *host_name;
CURLcode result;
char * const hostname = SSL_HOST_NAME();
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
+
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 1/3)",
hostname, conn->remote_port));
@@ -846,10 +852,21 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
if(!backend->cred) {
+ char *snihost;
result = schannel_acquire_credential_handle(data, conn, sockindex);
if(result != CURLE_OK) {
return result;
}
+ /* A hostname associated with the credential is needed by
+ InitializeSecurityContext for SNI and other reasons. */
+ snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+ if(!snihost) {
+ failf(data, "Failed to set SNI");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost);
+ if(!backend->cred->sni_hostname)
+ return CURLE_OUT_OF_MEMORY;
}
/* Warn if SNI is disabled due to use of an IP address */
@@ -891,14 +908,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
alpn_buffer[cur++] = ALPN_H2_LENGTH;
memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
cur += ALPN_H2_LENGTH;
- infof(data, "schannel: ALPN, offering %s", ALPN_H2);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
}
#endif
alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, "schannel: ALPN, offering %s", ALPN_HTTP_1_1);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
*list_len = curlx_uitous(cur - list_start_index);
*extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
@@ -936,10 +953,6 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- host_name = curlx_convert_UTF8_to_tchar(hostname);
- if(!host_name)
- return CURLE_OUT_OF_MEMORY;
-
/* Schannel InitializeSecurityContext:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
@@ -948,13 +961,12 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
us problems with inbuf regardless. https://github.com/curl/curl/issues/983
*/
sspi_status = s_pSecFn->InitializeSecurityContext(
- &backend->cred->cred_handle, NULL, host_name, backend->req_flags, 0, 0,
+ &backend->cred->cred_handle, NULL, backend->cred->sni_hostname,
+ backend->req_flags, 0, 0,
(backend->use_alpn ? &inbuf_desc : NULL),
0, &backend->ctxt->ctxt_handle,
&outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp);
- curlx_unicodefree(host_name);
-
if(sspi_status != SEC_I_CONTINUE_NEEDED) {
char buffer[STRERROR_LEN];
Curl_safefree(backend->ctxt);
@@ -1027,15 +1039,16 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
bool doread;
- char * const hostname = SSL_HOST_NAME();
const char *pubkey_ptr;
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
+
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 2/3)",
- hostname, conn->remote_port));
+ SSL_HOST_NAME(), conn->remote_port));
if(!backend->cred || !backend->ctxt)
return CURLE_SSL_CONNECT_ERROR;
@@ -1083,7 +1096,6 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
for(;;) {
- TCHAR *host_name;
if(doread) {
/* read encrypted handshake data from socket */
result = Curl_read_plain(conn->sock[sockindex],
@@ -1136,17 +1148,12 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
memcpy(inbuf[0].pvBuffer, backend->encdata_buffer,
backend->encdata_offset);
- host_name = curlx_convert_UTF8_to_tchar(hostname);
- if(!host_name)
- return CURLE_OUT_OF_MEMORY;
-
sspi_status = s_pSecFn->InitializeSecurityContext(
&backend->cred->cred_handle, &backend->ctxt->ctxt_handle,
- host_name, backend->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+ backend->cred->sni_hostname, backend->req_flags,
+ 0, 0, &inbuf_desc, 0, NULL,
&outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp);
- curlx_unicodefree(host_name);
-
/* free buffer for received handshake data */
Curl_safefree(inbuf[0].pvBuffer);
@@ -1279,7 +1286,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(pubkey_ptr) {
result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
if(result) {
- failf(data, "SSL: public key does not match pinned public key!");
+ failf(data, "SSL: public key does not match pinned public key");
return result;
}
}
@@ -1370,6 +1377,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+ DEBUGASSERT(backend);
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 3/3)",
@@ -1408,7 +1416,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(alpn_result.ProtoNegoStatus ==
SecApplicationProtocolNegotiationStatus_Success) {
- infof(data, "schannel: ALPN, server accepted to use %.*s",
+ infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR,
alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
#ifdef USE_HTTP2
@@ -1425,7 +1433,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
}
}
else
- infof(data, "ALPN, server did not agree to a protocol");
+ infof(data, VTLS_INFOF_NO_ALPN);
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
@@ -1610,6 +1618,7 @@ schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
*/
{
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
conn->sslContext = &backend->ctxt->ctxt_handle;
}
#endif
@@ -1640,6 +1649,8 @@ schannel_send(struct Curl_easy *data, int sockindex,
CURLcode result;
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
+
/* check if the maximum stream sizes were queried */
if(backend->stream_sizes.cbMaximumMessage == 0) {
sspi_status = s_pSecFn->QueryContextAttributes(
@@ -1788,6 +1799,8 @@ schannel_recv(struct Curl_easy *data, int sockindex,
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
+
/****************************************************************************
* Don't return or set backend->recv_unrecoverable_err unless in the cleanup.
* The pattern for return error is set *err, optional infof, goto cleanup.
@@ -2122,6 +2135,8 @@ static bool schannel_data_pending(const struct connectdata *conn,
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+ DEBUGASSERT(backend);
+
if(connssl->use) /* SSL/TLS is in use */
return (backend->decdata_offset > 0 ||
(backend->encdata_offset > 0 && !backend->encdata_is_incomplete));
@@ -2138,6 +2153,7 @@ static void schannel_session_free(void *ptr)
cred->refcount--;
if(cred->refcount == 0) {
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+ curlx_unicodefree(cred->sni_hostname);
Curl_safefree(cred);
}
}
@@ -2157,6 +2173,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(data);
+ DEBUGASSERT(backend);
if(connssl->use) {
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu",
@@ -2170,7 +2187,6 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
SecBuffer outbuf;
SecBufferDesc outbuf_desc;
CURLcode result;
- TCHAR *host_name;
DWORD dwshut = SCHANNEL_SHUTDOWN;
InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
@@ -2185,10 +2201,6 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
}
- host_name = curlx_convert_UTF8_to_tchar(hostname);
- if(!host_name)
- return CURLE_OUT_OF_MEMORY;
-
/* setup output buffer */
InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
@@ -2196,7 +2208,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
sspi_status = s_pSecFn->InitializeSecurityContext(
&backend->cred->cred_handle,
&backend->ctxt->ctxt_handle,
- host_name,
+ backend->cred->sni_hostname,
backend->req_flags,
0,
0,
@@ -2207,8 +2219,6 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
&backend->ret_flags,
&backend->ctxt->time_stamp);
- curlx_unicodefree(host_name);
-
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
ssize_t written;
@@ -2314,6 +2324,8 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
/* Result is returned to caller */
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ DEBUGASSERT(backend);
+
/* if a path wasn't specified, don't pin */
if(!pinnedpubkey)
return CURLE_OK;
@@ -2359,7 +2371,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
(const unsigned char *)pubkey->header,
(size_t)(pubkey->end - pubkey->header));
if(result) {
- failf(data, "SSL: public key does not match pinned public key!");
+ failf(data, "SSL: public key does not match pinned public key");
}
} while(0);
@@ -2434,6 +2446,7 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
+ DEBUGASSERT(backend);
return &backend->ctxt->ctxt_handle;
}