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.annotation.PostConstruct;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.cert.CertPath; import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import static org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer.CLIENT; import static org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer.CLIENT;
@ -119,8 +128,8 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
TbLwM2MSecurityInfo securityInfo = null; TbLwM2MSecurityInfo securityInfo = null;
// verify if trust // verify if trust
if (config.getTrustSslCredentials().getTrustedCertificates().length > 0) { if (config.getTrustSslCredentials() != null && config.getTrustSslCredentials().getTrustedCertificates().length > 0) {
if (verifyIssuer(cert, config.getTrustSslCredentials().getTrustedCertificates()) != null) { if (verifyTrust(cert, config.getTrustSslCredentials().getTrustedCertificates()) != null) {
String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN"); String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN");
securityInfo = StringUtils.isNotEmpty(endpoint) ? securityInfoValidator.getEndpointSecurityInfoByCredentialsId(endpoint, CLIENT) : null; 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) { private X509Certificate verifyTrust(X509Certificate certificate, X509Certificate[] certificates) {
String issuerCN = config.getTrustSslCredentials().getValueFromSubjectNameByKey(certificate.getIssuerX500Principal().getName(), "CN"); try {
if (!StringUtils.isBlank(issuerCN)) { CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPath cp = cf.generateCertPath(Arrays.asList(new X509Certificate[]{certificate}));
for (int index = 0; index < certificates.length; ++index) { for (int index = 0; index < certificates.length; ++index) {
X509Certificate trust = certificates[index]; X509Certificate caCert = certificates[index];
String trustCN = config.getTrustSslCredentials().getValueFromSubjectNameByKey(trust.getSubjectX500Principal().getName(), "CN"); try {
if (!StringUtils.isBlank(trustCN) && issuerCN.length() >= trustCN.length() && issuerCN.substring(issuerCN.length()-trustCN.length()).equals(trustCN)) { TrustAnchor trustAnchor = new TrustAnchor(caCert, null);
if (verifyCertificate(certificate)) { CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
return certificate; 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; 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.keyPasswordArray = keyPassword.toCharArray();
} }
this.keyStore = this.loadKeyStore(trustsOnly, this.keyPasswordArray); 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]); this.trusts = trustedCerts.toArray(new X509Certificate[0]);
if (!trustsOnly) { if (!trustsOnly) {
PrivateKeyEntry privateKeyEntry = null; PrivateKeyEntry privateKeyEntry = null;
@ -179,7 +179,7 @@ public abstract class AbstractSslCredentials implements SslCredentials {
return entry; return entry;
} }
private static Set<X509Certificate> getTrustedCerts(KeyStore ks) { private static Set<X509Certificate> getTrustedCerts(KeyStore ks, boolean trustsOnly) {
Set<X509Certificate> set = new HashSet<>(); Set<X509Certificate> set = new HashSet<>();
try { try {
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) { for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
@ -187,19 +187,33 @@ public abstract class AbstractSslCredentials implements SslCredentials {
if (ks.isCertificateEntry(alias)) { if (ks.isCertificateEntry(alias)) {
Certificate cert = ks.getCertificate(alias); Certificate cert = ks.getCertificate(alias);
if (cert instanceof X509Certificate) { 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)) { } else if (ks.isKeyEntry(alias)) {
Certificate[] certs = ks.getCertificateChain(alias); Certificate[] certs = ks.getCertificateChain(alias);
if ((certs != null) && (certs.length > 0) && if ((certs != null) && (certs.length > 0) &&
(certs[0] instanceof X509Certificate)) { (certs[0] instanceof X509Certificate)) {
if (trustsOnly) {
for (Certificate cert : certs) {
// is CA certificate
if (((X509Certificate) cert).getBasicConstraints()>=0) {
set.add((X509Certificate) cert);
}
}
} else {
set.add((X509Certificate)certs[0]); set.add((X509Certificate)certs[0]);
} }
} }
} }
}
} catch (KeyStoreException ignored) {} } catch (KeyStoreException ignored) {}
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }