def test_ReplaceCerts_skipNonExistentCerts(self):
        cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
        with open(cert1_path) as cert1_fp:
            cert1 = cert1_fp.read()
        cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
        with open(cert2_path) as cert2_fp:
            cert2 = cert2_fp.read()
        cert3_path = os.path.join(self.testdata_dir, 'testkey.x509.pem')
        with open(cert3_path) as cert3_fp:
            cert3 = cert3_fp.read()

        input_xml = self.MAC_PERMISSIONS_XML.format(
            base64.b16encode(common.ParseCertificate(cert1)).lower(),
            base64.b16encode(common.ParseCertificate(cert2)).lower())

        output_xml = self.MAC_PERMISSIONS_XML.format(
            base64.b16encode(common.ParseCertificate(cert3)).lower(),
            base64.b16encode(common.ParseCertificate(cert2)).lower())

        common.OPTIONS.key_map = {
            cert1_path[:-9]: cert3_path[:-9],
            'non-existent': cert3_path[:-9],
            cert2_path[:-9]: 'non-existent',
        }
        self.assertEqual(output_xml, ReplaceCerts(input_xml))
Exemple #2
0
def ReplaceCerts(data):
  """Given a string of data, replace all occurences of a set
  of X509 certs with a newer set of X509 certs and return
  the updated data string."""
  for old, new in OPTIONS.key_map.iteritems():
    try:
      if OPTIONS.verbose:
        print "    Replacing %s.x509.pem with %s.x509.pem" % (old, new)
      f = open(old + ".x509.pem")
      old_cert16 = base64.b16encode(common.ParseCertificate(f.read())).lower()
      f.close()
      f = open(new + ".x509.pem")
      new_cert16 = base64.b16encode(common.ParseCertificate(f.read())).lower()
      f.close()
      # Only match entire certs.
      pattern = "\\b"+old_cert16+"\\b"
      (data, num) = re.subn(pattern, new_cert16, data, flags=re.IGNORECASE)
      if OPTIONS.verbose:
        print "    Replaced %d occurence(s) of %s.x509.pem with " \
            "%s.x509.pem" % (num, old, new)
    except IOError as e:
      if e.errno == errno.ENOENT and not OPTIONS.verbose:
        continue

      print "    Error accessing %s. %s. Skip replacing %s.x509.pem " \
          "with %s.x509.pem." % (e.filename, e.strerror, old, new)

  return data
Exemple #3
0
def ReplaceCerts(data):
    """Replaces all the occurences of X.509 certs with the new ones.

  The mapping info is read from OPTIONS.key_map. Non-existent certificate will
  be skipped. After the replacement, it additionally checks for duplicate
  entries, which would otherwise fail the policy loading code in
  frameworks/base/services/core/java/com/android/server/pm/SELinuxMMAC.java.

  Args:
    data: Input string that contains a set of X.509 certs.

  Returns:
    A string after the replacement.

  Raises:
    AssertionError: On finding duplicate entries.
  """
    for old, new in OPTIONS.key_map.iteritems():
        if OPTIONS.verbose:
            print("    Replacing %s.x509.pem with %s.x509.pem" % (old, new))

        try:
            with open(old + ".x509.pem") as old_fp:
                old_cert16 = base64.b16encode(
                    common.ParseCertificate(old_fp.read())).lower()
            with open(new + ".x509.pem") as new_fp:
                new_cert16 = base64.b16encode(
                    common.ParseCertificate(new_fp.read())).lower()
        except IOError as e:
            if OPTIONS.verbose or e.errno != errno.ENOENT:
                print(
                    "    Error accessing %s: %s.\nSkip replacing %s.x509.pem with "
                    "%s.x509.pem." % (e.filename, e.strerror, old, new))
            continue

        # Only match entire certs.
        pattern = "\\b" + old_cert16 + "\\b"
        (data, num) = re.subn(pattern, new_cert16, data, flags=re.IGNORECASE)

        if OPTIONS.verbose:
            print(
                "    Replaced %d occurence(s) of %s.x509.pem with %s.x509.pem"
                % (num, old, new))

    # Verify that there're no duplicate entries after the replacement. Note that
    # it's only checking entries with global seinfo at the moment (i.e. ignoring
    # the ones with inner packages). (Bug: 69479366)
    root = ElementTree.fromstring(data)
    signatures = [
        signer.attrib['signature'] for signer in root.findall('signer')
    ]
    assert len(signatures) == len(set(signatures)), \
        "Found duplicate entries after cert replacement: {}".format(data)

    return data
    def test_ReplaceCerts_duplicateEntries(self):
        cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
        with open(cert1_path) as cert1_fp:
            cert1 = cert1_fp.read()
        cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
        with open(cert2_path) as cert2_fp:
            cert2 = cert2_fp.read()

        # Replace cert1 with cert2, which leads to duplicate entries.
        input_xml = self.MAC_PERMISSIONS_XML.format(
            base64.b16encode(common.ParseCertificate(cert1)).lower(),
            base64.b16encode(common.ParseCertificate(cert2)).lower())

        common.OPTIONS.key_map = {
            cert1_path[:-9]: cert2_path[:-9],
        }
        self.assertRaises(AssertionError, ReplaceCerts, input_xml)
Exemple #5
0
  def test_ParseCertificate(self):
    cert = os.path.join(self.testdata_dir, 'testkey.x509.pem')

    cmd = ['openssl', 'x509', '-in', cert, '-outform', 'DER']
    proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    expected, _ = proc.communicate()
    self.assertEqual(0, proc.returncode)

    with open(cert) as cert_fp:
      actual = common.ParseCertificate(cert_fp.read())
    self.assertEqual(expected, actual)
Exemple #6
0
  def FindLocalCerts(self):
    to_load = []
    for top in OPTIONS.local_cert_dirs:
      for dirpath, _, filenames in os.walk(top):
        certs = [os.path.join(dirpath, i)
                 for i in filenames if i.endswith(".x509.pem")]
        if certs:
          to_load.extend(certs)

    for i in to_load:
      with open(i) as f:
        cert = common.ParseCertificate(f.read())
      name, _ = os.path.splitext(i)
      name, _ = os.path.splitext(name)
      self.Add(cert, name)
Exemple #7
0
def CertFromPKCS7(data, filename):
  """Read the cert out of a PKCS#7-format file (which is what is
  stored in a signed .apk)."""
  Push(filename + ":")
  try:
    p = common.Run(["openssl", "pkcs7",
                    "-inform", "DER",
                    "-outform", "PEM",
                    "-print_certs"],
                   stdin=subprocess.PIPE,
                   stdout=subprocess.PIPE)
    out, err = p.communicate(data)
    if err and not err.strip():
      AddProblem("error reading cert:\n" + err)
      return None

    cert = common.ParseCertificate(out)
    if not cert:
      AddProblem("error parsing cert output")
      return None
    return cert
  finally:
    Pop()