def sign(self): logger.debug('certificate.sign') assert self.cert != None assert self.issuerSubject != None assert self.issuerKey != None self.cert.set_issuer(self.issuerSubject) self.cert.sign(self.issuerKey.get_openssl_pkey(), self.digest)
def get_extensions(self): # pyOpenSSL does not have a way to get extensions triples=[] m2x509 = X509.load_cert_string(self.save_to_string()) nb_extensions=m2x509.get_ext_count() logger.debug("X509 had %d extensions"%nb_extensions) for i in range(nb_extensions): ext=m2x509.get_ext_at(i) triples.append( (ext.get_name(), ext.get_value(), ext.get_critical(),) ) return triples
def __init__(self, create=False, subject=None, string=None, filename=None, uuid=None, hrn=None, urn=None, lifeDays=1825): Certificate.__init__(self, lifeDays, create, subject, string, filename) if subject: logger.debug("Creating GID for subject: %s" % subject) if uuid: self.uuid = int(uuid) if hrn: self.hrn = hrn self.urn = hrn_to_urn(hrn, 'unknown') if urn: self.urn = urn self.hrn, type = urn_to_hrn(urn)
def get_extensions(self): # pyOpenSSL does not have a way to get extensions triples = [] m2x509 = X509.load_cert_string(self.save_to_string()) nb_extensions = m2x509.get_ext_count() logger.debug("X509 had %d extensions" % nb_extensions) for i in range(nb_extensions): ext = m2x509.get_ext_at(i) triples.append(( ext.get_name(), ext.get_value(), ext.get_critical(), )) return triples
def verify_issuer(self, trusted_gids): root_cred = self.get_credential_list()[-1] root_target_gid = root_cred.get_gid_object() root_cred_signer = root_cred.get_signature().get_issuer_gid() # Case 1: # Allow non authority to sign target and cred about target. # # Why do we need to allow non authorities to sign? # If in the target gid validation step we correctly # checked that the target is only signed by an authority, # then this is just a special case of case 3. # This short-circuit is the common case currently - # and cause GID validation doesn't check 'authority', # this allows users to generate valid slice credentials. if root_target_gid.is_signed_by_cert(root_cred_signer): # cred signer matches target signer, return success return # Case 2: # Allow someone to sign credential about themeselves. Used? # If not, remove this. #root_target_gid_str = root_target_gid.save_to_string() #root_cred_signer_str = root_cred_signer.save_to_string() #if root_target_gid_str == root_cred_signer_str: # # cred signer is target, return success # return # Case 3: # root_cred_signer is not the target_gid # So this is a different gid that we have not verified. # xmlsec1 verified the cert chain on this already, but # it hasn't verified that the gid meets the HRN namespace # requirements. # Below we'll ensure that it is an authority. # But we haven't verified that it is _signed by_ an authority # We also don't know if xmlsec1 requires that cert signers # are marked as CAs. # Note that if verify() gave us no trusted_gids then this # call will fail. So skip it if we have no trusted_gids if trusted_gids and len(trusted_gids) > 0: root_cred_signer.verify_chain(trusted_gids) else: logger.debug( "No trusted gids. Cannot verify that cred signer is signed by a trusted authority. Skipping that check." ) # See if the signer is an authority over the domain of the target. # There are multiple types of authority - accept them all here # Maybe should be (hrn, type) = urn_to_hrn(root_cred_signer.get_urn()) root_cred_signer_type = root_cred_signer.get_type() if (root_cred_signer_type.find('authority') == 0): #logger.debug('Cred signer is an authority') # signer is an authority, see if target is in authority's domain signerhrn = root_cred_signer.get_hrn() if hrn_authfor_hrn(signerhrn, root_target_gid.get_hrn()): return # We've required that the credential be signed by an authority # for that domain. Reasonable and probably correct. # A looser model would also allow the signer to be an authority # in my control framework - eg My CA or CH. Even if it is not # the CH that issued these, eg, user credentials. # Give up, credential does not pass issuer verification raise CredentialNotVerifiable( "Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))
def verify_chain(self, trusted_certs=None): # Verify a chain of certificates. Each certificate must be signed by # the public key contained in it's parent. The chain is recursed # until a certificate is found that is signed by a trusted root. # verify expiration time if self.cert.has_expired(): logger.debug("verify_chain: NO, Certificate %s has expired" % self.get_printable_subject()) raise CertExpired(self.get_printable_subject(), "client cert") # if this cert is signed by a trusted_cert, then we are set for trusted_cert in trusted_certs: if self.is_signed_by_cert(trusted_cert): # verify expiration of trusted_cert ? if not trusted_cert.cert.has_expired(): logger.debug( "verify_chain: YES. Cert %s signed by trusted cert %s" % (self.get_printable_subject(), trusted_cert.get_printable_subject())) return trusted_cert else: logger.debug( "verify_chain: NO. Cert %s is signed by trusted_cert %s, but that signer is expired..." % (self.get_printable_subject(), trusted_cert.get_printable_subject())) raise CertExpired( self.get_printable_subject(), " signer trusted_cert %s" % trusted_cert.get_printable_subject()) # if there is no parent, then no way to verify the chain if not self.parent: logger.debug( "verify_chain: NO. %s has no parent and issuer %s is not in %d trusted roots" % (self.get_printable_subject(), self.get_issuer(), len(trusted_certs))) raise CertMissingParent( self.get_printable_subject() + ": Issuer %s is not one of the %d trusted roots, and cert has no parent." % (self.get_issuer(), len(trusted_certs))) # if it wasn't signed by the parent... if not self.is_signed_by_cert(self.parent): logger.debug("verify_chain: NO. %s is not signed by parent %s, but by %s"%\ (self.get_printable_subject(), self.parent.get_printable_subject(), self.get_issuer())) raise CertNotSignedByParent("%s: Parent %s, issuer %s"\ % (self.get_printable_subject(), self.parent.get_printable_subject(), self.get_issuer())) # Confirm that the parent is a CA. Only CAs can be trusted as # signers. # Note that trusted roots are not parents, so don't need to be # CAs. # Ugly - cert objects aren't parsed so we need to read the # extension and hope there are no other basicConstraints if not self.parent.isCA and not ( self.parent.get_extension('basicConstraints') == 'CA:TRUE'): logger.warn("verify_chain: cert %s's parent %s is not a CA" % \ (self.get_printable_subject(), self.parent.get_printable_subject())) raise CertNotSignedByParent("%s: Parent %s not a CA" % (self.get_printable_subject(), self.parent.get_printable_subject())) # if the parent isn't verified... logger.debug("verify_chain: .. %s, -> verifying parent %s"%\ (self.get_printable_subject(),self.parent.get_printable_subject())) self.parent.verify_chain(trusted_certs) return
def verify_chain(self, trusted_certs = None): # Verify a chain of certificates. Each certificate must be signed by # the public key contained in it's parent. The chain is recursed # until a certificate is found that is signed by a trusted root. # verify expiration time if self.cert.has_expired(): logger.debug("verify_chain: NO, Certificate %s has expired" % self.get_printable_subject()) raise CertExpired(self.get_printable_subject(), "client cert") # if this cert is signed by a trusted_cert, then we are set for trusted_cert in trusted_certs: if self.is_signed_by_cert(trusted_cert): # verify expiration of trusted_cert ? if not trusted_cert.cert.has_expired(): logger.debug("verify_chain: YES. Cert %s signed by trusted cert %s"%( self.get_printable_subject(), trusted_cert.get_printable_subject())) return trusted_cert else: logger.debug("verify_chain: NO. Cert %s is signed by trusted_cert %s, but that signer is expired..."%( self.get_printable_subject(),trusted_cert.get_printable_subject())) raise CertExpired(self.get_printable_subject()," signer trusted_cert %s"%trusted_cert.get_printable_subject()) # if there is no parent, then no way to verify the chain if not self.parent: logger.debug("verify_chain: NO. %s has no parent and issuer %s is not in %d trusted roots"%(self.get_printable_subject(), self.get_issuer(), len(trusted_certs))) raise CertMissingParent(self.get_printable_subject() + ": Issuer %s is not one of the %d trusted roots, and cert has no parent." % (self.get_issuer(), len(trusted_certs))) # if it wasn't signed by the parent... if not self.is_signed_by_cert(self.parent): logger.debug("verify_chain: NO. %s is not signed by parent %s, but by %s"%\ (self.get_printable_subject(), self.parent.get_printable_subject(), self.get_issuer())) raise CertNotSignedByParent("%s: Parent %s, issuer %s"\ % (self.get_printable_subject(), self.parent.get_printable_subject(), self.get_issuer())) # Confirm that the parent is a CA. Only CAs can be trusted as # signers. # Note that trusted roots are not parents, so don't need to be # CAs. # Ugly - cert objects aren't parsed so we need to read the # extension and hope there are no other basicConstraints if not self.parent.isCA and not (self.parent.get_extension('basicConstraints') == 'CA:TRUE'): logger.warn("verify_chain: cert %s's parent %s is not a CA" % \ (self.get_printable_subject(), self.parent.get_printable_subject())) raise CertNotSignedByParent("%s: Parent %s not a CA" % (self.get_printable_subject(), self.parent.get_printable_subject())) # if the parent isn't verified... logger.debug("verify_chain: .. %s, -> verifying parent %s"%\ (self.get_printable_subject(),self.parent.get_printable_subject())) self.parent.verify_chain(trusted_certs) return
def verify_issuer(self, trusted_gids): root_cred = self.get_credential_list()[-1] root_target_gid = root_cred.get_gid_object() root_cred_signer = root_cred.get_signature().get_issuer_gid() # Case 1: # Allow non authority to sign target and cred about target. # # Why do we need to allow non authorities to sign? # If in the target gid validation step we correctly # checked that the target is only signed by an authority, # then this is just a special case of case 3. # This short-circuit is the common case currently - # and cause GID validation doesn't check 'authority', # this allows users to generate valid slice credentials. if root_target_gid.is_signed_by_cert(root_cred_signer): # cred signer matches target signer, return success return # Case 2: # Allow someone to sign credential about themeselves. Used? # If not, remove this. #root_target_gid_str = root_target_gid.save_to_string() #root_cred_signer_str = root_cred_signer.save_to_string() #if root_target_gid_str == root_cred_signer_str: # # cred signer is target, return success # return # Case 3: # root_cred_signer is not the target_gid # So this is a different gid that we have not verified. # xmlsec1 verified the cert chain on this already, but # it hasn't verified that the gid meets the HRN namespace # requirements. # Below we'll ensure that it is an authority. # But we haven't verified that it is _signed by_ an authority # We also don't know if xmlsec1 requires that cert signers # are marked as CAs. # Note that if verify() gave us no trusted_gids then this # call will fail. So skip it if we have no trusted_gids if trusted_gids and len(trusted_gids) > 0: root_cred_signer.verify_chain(trusted_gids) else: logger.debug("No trusted gids. Cannot verify that cred signer is signed by a trusted authority. Skipping that check.") # See if the signer is an authority over the domain of the target. # There are multiple types of authority - accept them all here # Maybe should be (hrn, type) = urn_to_hrn(root_cred_signer.get_urn()) root_cred_signer_type = root_cred_signer.get_type() if (root_cred_signer_type.find('authority') == 0): #logger.debug('Cred signer is an authority') # signer is an authority, see if target is in authority's domain signerhrn = root_cred_signer.get_hrn() if hrn_authfor_hrn(signerhrn, root_target_gid.get_hrn()): return # We've required that the credential be signed by an authority # for that domain. Reasonable and probably correct. # A looser model would also allow the signer to be an authority # in my control framework - eg My CA or CH. Even if it is not # the CH that issued these, eg, user credentials. # Give up, credential does not pass issuer verification raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))