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