mirror of
https://github.com/nmap/nmap.git
synced 2026-01-21 05:39:14 +00:00
Handle SSL_read()/SSL_write() returning 0 when not EOF.
OpenSSL docs say, "Old documentation indicated a difference between 0 and -1, and that -1 was retryable. You should instead call SSL_get_error() to find out if it's retryable."
This commit is contained in:
@@ -537,43 +537,50 @@ void handle_write_result(struct npool *ms, struct nevent *nse, enum nse_status s
|
||||
if (nse->writeinfo.written_so_far > 0)
|
||||
assert(bytesleft > 0);
|
||||
#if HAVE_OPENSSL
|
||||
if (iod->ssl)
|
||||
if (iod->ssl) {
|
||||
res = SSL_write(iod->ssl, str, bytesleft);
|
||||
if (res == bytesleft) {
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_SUCCESS;
|
||||
} else if (res > 0) {
|
||||
// This should never happen unless we set SSL_MODE_ENABLE_PARTIAL_WRITE
|
||||
nse->writeinfo.written_so_far += res;
|
||||
} else { // res <= 0
|
||||
int evclr, evset;
|
||||
err = SSL_get_error(iod->ssl, res);
|
||||
switch(err) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
evclr = socket_count_dec_ssl_desire(nse);
|
||||
evset = (err == SSL_ERROR_WANT_READ) ?
|
||||
socket_count_read_inc(iod) :
|
||||
socket_count_write_inc(iod);
|
||||
update_events(iod, ms, nse, evset, evclr);
|
||||
nse->sslinfo.ssl_desire = err;
|
||||
break;
|
||||
default:
|
||||
assert(err != SSL_ERROR_NONE);
|
||||
/* Unexpected error */
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_ERROR;
|
||||
nse->errnum = EIO;
|
||||
nsock_log_info("SSL_write() failed for reason %s on NSI %li",
|
||||
ERR_error_string(err, NULL), iod->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
res = ms->engine->io_operations->iod_write(ms, nse->iod->sd, str, bytesleft, 0, (struct sockaddr *)&nse->writeinfo.dest, (int)nse->writeinfo.destlen);
|
||||
if (res == bytesleft) {
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_SUCCESS;
|
||||
} else if (res >= 0) {
|
||||
nse->writeinfo.written_so_far += res;
|
||||
} else {
|
||||
assert(res == -1);
|
||||
if (iod->ssl) {
|
||||
#if HAVE_OPENSSL
|
||||
err = SSL_get_error(iod->ssl, res);
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
int evclr;
|
||||
|
||||
evclr = socket_count_dec_ssl_desire(nse);
|
||||
socket_count_read_inc(iod);
|
||||
update_events(iod, ms, nse, EV_READ, evclr);
|
||||
nse->sslinfo.ssl_desire = err;
|
||||
} else if (err == SSL_ERROR_WANT_WRITE) {
|
||||
int evclr;
|
||||
|
||||
evclr = socket_count_dec_ssl_desire(nse);
|
||||
socket_count_write_inc(iod);
|
||||
update_events(iod, ms, nse, EV_WRITE, evclr);
|
||||
nse->sslinfo.ssl_desire = err;
|
||||
} else {
|
||||
/* Unexpected error */
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_ERROR;
|
||||
nse->errnum = EIO;
|
||||
}
|
||||
#endif
|
||||
if (res == bytesleft) {
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_SUCCESS;
|
||||
} else if (res >= 0) {
|
||||
nse->writeinfo.written_so_far += res;
|
||||
} else {
|
||||
assert(res == -1);
|
||||
err = socket_errno();
|
||||
if (errcode_is_failure(err)) {
|
||||
nse->event_done = 1;
|
||||
@@ -714,30 +721,34 @@ static int do_actual_read(struct npool *ms, struct nevent *nse) {
|
||||
return fs_length(&nse->iobuf) - startlen;
|
||||
}
|
||||
|
||||
if (buflen == -1) {
|
||||
if (buflen <= 0) {
|
||||
int evclr, evset;
|
||||
err = SSL_get_error(iod->ssl, buflen);
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
int evclr;
|
||||
|
||||
evclr = socket_count_dec_ssl_desire(nse);
|
||||
socket_count_read_inc(iod);
|
||||
update_events(iod, ms, nse, EV_READ, evclr);
|
||||
nse->sslinfo.ssl_desire = err;
|
||||
} else if (err == SSL_ERROR_WANT_WRITE) {
|
||||
int evclr;
|
||||
|
||||
evclr = socket_count_dec_ssl_desire(nse);
|
||||
socket_count_write_inc(iod);
|
||||
update_events(iod, ms, nse, EV_WRITE, evclr);
|
||||
nse->sslinfo.ssl_desire = err;
|
||||
} else {
|
||||
/* Unexpected error */
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_ERROR;
|
||||
nse->errnum = EIO;
|
||||
nsock_log_info("SSL_read() failed for reason %s on NSI %li",
|
||||
ERR_error_string(err, NULL), iod->id);
|
||||
return -1;
|
||||
switch (err) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
evclr = socket_count_dec_ssl_desire(nse);
|
||||
evset = (err == SSL_ERROR_WANT_READ) ?
|
||||
socket_count_read_inc(iod) :
|
||||
socket_count_write_inc(iod);
|
||||
update_events(iod, ms, nse, evset, evclr);
|
||||
nse->sslinfo.ssl_desire = err;
|
||||
/* Not EOF! */
|
||||
buflen = 1;
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
/* EOF because of close_notify */
|
||||
buflen = 0;
|
||||
break;
|
||||
default:
|
||||
assert(err != SSL_ERROR_NONE);
|
||||
/* Unexpected error */
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_ERROR;
|
||||
nse->errnum = EIO;
|
||||
nsock_log_info("SSL_read() failed for reason %s on NSI %li",
|
||||
ERR_error_string(err, NULL), iod->id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
Reference in New Issue
Block a user