mirror of
https://github.com/nmap/nmap.git
synced 2026-01-20 13:19:01 +00:00
Do a 2nd SSL_read if necessary for renegotiation.
This fix was previously applied to ncat_listen's read_socket in r36652
(ac8b866) as a fix for #773. It didn't fully solve the problem, though,
since the fix should have been applied in ncat_core's fdinfo_recv, right
after the call to SSL_read. This commit moves the fix where it belongs,
which also simplifies the code.
Fixes #197 and #1049.
This commit is contained in:
@@ -338,8 +338,24 @@ int fdinfo_close(struct fdinfo *fdn)
|
||||
int fdinfo_recv(struct fdinfo *fdn, char *buf, size_t size)
|
||||
{
|
||||
#ifdef HAVE_OPENSSL
|
||||
int n;
|
||||
int err = SSL_ERROR_NONE;
|
||||
if (o.ssl && fdn->ssl)
|
||||
return SSL_read(fdn->ssl, buf, size);
|
||||
{
|
||||
do {
|
||||
n = SSL_read(fdn->ssl, buf, size);
|
||||
/* SSL_read returns <0 in some cases like renegotiation. In these
|
||||
* cases, SSL_get_error gives SSL_ERROR_WANT_{READ,WRITE}, and we
|
||||
* should try the SSL_read again. */
|
||||
if (n < 0) {
|
||||
err = SSL_get_error(fdn->ssl, n);
|
||||
if (err != SSL_ERROR_WANT_READ || err != SSL_ERROR_WANT_WRITE) {
|
||||
logdebug("SSL error on %d: %s\n", fdn->fd, ERR_error_string(err, NULL));
|
||||
}
|
||||
}
|
||||
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
return recv(fdn->fd, buf, size, 0);
|
||||
}
|
||||
|
||||
@@ -636,9 +636,6 @@ int read_socket(int recv_fd)
|
||||
char buf[DEFAULT_TCP_BUF_LEN];
|
||||
struct fdinfo *fdn;
|
||||
int nbytes, pending;
|
||||
#ifdef HAVE_OPENSSL
|
||||
int err = SSL_ERROR_NONE;
|
||||
#endif
|
||||
|
||||
fdn = get_fdinfo(&client_fdlist, recv_fd);
|
||||
ncat_assert(fdn != NULL);
|
||||
@@ -648,28 +645,11 @@ int read_socket(int recv_fd)
|
||||
int n;
|
||||
|
||||
n = ncat_recv(fdn, buf, sizeof(buf), &pending);
|
||||
#ifdef HAVE_OPENSSL
|
||||
/* SSL_read returns <0 in some cases like renegotiation. In these
|
||||
* cases, SSL_get_error gives SSL_ERROR_WANT_{READ,WRITE}, and we
|
||||
* should try the SSL_read again. */
|
||||
if (n < 0 && o.ssl && fdn->ssl) {
|
||||
err = SSL_get_error(fdn->ssl, n);
|
||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
||||
pending = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* If return value is 0, it's a clean shutdown from the other side, SSL
|
||||
* or plain. If <0, it's an error. If pending, the error may be
|
||||
* recoverable with a second SSL_read, so don't shut down yet. */
|
||||
if (n <= 0 && !pending) {
|
||||
if (n <= 0) {
|
||||
if (o.debug)
|
||||
logdebug("Closing fd %d.\n", recv_fd);
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (o.ssl && fdn->ssl) {
|
||||
if (n < 0 && o.debug) {
|
||||
logdebug("SSL error on %d: %s\n", recv_fd, ERR_error_string(err, NULL));;
|
||||
}
|
||||
if (nbytes == 0)
|
||||
SSL_shutdown(fdn->ssl);
|
||||
SSL_free(fdn->ssl);
|
||||
@@ -687,7 +667,7 @@ int read_socket(int recv_fd)
|
||||
|
||||
return n;
|
||||
}
|
||||
else if (n > 0) {
|
||||
else {
|
||||
Write(STDOUT_FILENO, buf, n);
|
||||
nbytes += n;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user