schannel SSL: changes in schannel_connect_step2
Process extra data buffer before returning from schannel_connect_step2. Without this change I've seen WinCE hang when schannel_connect_step2 returns and calls Curl_socket_ready. If the encrypted handshake does not fit in the intial buffer (seen with large certificate chain), increasing the encrypted data buffer is necessary. Fixed warning in curl_schannel.c line 1215.
This commit is contained in:
parent
99b13f2741
commit
72a5813192
@ -290,6 +290,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
SECURITY_STATUS sspi_status = SEC_E_OK;
|
||||
TCHAR *host_name;
|
||||
CURLcode code;
|
||||
bool doread = TRUE;
|
||||
|
||||
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
|
||||
conn->host.name, conn->remote_port);
|
||||
@ -305,6 +306,22 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
}
|
||||
|
||||
/* if we need a bigger buffer to read a full message, increase buffer now */
|
||||
if(connssl->encdata_offset == connssl->encdata_length) {
|
||||
if(connssl->encdata_length >= CURL_SCHANNEL_BUFFER_INIT_SIZE * 16)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
/* increase internal encrypted data buffer */
|
||||
connssl->encdata_length *= 2;
|
||||
connssl->encdata_buffer = realloc(connssl->encdata_buffer,
|
||||
connssl->encdata_length);
|
||||
if(connssl->encdata_buffer == NULL) {
|
||||
failf(data, "schannel: unable to re-allocate memory");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if(doread) {
|
||||
/* read encrypted handshake data from socket */
|
||||
code = Curl_read_plain(conn->sock[sockindex],
|
||||
(char *) (connssl->encdata_buffer + connssl->encdata_offset),
|
||||
@ -325,6 +342,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* increase encrypted data buffer offset */
|
||||
connssl->encdata_offset += nread;
|
||||
}
|
||||
|
||||
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
|
||||
connssl->encdata_offset, connssl->encdata_length);
|
||||
@ -346,7 +364,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
|
||||
/* copy received handshake data into input buffer */
|
||||
memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer, connssl->encdata_offset);
|
||||
memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
|
||||
connssl->encdata_offset);
|
||||
|
||||
#ifdef UNICODE
|
||||
host_name = Curl_convert_UTF8_to_wchar(conn->host.name);
|
||||
@ -415,20 +434,34 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
/* check if there was additional remaining encrypted data */
|
||||
if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
|
||||
infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer);
|
||||
|
||||
/* check if the remaining data is less than the total amount
|
||||
* and therefore begins after the already processed data
|
||||
/*
|
||||
There are two cases where we could be getting extra data here:
|
||||
1) If we're renegotiating a connection and the handshake is already
|
||||
complete (from the server perspective), it can encrypted app data
|
||||
(not handshake data) in an extra buffer at this point.
|
||||
2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a
|
||||
connection and this extra data is part of the handshake.
|
||||
We should process the data immediately; waiting for the socket to
|
||||
be ready may fail since the server is done sending handshake data.
|
||||
*/
|
||||
/* check if the remaining data is less than the total amount
|
||||
and therefore begins after the already processed data */
|
||||
if(connssl->encdata_offset > inbuf[1].cbBuffer) {
|
||||
memmove(connssl->encdata_buffer,
|
||||
(connssl->encdata_buffer + connssl->encdata_offset) -
|
||||
inbuf[1].cbBuffer, inbuf[1].cbBuffer);
|
||||
connssl->encdata_offset = inbuf[1].cbBuffer;
|
||||
if(sspi_status == SEC_I_CONTINUE_NEEDED) {
|
||||
doread = FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
connssl->encdata_offset = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if the handshake needs to be continued */
|
||||
if(sspi_status == SEC_I_CONTINUE_NEEDED) {
|
||||
@ -1229,7 +1262,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
|
||||
failf(data, "schannel: CertGetNameString() certificate hostname "
|
||||
"(%s) did not match connection (%s)",
|
||||
_cert_hostname, conn->host.name);
|
||||
free(_cert_hostname);
|
||||
free((void *)_cert_hostname);
|
||||
}
|
||||
free(hostname);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user