NativeCrypto: throw exception on invalid DNS altname
When we receive an invalid DNS alt name (e.g., contains characters
outside of the ASCII printable range), we should throw an exception to
match the previous behavior. This is not validated this against the RI
since the tests currently don't work, but it brings the behavior back to
what it was previously.
Also amend the previous ASN.1 string check to use
ASN1_PRINTABLE_type(...) which actually scans the string to check its
contents. This is what was meant in the last patch.
Bug: 8398461
Change-Id: I260f045a2e144fb9ded7e1d3aa46592da8f63272
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
index e1038a6..b24ad0e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
@@ -28,6 +28,7 @@
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
@@ -409,7 +410,8 @@
public static native String[] get_X509_ext_oids(long x509ctx, int critical);
- public static native Object[][] get_X509_GENERAL_NAME_stack(long x509ctx, int type);
+ public static native Object[][] get_X509_GENERAL_NAME_stack(long x509ctx, int type)
+ throws CertificateParsingException;
public static native boolean[] get_X509_ex_kusage(long x509ctx);
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index 9991fc4..ce2e2ee 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -3825,12 +3825,17 @@
case GEN_EMAIL:
case GEN_DNS:
case GEN_URI: {
- // This must be an IA5String and must not contain NULLs.
- char* data = reinterpret_cast<char*>(ASN1_STRING_data(gen->d.ia5));
- if ((ASN1_STRING_type(gen->d.ia5) == V_ASN1_IA5STRING)
- && (static_cast<size_t>(ASN1_STRING_length(gen->d.ia5)) == strlen(data))) {
+ // This must not be a T61String and must not contain NULLs.
+ const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
+ ssize_t len = ASN1_STRING_length(gen->d.ia5);
+ if ((len == static_cast<ssize_t>(strlen(data)))
+ && (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
+ JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
return env->NewStringUTF(data);
} else {
+ jniThrowException(env, "java/security/cert/CertificateParsingException",
+ "Invalid dNSName encoding");
+ JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
return NULL;
}
}
@@ -3858,7 +3863,9 @@
JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen, strerror(errno));
}
}
- break;
+
+ /* Invalid IP encodings are pruned out without throwing an exception. */
+ return NULL;
}
case GEN_RID:
return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
@@ -3918,6 +3925,11 @@
for (int i = 0, j = 0; i < origCount; i++, j++) {
GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
+ if (env->ExceptionCheck()) {
+ JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
+ x509, type);
+ return NULL;
+ }
/*
* If it's NULL, we'll have to skip this, reduce the number of total