Skip to content

Commit

Permalink
Bug 1652677 - P2: Implement necko part of echconfig r=dragana
Browse files Browse the repository at this point in the history
  • Loading branch information
KershawChang committed Sep 25, 2020
1 parent 0ec383b commit 93e628b
Show file tree
Hide file tree
Showing 19 changed files with 98 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ class FakeSocketTransportProvider : public nsISocketTransport {
MOZ_ASSERT(false);
return NS_OK;
}
NS_IMETHOD GetEsniUsed(bool* aEsniUsed) override {
NS_IMETHOD GetEchConfigUsed(bool* aEchConfigUsed) override {
MOZ_ASSERT(false);
return NS_OK;
}
NS_IMETHOD SetEchConfig(const nsACString& aEchConfig) override {
MOZ_ASSERT(false);
return NS_OK;
}
Expand Down
4 changes: 2 additions & 2 deletions netwerk/base/FuzzySecurityInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,10 @@ FuzzySecurityInfo::SetNPNList(nsTArray<nsCString>& protocolArray) {
}

NS_IMETHODIMP
FuzzySecurityInfo::GetEsniTxt(nsACString& aEsniTxt) { return NS_OK; }
FuzzySecurityInfo::GetEchConfig(nsACString& aEchConfig) { return NS_OK; }

NS_IMETHODIMP
FuzzySecurityInfo::SetEsniTxt(const nsACString& aEsniTxt) {
FuzzySecurityInfo::SetEchConfig(const nsACString& aEchConfig) {
MOZ_CRASH("Unused");
return NS_OK;
}
Expand Down
10 changes: 6 additions & 4 deletions netwerk/base/nsISocketTransport.idl
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,9 @@ interface nsISocketTransport : nsITransport

/**
* If we know that a server speaks only tls <1.3 there is no need to try
* to use esni and query dns for esni keys.
* to use ech and query dns for echconfig.
*/
const unsigned long DONT_TRY_ESNI = (1 << 10);
const unsigned long DONT_TRY_ECH = (1 << 10);

/**
* These two bits encode the TRR mode of the request.
Expand Down Expand Up @@ -326,10 +326,12 @@ interface nsISocketTransport : nsITransport
readonly attribute boolean resetIPFamilyPreference;

/**
* This attribute holds information whether esni has been used.
* This attribute holds information whether echconfig has been used.
* The value is set after PR_Connect is called.
*/
readonly attribute boolean esniUsed;
readonly attribute boolean echConfigUsed;

void setEchConfig(in ACString echConfig);

/**
* IP address resolved using TRR.
Expand Down
125 changes: 24 additions & 101 deletions netwerk/base/nsSocketTransport2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,10 +710,7 @@ nsSocketTransport::nsSocketTransport()
mInputClosed(true),
mOutputClosed(true),
mResolving(false),
mDNSLookupStatus(NS_OK),
mDNSARequestFinished(0),
mEsniQueried(false),
mEsniUsed(false),
mEchConfigUsed(false),
mResolvedByTRR(false),
mNetAddrIsSet(false),
mSelfAddrIsSet(false),
Expand Down Expand Up @@ -1072,36 +1069,6 @@ nsresult nsSocketTransport::ResolveHost() {
dns->AsyncResolveNative(SocketHost(), nsIDNSService::RESOLVE_TYPE_DEFAULT,
dnsFlags, nullptr, this, mSocketTransportService,
mOriginAttributes, getter_AddRefs(mDNSRequest));
mEsniQueried = false;
if (mSocketTransportService->IsEsniEnabled() && NS_SUCCEEDED(rv) &&
!(mConnectionFlags & (DONT_TRY_ESNI | BE_CONSERVATIVE))) {
bool isSSL = false;
for (unsigned int i = 0; i < mTypes.Length(); ++i) {
if (mTypes[i].EqualsLiteral("ssl")) {
isSSL = true;
break;
}
}
if (isSSL) {
SOCKET_LOG((" look for esni txt record"));
nsAutoCString esniHost;
esniHost.Append("_esni.");
// This might end up being the SocketHost
// see https://github.com/ekr/draft-rescorla-tls-esni/issues/61
esniHost.Append(SocketHost());
rv = dns->AsyncResolveNative(esniHost, nsIDNSService::RESOLVE_TYPE_TXT,
dnsFlags, nullptr, this,
mSocketTransportService, mOriginAttributes,
getter_AddRefs(mDNSTxtRequest));
if (NS_FAILED(rv)) {
SOCKET_LOG((" dns request by type failed."));
mDNSTxtRequest = nullptr;
rv = NS_OK;
} else {
mEsniQueried = true;
}
}
}

if (NS_SUCCEEDED(rv)) {
SOCKET_LOG((" advancing to STATE_RESOLVING\n"));
Expand Down Expand Up @@ -1558,15 +1525,16 @@ nsresult nsSocketTransport::InitiateSocket() {
}
#endif

if (!mDNSRecordTxt.IsEmpty() && !mUsingQuic && mSecInfo) {
if (!mEchConfig.IsEmpty() &&
!(mConnectionFlags & (DONT_TRY_ECH | BE_CONSERVATIVE)) && mSecInfo) {
nsCOMPtr<nsISSLSocketControl> secCtrl = do_QueryInterface(mSecInfo);
if (secCtrl) {
SOCKET_LOG(("nsSocketTransport::InitiateSocket set esni keys."));
rv = secCtrl->SetEsniTxt(mDNSRecordTxt);
SOCKET_LOG(("nsSocketTransport::InitiateSocket set echconfig."));
rv = secCtrl->SetEchConfig(mEchConfig);
if (NS_FAILED(rv)) {
return rv;
}
mEsniUsed = true;
mEchConfigUsed = true;
}
}

Expand Down Expand Up @@ -2181,14 +2149,12 @@ void nsSocketTransport::OnSocketEvent(uint32_t type, nsresult status,
break;

case MSG_DNS_LOOKUP_COMPLETE:
if (mDNSRequest ||
mDNSTxtRequest) { // only send this if we actually resolved anything
if (mDNSRequest) { // only send this if we actually resolved anything
SendStatus(NS_NET_STATUS_RESOLVED_HOST);
}

SOCKET_LOG((" MSG_DNS_LOOKUP_COMPLETE\n"));
mDNSRequest = nullptr;
mDNSTxtRequest = nullptr;
if (mDNSRecord) {
mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr);
mDNSRecord->IsTRR(&mResolvedByTRR);
Expand Down Expand Up @@ -2461,11 +2427,6 @@ void nsSocketTransport::OnSocketDetached(PRFileDesc* fd) {
mDNSRequest = nullptr;
}

if (mDNSTxtRequest) {
mDNSTxtRequest->Cancel(NS_ERROR_ABORT);
mDNSTxtRequest = nullptr;
}

//
// notify input/output streams
//
Expand Down Expand Up @@ -2990,65 +2951,21 @@ nsSocketTransport::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
".",
this, static_cast<uint32_t>(status)));

if (request == mDNSTxtRequest) {
if (NS_SUCCEEDED(status)) {
nsCOMPtr<nsIDNSTXTRecord> txtResponse = do_QueryInterface(rec);
txtResponse->GetRecordsAsOneString(mDNSRecordTxt);
mDNSRecordTxt.Trim(" ");
}
Telemetry::Accumulate(Telemetry::ESNI_KEYS_RECORDS_FOUND,
NS_SUCCEEDED(status));
// flag host lookup complete for the benefit of the ResolveHost method.
if (!mDNSRequest) {
mResolving = false;
MOZ_ASSERT(mDNSARequestFinished);
Telemetry::Accumulate(
Telemetry::ESNI_KEYS_RECORD_FETCH_DELAYS,
PR_IntervalToMilliseconds(PR_IntervalNow() - mDNSARequestFinished));

nsresult rv =
PostEvent(MSG_DNS_LOOKUP_COMPLETE, mDNSLookupStatus, nullptr);

// if posting a message fails, then we should assume that the socket
// transport has been shutdown. this should never happen! if it does
// it means that the socket transport service was shutdown before the
// DNS service.
if (NS_FAILED(rv)) {
NS_WARNING("unable to post DNS lookup complete message");
}
} else {
mDNSTxtRequest = nullptr;
}
return NS_OK;
}

if (NS_FAILED(status) && mDNSTxtRequest) {
mDNSTxtRequest->Cancel(NS_ERROR_ABORT);
} else if (NS_SUCCEEDED(status)) {
if (NS_SUCCEEDED(status)) {
mDNSRecord = do_QueryInterface(rec);
MOZ_ASSERT(mDNSRecord);
}

// flag host lookup complete for the benefit of the ResolveHost method.
if (!mDNSTxtRequest) {
if (mEsniQueried) {
Telemetry::Accumulate(Telemetry::ESNI_KEYS_RECORD_FETCH_DELAYS, 0);
}
mResolving = false;
nsresult rv = PostEvent(MSG_DNS_LOOKUP_COMPLETE, status, nullptr);
mResolving = false;
nsresult rv = PostEvent(MSG_DNS_LOOKUP_COMPLETE, status, nullptr);

// if posting a message fails, then we should assume that the socket
// transport has been shutdown. this should never happen! if it does
// it means that the socket transport service was shutdown before the
// DNS service.
if (NS_FAILED(rv)) {
NS_WARNING("unable to post DNS lookup complete message");
}
} else {
mDNSLookupStatus =
status; // remember the status to send it when esni lookup is ready.
mDNSRequest = nullptr;
mDNSARequestFinished = PR_IntervalNow();
// if posting a message fails, then we should assume that the socket
// transport has been shutdown. this should never happen! if it does
// it means that the socket transport service was shutdown before the
// DNS service.
if (NS_FAILED(rv)) {
NS_WARNING("unable to post DNS lookup complete message");
}

return NS_OK;
Expand Down Expand Up @@ -3623,8 +3540,14 @@ nsSocketTransport::GetResetIPFamilyPreference(bool* aReset) {
}

NS_IMETHODIMP
nsSocketTransport::GetEsniUsed(bool* aEsniUsed) {
*aEsniUsed = mEsniUsed;
nsSocketTransport::GetEchConfigUsed(bool* aEchConfigUsed) {
*aEchConfigUsed = mEchConfigUsed;
return NS_OK;
}

NS_IMETHODIMP
nsSocketTransport::SetEchConfig(const nsACString& aEchConfig) {
mEchConfig = aEchConfig;
return NS_OK;
}

Expand Down
8 changes: 2 additions & 6 deletions netwerk/base/nsSocketTransport2.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,8 @@ class nsSocketTransport final : public nsASocketHandler,
nsCOMPtr<nsICancelable> mDNSRequest;
nsCOMPtr<nsIDNSAddrRecord> mDNSRecord;

nsresult mDNSLookupStatus;
PRIntervalTime mDNSARequestFinished;
nsCOMPtr<nsICancelable> mDNSTxtRequest;
nsCString mDNSRecordTxt;
bool mEsniQueried;
bool mEsniUsed;
nsCString mEchConfig;
bool mEchConfigUsed;
bool mResolvedByTRR;

// mNetAddr/mSelfAddr is valid from GetPeerAddr()/GetSelfAddr() once we have
Expand Down
5 changes: 5 additions & 0 deletions netwerk/dns/HTTPSSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,11 @@ Maybe<uint16_t> SVCBRecord::GetPort() { return mPort; }

Maybe<nsCString> SVCBRecord::GetAlpn() { return mAlpn; }

NS_IMETHODIMP SVCBRecord::GetEchConfig(nsACString& aEchConfig) {
aEchConfig = mData.mEchConfig;
return NS_OK;
}

NS_IMETHODIMP SVCBRecord::GetValues(nsTArray<RefPtr<nsISVCParam>>& aValues) {
for (const auto& v : mData.mSvcFieldValue) {
RefPtr<nsISVCParam> param = new SvcParam(v.mValue);
Expand Down
1 change: 1 addition & 0 deletions netwerk/dns/HTTPSSVC.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct SVCB {
void GetIPHints(CopyableTArray<mozilla::net::NetAddr>& aAddresses) const;
uint16_t mSvcFieldPriority = 0;
nsCString mSvcDomainName;
nsCString mEchConfig;
bool mHasIPHints = false;
bool mHasEchConfig = false;
CopyableTArray<SvcFieldValue> mSvcFieldValue;
Expand Down
1 change: 1 addition & 0 deletions netwerk/dns/TRR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,7 @@ nsresult TRR::DohDecode(nsCString& aHost) {
}
if (value.mValue.is<SvcParamEchConfig>()) {
parsed.mHasEchConfig = true;
parsed.mEchConfig = value.mValue.as<SvcParamEchConfig>().mValue;
}
parsed.mSvcFieldValue.AppendElement(value);
}
Expand Down
1 change: 1 addition & 0 deletions netwerk/dns/nsIDNSByTypeRecord.idl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ interface nsISVCBRecord : nsISupports {
readonly attribute ACString name;
[noscript, nostdcall, notxpcom] readonly attribute MaybePort port;
[noscript, nostdcall, notxpcom] readonly attribute MaybeAlpn alpn;
readonly attribute ACString echConfig;
readonly attribute bool hasIPHintAddress;
readonly attribute Array<nsISVCParam> values;
};
Expand Down
1 change: 1 addition & 0 deletions netwerk/ipc/NeckoChannelParams.ipdlh
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ struct HttpConnectionInfoCloneArgs
nsCString topWindowOrigin;
bool isHttp3;
bool hasIPHintAddress;
nsCString echConfig;
ProxyInfoCloneArgs[] proxyInfo;
};

Expand Down
12 changes: 10 additions & 2 deletions netwerk/protocol/http/TunnelUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2060,9 +2060,17 @@ SocketTransportShim::GetFirstRetryError(nsresult* aFirstRetryError) {
}

NS_IMETHODIMP
SocketTransportShim::GetEsniUsed(bool* aEsniUsed) {
SocketTransportShim::GetEchConfigUsed(bool* aEchConfigUsed) {
if (mIsWebsocket) {
LOG3(("WARNING: SocketTransportShim::GetEsniUsed %p", this));
LOG3(("WARNING: SocketTransportShim::GetEchConfigUsed %p", this));
}
return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
SocketTransportShim::SetEchConfig(const nsACString& aEchConfig) {
if (mIsWebsocket) {
LOG3(("WARNING: SocketTransportShim::SetEchConfig %p", this));
}
return NS_ERROR_NOT_IMPLEMENTED;
}
Expand Down
17 changes: 0 additions & 17 deletions netwerk/protocol/http/nsHttpConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,6 @@ bool nsHttpConnection::EnsureNPNComplete(nsresult& aOut0RTTWriteHandshakeValue,
nsCOMPtr<nsITransportSecurityInfo> info;
nsCOMPtr<nsISSLSocketControl> ssl;
nsAutoCString negotiatedNPN;
// This is neede for telemetry
bool handshakeSucceeded = false;

GetSecurityInfo(getter_AddRefs(securityInfo));
if (!securityInfo) {
Expand Down Expand Up @@ -561,8 +559,6 @@ bool nsHttpConnection::EnsureNPNComplete(nsresult& aOut0RTTWriteHandshakeValue,
this, mConnInfo->HashKey().get(), negotiatedNPN.get(),
mTLSFilter ? " [Double Tunnel]" : ""));

handshakeSucceeded = true;

int16_t tlsVersion;
ssl->GetSSLVersionUsed(&tlsVersion);
mConnInfo->SetLessThanTls13(
Expand Down Expand Up @@ -701,19 +697,6 @@ bool nsHttpConnection::EnsureNPNComplete(nsresult& aOut0RTTWriteHandshakeValue,
mDid0RTTSpdy = false;
}

if (ssl) {
// Telemetry for tls failure rate with and without esni;
bool esni = false;
rv = mSocketTransport->GetEsniUsed(&esni);
if (NS_SUCCEEDED(rv)) {
Telemetry::Accumulate(
Telemetry::ESNI_NOESNI_TLS_SUCCESS_RATE,
(esni)
? ((handshakeSucceeded) ? ESNI_SUCCESSFUL : ESNI_FAILED)
: ((handshakeSucceeded) ? NO_ESNI_SUCCESSFUL : NO_ESNI_FAILED));
}
}

if (rv == psm::GetXPCOMFromNSSError(
mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED)) {
gSocketTransportService->SetNotTrustedMitmDetected();
Expand Down
Loading

0 comments on commit 93e628b

Please sign in to comment.