1# 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( 37 '%s x509 -noout -%s -in %s' % 38 (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 72