Honor SSL_read semantics

This commit is contained in:
Tatsuhiro Tsujikawa 2017-04-01 22:15:26 +09:00
parent 90a9a804d0
commit aca99d42f1
1 changed files with 21 additions and 17 deletions

View File

@ -731,6 +731,26 @@ ssize_t Connection::read_tls(void *data, size_t len) {
if (tls.earlybuf.rleft()) { if (tls.earlybuf.rleft()) {
return tls.earlybuf.remove(data, len); return tls.earlybuf.remove(data, len);
} }
#endif // OPENSSL_1_1_1_API
// SSL_read requires the same arguments (buf pointer and its
// length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
// rlimit_.avail() or rlimit_.avail() may return different length
// than the length previously passed to SSL_read, which violates
// OpenSSL assumption. To avoid this, we keep last legnth passed
// to SSL_read to tls_last_readlen_ if SSL_read indicated I/O
// blocking.
if (tls.last_readlen == 0) {
len = std::min(len, rlimit.avail());
if (len == 0) {
return 0;
}
} else {
len = tls.last_readlen;
tls.last_readlen = 0;
}
#if OPENSSL_1_1_1_API
if (!tls.early_data_finish) { if (!tls.early_data_finish) {
// TLSv1.3 handshake is still going on. // TLSv1.3 handshake is still going on.
size_t nread; size_t nread;
@ -740,6 +760,7 @@ ssize_t Connection::read_tls(void *data, size_t len) {
switch (err) { switch (err) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: // TODO Probably not required. case SSL_ERROR_WANT_WRITE: // TODO Probably not required.
tls.last_readlen = len;
return 0; return 0;
case SSL_ERROR_SSL: case SSL_ERROR_SSL:
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
@ -771,23 +792,6 @@ ssize_t Connection::read_tls(void *data, size_t len) {
} }
#endif // OPENSSL_1_1_1_API #endif // OPENSSL_1_1_1_API
// SSL_read requires the same arguments (buf pointer and its
// length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
// rlimit_.avail() or rlimit_.avail() may return different length
// than the length previously passed to SSL_read, which violates
// OpenSSL assumption. To avoid this, we keep last legnth passed
// to SSL_read to tls_last_readlen_ if SSL_read indicated I/O
// blocking.
if (tls.last_readlen == 0) {
len = std::min(len, rlimit.avail());
if (len == 0) {
return 0;
}
} else {
len = tls.last_readlen;
tls.last_readlen = 0;
}
auto rv = SSL_read(tls.ssl, data, len); auto rv = SSL_read(tls.ssl, data, len);
if (rv <= 0) { if (rv <= 0) {