Beispiel #1
0
//================[ append one OctetStr to another ]==================
OctetStr& OctetStr::operator+=(const OctetStr& octet)
{
  unsigned char *tmp;
  size_t slen, nlen;

  if (!octet.validity || !((slen = (size_t)octet.len())))
    return *this;

  nlen = slen + (size_t) smival.value.string.len;  // total len of new octet
  tmp = (SmiLPBYTE) new unsigned char[nlen];  // get mem needed

  if (tmp)
  {
    // copy in the original 1st
    MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
    // copy in the string
    MEMCPY(tmp + smival.value.string.len, octet.data(), slen);
    // delete the original
    if (smival.value.string.ptr )
      delete [] smival.value.string.ptr;
    // point to the new one
    smival.value.string.ptr = tmp;
    smival.value.string.len = SAFE_INT_CAST(nlen);

    m_changed = true;
  }
  return *this;
}
Beispiel #2
0
//===============[ append operator, appends a string ]================
OctetStr& OctetStr::operator+=(const char *a)
{
  unsigned char *tmp;
  size_t slen, nlen;

  // get len of string
  if (!a || ((slen = strlen(a)) == 0))
    return *this;

  nlen = slen + (size_t) smival.value.string.len;  // total len of new octet
  tmp = (SmiLPBYTE) new unsigned char[nlen];  // get mem needed

  if (tmp)
  {
    // copy in the original 1st
    memcpy(tmp, smival.value.string.ptr, smival.value.string.len);
    // copy in the string
    memcpy(tmp + smival.value.string.len, a, slen);
    // delete the original
    if (smival.value.string.ptr)
      delete [] smival.value.string.ptr;
    // point to the new one
    smival.value.string.ptr = tmp;
    smival.value.string.len = SAFE_INT_CAST(nlen);

    m_changed = true;
    validity = true;
  }
  return *this;
}
Beispiel #3
0
// Parse the given buffer as a SNMPv3-Message.
int v3MP::snmp_parse(Snmp *snmp_session,
                     struct snmp_pdu *pdu,
                     unsigned char *inBuf,
                     int inBufLength,
                     OctetStr &securityEngineID,
                     OctetStr &securityName,
                     OctetStr &contextEngineID,
                     OctetStr &contextName,
                     long     &securityLevel,
                     long     &msgSecurityModel,
                     snmp_version &spp_version,
                     UdpAddress from_address)
{
  debugprintf(3, "mp is parsing incoming message:");
  debughexprintf(25, inBuf, inBufLength);

  if (inBufLength > MAX_SNMP_PACKET)
    return  SNMPv3_MP_ERROR;

  unsigned char type;
  long version;
  int origLength = inBufLength;
  unsigned char *inBufPtr = inBuf;
  long msgID, msgMaxSize;
  unsigned char msgFlags;
  Buffer<unsigned char> msgSecurityParameters(MAX_SNMP_PACKET);
  Buffer<unsigned char> msgData(MAX_SNMP_PACKET);
  int msgSecurityParametersLength = inBufLength,   msgDataLength = inBufLength;
  Buffer<unsigned char> scopedPDU(MAX_SNMP_PACKET);
  int scopedPDULength = MAX_SNMP_PACKET;
  long  maxSizeResponseScopedPDU = 0;
  struct SecurityStateReference *securityStateReference = NULL;
  int securityParametersPosition;
  int rc;
  int errorCode = 0;

  // get the type
  inBuf = asn_parse_header( inBuf, &inBufLength, &type);
  if (inBuf == NULL){
    debugprintf(0, "snmp_parse: bad header");
    return SNMPv3_MP_PARSE_ERROR;
  }

  if (type != (ASN_SEQ_CON)){
    debugprintf(0, "snmp_parse: wrong auth header type");
    return SNMPv3_MP_PARSE_ERROR;
  }

  if (origLength != inBufLength + (inBuf - inBufPtr)) {
    debugprintf(0, "snmp_parse: wrong length of received packet");
    return SNMPv3_MP_PARSE_ERROR;
  }

  // get the version
  inBuf = asn_parse_int(inBuf, &inBufLength, &type, &version);
  if (inBuf == NULL){
    debugprintf(0, "snmp_parse: bad parse of version");
    return SNMPv3_MP_PARSE_ERROR;
  }

  debugprintf(3, "Parsed length(%x), version(0x%lx)", inBufLength, version);

  if ( version != SNMP_VERSION_3 )
    return SNMPv3_MP_PARSE_ERROR;

  spp_version = (snmp_version) version;

  inBuf = asn1_parse_header_data(inBuf, &inBufLength,
				 &msgID, &msgMaxSize,
				 &msgFlags, &msgSecurityModel);

  if (inBuf == NULL){
    debugprintf(0, "snmp_parse: bad parse of msgHeaderData");
    return SNMPv3_MP_PARSE_ERROR;
  }

  pdu->msgid = msgID;
  if ((msgMaxSize < 484) || (msgMaxSize > 0x7FFFFFFF)) {
    debugprintf(0, "snmp_parse: bad parse of msgMaxSize");
    return SNMPv3_MP_PARSE_ERROR;
  }

  // do not allow larger messages than this entity can handle
  if (msgMaxSize > MAX_SNMP_PACKET) msgMaxSize = MAX_SNMP_PACKET;
  pdu->maxsize_scopedpdu = msgMaxSize;

  inBuf = asn_parse_string( inBuf, &inBufLength, &type,
                            msgSecurityParameters.get_ptr(),
                            &msgSecurityParametersLength);

  if (inBuf == NULL){
    debugprintf(0, "snmp_parse: bad parse of msgSecurityParameters");
    return SNMPv3_MP_PARSE_ERROR;
  }

  securityParametersPosition= SAFE_INT_CAST(inBuf - inBufPtr) - msgSecurityParametersLength;

  // the rest of the message is passed directly to the security module

  msgDataLength = origLength - SAFE_INT_CAST(inBuf - inBufPtr);
  memcpy(msgData.get_ptr(), inBuf, msgDataLength);

  debugprintf(3, "Parsed msgdata length(0x%x), "
	      "msgSecurityParameters length(0x%x)", msgDataLength,
	      msgSecurityParametersLength);

  switch (msgFlags & 0x03) {
    case 3:  { securityLevel = SNMP_SECURITY_LEVEL_AUTH_PRIV;     break;}
    case 0:  { securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break;}
    case 1:  { securityLevel = SNMP_SECURITY_LEVEL_AUTH_NOPRIV;   break;}
    default: { securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
               snmpInvalidMsgs++;
               // do not send back report
               return SNMPv3_MP_INVALID_MESSAGE;
               break;
             }
  }

  bool reportableFlag;

  if (msgFlags & 0x04) reportableFlag = true;
  else                 reportableFlag = false;

  securityStateReference = usm->get_new_sec_state_reference();
  if (!securityStateReference)
    return SNMPv3_MP_ERROR;

  switch (msgSecurityModel) {
    case SNMP_SECURITY_MODEL_USM:
      {
        rc = usm->process_msg(
                           msgMaxSize,
                           msgSecurityParameters.get_ptr(),
			   msgSecurityParametersLength,
                           securityParametersPosition,
                           securityLevel,
                           inBufPtr, origLength, //wholeMsg
                           msgData.get_ptr(), msgDataLength,
                           securityEngineID,
                           securityName,
                           scopedPDU.get_ptr(), &scopedPDULength,
                           &maxSizeResponseScopedPDU,
                           securityStateReference,
			   from_address);
        pdu->maxsize_scopedpdu = maxSizeResponseScopedPDU;
        if (rc != SNMPv3_USM_OK) {
          if (rc == SNMPv3_USM_NOT_IN_TIME_WINDOW) {
            errorCode = SNMPv3_MP_NOT_IN_TIME_WINDOW;
          }
          else {
            // error handling! rfc2262 page 31
            debugprintf(0, "mp: error while executing USM::process_msg");
            errorCode = rc;
          }
        }
        if (errorCode != SNMPv3_USM_PARSE_ERROR)
          if (securityEngineID.len() == 0)
            errorCode = SNMPv3_MP_INVALID_ENGINEID;
        break;
      }
    default: {
        snmpUnknownSecurityModels++;
	usm->delete_sec_state_reference(securityStateReference);
        debugprintf(0, "SecurityModel of incomming Message not supported!");
        // Message should be dropped without a report
        return SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL;
      }
  }
  // process scopedPDU
  debughexcprintf(21, "scoped PDU", scopedPDU.get_ptr(), scopedPDULength);

  unsigned char *scopedPDUPtr= scopedPDU.get_ptr();
  unsigned char tmp_contextEngineID[MAXLENGTH_ENGINEID];
  unsigned char tmp_contextName[MAXLENGTH_CONTEXT_NAME];
  int tmp_contextEngineIDLength = MAXLENGTH_ENGINEID;
  int tmp_contextNameLength     = MAXLENGTH_CONTEXT_NAME;

  unsigned char *data;
  int dataLength;

  debugprintf(1,"ErrorCode is %i",errorCode);

  if (!errorCode) {
    data = asn1_parse_scoped_pdu(scopedPDUPtr, &scopedPDULength,
				 tmp_contextEngineID,
				 &tmp_contextEngineIDLength,
				 tmp_contextName, &tmp_contextNameLength);
    if (data == NULL) {
      debugprintf(0, "mp: Error Parsing scopedPDU!");
      usm->delete_sec_state_reference(securityStateReference);
      return SNMPv3_MP_PARSE_ERROR;
    }
    dataLength = scopedPDULength;
    contextEngineID.set_data(tmp_contextEngineID, tmp_contextEngineIDLength);
    contextName.set_data(tmp_contextName, tmp_contextNameLength);

    // parse data of scopedPDU
    if (snmp_parse_data_pdu(pdu, data, dataLength) != SNMP_CLASS_SUCCESS) {
      debugprintf(0, "mp: Error parsing PDU!");
      usm->delete_sec_state_reference(securityStateReference);
      return SNMPv3_MP_PARSE_ERROR;
    }
    if (SNMP_CLASS_SUCCESS != snmp_parse_vb(pdu, data, dataLength)) {
      debugprintf(0, "mp: Error parsing Vb");
      usm->delete_sec_state_reference(securityStateReference);
      return SNMPv3_MP_PARSE_ERROR;
    }
    if ((tmp_contextEngineIDLength == 0) &&
        ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) ||
         (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) ||
         (pdu->command == TRP_REQ_MSG) || (pdu->command == INFORM_REQ_MSG)  ||
         (pdu->command == TRP2_REQ_MSG)))
    {
      //  RFC 2572 � 4.2.2.1 (2a)
      debugprintf(2, "mp: received request message with zero length"
                  " contextEngineID -> unknownPduHandlers.");
      inc_stats_unknown_pdu_handlers();
      errorCode = SNMPv3_MP_UNKNOWN_PDU_HANDLERS;
    }
  }
  if (errorCode) {
    if ((reportableFlag) && (errorCode != SNMPv3_USM_PARSE_ERROR)) {
      // error occured: prepare reportpdu in agent
      cache.add_entry(msgID, pdu->reqid, securityEngineID,
                      msgSecurityModel,
                      securityName, securityLevel, "", "",
                      securityStateReference, errorCode, CACHE_REMOTE_REQ);

      send_report(scopedPDUPtr, scopedPDULength, pdu, errorCode,
		  securityLevel, msgSecurityModel, securityName,
		  from_address, snmp_session);
      clear_pdu(pdu, true);   // Clear pdu and free all content AND IDs!
    }
    else {
      usm->delete_sec_state_reference(securityStateReference);
    }
    return errorCode;
  }

  struct Cache::Entry_T centry;

  if ((pdu->command == GET_RSP_MSG) || (pdu->command == REPORT_MSG)) {
    rc = cache.get_entry(msgID, true, &centry);
    if (rc != SNMPv3_MP_OK) {
      // RFC 2572 � 4
      debugprintf(2, "Received rspMsg without outstanding request."
                  " -> SnmpUnknownPduHandler");
      usm->delete_sec_state_reference(securityStateReference);
      inc_stats_unknown_pdu_handlers();
      return SNMPv3_MP_UNKNOWN_PDU_HANDLERS;
    }
    if (((pdu->reqid == 0) || (pdu->reqid == 0x7fffffff))
	&& (pdu->command == REPORT_MSG))
      pdu->reqid = centry.req_id;
#ifdef BUGGY_REPORT_REQID
    if ((pdu->reqid != centry.req_id) && (pdu->command == REPORT_MSG))
    {
      debugprintf(0, "WARNING: setting reqid of REPORT PDU (from) (to): (%ld) (%ld)",  pdu->reqid, centry.req_id);
      pdu->reqid = centry.req_id;
    }
#endif
  }

  if (pdu->command == REPORT_MSG) {
    // !! rfc2262 page 33

    debugprintf(2, "*** Receiving a ReportPDU ***");
    if (/*((securityEngineID != centry.sec_engine_id)
	  && (centry.sec_engine_id.len() != 0)) ||*/
        ((msgSecurityModel != centry.sec_model)
         && (msgSecurityModel != SNMP_SECURITY_MODEL_USM)) ||
        ((securityName != centry.sec_name)
         && (securityName.len() != 0)))
    {
      debugprintf(0, "Received report message doesn't match sent message!");
      usm->delete_sec_state_reference(securityStateReference);
      return SNMPv3_MP_MATCH_ERROR;
    }
    usm->delete_sec_state_reference(securityStateReference);
    cache.delete_content(centry);
    debugprintf(1, "mp finished (OK)");
    return SNMPv3_MP_OK;
  }

  if (pdu->command == GET_RSP_MSG) {
    if (((securityEngineID != centry.sec_engine_id)
         && (centry.sec_engine_id.len() != 0)) ||
        (msgSecurityModel != centry.sec_model) ||
        (securityName != centry.sec_name) ||
        (securityLevel != centry.sec_level) ||
        ((contextEngineID != centry.context_engine_id)
         && (centry.context_engine_id.len() != 0))||
        ((contextName != centry.context_name)
         && (centry.context_name.len() != 0))) {
      debugprintf(0, "Received response message doesn't match sent message!");
      usm->delete_sec_state_reference(securityStateReference);
      cache.delete_content(centry);
      return SNMPv3_MP_MATCH_ERROR;
    }
    usm->delete_sec_state_reference(securityStateReference);
    cache.delete_content(centry);
    debugprintf(1, "mp finished (OK)");
    return SNMPv3_MP_OK;
  }

  if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) ||
      (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) ||
      (pdu->command == INFORM_REQ_MSG)) {
    if (securityEngineID.len() == 0) {
      debugprintf(2, "Received Message with engineID = 0.");
    }
    else {
      if (!(unsignedCharCompare(securityEngineID.data(), securityEngineID.len(),
                                own_engine_id, own_engine_id_len))) {
        debugprintf(0, "snmp_parse: securityEngineID doesn't match own_engine_id.");
	/* we are authoritative but engine id of message is wrong
	   if discovery in USM is enabled:
	   - remove automatically added illegal engine id from USM tables
	   - send a report
	*/
	if (usm->is_discovery_enabled())
	{
	  // TODO: try to remove engine id from USM
	  if (reportableFlag)
	  {
	    cache.add_entry(msgID, pdu->reqid, securityEngineID,
			    msgSecurityModel,
			    securityName, securityLevel, "", "",
			    securityStateReference,
			    SNMPv3_MP_INVALID_ENGINEID,
			    CACHE_REMOTE_REQ);

	    send_report(0, MAX_SNMP_PACKET, pdu, SNMPv3_MP_INVALID_ENGINEID,
			SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV, msgSecurityModel,
			securityName, from_address, snmp_session);
	    clear_pdu(pdu, true);  // Clear pdu and free all content AND IDs!
	  }
	  else
	  {
	    usm->delete_sec_state_reference(securityStateReference);
	  }
	  return SNMPv3_MP_INVALID_ENGINEID;
	}

        usm->delete_sec_state_reference(securityStateReference);
        return SNMPv3_MP_MATCH_ERROR;
      }
    }
    int ret = cache.add_entry(msgID, pdu->reqid, securityEngineID,
                              msgSecurityModel, securityName,
                              securityLevel, contextEngineID,
                              contextName, securityStateReference,
                              SNMPv3_MP_OK, CACHE_REMOTE_REQ);
    if (ret == SNMPv3_MP_DOUBLED_MESSAGE) {
      debugprintf(0, "*** received doubled message ***");
      // message will be ignored so return OK
      usm->delete_sec_state_reference(securityStateReference);
    }

    debugprintf(1, "mp: parsing finished (ok).");
    return SNMPv3_MP_OK;
  }

  if ((pdu->command == TRP_REQ_MSG) || (pdu->command == TRP2_REQ_MSG))
  {
    usm->delete_sec_state_reference(securityStateReference);
    return SNMPv3_MP_OK;
  }

  debugprintf(0, "mp error: This line should not be executed.");
  usm->delete_sec_state_reference(securityStateReference);
  return SNMPv3_MP_ERROR;
}
Beispiel #4
0
// Do the complete process of encoding the given values into the buffer
// ready to send to the target.
int v3MP::snmp_build(struct snmp_pdu *pdu,
		     unsigned char *packet,
		     int *out_length,             // maximum Bytes in packet
		     const OctetStr &securityEngineID,
		     const OctetStr &securityName,
		     int securityModel,
		     int securityLevel,
		     const OctetStr &contextEngineID,
		     const OctetStr &contextName)
{
  Buffer<unsigned char> scopedPDU(MAX_SNMP_PACKET);
  unsigned char *scopedPDUPtr = scopedPDU.get_ptr();
  unsigned char globalData[MAXLENGTH_GLOBALDATA];
  int globalDataLength = MAXLENGTH_GLOBALDATA;
  int scopedPDULength, maxLen = *out_length;
  Buffer<unsigned char> buf(MAX_SNMP_PACKET);
  unsigned char *bufPtr = buf.get_ptr();
  long bufLength = 0, rc;
  int msgID;
  int cachedErrorCode = SNMPv3_MP_OK;
  struct SecurityStateReference *securityStateReference = NULL;
  int isRequestMessage = 0;

  if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) ||
      (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) ||
      (pdu->command == TRP_REQ_MSG) || (pdu->command == INFORM_REQ_MSG)  ||
      (pdu->command == TRP2_REQ_MSG))
    isRequestMessage = 1;

  if (isRequestMessage) {
    if (securityEngineID.len() == 0) {
      // First Contact => use user  noAuthNoPriv and USM
      securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      securityModel = SNMP_SECURITY_MODEL_USM;
    }

    cur_msg_id_lock.lock();
    msgID = cur_msg_id;
    cur_msg_id++;
    if (cur_msg_id >= MAX_MPMSGID)
      cur_msg_id = 1;
    cur_msg_id_lock.unlock();

#ifdef INVALID_MSGID
    LOG_BEGIN(loggerModuleName, ERROR_LOG | 1);
    LOG("*** WARNING: Using constant MessageID! ***");
    LOG_END;

    msgID = 0xdead;
#endif

    if (securityEngineID.len() == 0) {
      // length==0 => SecurityLevel == noAuthNoPriv
      //  => we do not send any management information
      //  => delete VariableBinding
      clear_pdu(pdu);
    }
  }
  else {
    // it is a response => search for request
    debugprintf(3, "Looking up cache");
    msgID = pdu->msgid;
    rc = cache.get_entry(msgID, CACHE_REMOTE_REQ,
                         &cachedErrorCode, &securityStateReference);

    if (rc != SNMPv3_MP_OK) {

      debugprintf(0, "mp: Cache lookup error");
      return SNMPv3_MP_MATCH_ERROR;
    }
  }

  LOG_BEGIN(loggerModuleName, DEBUG_LOG | 5);
  LOG("v3MP: Building message with (SecurityEngineID) (securityName) (securityLevel) (contextEngineID) (contextName)");
  LOG(securityEngineID.get_printable());
  LOG(securityName.get_printable());
  LOG(securityLevel);
  LOG(contextEngineID.get_printable());
  LOG(contextName.get_printable());
  LOG_END;

  // encode vb in buf
  scopedPDUPtr = build_vb(pdu, scopedPDUPtr, &maxLen);
  if (!scopedPDUPtr)
  {
    LOG_BEGIN(loggerModuleName, WARNING_LOG | 1);
    LOG("v3MP: Error encoding vbs into buffer");
    LOG_END;

    return SNMPv3_MP_BUILD_ERROR;
  }
  scopedPDULength = SAFE_INT_CAST(scopedPDUPtr - scopedPDU.get_ptr());

  //build dataPDU in buf
  maxLen = *out_length;
  scopedPDUPtr = scopedPDU.get_ptr();
  bufPtr = build_data_pdu(pdu, bufPtr, &maxLen, scopedPDUPtr, scopedPDULength);

  if (!bufPtr)
  {
    LOG_BEGIN(loggerModuleName, WARNING_LOG | 1);
    LOG("v3MP: Error encoding data pdu into buffer");
    LOG_END;

    return SNMPv3_MP_BUILD_ERROR;
  }

  bufLength = SAFE_INT_CAST(bufPtr - buf.get_ptr());

  //  serialize scopedPDU
  maxLen = *out_length;
  scopedPDUPtr = asn1_build_scoped_pdu(scopedPDUPtr, &maxLen,
				       contextEngineID.data(),
				       contextEngineID.len(),
				       contextName.data(), contextName.len(),
				       buf.get_ptr(), bufLength);

  if (!scopedPDUPtr)
  {
    LOG_BEGIN(loggerModuleName, WARNING_LOG | 1);
    LOG("v3MP: Error encoding scoped pdu into buffer");
    LOG_END;

    return SNMPv3_MP_BUILD_ERROR;
  }

  scopedPDULength = SAFE_INT_CAST(scopedPDUPtr - scopedPDU.get_ptr());

  // build msgGlobalData
  unsigned char *globalDataPtr = (unsigned char *)&globalData;
  unsigned char msgFlags;
  switch (securityLevel) {
    case SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV:
      { msgFlags = 0 ; break;}
    case SNMP_SECURITY_LEVEL_AUTH_NOPRIV:
      { msgFlags = SNMPv3_AUTHFLAG; break;}
    case SNMP_SECURITY_LEVEL_AUTH_PRIV:
      { msgFlags = SNMPv3_AUTHFLAG | SNMPv3_PRIVFLAG; break;}
    default:
    {
      LOG_BEGIN(loggerModuleName, WARNING_LOG | 1);
      LOG("v3MP: Unknown security level requested, will use authPriv");
      LOG(securityLevel);
      LOG_END;

      msgFlags = SNMPv3_AUTHFLAG | SNMPv3_PRIVFLAG;
    }
  }

  if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) ||
      (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) ||
      (pdu->command == INFORM_REQ_MSG))
    msgFlags = msgFlags | SNMPv3_REPORTABLEFLAG;

  globalDataPtr = asn1_build_header_data(globalDataPtr, &globalDataLength,
					 msgID, *out_length,  // maxMessageSize
					 msgFlags, securityModel);
  if (!globalDataPtr)
  {
    LOG_BEGIN(loggerModuleName, ERROR_LOG | 1);
    LOG("v3MP: Error building header data");
    LOG_END;

    return SNMPv3_MP_BUILD_ERROR;
  }
  globalDataLength = SAFE_INT_CAST(globalDataPtr - (unsigned char *)&globalData);

  switch (securityModel) {
    case SNMP_SECURITY_MODEL_USM: {
      int use_own_engine_id = 0;
      if ((pdu->command == TRP_REQ_MSG) || (pdu->command == GET_RSP_MSG) ||
          (pdu->command == REPORT_MSG)  || (pdu->command == TRP2_REQ_MSG)) {
        use_own_engine_id = 1;
      }

      rc = usm->generate_msg(globalData, globalDataLength, *out_length,
                             (use_own_engine_id ?
                                        own_engine_id_oct : securityEngineID),
                             securityName, securityLevel,
                             scopedPDU.get_ptr(), scopedPDULength,
                             securityStateReference, packet, out_length);

      if ( rc == SNMPv3_USM_OK ) {
        // build cache
        if (!((pdu->command == TRP_REQ_MSG) || (pdu->command == GET_RSP_MSG) ||
              (pdu->command == REPORT_MSG) || (pdu->command == TRP2_REQ_MSG)))
          cache.add_entry(msgID, pdu->reqid, securityEngineID,
                          securityModel, securityName, securityLevel,
                          contextEngineID, contextName, securityStateReference,
                          SNMPv3_MP_OK, CACHE_LOCAL_REQ);

	LOG_BEGIN(loggerModuleName, INFO_LOG | 3);
	LOG("v3MP: Message built OK");
	LOG_END;

        return SNMPv3_MP_OK;
      }
      else
      {
	LOG_BEGIN(loggerModuleName, WARNING_LOG | 1);
	LOG("v3MP: Returning error for building message");
	LOG(rc);
	LOG_END;

        return rc;
      }
    }
    default:
    {
      LOG_BEGIN(loggerModuleName, WARNING_LOG | 1);
      LOG("v3MP: Should build message with unsupported securityModel");
      LOG(securityModel);
      LOG_END;

      return SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL;
    }
  }
}