def _judge_name(self, certificate, name): judgements = SecurityJudgements() rdns = certificate.subject.get_all(OIDDB.RDNTypes.inverse("CN")) have_valid_cn = False if len(rdns) > 0: found_rdn = None for rdn in rdns: value = rdn.get_value(OIDDB.RDNTypes.inverse("CN")) if ValidationTools.validate_domainname_template_match( value.printable_value, name): found_rdn = rdn break if found_rdn is not None: if found_rdn.component_cnt == 1: judgements += SecurityJudgement( JudgementCode.CertUsage_Purpose_ServerCert_CN_Match, "Common name (CN) matches '%s'." % (name), commonness=Commonness.COMMON) else: judgements += SecurityJudgement( JudgementCode. CertUsage_Purpose_ServerCert_CN_MatchMultivalueRDN, "Common name (CN) matches '%s', but is part of a multi-valued RDN: %s" % (name, found_rdn.pretty_str), commonness=Commonness.HIGHLY_UNUSUAL) else: judgements += SecurityJudgement( JudgementCode.CertUsage_Purpose_ServerCert_CN_Mismatch, "No common name (CN) matches '%s'." % (name), commonness=Commonness.UNUSUAL) have_valid_san = False extension = certificate.extensions.get_first( OIDDB.X509Extensions.inverse("SubjectAlternativeName")) if extension is not None: for san_name in extension.get_all("dNSName"): if ValidationTools.validate_domainname_template_match( san_name.str_value, name): have_valid_san = True judgements += SecurityJudgement( JudgementCode.CertUsage_Purpose_ServerCert_SAN_Match, "Subject Alternative Name matches '%s'." % (name), commonness=Commonness.COMMON) break else: judgements += SecurityJudgement( JudgementCode.CertUsage_Purpose_ServerCert_SAN_Mismatch, "No Subject Alternative Name X.509 extension matches '%s'." % (name), commonness=Commonness.UNUSUAL) if (not have_valid_cn) and (not have_valid_san): judgements += SecurityJudgement( JudgementCode. CertUsage_Purpose_ServerCert_NameVerificationFailed, "Found neither valid common name (CN) nor valid subject alternative name (SAN).", commonness=Commonness.HIGHLY_UNUSUAL, verdict=Verdict.NO_SECURITY) return judgements
def test_domainname_template_no_match(self): self.assertFalse( ValidationTools.validate_domainname_template_match( "foo.com", "foo.de")) self.assertFalse( ValidationTools.validate_domainname_template_match( "*.com", "www.FOO.com")) self.assertFalse( ValidationTools.validate_domainname_template_match( "*.foo.com", "FOO.cOm")) self.assertFalse( ValidationTools.validate_domainname_template_match( "*blubb.foo.com", "wWw.FOO.cOm")) self.assertFalse( ValidationTools.validate_domainname_template_match( "blubb*.foo.com", "www.FOO.cOm")) self.assertFalse( ValidationTools.validate_domainname_template_match( "muh*blubb.foo.com", "mUh.FOO.cOm")) self.assertFalse( ValidationTools.validate_domainname_template_match( "muh*blubb.foo.com", "blubb.FOO.cOm")) self.assertFalse( ValidationTools.validate_domainname_template_match( "muh*blubb.foo.com", "abcblubb.FOO.cOm")) self.assertFalse( ValidationTools.validate_domainname_template_match( "muh.f*o.com", "mUh.web.cOm"))
def test_emails_invalid(self): self.assertFalse(ValidationTools.validate_email_address("")) self.assertFalse(ValidationTools.validate_email_address("@")) self.assertFalse(ValidationTools.validate_email_address("a")) self.assertFalse(ValidationTools.validate_email_address("abc@")) self.assertFalse(ValidationTools.validate_email_address("@abc")) self.assertFalse(ValidationTools.validate_email_address("[email protected]")) self.assertFalse(ValidationTools.validate_email_address("abc@abc.")) self.assertFalse(ValidationTools.validate_email_address("abc@ abc")) self.assertFalse(ValidationTools.validate_email_address("abc@ abc"))
def test_domainname_template_invalid(self): self.assertEqual( ValidationTools.validate_domainname_template("*foo*.foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("**.foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("f$oo.foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.InvalidCharacter ) self.assertEqual( ValidationTools.validate_domainname_template("f*$oo.foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.InvalidCharacter ) self.assertEqual( ValidationTools.validate_domainname_template("foo.*.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult. FullWildcardNotLeftmost) self.assertEqual( ValidationTools.validate_domainname_template("foo.co.uk.*")[0], ValidationTools.DomainnameTemplateValidationResult. FullWildcardNotLeftmost) self.assertEqual( ValidationTools.validate_domainname_template("foo*.co*.uk")[0], ValidationTools.DomainnameTemplateValidationResult. MoreThanOneWildcard) self.assertEqual( ValidationTools.validate_domainname_template("foo.xn--foo*.uk")[0], ValidationTools.DomainnameTemplateValidationResult. WildcardInInternationalDomain)
def test_emails_valid(self): self.assertTrue(ValidationTools.validate_email_address("*****@*****.**")) self.assertTrue(ValidationTools.validate_email_address("x@y")) self.assertTrue(ValidationTools.validate_email_address("[email protected]")) self.assertTrue(ValidationTools.validate_email_address("[email protected]")) self.assertTrue(ValidationTools.validate_email_address("[email protected]")) self.assertTrue( ValidationTools.validate_email_address("*****@*****.**")) self.assertTrue( ValidationTools.validate_email_address("*****@*****.**")) self.assertTrue( ValidationTools.validate_email_address("*****@*****.**"))
def _validate_rfc822Name(self): self._report("Enc_DER_Struct_GenName_Email_Unexpected", "contains unexpected email address \"%s\"." % (self._subject.str_value), commonness=Commonness.UNUSUAL) if not ValidationTools.validate_email_address(self._subject.str_value): self._report("Enc_DER_Struct_GenName_Email_Malformed", "contains invalid email address \"%s\"." % (self._subject.str_value), commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION)
def test_uri_invalid(self): self.assertFalse(ValidationTools.validate_uri("/foo/bar")) self.assertFalse(ValidationTools.validate_uri("moo.com/foobar")) self.assertFalse(ValidationTools.validate_uri("foo.de:80/jfisoud")) self.assertFalse(ValidationTools.validate_uri("://foo")) self.assertFalse(ValidationTools.validate_uri("://foo/")) self.assertFalse(ValidationTools.validate_uri("http:../example.com"))
def test_domains_valid(self): self.assertTrue(ValidationTools.validate_domainname("bar.de")) self.assertTrue(ValidationTools.validate_domainname("y")) self.assertTrue(ValidationTools.validate_domainname("d.y")) self.assertTrue(ValidationTools.validate_domainname("a.d.y")) self.assertTrue(ValidationTools.validate_domainname("a.d.y")) self.assertTrue(ValidationTools.validate_domainname("bar.co.uk"))
def _validate_uniformResourceIdentifier(self): self._report( "Enc_DER_Struct_GenName_URI_Unexpected", "contains unexpected URI \"%s\"." % (self._subject.str_value)) if not ValidationTools.validate_uri(str(self._subject.str_value)): self._report("Enc_DER_Struct_GenName_URI_Malformed", "contains invalid URI \"%s\"." % (str(self._subject.str_value)), commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) if self._validator.permissible_uri_schemes is not None: split_url = urllib.parse.urlsplit(self._subject.str_value) if split_url.scheme not in self._validator.permissible_uri_schemes: self._report( "Enc_DER_Struct_GenName_URI_UncommonURIScheme", "contains invalid URI scheme \"%s\" (permitted schemes are only %s)." % (str(self._subject.str_value), ", ".join( sorted(self._validator.permissible_uri_schemes))), commonness=Commonness.UNUSUAL)
def test_uri_valid(self): self.assertTrue(ValidationTools.validate_uri("http://a")) self.assertTrue(ValidationTools.validate_uri("http://a.a/")) self.assertTrue(ValidationTools.validate_uri("http://a/a")) self.assertTrue(ValidationTools.validate_uri("http://a/a/")) self.assertTrue(ValidationTools.validate_uri("http://a/a/?")) self.assertTrue(ValidationTools.validate_uri("http://a/a/?a")) self.assertTrue( ValidationTools.validate_uri( "http://de.wikipedia.org/wiki/Uniform_Resource_Identifier")) self.assertTrue( ValidationTools.validate_uri( "http://de.wikipedia.org/wiki/Uniform_Resource_Identifier/")) self.assertTrue( ValidationTools.validate_uri("ftp://ftp.is.co.za/rfc/rfc1808.txt")) self.assertTrue( ValidationTools.validate_uri( "file:///C:/Users/Benutzer/Desktop/Uniform%20Resource%20Identifier.html" )) self.assertTrue(ValidationTools.validate_uri("file:///etc/fstab")) self.assertTrue( ValidationTools.validate_uri("geo:48.33,14.122;u=22.5")) self.assertTrue( ValidationTools.validate_uri( "ldap://[2001:db8::7]/c=GB?objectClass?one")) self.assertTrue( ValidationTools.validate_uri("gopher://gopher.floodgap.com")) self.assertTrue( ValidationTools.validate_uri("mailto:[email protected]")) self.assertTrue( ValidationTools.validate_uri("sip:[email protected]")) self.assertTrue( ValidationTools.validate_uri( "news:comp.infosystems.www.servers.unix")) self.assertTrue( ValidationTools.validate_uri( "data:text/plain;charset=iso-8859-7,%be%fa%be")) self.assertTrue(ValidationTools.validate_uri("tel:+1-816-555-1212")) self.assertTrue( ValidationTools.validate_uri("telnet://192.0.2.16:80/")) self.assertTrue( ValidationTools.validate_uri( "urn:oasis:names:specification:docbook:dtd:xml:4.1.2")) self.assertTrue( ValidationTools.validate_uri("git://github.com/rails/rails.git")) self.assertTrue( ValidationTools.validate_uri( "crid://broadcaster.com/movies/BestActionMovieEver")) self.assertTrue( ValidationTools.validate_uri("http://aa.bbbb-c.dd/eeeeee"))
def test_domains_invalid(self): self.assertFalse(ValidationTools.validate_domainname("")) self.assertFalse(ValidationTools.validate_domainname(".")) self.assertFalse(ValidationTools.validate_domainname(".foo")) self.assertFalse(ValidationTools.validate_domainname("foo.")) self.assertFalse(ValidationTools.validate_domainname("foo bar"))
def test_domainname_template_match(self): self.assertTrue( ValidationTools.validate_domainname_template_match( "foo.com", "FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "foo.CoM", "FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "*.com", "FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "*.foo.com", "wWw.FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "*blubb.foo.com", "wWwblubb.FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "blubb*.foo.com", "bLubbmoo.FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "muh*blubb.foo.com", "mUhwWwblubb.FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "muh.f*o.com", "mUh.FOO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "muh.f*o.com", "mUh.FO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "muh.f*o.com", "mUh.FabcdefO.cOm")) self.assertTrue( ValidationTools.validate_domainname_template_match( "muh.fo*.com", "mUh.FOobar.cOm"))
def test_domainname_template_valid(self): self.assertEqual( ValidationTools.validate_domainname_template("bar.de")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("y")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("d.y")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("a.d.y")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("a.d.y")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("bar.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("*.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("foo*.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("*foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("foo.foo*.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("foo.*foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid) self.assertEqual( ValidationTools.validate_domainname_template("*.xn--foo.co.uk")[0], ValidationTools.DomainnameTemplateValidationResult.Valid)
def _validate_dNSName(self): self._report("Enc_DER_Struct_GenName_DNS_Unexpected", "contains unexpected domain name \"%s\"." % (self._subject.str_value), commonness=Commonness.UNUSUAL) if self._subject.str_value == " ": return self._report( "Enc_DER_Struct_GenName_DNS_OnlyWhitespace", "got invalid DNS name \" \" (space character).", commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) if self._validator.allow_dnsname_wildcard_matches: (result, label) = ValidationTools.validate_domainname_template( self._subject.str_value) if result != ValidationTools.DomainnameTemplateValidationResult.Valid: if result == ValidationTools.DomainnameTemplateValidationResult.InvalidCharacter: return self._report( "Enc_DER_Struct_GenName_DNS_Malformed", "has invalid domain name \"%s\", error at label \"%s\"." % (self._subject.str_value, label), commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) elif result == ValidationTools.DomainnameTemplateValidationResult.FullWildcardNotLeftmost: return self._report( "Enc_DER_Struct_GenName_DNS_Wildcard_NotLeftmost", "has invalid domain name \"%s\". Full-label wildcard appears not as leftmost element." % (self._subject.str_value), commonness=Commonness.UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) elif result == ValidationTools.DomainnameTemplateValidationResult.MoreThanOneWildcard: return self._report( "Enc_DER_Struct_GenName_DNS_Wildcard_MulitpleWildcards", "has invalid domain name \"%s\". More than one wildcard label present." % (self._subject.str_value), commonness=Commonness.UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) elif result == ValidationTools.DomainnameTemplateValidationResult.WildcardInInternationalDomain: return self._report( "Enc_DER_Struct_GenName_DNS_Wildcard_InternationalLabel", "has invalid domain name \"%s\". Wildcard in international domain label \"%s\"." % (self._subject.str_value, label), commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) else: raise NotImplementedError(result) if "*" in self._subject.str_value: # Wildcard match labels = self._subject.str_value.split(".") if len(labels) <= 2: self._report( "Enc_DER_Struct_GenName_DNS_Wildcard_BroadMatch", "has wildcard value \"%s\", which is an extremely broad domain match." % (self._subject.str_value), commonness=Commonness.HIGHLY_UNUSUAL) else: if "*" in self._subject.str_value: # Not permitted but wildcard present self._report( "Enc_DER_Struct_GenName_DNS_Wildcard_NotPermitted", "has wildcard value \"%s\", which is not permitted for this type." % (self._subject.str_value), commonness=Commonness.HIGHLY_UNUSUAL) if not "." in self._subject.str_value: self._report( "Enc_DER_Struct_GenName_DNS_SingleLabel", "contains only single label \"%s\", which is highly unusual." % (self._subject.str_value), commonness=Commonness.HIGHLY_UNUSUAL) validation_name = self._subject.str_value if self._validator.allow_dnsname_wildcard_matches: validation_name = validation_name.replace("*", "a") result = ValidationTools.validate_domainname(validation_name) if not result: self._report( "Enc_DER_Struct_GenName_DNS_Malformed", "has invalid domain name \"%s\" (wildcard matches %s)." % (self._subject.str_value, "permitted" if self._validator.allow_dnsname_wildcard_matches else "forbidden"), commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION)