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