def test_pem_remove_rfc7468_delimiters(): cert_str1 = fixture_cert_str(1) pem = XY509cert.pem_remove_rfc7468_delimiters(cert_str1, optional_delimiter=True) assert pem == fixture_cert_str(2) with pytest.raises(ValidationError): pem = XY509cert.pem_remove_rfc7468_delimiters(fixture_cert_str(2), optional_delimiter=False)
def _validate_authz(self) -> None: try: xml_sig_verifyer_response = self.ed.validateSignature() self.signer_cert_pem = xml_sig_verifyer_response.signer_cert_pem self.signer_cert_cn = XY509cert( self.signer_cert_pem).getSubjectCN() if len(self.ed.get_entityid_hostname()) == 0: self.authz_ok = False self.val_mesg_dict[ 'Hostname'] = 'Cannot authorize: no hostname found when URL-parsing entityID' raise NoFurtherValidation try: org_ids = self.policydict.get_orgids_for_signer( xml_sig_verifyer_response.signer_cert_pem) allowedDomains = self.policydict.getAllowedNamespacesForOrgs( org_ids) self.ed.validateDomainNames(allowedDomains) self.orgid = self.policydict.get_orgid( self.ed.get_entityid_hostname()) self.orgcn = self.policydict.get_orgcn(self.orgid) self.authz_ok = True except (PVZDuserexception) as e: self.authz_ok = False self.val_mesg_dict['Hostname'] = self._format_val_msg(e) except (PVZDuserexception) as e: self.authz_ok = False self.val_mesg_dict['Validate signature'] = self._format_val_msg(e)
def _save_trustedcerts_report(self) -> None: ''' Print human readable copy of trusted certificates, non-authoritative ''' pass for cert_pem in self.trusted_certs: cert = XY509cert(cert_pem, inform='PEM') # TODO: check encoding cert_report = (f"Subject: {cert.getSubject_str()}; " f"issuer: {cert.getIssuer_str()}; " f"not valid after: {cert.notAfter_str()}\n") self.aodsfh.save_trustedcerts_report(cert_report)
def checkCerts(self) -> None: """ validate that included signing and encryption certificates meet following conditions: * not expired AND * issued by a CA listed as issuer in the related trust store) AND * the x509subject's CN matches the hostname of the entityDescriptor """ for cert_pem in self._getCerts( 'IDP'): # certs in IDPSSODescriptor elements if cert_pem is None: continue cert = XY509cert(cert_pem) if not cert.isNotExpired(): raise CertExpiredError('Certificate is expired') x509storeContext = crypto.X509StoreContext( self.IDP_trustStore.x509store, cert.cert) try: x509storeContext.verify_certificate() except crypto.X509StoreContextError as e: raise CertInvalidError(('Certificate validation failed. ' + str(e) + ' ' + cert.getIssuer_str())) if cert.getSubject_str().find('/CN=' + self.get_entityid_hostname()) < 0: raise EdHostnameNotMatchingCertSubject( 'Hostname of entityID (%s) not matching CN in cert subject (%s)' % (self.get_entityid_hostname(), cert.getSubject_str())) for cert_pem in self._getCerts( 'SP'): # certs in SPSSODescriptor elements if cert_pem is None: continue cert = XY509cert(cert_pem) if not cert.isNotExpired(): raise CertExpiredError( f"Certificate is expired since {cert.notValidAfter()}; subject: {cert.getSubject_str}" ) x509storeContext = crypto.X509StoreContext( self.SP_trustStore.x509store, cert.cert) try: x509storeContext.verify_certificate() except crypto.X509StoreContextError as e: raise CertInvalidError(('Certificate validation failed. ' + str(e) + ' ' + cert.getIssuer_str())) logging.debug('Entity certificates valid for ' + self.ed.get_entityid())
def _load_certlist_from_certdir(self): if not self.pvzdconf.trustedcertsdir.is_dir(): raise ValidationError(f"Trusted Certs directory not found: {str(self.pvzdconf.trustedcertsdir)}") self.certs = set() for certfile in self.pvzdconf.trustedcertsdir.iterdir(): if certfile.suffix == '.pem': pem = XY509cert.pem_remove_rfc7468_delimiters( certfile.read_text(), optional_delimiter=True) pem_single_line = pem.replace('\n', '').strip() self.certs.add(pem_single_line) else: logging.debug(f"skipping file in certdir because extension != '.pem': {certfile}")
def cert2ed(cert_str, entityid, samlrole): cert_str_nodelimiters = XY509cert.pem_remove_rfc7468_delimiters( cert_str, optional_delimiter=True) if samlrole == 'IDP': entityDescriptor = """\ <md:EntityDescriptor entityID="{eid}" xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:pvzd="http://egov.gv.at/pvzd1.xsd" pvzd:pvptype="R-Profile"> <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <md:KeyDescriptor use="signing"> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> {pem} </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </md:KeyDescriptor> <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="{eid}/idp/unused"/> </md:IDPSSODescriptor> </md:EntityDescriptor>""".format(eid=entityid, pem=cert_str_nodelimiters) elif samlrole == 'SP': entityDescriptor = """\ <md:EntityDescriptor entityID="{eid}" xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:pvzd="http://egov.gv.at/pvzd1.xsd" pvzd:pvptype="R-Profile"> <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <md:KeyDescriptor use="signing"> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> {pem} </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </md:KeyDescriptor> <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="{eid}/acs/unused" index="0" isDefault="true"/> </md:SPSSODescriptor> </md:EntityDescriptor>""".format(eid=entityid, pem=cert_str_nodelimiters) else: raise EntityRoleNotSupportedError( f"Only IDP and SP entity roles implemented, but %s given {samlrole}" ) return entityDescriptor
def get_signing_certs(self, samlrole: str = 'IDP') -> [XY509cert]: x509certs = [] # if samlrole not in ('any', 'IDP', 'SP'): # raise InputValueError("samlrole must be on of 'any', 'IDP', 'SP'") if samlrole not in ('IDP', ): raise InputValueError("samlrole must be 'IDP'") idpssodesc = self.tree.xpath('//md:IDPSSODescriptor', namespaces={'md': XMLNS_MD}) if len(idpssodesc) > 0: keydescriptors = idpssodesc[0].findall(XMLNS_MD_PREFIX + 'KeyDescriptor') for kd in keydescriptors: if 'use' in kd.attrib and kd.attrib['use'] == 'encryption': pass else: # signing certs are those with use="signing" or have no use attribute for x509cert in kd.iter(XMLNS_DSIG_PREFIX + 'X509Certificate'): x509certs.append(XY509cert(x509cert.text.strip())) return x509certs
def save(self, *args, **kwargs): self.not_after = XY509cert(self.cert).notAfter_str() self.org_cn = self.gvouid_parent.gvouid.cn self.subject_cn = XY509cert(self.cert).getSubjectCN() super().save(*args, **kwargs)
def save(self, *args, **kwargs): xy509cert = XY509cert(self.cacert) self.subject_cn = xy509cert.getSubjectCN() super().save()
def save(self, *args, **kwargs): self.issuer_cn = XY509cert(self.cert).getIssuer_str() self.not_after = XY509cert(self.cert).notAfter_str() self.pubkey = XY509cert(self.cert).get_pubkey() self.subject_cn = XY509cert(self.cert).getSubject_str() super().save(*args, **kwargs)