Repository: trafficserver Updated Branches: refs/heads/5.2.x 52cddbc86 -> 496b946fa
TS-3424 SSL Failed: decryption failed or bad record mac. Backported by shinrich Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/496b946f Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/496b946f Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/496b946f Branch: refs/heads/5.2.x Commit: 496b946fa4f4ececb125801c8a0d123749e25f15 Parents: 52cddbc Author: Leif Hedstrom <[email protected]> Authored: Thu Mar 19 14:56:57 2015 -0600 Committer: Leif Hedstrom <[email protected]> Committed: Thu Mar 19 14:56:57 2015 -0600 ---------------------------------------------------------------------- CHANGES | 2 + iocore/net/P_SSLNetVConnection.h | 3 ++ iocore/net/SSLNetVConnection.cc | 87 ++++++++++++++++++----------------- 3 files changed, 49 insertions(+), 43 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/496b946f/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index fe789ea..513ad4b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache Traffic Server 5.2.1 + *) [TS-3424] SSL Failed: decryption failed or bad record mac. + *) [TS-3439] Chunked responses don't honor keep-alive. *) [TS-3404] Handle race condition in handling delayed terminating chunk. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/496b946f/iocore/net/P_SSLNetVConnection.h ---------------------------------------------------------------------- diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h index 77a3034..8cde284 100644 --- a/iocore/net/P_SSLNetVConnection.h +++ b/iocore/net/P_SSLNetVConnection.h @@ -153,6 +153,7 @@ public: this->handShakeBuffer = new_MIOBuffer(); this->handShakeReader = this->handShakeBuffer->alloc_reader(); this->handShakeHolder = this->handShakeReader->clone(); + this->handShakeBioStored = 0; } void free_handshake_buffers() { if (this->handShakeReader) { @@ -167,6 +168,7 @@ public: this->handShakeReader = NULL; this->handShakeHolder = NULL; this->handShakeBuffer = NULL; + this->handShakeBioStored = 0; } // Returns true if all the hooks reenabled bool callHooks(TSHttpHookID eventId); @@ -181,6 +183,7 @@ private: MIOBuffer *handShakeBuffer; IOBufferReader *handShakeHolder; IOBufferReader *handShakeReader; + int handShakeBioStored; /// The current hook. /// @note For @C SSL_HOOKS_INVOKE, this is the hook to invoke. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/496b946f/iocore/net/SSLNetVConnection.cc ---------------------------------------------------------------------- diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 1c63002..dcdaa29 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -361,18 +361,12 @@ SSLNetVConnection::read_raw_data() char *start = this->handShakeReader->start(); char *end = this->handShakeReader->end(); + this->handShakeBioStored = end - start; // Sets up the buffer as a read only bio target // Must be reset on each read - BIO *rbio = BIO_new_mem_buf(start, end - start); + BIO *rbio = BIO_new_mem_buf(start, this->handShakeBioStored); BIO_set_mem_eof_return(rbio, -1); - // Assigning directly into the SSL structure - // is dirty, but there is no openssl function that only - // assigns the read bio. Originally I was getting and - // resetting the same write bio, but that caused the - // inserted buffer bios to be freed and then reinserted. - //BIO *wbio = SSL_get_wbio(this->ssl); - //SSL_set_bio(this->ssl, rbio, wbio); SSL_set_rbio(this, rbio); return r; @@ -421,8 +415,6 @@ SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread) // vc is an SSLNetVConnection. if (!getSSLHandShakeComplete()) { int err; - int data_to_read = 0; - char *data_ptr = NULL; // Not done handshaking, go into the SSL handshake logic again if (!getSSLHandShakeComplete()) { @@ -435,10 +427,10 @@ SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread) // If we have flipped to blind tunnel, don't read ahead if (this->handShakeReader) { if (this->attributes != HttpProxyPort::TRANSPORT_BLIND_TUNNEL) { - // Check and consume data that has been read - int data_still_to_read = BIO_get_mem_data(SSL_get_rbio(this->ssl), &data_ptr); - data_to_read = this->handShakeReader->read_avail(); - this->handShakeReader->consume(data_to_read - data_still_to_read); + if (BIO_eof(SSL_get_rbio(this->ssl))) { + this->handShakeReader->consume(this->handShakeBioStored); + this->handShakeBioStored = 0; + } } else { // Now in blind tunnel. Set things up to read what is in the buffer this->readSignalDone(VC_EVENT_READ_COMPLETE, nh); @@ -509,34 +501,31 @@ SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread) // At this point we are at the post-handshake SSL processing // If the read BIO is not already a socket, consider changing it if (this->handShakeReader) { - if (this->handShakeReader->read_avail() <= 0) { - // Switch the read bio over to a socket bio - SSL_set_rfd(this->ssl, this->get_socket()); - this->free_handshake_buffers(); + // Check out if there is anything left in the current bio + if (!BIO_eof(SSL_get_rbio(this->ssl))) { + // Still data remaining in the current BIO block } - else { // There is still data in the buffer to drain - char *data_ptr = NULL; - int data_still_to_read = BIO_get_mem_data(SSL_get_rbio(this->ssl), &data_ptr); - if (data_still_to_read > 0) { - // Still data remaining in the current BIO block - } - else { - // reset the block + else { + // Consume what SSL has read so far. + this->handShakeReader->consume(this->handShakeBioStored); + + // If we are empty now, switch over + if (this->handShakeReader->read_avail() <= 0) { + // Switch the read bio over to a socket bio + SSL_set_rfd(this->ssl, this->get_socket()); + this->free_handshake_buffers(); + } else { + // Setup the next iobuffer block to drain char *start = this->handShakeReader->start(); char *end = this->handShakeReader->end(); + this->handShakeBioStored = end - start; + // Sets up the buffer as a read only bio target // Must be reset on each read - BIO *rbio = BIO_new_mem_buf(start, end - start); + BIO *rbio = BIO_new_mem_buf(start, this->handShakeBioStored); BIO_set_mem_eof_return(rbio, -1); - // So assigning directly into the SSL structure - // is dirty, but there is no openssl function that only - // assigns the read bio. Originally I was getting and - // resetting the same write bio, but that caused the - // inserted buffer bios to be freed and then reinserted. SSL_set_rbio(this, rbio); - //BIO *wbio = SSL_get_wbio(this->ssl); - //SSL_set_bio(this->ssl, rbio, wbio); - } + } } } // Otherwise, we already replaced the buffer bio with a socket bio @@ -773,6 +762,7 @@ SSLNetVConnection::SSLNetVConnection(): handShakeBuffer(NULL), handShakeHolder(NULL), handShakeReader(NULL), + handShakeBioStored(0), sslPreAcceptHookState(SSL_HOOKS_INIT), sslSNIHookState(SNI_HOOKS_INIT), npnSet(NULL), @@ -941,14 +931,25 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) // All the pre-accept hooks have completed, proceed with the actual accept. - char *data_ptr = NULL; - int data_to_read = BIO_get_mem_data(SSL_get_rbio(this->ssl), &data_ptr); - if (data_to_read <= 0) { // If there is not already data in the buffer - // Read from socket to fill in the BIO buffer with the - // raw handshake data before calling the ssl accept calls. - int64_t data_read; - if ((data_read = this->read_raw_data()) > 0) { - BIO_get_mem_data(SSL_get_rbio(this->ssl), &data_ptr); + if (BIO_eof(SSL_get_rbio(this->ssl))) { // No more data in the buffer + + this->handShakeReader->consume(this->handShakeBioStored); + if (this->handShakeReader->read_avail() > 0) { + Warning("Shifing block of handshake data %d", this->handShakeReader->read_avail()); + // Setup the next iobuffer block to drain + char *start = this->handShakeReader->start(); + char *end = this->handShakeReader->end(); + this->handShakeBioStored = end - start; + + // Sets up the buffer as a read only bio target + // Must be reset on each read + BIO *rbio = BIO_new_mem_buf(start, this->handShakeBioStored); + BIO_set_mem_eof_return(rbio, -1); + SSL_set_rbio(this, rbio); + } else { + // Read from socket to fill in the BIO buffer with the + // raw handshake data before calling the ssl accept calls. + this->read_raw_data(); } }
