schannel: Implemented SSL/TLS renegotiation
Updated TODO information and added related MSDN articles
This commit is contained in:
parent
46792af733
commit
ec9e9f38b1
@ -40,7 +40,15 @@
|
||||
* TODO list for TLS/SSL implementation:
|
||||
* - implement write buffering
|
||||
* - implement SSL/TLS shutdown
|
||||
* - special cases: renegotiation, certificates, algorithms
|
||||
* - implement client certificate authentication
|
||||
* - implement custom server certificate validation
|
||||
* - implement cipher/algorithm option
|
||||
*
|
||||
* Related articles on MSDN:
|
||||
* - Getting a Certificate for Schannel
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375447.aspx
|
||||
* - Specifying Schannel Ciphers and Cipher Strengths
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa380161.aspx
|
||||
*/
|
||||
|
||||
#include "setup.h"
|
||||
@ -86,7 +94,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
|
||||
struct in6_addr addr6;
|
||||
#endif
|
||||
|
||||
infof(data, "schannel: Connecting to %s:%d (step 1/3)\n",
|
||||
infof(data, "schannel: connecting to %s:%d (step 1/3)\n",
|
||||
conn->host.name, conn->remote_port);
|
||||
|
||||
/* check for an existing re-usable credential handle */
|
||||
@ -229,11 +237,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
|
||||
SecBufferDesc inbuf_desc;
|
||||
SECURITY_STATUS sspi_status = SEC_E_OK;
|
||||
|
||||
infof(data, "schannel: Connecting to %s:%d (step 2/3)\n",
|
||||
infof(data, "schannel: connecting to %s:%d (step 2/3)\n",
|
||||
conn->host.name, conn->remote_port);
|
||||
|
||||
connssl->connecting_state = ssl_connect_2;
|
||||
|
||||
/* buffer to store previously received and encrypted data */
|
||||
if(connssl->encdata_buffer == NULL) {
|
||||
connssl->encdata_offset = 0;
|
||||
@ -249,13 +255,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
|
||||
read = sread(conn->sock[sockindex],
|
||||
connssl->encdata_buffer + connssl->encdata_offset,
|
||||
connssl->encdata_length - connssl->encdata_offset);
|
||||
if(read < 0) {
|
||||
if(read < 0 && connssl->connecting_state != ssl_connect_2_writing) {
|
||||
connssl->connecting_state = ssl_connect_2_reading;
|
||||
infof(data, "schannel: failed to receive handshake, waiting for more: %d\n",
|
||||
read);
|
||||
return CURLE_OK;
|
||||
}
|
||||
else if(read == 0) {
|
||||
else if(read == 0 && connssl->connecting_state != ssl_connect_2_writing) {
|
||||
failf(data, "schannel: failed to receive handshake, connection failed\n");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
@ -394,6 +400,9 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) {
|
||||
|
||||
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
|
||||
|
||||
infof(data, "schannel: connecting to %s:%d (step 3/3)\n",
|
||||
conn->host.name, conn->remote_port);
|
||||
|
||||
/* check if the required context attributes are met */
|
||||
if(connssl->ret_flags != connssl->req_flags) {
|
||||
if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT))
|
||||
@ -697,15 +706,19 @@ schannel_recv(struct connectdata *conn, int sockindex,
|
||||
/* increase encrypted data buffer offset */
|
||||
connssl->encdata_offset += read;
|
||||
}
|
||||
else if(connssl->encdata_offset == 0) {
|
||||
if(read == 0)
|
||||
ret = 0;
|
||||
else
|
||||
*err = CURLE_AGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
infof(data, "schannel: encrypted data buffer %d/%d\n",
|
||||
connssl->encdata_offset, connssl->encdata_length);
|
||||
|
||||
/* check if we still have some data in our buffers */
|
||||
while(connssl->encdata_offset > 0 &&
|
||||
sspi_status != SEC_E_INCOMPLETE_MESSAGE) {
|
||||
|
||||
while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK) {
|
||||
/* prepare data buffer for DecryptMessage call */
|
||||
inbuf[0].pvBuffer = connssl->encdata_buffer;
|
||||
inbuf[0].cbBuffer = connssl->encdata_offset;
|
||||
@ -783,9 +796,12 @@ schannel_recv(struct connectdata *conn, int sockindex,
|
||||
|
||||
/* begin renegotiation */
|
||||
connssl->state = ssl_connection_negotiating;
|
||||
connssl->connecting_state = ssl_connect_2_writing;
|
||||
retcode = schannel_connect_common(conn, sockindex, FALSE, &done);
|
||||
if(retcode)
|
||||
*err = retcode;
|
||||
else /* now retry receiving data */
|
||||
return schannel_recv(conn, sockindex, buf, len, err);
|
||||
}
|
||||
}
|
||||
|
||||
@ -815,6 +831,13 @@ schannel_recv(struct connectdata *conn, int sockindex,
|
||||
connssl->decdata_length);
|
||||
}
|
||||
|
||||
/* check if the server closed the connection */
|
||||
if(ret <= 0 && sspi_status == SEC_I_CONTEXT_EXPIRED) {
|
||||
infof(data, "schannel: server closed the connection\n");
|
||||
*err = CURLE_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if something went wrong and we need to return an error */
|
||||
if(ret < 0) {
|
||||
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE)
|
||||
|
Loading…
x
Reference in New Issue
Block a user