Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug2229930-crlCertValid-leaf-only #4554

Merged
merged 1 commit into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.netscape.cmscore.apps.CMSEngine;
import com.netscape.cmscore.apps.EngineConfig;
import com.netscape.cmscore.base.ConfigStorage;
import com.netscape.cmscore.cert.CertUtils;
import com.netscape.ocsp.OCSPAuthority;

@WebListener
Expand Down Expand Up @@ -149,9 +150,13 @@ public boolean isRevoked(X509Certificate[] certificates) {
}

for (X509Certificate cert: certificates) {
// validateConnCertWithCRL only handles leaf certs
if (CertUtils.isCACert(cert))
continue;
Comment on lines +154 to +155
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there ever be a case where the leaf cert is also a CA cert? If that's the case, the leaf cert will not be checked.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it also guaranteed that all non-leaf certs are CA certs? If that's not guaranteed, the loop might pick the wrong cert to check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we just want to check the leaf cert without touching the non-leaf certs at all, we probably can do something like this:

try {
    CertificateChain certChain = new CertificateChain(certificates);
    certChain.sort();
    certificates = certChain.getChain();

    X509Certificate leafCert = certificates[certificates.length - 1];
    return !crlCertValid(crlStore, leafCert, null);

} catch (Exception e) {
    throw new RuntimeException("Unable to check cert revocation: " + e.getMessage(), e);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, I didn't realize there were comments before I clicked merge, so I'm replying after the fact. sorry about it. So, to answer your questions. The crl cert validation is only for validating peer certs. 1. in the pki setup, we never use a ca or self-signed cert for SSL connections, either a client cert, or a server cert. 2. yes all non-leaf certs are supposed to be ca certs, hence forming a chain. 3. Yes your proposal of using CertificateChain to sort is a very good idea. I actually copied a part of this code from JssSubsystem isCACert(). How about we create a separate ticket to combine the two isCACert() and make the improvement at the same time? I'll leave it as it for now, since Pritam has already tested it. Thanks!


if(!crlCertValid(crlStore, cert, null)) {
return true;
}
} else break;
}
return false;

Expand Down
38 changes: 38 additions & 0 deletions base/server/src/main/java/com/netscape/cmscore/cert/CertUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.BasicConstraintsExtension;
import org.mozilla.jss.netscape.security.x509.CertificateExtensions;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.X500Name;
Expand Down Expand Up @@ -1339,6 +1340,43 @@ public static void addCTv1PoisonExt(X509CertInfo certinfo)
certinfo.set(X509CertInfo.EXTENSIONS, exts);
}

public static boolean isCACert(X509Certificate cert) {
String method = "CertUtils.isCACert: ";
try {
X509CertImpl impl = new X509CertImpl(cert.getEncoded());
X509CertInfo certinfo = (X509CertInfo) impl.get(
X509CertImpl.NAME + "." + X509CertImpl.INFO);
if (certinfo == null)
return false;
else {
CertificateExtensions exts = (CertificateExtensions) certinfo.get(X509CertInfo.EXTENSIONS);

if (exts == null)
return false;
else {
try {
BasicConstraintsExtension ext = (BasicConstraintsExtension) exts
.get(BasicConstraintsExtension.NAME);

if (ext == null)
return false;
else {
Boolean bool = (Boolean) ext.get(BasicConstraintsExtension.IS_CA);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can bool be null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question. Boolean by default is null, however, BasicConstraintsExtension has the following defined: // Private data members
private boolean ca = false;


return bool.booleanValue();
}
} catch (IOException ee) {
return false;
}
}
}
} catch (Exception e) {
logger.warn(method + CMS.getLogMessage("CMSCORE_SECURITY_IS_CA_CERT", e.toString()), e);
return false;
//throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED"));
}
}

/*
* for debugging
*/
Expand Down
Loading