org.snmp4j.transport.tls.PropertiesTlsTmSecurityCallback Maven / Gradle / Ivy
/*_############################################################################
_##
_## SNMP4J - PropertiesTlsTmSecurityCallback.java
_##
_## Copyright (C) 2003-2024 Frank Fock (SNMP4J.org)
_##
_## Licensed under the Apache License, Version 2.0 (the "License");
_## you may not use this file except in compliance with the License.
_## You may obtain a copy of the License at
_##
_## http://www.apache.org/licenses/LICENSE-2.0
_##
_## Unless required by applicable law or agreed to in writing, software
_## distributed under the License is distributed on an "AS IS" BASIS,
_## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
_## See the License for the specific language governing permissions and
_## limitations under the License.
_##
_##########################################################################*/
package org.snmp4j.transport.tls;
import org.snmp4j.log.LogAdapter;
import org.snmp4j.log.LogFactory;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.OctetString;
import org.snmp4j.util.SnmpConfigurator;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Properties;
/**
* The {@code PropertiesTlsTmSecurityCallback} resolves the
* {@code tmSecurityName} for incoming requests by using the
* (system) properties
* {@code org.snmp4j.arg.securityName}
* {@code org.snmp4j.arg.tlsLocalID}
* {@code org.snmp4j.arg.tlsTrustCA}
* {@code org.snmp4j.arg.tlsPeerID}
*
* @author Frank Fock
* @since 2.0
* @version 3.3.0
*/
public class PropertiesTlsTmSecurityCallback implements TlsTmSecurityCallback {
private static final LogAdapter LOGGER = LogFactory.getLogger(PropertiesTlsTmSecurityCallback.class);
private final boolean serverMode;
private final Properties properties;
public PropertiesTlsTmSecurityCallback(boolean serverMode) {
this(System.getProperties(), serverMode);
}
public PropertiesTlsTmSecurityCallback(Properties properties, boolean serverMode) {
this.serverMode = serverMode;
if (properties == null) {
throw new NullPointerException();
}
this.properties = properties;
}
@Override
public OctetString getSecurityName(X509Certificate[] peerCertificateChain) {
String securityName = properties.getProperty(SnmpConfigurator.P_SECURITY_NAME, null);
if (securityName != null) {
return new OctetString(securityName);
}
return null;
}
@Override
public boolean isClientCertificateAccepted(X509Certificate peerEndCertificate) throws CertificateException {
String accepted = properties.getProperty(SnmpConfigurator.P_TLS_LOCAL_ID, "");
if (serverMode) {
accepted = properties.getProperty(SnmpConfigurator.P_TLS_PEER_ID, "");
}
if (peerEndCertificate != null && peerEndCertificate.getSubjectX500Principal().getName().equals(accepted)) {
return true;
}
else if (accepted.length() == 0) {
return false;
}
String errmsg = "Certificate "+peerEndCertificate+" rejected because subject DN does not match "+accepted;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(errmsg);
}
throw new CertificateException(errmsg);
}
@Override
public boolean isServerCertificateAccepted(X509Certificate[] peerCertificateChain) throws CertificateException {
if (peerCertificateChain == null || peerCertificateChain.length == 0) {
throw new CertificateException("Server certificate chain is empty");
}
String fingerprint = properties.getProperty(SnmpConfigurator.P_TLS_CERT_FINGERPRINT, "");
if (fingerprint.length() > 0) {
OctetString acceptedFingerprint = OctetString.fromHexString(fingerprint);
int accepted = -1;
for (X509Certificate cert : peerCertificateChain) {
OctetString certFingerprint = TLSTMUtil.getFingerprint(cert);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Matching server fingerprint " + certFingerprint + " against accepted " + fingerprint);
}
if ((certFingerprint != null) && (certFingerprint.equals(acceptedFingerprint))) {
accepted = 1;
break;
}
else {
accepted = 0;
}
}
if (accepted <= 0) {
throw new CertificateException("Server certificate chain "+ Arrays.asList(peerCertificateChain)+
" does not match accepted fingerprint "+acceptedFingerprint);
}
}
String acceptedPeer = properties.getProperty(SnmpConfigurator.P_TLS_PEER_ID, "");
if (serverMode) {
acceptedPeer = properties.getProperty(SnmpConfigurator.P_TLS_LOCAL_ID, "");
}
String subject = peerCertificateChain[0].getSubjectX500Principal().getName();
if (subject.equals(acceptedPeer)) {
return true;
} else if (acceptedPeer.length() > 0) {
throw new CertificateException("Certificate subject '" + subject +
"' does not match accepted peer '" + acceptedPeer + "'");
}
String acceptedCA = properties.getProperty(SnmpConfigurator.P_TLS_TRUST_CA, "");
if (acceptedCA.length() == 0) {
return false;
}
for (int i = 1; i < peerCertificateChain.length; i++) {
String ca = peerCertificateChain[i].getIssuerX500Principal().getName();
if (ca.equals(acceptedCA)) {
return true;
} else {
LOGGER.debug("Certification authority '" + ca + "' does not match accepted CA '" + acceptedCA + "'");
}
}
throw new CertificateException("Certification authorities for certificate chain " +
Arrays.asList(peerCertificateChain) + " does not match accepted CA '" + acceptedCA + "'");
}
@Override
public boolean isAcceptedIssuer(X509Certificate issuerCertificate) throws CertificateException {
String acceptedCA = properties.getProperty(SnmpConfigurator.P_TLS_TRUST_CA, "");
if (acceptedCA.length() == 0) {
return false;
}
if (issuerCertificate != null && issuerCertificate.getIssuerX500Principal().getName().equals(acceptedCA)) {
return true;
}
throw new CertificateException("Issuer certificate "+issuerCertificate+
" does not have accepted DN: "+acceptedCA);
}
@Override
public String getLocalCertificateAlias(Address targetAddress) {
return properties.getProperty(SnmpConfigurator.P_TLS_LOCAL_ID);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy