1
0
mirror of https://github.com/moparisthebest/curl synced 2025-01-08 12:28:06 -05:00

schannel SSL: Implemented SSL shutdown

curl_schannel.c - implemented graceful SSL shutdown.  If we fail to
shutdown the connection gracefully, I've seen schannel try to use a
session ID for future connects and the server aborts the connection
during the handshake.
This commit is contained in:
Mark Salisbury 2012-06-19 04:15:03 +02:00 committed by Yang Tse
parent 1e4c57fa64
commit 8a8829499d

View File

@ -41,7 +41,6 @@
/*
* TODO list for TLS/SSL implementation:
* - implement write buffering
* - implement SSL/TLS shutdown
* - implement client certificate authentication
* - implement custom server certificate validation
* - implement cipher/algorithm option
@ -946,17 +945,90 @@ bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
void Curl_schannel_close(struct connectdata *conn, int sockindex)
{
if(conn->ssl[sockindex].use)
/* if the SSL channel hasn't been shut down yet, do that now. */
Curl_ssl_shutdown(conn, sockindex);
}
int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
{
/* See
http://msdn.microsoft.com/en-us/library/windows/desktop/aa380138(v=vs.85).aspx
Shutting Down an Schannel Connection */
struct SessionHandle *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
infof(data, "schannel: Closing connection with %s:%hu\n",
infof(data, "schannel: shutting down SSL connection with %s:%hu\n",
conn->host.name, conn->remote_port);
/* free SSPI Schannel API security context handle */
if(connssl->ctxt) {
s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
free(connssl->ctxt);
connssl->ctxt = NULL;
SecBufferDesc BuffDesc;
SecBuffer Buffer;
SECURITY_STATUS sspi_status;
SecBuffer outbuf;
SecBufferDesc outbuf_desc;
CURLcode code;
TCHAR *host_name;
DWORD dwshut = SCHANNEL_SHUTDOWN;
InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
InitSecBufferDesc(&BuffDesc, &Buffer, 1);
sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
&BuffDesc);
if(sspi_status != SEC_E_OK)
failf(data, "schannel: ApplyControlToken failure: %s",
Curl_sspi_strerror(conn, sspi_status));
#ifdef UNICODE
host_name = Curl_convert_UTF8_to_wchar(conn->host.name);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
#else
host_name = conn->host.name;
#endif
/* setup output buffer */
InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
sspi_status = s_pSecFn->InitializeSecurityContext(
&connssl->cred->cred_handle,
&connssl->ctxt->ctxt_handle,
host_name,
connssl->req_flags,
0,
0,
NULL,
0,
&connssl->ctxt->ctxt_handle,
&outbuf_desc,
&connssl->ret_flags,
&connssl->ctxt->time_stamp);
#ifdef UNICODE
free(host_name);
#endif
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
ssize_t written;
code = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((code != CURLE_OK) || (outbuf.cbBuffer != (size_t)written)) {
infof(data, "schannel: failed to send close msg: %s"
" (bytes written: %zd)\n", curl_easy_strerror(code), written);
}
}
/* free SSPI Schannel API security context handle */
if(connssl->ctxt) {
s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
free(connssl->ctxt);
connssl->ctxt = NULL;
}
}
/* free internal buffer for received encrypted data */
@ -974,13 +1046,8 @@ void Curl_schannel_close(struct connectdata *conn, int sockindex)
connssl->decdata_length = 0;
connssl->decdata_offset = 0;
}
}
int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
{
(void)conn;
(void)sockindex;
return CURLE_NOT_BUILT_IN; /* TODO: implement SSL/TLS shutdown */
return CURLE_OK;
}
void Curl_schannel_session_free(void *ptr)