mirror of
https://github.com/roytam1/mozilla45esr.git
synced 2026-05-26 06:25:03 +00:00
TLS 1.3 support (part 2), adapted from https://github.com/MoonchildProductions/Pale-Moon/commit/9c415a96f80c361ac2b8b9b1f2f4a90985acd232
This commit is contained in:
@@ -893,13 +893,15 @@ typedef struct
|
||||
#define ERROR(key, val) {key, #key}
|
||||
|
||||
ErrorEntry socketTransportStatuses[] = {
|
||||
ERROR(NS_NET_STATUS_RESOLVING_HOST, FAILURE(3)),
|
||||
ERROR(NS_NET_STATUS_RESOLVED_HOST, FAILURE(11)),
|
||||
ERROR(NS_NET_STATUS_CONNECTING_TO, FAILURE(7)),
|
||||
ERROR(NS_NET_STATUS_CONNECTED_TO, FAILURE(4)),
|
||||
ERROR(NS_NET_STATUS_SENDING_TO, FAILURE(5)),
|
||||
ERROR(NS_NET_STATUS_WAITING_FOR, FAILURE(10)),
|
||||
ERROR(NS_NET_STATUS_RECEIVING_FROM, FAILURE(6)),
|
||||
ERROR(NS_NET_STATUS_RESOLVING_HOST, FAILURE(3)),
|
||||
ERROR(NS_NET_STATUS_RESOLVED_HOST, FAILURE(11)),
|
||||
ERROR(NS_NET_STATUS_CONNECTING_TO, FAILURE(7)),
|
||||
ERROR(NS_NET_STATUS_CONNECTED_TO, FAILURE(4)),
|
||||
ERROR(NS_NET_STATUS_TLS_HANDSHAKE_STARTING, FAILURE(12)),
|
||||
ERROR(NS_NET_STATUS_TLS_HANDSHAKE_ENDED, FAILURE(13)),
|
||||
ERROR(NS_NET_STATUS_SENDING_TO, FAILURE(5)),
|
||||
ERROR(NS_NET_STATUS_WAITING_FOR, FAILURE(10)),
|
||||
ERROR(NS_NET_STATUS_RECEIVING_FROM, FAILURE(6)),
|
||||
};
|
||||
#undef ERROR
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pref("security.tls.version.max", 3);
|
||||
pref("security.tls.version.fallback-limit", 3);
|
||||
pref("security.tls.insecure_fallback_hosts", "");
|
||||
pref("security.tls.unrestricted_rc4_fallback", false);
|
||||
pref("security.tls.enable_0rtt_data", false);
|
||||
|
||||
pref("security.ssl.treat_unsafe_negotiation_as_broken", false);
|
||||
pref("security.ssl.require_safe_negotiation", false);
|
||||
|
||||
@@ -204,6 +204,22 @@ public:
|
||||
|
||||
virtual void DisableSpdy() { }
|
||||
virtual void ReuseConnectionOnRestartOK(bool) { }
|
||||
|
||||
// Returns true if early-data is possible.
|
||||
virtual bool Do0RTT() {
|
||||
return false;
|
||||
}
|
||||
// This function will be called when a tls handshake has been finished and
|
||||
// we know whether early-data that was sent has been accepted or not, e.g.
|
||||
// do we need to restart a transaction. This will be called only if Do0RTT
|
||||
// returns true.
|
||||
// If aRestart parameter is true we need to restart the transaction,
|
||||
// otherwise the erly-data has been accepted and we can continue the
|
||||
// transaction.
|
||||
// The function will return success or failure of the transaction restart.
|
||||
virtual nsresult Finish0RTT(bool aRestart) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpTransaction, NS_AHTTPTRANSACTION_IID)
|
||||
|
||||
@@ -79,6 +79,9 @@ nsHttpConnection::nsHttpConnection()
|
||||
, mResponseTimeoutEnabled(false)
|
||||
, mTCPKeepaliveConfig(kTCPKeepaliveDisabled)
|
||||
, mForceSendPending(false)
|
||||
, m0RTTChecked(false)
|
||||
, mWaitingFor0RTTResponse(false)
|
||||
, mContentBytesWritten0RTT(0)
|
||||
{
|
||||
LOG(("Creating nsHttpConnection @%p\n", this));
|
||||
|
||||
@@ -268,8 +271,12 @@ nsHttpConnection::StartSpdy(uint8_t spdyVersion)
|
||||
}
|
||||
|
||||
bool
|
||||
nsHttpConnection::EnsureNPNComplete()
|
||||
nsHttpConnection::EnsureNPNComplete(nsresult &aOut0RTTWriteHandshakeValue,
|
||||
uint32_t &aOut0RTTBytesWritten)
|
||||
{
|
||||
aOut0RTTWriteHandshakeValue = NS_OK;
|
||||
aOut0RTTBytesWritten = 0;
|
||||
|
||||
// If for some reason the components to check on NPN aren't available,
|
||||
// this function will just return true to continue on and disable SPDY
|
||||
|
||||
@@ -294,16 +301,81 @@ nsHttpConnection::EnsureNPNComplete()
|
||||
goto npnComplete;
|
||||
}
|
||||
|
||||
if (!m0RTTChecked) {
|
||||
// We reuse m0RTTChecked. We want to send this status only once.
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_TLS_HANDSHAKE_STARTING,
|
||||
0);
|
||||
}
|
||||
|
||||
ssl = do_QueryInterface(securityInfo, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
goto npnComplete;
|
||||
|
||||
rv = ssl->GetNegotiatedNPN(negotiatedNPN);
|
||||
if (!m0RTTChecked && (rv == NS_ERROR_NOT_CONNECTED) &&
|
||||
!mConnInfo->UsingProxy()) {
|
||||
// There is no ALPN info (yet!). We need to consider doing 0RTT. We
|
||||
// will do so if there is ALPN information from a previous session
|
||||
// (AlpnEarlySelection), we are using HTTP/1, and the request data can
|
||||
// be safely retried.
|
||||
m0RTTChecked = true;
|
||||
nsAutoCString earlyNegotiatedNPN;
|
||||
nsresult rvEarlyAlpn = ssl->GetAlpnEarlySelection(earlyNegotiatedNPN);
|
||||
if (NS_FAILED(rvEarlyAlpn)) {
|
||||
// if ssl->DriveHandshake() has never been called the value
|
||||
// for AlpnEarlySelection is still not set. So call it here and
|
||||
// check again.
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete %p - "
|
||||
"early selected alpn not available, we will try one more time.",
|
||||
this));
|
||||
// Let's do DriveHandshake again.
|
||||
rv = ssl->DriveHandshake();
|
||||
if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
goto npnComplete;
|
||||
}
|
||||
|
||||
// Check NegotiatedNPN first.
|
||||
rv = ssl->GetNegotiatedNPN(negotiatedNPN);
|
||||
if (rv == NS_ERROR_NOT_CONNECTED) {
|
||||
rvEarlyAlpn = ssl->GetAlpnEarlySelection(earlyNegotiatedNPN);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rvEarlyAlpn)) {
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete %p - "
|
||||
"early selected alpn not available", this));
|
||||
} else {
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete %p -"
|
||||
"early selected alpn: %s", this, earlyNegotiatedNPN.get()));
|
||||
uint32_t infoIndex;
|
||||
const SpdyInformation *info = gHttpHandler->SpdyInfo();
|
||||
// We are doing 0RTT only with Http/1 right now!
|
||||
if (NS_FAILED(info->GetNPNIndex(earlyNegotiatedNPN, &infoIndex))) {
|
||||
// Check if early-data is allowed for this transaction.
|
||||
if (mTransaction->Do0RTT()) {
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] - We "
|
||||
"can do 0RTT!", this));
|
||||
mWaitingFor0RTTResponse = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rv == NS_ERROR_NOT_CONNECTED) {
|
||||
// By writing 0 bytes to the socket the SSL handshake machine is
|
||||
// pushed forward.
|
||||
uint32_t count = 0;
|
||||
rv = mSocketOut->Write("", 0, &count);
|
||||
if (mWaitingFor0RTTResponse) {
|
||||
aOut0RTTWriteHandshakeValue = mTransaction->ReadSegments(this,
|
||||
nsIOService::gDefaultSegmentSize, &aOut0RTTBytesWritten);
|
||||
if (NS_FAILED(aOut0RTTWriteHandshakeValue) &&
|
||||
aOut0RTTWriteHandshakeValue != NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
goto npnComplete;
|
||||
}
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] - written %d "
|
||||
"bytes during 0RTT", this, aOut0RTTBytesWritten));
|
||||
mContentBytesWritten0RTT += aOut0RTTBytesWritten;
|
||||
}
|
||||
|
||||
rv = ssl->DriveHandshake();
|
||||
if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
goto npnComplete;
|
||||
}
|
||||
@@ -316,10 +388,30 @@ nsHttpConnection::EnsureNPNComplete()
|
||||
this, mConnInfo->HashKey().get(), negotiatedNPN.get(),
|
||||
mTLSFilter ? " [Double Tunnel]" : ""));
|
||||
|
||||
uint32_t infoIndex;
|
||||
const SpdyInformation *info = gHttpHandler->SpdyInfo();
|
||||
if (NS_SUCCEEDED(info->GetNPNIndex(negotiatedNPN, &infoIndex))) {
|
||||
StartSpdy(info->Version[infoIndex]);
|
||||
bool ealyDataAccepted = false;
|
||||
if (mWaitingFor0RTTResponse) {
|
||||
mWaitingFor0RTTResponse = false;
|
||||
// Check if early data has been accepted.
|
||||
rv = ssl->GetEarlyDataAccepted(&ealyDataAccepted);
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] - early data "
|
||||
"that was sent during 0RTT %s been accepted.",
|
||||
this, ealyDataAccepted ? "has" : "has not"));
|
||||
if (NS_FAILED(rv) ||
|
||||
NS_FAILED(mTransaction->Finish0RTT(!ealyDataAccepted))) {
|
||||
mTransaction->Close(NS_ERROR_NET_RESET);
|
||||
goto npnComplete;
|
||||
}
|
||||
}
|
||||
if (!ealyDataAccepted) {
|
||||
uint32_t infoIndex;
|
||||
const SpdyInformation *info = gHttpHandler->SpdyInfo();
|
||||
if (NS_SUCCEEDED(info->GetNPNIndex(negotiatedNPN, &infoIndex))) {
|
||||
StartSpdy(info->Version[infoIndex]);
|
||||
}
|
||||
} else {
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] - %d bytes "
|
||||
"has been sent during 0RTT.", this, mContentBytesWritten0RTT));
|
||||
mContentBytesWritten = mContentBytesWritten0RTT;
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SPDY_NPN_CONNECT, UsingSpdy());
|
||||
@@ -328,6 +420,17 @@ nsHttpConnection::EnsureNPNComplete()
|
||||
npnComplete:
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete setting complete to true"));
|
||||
mNPNComplete = true;
|
||||
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_TLS_HANDSHAKE_ENDED,
|
||||
0);
|
||||
if (mWaitingFor0RTTResponse) {
|
||||
mWaitingFor0RTTResponse = false;
|
||||
if (NS_FAILED(mTransaction->Finish0RTT(true))) {
|
||||
mTransaction->Close(NS_ERROR_NET_RESET);
|
||||
}
|
||||
mContentBytesWritten0RTT = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1572,7 +1675,9 @@ nsHttpConnection::OnSocketWritable()
|
||||
// request differently for http/1, http/2, spdy, etc.. and that is
|
||||
// negotiated with NPN/ALPN in the SSL handshake.
|
||||
|
||||
if (mConnInfo->UsingHttpsProxy() && !EnsureNPNComplete()) {
|
||||
if (mConnInfo->UsingHttpsProxy() &&
|
||||
!EnsureNPNComplete(rv, transactionBytes)) {
|
||||
MOZ_ASSERT(!transactionBytes);
|
||||
mSocketOutCondition = NS_BASE_STREAM_WOULD_BLOCK;
|
||||
} else if (mProxyConnectStream) {
|
||||
// If we're need an HTTP/1 CONNECT tunnel through a proxy
|
||||
@@ -1581,8 +1686,11 @@ nsHttpConnection::OnSocketWritable()
|
||||
rv = mProxyConnectStream->ReadSegments(ReadFromStream, this,
|
||||
nsIOService::gDefaultSegmentSize,
|
||||
&transactionBytes);
|
||||
} else if (!EnsureNPNComplete()) {
|
||||
mSocketOutCondition = NS_BASE_STREAM_WOULD_BLOCK;
|
||||
} else if (!EnsureNPNComplete(rv, transactionBytes)) {
|
||||
if (NS_SUCCEEDED(rv) && !transactionBytes &&
|
||||
NS_SUCCEEDED(mSocketOutCondition)) {
|
||||
mSocketOutCondition = NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
} else {
|
||||
|
||||
// for non spdy sessions let the connection manager know
|
||||
@@ -1630,7 +1738,7 @@ nsHttpConnection::OnSocketWritable()
|
||||
} else if (!transactionBytes) {
|
||||
rv = NS_OK;
|
||||
|
||||
if (mTransaction) { // in case the ReadSegments stack called CloseTransaction()
|
||||
if (mTransaction && !mWaitingFor0RTTResponse) { // in case the ReadSegments stack called CloseTransaction()
|
||||
//
|
||||
// at this point we've written out the entire transaction, and now we
|
||||
// must wait for the server's response. we manufacture a status message
|
||||
|
||||
@@ -241,7 +241,8 @@ private:
|
||||
|
||||
// Makes certain the SSL handshake is complete and NPN negotiation
|
||||
// has had a chance to happen
|
||||
bool EnsureNPNComplete();
|
||||
bool EnsureNPNComplete(nsresult &aOut0RTTWriteHandshakeValue,
|
||||
uint32_t &aOut0RTTBytesWritten);
|
||||
void SetupSSL();
|
||||
|
||||
// Start the Spdy transaction handler when NPN indicates spdy/*
|
||||
@@ -350,6 +351,17 @@ private:
|
||||
uint32_t mTCPKeepaliveConfig;
|
||||
nsCOMPtr<nsITimer> mTCPKeepaliveTransitionTimer;
|
||||
|
||||
// Helper variable for 0RTT handshake;
|
||||
bool m0RTTChecked; // Possible 0RTT has been
|
||||
// checked.
|
||||
bool mWaitingFor0RTTResponse; // We have are
|
||||
// sending 0RTT
|
||||
// data and we
|
||||
// are waiting
|
||||
// for the end of
|
||||
// the handsake.
|
||||
int64_t mContentBytesWritten0RTT;
|
||||
|
||||
private:
|
||||
// For ForceSend()
|
||||
static void ForceSendIO(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
@@ -139,6 +139,8 @@ nsHttpTransaction::nsHttpTransaction()
|
||||
, mAppId(NECKO_NO_APP_ID)
|
||||
, mIsInBrowser(false)
|
||||
, mClassOfService(0)
|
||||
, m0RTTInProgress(false)
|
||||
, mTransportStatus(NS_OK)
|
||||
{
|
||||
LOG(("Creating nsHttpTransaction @%p\n", this));
|
||||
gHttpHandler->GetMaxPipelineObjectSize(&mMaxPipelineObjectSize);
|
||||
@@ -529,6 +531,50 @@ nsHttpTransaction::OnTransportStatus(nsITransport* transport,
|
||||
}
|
||||
}
|
||||
|
||||
// A transaction can given to multiple HalfOpen sockets (this is a bug in
|
||||
// nsHttpConnectionMgr). We are going to fix it here as a work around to be
|
||||
// able to uplift it.
|
||||
switch(status) {
|
||||
case NS_NET_STATUS_RESOLVING_HOST:
|
||||
if (mTransportStatus != NS_OK) {
|
||||
LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
|
||||
"from backup transport"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case NS_NET_STATUS_RESOLVED_HOST:
|
||||
if (mTransportStatus != NS_NET_STATUS_RESOLVING_HOST &&
|
||||
mTransportStatus != NS_OK) {
|
||||
LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
|
||||
"from backup transport"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case NS_NET_STATUS_CONNECTING_TO:
|
||||
if (mTransportStatus != NS_NET_STATUS_RESOLVING_HOST &&
|
||||
mTransportStatus != NS_NET_STATUS_RESOLVED_HOST &&
|
||||
mTransportStatus != NS_OK) {
|
||||
LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
|
||||
"from backup transport"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case NS_NET_STATUS_CONNECTED_TO:
|
||||
if (mTransportStatus != NS_NET_STATUS_RESOLVING_HOST &&
|
||||
mTransportStatus != NS_NET_STATUS_RESOLVED_HOST &&
|
||||
mTransportStatus != NS_NET_STATUS_CONNECTING_TO &&
|
||||
mTransportStatus != NS_OK) {
|
||||
LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
|
||||
"from backup transport"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(("nsHttpTransaction::OnSocketStatus - a new event"));
|
||||
}
|
||||
|
||||
mTransportStatus = status;
|
||||
|
||||
// If the timing is enabled, and we are not using a persistent connection
|
||||
// then the requestStart timestamp will be null, so we mark the timestamps
|
||||
// for domainLookupStart/End and connectStart/End
|
||||
@@ -542,7 +588,9 @@ nsHttpTransaction::OnTransportStatus(nsITransport* transport,
|
||||
} else if (status == NS_NET_STATUS_CONNECTING_TO) {
|
||||
SetConnectStart(TimeStamp::Now());
|
||||
} else if (status == NS_NET_STATUS_CONNECTED_TO) {
|
||||
SetConnectEnd(TimeStamp::Now());
|
||||
SetConnectEnd(TimeStamp::Now(), true);
|
||||
} else if (status == NS_NET_STATUS_TLS_HANDSHAKE_ENDED) {
|
||||
SetConnectEnd(TimeStamp::Now(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,7 +735,7 @@ nsHttpTransaction::ReadSegments(nsAHttpSegmentReader *reader,
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
if (!mConnected) {
|
||||
if (!mConnected && !m0RTTInProgress) {
|
||||
mConnected = true;
|
||||
mConnection->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
|
||||
}
|
||||
@@ -1271,6 +1319,8 @@ nsHttpTransaction::Restart()
|
||||
}
|
||||
}
|
||||
|
||||
mTransportStatus = NS_OK;
|
||||
|
||||
return gHttpHandler->InitiateTransaction(this, mPriority);
|
||||
}
|
||||
|
||||
@@ -2304,5 +2354,33 @@ nsHttpTransaction::GetNetworkAddresses(NetAddr &self, NetAddr &peer)
|
||||
peer = mPeerAddr;
|
||||
}
|
||||
|
||||
bool
|
||||
nsHttpTransaction::Do0RTT()
|
||||
{
|
||||
if (mRequestHead->IsSafeMethod() &&
|
||||
!mConnection->IsProxyConnectInProgress()) {
|
||||
m0RTTInProgress = true;
|
||||
}
|
||||
return m0RTTInProgress;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpTransaction::Finish0RTT(bool aRestart)
|
||||
{
|
||||
MOZ_ASSERT(m0RTTInProgress);
|
||||
m0RTTInProgress = false;
|
||||
if (aRestart) {
|
||||
// Reset request headers to be sent again.
|
||||
nsCOMPtr<nsISeekableStream> seekable =
|
||||
do_QueryInterface(mRequestStream);
|
||||
if (seekable) {
|
||||
seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -164,6 +164,8 @@ public:
|
||||
|
||||
int64_t GetTransferSize() { return mTransferSize; }
|
||||
|
||||
bool Do0RTT() override;
|
||||
nsresult Finish0RTT(bool aRestart) override;
|
||||
private:
|
||||
friend class DeleteHttpTransaction;
|
||||
virtual ~nsHttpTransaction();
|
||||
@@ -451,6 +453,10 @@ public:
|
||||
private:
|
||||
RefPtr<ASpdySession> mTunnelProvider;
|
||||
|
||||
bool m0RTTInProgress;
|
||||
|
||||
nsresult mTransportStatus;
|
||||
|
||||
public:
|
||||
void GetNetworkAddresses(NetAddr &self, NetAddr &peer);
|
||||
|
||||
|
||||
@@ -44,6 +44,22 @@ interface nsISSLSocketControl : nsISupports {
|
||||
*/
|
||||
readonly attribute ACString negotiatedNPN;
|
||||
|
||||
/* For 0RTT we need to know the alpn protocol selected for the last tls
|
||||
* session. This function will return a value if applicable or an error
|
||||
* NS_ERROR_NOT_AVAILABLE.
|
||||
*/
|
||||
ACString getAlpnEarlySelection();
|
||||
|
||||
/* If 0RTT handshake was applied and some data has been sent, as soon as
|
||||
* the handshake finishes this attribute will be set to appropriate value.
|
||||
*/
|
||||
readonly attribute bool earlyDataAccepted;
|
||||
|
||||
/* When 0RTT is performed, PR_Write will not drive the handshake forward.
|
||||
* It must be forced by calling this function.
|
||||
*/
|
||||
void driveHandshake();
|
||||
|
||||
/* Determine if a potential SSL connection to hostname:port with
|
||||
* a desired NPN negotiated protocol of npnProtocol can use the socket
|
||||
* associated with this object instead of making a new one.
|
||||
|
||||
@@ -887,6 +887,7 @@ PreliminaryHandshakeDone(PRFileDesc* fd)
|
||||
SSLChannelInfo channelInfo;
|
||||
if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) == SECSuccess) {
|
||||
infoObject->SetSSLVersionUsed(channelInfo.protocolVersion);
|
||||
infoObject->SetEarlyDataAccepted(channelInfo.earlyDataAccepted);
|
||||
|
||||
SSLCipherSuiteInfo cipherInfo;
|
||||
if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
|
||||
|
||||
@@ -726,6 +726,7 @@ static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
|
||||
static const bool FALSE_START_ENABLED_DEFAULT = true;
|
||||
static const bool NPN_ENABLED_DEFAULT = true;
|
||||
static const bool ALPN_ENABLED_DEFAULT = false;
|
||||
static const bool ENABLED_0RTT_DATA_DEFAULT = false;
|
||||
|
||||
static void
|
||||
ConfigureTLSSessionIdentifiers()
|
||||
@@ -1086,6 +1087,10 @@ nsNSSComponent::InitializeNSS()
|
||||
Preferences::GetBool("security.ssl.enable_alpn",
|
||||
ALPN_ENABLED_DEFAULT));
|
||||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
|
||||
Preferences::GetBool("security.tls.enable_0rtt_data",
|
||||
ENABLED_0RTT_DATA_DEFAULT));
|
||||
|
||||
if (NS_FAILED(InitializeCipherSuite())) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("Unable to initialize cipher suite settings\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
@@ -1300,6 +1305,10 @@ nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
SSL_OptionSetDefault(SSL_ENABLE_ALPN,
|
||||
Preferences::GetBool("security.ssl.enable_alpn",
|
||||
ALPN_ENABLED_DEFAULT));
|
||||
} else if (prefName.EqualsLiteral("security.tls.enable_0rtt_data")) {
|
||||
SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
|
||||
Preferences::GetBool("security.tls.enable_0rtt_data",
|
||||
ENABLED_0RTT_DATA_DEFAULT));
|
||||
} else if (prefName.Equals("security.ssl.disable_session_identifiers")) {
|
||||
ConfigureTLSSessionIdentifiers();
|
||||
} else if (prefName.EqualsLiteral("security.OCSP.enabled") ||
|
||||
|
||||
@@ -61,6 +61,8 @@ using namespace mozilla::psm;
|
||||
|
||||
namespace {
|
||||
|
||||
#define MAX_ALPN_LENGTH 255
|
||||
|
||||
void
|
||||
getSiteKey(const nsACString& hostName, uint16_t port,
|
||||
/*out*/ nsCSubstring& key)
|
||||
@@ -93,6 +95,7 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
|
||||
mRememberClientAuthCertificate(false),
|
||||
mPreliminaryHandshakeDone(false),
|
||||
mNPNCompleted(false),
|
||||
mEarlyDataAccepted(false),
|
||||
mFalseStartCallbackCalled(false),
|
||||
mFalseStarted(false),
|
||||
mIsFullHandshake(false),
|
||||
@@ -313,6 +316,71 @@ nsNSSSocketInfo::GetNegotiatedNPN(nsACString& aNegotiatedNPN)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetAlpnEarlySelection(nsACString& aAlpnSelected)
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown() || isPK11LoggedOut()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
SSLNextProtoState alpnState;
|
||||
unsigned char chosenAlpn[MAX_ALPN_LENGTH];
|
||||
unsigned int chosenAlpnLen;
|
||||
SECStatus rv = SSL_GetNextProto(mFd, &alpnState, chosenAlpn, &chosenAlpnLen,
|
||||
AssertedCast<unsigned int>(ArrayLength(chosenAlpn)));
|
||||
|
||||
if (rv != SECSuccess || alpnState != SSL_NEXT_PROTO_EARLY_VALUE ||
|
||||
chosenAlpnLen == 0) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
aAlpnSelected.Assign(BitwiseCast<char*, unsigned char*>(chosenAlpn),
|
||||
chosenAlpnLen);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetEarlyDataAccepted(bool* aAccepted)
|
||||
{
|
||||
*aAccepted = mEarlyDataAccepted;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsNSSSocketInfo::SetEarlyDataAccepted(bool aAccepted)
|
||||
{
|
||||
mEarlyDataAccepted = aAccepted;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::DriveHandshake()
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown() || isPK11LoggedOut()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (!mFd) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRErrorCode errorCode = GetErrorCode();
|
||||
if (errorCode) {
|
||||
return GetXPCOMFromNSSError(errorCode);
|
||||
}
|
||||
|
||||
SECStatus rv = SSL_ForceHandshake(mFd);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
errorCode = PR_GetError();
|
||||
if (errorCode == PR_WOULD_BLOCK_ERROR) {
|
||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
SetCanceled(errorCode, PlainErrorMessage);
|
||||
return GetXPCOMFromNSSError(errorCode);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::IsAcceptableForHost(const nsACString& hostname, bool* _retval)
|
||||
{
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
const nsNSSShutDownPreventionLock& proofOfLock);
|
||||
|
||||
void SetNegotiatedNPN(const char* value, uint32_t length);
|
||||
void SetEarlyDataAccepted(bool aAccepted);
|
||||
|
||||
void SetHandshakeCompleted();
|
||||
void NoteTimeUntilReady();
|
||||
@@ -139,6 +140,7 @@ private:
|
||||
|
||||
nsCString mNegotiatedNPN;
|
||||
bool mNPNCompleted;
|
||||
bool mEarlyDataAccepted;
|
||||
bool mFalseStartCallbackCalled;
|
||||
bool mFalseStarted;
|
||||
bool mIsFullHandshake;
|
||||
|
||||
@@ -313,13 +313,15 @@
|
||||
ERROR(NS_NET_STATUS_WRITING, FAILURE(9)),
|
||||
|
||||
/* nsISocketTransport */
|
||||
ERROR(NS_NET_STATUS_RESOLVING_HOST, FAILURE(3)),
|
||||
ERROR(NS_NET_STATUS_RESOLVED_HOST, FAILURE(11)),
|
||||
ERROR(NS_NET_STATUS_CONNECTING_TO, FAILURE(7)),
|
||||
ERROR(NS_NET_STATUS_CONNECTED_TO, FAILURE(4)),
|
||||
ERROR(NS_NET_STATUS_SENDING_TO, FAILURE(5)),
|
||||
ERROR(NS_NET_STATUS_WAITING_FOR, FAILURE(10)),
|
||||
ERROR(NS_NET_STATUS_RECEIVING_FROM, FAILURE(6)),
|
||||
ERROR(NS_NET_STATUS_RESOLVING_HOST, FAILURE(3)),
|
||||
ERROR(NS_NET_STATUS_RESOLVED_HOST, FAILURE(11)),
|
||||
ERROR(NS_NET_STATUS_CONNECTING_TO, FAILURE(7)),
|
||||
ERROR(NS_NET_STATUS_CONNECTED_TO, FAILURE(4)),
|
||||
ERROR(NS_NET_STATUS_TLS_HANDSHAKE_STARTING, FAILURE(12)),
|
||||
ERROR(NS_NET_STATUS_TLS_HANDSHAKE_ENDED, FAILURE(13)),
|
||||
ERROR(NS_NET_STATUS_SENDING_TO, FAILURE(5)),
|
||||
ERROR(NS_NET_STATUS_WAITING_FOR, FAILURE(10)),
|
||||
ERROR(NS_NET_STATUS_RECEIVING_FROM, FAILURE(6)),
|
||||
|
||||
/* nsIInterceptedChannel */
|
||||
/* Generic error for non-specific failures during service worker interception */
|
||||
|
||||
Reference in New Issue
Block a user