From 9d1f162fa5a01c06b9357e91e80e02af4804759f Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 16 Aug 2024 13:20:38 +0300 Subject: [PATCH 1/3] SNMP v3: fix unsupported authentication and protocol versions --- .../transport/snmp/SnmpTransportContext.java | 4 ++-- .../snmp/service/SnmpAuthService.java | 19 +++++++++++++------ .../snmp/service/SnmpTransportService.java | 1 + 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/SnmpTransportContext.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/SnmpTransportContext.java index 6e30b06a2c..ffd2b7e33c 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/SnmpTransportContext.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/SnmpTransportContext.java @@ -127,7 +127,7 @@ public class SnmpTransportContext extends TransportContext { .build(); registerSessionMsgListener(sessionContext); } catch (Exception e) { - log.error("Failed to establish session for SNMP device {}: {}", device.getId(), e.toString()); + log.error("Failed to establish session for SNMP device {}", device.getId(), e); transportService.errorEvent(device.getTenantId(), device.getId(), "sessionEstablishing", e); return; } @@ -166,7 +166,7 @@ public class SnmpTransportContext extends TransportContext { log.trace("Configuration of the device {} was not updated", device); } } catch (Exception e) { - log.error("Failed to update session for SNMP device {}: {}", sessionContext.getDeviceId(), e.getMessage()); + log.error("Failed to update session for SNMP device {}", sessionContext.getDeviceId(), e); transportService.lifecycleEvent(sessionContext.getTenantId(), sessionContext.getDeviceId(), ComponentLifecycleEvent.UPDATED, false, e); destroyDeviceSession(sessionContext); } diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java index b5f9cac09b..aca736c3ed 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java @@ -72,11 +72,18 @@ public class SnmpAuthService { OctetString engineId = new OctetString(deviceTransportConfig.getEngineId()); OID authenticationProtocol = new OID(deviceTransportConfig.getAuthenticationProtocol().getOid()); + byte[] authenticationPassphrase = SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, + new OctetString(deviceTransportConfig.getAuthenticationPassphrase()), engineId.getValue()); + if (authenticationPassphrase == null) { + throw new UnsupportedOperationException("Authentication protocol " + deviceTransportConfig.getAuthenticationProtocol() + " is not supported"); + } + OID privacyProtocol = new OID(deviceTransportConfig.getPrivacyProtocol().getOid()); - OctetString authenticationPassphrase = new OctetString(deviceTransportConfig.getAuthenticationPassphrase()); - authenticationPassphrase = new OctetString(SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, authenticationPassphrase, engineId.getValue())); - OctetString privacyPassphrase = new OctetString(deviceTransportConfig.getPrivacyPassphrase()); - privacyPassphrase = new OctetString(SecurityProtocols.getInstance().passwordToKey(privacyProtocol, authenticationProtocol, privacyPassphrase, engineId.getValue())); + byte[] privacyPassphrase = SecurityProtocols.getInstance().passwordToKey(privacyProtocol, + authenticationProtocol, new OctetString(deviceTransportConfig.getPrivacyPassphrase()), engineId.getValue()); + if (privacyPassphrase == null) { + throw new UnsupportedOperationException("Privacy protocol " + deviceTransportConfig.getPrivacyProtocol() + " is not supported"); + } USM usm = snmpTransportService.getSnmp().getUSM(); if (usm.hasUser(engineId, securityName)) { @@ -84,8 +91,8 @@ public class SnmpAuthService { } usm.addLocalizedUser( engineId.getValue(), username, - authenticationProtocol, authenticationPassphrase.getValue(), - privacyProtocol, privacyPassphrase.getValue() + authenticationProtocol, authenticationPassphrase, + privacyProtocol, privacyPassphrase ); UserTarget userTarget = new UserTarget(); diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java index 3a1d440d20..26008e2c82 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java @@ -148,6 +148,7 @@ public class SnmpTransportService implements TbTransportService, CommandResponde snmp.addNotificationListener(transportMapping, transportMapping.getListenAddress(), this); snmp.listen(); + SecurityProtocols.getInstance().addPredefinedProtocolSet(SecurityProtocols.SecurityProtocolSet.maxCompatibility); USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); SecurityModels.getInstance().addSecurityModel(usm); } From 6f307cdede48b4aa5d01db8a47033a7372867b8a Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Mon, 19 Aug 2024 11:27:20 +0300 Subject: [PATCH 2/3] SNMP v3: fix engine id --- .../server/transport/snmp/service/SnmpAuthService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java index aca736c3ed..bcc3240570 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java @@ -69,7 +69,7 @@ public class SnmpAuthService { case V3: OctetString username = new OctetString(deviceTransportConfig.getUsername()); OctetString securityName = new OctetString(deviceTransportConfig.getSecurityName()); - OctetString engineId = new OctetString(deviceTransportConfig.getEngineId()); + OctetString engineId = OctetString.fromString(deviceTransportConfig.getEngineId(), 16); OID authenticationProtocol = new OID(deviceTransportConfig.getAuthenticationProtocol().getOid()); byte[] authenticationPassphrase = SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, From 5e47e1691305d9df3f5c4aef50d7551e6d09ce3f Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Mon, 26 Aug 2024 16:12:27 +0300 Subject: [PATCH 3/3] Fix unknown security name --- .../snmp/service/SnmpAuthService.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java index bcc3240570..13f50621ad 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java @@ -24,6 +24,7 @@ import org.snmp4j.security.SecurityLevel; import org.snmp4j.security.SecurityModel; import org.snmp4j.security.SecurityProtocols; import org.snmp4j.security.USM; +import org.snmp4j.security.UsmUser; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; @@ -72,28 +73,23 @@ public class SnmpAuthService { OctetString engineId = OctetString.fromString(deviceTransportConfig.getEngineId(), 16); OID authenticationProtocol = new OID(deviceTransportConfig.getAuthenticationProtocol().getOid()); - byte[] authenticationPassphrase = SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, - new OctetString(deviceTransportConfig.getAuthenticationPassphrase()), engineId.getValue()); - if (authenticationPassphrase == null) { - throw new UnsupportedOperationException("Authentication protocol " + deviceTransportConfig.getAuthenticationProtocol() + " is not supported"); - } + OctetString authenticationPassphrase = Optional.ofNullable(SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, + new OctetString(deviceTransportConfig.getAuthenticationPassphrase()), engineId.getValue())) + .map(OctetString::new) + .orElseThrow(() -> new UnsupportedOperationException("Authentication protocol " + deviceTransportConfig.getAuthenticationProtocol() + " is not supported")); OID privacyProtocol = new OID(deviceTransportConfig.getPrivacyProtocol().getOid()); - byte[] privacyPassphrase = SecurityProtocols.getInstance().passwordToKey(privacyProtocol, - authenticationProtocol, new OctetString(deviceTransportConfig.getPrivacyPassphrase()), engineId.getValue()); - if (privacyPassphrase == null) { - throw new UnsupportedOperationException("Privacy protocol " + deviceTransportConfig.getPrivacyProtocol() + " is not supported"); - } + OctetString privacyPassphrase = Optional.ofNullable(SecurityProtocols.getInstance().passwordToKey(privacyProtocol, + authenticationProtocol, new OctetString(deviceTransportConfig.getPrivacyPassphrase()), engineId.getValue())) + .map(OctetString::new) + .orElseThrow(() -> new UnsupportedOperationException("Privacy protocol " + deviceTransportConfig.getPrivacyProtocol() + " is not supported")); USM usm = snmpTransportService.getSnmp().getUSM(); if (usm.hasUser(engineId, securityName)) { usm.removeAllUsers(username, engineId); } - usm.addLocalizedUser( - engineId.getValue(), username, - authenticationProtocol, authenticationPassphrase, - privacyProtocol, privacyPassphrase - ); + UsmUser usmUser = new UsmUser(username, authenticationProtocol, authenticationPassphrase, privacyProtocol, privacyPassphrase, engineId); + usm.addUser(username, engineId, usmUser); UserTarget userTarget = new UserTarget(); userTarget.setSecurityName(securityName);