SNMP get response contains wrong community string

Hi,

My snmpCommunity table looks like this:

SNMP-COMMUNITY-MIB::snmpCommunityTable
index  Name     SecurityName  ContextEngineID  ContextName  TransportTag  StorageType  Status
comr   public   comRead       <local_eid>      ""           ""            nonVolatile  active
comw   private  comWrite      <local_eid>      ""           ""            nonVolatile  active

If I query the agent with community name public, the response will have a community name of “comRead” instead of public. For community private the response will have a community of “comWrite”.
This is with SNMP++ v3.5.2 and Agent++ v4.6.1.

Thanks in advance

Holger

Hi Holger,

This is indeed a bug. I working on a fix.

Best regards,
Frank

The bug has been introduced in AGENT++ 4.5.3. A fix has been implemented but needs to be tested.

Thanks for fixing it. If you have a patch I’d be happy to help testing.

Happy New Year :slight_smile:
Do you know when the next release with a fix for this will be available?
Or would it be possible to get a patch?

Best Regards,
Holger

Hi Holger,
I am testing it currently and expect the new version within the next 14 days.
It took a lot of time to automate testing. The advantage is that MIB Explorer users will get soon a cool new feature to test complex scenarios easily as well.
Best regards
Frank

1 Like

Testing of the fix has been successful completed now.
The new release 4.6.2 will be available for download by mid of this week latest.

1 Like

Thanks for the update

SNMP++ 3.6.0 and AGENT++ 3.7.0 are now available for download from the agentpp.com site.
The new AgentX++ version will be released next week too.

Thanks for the new release. Trying to test it but failing to compile it. Running this on Ubuntu 22.04:

./configure
make

And get the following compile error:

libtool: compile:  g++ -DHAVE_CONFIG_H -I. -I.. -I/home/repositories/agent++/snmp++-3.6.0/include -pthread -g -O2 -pthread -MT asn1.lo -MD -MP -MF .deps/asn1.Tpo -c asn1.cpp  -fPIC -DPIC -o .libs/asn1.o
In file included from /home/repositories/agent++/snmp++-3.6.0/include/snmp_pp/asn1.h:34,
                 from asn1.cpp:54:
/home/repositories/agent++/snmp++-3.6.0/include/snmp_pp/target.h: In destructor 'virtual Snmp_pp::UTarget::~UTarget()':
/home/repositories/agent++/snmp++-3.6.0/include/snmp_pp/target.h:517:11: error: 'coexistence_security_name' was not declared in this scope; did you mean 'get_security_name'?
  517 |       if (coexistence_security_name) {
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~
      |           get_security_name
/home/repositories/agent++/snmp++-3.6.0/include/snmp_pp/target.h:518:18: error: type '<type error>' argument given to 'delete', expected pointer
  518 |           delete coexistence_security_name;
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [Makefile:582: asn1.lo] Error 1

Best regards,
Holger

Have you really used the required SNMP++ 3.6.0?
I am going to check it again with the download file…
The new member is defined in the header files of SNMP++ v3.6.0
You need to run:

autoreconf -i
./configure
make

Hi Frank,
Yes, this is SNMP++ v3.6.0. The problem is that the build process didn’t find the OpenSSL libs, so resorted to build without SNMPv3 support. Once I pointed it at the crypto libs it did build successful.
But this means building SNMP++ v3.6.0 without SNMPv3 support is broken. To recreate use:
./configure --disable-snmpv3

Ok, I will fix that, although using SNMP++ without v3 is almost useless :wink:.

1 Like

Hi finally had some time to look at this again.
The fix for the community string in the response didn’t quite work. The problem is now the following:
get_v3_info(security_name, context_engine_id, context_name, transport_tag);
replaces the community string in security_name with the security name. So
set_coexistence_security_name(security_name);
must get called before get_v3_info().

The following patch against agent++ v4.7.0 fixes this:

--- a/src/request.cpp
+++ b/src/request.cpp
@@ -1257,6 +1257,9 @@ namespace Agentpp {
             } else {
                 snmpCommunityEntry *communityEntry = snmpCommunityEntry::get_instance(mib);
                 if (communityEntry) {
+                    // keep copy of community string for proxy request and any internal request processing
+                    target.set_coexistence_security_name(security_name);
+
                     OctetStr transport_tag;
                     bool found = communityEntry->
                             get_v3_info(security_name, context_engine_id,
@@ -1286,8 +1289,6 @@ namespace Agentpp {
                                                           oidSnmpInBadCommunityNames);
                         return 0;
                     }
-                    // use coexistence security name for proxy request and any internal request processing
-                    target.set_coexistence_security_name(security_name);
 
                     pdu.set_context_engine_id(context_engine_id);
                     pdu.set_context_name(context_name);

I currently still have problems getting the proxy forwarder agent to work and will continue to investigate.

Thanks,

Holger

Hi Holger,

What problem should this fix patch, exactly? In which situations, is the 3.7.0 code doing it wrong?

As the name of the property in the Target object suggests, that property should store the security-name returned by the coexistence info. Thus, it does not make sense, to set it before the coexistence info has been fetched.

Thanks in advance,
Frank

Hi Frank,

I am still trying to fix the problem that the response PDU contains the securityName instead of the communityName. This is difficult to prove with your examples as the securityName and communityName are both ‘public’.

The following patch adds a communityName ‘private’ with a securityName comWrite to the proxy_forwarder example agent:

--- a/examples/proxy_forwarder/src/agent.cpp
+++ b/examples/proxy_forwarder/src/agent.cpp
@@ -356,6 +356,19 @@ int main(int argc, char* argv[]) {
     init(*mib, engineId);
     snmp_community_mib::add_public();
 
+    // Add write community 'private'
+    Oidx ind = Oidx::from_string("comw", FALSE);
+    MibTableRow* r = snmpCommunityEntry::instance->add_row(ind);
+    snmpCommunityEntry::instance->set_row(r,
+                                          OctetStr("private"),             // CommunityName
+                                          OctetStr("comWrite"),            // SecurityName
+                                          v3MP::I->get_local_engine_id(),  // ContextEngineID
+                                          OctetStr(""),                    // ContextName
+                                          OctetStr("access"),              // TransportTag
+                                          storageType_nonVolatile,         // StorageType
+                                          rowActive);                      // RowStatus
+
+
     ProxyForwarder* proxy = new ProxyForwarder(mib, "", ProxyForwarder::ALL);
     mib->register_proxy(proxy);
 
@@ -381,6 +394,10 @@ int main(int argc, char* argv[]) {
             "v1v2group", storageType_nonVolatile);
     vacm->addNewGroup(SNMP_SECURITY_MODEL_V1, "public",
             "v1v2group", storageType_nonVolatile);
+    vacm->addNewGroup(SNMP_SECURITY_MODEL_V2, "comWrite",
+            "v1v2group", storageType_nonVolatile);
+    vacm->addNewGroup(SNMP_SECURITY_MODEL_V1, "comWrite",
+            "v1v2group", storageType_nonVolatile);
     vacm->addNewGroup(SNMP_SECURITY_MODEL_USM, "initial",
             "initial", storageType_nonVolatile);
     vacm->addNewGroup(SNMP_SECURITY_MODEL_USM, "unsecureUser",

After applying the patch the snmpCommunityTable will look like this:

index   Name      SecurityName ContextEngineID                                        ContextName TransportTag StorageType Status 
'comw'  "private" comWrite     "80 00 13 70 05 75 62 75 6E 74 75 32 32 30 34 27  B1 "             access       nonVolatile active 
'proxy1'"proxy1"  pubProxy1    "80 00 13 70 05 75 62 75 6E 74 75 32 32 30 34 12  5D "             access       nonVolatile active 
'public'"public"  public       "80 00 13 70 05 75 62 75 6E 74 75 32 32 30 34 27  B1 "             access       nonVolatile active 

If you now start the proxy_forwarder and do a snmpget using the community ‘private’ and capture the packets you’ll get the following:

tcpdump -i lo -n udp port 4700 -T snmp
IP 127.0.0.1.52872 > 127.0.0.1.4700:  C="private" GetRequest(28)  .1.3.6.1.2.1.1.1.0
IP 127.0.0.1.4700 > 127.0.0.1.52872:  C="comWrite" GetResponse(128)  .1.3.6.1.2.1.1.1.0="AGENT++v4.7.0 Proxy Forwarder - Use 'MD5' as SNMPv3 user and 'MD5UserAuthPassword' as authentication"

Note how the response contains the comWrite instead of private as community.

Best regards,

Holger
PS: Currently the forum only allows to attach picture formats. Wouldn’t it be useful if we could upload patch files and source files as well?

I wonder why my tests with the buggy fix worked and your tests with the incorrect fix as well (at least somehow).

The real fix necessary is in SNMP++ v3.6.1:

   void set_coexistence_security_name(const OctetStr& oct) {
       if (coexistence_security_name) {
             delete coexistence_security_name;
       }
-      coexistence_security_name = new OctetStr(oct);
+      coexistence_security_name = new OctetStr(security_name);
       security_name = oct;
   };

I will need to test it again before it will be released :roll_eyes:

Hi Frank,

Unfortunately that patch still didn’t work for me. But the patch below does fix the community in the response PDU for me:

--- a/include/snmp_pp/target.h
+++ b/include/snmp_pp/target.h
@@ -623,7 +623,6 @@ class DLLOPT UTarget: public SnmpTarget
             delete coexistence_security_name;
       }
       coexistence_security_name = new OctetStr(oct);
-      security_name = oct;
   };
 
   /**

UTarget::security_name already contains the community name when set_coexistence_security_name() gets called. So only UTarget::coexistence_security_name needs to get updated with the actual security name.

There is a remaining issue though. The proxy forwarder won’t forward SNMPv2 packets anymore and instead returns a report with 1.3.6.1.2.1.11.32 (snmpProxyDrops) incrementing. I’ll try to explain it a bit better in a later post, with an example how to recreate that issue.

Had you undone your previous patch in AGENT++ before doing the last test? That would be required!

The idea of my fix is to use the security name from coexistence for internal processing - including proxy - and then restore the external security name (= community for v1/2c) just before sending the response.
I have the feeling you are trying a different approach, right?

Hi Frank,

Yes, the previous patch was undone. The only patches I applied to the snmp++ v3.6.1 code was your latest patch, and the only patch I applied to the agent++ v4.7.0 was my patch to add the private community to the proxy_forwarder agent to be able to prove that it is fixed. Unfortunately this still had the wrong community in the response PDU.
I wouldn’t say I am trying a different approach, just trying to get your approach to work.
Looking at set_coexistence_security_name() it is trying to set two members variables of UTarget:

  • security_name
  • coexistence_security_name

I assume one of these should contain the security name, and the other one the community name. Which variable should be which isn’t clear from the naming though. So I just tried it the other way round from what your patch was doing.

Your patch copies the community name from security_name into coexistence_security_name and the security name (passed in by oct) into security_name. So after a call to your variant of set_coexistence_security_name() you get:

  • UTarget::security_name => security name
  • UTarget::coexistence_security_name => community name

My patch to snmp++ just copies the security name (passed in by oct) into coexistence_security_name and doesn’t change security_name, which already contains the community name. So after a call to my variant of set_coexistence_security_name() you get:

  • UTarget::security_name => community name
  • UTarget::coexistence_security_name => security name

Note: you can’t really debug this with the public community created by snmp_community_mib::add_public() because it sets the community name and the security name both to “public”, so the bug won’t be visible.