8178714: PKIX validator nameConstraints check failing after change 8175940
Reviewed-by: mullan, ahgross
--- a/src/java.base/share/classes/sun/security/x509/DNSName.java Tue Mar 28 12:10:20 2017 -0700
+++ b/src/java.base/share/classes/sun/security/x509/DNSName.java Thu May 18 08:52:50 2017 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -194,45 +194,31 @@
*/
public int constrains(GeneralNameInterface inputName) throws UnsupportedOperationException {
int constraintType;
- if (inputName == null) {
- return NAME_DIFF_TYPE;
- }
- String inName;
- switch (inputName.getType()) {
- case NAME_DNS:
- inName = ((DNSName)inputName).getName();
- break;
- case NAME_DIRECTORY:
- try {
- inName = ((X500Name) inputName).getCommonName();
- if (inName == null) {
- return NAME_DIFF_TYPE;
- }
- } catch (IOException ioe) {
- return NAME_DIFF_TYPE;
- }
- break;
- default:
- return NAME_DIFF_TYPE;
- }
- inName = inName.toLowerCase(Locale.ENGLISH);
- String thisName = name.toLowerCase(Locale.ENGLISH);
- if (inName.equals(thisName))
- constraintType = NAME_MATCH;
- else if (thisName.endsWith(inName)) {
- int inNdx = thisName.lastIndexOf(inName);
- if (thisName.charAt(inNdx-1) == '.' )
- constraintType = NAME_WIDENS;
- else
+ if (inputName == null)
+ constraintType = NAME_DIFF_TYPE;
+ else if (inputName.getType() != NAME_DNS)
+ constraintType = NAME_DIFF_TYPE;
+ else {
+ String inName =
+ (((DNSName)inputName).getName()).toLowerCase(Locale.ENGLISH);
+ String thisName = name.toLowerCase(Locale.ENGLISH);
+ if (inName.equals(thisName))
+ constraintType = NAME_MATCH;
+ else if (thisName.endsWith(inName)) {
+ int inNdx = thisName.lastIndexOf(inName);
+ if (thisName.charAt(inNdx-1) == '.' )
+ constraintType = NAME_WIDENS;
+ else
+ constraintType = NAME_SAME_TYPE;
+ } else if (inName.endsWith(thisName)) {
+ int ndx = inName.lastIndexOf(thisName);
+ if (inName.charAt(ndx-1) == '.' )
+ constraintType = NAME_NARROWS;
+ else
+ constraintType = NAME_SAME_TYPE;
+ } else {
constraintType = NAME_SAME_TYPE;
- } else if (inName.endsWith(thisName)) {
- int ndx = inName.lastIndexOf(thisName);
- if (inName.charAt(ndx-1) == '.' )
- constraintType = NAME_NARROWS;
- else
- constraintType = NAME_SAME_TYPE;
- } else {
- constraintType = NAME_SAME_TYPE;
+ }
}
return constraintType;
}
--- a/src/java.base/share/classes/sun/security/x509/NameConstraintsExtension.java Tue Mar 28 12:10:20 2017 -0700
+++ b/src/java.base/share/classes/sun/security/x509/NameConstraintsExtension.java Thu May 18 08:52:50 2017 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
import javax.security.auth.x500.X500Principal;
+import sun.net.util.IPAddressUtil;
import sun.security.util.*;
import sun.security.pkcs.PKCS9Attribute;
@@ -440,6 +441,7 @@
X500Principal subjectPrincipal = cert.getSubjectX500Principal();
X500Name subject = X500Name.asX500Name(subjectPrincipal);
+ // Check subject as an X500Name
if (subject.isEmpty() == false) {
if (verify(subject) == false) {
return false;
@@ -465,12 +467,51 @@
"certificate: " + ce.getMessage());
}
- // If there are no subjectAlternativeNames, perform the special-case
- // check where if the subjectName contains any EMAILADDRESS
- // attributes, they must be checked against RFC822 constraints.
- // If that passes, we're fine.
if (altNames == null) {
- return verifyRFC822SpecialCase(subject);
+ altNames = new GeneralNames();
+
+ // RFC 5280 4.2.1.10:
+ // When constraints are imposed on the rfc822Name name form,
+ // but the certificate does not include a subject alternative name,
+ // the rfc822Name constraint MUST be applied to the attribute of
+ // type emailAddress in the subject distinguished name.
+ for (AVA ava : subject.allAvas()) {
+ ObjectIdentifier attrOID = ava.getObjectIdentifier();
+ if (attrOID.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) {
+ String attrValue = ava.getValueString();
+ if (attrValue != null) {
+ try {
+ altNames.add(new GeneralName(
+ new RFC822Name(attrValue)));
+ } catch (IOException ioe) {
+ continue;
+ }
+ }
+ }
+ }
+ }
+
+ // If there is no IPAddressName or DNSName in subjectAlternativeNames,
+ // see if the last CN inside subjectName can be used instead.
+ DerValue derValue = subject.findMostSpecificAttribute
+ (X500Name.commonName_oid);
+ String cn = derValue == null ? null : derValue.getAsString();
+
+ if (cn != null) {
+ try {
+ if (IPAddressUtil.isIPv4LiteralAddress(cn) ||
+ IPAddressUtil.isIPv6LiteralAddress(cn)) {
+ if (!hasNameType(altNames, GeneralNameInterface.NAME_IP)) {
+ altNames.add(new GeneralName(new IPAddressName(cn)));
+ }
+ } else {
+ if (!hasNameType(altNames, GeneralNameInterface.NAME_DNS)) {
+ altNames.add(new GeneralName(new DNSName(cn)));
+ }
+ }
+ } catch (IOException ioe) {
+ // OK, cn is neither IP nor DNS
+ }
}
// verify each subjectAltName
@@ -485,6 +526,15 @@
return true;
}
+ private static boolean hasNameType(GeneralNames names, int type) {
+ for (GeneralName name : names.names()) {
+ if (name.getType() == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* check whether a name conforms to these NameConstraints.
* This involves verifying that the name is consistent with the
@@ -567,37 +617,6 @@
}
/**
- * Perform the RFC 822 special case check. We have a certificate
- * that does not contain any subject alternative names. Check that
- * any EMAILADDRESS attributes in its subject name conform to these
- * NameConstraints.
- *
- * @param subject the certificate's subject name
- * @return true if certificate verifies successfully
- * @throws IOException on error
- */
- public boolean verifyRFC822SpecialCase(X500Name subject) throws IOException {
- for (AVA ava : subject.allAvas()) {
- ObjectIdentifier attrOID = ava.getObjectIdentifier();
- if (attrOID.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) {
- String attrValue = ava.getValueString();
- if (attrValue != null) {
- RFC822Name emailName;
- try {
- emailName = new RFC822Name(attrValue);
- } catch (IOException ioe) {
- continue;
- }
- if (!verify(emailName)) {
- return(false);
- }
- }
- }
- }
- return true;
- }
-
- /**
* Clone all objects that may be modified during certificate validation.
*/
public Object clone() {