mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1305970 - land NSS 0x5eb5f52b7922, r=me
This commit is contained in:
parent
acb9007769
commit
bcf48e11c8
@ -1 +1 @@
|
||||
0cccc59d04dd
|
||||
5eb5f52b7922
|
||||
|
@ -10,4 +10,3 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
@ -40,12 +40,13 @@
|
||||
"ClientAuth-SHA1-Fallback-RSA":"We fail when the sig_algs_ext is empty",
|
||||
"Downgrade-TLS12-*":"NSS implements downgrade detection",
|
||||
"TrailingMessageData-*": "Bug 1304575",
|
||||
"DuplicateKeyShares":"Bug 1304578"
|
||||
"DuplicateKeyShares":"Bug 1304578",
|
||||
"Resume-Server-TLS13-TLS13":"Bug 1314351"
|
||||
},
|
||||
"ErrorMap" : {
|
||||
":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:":"SSL_ERROR_NO_CYPHER_OVERLAP",
|
||||
":UNKNOWN_CIPHER_RETURNED:":"SSL_ERROR_NO_CYPHER_OVERLAP",
|
||||
":OLD_SESSION_CIPHER_NOT_RETURNED:":"SSL_ERROR_NO_CYPHER_OVERLAP",
|
||||
":OLD_SESSION_CIPHER_NOT_RETURNED:":"SSL_ERROR_RX_MALFORMED_SERVER_HELLO",
|
||||
":NO_SHARED_CIPHER:":"SSL_ERROR_NO_CYPHER_OVERLAP",
|
||||
":DIGEST_CHECK_FAILED:":"SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE"
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ std::unique_ptr<const Config> ReadConfig(int argc, char** argv) {
|
||||
|
||||
cfg->AddEntry<int>("port", 0);
|
||||
cfg->AddEntry<bool>("server", false);
|
||||
cfg->AddEntry<bool>("resume", false);
|
||||
cfg->AddEntry<int>("resume-count", 0);
|
||||
cfg->AddEntry<std::string>("key-file", "");
|
||||
cfg->AddEntry<std::string>("cert-file", "");
|
||||
|
||||
@ -321,7 +321,8 @@ int main(int argc, char** argv) {
|
||||
// Run a single test cycle.
|
||||
bool success = RunCycle(cfg);
|
||||
|
||||
if (success && cfg->get<bool>("resume")) {
|
||||
int resume_count = cfg->get<int>("resume-count");
|
||||
while (success && resume_count-- > 0) {
|
||||
std::cout << "Resuming" << std::endl;
|
||||
success = RunCycle(cfg);
|
||||
}
|
||||
|
@ -210,6 +210,26 @@ PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool SSLInt_SendNewSessionTicket(PRFileDesc *fd) {
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
ssl_GetSSL3HandshakeLock(ss);
|
||||
ssl_GetXmitBufLock(ss);
|
||||
|
||||
SECStatus rv = tls13_SendNewSessionTicket(ss);
|
||||
if (rv == SECSuccess) {
|
||||
rv = ssl3_FlushHandshake(ss, 0);
|
||||
}
|
||||
|
||||
ssl_ReleaseXmitBufLock(ss);
|
||||
ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
|
||||
return rv == SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to) {
|
||||
PRUint64 epoch;
|
||||
sslSocket *ss;
|
||||
|
@ -31,6 +31,7 @@ PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd);
|
||||
SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len);
|
||||
PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType);
|
||||
PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type);
|
||||
PRBool SSLInt_SendNewSessionTicket(PRFileDesc *fd);
|
||||
SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to);
|
||||
SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to);
|
||||
SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra);
|
||||
|
@ -557,4 +557,26 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
|
||||
ASSERT_NE(initialTicket, c2->extension());
|
||||
}
|
||||
|
||||
// Check that resumption works after receiving two NST messages.
|
||||
TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNST) {
|
||||
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
|
||||
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
Connect();
|
||||
|
||||
// Clear the session ticket keys to invalidate the old ticket.
|
||||
SSLInt_ClearSessionTicketKey();
|
||||
SSLInt_SendNewSessionTicket(server_->ssl_fd());
|
||||
|
||||
SendReceive(); // Need to read so that we absorb the session tickets.
|
||||
CheckKeys();
|
||||
|
||||
// Resume the connection.
|
||||
Reset();
|
||||
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
|
||||
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
Connect();
|
||||
SendReceive();
|
||||
}
|
||||
|
||||
} // namespace nss_test
|
||||
|
@ -30,6 +30,7 @@ CSRCS = \
|
||||
sslerrstrs.c \
|
||||
sslinit.c \
|
||||
ssl3ext.c \
|
||||
ssl3exthandle.c \
|
||||
sslmutex.c \
|
||||
sslnonce.c \
|
||||
sslreveal.c \
|
||||
@ -43,6 +44,7 @@ CSRCS = \
|
||||
sslinfo.c \
|
||||
ssl3ecc.c \
|
||||
tls13con.c \
|
||||
tls13exthandle.c \
|
||||
tls13hkdf.c \
|
||||
sslcert.c \
|
||||
sslgrp.c \
|
||||
|
@ -17,6 +17,7 @@
|
||||
'ssl3con.c',
|
||||
'ssl3ecc.c',
|
||||
'ssl3ext.c',
|
||||
'ssl3exthandle.c',
|
||||
'ssl3gthr.c',
|
||||
'sslauth.c',
|
||||
'sslcert.c',
|
||||
@ -37,6 +38,7 @@
|
||||
'ssltrace.c',
|
||||
'sslver.c',
|
||||
'tls13con.c',
|
||||
'tls13exthandle.c',
|
||||
'tls13hkdf.c',
|
||||
],
|
||||
'conditions': [
|
||||
|
@ -343,7 +343,7 @@ static const ssl3KEADef kea_defs[] =
|
||||
{kea_ecdh_anon, ssl_kea_ecdh, nullKey, ssl_auth_null, PR_TRUE, SEC_OID_TLS_ECDH_ANON},
|
||||
{kea_ecdhe_psk, ssl_kea_ecdh_psk, nullKey, ssl_auth_psk, PR_TRUE, SEC_OID_TLS_ECDHE_PSK},
|
||||
{kea_dhe_psk, ssl_kea_dh_psk, nullKey, ssl_auth_psk, PR_TRUE, SEC_OID_TLS_DHE_PSK},
|
||||
{kea_tls13_any, ssl_kea_tls13_any, nullKey, ssl_auth_tls13_any, PR_TRUE, SEC_OID_TLS13_KEA_ANY},
|
||||
{kea_tls13_any, ssl_kea_tls13_any, nullKey, ssl_auth_tls13_any, PR_TRUE, SEC_OID_TLS13_KEA_ANY},
|
||||
};
|
||||
|
||||
/* must use ssl_LookupCipherSuiteDef to access */
|
||||
@ -1557,6 +1557,7 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss)
|
||||
PRBool isTLS;
|
||||
|
||||
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
|
||||
PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
|
||||
ssl_GetSpecWriteLock(ss); /*******************************/
|
||||
|
||||
@ -6365,7 +6366,7 @@ ssl_PickSignatureScheme(sslSocket *ss,
|
||||
}
|
||||
|
||||
/* Skip RSA-PSS schemes when the certificate's private key slot does
|
||||
* not supporting that mechanism. */
|
||||
* not support this signature mechanism. */
|
||||
if (ssl_IsRsaPssSignatureScheme(preferred) && !slotDoesPss) {
|
||||
continue;
|
||||
}
|
||||
@ -9338,9 +9339,12 @@ ssl3_SendServerHello(sslSocket *ss)
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
rv = ssl3_SetupPendingCipherSpec(ss);
|
||||
if (rv != SECSuccess) {
|
||||
return rv; /* err set by ssl3_SetupPendingCipherSpec */
|
||||
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
rv = ssl3_SetupPendingCipherSpec(ss);
|
||||
if (rv != SECSuccess) {
|
||||
return rv; /* err set by ssl3_SetupPendingCipherSpec */
|
||||
}
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
@ -9552,6 +9556,13 @@ ssl3_EncodeSigAlgs(sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 *len)
|
||||
SSLHashType hashType = ssl_SignatureSchemeToHashType(
|
||||
ss->ssl3.signatureSchemes[i]);
|
||||
SECOidTag hashOID = ssl3_HashTypeToOID(hashType);
|
||||
|
||||
/* Skip RSA-PSS schemes if there are no tokens to verify them. */
|
||||
if (ssl_IsRsaPssSignatureScheme(ss->ssl3.signatureSchemes[i]) &&
|
||||
!PK11_TokenExists(auth_alg_defs[ssl_auth_rsa_pss])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
|
||||
(policy & NSS_USE_ALG_IN_SSL_KX)) {
|
||||
p = ssl_EncodeUintX((PRUint32)ss->ssl3.signatureSchemes[i], 2, p);
|
||||
|
File diff suppressed because it is too large
Load Diff
2447
security/nss/lib/ssl/ssl3exthandle.c
Normal file
2447
security/nss/lib/ssl/ssl3exthandle.c
Normal file
File diff suppressed because it is too large
Load Diff
71
security/nss/lib/ssl/ssl3exthandle.h
Normal file
71
security/nss/lib/ssl/ssl3exthandle.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is PRIVATE to SSL.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __ssl3exthandle_h_
|
||||
#define __ssl3exthandle_h_
|
||||
|
||||
PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket *ss,
|
||||
PRBool append, PRUint32 maxBytes);
|
||||
SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
|
||||
PRUint16 ex_type, SECItem *data);
|
||||
SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
|
||||
PRUint16 ex_type, SECItem *data);
|
||||
SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
|
||||
PRUint16 ex_type, SECItem *data);
|
||||
SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
|
||||
PRUint16 ex_type, SECItem *data);
|
||||
SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
PRInt32 ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
PRInt32 ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
PRInt32 ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket *ss,
|
||||
PRBool append, PRUint32 maxBytes);
|
||||
SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
|
||||
PRUint16 ex_type, SECItem *data);
|
||||
SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
|
||||
PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
|
||||
PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss,
|
||||
PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data);
|
||||
|
||||
#endif
|
@ -87,7 +87,6 @@ static SECStatus tls13_ClientHandleFinished(sslSocket *ss,
|
||||
static SECStatus tls13_ServerHandleFinished(sslSocket *ss,
|
||||
SSL3Opaque *b, PRUint32 length,
|
||||
const TLS13CombinedHash *hashes);
|
||||
static SECStatus tls13_SendNewSessionTicket(sslSocket *ss);
|
||||
static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b,
|
||||
PRUint32 length);
|
||||
static void
|
||||
@ -3354,10 +3353,7 @@ tls13_ServerHandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
|
||||
return SECFailure; /* Error code and alerts handled below */
|
||||
}
|
||||
ssl_GetXmitBufLock(ss);
|
||||
if (ss->opt.enableSessionTickets &&
|
||||
ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) {
|
||||
/* TODO(ekr@rtfm.com): Add support for new tickets in PSK
|
||||
* (bug 1281034).*/
|
||||
if (ss->opt.enableSessionTickets) {
|
||||
rv = tls13_SendNewSessionTicket(ss);
|
||||
if (rv != SECSuccess) {
|
||||
ssl_ReleaseXmitBufLock(ss);
|
||||
@ -3541,7 +3537,7 @@ loser:
|
||||
* TicketExtension extensions<0..2^16-2>;
|
||||
* } NewSessionTicket;
|
||||
*/
|
||||
static SECStatus
|
||||
SECStatus
|
||||
tls13_SendNewSessionTicket(sslSocket *ss)
|
||||
{
|
||||
PRUint16 message_length;
|
||||
@ -3726,10 +3722,6 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* TODO(ekr@rtfm.com): Re-enable new tickets when PSK mode is
|
||||
* in use. I believe this works, but I can't test it until the
|
||||
* server side supports it. Bug 1257047.
|
||||
*/
|
||||
if (!ss->opt.noCache) {
|
||||
PORT_Assert(ss->sec.ci.sid);
|
||||
|
||||
@ -3754,13 +3746,24 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
||||
/* Replace a previous session ticket when
|
||||
* we receive a second NewSessionTicket message. */
|
||||
if (ss->sec.ci.sid->cached == in_client_cache) {
|
||||
/* Uncache first. */
|
||||
ss->sec.uncache(ss->sec.ci.sid);
|
||||
/* Create a new session ID. */
|
||||
sslSessionID *sid = ssl3_NewSessionID(ss, PR_FALSE);
|
||||
if (!sid) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Then destroy and rebuild the SID. */
|
||||
/* Copy over the peerCert. */
|
||||
PORT_Assert(ss->sec.ci.sid->peerCert);
|
||||
sid->peerCert = CERT_DupCertificate(ss->sec.ci.sid->peerCert);
|
||||
if (!sid->peerCert) {
|
||||
ssl_FreeSID(sid);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Destroy the old SID. */
|
||||
ss->sec.uncache(ss->sec.ci.sid);
|
||||
ssl_FreeSID(ss->sec.ci.sid);
|
||||
ss->sec.ci.sid = ssl3_NewSessionID(ss, PR_FALSE);
|
||||
ss->sec.ci.sid->cached = never_cached;
|
||||
ss->sec.ci.sid = sid;
|
||||
}
|
||||
|
||||
ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ticket);
|
||||
|
@ -74,5 +74,6 @@ PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version);
|
||||
PRUint16 tls13_DecodeDraftVersion(PRUint16 version);
|
||||
SECStatus tls13_NegotiateVersion(sslSocket *ss,
|
||||
const TLSExtension *supported_versions);
|
||||
SECStatus tls13_SendNewSessionTicket(sslSocket *ss);
|
||||
|
||||
#endif /* __tls13con_h_ */
|
||||
|
1013
security/nss/lib/ssl/tls13exthandle.c
Normal file
1013
security/nss/lib/ssl/tls13exthandle.c
Normal file
File diff suppressed because it is too large
Load Diff
54
security/nss/lib/ssl/tls13exthandle.h
Normal file
54
security/nss/lib/ssl/tls13exthandle.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is PRIVATE to SSL.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __tls13exthandle_h_
|
||||
#define __tls13exthandle_h_
|
||||
|
||||
PRInt32 tls13_ServerSendStatusRequestXtn(sslSocket *ss,
|
||||
PRBool append, PRUint32 maxBytes);
|
||||
PRInt32 tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus tls13_ClientHandleKeyShareXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus tls13_ClientHandleKeyShareXtnHrr(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus tls13_ServerHandleKeyShareXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 tls13_ClientSendPreSharedKeyXtn(sslSocket *ss, PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus tls13_ServerHandlePreSharedKeyXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus tls13_ClientHandlePreSharedKeyXtn(sslSocket *ss,
|
||||
PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 tls13_ClientSendEarlyDataXtn(sslSocket *ss,
|
||||
PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus tls13_ServerHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus tls13_ClientHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus tls13_ClientHandleTicketEarlyDataInfoXtn(
|
||||
sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
SECStatus tls13_ClientHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 tls13_ClientSendSupportedVersionsXtn(sslSocket *ss,
|
||||
PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
SECStatus tls13_ClientHandleHrrCookie(sslSocket *ss, PRUint16 ex_type,
|
||||
SECItem *data);
|
||||
PRInt32 tls13_ClientSendHrrCookieXtn(sslSocket *ss,
|
||||
PRBool append,
|
||||
PRUint32 maxBytes);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user