lwm2m validate trust certs

This commit is contained in:
nickAS21 2022-01-05 16:28:37 +02:00
parent c655b58977
commit ec602248c0
2 changed files with 47 additions and 29 deletions

View File

@ -50,13 +50,22 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore;
import javax.annotation.PostConstruct;
import javax.security.auth.x500.X500Principal;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer.CLIENT;
@ -119,8 +128,8 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
TbLwM2MSecurityInfo securityInfo = null;
// verify if trust
if (config.getTrustSslCredentials().getTrustedCertificates().length > 0) {
if (verifyIssuer(cert, config.getTrustSslCredentials().getTrustedCertificates()) != null) {
if (config.getTrustSslCredentials() != null && config.getTrustSslCredentials().getTrustedCertificates().length > 0) {
if (verifyTrust(cert, config.getTrustSslCredentials().getTrustedCertificates()) != null) {
String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN");
securityInfo = StringUtils.isNotEmpty(endpoint) ? securityInfoValidator.getEndpointSecurityInfoByCredentialsId(endpoint, CLIENT) : null;
}
@ -193,31 +202,26 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
}
private X509Certificate verifyIssuer(X509Certificate certificate, X509Certificate[] certificates) {
String issuerCN = config.getTrustSslCredentials().getValueFromSubjectNameByKey(certificate.getIssuerX500Principal().getName(), "CN");
if (!StringUtils.isBlank(issuerCN)) {
private X509Certificate verifyTrust(X509Certificate certificate, X509Certificate[] certificates) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPath cp = cf.generateCertPath(Arrays.asList(new X509Certificate[]{certificate}));
for (int index = 0; index < certificates.length; ++index) {
X509Certificate trust = certificates[index];
String trustCN = config.getTrustSslCredentials().getValueFromSubjectNameByKey(trust.getSubjectX500Principal().getName(), "CN");
if (!StringUtils.isBlank(trustCN) && issuerCN.length() >= trustCN.length() && issuerCN.substring(issuerCN.length()-trustCN.length()).equals(trustCN)) {
if (verifyCertificate(certificate)) {
return certificate;
}
X509Certificate caCert = certificates[index];
try {
TrustAnchor trustAnchor = new TrustAnchor(caCert, null);
CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
PKIXParameters pkixParams = new PKIXParameters(
Collections.singleton(trustAnchor));
pkixParams.setRevocationEnabled(false);
if (cpv.validate(cp, pkixParams) != null) return certificate;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | CertPathValidatorException e) {
log.trace("[{}]. [{}]", certificate.getSubjectDN(), e.getMessage());
}
}
} catch (CertificateException e) {
log.trace("[{}] certPath not valid. [{}]", certificate.getSubjectDN(), e.getMessage());
}
return null;
}
private static boolean verifyCertificate(X509Certificate certificate) {
try {
// date
certificate.checkValidity();
// Validate X509.
SecurityUtil.certificate.decode(certificate.getEncoded());
return true;
} catch (Exception e) {
return false;
}
}
}

View File

@ -61,7 +61,7 @@ public abstract class AbstractSslCredentials implements SslCredentials {
this.keyPasswordArray = keyPassword.toCharArray();
}
this.keyStore = this.loadKeyStore(trustsOnly, this.keyPasswordArray);
Set<X509Certificate> trustedCerts = getTrustedCerts(this.keyStore);
Set<X509Certificate> trustedCerts = getTrustedCerts(this.keyStore, trustsOnly);
this.trusts = trustedCerts.toArray(new X509Certificate[0]);
if (!trustsOnly) {
PrivateKeyEntry privateKeyEntry = null;
@ -179,7 +179,7 @@ public abstract class AbstractSslCredentials implements SslCredentials {
return entry;
}
private static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
private static Set<X509Certificate> getTrustedCerts(KeyStore ks, boolean trustsOnly) {
Set<X509Certificate> set = new HashSet<>();
try {
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
@ -187,19 +187,33 @@ public abstract class AbstractSslCredentials implements SslCredentials {
if (ks.isCertificateEntry(alias)) {
Certificate cert = ks.getCertificate(alias);
if (cert instanceof X509Certificate) {
set.add((X509Certificate)cert);
if (trustsOnly) {
// is CA certificate
if (((X509Certificate) cert).getBasicConstraints()>=0) {
set.add((X509Certificate) cert);
}
} else {
set.add((X509Certificate) cert);
}
}
} else if (ks.isKeyEntry(alias)) {
Certificate[] certs = ks.getCertificateChain(alias);
if ((certs != null) && (certs.length > 0) &&
(certs[0] instanceof X509Certificate)) {
set.add((X509Certificate)certs[0]);
if (trustsOnly) {
for (Certificate cert : certs) {
// is CA certificate
if (((X509Certificate) cert).getBasicConstraints()>=0) {
set.add((X509Certificate) cert);
}
}
} else {
set.add((X509Certificate)certs[0]);
}
}
}
}
} catch (KeyStoreException ignored) {}
return Collections.unmodifiableSet(set);
}
}