Bug 1605273 - only run CRLite on certificates with a CT SCT available r=jcj

Because CAs can back-date a certificate (i.e. set the "notBefore" field to
earlier than when a certificate actually existed), the "notBefore" field can't
be relied on when determining when CRLite information is recent enough to check
a certificate with. To that end, this patch instead uses the earliest timestamp
from the embedded SCTs in the certificate being checked.

Differential Revision: https://phabricator.services.mozilla.com/D90599
This commit is contained in:
Dana Keeler 2020-09-24 18:10:05 +00:00
parent 55cfe61a1d
commit 3d9ab91ab0
16 changed files with 191 additions and 38 deletions

View File

@ -227,9 +227,10 @@ Result AppTrustDomain::DigestBuf(Input item, DigestAlgorithm digestAlg,
return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
}
Result AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time, Time,
Result AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time,
Duration,
/*optional*/ const Input*,
/*optional*/ const Input*,
/*optional*/ const Input*) {
// We don't currently do revocation checking. If we need to distrust an Apps
// certificate, we will use the active distrust mechanism.

View File

@ -39,10 +39,10 @@ class AppTrustDomain final : public mozilla::pkix::TrustDomain {
virtual Result CheckRevocation(
mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
mozilla::pkix::Time validityPeriodBeginning,
mozilla::pkix::Duration validityDuration,
/*optional*/ const mozilla::pkix::Input* stapledOCSPresponse,
/*optional*/ const mozilla::pkix::Input* aiaExtension) override;
/*optional*/ const mozilla::pkix::Input* aiaExtension,
/*optional*/ const mozilla::pkix::Input* sctExtension) override;
virtual Result IsChainValid(
const mozilla::pkix::DERArray& certChain, mozilla::pkix::Time time,
const mozilla::pkix::CertPolicyId& requiredPolicy) override;

View File

@ -9,6 +9,7 @@
#include <stdint.h>
#include "ExtendedValidation.h"
#include "MultiLogCTVerifier.h"
#include "NSSErrorsService.h"
#include "OCSPVerificationTrustDomain.h"
#include "PublicKeyPinningService.h"
@ -54,6 +55,7 @@
#include "TrustOverride-SymantecData.inc"
using namespace mozilla;
using namespace mozilla::ct;
using namespace mozilla::pkix;
extern LazyLogModule gCertVerifierLog;
@ -605,11 +607,34 @@ static Result GetOCSPAuthorityInfoAccessLocation(const UniquePLArenaPool& arena,
return Success;
}
Result GetEarliestSCTTimestamp(Input sctExtension,
Maybe<uint64_t>& earliestTimestamp) {
earliestTimestamp.reset();
Input sctList;
Result rv =
ExtractSignedCertificateTimestampListFromExtension(sctExtension, sctList);
if (rv != Success) {
return rv;
}
std::vector<SignedCertificateTimestamp> decodedSCTs;
size_t decodingErrors;
DecodeSCTs(sctList, decodedSCTs, decodingErrors);
Unused << decodingErrors;
for (const auto& scts : decodedSCTs) {
if (!earliestTimestamp.isSome() || scts.timestamp < *earliestTimestamp) {
earliestTimestamp = Some(scts.timestamp);
}
}
return Success;
}
Result NSSCertDBTrustDomain::CheckRevocation(
EndEntityOrCA endEntityOrCA, const CertID& certID, Time time,
Time certValidityPeriodBeginning, Duration validityDuration,
Duration validityDuration,
/*optional*/ const Input* stapledOCSPResponse,
/*optional*/ const Input* aiaExtension) {
/*optional*/ const Input* aiaExtension,
/*optional*/ const Input* sctExtension) {
// Actively distrusted certificates will have already been blocked by
// GetCertTrust.
@ -619,10 +644,20 @@ Result NSSCertDBTrustDomain::CheckRevocation(
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
("NSSCertDBTrustDomain: Top of CheckRevocation\n"));
Maybe<uint64_t> earliestSCTTimestamp = Nothing();
if (sctExtension) {
Result rv = GetEarliestSCTTimestamp(*sctExtension, earliestSCTTimestamp);
if (rv != Success) {
MOZ_LOG(
gCertVerifierLog, LogLevel::Debug,
("decoding SCT extension failed - CRLite will be not be consulted"));
}
}
Maybe<TimeDuration> crliteLookupDuration;
#ifdef MOZ_NEW_CERT_STORAGE
if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
mCRLiteMode != CRLiteMode::Disabled) {
mCRLiteMode != CRLiteMode::Disabled && earliestSCTTimestamp.isSome()) {
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
("NSSCertDBTrustDomain::CheckRevocation: checking CRLite"));
nsTArray<uint8_t> issuerBytes;
@ -668,12 +703,15 @@ Result NSSCertDBTrustDomain::CheckRevocation(
crliteLookupDuration.emplace(crliteLookupAfter - crliteLookupBefore);
}
Time filterTimestampTime(TimeFromEpochInSeconds(filterTimestamp));
// We can only use this result if this certificate's `notBefore` time
// (i.e. the beginning of its validity period) is older than what cert
// storage returned for its CRLite timestamp. Otherwise, the CRLite filter
// cascade may have been created before this certificate existed, and if
// it would create a false positive, it hasn't been accounted for.
if (certValidityPeriodBeginning <= filterTimestampTime &&
// We can only use this result if the earliest embedded signed
// certificate timestamp from the certificate is older than what cert
// storage returned for its CRLite timestamp. Otherwise, the CRLite
// filter cascade may have been created before this certificate existed,
// and if it would create a false positive, it hasn't been accounted for.
// SCT timestamps are milliseconds since the epoch.
Time earliestCertificateTimestamp(
TimeFromEpochInSeconds(*earliestSCTTimestamp / 1000));
if (earliestCertificateTimestamp <= filterTimestampTime &&
crliteRevocationState == nsICertStorage::STATE_ENFORCE) {
if (mCRLiteTelemetryInfo) {
mCRLiteTelemetryInfo->mLookupResult =
@ -707,7 +745,7 @@ Result NSSCertDBTrustDomain::CheckRevocation(
mCRLiteTelemetryInfo->mLookupResult =
CRLiteLookupResult::FilterNotAvailable;
}
} else if (certValidityPeriodBeginning > filterTimestampTime) {
} else if (earliestCertificateTimestamp > filterTimestampTime) {
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
("NSSCertDBTrustDomain::CheckRevocation: cert too new"));
if (mCRLiteTelemetryInfo) {

View File

@ -223,10 +223,10 @@ class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain {
virtual Result CheckRevocation(
mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
mozilla::pkix::Time validityPeriodBeginning,
mozilla::pkix::Duration validityDuration,
/*optional*/ const mozilla::pkix::Input* stapledOCSPResponse,
/*optional*/ const mozilla::pkix::Input* aiaExtension) override;
/*optional*/ const mozilla::pkix::Input* aiaExtension,
/*optional*/ const mozilla::pkix::Input* sctExtension) override;
virtual Result IsChainValid(
const mozilla::pkix::DERArray& certChain, mozilla::pkix::Time time,

View File

@ -36,8 +36,9 @@ Result OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time,
}
Result OCSPVerificationTrustDomain::CheckRevocation(EndEntityOrCA,
const CertID&, Time, Time,
const CertID&, Time,
Duration, const Input*,
const Input*,
const Input*) {
// We do not expect this to be called for OCSP signers
return Result::FATAL_ERROR_LIBRARY_FAILURE;

View File

@ -67,10 +67,10 @@ class OCSPVerificationTrustDomain : public mozilla::pkix::TrustDomain {
virtual Result CheckRevocation(
mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
mozilla::pkix::Time validityPeriodBeginning,
mozilla::pkix::Duration validityDuration,
/*optional*/ const mozilla::pkix::Input* stapledOCSPResponse,
/*optional*/ const mozilla::pkix::Input* aiaExtension) override;
/*optional*/ const mozilla::pkix::Input* aiaExtension,
/*optional*/ const mozilla::pkix::Input* sctExtension) override;
virtual Result IsChainValid(
const mozilla::pkix::DERArray& certChain, mozilla::pkix::Time time,

View File

@ -38,8 +38,8 @@ class SignatureParamsTrustDomain final : public TrustDomain {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Time, Duration,
const Input*, const Input*) override {
Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
const Input*, const Input*, const Input*) override {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}

View File

@ -73,34 +73,46 @@ Result MultiLogCTVerifier::Verify(Input cert, Input issuerSubjectPublicKeyInfo,
return Success;
}
Result MultiLogCTVerifier::VerifySCTs(Input encodedSctList,
const LogEntry& expectedEntry,
VerifiedSCT::Origin origin, Time time,
CTVerifyResult& result) {
void DecodeSCTs(Input encodedSctList,
std::vector<SignedCertificateTimestamp>& decodedSCTs,
size_t& decodingErrors) {
decodedSCTs.clear();
Reader listReader;
Result rv = DecodeSCTList(encodedSctList, listReader);
if (rv != Success) {
result.decodingErrors++;
return Success;
decodingErrors++;
return;
}
while (!listReader.AtEnd()) {
Input encodedSct;
rv = ReadSCTListItem(listReader, encodedSct);
if (rv != Success) {
result.decodingErrors++;
return Success;
decodingErrors++;
return;
}
Reader encodedSctReader(encodedSct);
SignedCertificateTimestamp sct;
rv = DecodeSignedCertificateTimestamp(encodedSctReader, sct);
if (rv != Success) {
result.decodingErrors++;
decodingErrors++;
continue;
}
decodedSCTs.push_back(std::move(sct));
}
}
rv = VerifySingleSCT(std::move(sct), expectedEntry, origin, time, result);
Result MultiLogCTVerifier::VerifySCTs(Input encodedSctList,
const LogEntry& expectedEntry,
VerifiedSCT::Origin origin, Time time,
CTVerifyResult& result) {
std::vector<SignedCertificateTimestamp> decodedSCTs;
DecodeSCTs(encodedSctList, decodedSCTs, result.decodingErrors);
for (auto sct : decodedSCTs) {
Result rv =
VerifySingleSCT(std::move(sct), expectedEntry, origin, time, result);
if (rv != Success) {
return rv;
}

View File

@ -19,6 +19,10 @@
namespace mozilla {
namespace ct {
void DecodeSCTs(Input encodedSctList,
std::vector<SignedCertificateTimestamp>& decodedSCTs,
size_t& decodingErrors);
// A Certificate Transparency verifier that can verify Signed Certificate
// Timestamps from multiple logs.
class MultiLogCTVerifier {

View File

@ -675,8 +675,9 @@ class OCSPExtensionTrustDomain : public TrustDomain {
return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
}
pkix::Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Time,
Duration, const Input*, const Input*) override {
pkix::Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
const Input*, const Input*,
const Input*) override {
ADD_FAILURE();
return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
}

View File

@ -138,9 +138,10 @@ Result CSTrustDomain::FindIssuer(Input encodedIssuerName,
Result CSTrustDomain::CheckRevocation(
EndEntityOrCA endEntityOrCA, const CertID& certID, Time time,
Time validityPeriodBeginning, Duration validityDuration,
Duration validityDuration,
/*optional*/ const Input* stapledOCSPresponse,
/*optional*/ const Input* aiaExtension) {
/*optional*/ const Input* aiaExtension,
/*optional*/ const Input* sctExtension) {
// We're relying solely on the CertBlocklist for revocation - and we're
// performing checks on this in GetCertTrust (as per nsNSSCertDBTrustDomain)
return Success;

View File

@ -35,10 +35,10 @@ class CSTrustDomain final : public mozilla::pkix::TrustDomain {
virtual Result CheckRevocation(
mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
mozilla::pkix::Time validityPeriodBeginning,
mozilla::pkix::Duration validityDuration,
/*optional*/ const mozilla::pkix::Input* stapledOCSPresponse,
/*optional*/ const mozilla::pkix::Input* aiaExtension) override;
/*optional*/ const mozilla::pkix::Input* aiaExtension,
/*optional*/ const mozilla::pkix::Input* sctExtension) override;
virtual Result IsChainValid(
const mozilla::pkix::DERArray& certChain, mozilla::pkix::Time time,
const mozilla::pkix::CertPolicyId& requiredPolicy) override;

View File

@ -1984,9 +1984,10 @@ class ClientAuthCertNonverifyingTrustDomain final : public TrustDomain {
virtual mozilla::pkix::Result CheckRevocation(
EndEntityOrCA endEntityOrCA, const CertID& certID, Time time,
Time validityPeriodBeginning, Duration validityDuration,
Duration validityDuration,
/*optional*/ const Input* stapledOCSPresponse,
/*optional*/ const Input* aiaExtension) override {
/*optional*/ const Input* aiaExtension,
/*optional*/ const Input* sctExtension) override {
return Success;
}

View File

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaME0xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIg
U2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ANyuWJBNwcQwFZA1W248ghX1LFy949v/cUP6ZCWA1O4Yok3wZtAKc24RmDYXZK83
nf36QYSvx6+M/hpzTc8zl5CilodTgyu5pnVILR1WN3vaMTIa16yrBvSqXUu3R0bd
KpPDkC55gIDvEwRqFDu1m5K+wgdlTvza/P96rtxcflUxDOg5B6TXvi/TC2rSsd9f
/ld0Uzs1gN2ujkSYs58O09rg1/RrKatEp0tYhG2SS4HD2nOLEpdIkARFdRrdNzGX
kujNVA075ME/OV4uuPNcfhCOhkEAjUVmR7ChZc6gqikJTvOX6+guqw9ypzAO+sf0
/RR3w6RbKFfCs/mC/bdFWJsCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8C
AQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY
aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6
Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwN6A1
oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RD
QS5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFA+AYRyCMWHVLyjnjUY4tCzh
xtniMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA0GCSqGSIb3DQEB
CwUAA4IBAQAjPt9L0jFCpbZ+QlwaRMxp0Wi0XUvgBCFsS+JtzLHgl4+mUwnNqipl
5TlPHoOlblyYoiQm5vuh7ZPHLgLGTUq/sELfeNqzqPlt/yGFUzZgTHbO7Djc1lGA
8MXW5dRNJ2Srm8c+cftIl7gzbckTB+6WohsYFfZcTEDts8Ls/3HB40f/1LkAtDdC
2iDJ6m6K7hQGrn2iWZiIqBtvLfTyyRRfJs8sjX7tN8Cp1Tm5gr8ZDOo0rwAhaPit
c+LJMto4JQtV05od8GiG7S5BNO98pVAdvzr508EIDObtHopYJeS4d60tbvVS3bR0
j6tJLp07kzQoH3jOlOrHvdPJbRzeXDLz
-----END CERTIFICATE-----

View File

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFpDCCBIygAwIBAgIQDVHBpbd6yyk2LgPoPr9QyjANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTkxMTE4MDAwMDAwWhcN
MjExMTE4MTIwMDAwWjCBlDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3Ju
aWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHTAbBgNVBAoTFFN5bWFudGVjIENv
cnBvcmF0aW9uMRcwFQYDVQQLEw5TeW1hbnRlYy5jbG91ZDEgMB4GA1UEAxMXbWFp
bDIzMy5tZXNzYWdlbGFicy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCyM1Fy9hAlahRqqeEnPKDWgUmsxofivWEWKNeSMEKcnXX3TCQOGbLQTthN
xfNU7IWY8ViTPwQ8JBWWDxNhd6dTYLNnytKrNRG8qDQ3rFMKJY4p0dZImMp55X3W
1xcKMxSOkPv0YUCGp7qlAHq6+N3YY1ILw6MRdJ75Njh4Kw8qe5F3rHLwD+AyYQmx
3WsMCRp5NZtWUcU5Vbc9ca/osrh9xBF7U3ZYR6GoPXQlizrNjXv7/BaKWWO5ChbD
iRI4Nj8d3HhWUHsJoGvYDof5Iudgtbubz3c5cwp6+VNNMas7izpvbixqW8zXdUug
8v5v47IkRNYnlma/zvv2IDC1dVlxAgMBAAGjggI2MIICMjAfBgNVHSMEGDAWgBQP
gGEcgjFh1S8o541GOLQs4cbZ4jAdBgNVHQ4EFgQUZnBdWwGQjkPX/+A2ZEYdUdnw
lN8wfQYDVR0RBHYwdIIbY2x1c3RlcjguZXUubWVzc2FnZWxhYnMuY29tgh5jbHVz
dGVyOG91dC5ldS5tZXNzYWdlbGFicy5jb22CHGNsdXN0ZXI4YS5ldS5tZXNzYWdl
bGFicy5jb22CF21haWwyMzMubWVzc2FnZWxhYnMuY29tMA4GA1UdDwEB/wQEAwIF
oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwawYDVR0fBGQwYjAvoC2g
K4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwL6At
oCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzYuY3JsMEwG
A1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMHwGCCsGAQUFBwEBBHAwbjAkBggr
BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEYGCCsGAQUFBzAChjpo
dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyU2VjdXJlU2Vy
dmVyQ0EuY3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAK7vS/qDcGKb
QYu26+jGtBemopT3+2YJjtALeR62eNhF9LoHu+mnmNLvPI0M0NMhz56Ss/6sUHOz
hJgB98SLAQ5ElSWXrnZThLIjsiH5X5MYTD0Y8MqzoJSi2Lf2Muy/UpyrD3wB14E1
kUYhvUnaWDDPIN81DCFzEosBmnsRqr5zlcZSKs0e1LVQ8cNkt8svVkiwFgeOIhwo
QF22GJAZPtRceSGlbRTFBYKh+u3KN8eNS/X+C935y+F4J/grufDCzRSGtRRseTcd
1QW49+QME/rx1mBb7id4iXNKxvGuJTivBlxaHWBQLh/RGk39DSdHfjAhYvt2gmxh
C3gxXMNrymE=
-----END CERTIFICATE-----

View File

@ -402,11 +402,15 @@ add_task(
let revokedInStashIssuer = constructCertFromFile(
"test_cert_storage_direct/revoked-in-stash-issuer.pem"
);
let noSCTCertIssuer = constructCertFromFile(
"test_cert_storage_direct/no-sct-issuer.pem"
);
let crliteEnrollmentRecords = [
getCRLiteEnrollmentRecordFor(validCertIssuer),
getCRLiteEnrollmentRecordFor(revokedCertIssuer),
getCRLiteEnrollmentRecordFor(revokedInStashIssuer),
getCRLiteEnrollmentRecordFor(noSCTCertIssuer),
];
await IntermediatePreloadsClient.onSync({
@ -521,6 +525,36 @@ add_task(
"schunk-group.com",
Ci.nsIX509CertDB.FLAG_LOCAL_ONLY
);
// This certificate has no embedded SCTs, so it is not guaranteed to be in
// CT, so CRLite can't be guaranteed to give the correct answer, so it is
// not consulted.
let noSCTCert = constructCertFromFile(
"test_cert_storage_direct/no-sct.pem"
);
// Currently OCSP will always be consulted for certificates that are not
// revoked in CRLite, but if/when OCSP gets skipped for all certificates
// covered by CRLite, this test will ensure that certificates without
// embedded SCTs will cause OCSP to be consulted.
// NB: this will cause an OCSP request to be sent to localhost:80, but
// since an OCSP responder shouldn't be running on that port, this should
// fail safely.
Services.prefs.setCharPref("network.dns.localDomains", "ocsp.digicert.com");
Services.prefs.setBoolPref("security.OCSP.require", true);
Services.prefs.setIntPref("security.OCSP.enabled", 1);
await checkCertErrorGenericAtTime(
certdb,
noSCTCert,
SEC_ERROR_OCSP_SERVER_ERROR,
certificateUsageSSLServer,
new Date("2020-11-20T00:00:00Z").getTime() / 1000,
false,
"mail233.messagelabs.com",
0
);
Services.prefs.clearUserPref("network.dns.localDomains");
Services.prefs.clearUserPref("security.OCSP.require");
Services.prefs.clearUserPref("security.OCSP.enabled");
}
);