import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,8 @@
"use strict";
module.exports = { // eslint-disable-line no-undef
"rules": {
// Disallow non-top level |var| declarations.
"mozilla/var-only-at-top-level": "error"
}
};

View file

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "gtest/gtest.h"
#include "nsCOMPtr.h"
#include "nsIPrefService.h"
#include "nsISimpleEnumerator.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsIX509CertList.h"
#include "nsServiceManagerUtils.h"
TEST(psm_CertDB, Test)
{
{
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
ASSERT_TRUE(prefs) << "couldn't get nsIPrefBranch";
// When PSM initializes, it attempts to get some localized strings.
// As a result, Android flips out if this isn't set.
nsresult rv = prefs->SetBoolPref("intl.locale.matchOS", true);
ASSERT_TRUE(NS_SUCCEEDED(rv)) << "couldn't set pref 'intl.locale.matchOS'";
nsCOMPtr<nsIX509CertDB> certdb(do_GetService(NS_X509CERTDB_CONTRACTID));
ASSERT_TRUE(certdb) << "couldn't get certdb";
nsCOMPtr<nsIX509CertList> certList;
rv = certdb->GetCerts(getter_AddRefs(certList));
ASSERT_TRUE(NS_SUCCEEDED(rv)) << "couldn't get list of certificates";
nsCOMPtr<nsISimpleEnumerator> enumerator;
rv = certList->GetEnumerator(getter_AddRefs(enumerator));
ASSERT_TRUE(NS_SUCCEEDED(rv)) << "couldn't enumerate certificate list";
bool foundBuiltIn = false;
bool hasMore = false;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> supports;
ASSERT_TRUE(NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(supports))))
<< "couldn't get next certificate";
nsCOMPtr<nsIX509Cert> cert(do_QueryInterface(supports));
ASSERT_TRUE(cert) << "couldn't QI to nsIX509Cert";
ASSERT_TRUE(NS_SUCCEEDED(cert->GetIsBuiltInRoot(&foundBuiltIn))) <<
"GetIsBuiltInRoot failed";
if (foundBuiltIn) {
break;
}
}
ASSERT_TRUE(foundBuiltIn) << "didn't load any built-in certificates";
printf("successfully loaded at least one built-in certificate\n");
} // this scopes the nsCOMPtrs
}

View file

@ -0,0 +1,225 @@
/* -*- 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 "gtest/gtest.h"
#include "mozilla/DataStorage.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsNetUtil.h"
#include "nsPrintfCString.h"
#include "nsStreamUtils.h"
#include "prtime.h"
using namespace mozilla;
class psm_DataStorageTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
NS_ConvertUTF8toUTF16 testName(testInfo->name());
storage = DataStorage::Get(testName);
storage->Init(dataWillPersist);
}
RefPtr<DataStorage> storage;
bool dataWillPersist;
};
NS_NAMED_LITERAL_CSTRING(testKey, "test");
NS_NAMED_LITERAL_CSTRING(testValue, "value");
NS_NAMED_LITERAL_CSTRING(privateTestValue, "private");
TEST_F(psm_DataStorageTest, GetPutRemove)
{
EXPECT_TRUE(dataWillPersist);
// Test Put/Get on Persistent data
EXPECT_EQ(NS_OK, storage->Put(testKey, testValue, DataStorage_Persistent));
// Don't re-use testKey / testValue here, to make sure that this works as
// expected with objects that have the same semantic value but are not
// literally the same object.
nsCString result = storage->Get(NS_LITERAL_CSTRING("test"),
DataStorage_Persistent);
EXPECT_STREQ("value", result.get());
// Get on Temporary/Private data with the same key should give nothing
result = storage->Get(testKey, DataStorage_Temporary);
EXPECT_TRUE(result.IsEmpty());
result = storage->Get(testKey, DataStorage_Private);
EXPECT_TRUE(result.IsEmpty());
// Put with Temporary/Private data shouldn't affect Persistent data
NS_NAMED_LITERAL_CSTRING(temporaryTestValue, "temporary");
EXPECT_EQ(NS_OK, storage->Put(testKey, temporaryTestValue,
DataStorage_Temporary));
EXPECT_EQ(NS_OK, storage->Put(testKey, privateTestValue,
DataStorage_Private));
result = storage->Get(testKey, DataStorage_Temporary);
EXPECT_STREQ("temporary", result.get());
result = storage->Get(testKey, DataStorage_Private);
EXPECT_STREQ("private", result.get());
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ("value", result.get());
// Put of a previously-present key overwrites it (if of the same type)
NS_NAMED_LITERAL_CSTRING(newValue, "new");
EXPECT_EQ(NS_OK, storage->Put(testKey, newValue, DataStorage_Persistent));
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ("new", result.get());
// Removal should work
storage->Remove(testKey, DataStorage_Temporary);
result = storage->Get(testKey, DataStorage_Temporary);
EXPECT_TRUE(result.IsEmpty());
// But removing one type shouldn't affect the others
result = storage->Get(testKey, DataStorage_Private);
EXPECT_STREQ("private", result.get());
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ("new", result.get());
// Test removing the other types as well
storage->Remove(testKey, DataStorage_Private);
result = storage->Get(testKey, DataStorage_Private);
EXPECT_TRUE(result.IsEmpty());
storage->Remove(testKey, DataStorage_Persistent);
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_TRUE(result.IsEmpty());
}
TEST_F(psm_DataStorageTest, InputValidation)
{
EXPECT_TRUE(dataWillPersist);
// Keys may not have tabs or newlines
EXPECT_EQ(NS_ERROR_INVALID_ARG,
storage->Put(NS_LITERAL_CSTRING("key\thas tab"), testValue,
DataStorage_Persistent));
nsCString result = storage->Get(NS_LITERAL_CSTRING("key\thas tab"),
DataStorage_Persistent);
EXPECT_TRUE(result.IsEmpty());
EXPECT_EQ(NS_ERROR_INVALID_ARG,
storage->Put(NS_LITERAL_CSTRING("key has\nnewline"), testValue,
DataStorage_Persistent));
result = storage->Get(NS_LITERAL_CSTRING("keyhas\nnewline"),
DataStorage_Persistent);
EXPECT_TRUE(result.IsEmpty());
// Values may not have newlines
EXPECT_EQ(NS_ERROR_INVALID_ARG,
storage->Put(testKey, NS_LITERAL_CSTRING("value\nhas newline"),
DataStorage_Persistent));
result = storage->Get(testKey, DataStorage_Persistent);
// Values may have tabs
EXPECT_TRUE(result.IsEmpty());
EXPECT_EQ(NS_OK, storage->Put(testKey,
NS_LITERAL_CSTRING("val\thas tab; this is ok"),
DataStorage_Persistent));
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ("val\thas tab; this is ok", result.get());
nsCString longKey("a");
for (int i = 0; i < 8; i++) {
longKey.Append(longKey);
}
// A key of length 256 will work
EXPECT_EQ(NS_OK, storage->Put(longKey, testValue, DataStorage_Persistent));
result = storage->Get(longKey, DataStorage_Persistent);
EXPECT_STREQ("value", result.get());
longKey.Append("a");
// A key longer than that will not work
EXPECT_EQ(NS_ERROR_INVALID_ARG,
storage->Put(longKey, testValue, DataStorage_Persistent));
result = storage->Get(longKey, DataStorage_Persistent);
EXPECT_TRUE(result.IsEmpty());
nsCString longValue("a");
for (int i = 0; i < 10; i++) {
longValue.Append(longValue);
}
// A value of length 1024 will work
EXPECT_EQ(NS_OK, storage->Put(testKey, longValue, DataStorage_Persistent));
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ(longValue.get(), result.get());
longValue.Append("a");
// A value longer than that will not work
storage->Remove(testKey, DataStorage_Persistent);
EXPECT_EQ(NS_ERROR_INVALID_ARG,
storage->Put(testKey, longValue, DataStorage_Persistent));
result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_TRUE(result.IsEmpty());
}
TEST_F(psm_DataStorageTest, Eviction)
{
EXPECT_TRUE(dataWillPersist);
// Eviction is on a per-table basis. Tables shouldn't affect each other.
EXPECT_EQ(NS_OK, storage->Put(testKey, testValue, DataStorage_Persistent));
for (int i = 0; i < 1025; i++) {
EXPECT_EQ(NS_OK, storage->Put(nsPrintfCString("%d", i),
nsPrintfCString("%d", i),
DataStorage_Temporary));
nsCString result = storage->Get(nsPrintfCString("%d", i),
DataStorage_Temporary);
EXPECT_STREQ(nsPrintfCString("%d", i).get(), result.get());
}
// We don't know which entry got evicted, but we can count them.
int entries = 0;
for (int i = 0; i < 1025; i++) {
nsCString result = storage->Get(nsPrintfCString("%d", i),
DataStorage_Temporary);
if (!result.IsEmpty()) {
entries++;
}
}
EXPECT_EQ(entries, 1024);
nsCString result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ("value", result.get());
}
TEST_F(psm_DataStorageTest, ClearPrivateData)
{
EXPECT_TRUE(dataWillPersist);
EXPECT_EQ(NS_OK, storage->Put(testKey, privateTestValue,
DataStorage_Private));
nsCString result = storage->Get(testKey, DataStorage_Private);
EXPECT_STREQ("private", result.get());
storage->Observe(nullptr, "last-pb-context-exited", nullptr);
result = storage->Get(testKey, DataStorage_Private);
EXPECT_TRUE(result.IsEmpty());
}
TEST_F(psm_DataStorageTest, Shutdown)
{
EXPECT_TRUE(dataWillPersist);
EXPECT_EQ(NS_OK, storage->Put(testKey, testValue, DataStorage_Persistent));
nsCString result = storage->Get(testKey, DataStorage_Persistent);
EXPECT_STREQ("value", result.get());
// Get "now" (in days) close to when the data was last touched, so we won't
// get intermittent failures with the day not matching.
int64_t microsecondsPerDay = 24 * 60 * 60 * int64_t(PR_USEC_PER_SEC);
int32_t nowInDays = int32_t(PR_Now() / microsecondsPerDay);
storage->Observe(nullptr, "profile-before-change", nullptr);
nsCOMPtr<nsIFile> backingFile;
EXPECT_EQ(NS_OK, NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(backingFile)));
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
NS_ConvertUTF8toUTF16 testName(testInfo->name());
EXPECT_EQ(NS_OK, backingFile->Append(testName));
nsCOMPtr<nsIInputStream> fileInputStream;
EXPECT_EQ(NS_OK, NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream),
backingFile));
nsCString data;
EXPECT_EQ(NS_OK, NS_ConsumeStream(fileInputStream, UINT32_MAX, data));
// The data will be of the form 'test\t0\t<days since the epoch>\tvalue'
EXPECT_STREQ(nsPrintfCString("test\t0\t%d\tvalue\n", nowInDays).get(),
data.get());
}

View file

@ -0,0 +1,96 @@
/* -*- 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 "gtest/gtest.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsSerializationHelper.h"
// These tests verify that we can still deserialize old binary strings
// generated for security info. This is necessary because service workers
// stores these strings on disk.
//
// If you make a change and start breaking these tests, you will need to
// add a compat fix for loading the old versions. For things that affect
// the UUID, but do not break the rest of the format you can simply add
// another hack condition in nsBinaryInputStream::ReadObject(). If you
// change the overall format of the serialization then we will need more
// complex handling in the security info concrete classes.
//
// We would like to move away from this binary compatibility requirement
// in service workers. See bug 1248628.
TEST(psm_DeserializeCert, gecko33)
{
// Gecko 33+ vintage Security info serialized with UUIDs:
// - nsISupports 00000000-0000-0000-c000-000000000046
// - nsISSLStatus fa9ba95b-ca3b-498a-b889-7c79cf28fee8
// - nsIX509Cert f8ed8364-ced9-4c6e-86ba-48af53c393e6
nsCString base64Serialization(
"FnhllAKWRHGAlo+ESXykKAAAAAAAAAAAwAAAAAAAAEaphjojH6pBabDSgSnsfLHeAAQAAgAAAAAAAAAAAAAAAAAAAAA"
"B4vFIJp5wRkeyPxAQ9RJGKPqbqVvKO0mKuIl8ec8o/uhmCjImkVxP+7sgiYWmMt8F+O2DZM7ZTG6GukivU8OT5gAAAAIAAAWpMII"
"FpTCCBI2gAwIBAgIQD4svsaKEC+QtqtsU2TF8ITANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUN"
"lcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFN"
"lcnZlciBDQTAeFw0xNTAyMjMwMDAwMDBaFw0xNjAzMDIxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMRYwFAYDVQQHEw1TYW4gRnJhbmN"
"pc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRUwEwYDVQQKEwxGYXN0bHksIEluYy4xFzAVBgNVBAMTDnd3dy5naXRodWIuY29tMII"
"BIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+9WUCgrgUNwP/JC3cUefLAXeDpq8Ko/U8p8IRvny0Ri0I6Uq0t+RP/nF0LJ"
"Avda8QHYujdgeDTePepBX7+OiwBFhA0YO+rM3C2Z8IRaN/i9eLln+Yyc68+1z+E10s1EXdZrtDGvN6MHqygGsdfkXKfBLUJ1BZEh"
"s9sBnfcjq3kh5gZdBArdG9l5NpdmQhtceaFGsPiWuJxGxRzS4i95veUHWkhMpEYDEEBdcDGxqArvQCvzSlngdttQCfx8OUkBTb3B"
"A2okpTwwJfqPsxVetA6qR7UNc+fVb6KHwvm0bzi2rQ3xw3D/syRHwdMkpoVDQPCk43H9WufgfBKRen87dFwIDAQABo4ICPzCCAjs"
"wHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFGS/RLNGCZvPWh1xSaIEcouINIQjMHsGA1UdEQR0MHK"
"CDnd3dy5naXRodWIuY29tggpnaXRodWIuY29tggwqLmdpdGh1Yi5jb22CCyouZ2l0aHViLmlvgglnaXRodWIuaW+CFyouZ2l0aHV"
"idXNlcmNvbnRlbnQuY29tghVnaXRodWJ1c2VyY29udGVudC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwM"
"BBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3J"
"sMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3JsMEIGA1UdIAQ7MDkwNwYJYIZIAYb"
"9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQc"
"wAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUN"
"lcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAc4dbVmuKvyI7"
"KZ4Txk+ZqcAYToJGKUIVaPL94e5SZGweUisjaCbplAOihnf6Mxt8n6vnuH2IsCaz2NRHqhdcosjT3CwAiJpJNkXPKWVL/txgdSTV"
"2cqB1GG4esFOalvI52dzn+J4fTIYZvNF+AtGyHSLm2XRXYZCw455laUKf6Sk9RDShDgUvzhOKL4GXfTwKXv12MyMknJybH8UCpjC"
"HZmFBVHMcUN/87HsQo20PdOekeEvkjrrMIxW+gxw22Yb67yF/qKgwrWr+43bLN709iyw+LWiU7sQcHL2xk9SYiWQDj2tYz2soObV"
"QYTJm0VUZMEVFhtALq46cx92Zu4vFwC8AAwAAAAABAQAA");
nsCOMPtr<nsISupports> cert;
nsresult rv = NS_DeserializeObject(base64Serialization, getter_AddRefs(cert));
ASSERT_EQ(NS_OK, rv);
ASSERT_TRUE(cert);
}
TEST(psm_DeserializeCert, gecko46)
{
// Gecko 46+ vintage Security info serialized with UUIDs:
// - nsISupports 00000000-0000-0000-c000-000000000046
// - nsISSLStatus fa9ba95b-ca3b-498a-b889-7c79cf28fee8
// - nsIX509Cert bdc3979a-5422-4cd5-8589-696b6e96ea83
nsCString base64Serialization(
"FnhllAKWRHGAlo+ESXykKAAAAAAAAAAAwAAAAAAAAEaphjojH6pBabDSgSnsfLHeAAQAAgAAAAAAAAAAAAAAAAAAAAA"
"B4vFIJp5wRkeyPxAQ9RJGKPqbqVvKO0mKuIl8ec8o/uhmCjImkVxP+7sgiYWmMt8FvcOXmlQiTNWFiWlrbpbqgwAAAAIAAAWzMII"
"FrzCCBJegAwIBAgIQB3pdwzYjAfmJ/lT3+G8+ZDANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUN"
"lcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFN"
"lcnZlciBDQTAeFw0xNjAxMjAwMDAwMDBaFw0xNzA0MDYxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybml"
"hMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxGYXN0bHksIEluYy4xFzAVBgNVBAMTDnd3dy5naXRodWIuY29tMII"
"BIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+9WUCgrgUNwP/JC3cUefLAXeDpq8Ko/U8p8IRvny0Ri0I6Uq0t+RP/nF0LJ"
"Avda8QHYujdgeDTePepBX7+OiwBFhA0YO+rM3C2Z8IRaN/i9eLln+Yyc68+1z+E10s1EXdZrtDGvN6MHqygGsdfkXKfBLUJ1BZEh"
"s9sBnfcjq3kh5gZdBArdG9l5NpdmQhtceaFGsPiWuJxGxRzS4i95veUHWkhMpEYDEEBdcDGxqArvQCvzSlngdttQCfx8OUkBTb3B"
"A2okpTwwJfqPsxVetA6qR7UNc+fVb6KHwvm0bzi2rQ3xw3D/syRHwdMkpoVDQPCk43H9WufgfBKRen87dFwIDAQABo4ICSTCCAkU"
"wHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFGS/RLNGCZvPWh1xSaIEcouINIQjMHsGA1UdEQR0MHK"
"CDnd3dy5naXRodWIuY29tggwqLmdpdGh1Yi5jb22CCmdpdGh1Yi5jb22CCyouZ2l0aHViLmlvgglnaXRodWIuaW+CFyouZ2l0aHV"
"idXNlcmNvbnRlbnQuY29tghVnaXRodWJ1c2VyY29udGVudC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwM"
"BBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzUuY3J"
"sMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzUuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb"
"9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcBAQR3MHU"
"wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQ"
"uY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQE"
"ATxbRdPg+o49+96/P+rbdp4ie+CGtfCgUubT/Z9C54k+BfQO0nbxVgCSM5WZQuLgo2Q+0lcxisod8zxZeU0j5wviQINwOln/iN89"
"Bx3VmDRynTe4CqhsAwOoO1ERmCAmsAJBwY/rNr4mK22p8erBrqMW0nYXYU5NFynI+pNTjojhKD4II8PNV8G2yMWwYOb/u4+WPzUA"
"HC9DpZdrWTEH/W69Cr/KxRqGsWPwpgMv2Wqav8jaT35JxqTXjOlhQqzo6fNn3eYOeCf4PkCxZKwckWjy10qDaRbjhwAMHAGj2TPr"
"idlvOj/7QyyX5m8up/1US8z1fRW4yoCSOt6V2bwuH6cAvAAMAAAAAAQEAAA==");
nsCOMPtr<nsISupports> cert;
nsresult rv = NS_DeserializeObject(base64Serialization, getter_AddRefs(cert));
ASSERT_EQ(NS_OK, rv);
ASSERT_TRUE(cert);
}

View file

@ -0,0 +1,76 @@
/* -*- 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/. */
// This file tests the md4.c implementation.
#include "gtest/gtest.h"
#include "md4.h"
#include "mozilla/Casting.h"
#include "mozilla/PodOperations.h"
struct RFC1320TestParams
{
const char* data;
const uint8_t expectedHash[16];
};
static const RFC1320TestParams RFC1320_TEST_PARAMS[] =
{
{
"",
{ 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }
},
{
"a",
{ 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }
},
{
"abc",
{ 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }
},
{
"message digest",
{ 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }
},
{
"abcdefghijklmnopqrstuvwxyz",
{ 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 },
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{ 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 },
},
{
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{ 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 },
}
};
class psm_MD4
: public ::testing::Test
, public ::testing::WithParamInterface<RFC1320TestParams>
{
};
TEST_P(psm_MD4, RFC1320TestValues)
{
const RFC1320TestParams& params(GetParam());
uint8_t actualHash[16];
md4sum(mozilla::BitwiseCast<const uint8_t*, const char*>(params.data),
strlen(params.data), actualHash);
EXPECT_TRUE(mozilla::PodEqual(actualHash, params.expectedHash))
<< "MD4 hashes aren't equal for input: '" << params.data << "'";
}
INSTANTIATE_TEST_CASE_P(psm_MD4, psm_MD4,
testing::ValuesIn(RFC1320_TEST_PARAMS));

View file

@ -0,0 +1,337 @@
/* -*- 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 "CertVerifier.h"
#include "OCSPCache.h"
#include "gtest/gtest.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/Casting.h"
#include "mozilla/Sprintf.h"
#include "nss.h"
#include "pkix/pkixtypes.h"
#include "pkixtestutil.h"
#include "prerr.h"
#include "secerr.h"
using namespace mozilla::pkix;
using namespace mozilla::pkix::test;
using mozilla::NeckoOriginAttributes;
template <size_t N>
inline Input
LiteralInput(const char(&valueString)[N])
{
// Ideally we would use mozilla::BitwiseCast() here rather than
// reinterpret_cast for better type checking, but the |N - 1| part trips
// static asserts.
return Input(reinterpret_cast<const uint8_t(&)[N - 1]>(valueString));
}
const int MaxCacheEntries = 1024;
class psm_OCSPCacheTest : public ::testing::Test
{
protected:
psm_OCSPCacheTest() : now(Now()) { }
static void SetUpTestCase()
{
NSS_NoDB_Init(nullptr);
}
const Time now;
mozilla::psm::OCSPCache cache;
};
static void
PutAndGet(mozilla::psm::OCSPCache& cache, const CertID& certID, Result result,
Time time,
const NeckoOriginAttributes& originAttributes = NeckoOriginAttributes())
{
// The first time is thisUpdate. The second is validUntil.
// The caller is expecting the validUntil returned with Get
// to be equal to the passed-in time. Since these values will
// be different in practice, make thisUpdate less than validUntil.
Time thisUpdate(time);
ASSERT_EQ(Success, thisUpdate.SubtractSeconds(10));
Result rv = cache.Put(certID, originAttributes, result, thisUpdate, time);
ASSERT_TRUE(rv == Success);
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_TRUE(cache.Get(certID, originAttributes, resultOut, timeOut));
ASSERT_EQ(result, resultOut);
ASSERT_EQ(time, timeOut);
}
Input fakeIssuer1(LiteralInput("CN=issuer1"));
Input fakeKey000(LiteralInput("key000"));
Input fakeKey001(LiteralInput("key001"));
Input fakeSerial0000(LiteralInput("0000"));
TEST_F(psm_OCSPCacheTest, TestPutAndGet)
{
Input fakeSerial000(LiteralInput("000"));
Input fakeSerial001(LiteralInput("001"));
SCOPED_TRACE("");
PutAndGet(cache, CertID(fakeIssuer1, fakeKey000, fakeSerial001),
Success, now);
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_FALSE(cache.Get(CertID(fakeIssuer1, fakeKey001, fakeSerial000),
NeckoOriginAttributes(), resultOut, timeOut));
}
TEST_F(psm_OCSPCacheTest, TestVariousGets)
{
SCOPED_TRACE("");
for (int i = 0; i < MaxCacheEntries; i++) {
uint8_t serialBuf[8];
snprintf(mozilla::BitwiseCast<char*, uint8_t*>(serialBuf), sizeof(serialBuf),
"%04d", i);
Input fakeSerial;
ASSERT_EQ(Success, fakeSerial.Init(serialBuf, 4));
Time timeIn(now);
ASSERT_EQ(Success, timeIn.AddSeconds(i));
PutAndGet(cache, CertID(fakeIssuer1, fakeKey000, fakeSerial),
Success, timeIn);
}
Time timeIn(now);
Result resultOut;
Time timeOut(Time::uninitialized);
// This will be at the end of the list in the cache
CertID cert0000(fakeIssuer1, fakeKey000, fakeSerial0000);
ASSERT_TRUE(cache.Get(cert0000, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(timeIn, timeOut);
// Once we access it, it goes to the front
ASSERT_TRUE(cache.Get(cert0000, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(timeIn, timeOut);
// This will be in the middle
Time timeInPlus512(now);
ASSERT_EQ(Success, timeInPlus512.AddSeconds(512));
static const Input fakeSerial0512(LiteralInput("0512"));
CertID cert0512(fakeIssuer1, fakeKey000, fakeSerial0512);
ASSERT_TRUE(cache.Get(cert0512, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(timeInPlus512, timeOut);
ASSERT_TRUE(cache.Get(cert0512, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(timeInPlus512, timeOut);
// We've never seen this certificate
static const Input fakeSerial1111(LiteralInput("1111"));
ASSERT_FALSE(cache.Get(CertID(fakeIssuer1, fakeKey000, fakeSerial1111),
NeckoOriginAttributes(), resultOut, timeOut));
}
TEST_F(psm_OCSPCacheTest, TestEviction)
{
SCOPED_TRACE("");
// By putting more distinct entries in the cache than it can hold,
// we cause the least recently used entry to be evicted.
for (int i = 0; i < MaxCacheEntries + 1; i++) {
uint8_t serialBuf[8];
snprintf(mozilla::BitwiseCast<char*, uint8_t*>(serialBuf), sizeof(serialBuf),
"%04d", i);
Input fakeSerial;
ASSERT_EQ(Success, fakeSerial.Init(serialBuf, 4));
Time timeIn(now);
ASSERT_EQ(Success, timeIn.AddSeconds(i));
PutAndGet(cache, CertID(fakeIssuer1, fakeKey000, fakeSerial),
Success, timeIn);
}
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_FALSE(cache.Get(CertID(fakeIssuer1, fakeKey001, fakeSerial0000),
NeckoOriginAttributes(), resultOut, timeOut));
}
TEST_F(psm_OCSPCacheTest, TestNoEvictionForRevokedResponses)
{
SCOPED_TRACE("");
CertID notEvicted(fakeIssuer1, fakeKey000, fakeSerial0000);
Time timeIn(now);
PutAndGet(cache, notEvicted, Result::ERROR_REVOKED_CERTIFICATE, timeIn);
// By putting more distinct entries in the cache than it can hold,
// we cause the least recently used entry that isn't revoked to be evicted.
for (int i = 1; i < MaxCacheEntries + 1; i++) {
uint8_t serialBuf[8];
snprintf(mozilla::BitwiseCast<char*, uint8_t*>(serialBuf), sizeof(serialBuf),
"%04d", i);
Input fakeSerial;
ASSERT_EQ(Success, fakeSerial.Init(serialBuf, 4));
Time timeIn(now);
ASSERT_EQ(Success, timeIn.AddSeconds(i));
PutAndGet(cache, CertID(fakeIssuer1, fakeKey000, fakeSerial),
Success, timeIn);
}
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_TRUE(cache.Get(notEvicted, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE, resultOut);
ASSERT_EQ(timeIn, timeOut);
Input fakeSerial0001(LiteralInput("0001"));
CertID evicted(fakeIssuer1, fakeKey000, fakeSerial0001);
ASSERT_FALSE(cache.Get(evicted, NeckoOriginAttributes(), resultOut, timeOut));
}
TEST_F(psm_OCSPCacheTest, TestEverythingIsRevoked)
{
SCOPED_TRACE("");
Time timeIn(now);
// Fill up the cache with revoked responses.
for (int i = 0; i < MaxCacheEntries; i++) {
uint8_t serialBuf[8];
snprintf(mozilla::BitwiseCast<char*, uint8_t*>(serialBuf), sizeof(serialBuf),
"%04d", i);
Input fakeSerial;
ASSERT_EQ(Success, fakeSerial.Init(serialBuf, 4));
Time timeIn(now);
ASSERT_EQ(Success, timeIn.AddSeconds(i));
PutAndGet(cache, CertID(fakeIssuer1, fakeKey000, fakeSerial),
Result::ERROR_REVOKED_CERTIFICATE, timeIn);
}
static const Input fakeSerial1025(LiteralInput("1025"));
CertID good(fakeIssuer1, fakeKey000, fakeSerial1025);
// This will "succeed", allowing verification to continue. However,
// nothing was actually put in the cache.
Time timeInPlus1025(timeIn);
ASSERT_EQ(Success, timeInPlus1025.AddSeconds(1025));
Time timeInPlus1025Minus50(timeInPlus1025);
ASSERT_EQ(Success, timeInPlus1025Minus50.SubtractSeconds(50));
Result result = cache.Put(good, NeckoOriginAttributes(), Success, timeInPlus1025Minus50,
timeInPlus1025);
ASSERT_EQ(Success, result);
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_FALSE(cache.Get(good, NeckoOriginAttributes(), resultOut, timeOut));
static const Input fakeSerial1026(LiteralInput("1026"));
CertID revoked(fakeIssuer1, fakeKey000, fakeSerial1026);
// This will fail, causing verification to fail.
Time timeInPlus1026(timeIn);
ASSERT_EQ(Success, timeInPlus1026.AddSeconds(1026));
Time timeInPlus1026Minus50(timeInPlus1026);
ASSERT_EQ(Success, timeInPlus1026Minus50.SubtractSeconds(50));
result = cache.Put(revoked, NeckoOriginAttributes(), Result::ERROR_REVOKED_CERTIFICATE,
timeInPlus1026Minus50, timeInPlus1026);
ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE, result);
}
TEST_F(psm_OCSPCacheTest, VariousIssuers)
{
SCOPED_TRACE("");
Time timeIn(now);
static const Input fakeIssuer2(LiteralInput("CN=issuer2"));
static const Input fakeSerial001(LiteralInput("001"));
CertID subject(fakeIssuer1, fakeKey000, fakeSerial001);
PutAndGet(cache, subject, Success, now);
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_TRUE(cache.Get(subject, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(timeIn, timeOut);
// Test that we don't match a different issuer DN
ASSERT_FALSE(cache.Get(CertID(fakeIssuer2, fakeKey000, fakeSerial001),
NeckoOriginAttributes(), resultOut, timeOut));
// Test that we don't match a different issuer key
ASSERT_FALSE(cache.Get(CertID(fakeIssuer1, fakeKey001, fakeSerial001),
NeckoOriginAttributes(), resultOut, timeOut));
}
TEST_F(psm_OCSPCacheTest, Times)
{
SCOPED_TRACE("");
CertID certID(fakeIssuer1, fakeKey000, fakeSerial0000);
PutAndGet(cache, certID, Result::ERROR_OCSP_UNKNOWN_CERT,
TimeFromElapsedSecondsAD(100));
PutAndGet(cache, certID, Success, TimeFromElapsedSecondsAD(200));
// This should not override the more recent entry.
ASSERT_EQ(Success,
cache.Put(certID, NeckoOriginAttributes(), Result::ERROR_OCSP_UNKNOWN_CERT,
TimeFromElapsedSecondsAD(100),
TimeFromElapsedSecondsAD(100)));
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_TRUE(cache.Get(certID, NeckoOriginAttributes(), resultOut, timeOut));
// Here we see the more recent time.
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(TimeFromElapsedSecondsAD(200), timeOut);
// Result::ERROR_REVOKED_CERTIFICATE overrides everything
PutAndGet(cache, certID, Result::ERROR_REVOKED_CERTIFICATE,
TimeFromElapsedSecondsAD(50));
}
TEST_F(psm_OCSPCacheTest, NetworkFailure)
{
SCOPED_TRACE("");
CertID certID(fakeIssuer1, fakeKey000, fakeSerial0000);
PutAndGet(cache, certID, Result::ERROR_CONNECT_REFUSED,
TimeFromElapsedSecondsAD(100));
PutAndGet(cache, certID, Success, TimeFromElapsedSecondsAD(200));
// This should not override the already present entry.
ASSERT_EQ(Success,
cache.Put(certID, NeckoOriginAttributes(), Result::ERROR_CONNECT_REFUSED,
TimeFromElapsedSecondsAD(300),
TimeFromElapsedSecondsAD(350)));
Result resultOut;
Time timeOut(Time::uninitialized);
ASSERT_TRUE(cache.Get(certID, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Success, resultOut);
ASSERT_EQ(TimeFromElapsedSecondsAD(200), timeOut);
PutAndGet(cache, certID, Result::ERROR_OCSP_UNKNOWN_CERT,
TimeFromElapsedSecondsAD(400));
// This should not override the already present entry.
ASSERT_EQ(Success,
cache.Put(certID, NeckoOriginAttributes(), Result::ERROR_CONNECT_REFUSED,
TimeFromElapsedSecondsAD(500),
TimeFromElapsedSecondsAD(550)));
ASSERT_TRUE(cache.Get(certID, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Result::ERROR_OCSP_UNKNOWN_CERT, resultOut);
ASSERT_EQ(TimeFromElapsedSecondsAD(400), timeOut);
PutAndGet(cache, certID, Result::ERROR_REVOKED_CERTIFICATE,
TimeFromElapsedSecondsAD(600));
// This should not override the already present entry.
ASSERT_EQ(Success,
cache.Put(certID, NeckoOriginAttributes(), Result::ERROR_CONNECT_REFUSED,
TimeFromElapsedSecondsAD(700),
TimeFromElapsedSecondsAD(750)));
ASSERT_TRUE(cache.Get(certID, NeckoOriginAttributes(), resultOut, timeOut));
ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE, resultOut);
ASSERT_EQ(TimeFromElapsedSecondsAD(600), timeOut);
}
TEST_F(psm_OCSPCacheTest, TestOriginAttributes)
{
CertID certID(fakeIssuer1, fakeKey000, fakeSerial0000);
SCOPED_TRACE("");
NeckoOriginAttributes attrs;
attrs.mFirstPartyDomain.AssignLiteral("foo.com");
PutAndGet(cache, certID, Success, now, attrs);
Result resultOut;
Time timeOut(Time::uninitialized);
attrs.mFirstPartyDomain.AssignLiteral("bar.com");
ASSERT_FALSE(cache.Get(certID, attrs, resultOut, timeOut));
// OCSP cache should not be isolated by containers.
attrs.mUserContextId = 1;
attrs.mFirstPartyDomain.AssignLiteral("foo.com");
ASSERT_TRUE(cache.Get(certID, attrs, resultOut, timeOut));
}

View file

@ -0,0 +1,2 @@
Please name all test cases in this directory with the prefix "psm". This makes
it easier to run all PSM related GTests at once.

View file

@ -0,0 +1,144 @@
/* 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 <stdio.h>
#include "gtest/gtest.h"
#include "nsNetUtil.h"
#include "nsISiteSecurityService.h"
#include "nsIURI.h"
void
TestSuccess(const char* hdr, bool extraTokens,
uint64_t expectedMaxAge, bool expectedIncludeSubdomains,
nsISiteSecurityService* sss)
{
nsCOMPtr<nsIURI> dummyUri;
nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
ASSERT_TRUE(NS_SUCCEEDED(rv)) << "Failed to create URI";
uint64_t maxAge = 0;
bool includeSubdomains = false;
rv = sss->UnsafeProcessHeader(nsISiteSecurityService::HEADER_HSTS, dummyUri,
hdr, 0, &maxAge, &includeSubdomains, nullptr);
ASSERT_TRUE(NS_SUCCEEDED(rv)) << "Failed to process valid header: " << hdr;
ASSERT_EQ(maxAge, expectedMaxAge) << "Did not correctly parse maxAge";
EXPECT_EQ(includeSubdomains, expectedIncludeSubdomains) <<
"Did not correctly parse presence/absence of includeSubdomains";
if (extraTokens) {
EXPECT_EQ(rv, NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA) <<
"Extra tokens were expected when parsing, but were not encountered.";
} else {
EXPECT_EQ(rv, NS_OK) << "Unexpected tokens found during parsing.";
}
printf("%s\n", hdr);
}
void TestFailure(const char* hdr,
nsISiteSecurityService* sss)
{
nsCOMPtr<nsIURI> dummyUri;
nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
ASSERT_TRUE(NS_SUCCEEDED(rv)) << "Failed to create URI";
rv = sss->UnsafeProcessHeader(nsISiteSecurityService::HEADER_HSTS, dummyUri,
hdr, 0, nullptr, nullptr, nullptr);
ASSERT_TRUE(NS_FAILED(rv)) << "Parsed invalid header: " << hdr;
printf("%s\n", hdr);
}
TEST(psm_STSParser, Test)
{
nsresult rv;
// grab handle to the service
nsCOMPtr<nsISiteSecurityService> sss;
sss = do_GetService("@mozilla.org/ssservice;1", &rv);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// *** parsing tests
printf("*** Attempting to parse valid STS headers ...\n");
// SHOULD SUCCEED:
TestSuccess("max-age=100", false, 100, false, sss);
TestSuccess("max-age =100", false, 100, false, sss);
TestSuccess(" max-age=100", false, 100, false, sss);
TestSuccess("max-age = 100 ", false, 100, false, sss);
TestSuccess("max-age = \"100\" ", false, 100, false, sss);
TestSuccess("max-age=\"100\"", false, 100, false, sss);
TestSuccess(" max-age =\"100\" ", false, 100, false, sss);
TestSuccess("\tmax-age\t=\t\"100\"\t", false, 100, false, sss);
TestSuccess("max-age = 100 ", false, 100, false, sss);
TestSuccess("maX-aGe=100", false, 100, false, sss);
TestSuccess("MAX-age =100", false, 100, false, sss);
TestSuccess("max-AGE=100", false, 100, false, sss);
TestSuccess("Max-Age = 100 ", false, 100, false, sss);
TestSuccess("MAX-AGE = 100 ", false, 100, false, sss);
TestSuccess("max-age=100;includeSubdomains", false, 100, true, sss);
TestSuccess("max-age=100\t; includeSubdomains", false, 100, true, sss);
TestSuccess(" max-age=100; includeSubdomains", false, 100, true, sss);
TestSuccess("max-age = 100 ; includeSubdomains", false, 100, true, sss);
TestSuccess("max-age = 100 ; includeSubdomains",
false, 100, true, sss);
TestSuccess("maX-aGe=100; includeSUBDOMAINS", false, 100, true, sss);
TestSuccess("MAX-age =100; includeSubDomains", false, 100, true, sss);
TestSuccess("max-AGE=100; iNcLuDeSuBdoMaInS", false, 100, true, sss);
TestSuccess("Max-Age = 100; includesubdomains ", false, 100, true, sss);
TestSuccess("INCLUDESUBDOMAINS;MaX-AgE = 100 ", false, 100, true, sss);
// Turns out, the actual directive is entirely optional (hence the
// trailing semicolon)
TestSuccess("max-age=100;includeSubdomains;", true, 100, true, sss);
// these are weird tests, but are testing that some extended syntax is
// still allowed (but it is ignored)
TestSuccess("max-age=100 ; includesubdomainsSomeStuff",
true, 100, false, sss);
TestSuccess("\r\n\t\t \tcompletelyUnrelated = foobar; max-age= 34520103"
"\t \t; alsoUnrelated;asIsThis;\tincludeSubdomains\t\t \t",
true, 34520103, true, sss);
TestSuccess("max-age=100; unrelated=\"quoted \\\"thingy\\\"\"",
true, 100, false, sss);
// SHOULD FAIL:
printf("* Attempting to parse invalid STS headers (should not parse)...\n");
// invalid max-ages
TestFailure("max-age", sss);
TestFailure("max-age ", sss);
TestFailure("max-age=p", sss);
TestFailure("max-age=*1p2", sss);
TestFailure("max-age=.20032", sss);
TestFailure("max-age=!20032", sss);
TestFailure("max-age==20032", sss);
// invalid headers
TestFailure("foobar", sss);
TestFailure("maxage=100", sss);
TestFailure("maxa-ge=100", sss);
TestFailure("max-ag=100", sss);
TestFailure("includesubdomains", sss);
TestFailure(";", sss);
TestFailure("max-age=\"100", sss);
// The max-age directive here doesn't conform to the spec, so it MUST
// be ignored. Consequently, the REQUIRED max-age directive is not
// present in this header, and so it is invalid.
TestFailure("max-age=100, max-age=200; includeSubdomains", sss);
TestFailure("max-age=100 includesubdomains", sss);
TestFailure("max-age=100 bar foo", sss);
TestFailure("max-age=100randomstuffhere", sss);
// All directives MUST appear only once in an STS header field.
TestFailure("max-age=100; max-age=200", sss);
TestFailure("includeSubdomains; max-age=200; includeSubdomains", sss);
TestFailure("max-age=200; includeSubdomains; includeSubdomains", sss);
// The includeSubdomains directive is valueless.
TestFailure("max-age=100; includeSubdomains=unexpected", sss);
// LWS must have at least one space or horizontal tab
TestFailure("\r\nmax-age=200", sss);
}

View file

@ -0,0 +1,568 @@
/* -*- 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 "sslerr.h"
#include "gtest/gtest.h"
NS_NAMED_LITERAL_CSTRING(HOST, "example.org");
const int16_t PORT = 443;
class psm_TLSIntoleranceTest : public ::testing::Test
{
protected:
nsSSLIOLayerHelpers helpers;
};
TEST_F(psm_TLSIntoleranceTest, FullFallbackProcess)
{
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, helpers.mVersionFallbackLimit);
// No adjustment made when there is no entry for the site.
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
ASSERT_TRUE(
helpers.rememberStrongCiphersFailed(
HOST, PORT, SSL_ERROR_NO_CYPHER_OVERLAP));
ASSERT_EQ(SSL_ERROR_NO_CYPHER_OVERLAP,
helpers.getIntoleranceReason(HOST, PORT));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_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);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
}
}
TEST_F(psm_TLSIntoleranceTest, DisableFallbackWithHighLimit)
{
// this value disables version fallback entirely: with this value, all efforts
// to mark an origin as version intolerant fail
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_2;
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1,
0));
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_0,
0));
}
TEST_F(psm_TLSIntoleranceTest, FallbackLimitBelowMin)
{
// check that we still respect the minimum version,
// when it is higher than the fallback limit
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
}
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_1,
0));
}
TEST_F(psm_TLSIntoleranceTest, TolerantOverridesIntolerant1)
{
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1,
0));
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
TEST_F(psm_TLSIntoleranceTest, TolerantOverridesIntolerant2)
{
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1,
0));
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_2);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
TEST_F(psm_TLSIntoleranceTest, IntolerantDoesNotOverrideTolerant)
{
// No adjustment made when there is no entry for the site.
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
// false because we reached the floor set by rememberTolerantAtVersion.
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1,
0));
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
TEST_F(psm_TLSIntoleranceTest, PortIsRelevant)
{
helpers.rememberTolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_2);
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, 1,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, 2,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, 1, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, 2, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
}
}
TEST_F(psm_TLSIntoleranceTest, IntoleranceReasonInitial)
{
ASSERT_EQ(0, helpers.getIntoleranceReason(HOST, 1));
helpers.rememberTolerantAtVersion(HOST, 2, SSL_LIBRARY_VERSION_TLS_1_2);
ASSERT_EQ(0, helpers.getIntoleranceReason(HOST, 2));
}
TEST_F(psm_TLSIntoleranceTest, IntoleranceReasonStored)
{
helpers.rememberIntolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
SSL_ERROR_BAD_SERVER);
ASSERT_EQ(SSL_ERROR_BAD_SERVER, helpers.getIntoleranceReason(HOST, 1));
helpers.rememberIntolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1,
SSL_ERROR_BAD_MAC_READ);
ASSERT_EQ(SSL_ERROR_BAD_MAC_READ, helpers.getIntoleranceReason(HOST, 1));
}
TEST_F(psm_TLSIntoleranceTest, IntoleranceReasonCleared)
{
ASSERT_EQ(0, helpers.getIntoleranceReason(HOST, 1));
helpers.rememberIntolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
ASSERT_EQ(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT,
helpers.getIntoleranceReason(HOST, 1));
helpers.rememberTolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_2);
ASSERT_EQ(0, helpers.getIntoleranceReason(HOST, 1));
}
TEST_F(psm_TLSIntoleranceTest, StrongCiphersFailed)
{
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_1;
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_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);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
}
}
TEST_F(psm_TLSIntoleranceTest, StrongCiphersFailedAt1_1)
{
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_0;
// No adjustment made when there is no entry for the site.
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
range.min, range.max, 0));
}
{
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
}
}
TEST_F(psm_TLSIntoleranceTest, StrongCiphersFailedWithHighLimit)
{
// this value disables version fallback entirely: with this value, all efforts
// to mark an origin as version intolerant fail
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_2;
// ...but weak ciphers fallback will not be disabled
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1,
0));
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_0,
0));
}
TEST_F(psm_TLSIntoleranceTest, TolerantDoesNotOverrideWeakCiphersFallback)
{
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
// No adjustment made when intolerant is zero.
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
}
TEST_F(psm_TLSIntoleranceTest, WeakCiphersFallbackDoesNotOverrideTolerant)
{
// No adjustment made when there is no entry for the site.
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
// false because strongCipherWorked is set by rememberTolerantAtVersion.
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
TEST_F(psm_TLSIntoleranceTest, TLSForgetIntolerance)
{
{
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
}
{
helpers.forgetIntolerance(HOST, PORT);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
}
}
TEST_F(psm_TLSIntoleranceTest, TLSForgetStrongCipherFailed)
{
{
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
}
{
helpers.forgetIntolerance(HOST, PORT);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
}
}
TEST_F(psm_TLSIntoleranceTest, TLSDontForgetTolerance)
{
{
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
{
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2,
0));
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
{
helpers.forgetIntolerance(HOST, PORT);
SSLVersionRange range = { SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2 };
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.min);
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
}
}
TEST_F(psm_TLSIntoleranceTest, TLSPerSiteFallbackLimit)
{
NS_NAMED_LITERAL_CSTRING(example_com, "example.com");
NS_NAMED_LITERAL_CSTRING(example_net, "example.net");
NS_NAMED_LITERAL_CSTRING(example_org, "example.org");
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_0;
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_FALSE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_2;
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
helpers.setInsecureFallbackSites(example_com);
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
helpers.setInsecureFallbackSites(NS_LITERAL_CSTRING("example.com,example.net"));
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
helpers.setInsecureFallbackSites(example_net);
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
helpers.setInsecureFallbackSites(EmptyCString());
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
}

View file

@ -0,0 +1,29 @@
# -*- Mode: python; 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/.
SOURCES += [
'CertDBTest.cpp',
'DataStorageTest.cpp',
'DeserializeCertTest.cpp',
'MD4Test.cpp',
'OCSPCacheTest.cpp',
'STSParserTest.cpp',
'TLSIntoleranceTest.cpp',
]
LOCAL_INCLUDES += [
'/security/certverifier',
'/security/manager/ssl',
'/security/pkix/include',
'/security/pkix/test/lib',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

View file

@ -0,0 +1,5 @@
"use strict";
module.exports = { // eslint-disable-line no-undef
"extends": "../../../../../../testing/mochitest/browser.eslintrc.js"
};

View file

@ -0,0 +1,18 @@
[DEFAULT]
tags = psm
support-files =
head.js
*.pem
[browser_bug627234_perwindowpb.js]
[browser_certificateManagerLeak.js]
[browser_certViewer.js]
[browser_clientAuth_connection.js]
[browser_clientAuth_ui.js]
[browser_deleteCert_ui.js]
[browser_downloadCert_ui.js]
[browser_editCACertTrust.js]
# An earlier attempt at landing this test resulted in frequent intermittent
# failures, almost entirely on Linux. See Bug 1309519.
skip-if = os == "linux"
[browser_exportP12_passwordUI.js]

View file

@ -0,0 +1,102 @@
/* 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/. */
"use strict";
var FakeSSLStatus = function() {
};
FakeSSLStatus.prototype = {
serverCert: null,
cipherName: null,
keyLength: 2048,
isDomainMismatch: false,
isNotValidAtThisTime: false,
isUntrusted: false,
isExtendedValidation: false,
getInterface: function(aIID) {
return this.QueryInterface(aIID);
},
QueryInterface: function(aIID) {
if (aIID.equals(Ci.nsISSLStatus) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw new Error(Cr.NS_ERROR_NO_INTERFACE);
},
};
function whenNewWindowLoaded(aOptions, aCallback) {
let win = OpenBrowserWindow(aOptions);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
aCallback(win);
}, false);
}
// This is a template to help porting global private browsing tests
// to per-window private browsing tests
function test() {
// initialization
waitForExplicitFinish();
let windowsToClose = [];
let testURI = "about:blank";
let uri;
let gSSService = Cc["@mozilla.org/ssservice;1"].
getService(Ci.nsISiteSecurityService);
function privacyFlags(aIsPrivateMode) {
return aIsPrivateMode ? Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
}
function doTest(aIsPrivateMode, aWindow, aCallback) {
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
let sslStatus = new FakeSSLStatus();
uri = aWindow.Services.io.newURI("https://localhost/img.png", null, null);
gSSService.processHeader(Ci.nsISiteSecurityService.HEADER_HSTS, uri,
"max-age=1000", sslStatus, privacyFlags(aIsPrivateMode));
ok(gSSService.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS, "localhost", privacyFlags(aIsPrivateMode)), "checking sts host");
aCallback();
}, true);
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
}
function testOnWindow(aOptions, aCallback) {
whenNewWindowLoaded(aOptions, function(aWin) {
windowsToClose.push(aWin);
// execute should only be called when need, like when you are opening
// web pages on the test. If calling executeSoon() is not necesary, then
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
executeSoon(function() { aCallback(aWin); });
});
}
// this function is called after calling finish() on the test.
registerCleanupFunction(function() {
windowsToClose.forEach(function(aWin) {
aWin.close();
});
uri = Services.io.newURI("http://localhost", null, null);
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
});
// test first when on private mode
testOnWindow({private: true}, function(aWin) {
doTest(true, aWin, function() {
//test when not on private mode
testOnWindow({}, function(aWin) {
doTest(false, aWin, function() {
//test again when on private mode
testOnWindow({private: true}, function(aWin) {
doTest(true, aWin, function () {
finish();
});
});
});
});
});
});
}

View file

@ -0,0 +1,224 @@
/* 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/. */
"use strict";
// Repeatedly opens the certificate viewer dialog with various certificates and
// determines that the viewer correctly identifies either what usages those
// certificates are valid for or what errors prevented the certificates from
// being verified.
var { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
add_task(function* testCAandTitle() {
let cert = yield readCertificate("ca.pem", "CTu,CTu,CTu");
let win = yield displayCertificate(cert);
checkUsages(win, ["SSL Certificate Authority"]);
// There's no real need to test the title for every cert, so we just test it
// once here.
Assert.equal(win.document.title, "Certificate Viewer: \u201Cca\u201D",
"Actual and expected title should match");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testSSLEndEntity() {
let cert = yield readCertificate("ssl-ee.pem", ",,");
let win = yield displayCertificate(cert);
checkUsages(win, ["SSL Server Certificate", "SSL Client Certificate"]);
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testEmailEndEntity() {
let cert = yield readCertificate("email-ee.pem", ",,");
let win = yield displayCertificate(cert);
checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate"]);
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testCodeSignEndEntity() {
let cert = yield readCertificate("code-ee.pem", ",,");
let win = yield displayCertificate(cert);
checkUsages(win, ["Object Signer"]);
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testExpired() {
let cert = yield readCertificate("expired-ca.pem", ",,");
let win = yield displayCertificate(cert);
checkError(win, "Could not verify this certificate because it has expired.");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testIssuerExpired() {
let cert = yield readCertificate("ee-from-expired-ca.pem", ",,");
let win = yield displayCertificate(cert);
checkError(win,
"Could not verify this certificate because the CA certificate " +
"is invalid.");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testUnknownIssuer() {
let cert = yield readCertificate("unknown-issuer.pem", ",,");
let win = yield displayCertificate(cert);
checkError(win,
"Could not verify this certificate because the issuer is " +
"unknown.");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testInsecureAlgo() {
let cert = yield readCertificate("md5-ee.pem", ",,");
let win = yield displayCertificate(cert);
checkError(win,
"Could not verify this certificate because it was signed using " +
"a signature algorithm that was disabled because that algorithm " +
"is not secure.");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testUntrusted() {
let cert = yield readCertificate("untrusted-ca.pem", "p,p,p");
let win = yield displayCertificate(cert);
checkError(win,
"Could not verify this certificate because it is not trusted.");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testUntrustedIssuer() {
let cert = yield readCertificate("ee-from-untrusted-ca.pem", ",,");
let win = yield displayCertificate(cert);
checkError(win,
"Could not verify this certificate because the issuer is not " +
"trusted.");
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testRevoked() {
// Note that there's currently no way to un-do this. This should only be a
// problem if another test re-uses a certificate with this same key (perhaps
// likely) and subject (less likely).
let certBlocklist = Cc["@mozilla.org/security/certblocklist;1"]
.getService(Ci.nsICertBlocklist);
certBlocklist.revokeCertBySubjectAndPubKey(
"MBIxEDAOBgNVBAMMB3Jldm9rZWQ=", // CN=revoked
"VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="); // hash of the shared key
let cert = yield readCertificate("revoked.pem", ",,");
let win = yield displayCertificate(cert);
// As of bug 1312827, OneCRL only applies to TLS web server certificates, so
// this certificate will actually verify successfully for every end-entity
// usage except TLS web server.
checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate",
"Object Signer", "SSL Client Certificate"]);
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* testInvalid() {
// This certificate has a keyUsage extension asserting cRLSign and
// keyCertSign, but it doesn't have a basicConstraints extension. This
// shouldn't be valid for any usage. Sadly, we give a pretty lame error
// message in this case.
let cert = yield readCertificate("invalid.pem", ",,");
let win = yield displayCertificate(cert);
checkError(win, "Could not verify this certificate for unknown reasons.");
yield BrowserTestUtils.closeWindow(win);
});
/**
* Given a certificate, returns a promise that will resolve when the certificate
* viewer has opened is displaying that certificate, and has finished
* determining its valid usages.
*
* @param {nsIX509Cert} certificate
* The certificate to view and determine usages for.
* @return {Promise}
* A promise that will resolve with a handle on the opened certificate
* viewer window when the usages have been determined.
*/
function displayCertificate(certificate) {
let win = window.openDialog("chrome://pippki/content/certViewer.xul", "",
"", certificate);
return TestUtils.topicObserved("ViewCertDetails:CertUsagesDone",
(subject, data) => subject == win)
.then(([subject, data]) => subject, error => { throw error; });
}
/**
* Given a certificate viewer window, finds the usages the certificate is valid
* for.
*
* @param {window} win
* The certificate viewer window.
* @return {String[]}
* An array of strings describing the usages the certificate is valid
* for.
*/
function getUsages(win) {
let determinedUsages = [];
let verifyInfoBox = win.document.getElementById("verify_info_box");
Array.from(verifyInfoBox.children).forEach(child => {
if (child.getAttribute("hidden") != "true" &&
child.getAttribute("id") != "verified") {
determinedUsages.push(child.getAttribute("value"));
}
});
return determinedUsages.sort();
}
/**
* Given a certificate viewer window, returns the error string describing a
* failure encountered when determining the certificate's usages. It will be
* "This certificate has been verified for the following uses:" when the
* certificate has successfully verified for at least one usage.
*
* @param {window} win
* The certificate viewer window.
* @return {String}
* A string describing the error encountered, or the success message if
* the certificate is valid for at least one usage.
*/
function getError(win) {
return win.document.getElementById("verified").textContent;
}
/**
* Given a certificate viewer window and an array of expected usage
* descriptions, verifies that the window is actually showing that the
* certificate has validated for those usages.
*
* @param {window} win
* The certificate viewer window.
* @param {String[]} usages
* An array of expected usage descriptions.
*/
function checkUsages(win, usages) {
Assert.equal(getError(win),
"This certificate has been verified for the following uses:",
"should have successful verification message");
let determinedUsages = getUsages(win);
usages.sort();
Assert.equal(determinedUsages.length, usages.length,
"number of usages as determined by cert viewer should be equal");
while (usages.length > 0) {
Assert.equal(determinedUsages.pop(), usages.pop(),
"usages as determined by cert viewer should be equal");
}
}
/**
* Given a certificate viewer window and an expected error, verifies that the
* window is actually showing that error.
*
* @param {window} win
* The certificate viewer window.
* @param {String} error
* The expected error message.
*/
function checkError(win, error) {
let determinedUsages = getUsages(win);
Assert.equal(determinedUsages.length, 0,
"should not have any successful usages in error case");
Assert.equal(getError(win), error,
"determined error should be the same as expected error");
}

View file

@ -0,0 +1,32 @@
/* 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/. */
"use strict";
var gBugWindow;
function onLoad() {
gBugWindow.removeEventListener("load", onLoad);
gBugWindow.addEventListener("unload", onUnload);
gBugWindow.close();
}
function onUnload() {
gBugWindow.removeEventListener("unload", onUnload);
window.focus();
finish();
}
// This test opens and then closes the certificate manager to test that it
// does not leak. The test harness keeps track of and reports leaks, so
// there are no actual checks here.
function test() {
waitForExplicitFinish();
// This test relies on the test timing out in order to indicate failure so
// let's add a dummy pass.
ok(true, "Each test requires at least one pass, fail or todo so here is a pass.");
gBugWindow = window.openDialog("chrome://pippki/content/certManager.xul");
gBugWindow.addEventListener("load", onLoad);
}

View file

@ -0,0 +1,135 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests various scenarios connecting to a server that requires client cert
// authentication. Also tests that nsIClientAuthDialogs.chooseCertificate
// is called at the appropriate times and with the correct arguments.
const { MockRegistrar } =
Cu.import("resource://testing-common/MockRegistrar.jsm", {});
const DialogState = {
// Assert that chooseCertificate() is never called.
ASSERT_NOT_CALLED: "ASSERT_NOT_CALLED",
// Return that the user selected the first given cert.
RETURN_CERT_SELECTED: "RETURN_CERT_SELECTED",
// Return that the user canceled.
RETURN_CERT_NOT_SELECTED: "RETURN_CERT_NOT_SELECTED",
};
let sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
// Mock implementation of nsIClientAuthDialogs.
const gClientAuthDialogs = {
_state: DialogState.ASSERT_NOT_CALLED,
set state(newState) {
info(`old state: ${this._state}`);
this._state = newState;
info(`new state: ${this._state}`);
},
get state() {
return this._state;
},
chooseCertificate(ctx, hostname, port, organization, issuerOrg, certList,
selectedIndex) {
Assert.notEqual(this.state, DialogState.ASSERT_NOT_CALLED,
"chooseCertificate() should be called only when expected");
let caud = ctx.QueryInterface(Ci.nsIClientAuthUserDecision);
Assert.notEqual(caud, null,
"nsIClientAuthUserDecision should be queryable from the " +
"given context");
caud.rememberClientAuthCertificate = false;
Assert.equal(hostname, "requireclientcert.example.com",
"Hostname should be 'requireclientcert.example.com'");
Assert.equal(port, 443, "Port should be 443");
Assert.equal(organization, "",
"Server cert Organization should be empty/not present");
Assert.equal(issuerOrg, "Mozilla Testing",
"Server cert issuer Organization should be 'Mozilla Testing'");
// For mochitests, only the cert at build/pgo/certs/mochitest.client should
// be selectable, so we do some brief checks to confirm this.
Assert.notEqual(certList, null, "Cert list should not be null");
Assert.equal(certList.length, 1, "Only 1 certificate should be available");
let cert = certList.queryElementAt(0, Ci.nsIX509Cert);
Assert.notEqual(cert, null, "Cert list should contain an nsIX509Cert");
Assert.equal(cert.commonName, "Mochitest client",
"Cert CN should be 'Mochitest client'");
if (this.state == DialogState.RETURN_CERT_SELECTED) {
selectedIndex.value = 0;
return true;
}
return false;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIClientAuthDialogs])
};
add_task(function* setup() {
let clientAuthDialogsCID =
MockRegistrar.register("@mozilla.org/nsClientAuthDialogs;1",
gClientAuthDialogs);
registerCleanupFunction(() => {
MockRegistrar.unregister(clientAuthDialogsCID);
});
});
/**
* Test helper for the tests below.
*
* @param {String} prefValue
* Value to set the "security.default_personal_cert" pref to.
* @param {String} expectedURL
* If the connection is expected to load successfully, the URL that
* should load. If the connection is expected to fail and result in an
* error page, |undefined|.
*/
function* testHelper(prefValue, expectedURL) {
yield SpecialPowers.pushPrefEnv({"set": [
["security.default_personal_cert", prefValue],
]});
yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser,
"https://requireclientcert.example.com:443");
// |loadedURL| will be a string URL if browserLoaded() wins the race, or
// |undefined| if waitForErrorPage() wins the race.
let loadedURL = yield Promise.race([
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser),
BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser),
]);
Assert.equal(expectedURL, loadedURL, "Expected and actual URLs should match");
// Ensure previously successful connections don't influence future tests.
sdr.logoutAndTeardown();
}
// Test that if a certificate is chosen automatically the connection succeeds,
// and that nsIClientAuthDialogs.chooseCertificate() is never called.
add_task(function* testCertChosenAutomatically() {
gClientAuthDialogs.state = DialogState.ASSERT_NOT_CALLED;
yield* testHelper("Select Automatically",
"https://requireclientcert.example.com/");
});
// Test that if the user doesn't choose a certificate, the connection fails and
// an error page is displayed.
add_task(function* testCertNotChosenByUser() {
gClientAuthDialogs.state = DialogState.RETURN_CERT_NOT_SELECTED;
yield* testHelper("Ask Every Time", undefined);
});
// Test that if the user chooses a certificate the connection suceeeds.
add_task(function* testCertChosenByUser() {
gClientAuthDialogs.state = DialogState.RETURN_CERT_SELECTED;
yield* testHelper("Ask Every Time",
"https://requireclientcert.example.com/");
});

View file

@ -0,0 +1,137 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests that the client authentication certificate chooser correctly displays
// provided information and correctly returns user input.
const TEST_HOSTNAME = "Test Hostname";
const TEST_ORG = "Test Org";
const TEST_ISSUER_ORG = "Test Issuer Org";
const TEST_PORT = 123;
var certDB = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
/**
* Test certificate (i.e. build/pgo/certs/mochitest.client).
* @type nsIX509Cert
*/
var cert;
/**
* Opens the client auth cert chooser dialog.
*
* @param {nsIX509Cert} cert The cert to pass to the dialog for display.
* @returns {Promise}
* A promise that resolves when the dialog has finished loading, with
* an array consisting of:
* 1. The window of the opened dialog.
* 2. The return value nsIWritablePropertyBag2 passed to the dialog.
*/
function openClientAuthDialog(cert) {
let certList = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
certList.appendElement(cert, false);
let returnVals = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
let win = window.openDialog("chrome://pippki/content/clientauthask.xul", "",
"", TEST_HOSTNAME, TEST_ORG, TEST_ISSUER_ORG,
TEST_PORT, certList, returnVals);
return new Promise((resolve, reject) => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
resolve([win, returnVals]);
});
});
}
/**
* Checks that the contents of the given cert chooser dialog match the details
* of build/pgo/certs/mochitest.client.
*
* @param {window} win The cert chooser window.
* @param {String} notBefore
* The notBeforeLocalTime attribute of mochitest.client.
* @param {String} notAfter
* The notAfterLocalTime attribute of mochitest.client.
*/
function checkDialogContents(win, notBefore, notAfter) {
Assert.equal(win.document.getElementById("hostname").textContent,
`${TEST_HOSTNAME}:${TEST_PORT}`,
"Actual and expected hostname and port should be equal");
// “ and ” don't seem to work when embedded in the following literals, which
// is why escape codes are used instead.
Assert.equal(win.document.getElementById("organization").textContent,
`Organization: \u201C${TEST_ORG}\u201D`,
"Actual and expected organization should be equal");
Assert.equal(win.document.getElementById("issuer").textContent,
`Issued Under: \u201C${TEST_ISSUER_ORG}\u201D`,
"Actual and expected issuer organization should be equal");
Assert.equal(win.document.getElementById("nicknames").label,
"test client certificate [03]",
"Actual and expected selected cert nickname and serial should " +
"be equal");
let [subject, serialNum, validity, issuer, tokenName] =
win.document.getElementById("details").value.split("\n");
Assert.equal(subject, "Issued to: CN=Mochitest client",
"Actual and expected subject should be equal");
Assert.equal(serialNum, "Serial number: 03",
"Actual and expected serial number should be equal");
Assert.equal(validity, `Valid from ${notBefore} to ${notAfter}`,
"Actual and expected validity should be equal");
Assert.equal(issuer,
"Issued by: CN=Temporary Certificate Authority,O=Mozilla " +
"Testing,OU=Profile Guided Optimization",
"Actual and expected issuer should be equal");
Assert.equal(tokenName, "Stored on: Software Security Device",
"Actual and expected token name should be equal");
}
add_task(function* setup() {
cert = certDB.findCertByNickname("test client certificate");
Assert.notEqual(cert, null, "Should be able to find the test client cert");
});
// Test that the contents of the dialog correspond to the details of the
// provided cert.
add_task(function* testContents() {
let [win, retVals] = yield openClientAuthDialog(cert);
checkDialogContents(win, cert.validity.notBeforeLocalTime,
cert.validity.notAfterLocalTime);
yield BrowserTestUtils.closeWindow(win);
});
// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
let [win, retVals] = yield openClientAuthDialog(cert);
win.document.getElementById("rememberBox").checked = true;
info("Accepting dialog");
win.document.getElementById("certAuthAsk").acceptDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(retVals.get("certChosen"),
"Return value should signal user chose a certificate");
Assert.equal(retVals.get("selectedIndex"), 0,
"0 should be returned as the selected index");
Assert.ok(retVals.get("rememberSelection"),
"Return value should signal 'Remember this decision' checkbox was" +
"checked");
});
// Test that the right values are returned when the dialog is canceled.
add_task(function* testCancelDialogReturnValues() {
let [win, retVals] = yield openClientAuthDialog(cert);
win.document.getElementById("rememberBox").checked = false;
info("Canceling dialog");
win.document.getElementById("certAuthAsk").cancelDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(!retVals.get("certChosen"),
"Return value should signal user did not choose a certificate");
Assert.ok(!retVals.get("rememberSelection"),
"Return value should signal 'Remember this decision' checkbox was" +
"unchecked");
});

View file

@ -0,0 +1,215 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests various aspects of the cert delete confirmation dialog.
// Among other things, tests that for each type of cert that can be deleted:
// 1. The various lines of explanation text are correctly set.
// 2. The implementation correctly falls back through multiple cert attributes
// to determine what to display to represent a cert.
/**
* An array of tree items corresponding to TEST_CASES.
* @type nsICertTreeItem[]
*/
var gCertArray = [];
const FAKE_HOST_PORT = "Fake host and port";
/**
* @typedef {TestCase}
* @type Object
* @property {String} certFilename
* Filename of the cert, or null if we don't want to import a cert for
* this test case (i.e. we expect the hostPort attribute of
* nsICertTreeItem to be used).
* @property {String} expectedDisplayString
* The string we expect the UI to display to represent the given cert.
*/
/**
* A list of test cases representing certs that get "deleted".
* @type TestCase[]
*/
const TEST_CASES = [
{ certFilename: null,
expectedDisplayString: FAKE_HOST_PORT },
{ certFilename: "has-cn.pem",
expectedDisplayString: "Foo" },
{ certFilename: "has-ou.pem",
expectedDisplayString: "Bar" },
{ certFilename: "has-o.pem",
expectedDisplayString: "Baz" },
{ certFilename: "has-non-empty-subject.pem",
expectedDisplayString: "C=US" },
{ certFilename: "has-empty-subject.pem",
expectedDisplayString: "Certificate with serial number: 0A" },
];
/**
* Opens the cert delete confirmation dialog.
*
* @param {String} tabID
* The ID of the cert category tab the certs to delete belong to.
* @returns {Promise}
* A promise that resolves when the dialog has finished loading, with
* an array consisting of:
* 1. The window of the opened dialog.
* 2. The return value object passed to the dialog.
*/
function openDeleteCertConfirmDialog(tabID) {
let retVals = {
deleteConfirmed: false,
};
let win = window.openDialog("chrome://pippki/content/deletecert.xul", "", "",
tabID, gCertArray, retVals);
return new Promise((resolve, reject) => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
resolve([win, retVals]);
});
});
}
add_task(function* setup() {
for (let testCase of TEST_CASES) {
let cert = null;
if (testCase.certFilename) {
cert = yield readCertificate(testCase.certFilename, ",,");
}
let certTreeItem = {
hostPort: FAKE_HOST_PORT,
cert: cert,
QueryInterface(iid) {
if (iid.equals(Ci.nsICertTreeItem)) {
return this;
}
throw new Error(Cr.NS_ERROR_NO_INTERFACE);
}
};
gCertArray.push(certTreeItem);
}
});
/**
* Test helper for the below test cases.
*
* @param {String} tabID
* ID of the cert category tab the certs to delete belong to.
* @param {String} expectedTitle
* Title the dialog is expected to have.
* @param {String} expectedConfirmMsg
* Confirmation message the dialog is expected to show.
* @param {String} expectedImpact
* Impact the dialog is expected to show.
*/
function* testHelper(tabID, expectedTitle, expectedConfirmMsg, expectedImpact) {
let [win, retVals] = yield openDeleteCertConfirmDialog(tabID);
let certList = win.document.getElementById("certlist");
Assert.equal(win.document.title, expectedTitle,
`Actual and expected titles should match for ${tabID}`);
Assert.equal(win.document.getElementById("confirm").textContent,
expectedConfirmMsg,
`Actual and expected confirm message should match for ${tabID}`);
Assert.equal(win.document.getElementById("impact").textContent,
expectedImpact,
`Actual and expected impact should match for ${tabID}`);
Assert.equal(certList.itemCount, TEST_CASES.length,
`No. of certs displayed should match for ${tabID}`);
for (let i = 0; i < certList.itemCount; i++) {
Assert.equal(certList.getItemAtIndex(i).label,
TEST_CASES[i].expectedDisplayString,
"Actual and expected display string should match for " +
`index ${i} for ${tabID}`);
}
yield BrowserTestUtils.closeWindow(win);
}
// Test deleting certs from the "Your Certificates" tab.
add_task(function* testDeletePersonalCerts() {
const expectedTitle = "Delete your Certificates";
const expectedConfirmMsg =
"Are you sure you want to delete these certificates?";
const expectedImpact =
"If you delete one of your own certificates, you can no longer use it to " +
"identify yourself.";
yield* testHelper("mine_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "People" tab.
add_task(function* testDeleteOtherPeopleCerts() {
const expectedTitle = "Delete E-Mail Certificates";
// ’ doesn't seem to work when embedded in the following literals, which is
// why escape codes are used instead.
const expectedConfirmMsg =
"Are you sure you want to delete these people\u2019s e-mail certificates?";
const expectedImpact =
"If you delete a person\u2019s e-mail certificate, you will no longer be " +
"able to send encrypted e-mail to that person.";
yield* testHelper("others_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "Servers" tab.
add_task(function* testDeleteServerCerts() {
const expectedTitle = "Delete Server Certificate Exceptions";
const expectedConfirmMsg =
"Are you sure you want to delete these server exceptions?";
const expectedImpact =
"If you delete a server exception, you restore the usual security checks " +
"for that server and require it uses a valid certificate.";
yield* testHelper("websites_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "Authorities" tab.
add_task(function* testDeleteCACerts() {
const expectedTitle = "Delete or Distrust CA Certificates";
const expectedConfirmMsg =
"You have requested to delete these CA certificates. For built-in " +
"certificates all trust will be removed, which has the same effect. Are " +
"you sure you want to delete or distrust?";
const expectedImpact =
"If you delete or distrust a certificate authority (CA) certificate, " +
"this application will no longer trust any certificates issued by that CA.";
yield* testHelper("ca_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "Other" tab.
add_task(function* testDeleteOtherCerts() {
const expectedTitle = "Delete Certificates";
const expectedConfirmMsg =
"Are you sure you want to delete these certificates?";
const expectedImpact = "";
yield* testHelper("orphan_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
let [win, retVals] = yield openDeleteCertConfirmDialog("ca_tab" /*arbitrary*/);
info("Accepting dialog");
win.document.getElementById("deleteCertificate").acceptDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(retVals.deleteConfirmed,
"Return value should signal user accepted");
});
// Test that the right values are returned when the dialog is canceled.
add_task(function* testCancelDialogReturnValues() {
let [win, retVals] = yield openDeleteCertConfirmDialog("ca_tab" /*arbitrary*/);
info("Canceling dialog");
win.document.getElementById("deleteCertificate").cancelDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(!retVals.deleteConfirmed,
"Return value should signal user did not accept");
});

View file

@ -0,0 +1,150 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests that the cert download/import UI correctly identifies the cert being
// downloaded, and allows the trust of the cert to be specified.
const { MockRegistrar } =
Cu.import("resource://testing-common/MockRegistrar.jsm", {});
/**
* @typedef {TestCase}
* @type Object
* @property {String} certFilename
* Filename of the cert for this test case.
* @property {String} expectedDisplayString
* The string we expect the UI to display to represent the given cert.
* @property {nsIX509Cert} cert
* Handle to the cert once read in setup().
*/
/**
* A list of test cases representing certs that get "downloaded".
* @type TestCase[]
*/
const TEST_CASES = [
{ certFilename: "has-cn.pem",
expectedDisplayString: "Foo",
cert: null },
{ certFilename: "has-empty-subject.pem",
expectedDisplayString: "Certificate Authority (unnamed)",
cert: null },
];
/**
* Opens the cert download dialog.
*
* @param {nsIX509Cert} cert
* The cert to pass to the dialog for display.
* @returns {Promise}
* A promise that resolves when the dialog has finished loading, with
* an array consisting of:
* 1. The window of the opened dialog.
* 2. The return value nsIWritablePropertyBag2 passed to the dialog.
*/
function openCertDownloadDialog(cert) {
let returnVals = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
let win = window.openDialog("chrome://pippki/content/downloadcert.xul", "",
"", cert, returnVals);
return new Promise((resolve, reject) => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
resolve([win, returnVals]);
});
});
}
// Mock implementation of nsICertificateDialogs.
const gCertificateDialogs = {
expectedCert: null,
viewCertCallCount: 0,
confirmDownloadCACert(ctx, cert, trust) {
Assert.ok(false, "confirmDownloadCACert() should not have been called");
},
setPKCS12FilePassword(ctx, password) {
Assert.ok(false, "setPKCS12FilePassword() should not have been called");
},
getPKCS12FilePassword(ctx, password) {
Assert.ok(false, "getPKCS12FilePassword() should not have been called");
},
viewCert(ctx, cert) {
this.viewCertCallCount++;
Assert.notEqual(cert, null, "Cert to view should not be null");
Assert.equal(cert, this.expectedCert,
"Actual and expected cert should match");
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsICertificateDialogs])
};
add_task(function* setup() {
for (let testCase of TEST_CASES) {
testCase.cert = yield readCertificate(testCase.certFilename, ",,");
Assert.notEqual(testCase.cert, null,
`'${testCase.certFilename}' should have been read`);
}
let certificateDialogsCID =
MockRegistrar.register("@mozilla.org/nsCertificateDialogs;1",
gCertificateDialogs);
registerCleanupFunction(() => {
MockRegistrar.unregister(certificateDialogsCID);
});
});
// Test that the trust header message corresponds to the provided cert, and that
// the View Cert button launches the cert viewer for the provided cert.
add_task(function* testTrustHeaderAndViewCertButton() {
for (let testCase of TEST_CASES) {
let [win, retVals] = yield openCertDownloadDialog(testCase.cert);
let expectedTrustHeaderString =
`Do you want to trust \u201C${testCase.expectedDisplayString}\u201D ` +
"for the following purposes?";
Assert.equal(win.document.getElementById("trustHeader").textContent,
expectedTrustHeaderString,
"Actual and expected trust header text should match for " +
`${testCase.certFilename}`);
gCertificateDialogs.viewCertCallCount = 0;
gCertificateDialogs.expectedCert = testCase.cert;
info("Pressing View Cert button");
win.document.getElementById("viewC-button").doCommand();
Assert.equal(gCertificateDialogs.viewCertCallCount, 1,
"viewCert() should've been called once");
yield BrowserTestUtils.closeWindow(win);
}
});
// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
let [win, retVals] = yield openCertDownloadDialog(TEST_CASES[0].cert);
win.document.getElementById("trustSSL").checked = true;
win.document.getElementById("trustEmail").checked = false;
win.document.getElementById("trustObjSign").checked = true;
info("Accepting dialog");
win.document.getElementById("download_cert").acceptDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(retVals.get("importConfirmed"),
"Return value should signal user chose to import the cert");
Assert.ok(retVals.get("trustForSSL"),
"Return value should signal SSL trust checkbox was checked");
Assert.ok(!retVals.get("trustForEmail"),
"Return value should signal E-mail trust checkbox was unchecked");
Assert.ok(retVals.get("trustForObjSign"),
"Return value should signal Obj Sign trust checkbox was checked");
});
// Test that the right values are returned when the dialog is canceled.
add_task(function* testCancelDialogReturnValues() {
let [win, retVals] = yield openCertDownloadDialog(TEST_CASES[0].cert);
info("Canceling dialog");
win.document.getElementById("download_cert").cancelDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(!retVals.get("importConfirmed"),
"Return value should signal user chose not to import the cert");
});

View file

@ -0,0 +1,119 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests that the UI for editing the trust of a CA certificate correctly
// reflects trust in the cert DB, and correctly updates trust in the cert DB
// when requested.
var gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
/**
* The cert we're editing the trust of.
* @type nsIX509Cert
*/
var gCert;
/**
* Opens the cert trust editing dialog.
*
* @returns {Promise}
* A promise that resolves when the dialog has finished loading with
* the window of the opened dialog.
*/
function openEditCertTrustDialog() {
let win = window.openDialog("chrome://pippki/content/editcacert.xul", "", "",
gCert);
return new Promise((resolve, reject) => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
resolve(win);
});
});
}
add_task(function* setup() {
// Initially trust ca.pem for SSL, but not e-mail or object signing.
gCert = yield readCertificate("ca.pem", "CT,,");
Assert.ok(gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_SSL),
"Sanity check: ca.pem should be trusted for SSL");
Assert.ok(!gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_EMAIL),
"Sanity check: ca.pem should not be trusted for e-mail");
Assert.ok(!gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_OBJSIGN),
"Sanity check: ca.pem should not be trusted for object signing");
});
// Tests the following:
// 1. The checkboxes correctly reflect the trust set in setup().
// 2. Accepting the dialog after flipping some of the checkboxes results in the
// correct trust being set in the cert DB.
add_task(function* testAcceptDialog() {
let win = yield openEditCertTrustDialog();
let sslCheckbox = win.document.getElementById("trustSSL");
let emailCheckbox = win.document.getElementById("trustEmail");
let objSignCheckbox = win.document.getElementById("trustObjSign");
Assert.ok(sslCheckbox.checked,
"Cert should be trusted for SSL in UI");
Assert.ok(!emailCheckbox.checked,
"Cert should not be trusted for e-mail in UI");
Assert.ok(!objSignCheckbox.checked,
"Cert should not be trusted for object signing in UI");
sslCheckbox.checked = false;
emailCheckbox.checked = true;
info("Accepting dialog");
win.document.getElementById("editCaCert").acceptDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(!gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_SSL),
"Cert should no longer be trusted for SSL");
Assert.ok(gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_EMAIL),
"Cert should now be trusted for e-mail");
Assert.ok(!gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_OBJSIGN),
"Cert should still not be trusted for object signing");
});
// Tests the following:
// 1. The checkboxes correctly reflect the trust set in testAcceptDialog().
// 2. Canceling the dialog even after flipping the checkboxes doesn't result in
// a change of trust in the cert DB.
add_task(function* testCancelDialog() {
let win = yield openEditCertTrustDialog();
let sslCheckbox = win.document.getElementById("trustSSL");
let emailCheckbox = win.document.getElementById("trustEmail");
let objSignCheckbox = win.document.getElementById("trustObjSign");
Assert.ok(!sslCheckbox.checked,
"Cert should not be trusted for SSL in UI");
Assert.ok(emailCheckbox.checked,
"Cert should be trusted for e-mail in UI");
Assert.ok(!objSignCheckbox.checked,
"Cert should not be trusted for object signing in UI");
sslCheckbox.checked = true;
emailCheckbox.checked = false;
objSignCheckbox.checked = true;
info("Canceling dialog");
win.document.getElementById("editCaCert").cancelDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(!gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_SSL),
"Cert should still not be trusted for SSL");
Assert.ok(gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_EMAIL),
"Cert should still be trusted for e-mail");
Assert.ok(!gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_OBJSIGN),
"Cert should still not be trusted for object signing");
});

View file

@ -0,0 +1,142 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests that the UI for setting the password on a to be exported PKCS #12 file:
// 1. Correctly requires the password to be typed in twice as confirmation.
// 2. Calculates and displays the strength of said password.
/**
* @typedef {TestCase}
* @type Object
* @property {String} name
* The name of the test case for display purposes.
* @property {String} password1
* The password to enter into the first password textbox.
* @property {String} password2
* The password to enter into the second password textbox.
* @property {String} strength
* The expected strength of the password in the range [0, 100].
*/
/**
* A list of test cases representing various inputs to the password textboxes.
* @type TestCase[]
*/
const TEST_CASES = [
{ name: "empty",
password1: "",
password2: "",
strength: "0" },
{ name: "match-weak",
password1: "foo",
password2: "foo",
strength: "10" },
{ name: "match-medium",
password1: "foo123",
password2: "foo123",
strength: "60" },
{ name: "match-strong",
password1: "fooBARBAZ 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三",
password2: "fooBARBAZ 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三",
strength: "100" },
{ name: "mismatch-weak",
password1: "foo",
password2: "bar",
strength: "10" },
{ name: "mismatch-medium",
password1: "foo123",
password2: "bar",
strength: "60" },
{ name: "mismatch-strong",
password1: "fooBARBAZ 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三",
password2: "bar",
strength: "100" },
];
/**
* Opens the dialog shown to set the password on a PKCS #12 file being exported.
*
* @returns {Promise}
* A promise that resolves when the dialog has finished loading, with
* an array consisting of:
* 1. The window of the opened dialog.
* 2. The return value nsIWritablePropertyBag2 passed to the dialog.
*/
function openSetP12PasswordDialog() {
let returnVals = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
let win = window.openDialog("chrome://pippki/content/setp12password.xul", "",
"", returnVals);
return new Promise((resolve, reject) => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
resolve([win, returnVals]);
});
});
}
// Tests that the first password textbox is the element that is initially
// focused.
add_task(function* testFocus() {
let [win, retVals] = yield openSetP12PasswordDialog();
Assert.equal(win.document.activeElement,
win.document.getElementById("pw1").inputField,
"First password textbox should have focus");
yield BrowserTestUtils.closeWindow(win);
});
// Tests that the password strength algorithm used is reasonable, and that the
// Accept button is only enabled if the two passwords match.
add_task(function* testPasswordStrengthAndEquality() {
let [win, retVals] = yield openSetP12PasswordDialog();
let password1Textbox = win.document.getElementById("pw1");
let password2Textbox = win.document.getElementById("pw2");
let strengthProgressBar = win.document.getElementById("pwmeter");
for (let testCase of TEST_CASES) {
password1Textbox.value = testCase.password1;
password2Textbox.value = testCase.password2;
// Setting the value of the password textboxes via |.value| apparently
// doesn't cause the oninput handlers to be called, so we do it here.
password1Textbox.oninput();
password2Textbox.oninput();
Assert.equal(win.document.documentElement.getButton("accept").disabled,
password1Textbox.value != password2Textbox.value,
"Actual and expected accept button disable state should " +
`match for ${testCase.name}`);
Assert.equal(strengthProgressBar.value, testCase.strength,
"Actual and expected strength value should match for" +
`${testCase.name}`);
}
yield BrowserTestUtils.closeWindow(win);
});
// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
let [win, retVals] = yield openSetP12PasswordDialog();
const password = "fooBAR 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三";
win.document.getElementById("pw1").value = password;
win.document.getElementById("pw2").value = password;
info("Accepting dialog");
win.document.getElementById("setp12password").acceptDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(retVals.get("confirmedPassword"),
"Return value should signal user confirmed a password");
Assert.equal(retVals.get("password"), password,
"Actual and expected password should match");
});
// Test that the right values are returned when the dialog is canceled.
add_task(function* testCancelDialogReturnValues() {
let [win, retVals] = yield openSetP12PasswordDialog();
info("Canceling dialog");
win.document.getElementById("setp12password").cancelDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.ok(!retVals.get("confirmedPassword"),
"Return value should signal user didn't confirm a password");
});

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICxTCCAa+gAwIBAgIUL5zykZEc2ro5d6th43aWGfm735cwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMA0xCzAJBgNVBAMMAmNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptu
Gobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO
7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgf
qDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/yt
HSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcx
uLP+SSP6clHEMdUDrNoYCjXtjQIDAQABox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud
DwQEAwIBBjALBgkqhkiG9w0BAQsDggEBAHPYBjNnv//Ssc8Elepb8SWIXRdahKbL
/dcPoMR+7yhJVaelUaxdwUytJWJAGdkkuv+P+G4b82RVYEXT+9k1S/aAfByFyR9q
vS7POfdy/ZPfGTXltlnmYX/84a6QeYQa4Nl4JpIOXBCesLxmErBhczka6D26iqsz
GeseKRSjVPgF3mXc2CRGZnTDRhUmd7wOABLmj7GtuFvOm96363M3IUByMohvoj1G
dic3s5D0seXwTKnEc5B27lJt7Q0oIXEldL+UW8Mo1hfGWQeXzqTZbpOVLnVWvHBH
H8yYs5hyH01qFJZbztJ1JJ3F2NpYLlr4P5I6fW2e9w5MG/VMQRU3wzQ=
-----END CERTIFICATE-----

View file

@ -0,0 +1,4 @@
issuer:ca
subject:ca
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICxDCCAa6gAwIBAgIUSbYQoLY1s6wWqgbKhxQZ3XME7ukwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBIxEDAOBgNVBAMMB2NvZGUtZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9
sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5
TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7
xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHd
tMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l
8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjFzAVMBMGA1UdJQQMMAoGCCsG
AQUFBwMDMAsGCSqGSIb3DQEBCwOCAQEAV69uBbyc/d1eBdZlT7eAw4onQzkdndd8
kEXdmP3hd+jJm1+/F733IflLLqE5mmUL9l7q7EJ+TgdZa19T6JHEaVjdJcIuwJO/
kKSJXXqADQXoxHOZADDWjAFStiR3xd78BzYfuUANgozG6hq7QuVh0cYBx/8Q9gx/
pGtuCJiN0d2Mknu0SoQzIZlXTuqmnFj7G/88O5Yh5MaFZxbvIJJSIWQoS396GrI6
yXAdqHNoVM9mwwaMcnG5QeeKSIPuvEkZncQsxFc0zqIjeOVx/zEx2Bocx71dLuVB
fqrIrAXLpwparoSxLzNqq8UgtXF8NQOuAcUu7ok0r1VbdMbSZHZ3Gg==
-----END CERTIFICATE-----

View file

@ -0,0 +1,3 @@
issuer:ca
subject:code-ee
extension:extKeyUsage:codeSigning

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvjCCAaigAwIBAgIUGzSP8KEmmRm3sIPiyQW35sazlHEwCwYJKoZIhvcNAQEL
MBUxEzARBgNVBAMMCmV4cGlyZWQtY2EwIhgPMjAxNTExMjgwMDAwMDBaGA8yMDE4
MDIwNTAwMDAwMFowHTEbMBkGA1UEAwwSZWUtZnJvbS1leHBpcmVkLWNhMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohRqESOFtZB/W62iAY2ED08E9nq
5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+KvWnVramRxCHqlWqdFh/cc1SSc
An7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+rWkasdMCOosqQe6ncOAPDY39
ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYk
zBxsl62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5Fw6naOGzey8ib2njtIqVYR3u
JtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXtjQIDAQAB
MAsGCSqGSIb3DQEBCwOCAQEAZ6Nrb/1fit8cALMhcbmuZ5kd3J34d0o9p3g3E7m7
8RsTbYLA4xp9UmSzpO/10x9q4TUZ8jxW1dotoCVf7OqYYxQewrU2x3qoxKvP/Fvf
8ssWSIang91w+app+fv7QYDySymT6DJMLWyCmxyhaFjYnmr67GKldcgK9hbyjfDB
Rj382czI/HMSvw/vCB6rRKchzr5hsDGl+YN0MMI4M7/3b5wvMUmxlXqKu1VlslDZ
8Ez6ONuMdPJD3aQZMxmEph05pEMvhjFhLh+0n7kfLR+9n0D7IR9paVc6LgHLLxsP
ENoZLGOwJYNdAwwkd6fIa9E6KCpaRgyvWslm+iFCg3XxoA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:expired-ca
subject:ee-from-expired-ca

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICwjCCAaygAwIBAgIUI/4Y+KSEZo8YGQK6Ptrdmev5FO0wCwYJKoZIhvcNAQEL
MBcxFTATBgNVBAMMDHVudHJ1c3RlZC1jYTAiGA8yMDE1MTEyODAwMDAwMFoYDzIw
MTgwMjA1MDAwMDAwWjAfMR0wGwYDVQQDDBRlZS1mcm9tLXVudHJ1c3RlZC1jYTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9
PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3
HNUknAJ+zUP8HmnQOCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3Dg
Dw2N/WYLK7AkkqR9uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7
EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SK
lWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0C
AwEAATALBgkqhkiG9w0BAQsDggEBAJqsDDoJqxrmV4Mlt815HmJwhr/SuYhPwhoQ
RyU56Ci5kY/8fYa3F1uxSrpzuiYBX4bq6g8keXmltPZGN9gexPP2QJDAecNt0NKW
+04ZKSiz6Tbu+MEyBaXCINDKaAHVPRnbMWR1eCyHzYpZRKZW2Sb2NinWGebzq0mI
wt5l7veMkL5ZbeYF8u8bNFsdvhl1PM7/AfAZLJL4+fncaqQeDRyVffxrl4mCooS9
DYajnw7AhFvN0XtXb5vK3HYiz9mv/OnXeoeWxYcWI6aY6LR0OwHHQQptKQSIOP87
2mo64IbAwzuBrhxNrdrQKCnf1mtyDZig+2r6R4TP3EM3sCNAoiU=
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:untrusted-ca
subject:ee-from-untrusted-ca

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICxTCCAa+gAwIBAgIUJctkeS6qP+WqsgOLbjATJuPlN40wCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBMxETAPBgNVBAMMCGVtYWlsLWVlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4Ngf
vbGcBptuGobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTb
uUzCa2wO7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3S
O8XguEgfqDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR
3bTK9/ytHSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv
5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXtjQIDAQABoxcwFTATBgNVHSUEDDAKBggr
BgEFBQcDBDALBgkqhkiG9w0BAQsDggEBAIFmRk4ZfcxWjetAoyYp0bIFLr5AjGqv
ecmc0khsRkW7NR23ywJsRsCU1u82JIGrE0bpDu/KQPAMJsi6QMc9hZEOzO1t1QmG
OJFLhCNTe+wf+5X+UKHKo01lEp7vDcO7DjuZIgEZSyOp9qbV88AtEiqESIzRBWYp
dL15cS1PDH8fa5k7MHCAh0C/HeDRD5EP8derIWWrFIesEdJAhwzMRzJrCWIqzLPP
Lv2gsXhehXCN7U14zkoGU97sSE09k5BopHd4fgqZesSApJrd2OenQAzdRIs3+UQy
iCs7oLH16lOl/yeRxVjcHRWaSRM47eGpn5+YOnGkoE/lqfux+jjB3rc=
-----END CERTIFICATE-----

View file

@ -0,0 +1,3 @@
issuer:ca
subject:email-ee
extension:extKeyUsage:emailProtection

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIICzTCCAbegAwIBAgIUAfElDw37NeFULPHd+G2eoaHpvEYwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTAwMTAxMDAwMDAwWhgPMjAxMTAxMDEwMDAw
MDBaMBUxEzARBgNVBAMMCmV4cGlyZWQtY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg
2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ
5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQ
PdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGj
DJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8W
iy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjHTAbMAwGA1UdEwQFMAMB
Af8wCwYDVR0PBAQDAgEGMAsGCSqGSIb3DQEBCwOCAQEAde8CQNB8dVo5ly7Lu8x9
5yDz2hpzAqqPDxP3+UqxzEgXeA4vfv1Bzvmxx69XEd+884M9Lkt2WBTrc+OrAgqX
pCCt4X8bjV2t+mG1shtYEGKk5BtRVnorHhZyf6+5xtOfpV9DeWkf/aA1SJK1Kpt3
cNSDW10PwaGuaNiUMEtIFLD/MYZCM98RFOSVDWjqafbfUBn4ZSeoyRi1C2d3lg0C
jRFmOc1I4DQOUezp3C0WyCumJ0SLTIoYJGdAshMbDWPr0OOaB4GmI8miKhS6LM59
o6C3fU8MJrRYKctYj0k9gW0DI6KuEFZj2AY8brv6Ufx1TKy5Z2pqIPeUbuJInCXM
qA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,5 @@
issuer:ca
subject:expired-ca
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign
validity:20100101-20110101

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC0DCCAbqgAwIBAgIUfQIwxuYCoWiJuu/qTiEf7fbljnswCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMDcxDDAKBgNVBAMMA0ZvbzEMMAoGA1UECwwDQmFyMQwwCgYDVQQKDANCYXox
CzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohR
qESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+Kv
WnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+
rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPv
JxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5
Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6
clHEMdUDrNoYCjXtjQIDAQABMAsGCSqGSIb3DQEBCwOCAQEAJ2fIigbkc2Lh5Z/s
Y7s4o0D9UnzttXjjEqKYhttk6PJnmVYG3zn3MBmyWPhDcXYW9fJwx7IOcC0woVdJ
yjkVZUIlJY6xAqIC6kVNtbI3PJ+mji8qQk/ecXCwhTGk0H2lZXrUtc6WMmD3GUIP
yNQGN/qAniRLnXzzVY3MJPLKKSlWSJEJCY4F4uDwBtwudPc+1yRIR6XblEL3dazS
H2kuIzGwIu6/i3AN2WIFWFhcuRTfLZINlNeH9gYEaUrwI3MS0aMPqGXtOHz+imZl
RwNng0xaiDxZXcEPjrRw5HEZcIEGBc6X8WtSzbWufiWBqMue1ltEpc1AkvUamuB3
KJxYPA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:ca
subject:/CN=Foo/OU=Bar/O=Baz/C=US

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIChjCCAXCgAwIBAgIBCjALBgkqhkiG9w0BAQswDTELMAkGA1UEAwwCY2EwIhgP
MjAxNTExMjgwMDAwMDBaGA8yMDE4MDIwNTAwMDAwMFowADCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhX
bCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQ
OCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9
uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFb
t+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhO
NsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAATALBgkqhkiG
9w0BAQsDggEBAF/OD4h9UNl2afVbw/Hv2dCV5uMyDV3T8iEUI9eiCvYDMAOElkAN
NZbDfGfQdg8rNLKG6r7Vz8VBu0T/Vn2lswtKYPll63ANv9qZVtKGsDTGzN8JSC0k
xgMbtVsj+OsJs81hmNnW6xw7wehpPw3l1UakAEb6dbYuYCanR/p/u/hvTz7phe9D
AsJyRAo4a+QDyeqgAPKrzTatawshNnz9O4QhNzUqj53fMkpUq2ebOyIGMOvbh/N5
nT6AVT2wn95mWawnS5v2VTRPALyMkgbl+0bb/VzXHN6CjDHO+n239lL2uQlAZFHe
8pKr4lmb82dLU9qUFbY7exLyV1aUyYSXSNU=
-----END CERTIFICATE-----

View file

@ -0,0 +1,3 @@
issuer:ca
subject:
serialNumber:10

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICpjCCAZCgAwIBAgIUCwPRyN8HCSE5XEIq7e2eEEe1OdIwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMA0xCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptu
Gobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO
7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgf
qDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/yt
HSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcx
uLP+SSP6clHEMdUDrNoYCjXtjQIDAQABMAsGCSqGSIb3DQEBCwOCAQEAt2CF0E7d
QYnfn/kc8hb6GF6sYpCFA6egEzr6OsYMYE7jt5mKlMJdbIxw57L8jg8IZ1fjH5AQ
KA5cchGcgjCkHoJ7jOYfMZCubCBdrsNKx2YYWcna8WIAZjwOIfNC0Ajs3IDiRDWm
vlBrFP9Z6bGuzNrvLFAB0lU2dM2b99DqzaYNZeQP5DcP6ZjaPkSvqOWr3Lf6ZAvO
tU70OcTelx74Hj9bI75bxVYd71Vorv5qB77zrl7GHb36f2pkludDOKeZ6XhRgy9e
vN6DLctM0v6fJprG50xrILDhqsTydTdjhETLaIWhF9aUHzFybpFArp8TLoWbXiX1
eAVaASutFVprhA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:ca
subject:/C=US

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICtDCCAZ6gAwIBAgIUeXeYs5jw41bNt0btBeEFNbUQonAwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBsxDDAKBgNVBAoMA0JhejELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wk
e8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0Dgg
KZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmI
YXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7fi
lhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbL
HCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJKoZIhvcN
AQELA4IBAQAs60sU1VqjaVQbGBHvBNyiQn9oTugmuEx9ogwVKhnmgRK+hYw+wgBn
H4yYZF1gF4xG7Rt+ut+EruSd4ht8vY9ZMvKrbgMrZ6HbNIZg9oIX+u0i9Bba2lh7
p87mCePS5L7U1gPbg/fZ8jd0FvW8EusC/TX5tOeeUnawXWE4ciqPZfIVriU0iCP1
nKzvFtawYzWwgN+QZ1ruzBi7qqrHNDAhgLu9+3g+9QyBd40XV7/EhDQ18kViaTSj
WmaUX7jJD1FUkGBkxjqHfgGkaYnt7UXGMDTeQ8vFeja11PJJIdRT8hSu0oTMdE6M
WCEw02+Fc+qsYH5I6vp3MOV8wyBqIqYc
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:ca
subject:/O=Baz/C=US

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICwjCCAaygAwIBAgIUU/td7MxWYwvdFLfgNUraIpy3GP8wCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMCkxDDAKBgNVBAsMA0JhcjEMMAoGA1UECgwDQmF6MQswCQYDVQQGEwJVUzCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9
PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3
HNUknAJ+zUP8HmnQOCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3Dg
Dw2N/WYLK7AkkqR9uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7
EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SK
lWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0C
AwEAATALBgkqhkiG9w0BAQsDggEBAGbVHQ19S6R62HovLt9Ltir1z9KJ4QXWNAEu
FKicntKaId+jJY42y1+iAqQHy3FpjfLfx5eVKPW8vHbyTQSL/y0jJ9bPKepYsSay
5McWggOxMxVFazUCOntZN282WYIg3H/OFaeRarjeHlraZjwmNxrfHKzyBJ6bBqBJ
2vtmDez/+h+f0reutgnY1v4bJ02x/5YuG39+i08uRI0Vc+lrDiqDPYMxlmzwVvJM
xqo9TZu9gU4XFbK8c8EUsPjMMO1gKyroiBhthtEZ8a9Q4jdeD92cOZRcPrHtYyvR
qw9VhFLJRgLJ0DVOWqCHqYXUFfYngFezem1eeNxrz2eAbaURdCs=
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:ca
subject:/OU=Bar/O=Baz/C=US

View file

@ -0,0 +1,59 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
/**
* List of certs imported via readCertificate(). Certs in this list are
* automatically deleted from the cert DB when a test including this head file
* finishes.
* @type nsIX509Cert[]
*/
var gImportedCerts = [];
registerCleanupFunction(() => {
for (let cert of gImportedCerts) {
gCertDB.deleteCertificate(cert);
}
});
/**
* This function serves the same purpose as the one defined in head_psm.js.
*/
function pemToBase64(pem) {
return pem.replace(/-----BEGIN CERTIFICATE-----/, "")
.replace(/-----END CERTIFICATE-----/, "")
.replace(/[\r\n]/g, "");
}
/**
* Given the filename of a certificate, returns a promise that will resolve with
* a handle to the certificate when that certificate has been read and imported
* with the given trust settings.
*
* Certs imported via this function will automatically be deleted from the cert
* DB once the calling test finishes.
*
* @param {String} filename
* The filename of the certificate (assumed to be in the same directory).
* @param {String} trustString
* A string describing how the certificate should be trusted (see
* `certutil -A --help`).
* @return {Promise}
* A promise that will resolve with a handle to the certificate.
*/
function readCertificate(filename, trustString) {
return OS.File.read(getTestFilePath(filename)).then(data => {
let decoder = new TextDecoder();
let pem = decoder.decode(data);
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
let base64 = pemToBase64(pem);
certdb.addCertFromBase64(base64, trustString, "unused");
let cert = certdb.constructX509FromBase64(base64);
gImportedCerts.push(cert);
return cert;
}, error => { throw error; });
}

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvDCCAaagAwIBAgIUcy9NBl2j6kWrXfJ6Na36AnwN2Q8wCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBIxEDAOBgNVBAMMB2ludmFsaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9
sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5
TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7
xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHd
tMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l
8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjDzANMAsGA1UdDwQEAwIBBjAL
BgkqhkiG9w0BAQsDggEBAHw1PeRKbGVaiNBPlshPnuEjJ5XN+ls3Lv8CVplvuFgM
uvOAfuXNcLcQmqU4QZm9PvIboCAe2FTFMJ+szDbCIFaBzzJ4RnuJ0FnBZDf1fKJm
/Nj4XikPePo5DnsqSs53aNKM7Nf5dcdCCA8kfpMm50Nw6ufWrr8HAEqQbDixecv1
6as6xc458UU8AXKZb30VfLFAm0uPz2Y/ZjROnSqrNSB5ZRx9m4MqS3/4H7fSnlFU
yMcetH5ovGk3xJg65qWhaRlaoeExco9E5x1nUr+eK4OmP3MXlGbxxMQx1R43Ea11
zSyaqlhGUs06uDOl4rk4b2FmkPgGV+A26gtjMYD005k=
-----END CERTIFICATE-----

View file

@ -0,0 +1,3 @@
issuer:ca
subject:invalid
extension:keyUsage:cRLSign,keyCertSign

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICqjCCAZSgAwIBAgIURZ4xXpmcV9oh3RekbTwkCGv62NowCwYJKoZIhvcNAQEE
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBExDzANBgNVBAMMBm1kNS1lZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72x
nAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sgw0nk27lM
wmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCxV5A90jvF
4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20
yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xx
j5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAATALBgkqhkiG9w0BAQQDggEBAKs7
7/g5m901xqDth2t0tDTFWlfh/h94KLk8d8JAAa8AMdVwpMUMc2IKPk+H+f7JkBeE
hhJ/r4ZEbQkjZuoLSkAR6aKRprE97Ddw1LJLVish39DitEXxpyDemCIl8V6E8FpW
CWqbOZtvUScOQOlJ2uJfPwHkh93RJbzP9EY8Hd2arFYKuExi5z8Z465feZ53mdOe
17WG9IKKIQirr4OAxD+ab1EdMuPuXKQ9qfg4fSW/LDsb97x0/ElRfHwFDxsbEiVi
zR/gGMW9AQhc+eW2qchjYkO0v/ps7dzjDQFDJzLAd/mlb90cK1cpUz6XVn/HagvZ
0MRczu3MnE6KRPVpW8Y=
-----END CERTIFICATE-----

View file

@ -0,0 +1,3 @@
issuer:ca
subject:md5-ee
signature:md5WithRSAEncryption

View file

@ -0,0 +1,35 @@
# -*- Mode: python; 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/.
BROWSER_CHROME_MANIFESTS += ['browser.ini']
# Temporarily disabled. See bug 1256495.
# (Note that when this gets enabled, some extra work will have to happen so
# that the mochitest harness knows where to get the generated certificates -
# right now it assumes they're in the source directory, which isn't the case
# when they're automatically generated.)
#test_certificates = (
# 'ca.pem',
# 'code-ee.pem',
# 'ee-from-expired-ca.pem',
# 'ee-from-untrusted-ca.pem',
# 'email-ee.pem',
# 'expired-ca.pem',
# 'has-cn.pem',
# 'has-empty-subject.pem',
# 'has-non-empty-subject.pem',
# 'has-o.pem',
# 'has-ou.pem',
# 'invalid.pem',
# 'md5-ee.pem',
# 'revoked.pem',
# 'ssl-ee.pem',
# 'unknown-issuer.pem',
# 'untrusted-ca.pem',
#)
#
#for test_certificate in test_certificates:
# GeneratedTestCertificate(test_certificate)

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICqzCCAZWgAwIBAgIUD1t15yWPBLIhosAm9w9++t/F/fkwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBIxEDAOBgNVBAMMB3Jldm9rZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9
sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5
TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7
xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHd
tMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l
8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJKoZIhvcNAQELA4IBAQCy
eobd3+MhGhQvhKQax5XNBqAEmogtsv6G1ZCoAx0kKU83r3Oj9ha4VfGN0syP8NQV
nmkecZ630QXQcyCD3RRiiLqU07N3nC5djm8v+vM5RhuDADkIwddH3WNWB+8KUJEd
3Sym1EN6xAYdQEAwWdPno73sUsFebuoL/c4gpTjD7PF+/vPzN0c3KVanlrMhayKe
3PLq8jST2OSdLvooa8qMYsFFG2S4A+gmp9Cx30moMG2+w1GBKZdtY2tlFx5DppIU
AoQzUl9pvT6AFDcY2RO6UvsWF9Pzr4dTjjgk8SO05jKcmj2GnBm480ZezDx5N5zm
+XVGgonJZRAucaVuJY79
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:ca
subject:revoked

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIICzTCCAbegAwIBAgIUYfe94xSwDUoffRodCo1TPdV/PaswCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBExDzANBgNVBAMMBnNzbC1lZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72x
nAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sgw0nk27lM
wmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCxV5A90jvF
4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20
yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xx
j5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAAaMhMB8wHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMAsGCSqGSIb3DQEBCwOCAQEAprVI8tGWBHIN2SV66ZnC
vOfWcQguUQg8QO3Al+O4X5U18hzgsmCjqt99b+oJCJD0qWBnPPBgqY52pckCgmTY
w73TZ5w3Rnr3v+BlQ5xPTyAQoUeutm1LMxY/Ju7m1XV44tyDnq6GZbOZLVWtRLXe
W4UEqVex4qbCw3GOvFyHmubSNUk81v4Iexe1SmIJN8glZsVmWJdaC2Xo7qhz+vvq
HljfO+/ejiBtZOJSf9qG6HcGW/Rf15Io0e+IA6jbZWrlAzIjBcYKumZF8LjRONHZ
vwiCwWit/IP6KvmsHAb7wj5c0U/p1TuyGdvu/ccp6nCdx8Ya7/QKfAEQTZXnloBG
4w==
-----END CERTIFICATE-----

View file

@ -0,0 +1,3 @@
issuer:ca
subject:ssl-ee
extension:extKeyUsage:serverAuth,clientAuth

View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICtzCCAaGgAwIBAgIUEfR3vHTQuzModYBSMepORIL++2gwCwYJKoZIhvcNAQEL
MBIxEDAOBgNVBAMMB3Vua25vd24wIhgPMjAxNTExMjgwMDAwMDBaGA8yMDE4MDIw
NTAwMDAwMFowGTEXMBUGA1UEAwwOdW5rbm93bi1pc3N1ZXIwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVo
V2wke8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p
0DggKZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKk
fbmIYXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZh
W7filhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EI
TjbLHCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJKoZI
hvcNAQELA4IBAQB4pRQvglUpzNZ2fH0oj5bcqfcTjE3dwEzGg7WaMD2t50zKgCRp
2sDObvEB1Nv5SHSkebxDeS9xQ6Dghf+TvuCnkapi/6q9etP51lkIOhl6okAGUwdZ
vO3duIvXCVUWbut3ATQghKovDYuJXKMx1OYapxyLKKCsdvTQ8LNQpPcwbpVtqWKC
jLYpa1i/vtn4Pv8xs/ceOf10z5AdydpFBgZ8JpY0CbRI73WHR5fr1yYI7tfzaAA8
d+OBZ7nqlg81khD/Oepl/h6/IJ3L2eB+lUZx6+yWML9jRD0HX1xRje19u2vxCuQ+
tNo6lQr9fTRG76Md1d4fdg9+F9LGqDd+yBBv
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
issuer:unknown
subject:unknown-issuer

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIICzzCCAbmgAwIBAgIUT/T//UMr8YnbQBWj+61OMGPKRC4wCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw
MDBaMBcxFTATBgNVBAMMDHVudHJ1c3RlZC1jYTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wccl
qODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sg
w0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCx
V5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1
MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQs
vxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAAaMdMBswDAYDVR0TBAUw
AwEB/zALBgNVHQ8EBAMCAQYwCwYJKoZIhvcNAQELA4IBAQCiDFgskGRygaarkruu
gTwsX59ULb7yhXyYKZLTdsUitHi8Zk4KUmsbkBHGaek30Ud9A1GyLzuP3hb1/M7M
FdARYO8qrl414tW3hiON36R47qtw5cO6a2YZfvxU79esuoa6uxChhHLUugqNotJb
bbGwSMszKzkGtOQ5ZTFNc8+t1kWeQfFoPMznjg5WC2oq9Pl45Rt9lFrU3SD8MkVA
8fLAGR5TEOY2ZvjDDMKg+ceJNIaA3SPXDTVSXWNIakJU2vsdUXThTyfnoCw0sMQG
ZwkmKbCXioYXDB/nrjoVBgJh85JSc4KX137y5m2FK+wHzkKMgf4yn6Ql2eg/yTen
CaeK
-----END CERTIFICATE-----

View file

@ -0,0 +1,4 @@
issuer:ca
subject:untrusted-ca
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View file

@ -0,0 +1,5 @@
"use strict";
module.exports = { // eslint-disable-line no-undef
"extends": "../../../../../../testing/mochitest/mochitest.eslintrc.js"
};

View file

@ -0,0 +1,6 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Access-Control-Allow-Origin", "*");
response.write("<html><body>hello!</body></html>");
}

View file

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
"use strict";
window.onload = function()
{
window.setTimeout(function()
{
SpecialPowers.wrap(window).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
.goBack();
}, 100);
};
</script>
</head>
</html>

View file

@ -0,0 +1,7 @@
/* import-globals-from mixedContentTest.js */
"use strict";
document.open();
document.write("This is insecure XSS script " + document.cookie);
isSecurityState("broken", "security broken after document write from unsecure script");
finish();

View file

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 383369 test, step 2</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/does_not_exist.css">
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
window.onload = function runTest() {
window.setTimeout(function () {
window.location =
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step3.html?runtest";
}, 0);
};
function afterNavigationTest()
{
}
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 383369 test, final step</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("secure", "secure page after insecure download and insecure subcontent still secure");
finish();
}
function afterNavigationTest()
{
isSecurityState("secure", "still secure after back/forward");
finish();
}
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1 @@
Temporary file for security/mixedconent tests

View file

@ -0,0 +1,2 @@
Content-disposition: "attachment"
Content-type: application/x-auto-download

View file

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 200, "OK");
//response.setHeader("Content-type", "image/gif");
}

View file

@ -0,0 +1,13 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-type", "image/bitmap");
let bmpheader = "\x42\x4D\x36\x10\x0E\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\xE0\x01\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\x00\x10\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
let bmpdatapiece = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
response.bodyOutputStream.write(bmpheader, 54);
// Fill 640*480*3 nulls
for (let i = 0; i < (640 * 480 * 3) / 64; ++i)
response.bodyOutputStream.write(bmpdatapiece, 64);
}

View file

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
This is frame 1:
<script>
"use strict";
document.write(location.href);
</script>
</body>
</html>

View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
This is frame 2:
<script>
"use strict";
document.write(location.href);
</script>
<iframe src="http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<META http-equiv="Refresh"
Content="0; URL=http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html">
<html>
<body>
Redirecting by meta tag...
</body>
</html>

View file

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
response.setHeader("Location", "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html");
}

View file

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
response.setHeader("Location", "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html");
}

View file

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
response.setHeader("Location", "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg");
}

View file

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
response.setHeader("Location", "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg");
}

View file

@ -0,0 +1,204 @@
"use strict";
/**
* Helper script for mixed content testing. It opens a new top-level window
* from a secure origin and '?runtest' query. That tells us to run the test
* body, function runTest(). Then we wait for call of finish(). On its first
* call it loads helper page 'backward.html' that immediately navigates
* back to the test secure test. This checks the bfcache. We got second call
* to onload and this time we call afterNavigationTest() function to let the
* test check security state after re-navigation back. Then we again wait for
* finish() call, that this time finishes completelly the test.
*/
// Tells the framework if to load the test in an insecure page (http://)
var loadAsInsecure = false;
// Set true to bypass the navigation forward/back test
var bypassNavigationTest = false;
// Set true to do forward/back navigation over an http:// page, test state leaks
var navigateToInsecure = false;
// Open the test in two separate windows, test requests sharing among windows
var openTwoWindows = false;
// Override the name of the test page to load, useful e.g. to prevent load
// of images or other content before the test starts; this is actually
// a 'redirect' to a different test page.
var testPage = "";
// Assign a function to this variable to have a clean up at the end
var testCleanUp = null;
// Contains mixed active content that needs to load to run the test
var hasMixedActiveContent = false;
// Internal variables
var _windowCount = 0;
window.onload = function onLoad() {
if (location.search == "?runtest") {
try {
if (history.length == 1) {
// Each test that includes this helper file is supposed to define
// runTest(). See the top level comment.
runTest(); // eslint-disable-line no-undef
} else {
// Each test that includes this helper file is supposed to define
// afterNavigationTest(). See the top level comment.
afterNavigationTest(); // eslint-disable-line no-undef
}
} catch (ex) {
ok(false, "Exception thrown during test: " + ex);
finish();
}
} else {
window.addEventListener("message", onMessageReceived, false);
let secureTestLocation = loadAsInsecure ? "http://example.com"
: "https://example.com";
secureTestLocation += location.pathname;
if (testPage != "") {
let array = secureTestLocation.split("/");
array.pop();
array.push(testPage);
secureTestLocation = array.join("/");
}
secureTestLocation += "?runtest";
if (hasMixedActiveContent) {
SpecialPowers.pushPrefEnv(
{"set": [["security.mixed_content.block_active_content", false]]},
null);
}
if (openTwoWindows) {
_windowCount = 2;
window.open(secureTestLocation, "_new1", "");
window.open(secureTestLocation, "_new2", "");
} else {
_windowCount = 1;
window.open(secureTestLocation);
}
}
};
function onMessageReceived(event)
{
switch (event.data) {
// Indication of all test parts finish (from any of the frames)
case "done":
if (--_windowCount == 0) {
if (testCleanUp) {
testCleanUp();
}
if (hasMixedActiveContent) {
SpecialPowers.popPrefEnv(null);
}
SimpleTest.finish();
}
break;
// Any other message is an error or success message of a test.
default:
SimpleTest.ok(!event.data.match(/^FAILURE/), event.data);
break;
}
}
function postMsg(message)
{
opener.postMessage(message, "http://mochi.test:8888");
}
function finish()
{
if (history.length == 1 && !bypassNavigationTest) {
window.setTimeout(() => {
window.location.assign(navigateToInsecure ?
"http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/backward.html" :
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/backward.html");
}, 0);
} else {
postMsg("done");
window.close();
}
}
function ok(a, message)
{
if (!a) {
postMsg("FAILURE: " + message);
} else {
postMsg(message);
}
}
function is(a, b, message)
{
if (a != b) {
postMsg(`FAILURE: ${message}, expected ${b} got ${a}`);
} else {
postMsg(`${message}, expected ${b} got ${a}`);
}
}
function isSecurityState(expectedState, message, test)
{
if (!test) {
test = ok;
}
let ui = SpecialPowers.wrap(window)
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
.QueryInterface(SpecialPowers.Ci.nsIDocShell)
.securityUI;
let isInsecure = !ui ||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_IS_INSECURE);
let isBroken = ui &&
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_IS_BROKEN);
let isEV = ui &&
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
let gotState = "secure";
if (isInsecure) {
gotState = "insecure";
} else if (isBroken) {
gotState = "broken";
} else if (isEV) {
gotState = "EV";
}
test(gotState == expectedState, (message || "") + ", " + "expected " + expectedState + " got " + gotState);
switch (expectedState) {
case "insecure":
test(isInsecure && !isBroken && !isEV, "for 'insecure' excpected flags [1,0,0], " + (message || ""));
break;
case "broken":
test(ui && !isInsecure && isBroken && !isEV, "for 'broken' expected flags [0,1,0], " + (message || ""));
break;
case "secure":
test(ui && !isInsecure && !isBroken && !isEV, "for 'secure' expected flags [0,0,0], " + (message || ""));
break;
case "EV":
test(ui && !isInsecure && !isBroken && isEV, "for 'EV' expected flags [0,0,1], " + (message || ""));
break;
default:
throw new Error("Invalid isSecurityState state");
}
}
function waitForSecurityState(expectedState, callback)
{
let roundsLeft = 200; // Wait for 20 seconds (=200*100ms)
let interval = window.setInterval(() => {
isSecurityState(expectedState, "", isok => {
if (isok) {
roundsLeft = 0;
}
});
if (!roundsLeft--) {
window.clearInterval(interval);
callback();
}
}, 100);
}

View file

@ -0,0 +1,62 @@
[DEFAULT]
skip-if = toolkit == 'android' #TIMED_OUT
support-files =
alloworigin.sjs
backward.html
bug329869.js
bug383369step2.html
bug383369step3.html
download.auto
download.auto^headers^
emptyimage.sjs
hugebmp.sjs
iframe.html
iframe2.html
iframeMetaRedirect.html
iframesecredirect.sjs
iframeunsecredirect.sjs
imgsecredirect.sjs
imgunsecredirect.sjs
mixedContentTest.js
moonsurface.jpg
nocontent.sjs
redirecttoemptyimage.sjs
somestyle.css
unsecureIframe.html
unsecurePictureDup.html
[test_bug329869.html]
[test_bug383369.html]
[test_bug455367.html]
[test_bug472986.html]
[test_bug477118.html]
[test_bug521461.html]
[test_cssBefore1.html]
[test_cssContent1.html]
[test_cssContent2.html]
[test_documentWrite1.html]
[test_documentWrite2.html]
[test_dynDelayedUnsecurePicture.html]
[test_dynDelayedUnsecureXHR.html]
[test_dynUnsecureBackground.html]
[test_dynUnsecureIframeRedirect.html]
[test_dynUnsecurePicture.html]
[test_dynUnsecurePicturePreload.html]
# [test_dynUnsecureRedirect.html]
# intermitently fails, quite often, bug 487402
[test_innerHtmlDelayedUnsecurePicture.html]
[test_innerHtmlUnsecurePicture.html]
[test_javascriptPicture.html]
[test_secureAll.html]
[test_securePicture.html]
[test_unsecureBackground.html]
[test_unsecureCSS.html]
[test_unsecureIframe.html]
[test_unsecureIframe2.html]
# [test_unsecureIframeMetaRedirect.html]
# intermittently fails, less often, bug 487632
[test_unsecureIframeRedirect.html]
[test_unsecurePicture.html]
[test_unsecurePictureDup.html]
[test_unsecurePictureInIframe.html]
[test_unsecureRedirect.html]

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -0,0 +1,8 @@
# -*- Mode: python; 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/.
MOCHITEST_MANIFESTS += ['mochitest.ini']

View file

@ -0,0 +1,4 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 204, "No Content");
}

View file

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
response.setHeader("Location", "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/emptyimage.sjs");
}

View file

@ -0,0 +1,4 @@
body
{
background-color: lightBlue;
}

View file

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
<title>dymanic script load</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
hasMixedActiveContent = true;
function runTest()
{
isSecurityState("secure");
window.setTimeout(function () {
let newElement = document.createElement("script");
newElement.src = "http://example.org/tests/security/manager/ssl/tests/" +
"mochitest/mixedcontent/bug329869.js";
document.body.appendChild(newElement);
}, 0);
}
function afterNavigationTest()
{
isSecurityState("broken", "security still broken after navigation");
finish();
}
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1,102 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 383369 test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* sendAsyncMessage isn't actually a global - this just mollifies eslint */
/* global sendAsyncMessage */
/* import-globals-from mixedContentTest.js */
"use strict";
// We want to start this test from an insecure context
loadAsInsecure = true;
// We don't want to go through the navigation back/forward test
bypassNavigationTest = true;
function runTest() {
let script = SpecialPowers.loadChromeScript(function() {
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
// Force download to be w/o user assistance for our testing mime type
const mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo =
mimeSvc.getFromTypeAndExtension("application/x-auto-download", "auto");
handlerInfo.preferredAction = Ci.nsIHandlerInfo.saveToDisk;
handlerInfo.alwaysAskBeforeHandling = false;
handlerInfo.preferredApplicationHandler = null;
const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"]
.getService(Ci.nsIHandlerService);
handlerSvc.store(handlerInfo);
let dirProvider = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
let profileDir = dirProvider.get("ProfDS", Ci.nsIFile);
profileDir.append("downloads");
let prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService);
let prefBranch = prefs.getBranch("browser.download.");
prefBranch.setCharPref("dir", profileDir.path);
prefBranch.setBoolPref("useDownloadDir", true);
prefBranch.setIntPref("folderList", 2);
prefBranch.setBoolPref("manager.closeWhenDone", true);
prefBranch.setBoolPref("manager.showWhenStarting", false);
const { Downloads } =
Cu.import("resource://gre/modules/Downloads.jsm", {});
Downloads.getList(Downloads.PUBLIC).then(list => {
list.addView({
onDownloadAdded: function (aDownload) {
list.removeView(this);
aDownload.whenSucceeded().then(() => {
list.removeFinished();
sendAsyncMessage("navigate", "bug383369step2.html");
});
},
});
sendAsyncMessage("navigate", "download.auto");
}).then(null, Cu.reportError);
});
script.addMessageListener("navigate", function(url) {
window.location = url;
});
}
function afterNavigationTest() {}
testCleanUp = function cleanup() {
SpecialPowers.loadChromeScript(function() {
const { classes: Cc, interfaces: Ci } = Components;
const mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo =
mimeSvc.getFromTypeAndExtension("application/x-auto-download", "auto");
const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"]
.getService(Ci.nsIHandlerService);
handlerSvc.remove(handlerInfo);
let prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService);
let prefBranch = prefs.getBranch("browser.download.");
const prefKeys = ["dir", "useDownloadDir", "folderList",
"manager.closeWhenDone", "manager.showWhenStarting"];
for (let prefKey of prefKeys) {
if (prefBranch.prefHasUserValue(prefKey)) {
prefBranch.clearUserPref(prefKey);
}
}
});
};
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<title>No content image doesn't break security</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("broken", "broken");
finish();
}
function afterNavigationTest()
{
isSecurityState("broken", "broken after navigation");
finish();
}
</script>
</head>
<body>
<img src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/redirecttoemptyimage.sjs" />
</body>
</html>

View file

@ -0,0 +1,47 @@
<!DOCTYPE HTML>
<html>
<head>
<title>img.src replace</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
SimpleTest.expectAssertions(0, 4);
// Clear the default onload assigned to test start because we must
// wait for replaced image to load and only after that test the security state
var onLoadFunction = window.onload;
window.onload = function()
{
let img1 = document.getElementById("img1");
img1.addEventListener("load", onLoadFunction, false);
img1.src = "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg";
};
function runTest()
{
isSecurityState("secure", "secure");
finish();
}
function afterNavigationTest()
{
isSecurityState("secure", "secure after navigation");
finish();
}
</script>
</head>
<body>
<img id="img1" src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/hugebmp.sjs" />
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 477118</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("secure", "data <img> doesn't break security");
finish();
}
function afterNavigationTest()
{
isSecurityState("secure", "still secure after navigation");
finish();
}
</script>
</head>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB9kBDxIAOdxBIbcAAAI+SURBVDjLxZO7TxRhFMV/M/PN7EPYhS02yytggo+ERAgxERsNhYnGzsQojaHT3r9F0cTaUjs6NUQLBRKDi4I8FEwkLMgO+5rdeX3XAoVYiZWnP797cu69Bv8gqZ+0QTqIdRpl1VHGvnV884CJwQgwicVtoB/ku/H4ycOnURgP/Q1g21Fw4+r0RjbbNmaq4ayO35UkXp9S2UzHxK2bE4QNl82FVwD0D49jn+hERBCRgwTiIX7pvGUGYF/BlO327d3ENfV7wuL0AyjPICIsfPvAmev3qdVqlMtlCoUCGxurDPT1kEnPomQKkRTFpXOjh4DN4kvGLuSJ/JC38y/ouXyXYrGIiBDHMVtbu1SrvXTlbfp6HcQcoVwp5hRAaWedPXFYfL+E1lAKswSRy+joKEEQICLkcjm01hiGgRcksW0b4SMKYHb+OSt6ma+VffxWRF3S5OeeMX7pHkqpwy5EBK31H90ogFODF1lbm8OtlEhloDORpbdnhDAMaTabhwbbtkkkEkRRhGVZR4BCfojJO4+o1VwQAItEIolpmliWRVtbG7s/dlDKotGo47U8CvkuAEwA3/eJoxhE0WyGuO4+nucRBAHVahXDMKg3agRhQBAGVKsVtNZHCRzHwTAMcrnc0eX9it3e3g7A6cGzhx0AKHWwQOV5jdXXb2ZOaa3BOP5ffF5ZptVqflG+3xpbWv5kh2FolEo7dnmv7Lium6zXG0nf95MiguM4QTqd9jPZTCvX2eF393QHqVRKZ7KZkP+unzPGLX8Jr7F8AAAAAElFTkSuQmCC" />
</body>
</html>

View file

@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 521461</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
loadAsInsecure = true;
function runTest()
{
window.location = "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/nocontent.sjs";
window.setTimeout(function() {
isSecurityState("insecure", "location.href doesn't effect the security state");
is(document.body.innerHTML, "This is an unsecure page!", "Document has not changed content");
finish();
}, 1000);
}
function afterNavigationTest()
{
isSecurityState("insecure", "still not secure after navigation");
is(document.body.innerHTML, "This is an unsecure page!", "Document has not changed content");
finish();
}
</script>
</head>
<body>This is an unsecure page!</body></html>

View file

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<head>
<title>CSS :before styling 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style type="text/css">
p:before
{
content: url(http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg);
}
</style>
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("broken", "insecure content added by :before styling breaks security");
finish();
}
function afterNavigationTest()
{
isSecurityState("broken", "security still broken after navigation");
finish();
}
</script>
</head>
<body>
<p>
There is a moon surface left to this text
</p>
</body>
</html>

View file

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<title>CSS conent styling 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style type="text/css">
p
{
content: url(http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg);
}
</style>
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("broken", "insecure content added by :before styling breaks security");
finish();
}
function afterNavigationTest()
{
isSecurityState("broken", "security still broken after navigation");
finish();
}
</script>
</head>
<body>
<p></p>
</body>
</html>

View file

@ -0,0 +1,47 @@
<!DOCTYPE HTML>
<html>
<head>
<title>CSS conent styling 2</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
if (navigator.platform.startsWith("Mac")) {
SimpleTest.expectAssertions(0, 1);
}
function runTest()
{
isSecurityState("secure");
document.getElementById("para").style.content =
"url('http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg')";
waitForSecurityState("broken", function()
{
isSecurityState("broken", "insecure content added by styling breaks security");
finish();
});
}
function afterNavigationTest()
{
is(document.getElementById("para").style.content, "");
isSecurityState("secure", "security full after navigation");
finish();
}
</script>
</head>
<body>
<p id="para"></p>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<head>
<title>document.write('<img src="http://">')</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("broken", "insecure <img> written dynamically breaks security");
finish();
}
function afterNavigationTest()
{
isSecurityState("broken", "security still broken after navigation");
finish();
}
</script>
</head>
<body>
<script class="testbody" type="text/javascript">
document.write(
"<img src='http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg' />");
</script>
</body>
</html>

View file

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<head>
<title>document.write('<iframe src="http://">')</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
hasMixedActiveContent = true;
function runTest()
{
isSecurityState("broken", "insecure iframe written dynamically breaks security");
finish();
}
function afterNavigationTest()
{
isSecurityState("broken", "security still broken after navigation");
finish();
}
</script>
</head>
<body>
<script class="testbody" type="text/javascript">
document.write(
"<iframe src='http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html'></iframe>");
</script>
</body>
</html>

View file

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<head>
<title>img.src changes to unsecure test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("secure");
window.setTimeout(function() {
// Don't do this synchronously from onload handler
document.getElementById("image1").src =
"http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg";
}, 0);
waitForSecurityState("broken", function()
{
isSecurityState("broken", "src='http://...' changed to broken");
finish();
});
}
function afterNavigationTest()
{
is(document.getElementById("image1").src,
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg",
"img.src secure again");
isSecurityState("secure", "security full after navigation");
finish();
}
</script>
</head>
<body>
<img id="image1" src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg" />
</body>
</html>

View file

@ -0,0 +1,49 @@
<!DOCTYPE HTML>
<html>
<head>
<title>unsecure XHR test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
hasMixedActiveContent = true;
function runTest()
{
isSecurityState("secure");
window.setTimeout(() => {
try {
let req = new XMLHttpRequest();
req.open("GET", "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/alloworigin.sjs", false);
req.send(null);
// Change should be immediate, the request was sent synchronously
isSecurityState("broken", "security broken after insecure XHR");
} catch (ex) {
ok(false, ex);
}
finish();
}, 0);
}
function afterNavigationTest()
{
isSecurityState("secure", "security full after navigation");
finish();
}
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<head>
<title>body.background changes to unsecure test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
// This test, as is, equals to https://kuix.de/misc/test17/358438.php
function runTest()
{
isSecurityState("secure");
document.body.background =
"http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg";
waitForSecurityState("broken", function () {
isSecurityState("broken", "document.body.background='http://...' changed to broken");
finish();
});
}
function afterNavigationTest()
{
is(document.body.background,
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg",
"document backround secure again");
isSecurityState("secure", "secure after re-navigation");
finish();
}
</script>
</head>
<body background="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg">
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<head>
<title>iframe.src changes to unsecure redirect test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
hasMixedActiveContent = true;
function runTest()
{
isSecurityState("secure");
let self = window;
let iframe = document.getElementById("iframe1");
iframe.onload = function() {
self.isSecurityState("broken", "src='redirect to unsecure' changed to broken");
self.finish();
};
iframe.src =
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframeunsecredirect.sjs";
}
function afterNavigationTest()
{
isSecurityState("broken", "security still broken after navigation");
finish();
}
</script>
</head>
<body>
<iframe id="iframe1" src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<head>
<title>img.src changes to unsecure test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
// This test, as is, equals to https://kuix.de/misc/test17/358438.php
function runTest()
{
isSecurityState("secure");
document.getElementById("image1").src =
"http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg";
window.setTimeout(function() {
isSecurityState("broken", "src='http://...' changed to broken");
finish();
}, 500);
}
function afterNavigationTest()
{
is(document.getElementById("image1").src,
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg",
"img.src secure again");
isSecurityState("secure", "security full after navigation");
finish();
}
</script>
</head>
<body>
<img id="image1" src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg" />
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
<title>img.src changes to unsecure test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
(new Image()).src =
"http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg";
function runTest()
{
isSecurityState("broken", "(new Image()).src='http://...' changed to broken");
finish();
}
function afterNavigationTest()
{
isSecurityState("broken", "security broken after navigation");
finish();
}
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<head>
<title>img.src changes to unsecure redirect test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("secure");
document.getElementById("image1").src =
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/imgunsecredirect.sjs";
window.setTimeout(function() {
isSecurityState("broken", "src='redirect to unsecure' changed to broken");
finish();
}, 500);
}
function afterNavigationTest()
{
is(document.getElementById("image1").src,
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg",
"img.src secure again");
isSecurityState("secure", "security full after navigation");
finish();
}
</script>
</head>
<body>
<img id="image1" src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg" />
</body>
</html>

View file

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<title>innerHTML changes to unsecure test</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mixedContentTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/* import-globals-from mixedContentTest.js */
"use strict";
function runTest()
{
isSecurityState("secure");
window.setTimeout(function () {
document.getElementById("buddy").innerHTML =
"<img id='image1' src='http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg' />";
}, 1);
waitForSecurityState("broken", function () {
isSecurityState("broken", "innerHTML loading insecure changed to broken");
finish();
});
}
function afterNavigationTest()
{
is(document.getElementById("buddy").innerHTML, "", "innerHTML back to previous");
isSecurityState("secure");
finish();
}
</script>
</head>
<body id="buddy"></body></html>

Some files were not shown because too many files have changed in this diff Show more