Toshaan Bharvani
2 months ago
2 changed files with 240 additions and 1 deletions
@ -0,0 +1,233 @@
@@ -0,0 +1,233 @@
|
||||
diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c |
||||
index 1a18174995..a09414c972 100644 |
||||
--- a/crypto/x509/v3_utl.c |
||||
+++ b/crypto/x509/v3_utl.c |
||||
@@ -916,36 +916,64 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen, |
||||
ASN1_STRING *cstr; |
||||
|
||||
gen = sk_GENERAL_NAME_value(gens, i); |
||||
- if ((gen->type == GEN_OTHERNAME) && (check_type == GEN_EMAIL)) { |
||||
- if (OBJ_obj2nid(gen->d.otherName->type_id) == |
||||
- NID_id_on_SmtpUTF8Mailbox) { |
||||
- san_present = 1; |
||||
- |
||||
- /* |
||||
- * If it is not a UTF8String then that is unexpected and we |
||||
- * treat it as no match |
||||
- */ |
||||
- if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) { |
||||
- cstr = gen->d.otherName->value->value.utf8string; |
||||
- |
||||
- /* Positive on success, negative on error! */ |
||||
- if ((rv = do_check_string(cstr, 0, equal, flags, |
||||
- chk, chklen, peername)) != 0) |
||||
- break; |
||||
- } |
||||
- } else |
||||
+ switch (gen->type) { |
||||
+ default: |
||||
+ continue; |
||||
+ case GEN_OTHERNAME: |
||||
+ switch (OBJ_obj2nid(gen->d.otherName->type_id)) { |
||||
+ default: |
||||
continue; |
||||
- } else { |
||||
- if ((gen->type != check_type) && (gen->type != GEN_OTHERNAME)) |
||||
+ case NID_id_on_SmtpUTF8Mailbox: |
||||
+ /*- |
||||
+ * https://datatracker.ietf.org/doc/html/rfc8398#section-3 |
||||
+ * |
||||
+ * Due to name constraint compatibility reasons described |
||||
+ * in Section 6, SmtpUTF8Mailbox subjectAltName MUST NOT |
||||
+ * be used unless the local-part of the email address |
||||
+ * contains non-ASCII characters. When the local-part is |
||||
+ * ASCII, rfc822Name subjectAltName MUST be used instead |
||||
+ * of SmtpUTF8Mailbox. This is compatible with legacy |
||||
+ * software that supports only rfc822Name (and not |
||||
+ * SmtpUTF8Mailbox). [...] |
||||
+ * |
||||
+ * SmtpUTF8Mailbox is encoded as UTF8String. |
||||
+ * |
||||
+ * If it is not a UTF8String then that is unexpected, and |
||||
+ * we ignore the invalid SAN (neither set san_present nor |
||||
+ * consider it a candidate for equality). This does mean |
||||
+ * that the subject CN may be considered, as would be the |
||||
+ * case when the malformed SmtpUtf8Mailbox SAN is instead |
||||
+ * simply absent. |
||||
+ * |
||||
+ * When CN-ID matching is not desirable, applications can |
||||
+ * choose to turn it off, doing so is at this time a best |
||||
+ * practice. |
||||
+ */ |
||||
+ if (check_type != GEN_EMAIL |
||||
+ || gen->d.otherName->value->type != V_ASN1_UTF8STRING) |
||||
+ continue; |
||||
+ alt_type = 0; |
||||
+ cstr = gen->d.otherName->value->value.utf8string; |
||||
+ break; |
||||
+ } |
||||
+ break; |
||||
+ case GEN_EMAIL: |
||||
+ if (check_type != GEN_EMAIL) |
||||
continue; |
||||
- } |
||||
- san_present = 1; |
||||
- if (check_type == GEN_EMAIL) |
||||
cstr = gen->d.rfc822Name; |
||||
- else if (check_type == GEN_DNS) |
||||
+ break; |
||||
+ case GEN_DNS: |
||||
+ if (check_type != GEN_DNS) |
||||
+ continue; |
||||
cstr = gen->d.dNSName; |
||||
- else |
||||
+ break; |
||||
+ case GEN_IPADD: |
||||
+ if (check_type != GEN_IPADD) |
||||
+ continue; |
||||
cstr = gen->d.iPAddress; |
||||
+ break; |
||||
+ } |
||||
+ san_present = 1; |
||||
/* Positive on success, negative on error! */ |
||||
if ((rv = do_check_string(cstr, alt_type, equal, flags, |
||||
chk, chklen, peername)) != 0) |
||||
diff --git a/test/recipes/25-test_eai_data.t b/test/recipes/25-test_eai_data.t |
||||
index 522982ddfb..e18735d89a 100644 |
||||
--- a/test/recipes/25-test_eai_data.t |
||||
+++ b/test/recipes/25-test_eai_data.t |
||||
@@ -21,16 +21,18 @@ setup("test_eai_data"); |
||||
#./util/wrap.pl apps/openssl verify -nameopt utf8 -no_check_time -CAfile test/recipes/25-test_eai_data/utf8_chain.pem test/recipes/25-test_eai_data/ascii_leaf.pem |
||||
#./util/wrap.pl apps/openssl verify -nameopt utf8 -no_check_time -CAfile test/recipes/25-test_eai_data/ascii_chain.pem test/recipes/25-test_eai_data/utf8_leaf.pem |
||||
|
||||
-plan tests => 12; |
||||
+plan tests => 16; |
||||
|
||||
require_ok(srctop_file('test','recipes','tconversion.pl')); |
||||
my $folder = "test/recipes/25-test_eai_data"; |
||||
|
||||
my $ascii_pem = srctop_file($folder, "ascii_leaf.pem"); |
||||
my $utf8_pem = srctop_file($folder, "utf8_leaf.pem"); |
||||
+my $kdc_pem = srctop_file($folder, "kdc-cert.pem"); |
||||
|
||||
my $ascii_chain_pem = srctop_file($folder, "ascii_chain.pem"); |
||||
my $utf8_chain_pem = srctop_file($folder, "utf8_chain.pem"); |
||||
+my $kdc_chain_pem = srctop_file($folder, "kdc-root-cert.pem"); |
||||
|
||||
my $out; |
||||
my $outcnt = 0; |
||||
@@ -56,10 +58,18 @@ SKIP: { |
||||
|
||||
ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $ascii_chain_pem, $ascii_pem]))); |
||||
ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $utf8_chain_pem, $utf8_pem]))); |
||||
+ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $kdc_chain_pem, $kdc_pem]))); |
||||
|
||||
ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $ascii_chain_pem, $utf8_pem]))); |
||||
ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $utf8_chain_pem, $ascii_pem]))); |
||||
|
||||
+# Check an otherName does not get misparsed as an DNS name, (should trigger ASAN errors if violated). |
||||
+ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_hostname", 'mx1.example.com', "-CAfile", $kdc_chain_pem, $kdc_pem]))); |
||||
+# Check an otherName does not get misparsed as an email address, (should trigger ASAN errors if violated). |
||||
+ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_email", 'joe@example.com', "-CAfile", $kdc_chain_pem, $kdc_pem]))); |
||||
+# We expect SmtpUTF8Mailbox to be a UTF8 String, not an IA5String. |
||||
+ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_email", 'moe@example.com', "-CAfile", $kdc_chain_pem, $kdc_pem]))); |
||||
+ |
||||
#Check that we get the expected failure return code |
||||
with({ exit_checker => sub { return shift == 2; } }, |
||||
sub { |
||||
diff --git a/test/recipes/25-test_eai_data/kdc-cert.pem b/test/recipes/25-test_eai_data/kdc-cert.pem |
||||
new file mode 100644 |
||||
index 0000000000..e8a2c6f55d |
||||
--- /dev/null |
||||
+++ b/test/recipes/25-test_eai_data/kdc-cert.pem |
||||
@@ -0,0 +1,21 @@ |
||||
+-----BEGIN CERTIFICATE----- |
||||
+MIIDbDCCAlSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 |
||||
+MCAXDTI0MDYyMDA2MTQxNVoYDzIxMjQwNjIwMDYxNDE1WjAXMRUwEwYDVQQDDAxU |
||||
+RVNULkVYQU1QTEUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6wfP+ |
||||
+6go79dkpo/dGLMlPZ7Gw/Q6gUYrCWZWUEgEeRVHCrqOlgUEyA+PcWas/XDPUxXry |
||||
+BQlJHLvlqamAQn8gs4QPBARFYWKNiTVGyaRkgNA1N5gqyZdrP9UE+ZJmdqxRAAe8 |
||||
+vvpGZWSgevPhLUiSCFYDiD0Rtji2Hm3rGUrReQFBQDEw2pNGwz9zIaxUs08kQZcx |
||||
+Yzyiplz5Oau+R/6sAgUwDlrD9xOlUxx/tA/MSDIfkK8qioU11uUZtO5VjkNQy/bT |
||||
+7zQMmXxWgm2MIgOs1u4YN7YGOtgqHE9v9iPHHfgrkbQDtVDGQsa8AQEhkUDSCtW9 |
||||
+3VFAKx6dGNXYzFwfAgMBAAGjgcgwgcUwHQYDVR0OBBYEFFR5tZycW19DmtbL4Zqj |
||||
+te1c2vZLMAkGA1UdIwQCMAAwCQYDVR0TBAIwADCBjQYDVR0RBIGFMIGCoD8GBisG |
||||
+AQUCAqA1MDOgDhsMVEVTVC5FWEFNUExFoSEwH6ADAgEBoRgwFhsGa3JidGd0GwxU |
||||
+RVNULkVYQU1QTEWgHQYIKwYBBQUHCAmgERYPbW9lQGV4YW1wbGUuY29tgQ9qb2VA |
||||
+ZXhhbXBsZS5jb22CD214MS5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA |
||||
+T0xzVtVpRtaOzIhgzw7XQUdzWD5UEGSJJ1cBCOmKUWwDLTAouCYLFB4TbEE7MMUb |
||||
+iuMy60bjmVtvfJIXorGUgSadRe5RWJ5DamJWvPA0Q9x7blnEcXqEF+9Td+ypevgU |
||||
+UYHFmg83OYwxOsFXZ5cRuXMk3WCsDHQIBi6D1L6oDDZ2pfArs5mqm3thQKVlqyl1 |
||||
+El3XRYEdqAz/5eCOFNfwxF0ALxjxVr/Z50StUZU8I7Zfev6+kHhyrR7dqzYJImv9 |
||||
+0fTCOBEMjIETDsrA70OxAMu4V16nrWZdJdvzblS2qrt97Omkj+2kiPAJFB76RpwI |
||||
+oDQ9fKfUOAmUFth2/R/eGA== |
||||
+-----END CERTIFICATE----- |
||||
diff --git a/test/recipes/25-test_eai_data/kdc-root-cert.pem b/test/recipes/25-test_eai_data/kdc-root-cert.pem |
||||
new file mode 100644 |
||||
index 0000000000..a74c96bf31 |
||||
--- /dev/null |
||||
+++ b/test/recipes/25-test_eai_data/kdc-root-cert.pem |
||||
@@ -0,0 +1,16 @@ |
||||
+-----BEGIN CERTIFICATE----- |
||||
+MIICnDCCAYQCCQCBswYcrlZSHjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARS |
||||
+b290MCAXDTI0MDYyMDA2MTQxNVoYDzIxMjQwNjIwMDYxNDE1WjAPMQ0wCwYDVQQD |
||||
+DARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqRj8S4kBbIUj |
||||
+61kZfi6nE35Q38U140+qt4uAiwAhKumfVHlBM0zQ98WFt5zMHIBQwIb3yjc2zj+0 |
||||
+qzUnQfwm1r/RfcMmBPEti9Ge+aEMSsds2gMXziOFM8wd2aAFPy7UVE0XpEWofsRK |
||||
+MGi61MKVdPSbGIxBwY9VW38/7D/wf1HtJe7y0xpuecR7GB2XAs+qST59NjuF+7wS |
||||
+dLM8Hb3TATgeYbXXWsRJgwz+SPzExg5WmLnU+7y4brZ32dHtdSmkRVSgSlaIf7Xj |
||||
+3Tc6Zi7I+W/JYk7hy1zUexVdWCak4PHcoWrXe0gNNN/t8VfLfMExt5z/HIylXnU7 |
||||
+pGUyqZlTGQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAHpLF1UCRy7b6Hk0rLokxI |
||||
+lgwiH9BU9mktigAGASvkbllpt+YbUbWnuYAvpHBGiP1qZtfX2r96UrSJaGO9BEzT |
||||
+Gp9ThnSjoj4Srul0+s/NArU22irFLmDzbalgevAmm9gMGkdqkiIm/mXbwrPj0ncl |
||||
+KGicevXryVpvaP62eZ8cc3C4p97frMmXxRX8sTdQpD/gRI7prdEILRSKveqT+AEW |
||||
+7rFGM5AOevb4U8ddop8A3D/kX0wcCAIBF6jCNk3uEJ57jVcagL04kPnVfdRiedTS |
||||
+vfq1DRNcD29d1H/9u0fHdSn1/+8Ep3X+afQ3C6//5NvOEaXcIGO4QSwkprQydfv8 |
||||
+-----END CERTIFICATE----- |
||||
diff --git a/test/recipes/25-test_eai_data/kdc.sh b/test/recipes/25-test_eai_data/kdc.sh |
||||
new file mode 100755 |
||||
index 0000000000..7a8dbc719f |
||||
--- /dev/null |
||||
+++ b/test/recipes/25-test_eai_data/kdc.sh |
||||
@@ -0,0 +1,41 @@ |
||||
+#! /usr/bin/env bash |
||||
+ |
||||
+# Create a root CA, signing a leaf cert with a KDC principal otherName SAN, and |
||||
+# also a non-UTF8 smtpUtf8Mailbox SAN followed by an rfc822Name SAN and a DNS |
||||
+# name SAN. In the vulnerable EAI code, the KDC principal `otherName` should |
||||
+# trigger ASAN errors in DNS name checks, while the non-UTF8 `smtpUtf8Mailbox` |
||||
+# should likewise lead to ASAN issues with email name checks. |
||||
+ |
||||
+rm -f root-key.pem root-cert.pem |
||||
+openssl req -nodes -new -newkey rsa:2048 -keyout kdc-root-key.pem \ |
||||
+ -x509 -subj /CN=Root -days 36524 -out kdc-root-cert.pem |
||||
+ |
||||
+exts=$( |
||||
+ printf "%s\n%s\n%s\n%s = " \ |
||||
+ "subjectKeyIdentifier = hash" \ |
||||
+ "authorityKeyIdentifier = keyid" \ |
||||
+ "basicConstraints = CA:false" \ |
||||
+ "subjectAltName" |
||||
+ printf "%s, " "otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name" |
||||
+ printf "%s, " "otherName:1.3.6.1.5.5.7.8.9;IA5:moe@example.com" |
||||
+ printf "%s, " "email:joe@example.com" |
||||
+ printf "%s\n" "DNS:mx1.example.com" |
||||
+ printf "[kdc_princ_name]\n" |
||||
+ printf "realm = EXP:0, GeneralString:TEST.EXAMPLE\n" |
||||
+ printf "principal_name = EXP:1, SEQUENCE:kdc_principal_seq\n" |
||||
+ printf "[kdc_principal_seq]\n" |
||||
+ printf "name_type = EXP:0, INTEGER:1\n" |
||||
+ printf "name_string = EXP:1, SEQUENCE:kdc_principal_components\n" |
||||
+ printf "[kdc_principal_components]\n" |
||||
+ printf "princ1 = GeneralString:krbtgt\n" |
||||
+ printf "princ2 = GeneralString:TEST.EXAMPLE\n" |
||||
+ ) |
||||
+ |
||||
+printf "%s\n" "$exts" |
||||
+ |
||||
+openssl req -nodes -new -newkey rsa:2048 -keyout kdc-key.pem \ |
||||
+ -subj "/CN=TEST.EXAMPLE" | |
||||
+ openssl x509 -req -out kdc-cert.pem \ |
||||
+ -CA "kdc-root-cert.pem" -CAkey "kdc-root-key.pem" \ |
||||
+ -set_serial 2 -days 36524 \ |
||||
+ -extfile <(printf "%s\n" "$exts") |
Loading…
Reference in new issue