Bug 1650388 - Cache and use resumption tokens. r=kershaw

Differential Revision: https://phabricator.services.mozilla.com/D87230
This commit is contained in:
Dragana Damjanovic 2020-09-10 20:48:56 +00:00
Родитель 3b0aed3acd
Коммит 368bae162a
7 изменённых файлов: 114 добавлений и 22 удалений

Просмотреть файл

@ -119,6 +119,26 @@ SSLTokensCache::~SSLTokensCache() { LOG(("SSLTokensCache::~SSLTokensCache")); }
nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen,
nsITransportSecurityInfo* aSecInfo) {
PRUint32 expirationTime;
SSLResumptionTokenInfo tokenInfo;
if (SSL_GetResumptionTokenInfo(aToken, aTokenLen, &tokenInfo,
sizeof(tokenInfo)) != SECSuccess) {
LOG((" cannot get expiration time from the token, NSS error %d",
PORT_GetError()));
return NS_ERROR_FAILURE;
}
expirationTime = tokenInfo.expirationTime;
SSL_DestroyResumptionTokenInfo(&tokenInfo);
return Put(aKey, aToken, aTokenLen, aSecInfo, expirationTime);
}
// static
nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen,
nsITransportSecurityInfo* aSecInfo,
PRUint32 aExpirationTime) {
StaticMutexAutoLock lock(sLock);
LOG(("SSLTokensCache::Put [key=%s, tokenLen=%u]",
@ -133,17 +153,6 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
return NS_ERROR_FAILURE;
}
PRUint32 expirationTime;
SSLResumptionTokenInfo tokenInfo;
if (SSL_GetResumptionTokenInfo(aToken, aTokenLen, &tokenInfo,
sizeof(tokenInfo)) != SECSuccess) {
LOG((" cannot get expiration time from the token, NSS error %d",
PORT_GetError()));
return NS_ERROR_FAILURE;
}
expirationTime = tokenInfo.expirationTime;
SSL_DestroyResumptionTokenInfo(&tokenInfo);
nsCOMPtr<nsIX509Cert> cert;
aSecInfo->GetServerCert(getter_AddRefs(cert));
if (!cert) {
@ -208,7 +217,7 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
rec->Reset();
}
rec->mExpirationTime = expirationTime;
rec->mExpirationTime = aExpirationTime;
MOZ_ASSERT(rec->mToken.IsEmpty());
rec->mToken.AppendElements(aToken, aTokenLen);

Просмотреть файл

@ -41,6 +41,9 @@ class SSLTokensCache : public nsIMemoryReporter {
static nsresult Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen, nsITransportSecurityInfo* aSecInfo);
static nsresult Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen, nsITransportSecurityInfo* aSecInfo,
PRUint32 aExpirationTime);
static nsresult Get(const nsACString& aKey, nsTArray<uint8_t>& aToken);
static bool GetSessionCacheInfo(const nsACString& aKey,
SessionCacheInfo& aResult);

Просмотреть файл

@ -20,6 +20,7 @@
#include "nsThreadUtils.h"
#include "QuicSocketControl.h"
#include "SSLServerCertVerification.h"
#include "SSLTokensCache.h"
#include "HttpConnectionUDP.h"
#include "sslerr.h"
@ -141,10 +142,22 @@ nsresult Http3Session::Init(const nsACString& aOrigin,
gHttpHandler->DefaultQpackTableSize(),
gHttpHandler->DefaultHttp3MaxBlockedStreams(), this));
return NeqoHttp3Conn::Init(aOrigin, aAlpnToken, selfAddrStr, peerAddrStr,
gHttpHandler->DefaultQpackTableSize(),
gHttpHandler->DefaultHttp3MaxBlockedStreams(),
getter_AddRefs(mHttp3Connection));
nsresult rv = NeqoHttp3Conn::Init(aOrigin, aAlpnToken, selfAddrStr, peerAddrStr,
gHttpHandler->DefaultQpackTableSize(),
gHttpHandler->DefaultHttp3MaxBlockedStreams(),
getter_AddRefs(mHttp3Connection));
if (NS_FAILED(rv)) {
return rv;
}
nsAutoCString peerId;
mSocketControl->GetPeerId(peerId);
nsTArray<uint8_t> token;
if (NS_SUCCEEDED(SSLTokensCache::Get(peerId, token))) {
LOG(("Found a resumption token in the cache."));
mHttp3Connection->SetResumptionToken(token);
}
return NS_OK;
}
// Shutdown the http3session and close all transactions.
@ -405,12 +418,27 @@ nsresult Http3Session::ProcessEvents(uint32_t count) {
}
break;
case Http3Event::Tag::ConnectionConnected:
LOG(("Http3Session::ProcessEvents - ConnectionConnected"));
mState = CONNECTED;
SetSecInfo();
mSocketControl->HandshakeCompleted();
gHttpHandler->ConnMgr()->ReportHttp3Connection(mSegmentReaderWriter);
MaybeResumeSend();
{
LOG(("Http3Session::ProcessEvents - ConnectionConnected"));
mState = CONNECTED;
SetSecInfo();
mSocketControl->HandshakeCompleted();
nsTArray<uint8_t> token;
mHttp3Connection->GetResumptionToken(token);
if (!token.IsEmpty()) {
LOG(("Got a resumption token"));
nsAutoCString peerId;
mSocketControl->GetPeerId(peerId);
if (NS_FAILED(
// Bug 1660080 tto get the proper expiration time for a token.
SSLTokensCache::Put(peerId, token.Elements(), token.Length(), mSocketControl, 1))) {
LOG(("Adding resumption token failed"));
}
}
gHttpHandler->ConnMgr()->ReportHttp3Connection(mSegmentReaderWriter);
MaybeResumeSend();
}
break;
case Http3Event::Tag::GoawayReceived:
LOG(("Http3Session::ProcessEvents - GoawayReceived"));

Просмотреть файл

@ -8,6 +8,7 @@
#include "Http3Session.h"
#include "SharedCertVerifier.h"
#include "nsISocketProvider.h"
#include "nsIWebProgressListener.h"
#include "nsNSSComponent.h"
#include "nsWeakReference.h"
@ -103,5 +104,33 @@ void QuicSocketControl::SetInfo(uint16_t aCipherSuite,
}
}
NS_IMETHODIMP QuicSocketControl::GetPeerId(nsACString& aResult) {
if (!mPeerId.IsEmpty()) {
aResult.Assign(mPeerId);
return NS_OK;
}
if (mProviderFlags &
nsISocketProvider::ANONYMOUS_CONNECT) { // See bug 466080
mPeerId.AppendLiteral("anon:");
}
if (mProviderFlags & nsISocketProvider::NO_PERMANENT_STORAGE) {
mPeerId.AppendLiteral("private:");
}
if (mProviderFlags & nsISocketProvider::BE_CONSERVATIVE) {
mPeerId.AppendLiteral("beConservative:");
}
mPeerId.Append(GetHostName());
mPeerId.Append(':');
mPeerId.AppendInt(GetPort());
nsAutoCString suffix;
GetOriginAttributes().CreateSuffix(suffix);
mPeerId.Append(suffix);
aResult.Assign(mPeerId);
return NS_OK;
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -43,11 +43,14 @@ class QuicSocketControl final : public CommonSocketControl {
void HandshakeCompleted();
void SetCertVerificationResult(PRErrorCode errorCode) override;
NS_IMETHOD GetPeerId(nsACString& aResult) override;
private:
~QuicSocketControl() = default;
// For Authentication done callback.
nsWeakPtr mHttp3Session;
nsCString mPeerId;
};
NS_DEFINE_STATIC_IID_ACCESSOR(QuicSocketControl, NS_QUICSOCKETCONTROL_IID)

Просмотреть файл

@ -80,6 +80,14 @@ class NeqoHttp3Conn final {
neqo_http3conn_reset_stream(this, aStreamId, aError);
}
void GetResumptionToken(nsTArray<uint8_t>& aToken) {
neqo_http3conn_resumption_token(this, &aToken);
}
void SetResumptionToken(nsTArray<uint8_t>& aToken) {
neqo_http3conn_set_resumption_token(this, &aToken);
}
nsrefcnt AddRef() { return neqo_http3conn_addref(this); }
nsrefcnt Release() { return neqo_http3conn_release(this); }

Просмотреть файл

@ -678,3 +678,15 @@ pub extern "C" fn neqo_http3conn_peer_certificate_info(
pub extern "C" fn neqo_http3conn_authenticated(conn: &mut NeqoHttp3Conn, error: PRErrorCode) {
conn.conn.authenticated(error.into(), Instant::now());
}
#[no_mangle]
pub extern "C" fn neqo_http3conn_resumption_token(conn: &mut NeqoHttp3Conn, token: &mut ThinVec<u8>,) {
if let Some(t) = conn.conn.resumption_token() {
token.extend_from_slice(&t);
}
}
#[no_mangle]
pub extern "C" fn neqo_http3conn_set_resumption_token(conn: &mut NeqoHttp3Conn, token: &mut ThinVec<u8>,) {
let _ = conn.conn.set_resumption_token(Instant::now(), token);
}