blob: 75f1c24e566b6ddc886f594d1b5ffe383dd6163d [file] [log] [blame]
Paul Stewart32d30332013-10-01 22:39:37 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import tempfile
6
7from autotest_lib.client.bin import utils
8
9class PEMCertificate(object):
10 """Object enclosing a PEM certificate.
11
12 Uses the "openssl" utility to report various properties of a certificate.
13
14 """
15 OPENSSL_COMMAND = 'openssl'
16 ATTRIBUTE_SUBJECT = 'subject'
17 ATTRIBUTE_FINGERPRINT = 'fingerprint'
18
19 def __init__(self, pem_contents):
20 self._pem_contents = pem_contents
21 self._fingerprint = None
22 self._subject = None
23 self._subject_dict = None
24
25
26 def get_attribute(self, attribute):
27 """Returns the named attribute of the certificate.
28
29 @param attribute string referring to the attribute to retrieve.
30 @return string containing the retrieved attribute value.
31
32 """
33 with tempfile.NamedTemporaryFile() as temp:
34 temp.write(self._pem_contents)
35 temp.flush()
36 output = utils.system_output(
Mattias Nissler3ee6c8e2020-01-22 12:19:39 +010037 '%s x509 -noout -nameopt compat -%s -in %s' %
Paul Stewart32d30332013-10-01 22:39:37 -070038 (self.OPENSSL_COMMAND, attribute, temp.name))
39 # Output is of the form "name=value..."
40 return output.split('=', 1)[1]
41
42
43 @property
44 def fingerprint(self):
45 """Returns the SHA-1 fingerprint of a certificate."""
46 if self._fingerprint is None:
47 self._fingerprint = self.get_attribute(self.ATTRIBUTE_FINGERPRINT)
48 return self._fingerprint
49
50
51 @property
52 def subject(self):
53 """Returns the subject DN of the certificate as a list of name=value"""
54 if self._subject is None:
55 subject = self.get_attribute(self.ATTRIBUTE_SUBJECT)
56 # OpenSSL returns a form of:
57 # " /C=US/ST=CA/L=Mountain View/CN=chromelab..."
58 # but we want to return something like:
59 # [ "C=US", "ST=CA", "L=Mountain View", "CN=chromelab..." ]
60 self._subject = subject.lstrip(' /').split('/')
61 return self._subject
62
63
64 @property
65 def subject_dict(self):
66 """Returns the subject DN of the certificate as a dict of name:value"""
67 if self._subject_dict is None:
68 # Convert the list [ 'A=B', ... ] into a dict { 'A': 'B', ... }
69 self._subject_dict = dict(map(lambda x: x.split('=', 1),
70 self.subject))
71 return self._subject_dict