bug 1187029 - convert test_bug480509.html to an xpcshell test r=jcj
authorDavid Keeler <dkeeler@mozilla.com>
Thu, 23 Jul 2015 13:31:45 -0700
changeset 255049 e6d2b7ec0b6124c859cc3aa6907ec7c2ca17ac21
parent 255048 9c83aee00646105cecf2d779735e7403d39b7a64
child 255050 40c187d91db4de94a1d4883573d4d3490c225f93
push id62939
push userdkeeler@mozilla.com
push dateTue, 28 Jul 2015 23:07:27 +0000
treeherdermozilla-inbound@e6d2b7ec0b61 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjcj
bugs1187029, 480509
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1187029 - convert test_bug480509.html to an xpcshell test r=jcj
security/manager/ssl/tests/mochitest/bugs/mochitest.ini
security/manager/ssl/tests/mochitest/bugs/moz.build
security/manager/ssl/tests/mochitest/bugs/test_bug480509.html
security/manager/ssl/tests/unit/moz.build
security/manager/ssl/tests/unit/pycert.py
security/manager/ssl/tests/unit/test_cert_embedded_null.js
security/manager/ssl/tests/unit/test_cert_embedded_null/ca.pem.certspec
security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNull.pem.certspec
security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNullCNAndSAN.pem.certspec
security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNullSAN.pem.certspec
security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNullSAN2.pem.certspec
security/manager/ssl/tests/unit/test_cert_embedded_null/moz.build
security/manager/ssl/tests/unit/xpcshell.ini
deleted file mode 100644
--- a/security/manager/ssl/tests/mochitest/bugs/mochitest.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[DEFAULT]
-tags = psm
-skip-if = buildapp == 'b2g' || e10s
-
-[test_bug480509.html]
-skip-if = toolkit == 'android'
--- a/security/manager/ssl/tests/mochitest/bugs/moz.build
+++ b/security/manager/ssl/tests/mochitest/bugs/moz.build
@@ -1,9 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-MOCHITEST_MANIFESTS += ['mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
-
deleted file mode 100644
--- a/security/manager/ssl/tests/mochitest/bugs/test_bug480509.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<html>
-<head>
-  <title>Test bug 483437 and bug 480509</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
-</head>
-<body onload="onWindowLoad()">
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-function badCertListener() 
-{
-}
-
-badCertListener.prototype = {
-  badCertCaught: false,
-
-  getInterface: function (aIID) {
-    return this.QueryInterface(aIID);
-  },
-
-  QueryInterface: function(aIID) {
-    if (aIID.equals(SpecialPowers.Ci.nsIBadCertListener2) ||
-        aIID.equals(SpecialPowers.Ci.nsIInterfaceRequestor) ||
-        aIID.equals(SpecialPowers.Ci.nsISupports))
-      return this;
-
-    throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
-  },  
-
-  testCert: function(cert1, expected)
-  {
-    var certDumpTree1 = SpecialPowers.Cc["@mozilla.org/security/nsASN1Tree;1"]
-                       .createInstance(SpecialPowers.Ci.nsIASN1Tree);
-    certDumpTree1.loadASN1Structure(cert1.ASN1Structure);
-    var value1 = certDumpTree1.getDisplayData(9);
-    
-    is(value1, expected, "Incorrect subject recognized");
-  },
-  
-  notifyCertProblem: function(socketInfo, sslStatus, targetHost) {
-    var cert = sslStatus.QueryInterface(SpecialPowers.Ci.nsISSLStatus)
-      .serverCert;
-    this.testCert(cert, "CN = www.bank1.com\\00www.bad-guy.com\n");
-
-    this.badCertCaught = true;
-    return true;
-  }
-}
-
-function onFrameLoad()
-{
-  ok(false, "Attackers page failed to load");
-}
-
-function onWindowLoad()
-{
-  var req = new XMLHttpRequest();
-  var certListener = new badCertListener();
-  certListener = SpecialPowers.wrapCallbackObject(certListener);
-  try
-  {
-    req.open("GET", "https://www.bank1.com/", false);
-    SpecialPowers.wrap(req).channel.notificationCallbacks = certListener;
-    req.send(null);
-  }
-  catch(ex)
-  {
-    // ignore
-  }
-  
-  ok(certListener.badCertCaught, "We Caught the invalid certificate");
-  
-  SimpleTest.finish();
-}
-
-</script>
-
-<iframe src="https://www.bank1.com/" onload="onFrameLoad()"></iframe>
-</body>
-</html>
--- a/security/manager/ssl/tests/unit/moz.build
+++ b/security/manager/ssl/tests/unit/moz.build
@@ -2,16 +2,17 @@
 # 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/.
 
 DIRS += ['tlsserver']
 TEST_DIRS += [
     'test_cert_eku',
+    'test_cert_embedded_null',
     'test_cert_keyUsage',
     'test_cert_trust',
     'test_cert_version',
     'test_intermediate_basic_usage_constraints',
     'test_pinning_dynamic',
     'test_ocsp_url',
 ]
 
--- a/security/manager/ssl/tests/unit/pycert.py
+++ b/security/manager/ssl/tests/unit/pycert.py
@@ -147,17 +147,20 @@ def stringToAlgorithmIdentifier(string):
     return algorithmIdentifier
 
 def stringToCommonName(string):
     """Helper function for taking a string and building an x520 name
     representation usable by the pyasn1 package. Currently returns one
     RDN with one AVA consisting of a Common Name encoded as a
     UTF8String."""
     commonName = rfc2459.X520CommonName()
-    commonName.setComponentByName('utf8String', string)
+    # The string may have things like '\0' (i.e. a slash followed by
+    # the number zero) that have to be decoded into the resulting
+    # '\x00' (i.e. a byte with value zero).
+    commonName.setComponentByName('utf8String', string.decode(encoding='string_escape'))
     ava = rfc2459.AttributeTypeAndValue()
     ava.setComponentByName('type', rfc2459.id_at_commonName)
     ava.setComponentByName('value', commonName)
     rdn = rfc2459.RelativeDistinguishedName()
     rdn.setComponentByPosition(0, ava)
     rdns = rfc2459.RDNSequence()
     rdns.setComponentByPosition(0, rdn)
     name = rfc2459.Name()
@@ -328,17 +331,20 @@ class Certificate:
             count += 1
         self.addExtension(rfc2459.id_ce_extKeyUsage, extKeyUsageExtension)
 
     def addSubjectAlternativeName(self, dNSNames):
         subjectAlternativeName = rfc2459.SubjectAltName()
         count = 0
         for dNSName in dNSNames.split(','):
             generalName = rfc2459.GeneralName()
-            generalName.setComponentByName('dNSName', dNSName)
+            # The string may have things like '\0' (i.e. a slash
+            # followed by the number zero) that have to be decoded into
+            # the resulting '\x00' (i.e. a byte with value zero).
+            generalName.setComponentByName('dNSName', dNSName.decode(encoding='string_escape'))
             subjectAlternativeName.setComponentByPosition(count, generalName)
             count += 1
         self.addExtension(rfc2459.id_ce_subjectAltName, subjectAlternativeName)
 
     def addAuthorityInformationAccess(self, ocspURI):
         sequence = univ.Sequence()
         accessDescription = stringToAccessDescription(ocspURI)
         sequence.setComponentByPosition(0, accessDescription)
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null.js
@@ -0,0 +1,38 @@
+// -*- indent-tabs-mode: nil; js-indent-level: 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/.
+
+// Tests that a certificate with a clever subject common name like
+// 'www.bank1.com[NUL]www.bad-guy.com' (where [NUL] is a single byte with
+// value 0) will not be treated as valid for www.bank1.com.
+// Includes a similar test case but for the subject alternative name extension.
+
+"use strict";
+
+do_get_profile(); // must be called before getting nsIX509CertDB
+const certdb = Cc["@mozilla.org/security/x509certdb;1"]
+                 .getService(Ci.nsIX509CertDB);
+
+function do_testcase(certname, checkCommonName) {
+  let cert = constructCertFromFile(`test_cert_embedded_null/${certname}.pem`);
+  // Where applicable, check that the testcase is meaningful (i.e. that the
+  // certificate's subject common name has an embedded NUL in it).
+  if (checkCommonName) {
+    equal(cert.commonName, "www.bank1.com\\00www.bad-guy.com",
+          "certificate subject common name should have an embedded NUL byte");
+  }
+  checkCertErrorGeneric(certdb, cert, SSL_ERROR_BAD_CERT_DOMAIN,
+                        certificateUsageSSLServer, {}, "www.bank1.com");
+  checkCertErrorGeneric(certdb, cert, SSL_ERROR_BAD_CERT_DOMAIN,
+                        certificateUsageSSLServer, {}, "www.bad-guy.com");
+}
+
+function run_test() {
+  addCertFromFile(certdb, "test_cert_embedded_null/ca.pem", "CTu,,");
+
+  do_testcase("embeddedNull", true);
+  do_testcase("embeddedNullSAN", false);
+  do_testcase("embeddedNullCNAndSAN", true);
+  do_testcase("embeddedNullSAN2", false);
+}
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null/ca.pem.certspec
@@ -0,0 +1,4 @@
+issuer:ca
+subject:ca
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNull.pem.certspec
@@ -0,0 +1,2 @@
+issuer:ca
+subject:www.bank1.com\0www.bad-guy.com
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNullCNAndSAN.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:www.bank1.com\0www.bad-guy.com
+extension:subjectAlternativeName:www.bank1.com\0www.bad-guy.com
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNullSAN.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:embedded NUL in SAN
+extension:subjectAlternativeName:www.bank1.com\0www.bad-guy.com
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null/embeddedNullSAN2.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:bad-guy.com
+extension:subjectAlternativeName:bad-guy.com,www.bank1.com\0www.bad-guy.com
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_cert_embedded_null/moz.build
@@ -0,0 +1,21 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+test_certificates = (
+    'ca.pem',
+    'embeddedNull.pem',
+    'embeddedNullCNAndSAN.pem',
+    'embeddedNullSAN.pem',
+    'embeddedNullSAN2.pem',
+)
+
+for test_certificate in test_certificates:
+    input_file = test_certificate + '.certspec'
+    GENERATED_FILES += [test_certificate]
+    props = GENERATED_FILES[test_certificate]
+    props.script = '../pycert.py'
+    props.inputs = [input_file]
+    TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.test_cert_embedded_null += ['!%s' % test_certificate]
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -11,16 +11,17 @@ support-files =
   test_client_cert/**
   test_ev_certs/**
   test_getchain/**
   test_intermediate_basic_usage_constraints/**
   test_name_constraints/**
   test_cert_trust/**
   test_cert_version/**
   test_cert_eku/**
+  test_cert_embedded_null/**
   test_ocsp_url/**
   test_ocsp_fetch_method/**
   test_keysize/**
   test_pinning_dynamic/**
   test_onecrl/**
   test_validity/**
 
 [test_datasignatureverifier.js]
@@ -97,16 +98,18 @@ run-sequentially = hardcoded ports
 [test_cert_eku-NS_TS.js]
 [test_cert_eku-OS.js]
 [test_cert_eku-OS_SA.js]
 [test_cert_eku-OS_TS.js]
 [test_cert_eku-SA.js]
 [test_cert_eku-SA_TS.js]
 [test_cert_eku-TS.js]
 
+[test_cert_embedded_null.js]
+
 [test_pinning.js]
 run-sequentially = hardcoded ports
 # This test can take longer than 300 seconds on B2G emulator debug builds, so
 # give it enough time to finish. See bug 1081128.
 requesttimeoutfactor = 2
 [test_ocsp_url.js]
 # OCSP requests in this test time out on slow B2G Emulator debug builds.
 # See Bug 1147725.