mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 839310: Expand TLS intolerance logic to work for versions beyond TLS 1.0, r=keeler, r=wtc
--HG-- extra : rebase_source : b83a610d08abb428f0f6894fa935712f820ddfe8
This commit is contained in:
parent
440791afd0
commit
03dc3ced83
@ -299,7 +299,7 @@ CertErrorRunnable::CheckCertOverrides()
|
|||||||
mInfoObject->GetPort(&port);
|
mInfoObject->GetPort(&port);
|
||||||
|
|
||||||
nsCString hostWithPortString;
|
nsCString hostWithPortString;
|
||||||
hostWithPortString.AppendASCII(mInfoObject->GetHostName());
|
hostWithPortString.AppendASCII(mInfoObject->GetHostNameRaw());
|
||||||
hostWithPortString.AppendLiteral(":");
|
hostWithPortString.AppendLiteral(":");
|
||||||
hostWithPortString.AppendInt(port);
|
hostWithPortString.AppendInt(port);
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ CertErrorRunnable::CheckCertOverrides()
|
|||||||
= do_GetService(NS_SSSERVICE_CONTRACTID, &nsrv);
|
= do_GetService(NS_SSSERVICE_CONTRACTID, &nsrv);
|
||||||
if (NS_SUCCEEDED(nsrv)) {
|
if (NS_SUCCEEDED(nsrv)) {
|
||||||
nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HSTS,
|
nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HSTS,
|
||||||
mInfoObject->GetHostName(),
|
mInfoObject->GetHostNameRaw(),
|
||||||
mProviderFlags,
|
mProviderFlags,
|
||||||
&strictTransportSecurityEnabled);
|
&strictTransportSecurityEnabled);
|
||||||
}
|
}
|
||||||
@ -413,7 +413,7 @@ CertErrorRunnable::CheckCertOverrides()
|
|||||||
OverridableCertErrorMessage);
|
OverridableCertErrorMessage);
|
||||||
|
|
||||||
LogInvalidCertError(mInfoObject,
|
LogInvalidCertError(mInfoObject,
|
||||||
nsDependentCString(mInfoObject->GetHostName()),
|
mInfoObject->GetHostName(),
|
||||||
hostWithPortString,
|
hostWithPortString,
|
||||||
port,
|
port,
|
||||||
result->mErrorCode,
|
result->mErrorCode,
|
||||||
@ -510,7 +510,7 @@ CreateCertErrorRunnable(PRErrorCode defaultErrorCodeToReport,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the name field against the desired hostname.
|
// Check the name field against the desired hostname.
|
||||||
if (CERT_VerifyCertName(cert, infoObject->GetHostName()) != SECSuccess) {
|
if (CERT_VerifyCertName(cert, infoObject->GetHostNameRaw()) != SECSuccess) {
|
||||||
collected_errors |= nsICertOverrideService::ERROR_MISMATCH;
|
collected_errors |= nsICertOverrideService::ERROR_MISMATCH;
|
||||||
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
|
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
|
||||||
}
|
}
|
||||||
@ -883,7 +883,7 @@ AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert,
|
|||||||
|
|
||||||
CERTCertList *verifyCertChain = nullptr;
|
CERTCertList *verifyCertChain = nullptr;
|
||||||
SECOidTag evOidPolicy;
|
SECOidTag evOidPolicy;
|
||||||
rv = PSM_SSL_PKIX_AuthCertificate(cert, infoObject, infoObject->GetHostName(),
|
rv = PSM_SSL_PKIX_AuthCertificate(cert, infoObject, infoObject->GetHostNameRaw(),
|
||||||
&verifyCertChain, &evOidPolicy);
|
&verifyCertChain, &evOidPolicy);
|
||||||
|
|
||||||
// We want to remember the CA certs in the temp db, so that the application can find the
|
// We want to remember the CA certs in the temp db, so that the application can find the
|
||||||
|
@ -49,9 +49,9 @@ public:
|
|||||||
nsresult SetSecurityState(uint32_t aState);
|
nsresult SetSecurityState(uint32_t aState);
|
||||||
nsresult SetShortSecurityDescription(const PRUnichar *aText);
|
nsresult SetShortSecurityDescription(const PRUnichar *aText);
|
||||||
|
|
||||||
const char * GetHostName() const {
|
const nsACString & GetHostName() const { return mHostName; }
|
||||||
return mHostName.get();
|
const char * GetHostNameRaw() const { return mHostName.get(); }
|
||||||
}
|
|
||||||
nsresult GetHostName(char **aHostName);
|
nsresult GetHostName(char **aHostName);
|
||||||
nsresult SetHostName(const char *aHostName);
|
nsresult SetHostName(const char *aHostName);
|
||||||
|
|
||||||
|
@ -1032,16 +1032,25 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
|||||||
// is absent at handshake time we have a resumed session. Check this before
|
// is absent at handshake time we have a resumed session. Check this before
|
||||||
// PreliminaryHandshakeDone() because that function also sets that flag.
|
// PreliminaryHandshakeDone() because that function also sets that flag.
|
||||||
bool isResumedSession = !(infoObject->GetFirstServerHelloReceived());
|
bool isResumedSession = !(infoObject->GetFirstServerHelloReceived());
|
||||||
|
|
||||||
// Do the bookkeeping that needs to be done after the
|
// Do the bookkeeping that needs to be done after the
|
||||||
// server's ServerHello...ServerHelloDone have been processed, but that doesn't
|
// server's ServerHello...ServerHelloDone have been processed, but that doesn't
|
||||||
// need the handshake to be completed.
|
// need the handshake to be completed.
|
||||||
PreliminaryHandshakeDone(fd);
|
PreliminaryHandshakeDone(fd);
|
||||||
|
|
||||||
// If the handshake completed, then we know the site is TLS tolerant (if this
|
nsSSLIOLayerHelpers& ioLayerHelpers
|
||||||
// was a TLS connection).
|
= infoObject->SharedState().IOLayerHelpers();
|
||||||
nsSSLIOLayerHelpers& ioLayerHelpers = infoObject->SharedState().IOLayerHelpers();
|
|
||||||
ioLayerHelpers.rememberTolerantSite(infoObject);
|
SSLVersionRange versions(infoObject->GetTLSVersionRange());
|
||||||
|
|
||||||
|
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
||||||
|
("[%p] HandshakeCallback: succeeded using TLS version range (0x%04x,0x%04x)\n",
|
||||||
|
fd, static_cast<unsigned int>(versions.min),
|
||||||
|
static_cast<unsigned int>(versions.max)));
|
||||||
|
|
||||||
|
// If the handshake completed, then we know the site is TLS tolerant
|
||||||
|
ioLayerHelpers.rememberTolerantAtVersion(infoObject->GetHostName(),
|
||||||
|
infoObject->GetPort(),
|
||||||
|
versions.max);
|
||||||
|
|
||||||
PRBool siteSupportsSafeRenego;
|
PRBool siteSupportsSafeRenego;
|
||||||
rv = SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn,
|
rv = SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn,
|
||||||
|
@ -64,6 +64,21 @@ NSSCleanupAutoPtrClass(void, PR_FREEIF)
|
|||||||
|
|
||||||
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
||||||
|
|
||||||
|
void
|
||||||
|
getSiteKey(const nsACString & hostName, uint16_t port,
|
||||||
|
/*out*/ nsCSubstring & key)
|
||||||
|
{
|
||||||
|
key = hostName;
|
||||||
|
key.AppendASCII(":");
|
||||||
|
key.AppendInt(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getSiteKey(const nsNSSSocketInfo & socketInfo, /*out*/ nsCSubstring & key)
|
||||||
|
{
|
||||||
|
getSiteKey(socketInfo.GetHostName(), socketInfo.GetPort(), key);
|
||||||
|
}
|
||||||
|
|
||||||
/* SSM_UserCertChoice: enum for cert choice info */
|
/* SSM_UserCertChoice: enum for cert choice info */
|
||||||
typedef enum {ASK, AUTO} SSM_UserCertChoice;
|
typedef enum {ASK, AUTO} SSM_UserCertChoice;
|
||||||
|
|
||||||
@ -78,8 +93,6 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
|
|||||||
mCertVerificationState(before_cert_verification),
|
mCertVerificationState(before_cert_verification),
|
||||||
mSharedState(aState),
|
mSharedState(aState),
|
||||||
mForSTARTTLS(false),
|
mForSTARTTLS(false),
|
||||||
mSSL3Enabled(false),
|
|
||||||
mTLSEnabled(false),
|
|
||||||
mHandshakePending(true),
|
mHandshakePending(true),
|
||||||
mHasCleartextPhase(false),
|
mHasCleartextPhase(false),
|
||||||
mHandshakeInProgress(false),
|
mHandshakeInProgress(false),
|
||||||
@ -101,6 +114,8 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
|
|||||||
mSocketCreationTimestamp(TimeStamp::Now()),
|
mSocketCreationTimestamp(TimeStamp::Now()),
|
||||||
mPlaintextBytesRead(0)
|
mPlaintextBytesRead(0)
|
||||||
{
|
{
|
||||||
|
mTLSVersionRange.min = 0;
|
||||||
|
mTLSVersionRange.max = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED2(nsNSSSocketInfo, TransportSecurityInfo,
|
NS_IMPL_ISUPPORTS_INHERITED2(nsNSSSocketInfo, TransportSecurityInfo,
|
||||||
@ -329,7 +344,7 @@ nsNSSSocketInfo::JoinConnection(const nsACString & npnProtocol,
|
|||||||
|
|
||||||
// If this is the same hostname then the certicate status does not
|
// If this is the same hostname then the certicate status does not
|
||||||
// need to be considered. They are joinable.
|
// need to be considered. They are joinable.
|
||||||
if (GetHostName() && hostname.Equals(GetHostName())) {
|
if (hostname.Equals(GetHostName())) {
|
||||||
*_retval = true;
|
*_retval = true;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -594,25 +609,12 @@ bool nsNSSSocketInfo::HandshakeTimeout()
|
|||||||
|
|
||||||
void nsSSLIOLayerHelpers::Cleanup()
|
void nsSSLIOLayerHelpers::Cleanup()
|
||||||
{
|
{
|
||||||
if (mTLSIntolerantSites) {
|
mTLSIntoleranceInfo.Clear();
|
||||||
delete mTLSIntolerantSites;
|
|
||||||
mTLSIntolerantSites = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTLSTolerantSites) {
|
|
||||||
delete mTLSTolerantSites;
|
|
||||||
mTLSTolerantSites = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mRenegoUnrestrictedSites) {
|
if (mRenegoUnrestrictedSites) {
|
||||||
delete mRenegoUnrestrictedSites;
|
delete mRenegoUnrestrictedSites;
|
||||||
mRenegoUnrestrictedSites = nullptr;
|
mRenegoUnrestrictedSites = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mutex) {
|
|
||||||
delete mutex;
|
|
||||||
mutex = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -641,12 +643,6 @@ nsHandleSSLError(nsNSSSocketInfo *socketInfo,
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nsXPIDLCString hostName;
|
|
||||||
socketInfo->GetHostName(getter_Copies(hostName));
|
|
||||||
|
|
||||||
int32_t port;
|
|
||||||
socketInfo->GetPort(&port);
|
|
||||||
|
|
||||||
// Try to get a nsISSLErrorListener implementation from the socket consumer.
|
// Try to get a nsISSLErrorListener implementation from the socket consumer.
|
||||||
nsCOMPtr<nsIInterfaceRequestor> cb;
|
nsCOMPtr<nsIInterfaceRequestor> cb;
|
||||||
socketInfo->GetNotificationCallbacks(getter_AddRefs(cb));
|
socketInfo->GetNotificationCallbacks(getter_AddRefs(cb));
|
||||||
@ -654,10 +650,11 @@ nsHandleSSLError(nsNSSSocketInfo *socketInfo,
|
|||||||
nsCOMPtr<nsISSLErrorListener> sel = do_GetInterface(cb);
|
nsCOMPtr<nsISSLErrorListener> sel = do_GetInterface(cb);
|
||||||
if (sel) {
|
if (sel) {
|
||||||
nsIInterfaceRequestor *csi = static_cast<nsIInterfaceRequestor*>(socketInfo);
|
nsIInterfaceRequestor *csi = static_cast<nsIInterfaceRequestor*>(socketInfo);
|
||||||
nsCString hostWithPortString = hostName;
|
|
||||||
hostWithPortString.AppendLiteral(":");
|
nsCString hostWithPortString;
|
||||||
hostWithPortString.AppendInt(port);
|
getSiteKey(socketInfo->GetHostName(), socketInfo->GetPort(),
|
||||||
|
hostWithPortString);
|
||||||
|
|
||||||
bool suppressMessage = false; // obsolete, ignored
|
bool suppressMessage = false; // obsolete, ignored
|
||||||
rv = sel->NotifySSLError(csi, err, hostWithPortString, &suppressMessage);
|
rv = sel->NotifySSLError(csi, err, hostWithPortString, &suppressMessage);
|
||||||
}
|
}
|
||||||
@ -739,58 +736,104 @@ nsSSLIOLayerConnect(PRFileDesc* fd, const PRNetAddr* addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsSSLIOLayerHelpers::getSiteKey(nsNSSSocketInfo *socketInfo, nsCSubstring &key)
|
nsSSLIOLayerHelpers::rememberTolerantAtVersion(const nsACString & hostName,
|
||||||
|
int16_t port, uint16_t tolerant)
|
||||||
{
|
{
|
||||||
int32_t port;
|
nsCString key;
|
||||||
socketInfo->GetPort(&port);
|
getSiteKey(hostName, port, key);
|
||||||
|
|
||||||
nsXPIDLCString host;
|
MutexAutoLock lock(mutex);
|
||||||
socketInfo->GetHostName(getter_Copies(host));
|
|
||||||
|
|
||||||
key = host + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
|
IntoleranceEntry entry;
|
||||||
|
if (mTLSIntoleranceInfo.Get(key, &entry)) {
|
||||||
|
entry.AssertInvariant();
|
||||||
|
entry.tolerant = std::max(entry.tolerant, tolerant);
|
||||||
|
if (entry.intolerant != 0 && entry.intolerant <= entry.tolerant) {
|
||||||
|
entry.intolerant = entry.tolerant + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry.tolerant = tolerant;
|
||||||
|
entry.intolerant = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.AssertInvariant();
|
||||||
|
|
||||||
|
mTLSIntoleranceInfo.Put(key, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this function to report a site that is possibly TLS intolerant.
|
// returns true if we should retry the handshake
|
||||||
// This function will return true, if the given socket is currently using TLS,
|
|
||||||
// and it's allowed to retry. Retrying only makes sense if an older
|
|
||||||
// protocol is enabled.
|
|
||||||
bool
|
bool
|
||||||
nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo)
|
nsSSLIOLayerHelpers::rememberIntolerantAtVersion(const nsACString & hostName,
|
||||||
|
int16_t port,
|
||||||
|
uint16_t minVersion,
|
||||||
|
uint16_t intolerant)
|
||||||
{
|
{
|
||||||
nsAutoCString key;
|
nsCString key;
|
||||||
getSiteKey(socketInfo, key);
|
getSiteKey(hostName, port, key);
|
||||||
|
|
||||||
|
MutexAutoLock lock(mutex);
|
||||||
|
|
||||||
|
if (intolerant <= minVersion) {
|
||||||
|
// We can't fall back any further. Assume that intolerance isn't the issue.
|
||||||
|
IntoleranceEntry entry;
|
||||||
|
if (mTLSIntoleranceInfo.Get(key, &entry)) {
|
||||||
|
entry.AssertInvariant();
|
||||||
|
entry.intolerant = 0;
|
||||||
|
entry.AssertInvariant();
|
||||||
|
mTLSIntoleranceInfo.Put(key, entry);
|
||||||
|
}
|
||||||
|
|
||||||
if (!socketInfo->IsTLSEnabled()) {
|
|
||||||
// We did not offer TLS but failed with an intolerant error using
|
|
||||||
// a different protocol. To give TLS a try on next connection attempt again
|
|
||||||
// drop this site from the list of intolerant sites. TLS failure might be
|
|
||||||
// caused only by a traffic congestion while the server is TLS tolerant.
|
|
||||||
removeIntolerantSite(key);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socketInfo->IsSSL3Enabled()) {
|
IntoleranceEntry entry;
|
||||||
// Add this site to the list of TLS intolerant sites.
|
if (mTLSIntoleranceInfo.Get(key, &entry)) {
|
||||||
addIntolerantSite(key);
|
entry.AssertInvariant();
|
||||||
|
if (intolerant <= entry.tolerant) {
|
||||||
|
// We already know the server is tolerant at an equal or higher version.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((entry.intolerant != 0 && intolerant >= entry.intolerant)) {
|
||||||
|
// We already know that the server is intolerant at a lower version.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry.tolerant = 0;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return false; // doesn't make sense to retry
|
entry.intolerant = intolerant;
|
||||||
}
|
entry.AssertInvariant();
|
||||||
|
mTLSIntoleranceInfo.Put(key, entry);
|
||||||
return socketInfo->IsTLSEnabled();
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsSSLIOLayerHelpers::rememberTolerantSite(nsNSSSocketInfo *socketInfo)
|
nsSSLIOLayerHelpers::adjustForTLSIntolerance(const nsACString & hostName,
|
||||||
|
int16_t port,
|
||||||
|
/*in/out*/ SSLVersionRange & range)
|
||||||
{
|
{
|
||||||
if (!socketInfo->IsTLSEnabled())
|
IntoleranceEntry entry;
|
||||||
return;
|
|
||||||
|
|
||||||
nsAutoCString key;
|
{
|
||||||
getSiteKey(socketInfo, key);
|
nsCString key;
|
||||||
|
getSiteKey(hostName, port, key);
|
||||||
|
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
nsSSLIOLayerHelpers::mTLSTolerantSites->PutEntry(key);
|
if (!mTLSIntoleranceInfo.Get(key, &entry)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.AssertInvariant();
|
||||||
|
|
||||||
|
if (entry.intolerant != 0) {
|
||||||
|
// We've tried connecting at a higher range but failed, so try at the
|
||||||
|
// version we haven't tried yet, unless we have reached the minimum.
|
||||||
|
if (range.min < entry.intolerant) {
|
||||||
|
range.max = entry.intolerant - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = false;
|
bool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = false;
|
||||||
@ -1037,8 +1080,11 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
|
|||||||
if (!wantRetry // no decision yet
|
if (!wantRetry // no decision yet
|
||||||
&& isTLSIntoleranceError(err, socketInfo->GetHasCleartextPhase()))
|
&& isTLSIntoleranceError(err, socketInfo->GetHasCleartextPhase()))
|
||||||
{
|
{
|
||||||
nsSSLIOLayerHelpers& helpers = socketInfo->SharedState().IOLayerHelpers();
|
SSLVersionRange range = socketInfo->GetTLSVersionRange();
|
||||||
wantRetry = helpers.rememberPossibleTLSProblemSite(socketInfo);
|
wantRetry = socketInfo->SharedState().IOLayerHelpers()
|
||||||
|
.rememberIntolerantAtVersion(socketInfo->GetHostName(),
|
||||||
|
socketInfo->GetPort(),
|
||||||
|
range.min, range.max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1066,13 +1112,19 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
|
|||||||
if (!wantRetry // no decision yet
|
if (!wantRetry // no decision yet
|
||||||
&& !socketInfo->GetHasCleartextPhase()) // mirror PR_CONNECT_RESET_ERROR treament
|
&& !socketInfo->GetHasCleartextPhase()) // mirror PR_CONNECT_RESET_ERROR treament
|
||||||
{
|
{
|
||||||
nsSSLIOLayerHelpers& helpers = socketInfo->SharedState().IOLayerHelpers();
|
SSLVersionRange range = socketInfo->GetTLSVersionRange();
|
||||||
wantRetry = helpers.rememberPossibleTLSProblemSite(socketInfo);
|
wantRetry = socketInfo->SharedState().IOLayerHelpers()
|
||||||
|
.rememberIntolerantAtVersion(socketInfo->GetHostName(),
|
||||||
|
socketInfo->GetPort(),
|
||||||
|
range.min, range.max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wantRetry) {
|
if (wantRetry) {
|
||||||
|
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
||||||
|
("[%p] checkHandshake: will retry with lower max TLS version\n",
|
||||||
|
ssl_layer_fd));
|
||||||
// We want to cause the network layer to retry the connection.
|
// We want to cause the network layer to retry the connection.
|
||||||
PR_SetError(PR_CONNECT_RESET_ERROR, 0);
|
PR_SetError(PR_CONNECT_RESET_ERROR, 0);
|
||||||
if (wasReading)
|
if (wasReading)
|
||||||
@ -1153,12 +1205,11 @@ nsSSLIOLayerPoll(PRFileDesc * fd, int16_t in_flags, int16_t *out_flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsSSLIOLayerHelpers::nsSSLIOLayerHelpers()
|
nsSSLIOLayerHelpers::nsSSLIOLayerHelpers()
|
||||||
: mutex(nullptr)
|
: mutex("nsSSLIOLayerHelpers.mutex")
|
||||||
, mTLSIntolerantSites(nullptr)
|
|
||||||
, mTLSTolerantSites(nullptr)
|
|
||||||
, mRenegoUnrestrictedSites(nullptr)
|
, mRenegoUnrestrictedSites(nullptr)
|
||||||
, mTreatUnsafeNegotiationAsBroken(false)
|
, mTreatUnsafeNegotiationAsBroken(false)
|
||||||
, mWarnLevelMissingRFC5746(1)
|
, mWarnLevelMissingRFC5746(1)
|
||||||
|
, mTLSIntoleranceInfo(16)
|
||||||
, mFalseStartRequireNPN(true)
|
, mFalseStartRequireNPN(true)
|
||||||
, mFalseStartRequireForwardSecrecy(false)
|
, mFalseStartRequireForwardSecrecy(false)
|
||||||
{
|
{
|
||||||
@ -1381,11 +1432,20 @@ static int32_t PlaintextRecv(PRFileDesc *fd, void *buf, int32_t amount,
|
|||||||
|
|
||||||
nsSSLIOLayerHelpers::~nsSSLIOLayerHelpers()
|
nsSSLIOLayerHelpers::~nsSSLIOLayerHelpers()
|
||||||
{
|
{
|
||||||
Preferences::RemoveObserver(mPrefObserver, "security.ssl.renego_unrestricted_hosts");
|
// mPrefObserver will only be set if this->Init was called. The GTest tests
|
||||||
Preferences::RemoveObserver(mPrefObserver, "security.ssl.treat_unsafe_negotiation_as_broken");
|
// do not call Init.
|
||||||
Preferences::RemoveObserver(mPrefObserver, "security.ssl.warn_missing_rfc5746");
|
if (mPrefObserver) {
|
||||||
Preferences::RemoveObserver(mPrefObserver, "security.ssl.false_start.require-npn");
|
Preferences::RemoveObserver(mPrefObserver,
|
||||||
Preferences::RemoveObserver(mPrefObserver, "security.ssl.false_start.require-forward-secrecy");
|
"security.ssl.renego_unrestricted_hosts");
|
||||||
|
Preferences::RemoveObserver(mPrefObserver,
|
||||||
|
"security.ssl.treat_unsafe_negotiation_as_broken");
|
||||||
|
Preferences::RemoveObserver(mPrefObserver,
|
||||||
|
"security.ssl.warn_missing_rfc5746");
|
||||||
|
Preferences::RemoveObserver(mPrefObserver,
|
||||||
|
"security.ssl.false_start.require-npn");
|
||||||
|
Preferences::RemoveObserver(mPrefObserver,
|
||||||
|
"security.ssl.false_start.require-forward-secrecy");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsSSLIOLayerHelpers::Init()
|
nsresult nsSSLIOLayerHelpers::Init()
|
||||||
@ -1432,16 +1492,7 @@ nsresult nsSSLIOLayerHelpers::Init()
|
|||||||
nsSSLPlaintextLayerMethods.recv = PlaintextRecv;
|
nsSSLPlaintextLayerMethods.recv = PlaintextRecv;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex = new Mutex("nsSSLIOLayerHelpers.mutex");
|
mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>(16);
|
||||||
|
|
||||||
mTLSIntolerantSites = new nsTHashtable<nsCStringHashKey>(1);
|
|
||||||
|
|
||||||
// Initialize the tolerant site hashtable to 16 items at the start seems
|
|
||||||
// reasonable as most servers are TLS tolerant. We just want to lower
|
|
||||||
// the rate of hashtable array reallocation.
|
|
||||||
mTLSTolerantSites = new nsTHashtable<nsCStringHashKey>(16);
|
|
||||||
|
|
||||||
mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>(1);
|
|
||||||
|
|
||||||
nsCString unrestricted_hosts;
|
nsCString unrestricted_hosts;
|
||||||
Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
|
Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
|
||||||
@ -1479,40 +1530,19 @@ nsresult nsSSLIOLayerHelpers::Init()
|
|||||||
void nsSSLIOLayerHelpers::clearStoredData()
|
void nsSSLIOLayerHelpers::clearStoredData()
|
||||||
{
|
{
|
||||||
mRenegoUnrestrictedSites->Clear();
|
mRenegoUnrestrictedSites->Clear();
|
||||||
mTLSTolerantSites->Clear();
|
mTLSIntoleranceInfo.Clear();
|
||||||
mTLSIntolerantSites->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsSSLIOLayerHelpers::addIntolerantSite(const nsCString &str)
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(*mutex);
|
|
||||||
// Remember intolerant site only if it is not known as tolerant
|
|
||||||
if (!mTLSTolerantSites->Contains(str))
|
|
||||||
mTLSIntolerantSites->PutEntry(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsSSLIOLayerHelpers::removeIntolerantSite(const nsCString &str)
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(*mutex);
|
|
||||||
mTLSIntolerantSites->RemoveEntry(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nsSSLIOLayerHelpers::isKnownAsIntolerantSite(const nsCString &str)
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(*mutex);
|
|
||||||
return mTLSIntolerantSites->Contains(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(const nsCString &str)
|
void nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(const nsCString &str)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
|
|
||||||
if (mRenegoUnrestrictedSites) {
|
if (mRenegoUnrestrictedSites) {
|
||||||
delete mRenegoUnrestrictedSites;
|
delete mRenegoUnrestrictedSites;
|
||||||
mRenegoUnrestrictedSites = nullptr;
|
mRenegoUnrestrictedSites = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>(1);
|
mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>();
|
||||||
if (!mRenegoUnrestrictedSites)
|
if (!mRenegoUnrestrictedSites)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1528,31 +1558,31 @@ void nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(const nsCString &str)
|
|||||||
|
|
||||||
bool nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(const nsCString &str)
|
bool nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(const nsCString &str)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
return mRenegoUnrestrictedSites->Contains(str);
|
return mRenegoUnrestrictedSites->Contains(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(bool broken)
|
void nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(bool broken)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
mTreatUnsafeNegotiationAsBroken = broken;
|
mTreatUnsafeNegotiationAsBroken = broken;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsSSLIOLayerHelpers::treatUnsafeNegotiationAsBroken()
|
bool nsSSLIOLayerHelpers::treatUnsafeNegotiationAsBroken()
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
return mTreatUnsafeNegotiationAsBroken;
|
return mTreatUnsafeNegotiationAsBroken;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(int32_t level)
|
void nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(int32_t level)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
mWarnLevelMissingRFC5746 = level;
|
mWarnLevelMissingRFC5746 = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nsSSLIOLayerHelpers::getWarnLevelMissingRFC5746()
|
int32_t nsSSLIOLayerHelpers::getWarnLevelMissingRFC5746()
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(*mutex);
|
MutexAutoLock lock(mutex);
|
||||||
return mWarnLevelMissingRFC5746;
|
return mWarnLevelMissingRFC5746;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2609,31 +2639,31 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, bool forSTARTTLS,
|
|||||||
nsAutoCString key;
|
nsAutoCString key;
|
||||||
key = nsDependentCString(host) + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
|
key = nsDependentCString(host) + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
|
||||||
|
|
||||||
if (infoObject->SharedState().IOLayerHelpers().isKnownAsIntolerantSite(key)) {
|
SSLVersionRange range;
|
||||||
if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_TLS, false))
|
if (SSL_VersionRangeGet(fd, &range) != SECSuccess) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
infoObject->SharedState().IOLayerHelpers()
|
||||||
|
.adjustForTLSIntolerance(infoObject->GetHostName(), infoObject->GetPort(),
|
||||||
|
range);
|
||||||
|
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
||||||
|
("[%p] nsSSLIOLayerSetOptions: using TLS version range (0x%04x,0x%04x)\n",
|
||||||
|
fd, static_cast<unsigned int>(range.min),
|
||||||
|
static_cast<unsigned int>(range.max)));
|
||||||
|
|
||||||
|
if (SSL_VersionRangeSet(fd, &range) != SECSuccess) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
infoObject->SetTLSVersionRange(range);
|
||||||
|
|
||||||
|
// If min == max, then we don't need the intolerance timeout since we have no
|
||||||
|
// lower version to fall back to.
|
||||||
|
if (range.min == range.max) {
|
||||||
infoObject->SetAllowTLSIntoleranceTimeout(false);
|
infoObject->SetAllowTLSIntoleranceTimeout(false);
|
||||||
|
|
||||||
// We assume that protocols that use the STARTTLS mechanism should support
|
|
||||||
// modern hellos. For other protocols, if we suspect a site
|
|
||||||
// does not support TLS, let's also use V2 hellos.
|
|
||||||
// One advantage of this approach, if a site only supports the older
|
|
||||||
// hellos, it is more likely that we will get a reasonable error code
|
|
||||||
// on our single retry attempt.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool enabled;
|
bool enabled = infoObject->SharedState().IsOCSPStaplingEnabled();
|
||||||
if (SECSuccess != SSL_OptionGet(fd, SSL_ENABLE_SSL3, &enabled)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
infoObject->SetSSL3Enabled(enabled);
|
|
||||||
if (SECSuccess != SSL_OptionGet(fd, SSL_ENABLE_TLS, &enabled)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
infoObject->SetTLSEnabled(enabled);
|
|
||||||
|
|
||||||
enabled = infoObject->SharedState().IsOCSPStaplingEnabled();
|
|
||||||
if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_OCSP_STAPLING, enabled)) {
|
if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_OCSP_STAPLING, enabled)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsTHashtable.h"
|
#include "nsTHashtable.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "sslt.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace psm {
|
namespace psm {
|
||||||
@ -56,6 +57,9 @@ public:
|
|||||||
|
|
||||||
void SetAllowTLSIntoleranceTimeout(bool aAllow);
|
void SetAllowTLSIntoleranceTimeout(bool aAllow);
|
||||||
|
|
||||||
|
void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; }
|
||||||
|
SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; };
|
||||||
|
|
||||||
PRStatus CloseSocketAndDestroy(
|
PRStatus CloseSocketAndDestroy(
|
||||||
const nsNSSShutDownPreventionLock & proofOfLock);
|
const nsNSSShutDownPreventionLock & proofOfLock);
|
||||||
|
|
||||||
@ -87,12 +91,6 @@ public:
|
|||||||
{
|
{
|
||||||
return mCertVerificationState == waiting_for_cert_verification;
|
return mCertVerificationState == waiting_for_cert_verification;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSSL3Enabled() const { return mSSL3Enabled; }
|
|
||||||
void SetSSL3Enabled(bool enabled) { mSSL3Enabled = enabled; }
|
|
||||||
bool IsTLSEnabled() const { return mTLSEnabled; }
|
|
||||||
void SetTLSEnabled(bool enabled) { mTLSEnabled = enabled; }
|
|
||||||
|
|
||||||
void AddPlaintextBytesRead(uint64_t val) { mPlaintextBytesRead += val; }
|
void AddPlaintextBytesRead(uint64_t val) { mPlaintextBytesRead += val; }
|
||||||
|
|
||||||
bool IsPreliminaryHandshakeDone() const { return mPreliminaryHandshakeDone; }
|
bool IsPreliminaryHandshakeDone() const { return mPreliminaryHandshakeDone; }
|
||||||
@ -125,8 +123,7 @@ private:
|
|||||||
|
|
||||||
mozilla::psm::SharedSSLState& mSharedState;
|
mozilla::psm::SharedSSLState& mSharedState;
|
||||||
bool mForSTARTTLS;
|
bool mForSTARTTLS;
|
||||||
bool mSSL3Enabled;
|
SSLVersionRange mTLSVersionRange;
|
||||||
bool mTLSEnabled;
|
|
||||||
bool mHandshakePending;
|
bool mHandshakePending;
|
||||||
bool mHasCleartextPhase;
|
bool mHasCleartextPhase;
|
||||||
bool mHandshakeInProgress;
|
bool mHandshakeInProgress;
|
||||||
@ -172,36 +169,43 @@ public:
|
|||||||
static PRIOMethods nsSSLIOLayerMethods;
|
static PRIOMethods nsSSLIOLayerMethods;
|
||||||
static PRIOMethods nsSSLPlaintextLayerMethods;
|
static PRIOMethods nsSSLPlaintextLayerMethods;
|
||||||
|
|
||||||
mozilla::Mutex *mutex;
|
|
||||||
nsTHashtable<nsCStringHashKey> *mTLSIntolerantSites;
|
|
||||||
nsTHashtable<nsCStringHashKey> *mTLSTolerantSites;
|
|
||||||
|
|
||||||
nsTHashtable<nsCStringHashKey> *mRenegoUnrestrictedSites;
|
nsTHashtable<nsCStringHashKey> *mRenegoUnrestrictedSites;
|
||||||
bool mTreatUnsafeNegotiationAsBroken;
|
bool mTreatUnsafeNegotiationAsBroken;
|
||||||
int32_t mWarnLevelMissingRFC5746;
|
int32_t mWarnLevelMissingRFC5746;
|
||||||
|
|
||||||
void setTreatUnsafeNegotiationAsBroken(bool broken);
|
void setTreatUnsafeNegotiationAsBroken(bool broken);
|
||||||
bool treatUnsafeNegotiationAsBroken();
|
bool treatUnsafeNegotiationAsBroken();
|
||||||
|
|
||||||
void setWarnLevelMissingRFC5746(int32_t level);
|
void setWarnLevelMissingRFC5746(int32_t level);
|
||||||
int32_t getWarnLevelMissingRFC5746();
|
int32_t getWarnLevelMissingRFC5746();
|
||||||
|
|
||||||
static void getSiteKey(nsNSSSocketInfo *socketInfo, nsCSubstring &key);
|
private:
|
||||||
bool rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo);
|
struct IntoleranceEntry
|
||||||
void rememberTolerantSite(nsNSSSocketInfo *socketInfo);
|
{
|
||||||
|
uint16_t tolerant;
|
||||||
|
uint16_t intolerant;
|
||||||
|
|
||||||
void addIntolerantSite(const nsCString &str);
|
void AssertInvariant() const
|
||||||
void removeIntolerantSite(const nsCString &str);
|
{
|
||||||
bool isKnownAsIntolerantSite(const nsCString &str);
|
MOZ_ASSERT(intolerant == 0 || tolerant < intolerant);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
nsDataHashtable<nsCStringHashKey, IntoleranceEntry> mTLSIntoleranceInfo;
|
||||||
|
public:
|
||||||
|
void rememberTolerantAtVersion(const nsACString & hostname, int16_t port,
|
||||||
|
uint16_t tolerant);
|
||||||
|
bool rememberIntolerantAtVersion(const nsACString & hostname, int16_t port,
|
||||||
|
uint16_t intolerant, uint16_t minVersion);
|
||||||
|
void adjustForTLSIntolerance(const nsACString & hostname, int16_t port,
|
||||||
|
/*in/out*/ SSLVersionRange & range);
|
||||||
|
|
||||||
void setRenegoUnrestrictedSites(const nsCString &str);
|
void setRenegoUnrestrictedSites(const nsCString &str);
|
||||||
bool isRenegoUnrestrictedSite(const nsCString &str);
|
bool isRenegoUnrestrictedSite(const nsCString &str);
|
||||||
|
|
||||||
void clearStoredData();
|
void clearStoredData();
|
||||||
|
|
||||||
bool mFalseStartRequireNPN;
|
bool mFalseStartRequireNPN;
|
||||||
bool mFalseStartRequireForwardSecrecy;
|
bool mFalseStartRequireForwardSecrecy;
|
||||||
private:
|
private:
|
||||||
|
mozilla::Mutex mutex;
|
||||||
nsCOMPtr<nsIObserver> mPrefObserver;
|
nsCOMPtr<nsIObserver> mPrefObserver;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
16
security/manager/ssl/tests/gtest/Makefile.in
Normal file
16
security/manager/ssl/tests/gtest/Makefile.in
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#! gmake
|
||||||
|
#
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
|
EXPORT_LIBRARY = 1
|
||||||
|
|
||||||
|
LOCAL_INCLUDES = \
|
||||||
|
-I$(topsrcdir)/security/manager/ssl/src \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
145
security/manager/ssl/tests/gtest/TLSIntoleranceTest.cpp
Normal file
145
security/manager/ssl/tests/gtest/TLSIntoleranceTest.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "nsNSSIOLayer.h"
|
||||||
|
#include "sslproto.h"
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
NS_NAMED_LITERAL_CSTRING(HOST, "example.org");
|
||||||
|
const int16_t PORT = 443;
|
||||||
|
|
||||||
|
class TLSIntoleranceTest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
nsSSLIOLayerHelpers helpers;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||||
|
{
|
||||||
|
// No adjustment made when there is no entry for the site.
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||||
|
|
||||||
|
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
range.min, range.max));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||||
|
|
||||||
|
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
range.min, range.max));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
|
||||||
|
|
||||||
|
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
range.min, range.max));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.max);
|
||||||
|
|
||||||
|
// false because we reached the floor set by range.min
|
||||||
|
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
range.min, range.max));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
// When rememberIntolerantAtVersion returns false, it also resets the
|
||||||
|
// intolerance information for the server.
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TLSIntoleranceTest, Test_Tolerant_Overrides_Intolerant_1)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_0));
|
||||||
|
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_0);
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TLSIntoleranceTest, Test_Tolerant_Overrides_Intolerant_2)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_0));
|
||||||
|
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TLSIntoleranceTest, Test_Intolerant_Does_Not_Override_Tolerant)
|
||||||
|
{
|
||||||
|
// No adjustment made when there is no entry for the site.
|
||||||
|
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_0);
|
||||||
|
// false because we reached the floor set by rememberTolerantAtVersion.
|
||||||
|
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||||
|
SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_0));
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TLSIntoleranceTest, Test_Port_Is_Relevant)
|
||||||
|
{
|
||||||
|
helpers.rememberTolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_2);
|
||||||
|
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, 1,
|
||||||
|
SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2));
|
||||||
|
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, 2,
|
||||||
|
SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2));
|
||||||
|
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, 1, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||||
|
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||||
|
helpers.adjustForTLSIntolerance(HOST, 2, range);
|
||||||
|
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||||
|
}
|
||||||
|
}
|
15
security/manager/ssl/tests/gtest/moz.build
Normal file
15
security/manager/ssl/tests/gtest/moz.build
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
MODULE = 'ssltest'
|
||||||
|
|
||||||
|
LIBRARY_NAME = 'ssltest'
|
||||||
|
|
||||||
|
LIBXUL_LIBRARY = True
|
||||||
|
|
||||||
|
GTEST_CPP_SOURCES += [
|
||||||
|
'TLSIntoleranceTest.cpp',
|
||||||
|
]
|
@ -5,7 +5,11 @@
|
|||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
DIRS += ['unit']
|
DIRS += ['unit']
|
||||||
TEST_DIRS += ['mochitest']
|
|
||||||
|
TEST_DIRS += [
|
||||||
|
'gtest',
|
||||||
|
'mochitest',
|
||||||
|
]
|
||||||
|
|
||||||
MODULE = 'pipnss'
|
MODULE = 'pipnss'
|
||||||
|
|
||||||
|
@ -7,4 +7,3 @@
|
|||||||
DIRS += ['tlsserver']
|
DIRS += ['tlsserver']
|
||||||
|
|
||||||
MODULE = 'pipnss'
|
MODULE = 'pipnss'
|
||||||
|
|
||||||
|
@ -693,6 +693,7 @@ ifdef LINK_GTEST
|
|||||||
COMPONENT_LIBS += \
|
COMPONENT_LIBS += \
|
||||||
gtest \
|
gtest \
|
||||||
gfxtest \
|
gfxtest \
|
||||||
|
ssltest \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user