diff options
Diffstat (limited to 'src/ssl/ssl_lib.cc')
-rw-r--r-- | src/ssl/ssl_lib.cc | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc index 11863129..703c2bc9 100644 --- a/src/ssl/ssl_lib.cc +++ b/src/ssl/ssl_lib.cc @@ -478,6 +478,7 @@ static bool ssl_can_renegotiate(const SSL *ssl) { return false; case ssl_renegotiate_freely: + case ssl_renegotiate_explicit: return true; case ssl_renegotiate_once: return ssl->s3->total_renegotiations == 0; @@ -945,29 +946,16 @@ static int ssl_do_post_handshake(SSL *ssl, const SSLMessage &msg) { return 1; // Ignore the HelloRequest. } - if (!ssl_can_renegotiate(ssl) || - // Renegotiation is only supported at quiescent points in the application - // protocol, namely in HTTPS, just before reading the HTTP response. - // Require the record-layer be idle and avoid complexities of sending a - // handshake record while an application_data record is being written. - !ssl->s3->write_buffer.empty() || - ssl->s3->write_shutdown != ssl_shutdown_none) { - OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION); - return 0; + ssl->s3->renegotiate_pending = true; + if (ssl->renegotiate_mode == ssl_renegotiate_explicit) { + return 1; // Handle it later. } - // Begin a new handshake. - if (ssl->s3->hs != nullptr) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; - } - ssl->s3->hs = ssl_handshake_new(ssl); - if (ssl->s3->hs == nullptr) { + if (!SSL_renegotiate(ssl)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION); return 0; } - ssl->s3->total_renegotiations++; return 1; } @@ -1012,6 +1000,11 @@ static int ssl_read_impl(SSL *ssl) { } while (ssl->s3->pending_app_data.empty()) { + if (ssl->s3->renegotiate_pending) { + ssl->s3->rwstate = SSL_ERROR_WANT_RENEGOTIATE; + return -1; + } + // Complete the current handshake, if any. False Start will cause // |SSL_do_handshake| to return mid-handshake, so this may require multiple // iterations. @@ -1353,6 +1346,7 @@ int SSL_get_error(const SSL *ssl, int ret_code) { case SSL_ERROR_PENDING_TICKET: case SSL_ERROR_EARLY_DATA_REJECTED: case SSL_ERROR_WANT_CERTIFICATE_VERIFY: + case SSL_ERROR_WANT_RENEGOTIATE: return ssl->s3->rwstate; case SSL_ERROR_WANT_READ: { @@ -1743,8 +1737,39 @@ long SSL_get_default_timeout(const SSL *ssl) { int SSL_renegotiate(SSL *ssl) { // Caller-initiated renegotiation is not supported. - OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; + if (!ssl->s3->renegotiate_pending) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (!ssl_can_renegotiate(ssl)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); + return 0; + } + + // Renegotiation is only supported at quiescent points in the application + // protocol, namely in HTTPS, just before reading the HTTP response. + // Require the record-layer be idle and avoid complexities of sending a + // handshake record while an application_data record is being written. + if (!ssl->s3->write_buffer.empty() || + ssl->s3->write_shutdown != ssl_shutdown_none) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); + return 0; + } + + // Begin a new handshake. + if (ssl->s3->hs != nullptr) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + ssl->s3->hs = ssl_handshake_new(ssl); + if (ssl->s3->hs == nullptr) { + return 0; + } + + ssl->s3->renegotiate_pending = false; + ssl->s3->total_renegotiations++; + return 1; } int SSL_renegotiate_pending(SSL *ssl) { @@ -2226,36 +2251,17 @@ int SSL_CTX_add_cert_compression_alg(SSL_CTX *ctx, uint16_t alg_id, ssl_cert_decompression_func_t decompress) { assert(compress != nullptr || decompress != nullptr); - for (const auto *alg : ctx->cert_compression_algs.get()) { - if (alg->alg_id == alg_id) { + for (const auto &alg : ctx->cert_compression_algs) { + if (alg.alg_id == alg_id) { return 0; } } - UniquePtr<CertCompressionAlg> alg = MakeUnique<CertCompressionAlg>(); - if (alg == nullptr) { - return 0; - } - - alg->alg_id = alg_id; - alg->compress = compress; - alg->decompress = decompress; - - if (ctx->cert_compression_algs == nullptr) { - ctx->cert_compression_algs.reset(sk_CertCompressionAlg_new_null()); - if (ctx->cert_compression_algs == nullptr) { - return 0; - } - } - - if (!PushToStack(ctx->cert_compression_algs.get(), std::move(alg))) { - if (sk_CertCompressionAlg_num(ctx->cert_compression_algs.get()) == 0) { - ctx->cert_compression_algs.reset(); - } - return 0; - } - - return 1; + CertCompressionAlg alg; + alg.alg_id = alg_id; + alg.compress = compress; + alg.decompress = decompress; + return ctx->cert_compression_algs.Push(alg); } void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx, int enabled) { |