diff --git a/libcfnet/client_code.c b/libcfnet/client_code.c index b8423d69c2..bd7bb841f6 100644 --- a/libcfnet/client_code.c +++ b/libcfnet/client_code.c @@ -753,6 +753,7 @@ bool CopyRegularFileNet(const char *source, const char *dest, off_t size, bool encrypt, AgentConnection *conn, mode_t mode) { assert(conn != NULL); + assert(conn->conn_info != NULL); char buf[CF_BUFSIZE + sizeof(int)]; /* Note CF_BUFSIZE not buf_size !! */ char workbuf[CF_BUFSIZE], cfchangedstr[265]; @@ -812,7 +813,7 @@ bool CopyRegularFileNet(const char *source, const char *dest, off_t size, assert(toget > 0); /* Stage C1 - receive */ - int n_read; + int n_read = 0; const ProtocolVersion version = conn->conn_info->protocol; @@ -822,7 +823,19 @@ bool CopyRegularFileNet(const char *source, const char *dest, off_t size, } else if (ProtocolIsTLS(version)) { - n_read = TLSRecv(conn->conn_info->ssl, buf, toget); + /* TLSRecv may return less than the requested number of Bytes, in + * which case we repeatedly call it until we get the expected + * number. */ + while (n_read < toget) + { + rc = TLSRecv(conn->conn_info->ssl, buf + n_read, toget - n_read); + if (rc <= 0) + { + n_read = rc; + break; + } + n_read += rc; + } } else { @@ -831,8 +844,6 @@ bool CopyRegularFileNet(const char *source, const char *dest, off_t size, n_read = -1; } - /* TODO what if 0 < n_read < toget? Might happen with TLS. */ - if (n_read <= 0) { /* This may happen on race conditions, where the file has shrunk diff --git a/libcfnet/net.c b/libcfnet/net.c index 9de7663f64..37b94c4ab4 100644 --- a/libcfnet/net.c +++ b/libcfnet/net.c @@ -148,6 +148,8 @@ int SendTransaction(ConnectionInfo *conn_info, */ int ReceiveTransaction(ConnectionInfo *conn_info, char *buffer, int *more) { + assert(conn_info != NULL); + char proto[CF_INBAND_OFFSET + 1] = { 0 }; int ret; @@ -158,7 +160,19 @@ int ReceiveTransaction(ConnectionInfo *conn_info, char *buffer, int *more) ret = RecvSocketStream(conn_info->sd, proto, CF_INBAND_OFFSET); break; case CF_PROTOCOL_TLS: - ret = TLSRecv(conn_info->ssl, proto, CF_INBAND_OFFSET); + /* TLSRecv may return less than the requested number of Bytes, in + * which case we repeatedly call it until we get the expected number. + */ + while (ret < CF_INBAND_OFFSET) + { + int rc = TLSRecv(conn_info->ssl, proto + ret, CF_INBAND_OFFSET - ret); + if (rc <= 0) + { + ret = rc; + break; + } + ret += rc; + } break; default: UnexpectedError("ReceiveTransaction: ProtocolVersion %d!", @@ -251,7 +265,18 @@ int ReceiveTransaction(ConnectionInfo *conn_info, char *buffer, int *more) ret = RecvSocketStream(conn_info->sd, buffer, len); break; case CF_PROTOCOL_TLS: - ret = TLSRecv(conn_info->ssl, buffer, len); + while (ret < len) + { + /* TLSRecv may return less than the requested number of Bytes, in + * which case we repeatedly call it until we get the expected + * number. */ + int rc = TLSRecv(conn_info->ssl, buffer + ret, len - ret); + if (rc <= 0) + { + ret = rc; + } + ret += rc; + } break; default: UnexpectedError("ReceiveTransaction: ProtocolVersion %d!",