From deeb0a4fd88981d562b2baf7d4eae6ead0ca7eda Mon Sep 17 00:00:00 2001 From: Josh Karlin Date: Mon, 8 Mar 2010 21:08:52 +0000 Subject: [PATCH] certificates now support w/ or without parent tag, and can write to issuerAltName as well as subjectAltName --- CHANGES-GENI-API.txt | 16 +++++++++---- sfa/trust/certificate.py | 52 ++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/CHANGES-GENI-API.txt b/CHANGES-GENI-API.txt index b9c428b5..9d37dd83 100644 --- a/CHANGES-GENI-API.txt +++ b/CHANGES-GENI-API.txt @@ -1,9 +1,15 @@ -2010-03-03 Josh Karlin +2010-03-08 Josh Karlin - * sfa/trust/certificate.py (Certificate.load_from_string): - Certificates no longer use a parent separator. Now uses the - standard openssl chaining format which is to simply append - certificates together. + * sfa/trust/certificate.py (Certificate.save_to_string): SaveParents defaults to true + (Certificate.save_to_string): Saves without the parent tag. + (Certificate.set_data): Accepts optional field + (Certificate.get_data): Accepts optional field +2010-03-05 Josh Karlin + + * sfa/trust/certificate.py (Certificate.load_from_string): + Certificates can either use a parent separator or do the standard + chaining method which is to just append multiple certs in one file + without any special separator. diff --git a/sfa/trust/certificate.py b/sfa/trust/certificate.py index 9b488357..bcdd214a 100644 --- a/sfa/trust/certificate.py +++ b/sfa/trust/certificate.py @@ -70,7 +70,7 @@ def convert_public_key(key): class Keypair: key = None # public/private keypair m2key = None # public key (m2crypto format) - + ## # Creates a Keypair object # @param create If create==True, creates a new public/private key and @@ -218,7 +218,7 @@ class Keypair: class Certificate: digest = "md5" - data = None + data = {} cert = None issuerKey = None issuerSubject = None @@ -266,13 +266,23 @@ class Certificate: def load_from_string(self, string): # if it is a chain of multiple certs, then split off the first one and - # load it - parts = string.split(Certificate.separator, 1) + # load it (support for the ---parent--- tag as well as normal chained certs) + + string = string.strip() + + parts = [] + if string.count('-----BEGIN CERTIFICATE-----') > 1 and \ + string.count(Certificate.separator) == 0: + parts = string.split('-----END CERTIFICATE-----',1) + parts[0] += '-----END CERTIFICATE-----' + else: + parts = string.split(Certificate.separator, 1) + self.cert = crypto.load_certificate(crypto.FILETYPE_PEM, parts[0]) # if there are more certs, then create a parent and let the parent load # itself from the remainder of the string - if len(parts) > 1: + if len(parts) > 1 and parts[1] != '': self.parent = self.__class__() self.parent.load_from_string(parts[1]) @@ -289,10 +299,10 @@ class Certificate: # # @param save_parents If save_parents==True, then also save the parent certificates. - def save_to_string(self, save_parents=False): + def save_to_string(self, save_parents=True): string = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert) if save_parents and self.parent: - string = string + Certificate.separator + self.parent.save_to_string(save_parents) + string = string + self.parent.save_to_string(save_parents) return string ## @@ -403,31 +413,31 @@ class Certificate: # the X509 subject_alt_name extension. Set_data can only be called once, due # to limitations in the underlying library. - def set_data(self, str): + def set_data(self, str, field='subjectAltName'): # pyOpenSSL only allows us to add extensions, so if we try to set the # same extension more than once, it will not work - if self.data != None: - raise "cannot set subjectAltName more than once" - self.data = str - self.add_extension("subjectAltName", 0, "URI:http://" + str) + if self.data.has_key(field): + raise "cannot set ", field, " more than once" + self.data[field] = str + self.add_extension(field, 0, "URI:http://" + str) ## # Return the data string that was previously set with set_data - def get_data(self): - if self.data: - return self.data + def get_data(self, field='subjectAltName'): + if self.data.has_key(field): + return self.data[field] try: - uri = self.get_extension("subjectAltName") + uri = self.get_extension(field) except LookupError: - self.data = None - return self.data + self.data.pop(field) + return None if not uri.startswith("URI:http://"): - raise "bad encoding in subjectAltName" - self.data = uri[11:] - return self.data + raise "bad encoding in ", field + self.data[field] = uri[11:] + return self.data[field] ## # Sign the certificate using the issuer private key and issuer subject previous set with set_issuer(). -- 2.43.0