summaryrefslogtreecommitdiff
path: root/lib/ssl/ssl3con.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/ssl3con.c')
-rw-r--r--lib/ssl/ssl3con.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index dd280d2ef..466fc296f 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -1476,6 +1476,13 @@ ssl3_SetupBothPendingCipherSpecs(sslSocket *ss)
goto loser;
}
+ if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) {
+ ss->ssl3.prSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH,
+ ss->opt.recordSizeLimit);
+ ss->ssl3.pwSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH,
+ ss->xtnData.recordSizeLimit);
+ }
+
ssl_ReleaseSpecWriteLock(ss); /*******************************/
return SECSuccess;
@@ -2272,7 +2279,7 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type,
unsigned int spaceNeeded;
SECStatus rv;
- contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH);
+ contentLen = PR_MIN(nIn, spec->recordSizeLimit);
spaceNeeded = contentLen + SSL3_BUFFER_FUDGE;
if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
spec->cipherDef->type == type_block) {
@@ -12147,6 +12154,11 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ciphertext *cText)
return NULL;
}
+/* MAX_EXPANSION is the amount by which a record might plausibly be expanded
+ * when protected. It's the worst case estimate, so the sum of block cipher
+ * padding (up to 256 octets) and HMAC (48 octets for SHA-384). */
+#define MAX_EXPANSION (256 + 48)
+
/* if cText is non-null, then decipher and check the MAC of the
* SSL record from cText->buf (typically gs->inbuf)
* into databuf (typically gs->buf), and any previous contents of databuf
@@ -12176,6 +12188,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
PRBool isTLS;
DTLSEpoch epoch;
ssl3CipherSpec *spec = NULL;
+ PRUint16 recordSizeLimit;
PRBool outOfOrderSpec = PR_FALSE;
SSL3ContentType rType;
sslBuffer *plaintext = &ss->gs.buf;
@@ -12230,12 +12243,20 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
return SECFailure;
}
- if (plaintext->space < MAX_FRAGMENT_LENGTH) {
- rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
+ recordSizeLimit = spec->recordSizeLimit;
+ if (cText->buf->len > recordSizeLimit + MAX_EXPANSION) {
+ ssl_ReleaseSpecReadLock(ss); /*****************************/
+ SSL3_SendAlert(ss, alert_fatal, record_overflow);
+ PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ return SECFailure;
+ }
+
+ if (plaintext->space < recordSizeLimit + MAX_EXPANSION) {
+ rv = sslBuffer_Grow(plaintext, recordSizeLimit + MAX_EXPANSION);
if (rv != SECSuccess) {
ssl_ReleaseSpecReadLock(ss); /*************************/
SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
- SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
+ SSL_GETPID(), ss->fd, recordSizeLimit + MAX_EXPANSION));
/* sslBuffer_Grow has set a memory error code. */
/* Perhaps we should send an alert. (but we have no memory!) */
return SECFailure;
@@ -12294,7 +12315,10 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
if (IS_DTLS(ss) ||
(ss->sec.isServer &&
ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
- /* Silently drop the packet */
+ /* Silently drop the packet unless we sent a fatal alert. */
+ if (ss->ssl3.fatalAlertSent) {
+ return SECFailure;
+ }
return SECSuccess;
}
@@ -12330,7 +12354,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
}
/* Check the length of the plaintext. */
- if (isTLS && plaintext->len > MAX_FRAGMENT_LENGTH) {
+ if (isTLS && plaintext->len > recordSizeLimit) {
plaintext->len = 0;
SSL3_SendAlert(ss, alert_fatal, record_overflow);
PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);