TLSTM: Connection using Agent certificate subject Alternative name

Hello Frank ,

I am working on connecting to SNMP4j agent with TLS connection, where I am able to successfully connect using Subject DN or by passing Agent certificate finger print in CertifiedTarget , but not able to connect using subjectAlternativeName

1. Subject Alternative Name: (NOK)

Code Snippet :


it fails as the fingerprint is returned as null in checkServerTrusted method of TlsTrustManager
fingerprint = ((CertifiedIdentity)tmStateReference.getTarget()).getServerFingerprint();

2. Subject DN (OK)

Code Snippet :

Can please provide your suggestion w.r.t connecting using the SubjectAlternativeName(SAN)?


Which SNMP4J version are you using?

An obvious error in your call to addSecurityNameMapping is that the second to last parameter (the “data”) is the empty OctetString. Instead of that it should contain the DN (e.g. “localhost”).

Hello Frank ,

I am using the latest SNMP4j -3.5.1
Have tried the below mentioned input parameters, however the error remains the same .

  1.   securityCallback.addSecurityNameMapping(new OctetString(), SecurityNameMapping.CertMappingType.SANDNSName, new OctetString("localhost"), null);
  2.   securityCallback.addSecurityNameMapping(new OctetString(), SecurityNameMapping.CertMappingType.SANDNSName, new OctetString("localhost"), new OctetString("agntcrt"));
  3.   securityCallback.addSecurityNameMapping(new OctetString(), SecurityNameMapping.CertMappingType.SANDNSName, new OctetString("DNS:localhost"), null)

Using JRE 9 , tried in JRE 16 as well but the error remains the same.


Ok, I have to try to reproduce that. My unit test is working, but there might be some difference.

I ran the wrong unit test so that I tested the server verification instead of the client side verification.
To get the client side verification working with the certified target, you need to add the DNS hostname pattern you want to accept as server in the “identity” parameter for the certified target:

new CertifiedTarget(new OctetString("localhost"),...)

Hope this helps. This unexpected difference for DNS SAN mapping is necessary because you might want to use different patterns for different targets but still use the same security callback.

Hi Frank ,

It would be helpful if you can share the sample code which is working for you and configuration which I may have to make it work .

Regards ,

This is the whole unit test which works as part of TLSTMTest:

public void sendMessageWithPDUDnsCertPathVerification() throws Exception {
    final boolean[] messageReceived = { false, false, false };
    CertifiedTarget<TlsAddress> certifiedTarget = new CertifiedTarget<>(new TlsAddress(tlstmCR.getListenAddress()),
            new OctetString("localhost"), new OctetString(), CLIENT_FINGER_PRINT);
    final CommandResponder commandResponder = new CommandResponder() {

        public synchronized <A extends Address> void processPdu(CommandResponderEvent<A> event) {
            messageReceived[event.getPDU().getVariableBindings().size()-2] = true;
            if (messageReceived[2]) {

    DefaultTlsTmSecurityCallback securityCallback = new DefaultTlsTmSecurityCallback();
    securityCallback.addAcceptedIssuerDN(", OU=Unit-Test, O=AGENTPP, L=Stuttgart, ST=Baden-Wuerttemberg, C=DE");
            new OctetString(),
            new OctetString("localhost"), new OctetString("localhost"));
    Snmp snmpAgent = new Snmp(tlstmCR);
    ScopedPDU scopedPDU = new ScopedPDU();
    UnsignedInteger32 value1 = new UnsignedInteger32(91589156l);
    OctetString value2 = new OctetString("peWadfnagnergrDFAAHAräöß394");
    scopedPDU.add(new VariableBinding(SnmpConstants.snmp4jStatsRequestRetries, value1));
    scopedPDU.add(new VariableBinding(SnmpConstants.snmpTrapCommunity, value2));
    OctetString localEngineID = new OctetString(MPv3.createLocalEngineID());
    Snmp snmp = new Snmp(tlstmCS);
            new SecurityModels().addSecurityModel(new TSM()));
            new SecurityModels().addSecurityModel(new TSM(localEngineID, false)));
    snmpAgent.setLocalEngine(localEngineID.getValue(), 1, 1);
    synchronized (commandResponder) {
        snmp.send(scopedPDU, certifiedTarget);
        ScopedPDU scopedPDU1 = (ScopedPDU) scopedPDU.clone();
        scopedPDU1.add(new VariableBinding(SnmpConstants.sysServices, new Integer32(42)));
        snmp.send(scopedPDU1, certifiedTarget);
        ScopedPDU scopedPDU2 = (ScopedPDU) scopedPDU.clone();
        scopedPDU1.add(new VariableBinding(SnmpConstants.sysContact, new OctetString("me")));
        snmp.send(scopedPDU2, certifiedTarget);

Hello Frank ,

Thank you for sharing the code snippet . Even in my case it works fine when I have addAcceptedIssuerDN and addSecurityNameMapping
But it does not work while having only the SAN or addSecurityNameMapping.

It is possible to have only the addSecurityNameMapping and not have addAcceptedIssuerDN and make it work ?

If possible can you please share the initialization of below variables which are in the code snippet ?
tlstmCR and tlstmCS

I will have a look. The TLSTM RFC rules to accept a certificate are hard to memorize…

Are you using the TLSTMExtendedTrustManager as TLSTM does by default?
For me the test works even if accepted issuer DN and accepted subject DN are not set (= empty) in the SecurityCallback. But from my code inspection, this works only, if the TLSTMExtendedTrustManager is actually used.

Hope this helps.

Hi Frank ,

Thank you for the reply.

I have not used TLSTMExtendedTrustManager explicitly it should be the default TLSTMTrustManager which is getting used.

It would be helpful if you could share the code for initialization of below variables which are in the code snippet (TLSTM: Connection using Agent certificate subject Alternative name - #8 by AGENTPP)?