fixed memory leak in SNMP trap receiver; SNMP PDU parser refactored and optimized
authorVictor Kirhenshtein <victor@netxms.org>
Fri, 14 Jul 2017 18:28:36 +0000 (21:28 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Fri, 14 Jul 2017 18:28:36 +0000 (21:28 +0300)
14 files changed:
include/nms_util.h
include/nxsnmp.h
src/agent/subagents/ecs/ecs.cpp
src/agent/subagents/ping/Makefile.am
src/libnetxms/hash.cpp
src/libnetxms/sha1.cpp
src/libnetxms/sha1.h
src/server/core/agent.cpp
src/server/core/dcobject.cpp
src/snmp/libnxsnmp/ber.cpp
src/snmp/libnxsnmp/libnxsnmp.h
src/snmp/libnxsnmp/pdu.cpp
src/snmp/libnxsnmp/transport.cpp
src/snmp/libnxsnmp/variable.cpp

index de09022..43aacc5 100644 (file)
@@ -2076,14 +2076,27 @@ BYTE LIBNETXMS_EXPORTABLE *LoadFileA(const char *pszFileName, UINT32 *pdwFileSiz
 #endif
 
 UINT32 LIBNETXMS_EXPORTABLE CalculateCRC32(const unsigned char *data, UINT32 size, UINT32 dwCRC);
-void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const unsigned char *data, size_t nbytes, unsigned char *hash);
-void LIBNETXMS_EXPORTABLE MD5HashForPattern(const unsigned char *data, size_t patternSize, size_t fullSize, BYTE *hash);
-void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(unsigned char *data, size_t nbytes, unsigned char *hash);
-void LIBNETXMS_EXPORTABLE SHA1HashForPattern(unsigned char *data, size_t patternSize, size_t fullSize, unsigned char *hash);
-void LIBNETXMS_EXPORTABLE CalculateSHA256Hash(const unsigned char *data, size_t len, unsigned char *hash);
+BOOL LIBNETXMS_EXPORTABLE CalculateFileCRC32(const TCHAR *pszFileName, UINT32 *pResult);
+
+typedef unsigned char MD5_STATE[128];
+
+void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const BYTE *data, size_t nbytes, BYTE *hash);
+void LIBNETXMS_EXPORTABLE MD5HashForPattern(const BYTE *data, size_t patternSize, size_t fullSize, BYTE *hash);
 BOOL LIBNETXMS_EXPORTABLE CalculateFileMD5Hash(const TCHAR *pszFileName, BYTE *pHash);
+void LIBNETXMS_EXPORTABLE MD5Init(MD5_STATE *state);
+void LIBNETXMS_EXPORTABLE MD5Update(MD5_STATE *state, const BYTE *data, size_t size);
+void LIBNETXMS_EXPORTABLE MD5Finish(MD5_STATE *state, BYTE *hash);
+
+typedef unsigned char SHA1_STATE[128];
+
+void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(const BYTE *data, size_t nbytes, BYTE *hash);
+void LIBNETXMS_EXPORTABLE SHA1HashForPattern(const BYTE *data, size_t patternSize, size_t fullSize, BYTE *hash);
 BOOL LIBNETXMS_EXPORTABLE CalculateFileSHA1Hash(const TCHAR *pszFileName, BYTE *pHash);
-BOOL LIBNETXMS_EXPORTABLE CalculateFileCRC32(const TCHAR *pszFileName, UINT32 *pResult);
+void LIBNETXMS_EXPORTABLE SHA1Init(SHA1_STATE *state);
+void LIBNETXMS_EXPORTABLE SHA1Update(SHA1_STATE *state, const BYTE *data, size_t size);
+void LIBNETXMS_EXPORTABLE SHA1Finish(SHA1_STATE *state, BYTE *hash);
+
+void LIBNETXMS_EXPORTABLE CalculateSHA256Hash(const BYTE *data, size_t len, BYTE *hash);
 
 void LIBNETXMS_EXPORTABLE GenerateRandomBytes(BYTE *buffer, size_t size);
 
index 3244866..4b6b0da 100644 (file)
@@ -415,7 +415,7 @@ public:
    SNMP_Variable(const SNMP_Variable *src);
    ~SNMP_Variable();
 
-   bool parse(BYTE *data, size_t varLength);
+   bool parse(const BYTE *data, size_t varLength);
    size_t encode(BYTE *buffer, size_t bufferSize);
 
    const SNMP_ObjectId& getName() const { return m_name; }
@@ -558,22 +558,23 @@ private:
        SNMP_Engine m_authoritativeEngine;
        int m_securityModel;
        BYTE m_signature[12];
-
-   bool parseVariable(BYTE *pData, size_t varLength);
-   bool parseVarBinds(BYTE *pData, size_t pduLength);
-   bool parsePdu(BYTE *pdu, size_t pduLength);
-   bool parseTrapPDU(BYTE *pData, size_t pduLength);
-   bool parseTrap2PDU(BYTE *pData, size_t pduLength);
-   bool parsePduContent(BYTE *pData, size_t pduLength);
-   bool parseV3Header(BYTE *pData, size_t pduLength);
-   bool parseV3SecurityUsm(BYTE *pData, size_t pduLength);
-   bool parseV3ScopedPdu(BYTE *pData, size_t pduLength);
-       bool validateSignedMessage(BYTE *msg, size_t msgLen, SNMP_SecurityContext *securityContext);
+       size_t m_signatureOffset;
+
+   bool parseVariable(const BYTE *pData, size_t varLength);
+   bool parseVarBinds(const BYTE *pData, size_t pduLength);
+   bool parsePdu(const BYTE *pdu, size_t pduLength);
+   bool parseTrapPDU(const BYTE *pData, size_t pduLength);
+   bool parseTrap2PDU(const BYTE *pData, size_t pduLength);
+   bool parsePduContent(const BYTE *pData, size_t pduLength);
+   bool parseV3Header(const BYTE *pData, size_t pduLength);
+   bool parseV3SecurityUsm(const BYTE *pData, size_t pduLength, const BYTE *rawMsg);
+   bool parseV3ScopedPdu(const BYTE *pData, size_t pduLength);
+       bool validateSignedMessage(const BYTE *msg, size_t msgLen, SNMP_SecurityContext *securityContext);
        size_t encodeV3Header(BYTE *buffer, size_t bufferSize, SNMP_SecurityContext *securityContext);
        size_t encodeV3SecurityParameters(BYTE *buffer, size_t bufferSize, SNMP_SecurityContext *securityContext);
        size_t encodeV3ScopedPDU(UINT32 pduType, BYTE *pdu, size_t pduSize, BYTE *buffer, size_t bufferSize);
        void signMessage(BYTE *msg, size_t msgLen, SNMP_SecurityContext *securityContext);
-       bool decryptData(BYTE *data, size_t length, BYTE *decryptedData, SNMP_SecurityContext *securityContext);
+       bool decryptData(const BYTE *data, size_t length, BYTE *decryptedData, SNMP_SecurityContext *securityContext);
 
 public:
    SNMP_PDU();
@@ -581,7 +582,7 @@ public:
    SNMP_PDU(SNMP_PDU *src);
    ~SNMP_PDU();
 
-   bool parse(BYTE *rawData, size_t rawLength, SNMP_SecurityContext *securityContext, bool engineIdAutoupdate);
+   bool parse(const BYTE *rawData, size_t rawLength, SNMP_SecurityContext *securityContext, bool engineIdAutoupdate);
    size_t encode(BYTE **ppBuffer, SNMP_SecurityContext *securityContext);
 
    UINT32 getCommand() { return m_command; }
index 1c03d4c..915dedf 100644 (file)
@@ -163,16 +163,16 @@ static LONG H_DoHttp(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, Ab
        char szArg[256];
 
        int digetSize;
-       void (*hashFunction)(unsigned char *, size_t, unsigned char *) = NULL;
+       void (*hashFunction)(const BYTE *, size_t, BYTE *) = NULL;
        if (CAST_FROM_POINTER(pArg, int) == 1)
        {
                digetSize = SHA1_DIGEST_SIZE;
-               hashFunction = &CalculateSHA1Hash;
+               hashFunction = CalculateSHA1Hash;
        }
        else
        {
                digetSize = MD5_DIGEST_SIZE;
-               hashFunction = (void (*)(unsigned char *, size_t, unsigned char *))&CalculateMD5Hash;
+               hashFunction = CalculateMD5Hash;
        }
 
        AgentGetParameterArgA(pszParam, 1, szArg, 255);
index c63a4f7..90ee4d3 100644 (file)
@@ -6,7 +6,7 @@ ping_la_CPPFLAGS=-I@top_srcdir@/include
 ping_la_LDFLAGS = -module -avoid-version -export-symbols ../subagent.sym
 ping_la_LIBADD = ../../libnxagent/libnxagent.la ../../../libnetxms/libnetxms.la
 
-EXTRA_DIST = ping.h ping.vcproj
+EXTRA_DIST = Makefile.w32 ping.h ping.vcproj
 
 if !STATIC_BUILD
 install-exec-hook:
index 95fd677..4ca38e5 100644 (file)
@@ -110,9 +110,33 @@ UINT32 LIBNETXMS_EXPORTABLE CalculateCRC32(const unsigned char *pData, UINT32 nB
 }
 
 /**
+ * Init MD5 hash function
+ */
+void LIBNETXMS_EXPORTABLE MD5Init(MD5_STATE *state)
+{
+   I_md5_init((md5_state_t *)state);
+}
+
+/**
+ * Append data to MD5 hash
+ */
+void LIBNETXMS_EXPORTABLE MD5Update(MD5_STATE *state, const BYTE *data, size_t size)
+{
+   I_md5_append((md5_state_t *)state, (const md5_byte_t *)data, (int)size);
+}
+
+/**
+ * Finish MD5 calculation
+ */
+void LIBNETXMS_EXPORTABLE MD5Finish(MD5_STATE *state, BYTE *hash)
+{
+   I_md5_finish((md5_state_t *)state, (md5_byte_t *)hash);
+}
+
+/**
  * Calculate MD5 hash for array of bytes
  */
-void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const unsigned char *data, size_t nbytes, BYTE *hash)
+void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const BYTE *data, size_t nbytes, BYTE *hash)
 {
        md5_state_t state;
 
@@ -124,7 +148,7 @@ void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const unsigned char *data, size_t nby
 /**
  * Calculate MD5 hash for repeated pattern in virtual buffer
  */
-void LIBNETXMS_EXPORTABLE MD5HashForPattern(const unsigned char *data, size_t patternSize, size_t fullSize, BYTE *hash)
+void LIBNETXMS_EXPORTABLE MD5HashForPattern(const BYTE *data, size_t patternSize, size_t fullSize, BYTE *hash)
 {
        md5_state_t state;
        int count, patternIndex;
@@ -151,9 +175,33 @@ void LIBNETXMS_EXPORTABLE MD5HashForPattern(const unsigned char *data, size_t pa
 }
 
 /**
+ * Init SHA1 hash function
+ */
+void LIBNETXMS_EXPORTABLE SHA1Init(SHA1_STATE *state)
+{
+   I_SHA1Init((SHA1_CTX *)state);
+}
+
+/**
+ * Append data to SHA1 hash
+ */
+void LIBNETXMS_EXPORTABLE SHA1Update(SHA1_STATE *state, const BYTE *data, size_t size)
+{
+   I_SHA1Update((SHA1_CTX *)state, data, (uint32)size);
+}
+
+/**
+ * Finish SHA1 calculation
+ */
+void LIBNETXMS_EXPORTABLE SHA1Finish(SHA1_STATE *state, BYTE *hash)
+{
+   I_SHA1Final(hash, (SHA1_CTX *)state);
+}
+
+/**
  * Calculate SHA1 hash for array of bytes
  */
-void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(unsigned char *data, size_t nbytes, BYTE *hash)
+void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(const BYTE *data, size_t nbytes, BYTE *hash)
 {
    SHA1_CTX context;
 
@@ -165,7 +213,7 @@ void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(unsigned char *data, size_t nbytes,
 /**
  * Calculate SHA1 hash for repeated pattern in virtual buffer
  */
-void LIBNETXMS_EXPORTABLE SHA1HashForPattern(unsigned char *data, size_t patternSize, size_t fullSize, BYTE *hash)
+void LIBNETXMS_EXPORTABLE SHA1HashForPattern(const BYTE *data, size_t patternSize, size_t fullSize, BYTE *hash)
 {
    SHA1_CTX context;
        int count, patternIndex;
@@ -258,7 +306,7 @@ BOOL LIBNETXMS_EXPORTABLE CalculateFileSHA1Hash(const TCHAR *pszFileName, BYTE *
 /**
  * Calculate SHA2-256 hash for array of bytes
  */
-void LIBNETXMS_EXPORTABLE CalculateSHA256Hash(const unsigned char *data, size_t len, unsigned char *hash)
+void LIBNETXMS_EXPORTABLE CalculateSHA256Hash(const BYTE *data, size_t len, BYTE *hash)
 {
    sha256_ctx ctx;
 
index e61fbd0..4fe5dfb 100644 (file)
@@ -113,7 +113,7 @@ A million repetitions of "a"
 
 /* Hash a single 512-bit block. This is the core of the algorithm. */
 
-static void SHA1Transform(uint32 state[5], unsigned char buffer[64])
+static void SHA1Transform(uint32 state[5], const unsigned char buffer[64])
 {
 uint32 a, b, c, d, e;
 typedef union {
@@ -182,7 +182,7 @@ void I_SHA1Init(SHA1_CTX* context)
 
 /* Run your data through this. */
 
-void I_SHA1Update(SHA1_CTX* context, unsigned char* data, uint32 len)  /* JHB */
+void I_SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32 len)    /* JHB */
 {
 uint32 i, j;   /* JHB */
 
index 141d52f..bc935f2 100644 (file)
@@ -116,7 +116,7 @@ extern "C"
 #endif
 
 void I_SHA1Init(SHA1_CTX* context);
-void I_SHA1Update(SHA1_CTX* context, unsigned char* data, uint32 len); /*
+void I_SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32 len);   /*
 JHB */
 void I_SHA1Final(unsigned char digest[20], SHA1_CTX* context);
 
index 9e7942a..dd62cd4 100644 (file)
@@ -440,17 +440,17 @@ void AgentConnectionEx::onSnmpTrap(NXCPMessage *msg)
       if (acceptTrap)
       {
          InetAddress originSenderIP = msg->getFieldAsInetAddress(VID_IP_ADDRESS);
-         UINT32 pduLenght = msg->getFieldAsUInt32(VID_PDU_SIZE);
-         BYTE *pduBytes = (BYTE*)malloc(pduLenght);
-         msg->getFieldAsBinary(VID_PDU, pduBytes, pduLenght);
+         size_t pduLenght;
+         const BYTE *pduBytes = msg->getBinaryFieldPtr(VID_PDU, &pduLenght);
          UINT32 zoneId = IsZoningEnabled() ? msg->getFieldAsUInt32(VID_ZONE_ID) : 0;
          Node *originNode = FindNodeByIP(zoneId, originSenderIP);
          if ((originNode != NULL) || ConfigReadInt(_T("LogAllSNMPTraps"), FALSE))
          {
             SNMP_PDU *pdu = new SNMP_PDU;
-            if (pdu->parse(pduBytes, pduLenght, (originNode != NULL) ? originNode->getSnmpSecurityContext() : NULL, true))
+            SNMP_SecurityContext *sctx = (originNode != NULL) ? originNode->getSnmpSecurityContext() : NULL;
+            if (pdu->parse(pduBytes, pduLenght, sctx, true))
             {
-               DbgPrintf(6, _T("SNMPTrapReceiver: received PDU of type %d"), pdu->getCommand());
+               nxlog_debug(6, _T("SNMPTrapReceiver: received PDU of type %d"), pdu->getCommand());
                if ((pdu->getCommand() == SNMP_TRAP) || (pdu->getCommand() == SNMP_INFORM_REQUEST))
                {
                   bool isInformRequest = (pdu->getCommand() == SNMP_INFORM_REQUEST);
@@ -466,7 +466,7 @@ void AgentConnectionEx::onSnmpTrap(NXCPMessage *msg)
                else if ((pdu->getVersion() == SNMP_VERSION_3) && (pdu->getCommand() == SNMP_GET_REQUEST) && (pdu->getAuthoritativeEngine().getIdLen() == 0))
                {
                   // Engine ID discovery
-                  DbgPrintf(6, _T("SNMPTrapReceiver: EngineId discovery"));
+                  nxlog_debug(6, _T("SNMPTrapReceiver: EngineId discovery"));
 
                   SNMP_ProxyTransport *snmpTransport = CreateSNMPProxyTransport(this, originNode, originSenderIP, msg->getFieldAsUInt16(VID_PORT));
 
@@ -502,6 +502,7 @@ void AgentConnectionEx::onSnmpTrap(NXCPMessage *msg)
             {
                debugPrintf(6, _T("AgentConnectionEx::onSnmpTrap(): REPORT PDU with error %s"), (const TCHAR *)pdu->getVariable(0)->getName().toString());
             }
+            delete sctx;
          }
          else
          {
index 8031d2a..ccf53a6 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2013 Victor Kirhenshtein
+** Copyright (C) 2003-2017 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -232,11 +232,11 @@ DCObject::DCObject(ConfigEntry *config, Template *owner)
  */
 DCObject::~DCObject()
 {
-   safe_free(m_transformationScriptSource);
+   free(m_transformationScriptSource);
    delete m_transformationScript;
    delete m_schedules;
-       safe_free(m_pszPerfTabSettings);
-       safe_free(m_comments);
+       free(m_pszPerfTabSettings);
+       free(m_comments);
    MutexDestroy(m_hMutex);
    free(m_instanceDiscoveryData);
    free(m_instanceFilterSource);
@@ -1225,7 +1225,7 @@ void DCObject::filterInstanceList(StringMap *instances)
  */
 void DCObject::setInstanceFilter(const TCHAR *pszScript)
 {
-   safe_free(m_instanceFilterSource);
+   free(m_instanceFilterSource);
    delete m_instanceFilter;
    if (pszScript != NULL)
    {
index d501038..31f9ca4 100644 (file)
 /**
  * Decode BER-encoded variable
  */
-bool BER_DecodeIdentifier(BYTE *rawData, size_t rawSize, UINT32 *type, size_t *dataLength, BYTE **data, size_t *idLength)
+bool BER_DecodeIdentifier(const BYTE *rawData, size_t rawSize, UINT32 *type, size_t *dataLength, const BYTE **data, size_t *idLength)
 {
    bool bResult = false;
-   BYTE *pbCurrPos = rawData;
+   const BYTE *pbCurrPos = rawData;
    UINT32 dwIdLength = 0;
 
    *type = (UINT32)(*pbCurrPos);
@@ -76,7 +76,7 @@ bool BER_DecodeIdentifier(BYTE *rawData, size_t rawSize, UINT32 *type, size_t *d
 /**
  * Decode content of specified types
  */
-bool BER_DecodeContent(UINT32 type, BYTE *data, size_t length, BYTE *buffer)
+bool BER_DecodeContent(UINT32 type, const BYTE *data, size_t length, BYTE *buffer)
 {
    bool bResult = true;
 
index 2ccc5d7..79f5cb8 100644 (file)
@@ -119,8 +119,8 @@ public:
 /**
  * Functions
  */
-bool BER_DecodeIdentifier(BYTE *rawData, size_t rawSize, UINT32 *type, size_t *length, BYTE **data, size_t *idLength);
-bool BER_DecodeContent(UINT32 type, BYTE *data, size_t length, BYTE *buffer);
+bool BER_DecodeIdentifier(const BYTE *rawData, size_t rawSize, UINT32 *type, size_t *length, const BYTE **data, size_t *idLength);
+bool BER_DecodeContent(UINT32 type, const BYTE *data, size_t length, BYTE *buffer);
 size_t BER_Encode(UINT32 type, const BYTE *data, size_t dataLength, BYTE *buffer, size_t bufferSize);
 
 #endif   /* _libnxsnmp_h_ */
index c6243be..91f70e3 100644 (file)
@@ -83,6 +83,7 @@ SNMP_PDU::SNMP_PDU()
    m_securityModel = SNMP_SECURITY_MODEL_V1;
        m_dwAgentAddr = 0;
        m_dwTimeStamp = 0;
+       m_signatureOffset = 0;
 }
 
 /**
@@ -109,6 +110,7 @@ SNMP_PDU::SNMP_PDU(UINT32 dwCommand, UINT32 dwRqId, UINT32 dwVersion)
    m_securityModel = (m_version == SNMP_VERSION_1) ? SNMP_SECURITY_MODEL_V1 : ((m_version == SNMP_VERSION_2C) ? SNMP_SECURITY_MODEL_V2C : SNMP_SECURITY_MODEL_USM);
    m_dwAgentAddr = 0;
    m_dwTimeStamp = 0;
+   m_signatureOffset = 0;
 }
 
 /**
@@ -138,6 +140,7 @@ SNMP_PDU::SNMP_PDU(SNMP_PDU *src) : m_authoritativeEngine(&src->m_authoritativeE
    m_securityModel = src->m_securityModel;
    m_dwAgentAddr = 0;
    m_dwTimeStamp = 0;
+   m_signatureOffset = src->m_signatureOffset;
 }
 
 /**
@@ -147,13 +150,13 @@ SNMP_PDU::~SNMP_PDU()
 {
    delete m_pEnterprise;
    delete m_variables;
-       safe_free(m_authObject);
+       free(m_authObject);
 }
 
 /**
  * Parse single variable binding
  */
-bool SNMP_PDU::parseVariable(BYTE *pData, size_t varLength)
+bool SNMP_PDU::parseVariable(const BYTE *pData, size_t varLength)
 {
    SNMP_Variable *var;
    bool success = true;
@@ -174,9 +177,9 @@ bool SNMP_PDU::parseVariable(BYTE *pData, size_t varLength)
 /**
  * Parse variable bindings
  */
-bool SNMP_PDU::parseVarBinds(BYTE *pData, size_t pduLength)
+bool SNMP_PDU::parseVarBinds(const BYTE *pData, size_t pduLength)
 {
-   BYTE *pbCurrPos;
+   const BYTE *pbCurrPos;
    UINT32 dwType;
    size_t dwLength, dwBindingLength, idLength;
 
@@ -207,11 +210,11 @@ bool SNMP_PDU::parseVarBinds(BYTE *pData, size_t pduLength)
 /**
  * Parse generic PDU content
  */
-bool SNMP_PDU::parsePduContent(BYTE *pData, size_t pduLength)
+bool SNMP_PDU::parsePduContent(const BYTE *pData, size_t pduLength)
 {
    UINT32 dwType;
    size_t dwLength, idLength;
-   BYTE *pbCurrPos = pData;
+   const BYTE *pbCurrPos = pData;
    bool bResult = false;
 
    // Request ID
@@ -267,11 +270,11 @@ bool SNMP_PDU::parsePduContent(BYTE *pData, size_t pduLength)
 /**
  * Parse version 1 TRAP PDU
  */
-bool SNMP_PDU::parseTrapPDU(BYTE *pData, size_t pduLength)
+bool SNMP_PDU::parseTrapPDU(const BYTE *pData, size_t pduLength)
 {
    UINT32 dwType;
    size_t dwLength, idLength;
-   BYTE *pbCurrPos = pData;
+   const BYTE *pbCurrPos = pData;
    SNMP_OID *oid;
    UINT32 dwBuffer;
    bool bResult = false;
@@ -395,7 +398,7 @@ bool SNMP_PDU::parseTrapPDU(BYTE *pData, size_t pduLength)
 /**
  * Parse version 2 TRAP or INFORM-REQUEST PDU
  */
-bool SNMP_PDU::parseTrap2PDU(BYTE *pData, size_t pduLength)
+bool SNMP_PDU::parseTrap2PDU(const BYTE *pData, size_t pduLength)
 {
    bool bResult;
    static UINT32 pdwStdTrapPrefix[9] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
@@ -436,11 +439,11 @@ bool SNMP_PDU::parseTrap2PDU(BYTE *pData, size_t pduLength)
 /**
  * Parse version 3 header
  */
-bool SNMP_PDU::parseV3Header(BYTE *header, size_t headerLength)
+bool SNMP_PDU::parseV3Header(const BYTE *header, size_t headerLength)
 {
        UINT32 type;
    size_t length, idLength, remLength = headerLength;
-       BYTE *currPos = header;
+       const BYTE *currPos = header;
 
    // Message id
    if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
@@ -491,12 +494,12 @@ bool SNMP_PDU::parseV3Header(BYTE *header, size_t headerLength)
 /**
  * Parse V3 USM security parameters
  */
-bool SNMP_PDU::parseV3SecurityUsm(BYTE *data, size_t dataLength)
+bool SNMP_PDU::parseV3SecurityUsm(const BYTE *data, size_t dataLength, const BYTE *rawMsg)
 {
        UINT32 type;
    size_t length, idLength, engineIdLen, remLength = dataLength;
        UINT32 engineBoots, engineTime;
-       BYTE *currPos = data;
+       const BYTE *currPos = data;
        BYTE engineId[SNMP_MAX_ENGINEID_LEN];
 
        // Should be sequence
@@ -561,7 +564,7 @@ bool SNMP_PDU::parseV3SecurityUsm(BYTE *data, size_t dataLength)
    if (type != ASN_OCTET_STRING)
       return false;
        memcpy(m_signature, currPos, min(length, 12));
-       memset(currPos, 0, min(length, 12));    // Replace with 0 to generate correct hash in validate method
+       m_signatureOffset = currPos - rawMsg;
    currPos += length;
    remLength -= length + idLength;
 
@@ -578,11 +581,11 @@ bool SNMP_PDU::parseV3SecurityUsm(BYTE *data, size_t dataLength)
 /**
  * Parse V3 scoped PDU
  */
-bool SNMP_PDU::parseV3ScopedPdu(BYTE *data, size_t dataLength)
+bool SNMP_PDU::parseV3ScopedPdu(const BYTE *data, size_t dataLength)
 {
        UINT32 type;
    size_t length, idLength, remLength = dataLength;
-       BYTE *currPos = data;
+       const BYTE *currPos = data;
 
    // Context engine ID
    if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
@@ -612,9 +615,9 @@ bool SNMP_PDU::parseV3ScopedPdu(BYTE *data, size_t dataLength)
 /**
  * Parse PDU
  */
-bool SNMP_PDU::parsePdu(BYTE *pdu, size_t pduLength)
+bool SNMP_PDU::parsePdu(const BYTE *pdu, size_t pduLength)
 {
-       BYTE *content;
+       const BYTE *content;
        size_t length, idLength;
    UINT32 type;
        bool success;
@@ -667,14 +670,16 @@ bool SNMP_PDU::parsePdu(BYTE *pdu, size_t pduLength)
 /**
  * Validate V3 signed message
  */
-bool SNMP_PDU::validateSignedMessage(BYTE *msg, size_t msgLen, SNMP_SecurityContext *securityContext)
+bool SNMP_PDU::validateSignedMessage(const BYTE *msg, size_t msgLen, SNMP_SecurityContext *securityContext)
 {
-       BYTE k1[64], k2[64], hash[20], *buffer;
-       int i;
-
        if (securityContext == NULL)
                return false;   // Unable to validate message without security context
 
+   BYTE k1[64], k2[64], hash[20];
+   SHA1_STATE sha1;
+   MD5_STATE md5;
+   int i;
+
        switch(securityContext->getAuthMethod())
        {
                case SNMP_AUTH_MD5:
@@ -689,16 +694,19 @@ bool SNMP_PDU::validateSignedMessage(BYTE *msg, size_t msgLen, SNMP_SecurityCont
                        }
 
                        // Calculate first hash (step 3)
-                       buffer = (BYTE *)malloc(msgLen + 64);
-                       memcpy(buffer, k1, 64);
-                       memcpy(&buffer[64], msg, msgLen);
-                       CalculateMD5Hash(buffer, msgLen + 64, hash);
+                       MD5Init(&md5);
+                       MD5Update(&md5, k1, 64);
+                       MD5Update(&md5, msg, m_signatureOffset);
+                       MD5Update(&md5, (const BYTE *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12); // Replace signature with 0 to generate correct hash
+                       if (msgLen > m_signatureOffset + 12)
+                          MD5Update(&md5, msg + m_signatureOffset + 12, msgLen - m_signatureOffset - 12);
+                       MD5Finish(&md5, hash);
 
                        // Calculate second hash
-                       memcpy(buffer, k2, 64);
-                       memcpy(&buffer[64], hash, 16);
-                       CalculateMD5Hash(buffer, 80, hash);
-                       free(buffer);
+         MD5Init(&md5);
+         MD5Update(&md5, k2, 64);
+         MD5Update(&md5, hash, 16);
+         MD5Finish(&md5, hash);
                        break;
                case SNMP_AUTH_SHA1:
                        // Create K1 and K2
@@ -712,16 +720,19 @@ bool SNMP_PDU::validateSignedMessage(BYTE *msg, size_t msgLen, SNMP_SecurityCont
                        }
 
                        // Calculate first hash (step 3)
-                       buffer = (BYTE *)malloc(msgLen + 64);
-                       memcpy(buffer, k1, 64);
-                       memcpy(&buffer[64], msg, msgLen);
-                       CalculateSHA1Hash(buffer, msgLen + 64, hash);
+                       SHA1Init(&sha1);
+         SHA1Update(&sha1, k1, 64);
+         SHA1Update(&sha1, msg, m_signatureOffset);
+         SHA1Update(&sha1, (const BYTE *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12); // Replace signature with 0 to generate correct hash
+         if (msgLen > m_signatureOffset + 12)
+            SHA1Update(&sha1, msg + m_signatureOffset + 12, msgLen - m_signatureOffset - 12);
+         SHA1Finish(&sha1, hash);
 
                        // Calculate second hash
-                       memcpy(buffer, k2, 64);
-                       memcpy(&buffer[64], hash, 20);
-                       CalculateSHA1Hash(buffer, 84, hash);
-                       free(buffer);
+         SHA1Init(&sha1);
+         SHA1Update(&sha1, k2, 64);
+         SHA1Update(&sha1, hash, 20);
+         SHA1Finish(&sha1, hash);
                        break;
                default:
                        break;
@@ -734,7 +745,7 @@ bool SNMP_PDU::validateSignedMessage(BYTE *msg, size_t msgLen, SNMP_SecurityCont
 /**
  * Decrypt data in packet
  */
-bool SNMP_PDU::decryptData(BYTE *data, size_t length, BYTE *decryptedData, SNMP_SecurityContext *securityContext)
+bool SNMP_PDU::decryptData(const BYTE *data, size_t length, BYTE *decryptedData, SNMP_SecurityContext *securityContext)
 {
 #ifdef _WITH_ENCRYPTION
        if (securityContext == NULL)
@@ -803,9 +814,9 @@ bool SNMP_PDU::decryptData(BYTE *data, size_t length, BYTE *decryptedData, SNMP_
 /**
  * Create PDU from packet
  */
-bool SNMP_PDU::parse(BYTE *rawData, size_t rawLength, SNMP_SecurityContext *securityContext, bool engineIdAutoupdate)
+bool SNMP_PDU::parse(const BYTE *rawData, size_t rawLength, SNMP_SecurityContext *securityContext, bool engineIdAutoupdate)
 {
-   BYTE *pbCurrPos;
+   const BYTE *pbCurrPos;
    UINT32 dwType;
    size_t dwLength, dwPacketLength, idLength;
    bool bResult = false;
@@ -850,7 +861,7 @@ bool SNMP_PDU::parse(BYTE *rawData, size_t rawLength, SNMP_SecurityContext *secu
 
                if (m_securityModel == SNMP_SECURITY_MODEL_USM)
                {
-                       if (!parseV3SecurityUsm(pbCurrPos, dwLength))
+                       if (!parseV3SecurityUsm(pbCurrPos, dwLength, rawData))
                                return false;
 
                        if (engineIdAutoupdate && (m_authoritativeEngine.getIdLen() > 0) && (securityContext != NULL))
@@ -869,33 +880,37 @@ bool SNMP_PDU::parse(BYTE *rawData, size_t rawLength, SNMP_SecurityContext *secu
                dwPacketLength -= dwLength + idLength;
 
                // Decrypt scoped PDU if needed
+               BYTE *decryptedPdu = NULL;
                if ((m_securityModel == SNMP_SECURITY_MODEL_USM) && (m_flags & SNMP_PRIV_FLAG))
                {
-                       BYTE *scopedPduStart = pbCurrPos;
-
                        if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &idLength))
                                return false;
                        if (dwType != ASN_OCTET_STRING)
                                return false;   // Should be encoded as octet string
 
-                       BYTE *decryptedPdu = (BYTE *)malloc(dwLength);
+                       decryptedPdu = (BYTE *)malloc(dwLength);
                        if (!decryptData(pbCurrPos, dwLength, decryptedPdu, securityContext))
                        {
                                free(decryptedPdu);
                                return false;
                        }
 
-                       pbCurrPos = scopedPduStart;
-                       memcpy(pbCurrPos, decryptedPdu, dwLength);
-                       free(decryptedPdu);
+                       pbCurrPos = decryptedPdu;
                }
 
                // Scoped PDU
                if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &idLength))
+               {
+             free(decryptedPdu);
                        return false;
+               }
                if (dwType != ASN_SEQUENCE)
+               {
+             free(decryptedPdu);
                        return false;   // Should be sequence
+               }
                bResult = parseV3ScopedPdu(pbCurrPos, dwLength);
+      free(decryptedPdu);
        }
        else
        {
index 66eab9b..c62f63a 100644 (file)
@@ -422,7 +422,7 @@ size_t SNMP_UDPTransport::preParsePDU()
 {
    UINT32 dwType;
    size_t dwLength, dwIdLength;
-   BYTE *pbCurrPos;
+   const BYTE *pbCurrPos;
 
    if (!BER_DecodeIdentifier(&m_pBuffer[m_dwBufferPos], m_dwBytesInBuffer,
                              &dwType, &dwLength, &pbCurrPos, &dwIdLength))
index 251ba95..e4dffaf 100644 (file)
@@ -86,9 +86,9 @@ SNMP_Variable::~SNMP_Variable()
 /**
  * Parse variable record in PDU
  */
-bool SNMP_Variable::parse(BYTE *data, size_t varLength)
+bool SNMP_Variable::parse(const BYTE *data, size_t varLength)
 {
-   BYTE *pbCurrPos;
+   const BYTE *pbCurrPos;
    UINT32 type;
    size_t length, dwIdLength;
    SNMP_OID *oid;