/*_############################################################################
_##
_## usm_v3.cpp
_##
_## SNMP++v3.2.22
_## -----------------------------------------------
_## Copyright (c) 2001-2007 Jochen Katz, Frank Fock
_##
_## This software is based on SNMP++2.6 from Hewlett Packard:
_##
_## Copyright (c) 1996
_## Hewlett-Packard Company
_##
_## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
_## Permission to use, copy, modify, distribute and/or sell this software
_## and/or its documentation is hereby granted without fee. User agrees
_## to display the above copyright notice and this license notice in all
_## copies of the software and any documentation of the software. User
_## agrees to assume all liability for the use of the software;
_## Hewlett-Packard and Jochen Katz make no representations about the
_## suitability of this software for any purpose. It is provided
_## "AS-IS" without warranty of any kind, either express or implied. User
_## hereby grants a royalty-free license to any and all derivatives based
_## upon this software code base.
_##
_## Stuttgart, Germany, Wed May 2 23:22:30 CEST 2007
_##
_##########################################################################*/
char usm_v3_cpp_version[]="@(#) SNMP++ $Id: usm_v3.cpp 290 2007-04-20 17:18:25Z katz $";
#ifdef _AIX
#include <unistd.h>
#endif
#ifdef __MINGW32__
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "config_snmp_pp.h"
#ifdef _SNMPv3
#include "v3.h"
#include "usm_v3.h"
#include "auth_priv.h"
#include "reentrant.h"
#include "mp_v3.h"
#include "asn1.h"
#include "vb.h"
#include "pdu.h"
#include "log.h"
#ifdef SNMP_PP_NAMESPACE
namespace Snmp_pp {
#endif
// Use locking on access methods in an multithreading enviroment.
#ifdef _THREADS
#define BEGIN_REENTRANT_CODE_BLOCK SnmpSynchronize auto_lock(*this)
#define BEGIN_REENTRANT_CODE_BLOCK_CONST \
SnmpSynchronize auto_lock(*(PP_CONST_CAST(SnmpSynchronized*, this)))
#define BEGIN_AUTO_LOCK(obj) SnmpSynchronize auto_lock(*obj)
#else
#define BEGIN_REENTRANT_CODE_BLOCK
#define BEGIN_REENTRANT_CODE_BLOCK_CONST
#define BEGIN_AUTO_LOCK(obj)
#endif
#ifndef min
#define min(a,b) ( (a) < (b) ? (a) : (b) )
#endif
#define MAX_LINE_LEN 2048 // Max line length in usm user files
// structure for key update
struct UsmKeyUpdate
{
OctetStr engineID;
OctetStr securityName;
OctetStr newPassword;
OctetStr newKey;
int type;
};
/* ------------------------- UsmTimeTable --------------------------*/
/**
* This class provides a table for the time values (engine boots and
* engine time) for snmp entities that are identified through their
* engine id.
*
* @author Jochen Katz
*/
class USMTimeTable : public SnmpSynchronized
{
public:
/**
* Initialize the usmTimeTable.
*
* The usmTimeTable stores for each known engineID the engineBoots
* and the difference to the local system time
*
* @param owner - Pointer to the USM object that created this table
* @param engine_boots - The new value for the snmpEngineBoots counter
* @param result - OUT: Result of the creation of the table
*/
USMTimeTable(const USM *owner, const unsigned int engine_boots, int &result);
~USMTimeTable();
/**
* Add a new entry to the usmTimeTable. The caller is responsible for
* not adding an engineID twice.
*
* @param engine_id - The engineID of the SNMP entity
* @param engine_boots - The engine boot counter
* @param engine_time - The engine time
*
* @return - SNMPv3_USM_ERROR (no memory) or SNMPv3_USM_OK
*/
int add_entry(const OctetStr &engine_id,
const long int engine_boots, const long int engine_time);
/**
* Delete this engine id from the table.
*
* @param engine_id - The engineID of the SNMP entity
*
* @return - SNMPv3_USM_ERROR (no memory) or SNMPv3_USM_OK
*/
int delete_entry(const OctetStr &engine_id);
/**
* Return engineBoots and engineTime for a given engineID
*
* @param engine_id - The engineID of the SNMP entity
* @param engine_boots - OUT: boot counter (0 if not found)
* @param engine_time - OUT: engine time (0 if not found)
*
* @return - SNMPv3_USM_ERROR (not initialized),
* SNMPv3_USM_OK (entry found, values are filled)
* SNMPv3_USM_UNKNOWN_ENGINEID ( not found)
*/
int get_time(const OctetStr &engine_id,
long int &engine_boots, long int &engine_time);
/**
* Return the engineBoots and engineTime of this snmp entity.
*
* @param engine_boots - OUT: boot counter (0 if not found)
* @param engine_time - OUT: engine time (0 if not found)
*
* @return - SNMPv3_USM_ERROR (not initialized),
* SNMPv3_USM_OK (entry found, values are filled)
*/
int get_local_time(long int &engine_boots, long int &engine_time);
/**
* Return the engineBoots value of this snmp entity.
*
* @return - engine_boots value if initialized, 0 else
*/
unsigned long get_local_boots()
{ return (table ? table[0].engine_boots : 0); };
/**
* Return the engineTime value of this snmp entity.
*
* @return - engine_time value if initialized, 0 else
*/
unsigned long get_local_time();
/**
* Check if the given values for engineBoots and engineTime are
* in the time window. If the time values are ok, the entry in
* the usmTimeTable is updated with the given time values.
*
* @param engine_id - The engineID of the SNMP entity
* @param engine_boots - The boot counter
* @param engine_time - The engine time
*
* @return - SNMPv3_USM_ERROR (not initialized),
* SNMPv3_USM_NOT_IN_TIME_WINDOW,
* SNMPv3_USM_OK (time ok),
* SNMPv3_USM_UNKNOWN_ENGINEID
*/
int check_time(const OctetStr &engine_id,
const long int engine_boots, const long int engine_time);
/**
* Check if the given engineID is known: If the USM is in
* the discovery mode, all engineIDs are accepted and entries
* in the timeTable are created.
*
* @param engine_id - engine id to check
*
* @return - SNMPv3_USM_ERROR (not found and no discovery)
* SNMPv3_USM_OK (found or discovery set)
*/
int check_engine_id(const OctetStr &engine_id);
private:
struct Entry_T
{
unsigned char engine_id[MAXLENGTH_ENGINEID];
int engine_id_len;
long int engine_boots;
long int time_diff;
long int latest_received_time;
};
struct Entry_T *table; ///< Array of entries
const USM *usm; ///< Pointer to the USM, this table belongs to
int max_entries; ///< the maximum number of entries
int entries; ///< the current amount of entries
};
/* ------------------------- UsmUserNameTable ----------------------*/
/**
* This class holds USM users with PASSWORDS.
*
* Whenever the USM has to process a message of a user that is not
* found in the USMUserTable, this table is queried for the
* properties of the user. If the user is found, a localized entry
* for the USMUserTable is created and used for processing the message.
*/
class USMUserNameTable : public SnmpSynchronized
{
public:
USMUserNameTable(int &result);
~USMUserNameTable();
/**
* Add a new user to the usmUserNameTable. If the userName is already
* known, the old entry is replaced.
*
* It is not recommended to add users with userName != securityName.
*
* @param user_name - Unique userName
* @param security_name - Unique securityName
* @param auth_proto - Possible values are:
* SNMP_AUTHPROTOCOL_NONE,
* SNMP_AUTHPROTOCOL_HMACMD5,
* SNMP_AUTHPROTOCOL_HMACSHA
* @param priv_proto - Possible values are:
* SNMP_PRIVPROTOCOL_NONE,
*