tls-socket: Change how EOF of the underlying socket is handled
With the previous code, there was an issue when replying to TLS 1.3 post-handshake messages. In this case, SUCCESS is eventually returned from build(), however, no actual data has been received so in_done is 0. This was interpreted as EOF, plain_eof was set to TRUE and no further data was read from the socket afterwards. Returning SUCCESS from build() if the exchange is initiated by write_(), as is the case with the finished reply, never was a problem because there the return value of 0 is not interpreted as EOF.
This commit is contained in:
+18
-6
@@ -101,6 +101,11 @@ struct private_tls_socket_t {
|
|||||||
* Underlying OS socket
|
* Underlying OS socket
|
||||||
*/
|
*/
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the socket returned EOF
|
||||||
|
*/
|
||||||
|
bool eof;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(tls_application_t, process, status_t,
|
METHOD(tls_application_t, process, status_t,
|
||||||
@@ -236,6 +241,7 @@ static bool exchange(private_tls_socket_t *this, bool wr, bool block)
|
|||||||
}
|
}
|
||||||
if (in == 0)
|
if (in == 0)
|
||||||
{ /* EOF */
|
{ /* EOF */
|
||||||
|
this->eof = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
switch (this->tls->process(this->tls, buf, in))
|
switch (this->tls->process(this->tls, buf, in))
|
||||||
@@ -268,11 +274,20 @@ METHOD(tls_socket_t, read_, ssize_t,
|
|||||||
}
|
}
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
if (this->eof)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
this->app.in.ptr = buf;
|
this->app.in.ptr = buf;
|
||||||
this->app.in.len = len;
|
this->app.in.len = len;
|
||||||
this->app.in_done = 0;
|
this->app.in_done = 0;
|
||||||
if (exchange(this, FALSE, block))
|
if (exchange(this, FALSE, block))
|
||||||
{
|
{
|
||||||
|
if (!this->app.in_done && !this->eof)
|
||||||
|
{
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return this->app.in_done;
|
return this->app.in_done;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -296,13 +311,13 @@ METHOD(tls_socket_t, splice, bool,
|
|||||||
{
|
{
|
||||||
char buf[PLAIN_BUF_SIZE], *pos;
|
char buf[PLAIN_BUF_SIZE], *pos;
|
||||||
ssize_t in, out;
|
ssize_t in, out;
|
||||||
bool old, plain_eof = FALSE, crypto_eof = FALSE;
|
bool old, crypto_eof = FALSE;
|
||||||
struct pollfd pfd[] = {
|
struct pollfd pfd[] = {
|
||||||
{ .fd = this->fd, .events = POLLIN, },
|
{ .fd = this->fd, .events = POLLIN, },
|
||||||
{ .fd = rfd, .events = POLLIN, },
|
{ .fd = rfd, .events = POLLIN, },
|
||||||
};
|
};
|
||||||
|
|
||||||
while (!plain_eof && !crypto_eof)
|
while (!this->eof && !crypto_eof)
|
||||||
{
|
{
|
||||||
old = thread_cancelability(TRUE);
|
old = thread_cancelability(TRUE);
|
||||||
in = poll(pfd, countof(pfd), -1);
|
in = poll(pfd, countof(pfd), -1);
|
||||||
@@ -312,14 +327,11 @@ METHOD(tls_socket_t, splice, bool,
|
|||||||
DBG1(DBG_TLS, "TLS select error: %s", strerror(errno));
|
DBG1(DBG_TLS, "TLS select error: %s", strerror(errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
while (!plain_eof && pfd[0].revents & (POLLIN | POLLHUP | POLLNVAL))
|
while (!this->eof && pfd[0].revents & (POLLIN | POLLHUP | POLLNVAL))
|
||||||
{
|
{
|
||||||
in = read_(this, buf, sizeof(buf), FALSE);
|
in = read_(this, buf, sizeof(buf), FALSE);
|
||||||
switch (in)
|
switch (in)
|
||||||
{
|
{
|
||||||
case 0:
|
|
||||||
plain_eof = TRUE;
|
|
||||||
break;
|
|
||||||
case -1:
|
case -1:
|
||||||
if (errno != EWOULDBLOCK)
|
if (errno != EWOULDBLOCK)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user