diff options
author | Dr. David von Oheimb <David.von.Oheimb@siemens.com> | 2020-02-21 21:41:56 +0100 |
---|---|---|
committer | Dr. David von Oheimb <David.von.Oheimb@siemens.com> | 2020-02-21 21:41:56 +0100 |
commit | e8d0819d52b2741fcb4ddb79ced4d824c3056918 (patch) | |
tree | 751519d69bc54c407c7431f1a0efd1d1017a177a /crypto/bio | |
parent | 745fc918e7eeb86b2ac541325a8ae5c6e374ee56 (diff) |
Don't exclude quite so much in a no-sock build
We were excluding more code than we needed to in the OCSP/HTTP code in
the event of no-sock. We should also not assume that a BIO passed to our
API is socket based.
This fixes the no-sock build
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/11134)
Diffstat (limited to 'crypto/bio')
-rw-r--r-- | crypto/bio/b_sock.c | 87 | ||||
-rw-r--r-- | crypto/bio/bio_lib.c | 97 |
2 files changed, 98 insertions, 86 deletions
diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c index 966bd64356..3c8a10b8fd 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/b_sock.c @@ -397,93 +397,8 @@ int BIO_socket_wait(int fd, int for_read, time_t max_time) FD_ZERO(&confds); openssl_fdset(fd, &confds); tv.tv_usec = 0; - tv.tv_sec = (long)(max_time - now); /* this might overflow */ + tv.tv_sec = (long)(max_time - now); /* might overflow */ return select(fd + 1, for_read ? &confds : NULL, for_read ? NULL : &confds, NULL, &tv); } - -/* - * Wait on BIO at most until max_time; succeed immediately if max_time == 0. - * Returns -1 on error, 0 on timeout, and 1 on success. - */ -static int bio_wait(BIO *bio, time_t max_time) -{ - int fd; - - if (BIO_get_fd(bio, &fd) <= 0) - return -1; - return BIO_socket_wait(fd, BIO_should_read(bio), max_time); -} - -/* - * Wait on BIO at most until max_time; succeed immediately if max_time == 0. - * Call BIOerr(...) unless success. - * Returns -1 on error, 0 on timeout, and 1 on success. - */ -int BIO_wait(BIO *bio, time_t max_time) -{ - int rv = bio_wait(bio, max_time); - - if (rv <= 0) - BIOerr(0, rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR); - return rv; -} - -/* - * Connect via the given BIO using BIO_do_connect() until success/timeout/error. - * Parameter timeout == 0 means infinite, < 0 leads to immediate timeout error. - * Returns -1 on error, 0 on timeout, and 1 on success. - */ -int BIO_connect_retry(BIO *bio, int timeout) -{ - int blocking = timeout == 0; - time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; - int rv; - - if (bio == NULL) { - BIOerr(0, ERR_R_PASSED_NULL_PARAMETER); - return -1; - } - - if (timeout < 0) { - BIOerr(0, BIO_R_CONNECT_TIMEOUT); - return 0; - } - - if (!blocking) - BIO_set_nbio(bio, 1); - - retry: /* it does not help here to set SSL_MODE_AUTO_RETRY */ - rv = BIO_do_connect(bio); /* This indirectly calls ERR_clear_error(); */ - - if (rv <= 0) { - if (get_last_sys_error() == ETIMEDOUT) { - /* - * if blocking, despite blocking BIO, BIO_do_connect() timed out - * when non-blocking, BIO_do_connect() timed out early - * with rv == -1 and get_last_sys_error() == 0 - */ - ERR_clear_error(); - (void)BIO_reset(bio); - /* - * unless using BIO_reset(), blocking next connect() may crash and - * non-blocking next BIO_do_connect() will fail - */ - goto retry; - } else if (BIO_should_retry(bio)) { - /* will not actually wait if timeout == 0 (i.e., blocking BIO) */ - rv = bio_wait(bio, max_time); - if (rv > 0) - goto retry; - BIOerr(0, rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR); - } else { - rv = -1; - if (ERR_peek_error() == 0) /* missing error queue entry */ - BIOerr(0, BIO_R_CONNECT_ERROR); /* workaround: general error */ - } - } - - return rv; -} - #endif /* !defined(OPENSSL_NO_SOCK) */ diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index b60568e066..ca1c9fc6de 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -784,3 +784,100 @@ void bio_cleanup(void) CRYPTO_THREAD_lock_free(bio_type_lock); bio_type_lock = NULL; } + +/* Internal variant of the below BIO_wait() not calling BIOerr() */ +static int bio_wait(BIO *bio, time_t max_time, unsigned int milliseconds) +{ + int fd; + + if (max_time == 0) + return 1; + +#ifndef OPENSSL_NO_SOCK + if (BIO_get_fd(bio, &fd) > 0) + return BIO_socket_wait(fd, BIO_should_read(bio), max_time); +#endif + if (milliseconds > 1000) { + long sec_diff = (long)(max_time - time(NULL)); /* might overflow */ + + if (sec_diff <= 0) + return 0; /* timeout */ + if ((unsigned long)sec_diff < milliseconds / 1000) + milliseconds = (unsigned long)sec_diff * 1000; + } + ossl_sleep(milliseconds); + return 1; +} + +/* + * Wait on (typically socket-based) BIO at most until max_time. + * Succeed immediately if max_time == 0. If sockets are not available succeed + * after waiting at most given milliseconds in order to avoid a tight busy loop. + * Call BIOerr(...) unless success. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_wait(BIO *bio, time_t max_time, unsigned int milliseconds) +{ + int rv = bio_wait(bio, max_time, milliseconds); + + if (rv <= 0) + BIOerr(0, rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR); + return rv; +} + +/* + * Connect via given BIO using BIO_do_handshake() until success/timeout/error. + * Parameter timeout == 0 means infinite, < 0 leads to immediate timeout error. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_connect_retry(BIO *bio, int timeout) +{ + int blocking = timeout == 0; + time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; + int rv; + + if (bio == NULL) { + BIOerr(0, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (timeout < 0) { + BIOerr(0, BIO_R_CONNECT_TIMEOUT); + return 0; + } + + if (!blocking) + BIO_set_nbio(bio, 1); + + retry: /* it does not help here to set SSL_MODE_AUTO_RETRY */ + rv = BIO_do_handshake(bio); /* This indirectly calls ERR_clear_error(); */ + + if (rv <= 0) { + if (get_last_sys_error() == ETIMEDOUT) { + /* + * if blocking, despite blocking BIO, BIO_do_handshake() timed out + * when non-blocking, BIO_do_handshake() timed out early + * with rv == -1 and get_last_sys_error() == 0 + */ + ERR_clear_error(); + (void)BIO_reset(bio); + /* + * unless using BIO_reset(), blocking next connect() may crash and + * non-blocking next BIO_do_handshake() will fail + */ + goto retry; + } else if (BIO_should_retry(bio)) { + /* will not actually wait if timeout == 0 (i.e., blocking BIO) */ + rv = bio_wait(bio, max_time, 100 /* milliseconds */); + if (rv > 0) + goto retry; + BIOerr(0, rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR); + } else { + rv = -1; + if (ERR_peek_error() == 0) /* missing error queue entry */ + BIOerr(0, BIO_R_CONNECT_ERROR); /* workaround: general error */ + } + } + + return rv; +} |