Use SSL_read_ex() and SSL_write_ex() instead of SSL_read() and SSL_write().
This commit is contained in:
@@ -279,7 +279,7 @@ read_io_buf(struct client_closure *closure)
|
||||
{
|
||||
struct timing_closure *timing = &closure->timing;
|
||||
const char *errstr = NULL;
|
||||
ssize_t nread;
|
||||
size_t nread;
|
||||
debug_decl(read_io_buf, SUDO_DEBUG_UTIL);
|
||||
|
||||
if (!closure->iolog_files[timing->event].enabled) {
|
||||
@@ -310,7 +310,7 @@ read_io_buf(struct client_closure *closure)
|
||||
|
||||
nread = iolog_read(&closure->iolog_files[timing->event], closure->buf,
|
||||
timing->u.nbytes, &errstr);
|
||||
if (nread == -1) {
|
||||
if (nread == (size_t)-1) {
|
||||
sudo_warnx(U_("unable to read %s/%s: %s"), iolog_dir,
|
||||
iolog_fd_to_name(timing->event), errstr);
|
||||
debug_return_bool(false);
|
||||
@@ -1260,11 +1260,11 @@ server_msg_cb(int fd, int what, void *v)
|
||||
{
|
||||
struct client_closure *closure = v;
|
||||
struct connection_buffer *buf = &closure->read_buf;
|
||||
ssize_t nread;
|
||||
size_t nread;
|
||||
uint32_t msg_len;
|
||||
debug_decl(server_msg_cb, SUDO_DEBUG_UTIL);
|
||||
|
||||
/* For TLS we may need to read as part of SSL_write(). */
|
||||
/* For TLS we may need to read as part of SSL_write_ex(). */
|
||||
if (closure->write_instead_of_read) {
|
||||
closure->write_instead_of_read = false;
|
||||
client_msg_cb(fd, what, v);
|
||||
@@ -1279,13 +1279,14 @@ server_msg_cb(int fd, int what, void *v)
|
||||
#if defined(HAVE_OPENSSL)
|
||||
if (cert != NULL) {
|
||||
SSL *ssl = closure->tls_client.ssl;
|
||||
int err;
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: reading ServerMessage (TLS)", __func__);
|
||||
nread = SSL_read(ssl, buf->data + buf->len, buf->size - buf->len);
|
||||
if (nread <= 0) {
|
||||
err = SSL_read_ex(ssl, buf->data + buf->len, buf->size - buf->len,
|
||||
&nread);
|
||||
if (err) {
|
||||
const char *errstr;
|
||||
int err;
|
||||
|
||||
switch (SSL_get_error(ssl, nread)) {
|
||||
switch (SSL_get_error(ssl, err)) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
/* ssl connection shutdown cleanly */
|
||||
nread = 0;
|
||||
@@ -1293,12 +1294,12 @@ server_msg_cb(int fd, int what, void *v)
|
||||
case SSL_ERROR_WANT_READ:
|
||||
/* ssl wants to read more, read event is always active */
|
||||
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
|
||||
"SSL_read returns SSL_ERROR_WANT_READ");
|
||||
"SSL_read_ex returns SSL_ERROR_WANT_READ");
|
||||
debug_return;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
/* ssl wants to write, schedule a write if not pending */
|
||||
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
|
||||
"SSL_read returns SSL_ERROR_WANT_WRITE");
|
||||
"SSL_read_ex returns SSL_ERROR_WANT_WRITE");
|
||||
if (!sudo_ev_pending(closure->write_ev, SUDO_EV_WRITE, NULL)) {
|
||||
/* Enable a temporary write event. */
|
||||
if (sudo_ev_add(closure->evbase, closure->write_ev, NULL, false) == -1) {
|
||||
@@ -1307,7 +1308,7 @@ server_msg_cb(int fd, int what, void *v)
|
||||
}
|
||||
closure->temporary_write_event = true;
|
||||
}
|
||||
/* Redirect write event to finish SSL_read() */
|
||||
/* Redirect write event to finish SSL_read_ex() */
|
||||
closure->read_instead_of_write = true;
|
||||
debug_return;
|
||||
case SSL_ERROR_SSL:
|
||||
@@ -1330,11 +1331,12 @@ server_msg_cb(int fd, int what, void *v)
|
||||
sudo_warnx("%s", errstr ? errstr : strerror(errno));
|
||||
goto bad;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
sudo_warn("recv");
|
||||
sudo_warn("SSL_read_ex");
|
||||
goto bad;
|
||||
default:
|
||||
errstr = ERR_reason_error_string(ERR_get_error());
|
||||
sudo_warnx("recv: %s", errstr ? errstr : strerror(errno));
|
||||
sudo_warnx("SSL_read_ex: %s",
|
||||
errstr ? errstr : strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -1342,15 +1344,15 @@ server_msg_cb(int fd, int what, void *v)
|
||||
#endif
|
||||
{
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: reading ServerMessage", __func__);
|
||||
nread = recv(fd, buf->data + buf->len, buf->size - buf->len, 0);
|
||||
nread = (size_t)read(fd, buf->data + buf->len, buf->size - buf->len);
|
||||
}
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received %zd bytes from server",
|
||||
__func__, nread);
|
||||
switch (nread) {
|
||||
case -1:
|
||||
case (size_t)-1:
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
debug_return;
|
||||
sudo_warn("recv");
|
||||
sudo_warn("read");
|
||||
goto bad;
|
||||
case 0:
|
||||
if (closure->state != FINISHED)
|
||||
@@ -1359,7 +1361,7 @@ server_msg_cb(int fd, int what, void *v)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
buf->len += (size_t)nread;
|
||||
buf->len += nread;
|
||||
|
||||
while (buf->len - buf->off >= sizeof(msg_len)) {
|
||||
/* Read wire message size (uint32_t in network byte order). */
|
||||
@@ -1402,7 +1404,7 @@ client_msg_cb(int fd, int what, void *v)
|
||||
{
|
||||
struct client_closure *closure = v;
|
||||
struct connection_buffer *buf;
|
||||
ssize_t nwritten;
|
||||
size_t nwritten;
|
||||
debug_decl(client_msg_cb, SUDO_DEBUG_UTIL);
|
||||
|
||||
if ((buf = TAILQ_FIRST(&closure->write_bufs)) == NULL) {
|
||||
@@ -1410,10 +1412,10 @@ client_msg_cb(int fd, int what, void *v)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* For TLS we may need to write as part of SSL_read(). */
|
||||
/* For TLS we may need to write as part of SSL_read_ex(). */
|
||||
if (closure->read_instead_of_write) {
|
||||
closure->read_instead_of_write = false;
|
||||
/* Delete write event if it was only due to SSL_read(). */
|
||||
/* Delete write event if it was only due to SSL_read_ex(). */
|
||||
if (closure->temporary_write_event) {
|
||||
closure->temporary_write_event = false;
|
||||
sudo_ev_del(closure->evbase, closure->write_ev);
|
||||
@@ -1433,47 +1435,49 @@ client_msg_cb(int fd, int what, void *v)
|
||||
#if defined(HAVE_OPENSSL)
|
||||
if (cert != NULL) {
|
||||
SSL *ssl = closure->tls_client.ssl;
|
||||
nwritten = SSL_write(ssl, buf->data + buf->off, buf->len - buf->off);
|
||||
if (nwritten <= 0) {
|
||||
int err = SSL_write_ex(ssl, buf->data + buf->off, buf->len - buf->off,
|
||||
&nwritten);
|
||||
if (err) {
|
||||
const char *errstr;
|
||||
|
||||
switch (SSL_get_error(ssl, nwritten)) {
|
||||
switch (SSL_get_error(ssl, err)) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
/* ssl connection shutdown */
|
||||
goto bad;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
/* ssl wants to read, read event always active */
|
||||
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
|
||||
"SSL_write returns SSL_ERROR_WANT_READ");
|
||||
/* Redirect read event to finish SSL_write() */
|
||||
"SSL_write_ex returns SSL_ERROR_WANT_READ");
|
||||
/* Redirect read event to finish SSL_write_ex() */
|
||||
closure->write_instead_of_read = true;
|
||||
debug_return;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
/* ssl wants to write more, write event remains active */
|
||||
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
|
||||
"SSL_write returns SSL_ERROR_WANT_WRITE");
|
||||
"SSL_write_ex returns SSL_ERROR_WANT_WRITE");
|
||||
debug_return;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
sudo_warn("recv");
|
||||
sudo_warn("SSL_write_ex");
|
||||
goto bad;
|
||||
default:
|
||||
errstr = ERR_reason_error_string(ERR_get_error());
|
||||
sudo_warnx("send: %s", errstr ? errstr : strerror(errno));
|
||||
sudo_warnx("SSL_write_ex: %s",
|
||||
errstr ? errstr : strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
nwritten = send(fd, buf->data + buf->off, buf->len - buf->off, 0);
|
||||
nwritten = (size_t)write(fd, buf->data + buf->off, buf->len - buf->off);
|
||||
}
|
||||
if (nwritten == -1) {
|
||||
if (nwritten == (size_t)-1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
debug_return;
|
||||
sudo_warn("send");
|
||||
sudo_warn("write");
|
||||
goto bad;
|
||||
}
|
||||
buf->off += (size_t)nwritten;
|
||||
buf->off += nwritten;
|
||||
|
||||
if (buf->off == buf->len) {
|
||||
/* sent entire message */
|
||||
|
Reference in New Issue
Block a user