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:
Tobias Brunner
2021-02-12 11:45:44 +01:00
parent bfcb49b393
commit 27360d3407
+18 -6
View File
@@ -101,6 +101,11 @@ struct private_tls_socket_t {
* Underlying OS socket
*/
int fd;
/**
* Whether the socket returned EOF
*/
bool eof;
};
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)
{ /* EOF */
this->eof = TRUE;
return TRUE;
}
switch (this->tls->process(this->tls, buf, in))
@@ -268,11 +274,20 @@ METHOD(tls_socket_t, read_, ssize_t,
}
return cache;
}
if (this->eof)
{
return 0;
}
this->app.in.ptr = buf;
this->app.in.len = len;
this->app.in_done = 0;
if (exchange(this, FALSE, block))
{
if (!this->app.in_done && !this->eof)
{
errno = EWOULDBLOCK;
return -1;
}
return this->app.in_done;
}
return -1;
@@ -296,13 +311,13 @@ METHOD(tls_socket_t, splice, bool,
{
char buf[PLAIN_BUF_SIZE], *pos;
ssize_t in, out;
bool old, plain_eof = FALSE, crypto_eof = FALSE;
bool old, crypto_eof = FALSE;
struct pollfd pfd[] = {
{ .fd = this->fd, .events = POLLIN, },
{ .fd = rfd, .events = POLLIN, },
};
while (!plain_eof && !crypto_eof)
while (!this->eof && !crypto_eof)
{
old = thread_cancelability(TRUE);
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));
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);
switch (in)
{
case 0:
plain_eof = TRUE;
break;
case -1:
if (errno != EWOULDBLOCK)
{