Bug 275744: Add new error code SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD
authorwtc%google.com
Wed, 03 Feb 2010 03:44:29 +0000
changeset 9534 c6fd99c1ed938ee2399d284b5f7cd5b2734fe1b5
parent 9533 c604c1f52e9d91eff42b1a7fef23817abe2a8822
child 9535 038d3ae4f3f2b76cf42075b5e5c0c3a695576169
push idunknown
push userunknown
push dateunknown
bugs275744
Bug 275744: Add new error code SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD when we detect missing compression. The patch is contributed by Adam Langley <agl@chromium.org>. r=nelson,wtc. Modified Files: cmd/lib/SSLerrs.h lib/ssl/ssl3con.c lib/ssl/sslerr.h
security/nss/cmd/lib/SSLerrs.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/sslerr.h
--- a/security/nss/cmd/lib/SSLerrs.h
+++ b/security/nss/cmd/lib/SSLerrs.h
@@ -394,8 +394,11 @@ ER3(SSL_ERROR_RX_MALFORMED_NEW_SESSION_T
 ER3(SSL_ERROR_DECOMPRESSION_FAILURE,           (SSL_ERROR_BASE + 111),
 "SSL received a compressed record that could not be decompressed.")
 
 ER3(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED,       (SSL_ERROR_BASE + 112),
 "Renegotiation is not allowed on this SSL socket.")
 
 ER3(SSL_ERROR_UNSAFE_NEGOTIATION,              (SSL_ERROR_BASE + 113),
 "Peer attempted old style (potentially vulnerable) handshake.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD, (SSL_ERROR_BASE + 114),
+"SSL received an unexpected uncompressed record.")
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -8956,21 +8956,43 @@ const ssl3BulkCipherDef *cipher_def;
 	}
 
 	rv = crSpec->decompressor(crSpec->decompressContext,
 				  databuf->buf,
 				  (int*) &databuf->len,
 				  databuf->space,
 				  plaintext->buf,
 				  plaintext->len);
+
 	if (rv != SECSuccess) {
 	    int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE);
-	    PORT_Free(plaintext->buf);
 	    SSL3_SendAlert(ss, alert_fatal,
 			   isTLS ? decompression_failure : bad_record_mac);
+
+	    /* There appears to be a bug with (at least) Apache + OpenSSL where
+	     * resumed SSLv3 connections don't actually use compression. See
+	     * comments 93-95 of
+	     * https://bugzilla.mozilla.org/show_bug.cgi?id=275744
+	     *
+	     * So, if we get a decompression error, and the record appears to
+	     * be already uncompressed, then we return a more specific error
+	     * code to hopefully save somebody some debugging time in the
+	     * future.
+	     */
+	    if (plaintext->len >= 4) {
+		unsigned int len = ((unsigned int) plaintext->buf[1] << 16) |
+		                   ((unsigned int) plaintext->buf[2] << 8) |
+		                   (unsigned int) plaintext->buf[3];
+		if (len == plaintext->len - 4) {
+		    /* This appears to be uncompressed already */
+		    err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD;
+		}
+	    }
+
+	    PORT_Free(plaintext->buf);
 	    PORT_SetError(err);
 	    return SECFailure;
 	}
 
 	PORT_Free(plaintext->buf);
     }
 
     /*
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -194,13 +194,15 @@ SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT		= (
 
 SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 109),
 SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET  = (SSL_ERROR_BASE + 110),
 
 SSL_ERROR_DECOMPRESSION_FAILURE		= (SSL_ERROR_BASE + 111),
 SSL_ERROR_RENEGOTIATION_NOT_ALLOWED     = (SSL_ERROR_BASE + 112),
 SSL_ERROR_UNSAFE_NEGOTIATION            = (SSL_ERROR_BASE + 113),
 
+SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD	= (SSL_ERROR_BASE + 114),
+
 SSL_ERROR_END_OF_LIST	/* let the c compiler determine the value of this. */
 } SSLErrorCodes;
 #endif /* NO_SECURITY_ERROR_ENUM */
 
 #endif /* __SSL_ERR_H_ */