summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-12-25 22:23:05 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-12-26 11:59:28 +0100
commitb8ef4a845be8cc2b82f3fbfee23f88b376655c0e (patch)
treec6bd4ddf165628fb328063f5a53112fffa76f3df
parent4a2ab69ab52e5dbf006533fc509b40d22cfbdbfa (diff)
downloadcurl-b8ef4a845be8cc2b82f3fbfee23f88b376655c0e.tar.gz
schannel: remove the BACKEND define kludge
Closes #8182
-rw-r--r--lib/vtls/schannel.c385
1 files changed, 198 insertions, 187 deletions
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 5d18037e8..4098f6a3b 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -147,8 +147,6 @@
#define ALG_CLASS_DHASH ALG_CLASS_HASH
#endif
-#define BACKEND connssl->backend
-
static Curl_recv schannel_recv;
static Curl_send schannel_send;
@@ -423,6 +421,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
+ struct ssl_backend_data *backend = connssl->backend;
/* setup Schannel API options */
memset(&schannel_cred, 0, sizeof(schannel_cred));
@@ -430,7 +429,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
if(conn->ssl_config.verifypeer) {
#ifdef HAS_MANUAL_VERIFY_API
- if(BACKEND->use_manual_cred_validation)
+ if(backend->use_manual_cred_validation)
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
else
#endif
@@ -503,7 +502,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);
+ backend->algIds);
if(CURLE_OK != result) {
failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
return result;
@@ -704,9 +703,9 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
#endif
/* allocate memory for the re-usable credential handle */
- BACKEND->cred = (struct Curl_schannel_cred *)
+ backend->cred = (struct Curl_schannel_cred *)
calloc(1, sizeof(struct Curl_schannel_cred));
- if(!BACKEND->cred) {
+ if(!backend->cred) {
failf(data, "schannel: unable to allocate memory");
if(client_certs[0])
@@ -714,14 +713,14 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
- BACKEND->cred->refcount = 1;
+ backend->cred->refcount = 1;
sspi_status =
s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
SECPKG_CRED_OUTBOUND, NULL,
&schannel_cred, NULL, NULL,
- &BACKEND->cred->cred_handle,
- &BACKEND->cred->time_stamp);
+ &backend->cred->cred_handle,
+ &backend->cred->time_stamp);
if(client_certs[0])
CertFreeCertificateContext(client_certs[0]);
@@ -730,7 +729,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
char buffer[STRERROR_LEN];
failf(data, "schannel: AcquireCredentialsHandle failed: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- Curl_safefree(BACKEND->cred);
+ Curl_safefree(backend->cred);
switch(sspi_status) {
case SEC_E_INSUFFICIENT_MEMORY:
return CURLE_OUT_OF_MEMORY;
@@ -769,6 +768,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
TCHAR *host_name;
CURLcode result;
char * const hostname = SSL_HOST_NAME();
+ struct ssl_backend_data *backend = connssl->backend;
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 1/3)",
@@ -785,20 +785,20 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#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. */
- BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
+ backend->use_alpn = conn->bits.tls_enable_alpn &&
!GetProcAddress(GetModuleHandle(TEXT("ntdll")),
"wine_get_version") &&
curlx_verify_windows_version(6, 3, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL);
#else
- BACKEND->use_alpn = false;
+ backend->use_alpn = false;
#endif
#ifdef _WIN32_WCE
#ifdef HAS_MANUAL_VERIFY_API
/* certificate validation on CE doesn't seem to work right; we'll
* do it following a more manual process. */
- BACKEND->use_manual_cred_validation = true;
+ backend->use_manual_cred_validation = true;
#else
#error "compiler too old to support requisite manual cert verify for Win CE"
#endif
@@ -807,7 +807,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
if(curlx_verify_windows_version(6, 1, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
- BACKEND->use_manual_cred_validation = true;
+ backend->use_manual_cred_validation = true;
}
else {
failf(data, "schannel: this version of Windows is too old to support "
@@ -816,7 +816,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
}
else
- BACKEND->use_manual_cred_validation = false;
+ backend->use_manual_cred_validation = false;
#else
if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
failf(data, "schannel: CA cert support not built in");
@@ -825,7 +825,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
#endif
- BACKEND->cred = NULL;
+ backend->cred = NULL;
/* check for an existing re-usable credential handle */
if(SSL_SET_OPTION(primary.sessionid)) {
@@ -833,19 +833,19 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
if(!Curl_ssl_getsessionid(data, conn,
SSL_IS_PROXY() ? TRUE : FALSE,
(void **)&old_cred, NULL, sockindex)) {
- BACKEND->cred = old_cred;
+ backend->cred = old_cred;
DEBUGF(infof(data, "schannel: re-using existing credential handle"));
/* increment the reference counter of the credential/session handle */
- BACKEND->cred->refcount++;
+ backend->cred->refcount++;
DEBUGF(infof(data,
"schannel: incremented credential handle refcount = %d",
- BACKEND->cred->refcount));
+ backend->cred->refcount));
}
Curl_ssl_sessionid_unlock(data);
}
- if(!BACKEND->cred) {
+ if(!backend->cred) {
result = schannel_acquire_credential_handle(data, conn, sockindex);
if(result != CURLE_OK) {
return result;
@@ -862,7 +862,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
#ifdef HAS_ALPN
- if(BACKEND->use_alpn) {
+ if(backend->use_alpn) {
int cur = 0;
int list_start_index = 0;
unsigned int *extension_len = NULL;
@@ -920,18 +920,18 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
/* security request flags */
- BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ 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;
+ backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
}
/* allocate memory for the security context handle */
- BACKEND->ctxt = (struct Curl_schannel_ctxt *)
+ backend->ctxt = (struct Curl_schannel_ctxt *)
calloc(1, sizeof(struct Curl_schannel_ctxt));
- if(!BACKEND->ctxt) {
+ if(!backend->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -948,16 +948,16 @@ 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->use_alpn ? &inbuf_desc : NULL),
- 0, &BACKEND->ctxt->ctxt_handle,
- &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
+ &backend->cred->cred_handle, NULL, host_name, 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);
+ Curl_safefree(backend->ctxt);
switch(sspi_status) {
case SEC_E_INSUFFICIENT_MEMORY:
failf(data, "schannel: initial InitializeSecurityContext failed: %s",
@@ -1001,10 +1001,10 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
DEBUGF(infof(data, "schannel: sent initial handshake data: "
"sent %zd bytes", written));
- BACKEND->recv_unrecoverable_err = CURLE_OK;
- BACKEND->recv_sspi_close_notify = false;
- BACKEND->recv_connection_closed = false;
- BACKEND->encdata_is_incomplete = false;
+ backend->recv_unrecoverable_err = CURLE_OK;
+ backend->recv_sspi_close_notify = false;
+ backend->recv_connection_closed = false;
+ backend->encdata_is_incomplete = false;
/* continue to second handshake step */
connssl->connecting_state = ssl_connect_2;
@@ -1029,6 +1029,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
bool doread;
char * const hostname = SSL_HOST_NAME();
const char *pubkey_ptr;
+ struct ssl_backend_data *backend = connssl->backend;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -1036,39 +1037,39 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
"schannel: SSL/TLS connection with %s port %hu (step 2/3)",
hostname, conn->remote_port));
- if(!BACKEND->cred || !BACKEND->ctxt)
+ if(!backend->cred || !backend->ctxt)
return CURLE_SSL_CONNECT_ERROR;
/* buffer to store previously received and decrypted data */
- 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) {
+ 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) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* buffer to store previously received and encrypted data */
- 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) {
+ 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) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* if we need a bigger buffer to read a full message, increase buffer now */
- if(BACKEND->encdata_length - BACKEND->encdata_offset <
+ if(backend->encdata_length - backend->encdata_offset <
CURL_SCHANNEL_BUFFER_FREE_SIZE) {
/* increase internal encrypted data buffer */
- size_t reallocated_length = BACKEND->encdata_offset +
+ size_t reallocated_length = backend->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE;
- reallocated_buffer = realloc(BACKEND->encdata_buffer,
+ reallocated_buffer = realloc(backend->encdata_buffer,
reallocated_length);
if(!reallocated_buffer) {
@@ -1076,8 +1077,8 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
else {
- BACKEND->encdata_buffer = reallocated_buffer;
- BACKEND->encdata_length = reallocated_length;
+ backend->encdata_buffer = reallocated_buffer;
+ backend->encdata_length = reallocated_length;
}
}
@@ -1086,10 +1087,10 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(doread) {
/* read encrypted handshake data from socket */
result = Curl_read_plain(conn->sock[sockindex],
- (char *) (BACKEND->encdata_buffer +
- BACKEND->encdata_offset),
- BACKEND->encdata_length -
- BACKEND->encdata_offset,
+ (char *) (backend->encdata_buffer +
+ backend->encdata_offset),
+ backend->encdata_length -
+ backend->encdata_offset,
&nread);
if(result == CURLE_AGAIN) {
if(connssl->connecting_state != ssl_connect_2_writing)
@@ -1105,18 +1106,18 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
/* increase encrypted data buffer offset */
- BACKEND->encdata_offset += nread;
- BACKEND->encdata_is_incomplete = false;
+ backend->encdata_offset += nread;
+ backend->encdata_is_incomplete = false;
DEBUGF(infof(data, "schannel: encrypted data got %zd", nread));
}
DEBUGF(infof(data,
"schannel: encrypted data buffer: offset %zu length %zu",
- BACKEND->encdata_offset, BACKEND->encdata_length));
+ backend->encdata_offset, backend->encdata_length));
/* setup input buffers */
- InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
- curlx_uztoul(BACKEND->encdata_offset));
+ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(backend->encdata_offset),
+ curlx_uztoul(backend->encdata_offset));
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, inbuf, 2);
@@ -1132,17 +1133,17 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
/* copy received handshake data into input buffer */
- memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
- BACKEND->encdata_offset);
+ 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,
- &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
+ &backend->cred->cred_handle, &backend->ctxt->ctxt_handle,
+ host_name, backend->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+ &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp);
curlx_unicodefree(host_name);
@@ -1151,7 +1152,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
/* check if the handshake was incomplete */
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
- BACKEND->encdata_is_incomplete = true;
+ backend->encdata_is_incomplete = true;
connssl->connecting_state = ssl_connect_2_reading;
DEBUGF(infof(data,
"schannel: received incomplete message, need more data"));
@@ -1162,8 +1163,8 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
the handshake without one. This will allow connections to servers which
request a client certificate but do not require it. */
if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
- !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
- BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+ !(backend->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
+ backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
connssl->connecting_state = ssl_connect_2_writing;
DEBUGF(infof(data,
"schannel: a client certificate has been requested"));
@@ -1245,11 +1246,11 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
*/
/* check if the remaining data is less than the total amount
and therefore begins after the already processed data */
- if(BACKEND->encdata_offset > inbuf[1].cbBuffer) {
- memmove(BACKEND->encdata_buffer,
- (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
+ if(backend->encdata_offset > inbuf[1].cbBuffer) {
+ memmove(backend->encdata_buffer,
+ (backend->encdata_buffer + backend->encdata_offset) -
inbuf[1].cbBuffer, inbuf[1].cbBuffer);
- BACKEND->encdata_offset = inbuf[1].cbBuffer;
+ backend->encdata_offset = inbuf[1].cbBuffer;
if(sspi_status == SEC_I_CONTINUE_NEEDED) {
doread = FALSE;
continue;
@@ -1257,7 +1258,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
}
else {
- BACKEND->encdata_offset = 0;
+ backend->encdata_offset = 0;
}
break;
}
@@ -1284,7 +1285,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
#ifdef HAS_MANUAL_VERIFY_API
- if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
+ if(conn->ssl_config.verifypeer && backend->use_manual_cred_validation) {
return Curl_verify_certificate(data, conn, sockindex);
}
#endif
@@ -1366,6 +1367,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
#ifdef HAS_ALPN
SecPkgContext_ApplicationProtocol alpn_result;
#endif
+ struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@@ -1373,28 +1375,28 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
"schannel: SSL/TLS connection with %s port %hu (step 3/3)",
hostname, conn->remote_port));
- if(!BACKEND->cred)
+ if(!backend->cred)
return CURLE_SSL_CONNECT_ERROR;
/* check if the required context attributes are met */
- if(BACKEND->ret_flags != BACKEND->req_flags) {
- if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT))
+ if(backend->ret_flags != backend->req_flags) {
+ if(!(backend->ret_flags & ISC_RET_SEQUENCE_DETECT))
failf(data, "schannel: failed to setup sequence detection");
- if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT))
+ if(!(backend->ret_flags & ISC_RET_REPLAY_DETECT))
failf(data, "schannel: failed to setup replay detection");
- if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY))
+ if(!(backend->ret_flags & ISC_RET_CONFIDENTIALITY))
failf(data, "schannel: failed to setup confidentiality");
- if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY))
+ if(!(backend->ret_flags & ISC_RET_ALLOCATED_MEMORY))
failf(data, "schannel: failed to setup memory allocation");
- if(!(BACKEND->ret_flags & ISC_RET_STREAM))
+ if(!(backend->ret_flags & ISC_RET_STREAM))
failf(data, "schannel: failed to setup stream orientation");
return CURLE_SSL_CONNECT_ERROR;
}
#ifdef HAS_ALPN
- if(BACKEND->use_alpn) {
+ if(backend->use_alpn) {
sspi_status =
- s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ s_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle,
SECPKG_ATTR_APPLICATION_PROTOCOL,
&alpn_result);
@@ -1439,7 +1441,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
incache = !(Curl_ssl_getsessionid(data, conn, isproxy, (void **)&old_cred,
NULL, sockindex));
if(incache) {
- if(old_cred != BACKEND->cred) {
+ if(old_cred != backend->cred) {
DEBUGF(infof(data,
"schannel: old credential handle is stale, removing"));
/* we're not taking old_cred ownership here, no refcount++ is needed */
@@ -1448,7 +1450,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred,
+ result = Curl_ssl_addsessionid(data, conn, isproxy, backend->cred,
sizeof(struct Curl_schannel_cred),
sockindex, &added);
if(result) {
@@ -1458,7 +1460,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
}
else if(added) {
/* this cred session is now also referenced by sessionid cache */
- BACKEND->cred->refcount++;
+ backend->cred->refcount++;
DEBUGF(infof(data,
"schannel: stored credential handle in session cache"));
}
@@ -1469,7 +1471,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(data->set.ssl.certinfo) {
int certs_count = 0;
sspi_status =
- s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ s_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&ccert_context);
@@ -1606,7 +1608,10 @@ schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
* binding to pass the IIS extended protection checks.
* Available on Windows 7 or later.
*/
- conn->sslContext = &BACKEND->ctxt->ctxt_handle;
+ {
+ struct ssl_backend_data *backend = connssl->backend;
+ conn->sslContext = &backend->ctxt->ctxt_handle;
+ }
#endif
*done = TRUE;
@@ -1633,13 +1638,14 @@ schannel_send(struct Curl_easy *data, int sockindex,
SecBufferDesc outbuf_desc;
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
+ struct ssl_backend_data *backend = connssl->backend;
/* check if the maximum stream sizes were queried */
- if(BACKEND->stream_sizes.cbMaximumMessage == 0) {
+ if(backend->stream_sizes.cbMaximumMessage == 0) {
sspi_status = s_pSecFn->QueryContextAttributes(
- &BACKEND->ctxt->ctxt_handle,
+ &backend->ctxt->ctxt_handle,
SECPKG_ATTR_STREAM_SIZES,
- &BACKEND->stream_sizes);
+ &backend->stream_sizes);
if(sspi_status != SEC_E_OK) {
*err = CURLE_SEND_ERROR;
return -1;
@@ -1647,13 +1653,13 @@ schannel_send(struct Curl_easy *data, int sockindex,
}
/* check if the buffer is longer than the maximum message length */
- if(len > BACKEND->stream_sizes.cbMaximumMessage) {
- len = BACKEND->stream_sizes.cbMaximumMessage;
+ if(len > backend->stream_sizes.cbMaximumMessage) {
+ len = backend->stream_sizes.cbMaximumMessage;
}
/* calculate the complete message length and allocate a buffer for it */
- data_len = BACKEND->stream_sizes.cbHeader + len +
- BACKEND->stream_sizes.cbTrailer;
+ data_len = backend->stream_sizes.cbHeader + len +
+ backend->stream_sizes.cbTrailer;
ptr = (unsigned char *) malloc(data_len);
if(!ptr) {
*err = CURLE_OUT_OF_MEMORY;
@@ -1662,12 +1668,12 @@ schannel_send(struct Curl_easy *data, int sockindex,
/* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
- ptr, BACKEND->stream_sizes.cbHeader);
+ ptr, backend->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
- ptr + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
+ ptr + backend->stream_sizes.cbHeader, curlx_uztoul(len));
InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
- ptr + BACKEND->stream_sizes.cbHeader + len,
- BACKEND->stream_sizes.cbTrailer);
+ ptr + backend->stream_sizes.cbHeader + len,
+ backend->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@@ -1675,7 +1681,7 @@ schannel_send(struct Curl_easy *data, int sockindex,
memcpy(outbuf[1].pvBuffer, buf, len);
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
- sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0,
+ sspi_status = s_pSecFn->EncryptMessage(&backend->ctxt->ctxt_handle, 0,
&outbuf_desc, 0);
/* check if the message was encrypted */
@@ -1780,9 +1786,10 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* we want the length of the encrypted buffer to be at least large enough
that it can hold all the bytes requested and some TLS record overhead. */
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
+ struct ssl_backend_data *backend = connssl->backend;
/****************************************************************************
- * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup.
+ * 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.
*
* Our priority is to always return as much decrypted data to the caller as
@@ -1794,16 +1801,16 @@ schannel_recv(struct Curl_easy *data, int sockindex,
DEBUGF(infof(data, "schannel: client wants to read %zu bytes", len));
*err = CURLE_OK;
- if(len && len <= BACKEND->decdata_offset) {
+ if(len && len <= backend->decdata_offset) {
infof(data, "schannel: enough decrypted data is already available");
goto cleanup;
}
- else if(BACKEND->recv_unrecoverable_err) {
- *err = BACKEND->recv_unrecoverable_err;
+ else if(backend->recv_unrecoverable_err) {
+ *err = backend->recv_unrecoverable_err;
infof(data, "schannel: an unrecoverable error occurred in a prior call");
goto cleanup;
}
- else if(BACKEND->recv_sspi_close_notify) {
+ else if(backend->recv_sspi_close_notify) {
/* once a server has indicated shutdown there is no more encrypted data */
infof(data, "schannel: server indicated shutdown in a prior call");
goto cleanup;
@@ -1813,17 +1820,17 @@ schannel_recv(struct Curl_easy *data, int sockindex,
immediately because there may be data to decrypt (in the case we want to
decrypt all encrypted cached data) so handle !len later in cleanup.
*/
- else if(len && !BACKEND->recv_connection_closed) {
+ else if(len && !backend->recv_connection_closed) {
/* increase enc buffer in order to fit the requested amount of data */
- size = BACKEND->encdata_length - BACKEND->encdata_offset;
+ size = backend->encdata_length - backend->encdata_offset;
if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
- BACKEND->encdata_length < min_encdata_length) {
- reallocated_length = BACKEND->encdata_offset +
+ backend->encdata_length < min_encdata_length) {
+ reallocated_length = backend->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE;
if(reallocated_length < min_encdata_length) {
reallocated_length = min_encdata_length;
}
- reallocated_buffer = realloc(BACKEND->encdata_buffer,
+ reallocated_buffer = realloc(backend->encdata_buffer,
reallocated_length);
if(!reallocated_buffer) {
*err = CURLE_OUT_OF_MEMORY;
@@ -1831,21 +1838,21 @@ schannel_recv(struct Curl_easy *data, int sockindex,
goto cleanup;
}
- BACKEND->encdata_buffer = reallocated_buffer;
- BACKEND->encdata_length = reallocated_length;
- size = BACKEND->encdata_length - BACKEND->encdata_offset;
+ backend->encdata_buffer = reallocated_buffer;
+ backend->encdata_length = reallocated_length;
+ size = backend->encdata_length - backend->encdata_offset;
DEBUGF(infof(data, "schannel: encdata_buffer resized %zu",
- BACKEND->encdata_length));
+ backend->encdata_length));
}
DEBUGF(infof(data,
"schannel: encrypted data buffer: offset %zu length %zu",
- BACKEND->encdata_offset, BACKEND->encdata_length));
+ backend->encdata_offset, backend->encdata_length));
/* read encrypted data from socket */
*err = Curl_read_plain(conn->sock[sockindex],
- (char *)(BACKEND->encdata_buffer +
- BACKEND->encdata_offset),
+ (char *)(backend->encdata_buffer +
+ backend->encdata_offset),
size, &nread);
if(*err) {
nread = -1;
@@ -1858,27 +1865,27 @@ schannel_recv(struct Curl_easy *data, int sockindex,
infof(data, "schannel: Curl_read_plain returned error %d", *err);
}
else if(nread == 0) {
- BACKEND->recv_connection_closed = true;
+ backend->recv_connection_closed = true;
DEBUGF(infof(data, "schannel: server closed the connection"));
}
else if(nread > 0) {
- BACKEND->encdata_offset += (size_t)nread;
- BACKEND->encdata_is_incomplete = false;
+ backend->encdata_offset += (size_t)nread;
+ backend->encdata_is_incomplete = false;
DEBUGF(infof(data, "schannel: encrypted data got %zd", nread));
}
}
DEBUGF(infof(data,
"schannel: encrypted data buffer: offset %zu length %zu",
- BACKEND->encdata_offset, BACKEND->encdata_length));
+ backend->encdata_offset, backend->encdata_length));
/* decrypt loop */
- while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
- (!len || BACKEND->decdata_offset < len ||
- BACKEND->recv_connection_closed)) {
+ while(backend->encdata_offset > 0 && sspi_status == SEC_E_OK &&
+ (!len || backend->decdata_offset < len ||
+ backend->recv_connection_closed)) {
/* prepare data buffer for DecryptMessage call */
- InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer,
- curlx_uztoul(BACKEND->encdata_offset));
+ InitSecBuffer(&inbuf[0], SECBUFFER_DATA, backend->encdata_buffer,
+ curlx_uztoul(backend->encdata_offset));
/* we need 3 more empty input buffers for possible output */
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
@@ -1888,7 +1895,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
*/
- sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->DecryptMessage(&backend->ctxt->ctxt_handle,
&inbuf_desc, 0, NULL);
/* check if everything went fine (server may want to renegotiate
@@ -1904,37 +1911,37 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* increase buffer in order to fit the received amount of data */
size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
- if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
- BACKEND->decdata_length < len) {
+ if(backend->decdata_length - backend->decdata_offset < size ||
+ backend->decdata_length < len) {
/* increase internal decrypted data buffer */
- reallocated_length = BACKEND->decdata_offset + size;
+ reallocated_length = backend->decdata_offset + size;
/* make sure that the requested amount of data fits */
if(reallocated_length < len) {
reallocated_length = len;
}
- reallocated_buffer = realloc(BACKEND->decdata_buffer,
+ reallocated_buffer = realloc(backend->decdata_buffer,
reallocated_length);
if(!reallocated_buffer) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
}
- BACKEND->decdata_buffer = reallocated_buffer;
- BACKEND->decdata_length = reallocated_length;
+ backend->decdata_buffer = reallocated_buffer;
+ backend->decdata_length = reallocated_length;
}
/* copy decrypted data to internal buffer */
size = inbuf[1].cbBuffer;
if(size) {
- memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset,
+ memcpy(backend->decdata_buffer + backend->decdata_offset,
inbuf[1].pvBuffer, size);
- BACKEND->decdata_offset += size;
+ backend->decdata_offset += size;
}
DEBUGF(infof(data, "schannel: decrypted data added: %zu", size));
DEBUGF(infof(data,
"schannel: decrypted cached: offset %zu length %zu",
- BACKEND->decdata_offset, BACKEND->decdata_length));
+ backend->decdata_offset, backend->decdata_length));
}
/* check for remaining encrypted data */
@@ -1945,22 +1952,22 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* check if the remaining data is less than the total amount
* and therefore begins after the already processed data
*/
- if(BACKEND->encdata_offset > inbuf[3].cbBuffer) {
+ if(backend->encdata_offset > inbuf[3].cbBuffer) {
/* move remaining encrypted data forward to the beginning of
buffer */
- memmove(BACKEND->encdata_buffer,
- (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
+ memmove(backend->encdata_buffer,
+ (backend->encdata_buffer + backend->encdata_offset) -
inbuf[3].cbBuffer, inbuf[3].cbBuffer);
- BACKEND->encdata_offset = inbuf[3].cbBuffer;
+ backend->encdata_offset = inbuf[3].cbBuffer;
}
DEBUGF(infof(data,
"schannel: encrypted cached: offset %zu length %zu",
- BACKEND->encdata_offset, BACKEND->encdata_length));
+ backend->encdata_offset, backend->encdata_length));
}
else {
/* reset encrypted buffer offset, because there is no data remaining */
- BACKEND->encdata_offset = 0;
+ backend->encdata_offset = 0;
}
/* check if server wants to renegotiate the connection context */
@@ -1970,7 +1977,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
infof(data, "schannel: can't renegotiate, an error is pending");
goto cleanup;
}
- if(BACKEND->encdata_offset) {
+ if(backend->encdata_offset) {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: can't renegotiate, "
"encrypted data available");
@@ -1994,16 +2001,16 @@ schannel_recv(struct Curl_easy *data, int sockindex,
else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
/* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
returned so we have to work around that in cleanup. */
- BACKEND->recv_sspi_close_notify = true;
- if(!BACKEND->recv_connection_closed) {
- BACKEND->recv_connection_closed = true;
+ backend->recv_sspi_close_notify = true;
+ if(!backend->recv_connection_closed) {
+ backend->recv_connection_closed = true;
infof(data, "schannel: server closed the connection");
}
goto cleanup;
}
}
else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
- BACKEND->encdata_is_incomplete = true;
+ backend->encdata_is_incomplete = true;
if(!*err)
*err = CURLE_AGAIN;
infof(data, "schannel: failed to decrypt data, need more data");
@@ -2022,11 +2029,11 @@ schannel_recv(struct Curl_easy *data, int sockindex,
DEBUGF(infof(data,
"schannel: encrypted data buffer: offset %zu length %zu",
- BACKEND->encdata_offset, BACKEND->encdata_length));
+ backend->encdata_offset, backend->encdata_length));
DEBUGF(infof(data,
"schannel: decrypted data buffer: offset %zu length %zu",
- BACKEND->decdata_offset, BACKEND->decdata_length));
+ backend->decdata_offset, backend->decdata_length));
cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */
@@ -2043,13 +2050,13 @@ schannel_recv(struct Curl_easy *data, int sockindex,
assume it was graceful (close_notify) since there doesn't seem to be a
way to tell.
*/
- if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
- !BACKEND->recv_sspi_close_notify) {
+ if(len && !backend->decdata_offset && backend->recv_connection_closed &&
+ !backend->recv_sspi_close_notify) {
bool isWin2k = curlx_verify_windows_version(5, 0, 0, PLATFORM_WINNT,
VERSION_EQUAL);
if(isWin2k && sspi_status == SEC_E_OK)
- BACKEND->recv_sspi_close_notify = true;
+ backend->recv_sspi_close_notify = true;
else {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: server closed abruptly (missing close_notify)");
@@ -2058,23 +2065,23 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* Any error other than CURLE_AGAIN is an unrecoverable error. */
if(*err && *err != CURLE_AGAIN)
- BACKEND->recv_unrecoverable_err = *err;
+ backend->recv_unrecoverable_err = *err;
- size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset;
+ size = len < backend->decdata_offset ? len : backend->decdata_offset;
if(size) {
- memcpy(buf, BACKEND->decdata_buffer, size);
- memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
- BACKEND->decdata_offset - size);
- BACKEND->decdata_offset -= size;
+ memcpy(buf, backend->decdata_buffer, size);
+ memmove(backend->decdata_buffer, backend->decdata_buffer + size,
+ backend->decdata_offset - size);
+ backend->decdata_offset -= size;
DEBUGF(infof(data, "schannel: decrypted data returned %zu", size));
DEBUGF(infof(data,
"schannel: decrypted data buffer: offset %zu length %zu",
- BACKEND->decdata_offset, BACKEND->decdata_length));
+ backend->decdata_offset, backend->decdata_length));
*err = CURLE_OK;
return (ssize_t)size;
}
- if(!*err && !BACKEND->recv_connection_closed)
+ if(!*err && !backend->recv_connection_closed)
*err = CURLE_AGAIN;
/* It's debatable what to return when !len. We could return whatever error
@@ -2113,10 +2120,11 @@ static bool schannel_data_pending(const struct connectdata *conn,
int sockindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *backend = connssl->backend;
if(connssl->use) /* SSL/TLS is in use */
- return (BACKEND->decdata_offset > 0 ||
- (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
+ return (backend->decdata_offset > 0 ||
+ (backend->encdata_offset > 0 && !backend->encdata_is_incomplete));
else
return FALSE;
}
@@ -2146,6 +2154,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
*/
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char * const hostname = SSL_HOST_NAME();
+ struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(data);
@@ -2154,7 +2163,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
hostname, conn->remote_port);
}
- if(connssl->use && BACKEND->cred && BACKEND->ctxt) {
+ if(connssl->use && backend->cred && backend->ctxt) {
SecBufferDesc BuffDesc;
SecBuffer Buffer;
SECURITY_STATUS sspi_status;
@@ -2167,7 +2176,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
InitSecBufferDesc(&BuffDesc, &Buffer, 1);
- sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->ApplyControlToken(&backend->ctxt->ctxt_handle,
&BuffDesc);
if(sspi_status != SEC_E_OK) {
@@ -2185,18 +2194,18 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
sspi_status = s_pSecFn->InitializeSecurityContext(
- &BACKEND->cred->cred_handle,
- &BACKEND->ctxt->ctxt_handle,
+ &backend->cred->cred_handle,
+ &backend->ctxt->ctxt_handle,
host_name,
- BACKEND->req_flags,
+ backend->req_flags,
0,
0,
NULL,
0,
- &BACKEND->ctxt->ctxt_handle,
+ &backend->ctxt->ctxt_handle,
&outbuf_desc,
- &BACKEND->ret_flags,
- &BACKEND->ctxt->time_stamp);
+ &backend->ret_flags,
+ &backend->ctxt->time_stamp);
curlx_unicodefree(host_name);
@@ -2215,33 +2224,33 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
}
/* free SSPI Schannel API security context handle */
- if(BACKEND->ctxt) {
+ if(backend->ctxt) {
DEBUGF(infof(data, "schannel: clear security context handle"));
- s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
- Curl_safefree(BACKEND->ctxt);
+ s_pSecFn->DeleteSecurityContext(&backend->ctxt->ctxt_handle);
+ Curl_safefree(backend->ctxt);
}
/* free SSPI Schannel API credential handle */
- if(BACKEND->cred) {
+ if(backend->cred) {
Curl_ssl_sessionid_lock(data);
- schannel_session_free(BACKEND->cred);
+ schannel_session_free(backend->cred);
Curl_ssl_sessionid_unlock(data);
- BACKEND->cred = NULL;
+ backend->cred = NULL;
}
/* free internal buffer for received encrypted data */
- if(BACKEND->encdata_buffer != NULL) {
- Curl_safefree(BACKEND->encdata_buffer);
- BACKEND->encdata_length = 0;
- BACKEND->encdata_offset = 0;
- BACKEND->encdata_is_incomplete = false;
+ if(backend->encdata_buffer != NULL) {
+ Curl_safefree(backend->encdata_buffer);
+ backend->encdata_length = 0;
+ backend->encdata_offset = 0;
+ backend->encdata_is_incomplete = false;
}
/* free internal buffer for received decrypted data */
- if(BACKEND->decdata_buffer != NULL) {
- Curl_safefree(BACKEND->decdata_buffer);
- BACKEND->decdata_length = 0;
- BACKEND->decdata_offset = 0;
+ if(backend->decdata_buffer != NULL) {
+ Curl_safefree(backend->decdata_buffer);
+ backend->decdata_length = 0;
+ backend->decdata_offset = 0;
}
return CURLE_OK;
@@ -2299,6 +2308,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
const char *pinnedpubkey)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *backend = connssl->backend;
CERT_CONTEXT *pCertContextServer = NULL;
/* Result is returned to caller */
@@ -2316,7 +2326,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
struct Curl_asn1Element *pubkey;
sspi_status =
- s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ s_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer);
@@ -2422,8 +2432,9 @@ static CURLcode schannel_sha256sum(const unsigned char *input,
static void *schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
+ struct ssl_backend_data *backend = connssl->backend;
(void)info;
- return &BACKEND->ctxt->ctxt_handle;
+ return &backend->ctxt->ctxt_handle;
}
const struct Curl_ssl Curl_ssl_schannel = {