diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java index bae7522c78..babf385bc8 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java @@ -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; - } - } } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/AbstractSslCredentials.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/AbstractSslCredentials.java index 01b7242805..3170aea9a2 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/AbstractSslCredentials.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/AbstractSslCredentials.java @@ -61,7 +61,7 @@ public abstract class AbstractSslCredentials implements SslCredentials { this.keyPasswordArray = keyPassword.toCharArray(); } this.keyStore = this.loadKeyStore(trustsOnly, this.keyPasswordArray); - Set trustedCerts = getTrustedCerts(this.keyStore); + Set 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 getTrustedCerts(KeyStore ks) { + private static Set getTrustedCerts(KeyStore ks, boolean trustsOnly) { Set set = new HashSet<>(); try { for (Enumeration 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); } - - }