--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -56,16 +56,54 @@ using namespace mozilla::psm;
//DEBUG_SSL_VERBOSE to dump SSL
//read/write buffer to a log.
//Uses PR_LOG except on Mac where
//we always write out to our own
//file.
namespace {
+// The NSSSocketInfo tls flags are meant to be opaque to most calling applications
+// but provide a mechanism for direct TLS manipulation when experimenting with new
+// features in the scope of a single socket. They do not create a persistent ABI.
+//
+// Use of these flags creates a new 'sharedSSLState' so existing states for intolerance
+// are not carried to sockets that use these flags (and intolerance they discover
+// does not impact other normal sockets not using the flags.
+//
+// Their current definitions are:
+//
+// bits 0-2 (mask 0x07) specify the max tls version
+// 0 means no override 1->4 are 1.0, 1.1, 1.2, 1.3, 4->7 unused
+// bits 3-5 (mask 0x38) specify the tls fallback limit
+// 0 means no override, values 1->4 match prefs
+// bit 6 (mask 0x40) specifies use of SSL_AltServerHelloType on handshake
+
+enum {
+ kTLSProviderFlagMaxVersion10 = 0x01,
+ kTLSProviderFlagMaxVersion11 = 0x02,
+ kTLSProviderFlagMaxVersion12 = 0x03,
+ kTLSProviderFlagMaxVersion13 = 0x04,
+};
+
+static uint32_t getTLSProviderFlagMaxVersion(uint32_t flags)
+{
+ return (flags & 0x07);
+}
+
+static uint32_t getTLSProviderFlagFallbackLimit(uint32_t flags)
+{
+ return (flags & 0x38) >> 3;
+}
+
+static bool getTLSProviderFlagAltServerHello(uint32_t flags)
+{
+ return (flags & 0x40);
+}
+
#define MAX_ALPN_LENGTH 255
void
getSiteKey(const nsACString& hostName, uint16_t port,
/*out*/ nsACString& key)
{
key = hostName;
key.AppendASCII(":");
@@ -1678,19 +1716,23 @@ nsSSLIOLayerHelpers::Init()
void
nsSSLIOLayerHelpers::loadVersionFallbackLimit()
{
// see nsNSSComponent::setEnabledTLSVersions for pref handling rules
uint32_t limit = Preferences::GetUint("security.tls.version.fallback-limit",
3); // 3 = TLS 1.2
// set fallback limit if it is set in the tls flags
- uint32_t tlsFlagsFallbackLimit = (mTlsFlags & (7 << 3)) >> 3;
- if (tlsFlagsFallbackLimit)
+ uint32_t tlsFlagsFallbackLimit = getTLSProviderFlagFallbackLimit(mTlsFlags);
+
+ if (tlsFlagsFallbackLimit) {
limit = tlsFlagsFallbackLimit;
+ MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+ ("loadVersionFallbackLimit overriden by tlsFlags %d\n", limit));
+ }
SSLVersionRange defaults = { SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2 };
SSLVersionRange filledInRange;
nsNSSComponent::FillTLSVersionRange(filledInRange, limit, limit, defaults);
if (filledInRange.max < SSL_LIBRARY_VERSION_TLS_1_2) {
filledInRange.max = SSL_LIBRARY_VERSION_TLS_1_2;
}
@@ -2439,42 +2481,44 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, b
}
SSLVersionRange range;
if (SSL_VersionRangeGet(fd, &range) != SECSuccess) {
return NS_ERROR_FAILURE;
}
// setting TLS max version
- switch(infoObject->GetProviderTlsFlags() & 7) {
- case 0:
- // the default value will be used
- break;
-
- case 1:
+ uint32_t versionFlags =
+ getTLSProviderFlagMaxVersion(infoObject->GetProviderTlsFlags());
+ if (versionFlags) {
+ MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+ ("[%p] nsSSLIOLayerSetOptions: version flags %d\n", fd, versionFlags));
+ if (versionFlags == kTLSProviderFlagMaxVersion10) {
range.max = SSL_LIBRARY_VERSION_TLS_1_0;
- break;
-
- case 2:
+ } else if (versionFlags == kTLSProviderFlagMaxVersion11) {
range.max = SSL_LIBRARY_VERSION_TLS_1_1;
- break;
-
- case 3:
+ } else if (versionFlags == kTLSProviderFlagMaxVersion12) {
range.max = SSL_LIBRARY_VERSION_TLS_1_2;
- break;
-
- case 4:
+ } else if (versionFlags == kTLSProviderFlagMaxVersion13) {
range.max = SSL_LIBRARY_VERSION_TLS_1_3;
- break;
+ } else {
+ MOZ_LOG(gPIPNSSLog, LogLevel::Error,
+ ("[%p] nsSSLIOLayerSetOptions: unknown version flags %d\n",
+ fd, versionFlags));
+ }
}
-
+
// enabling alternative server hello
- if (infoObject->GetProviderTlsFlags() & (1 << 6)) {
+ if (getTLSProviderFlagAltServerHello(infoObject->GetProviderTlsFlags())) {
+ MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+ ("[%p] nsSSLIOLayerSetOptions: Use AltServerHello\n", fd));
if (SECSuccess != SSL_UseAltServerHelloType(fd, PR_TRUE)) {
- return NS_ERROR_FAILURE;
+ MOZ_LOG(gPIPNSSLog, LogLevel::Error,
+ ("[%p] nsSSLIOLayerSetOptions: Use AltServerHello failed\n", fd));
+ // continue on default path
}
}
if ((infoObject->GetProviderFlags() & nsISocketProvider::BE_CONSERVATIVE) &&
(range.max > SSL_LIBRARY_VERSION_TLS_1_2)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("[%p] nsSSLIOLayerSetOptions: range.max limited to 1.2 due to BE_CONSERVATIVE flag\n",
fd));
@@ -2601,20 +2645,21 @@ nsSSLIOLayerAddToSocket(int32_t family,
nsNSSShutDownPreventionLock locker;
PRFileDesc* layer = nullptr;
PRFileDesc* plaintextLayer = nullptr;
nsresult rv;
PRStatus stat;
SharedSSLState* sharedState = nullptr;
- if (providerTlsFlags)
+ if (providerTlsFlags) {
sharedState = new SharedSSLState(providerTlsFlags);
- else
+ } else {
sharedState = (providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE) ? PrivateSSLState() : PublicSSLState();
+ }
nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags, providerTlsFlags);
if (!infoObject) return NS_ERROR_FAILURE;
NS_ADDREF(infoObject);
infoObject->SetForSTARTTLS(forSTARTTLS);
infoObject->SetHostName(host);
infoObject->SetPort(port);