usm_v3.cpp
上传用户:ets1996
上传日期:2014-09-30
资源大小:353k
文件大小:126k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  usm_v3.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8.   _##
  9.   _##  This software is based on SNMP++2.6 from Hewlett Packard:
  10.   _##  
  11.   _##    Copyright (c) 1996
  12.   _##    Hewlett-Packard Company
  13.   _##  
  14.   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  15.   _##  Permission to use, copy, modify, distribute and/or sell this software 
  16.   _##  and/or its documentation is hereby granted without fee. User agrees 
  17.   _##  to display the above copyright notice and this license notice in all 
  18.   _##  copies of the software and any documentation of the software. User 
  19.   _##  agrees to assume all liability for the use of the software; 
  20.   _##  Hewlett-Packard and Jochen Katz make no representations about the 
  21.   _##  suitability of this software for any purpose. It is provided 
  22.   _##  "AS-IS" without warranty of any kind, either express or implied. User 
  23.   _##  hereby grants a royalty-free license to any and all derivatives based
  24.   _##  upon this software code base. 
  25.   _##  
  26.   _##  Stuttgart, Germany, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. char usm_v3_cpp_version[]="@(#) SNMP++ $Id: usm_v3.cpp 290 2007-04-20 17:18:25Z katz $";
  30. #ifdef _AIX
  31. #include <unistd.h>
  32. #endif
  33. #ifdef __MINGW32__
  34. #include <io.h>
  35. #endif
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <time.h>
  40. #include "snmp_pp/config_snmp_pp.h"
  41. #ifdef _SNMPv3
  42. #include "snmp_pp/v3.h"
  43. #include "snmp_pp/usm_v3.h"
  44. #include "snmp_pp/auth_priv.h"
  45. #include "snmp_pp/reentrant.h"
  46. #include "snmp_pp/mp_v3.h"
  47. #include "snmp_pp/asn1.h"
  48. #include "snmp_pp/vb.h"
  49. #include "snmp_pp/pdu.h"
  50. #include "snmp_pp/log.h"
  51. #ifdef SNMP_PP_NAMESPACE
  52. namespace Snmp_pp {
  53. #endif
  54. // Use locking on access methods in an multithreading enviroment.
  55. #ifdef _THREADS
  56. #define BEGIN_REENTRANT_CODE_BLOCK SnmpSynchronize auto_lock(*this)
  57. #define BEGIN_REENTRANT_CODE_BLOCK_CONST  
  58.           SnmpSynchronize auto_lock(*(PP_CONST_CAST(SnmpSynchronized*, this)))
  59. #define BEGIN_AUTO_LOCK(obj) SnmpSynchronize auto_lock(*obj)
  60. #else
  61. #define BEGIN_REENTRANT_CODE_BLOCK
  62. #define BEGIN_REENTRANT_CODE_BLOCK_CONST
  63. #define BEGIN_AUTO_LOCK(obj)
  64. #endif
  65. #ifndef min
  66. #define min(a,b) ( (a) < (b) ? (a) : (b) )
  67. #endif
  68. #define MAX_LINE_LEN 2048  // Max line length in usm user files
  69. // structure for key update
  70. struct UsmKeyUpdate
  71. {
  72.   OctetStr engineID;
  73.   OctetStr securityName;
  74.   OctetStr newPassword;
  75.   OctetStr newKey;
  76.   int type;
  77. };
  78. /* ------------------------- UsmTimeTable --------------------------*/
  79. /**
  80.  * This class provides a table for the time values (engine boots and
  81.  * engine time) for snmp entities that are identified through their
  82.  * engine id.
  83.  *
  84.  * @author Jochen Katz
  85.  */
  86. class USMTimeTable : public SnmpSynchronized
  87. {
  88. public:
  89.   /**
  90.    * Initialize the usmTimeTable.
  91.    *
  92.    * The usmTimeTable stores for each known engineID the engineBoots
  93.    * and the difference to the local system time
  94.    *
  95.    * @param owner        - Pointer to the USM object that created this table
  96.    * @param engine_boots - The new value for the snmpEngineBoots counter
  97.    * @param result       - OUT: Result of the creation of the table
  98.    */
  99.   USMTimeTable(const USM *owner, const unsigned int engine_boots, int &result);
  100.   ~USMTimeTable();
  101.   /**
  102.    * Add a new entry to the usmTimeTable. The caller is responsible for
  103.    * not adding an engineID twice.
  104.    *
  105.    * @param engine_id    - The engineID of the SNMP entity
  106.    * @param engine_boots - The engine boot counter
  107.    * @param engine_time  - The engine time
  108.    *
  109.    * @return - SNMPv3_USM_ERROR (no memory) or SNMPv3_USM_OK
  110.    */
  111.   int add_entry(const OctetStr &engine_id,
  112.                 const long int engine_boots, const long int engine_time);
  113.   /**
  114.    * Delete this engine id from the table.
  115.    *
  116.    * @param engine_id    - The engineID of the SNMP entity
  117.    *
  118.    * @return - SNMPv3_USM_ERROR (no memory) or SNMPv3_USM_OK
  119.    */
  120.   int delete_entry(const OctetStr &engine_id);
  121.   /**
  122.    * Return engineBoots and engineTime for a given engineID
  123.    *
  124.    * @param engine_id    - The engineID of the SNMP entity
  125.    * @param engine_boots - OUT: boot counter (0 if not found)
  126.    * @param engine_time  - OUT: engine time (0 if not found)
  127.    *
  128.    * @return - SNMPv3_USM_ERROR (not initialized),
  129.    *           SNMPv3_USM_OK (entry found, values are filled)
  130.    *           SNMPv3_USM_UNKNOWN_ENGINEID ( not found)
  131.    */
  132.   int get_time(const OctetStr &engine_id,
  133.                long int &engine_boots, long int &engine_time);
  134.   /**
  135.    * Return the engineBoots and engineTime of this snmp entity.
  136.    *
  137.    * @param engine_boots - OUT: boot counter (0 if not found)
  138.    * @param engine_time  - OUT: engine time (0 if not found)
  139.    *
  140.    * @return - SNMPv3_USM_ERROR (not initialized),
  141.    *           SNMPv3_USM_OK (entry found, values are filled)
  142.    */
  143.   int get_local_time(long int &engine_boots, long int &engine_time);
  144.   /**
  145.    * Return the engineBoots value of this snmp entity.
  146.    *
  147.    * @return - engine_boots value if initialized, 0 else
  148.    */
  149.   unsigned long get_local_boots()
  150.     { return (table ? table[0].engine_boots : 0); };
  151.   /**
  152.    * Return the engineTime value of this snmp entity.
  153.    *
  154.    * @return - engine_time value if initialized, 0 else
  155.    */
  156.   unsigned long get_local_time();
  157.   /**
  158.    * Check if the given values for engineBoots and engineTime are
  159.    * in the time window. If the time values are ok, the entry in
  160.    * the usmTimeTable is updated with the given time values.
  161.    *
  162.    * @param engine_id    - The engineID of the SNMP entity
  163.    * @param engine_boots - The boot counter
  164.    * @param engine_time  - The engine time
  165.    *
  166.    * @return - SNMPv3_USM_ERROR (not initialized),
  167.    *           SNMPv3_USM_NOT_IN_TIME_WINDOW,
  168.    *           SNMPv3_USM_OK (time ok),
  169.    *           SNMPv3_USM_UNKNOWN_ENGINEID
  170.    */
  171.   int check_time(const OctetStr &engine_id,
  172.                  const long int engine_boots, const long int engine_time);
  173.   /**
  174.    * Check if the given engineID is known: If the USM is in
  175.    * the discovery mode, all engineIDs are accepted and entries
  176.    * in the timeTable are created.
  177.    *
  178.    * @param engine_id - engine id to check
  179.    *
  180.    * @return - SNMPv3_USM_ERROR (not found and no discovery)
  181.    *           SNMPv3_USM_OK (found or discovery set)
  182.    */
  183.   int check_engine_id(const OctetStr &engine_id);
  184. private:
  185.   struct Entry_T
  186.   {
  187.     unsigned char engine_id[MAXLENGTH_ENGINEID];
  188.     int engine_id_len;
  189.     long int engine_boots;
  190.     long int time_diff;
  191.     long int latest_received_time;
  192.   };
  193.   struct Entry_T *table; ///< Array of entries
  194.   const USM *usm;  ///< Pointer to the USM, this table belongs to
  195.   int max_entries; ///< the maximum number of entries
  196.   int entries;     ///< the current amount of entries
  197. };
  198. /* ------------------------- UsmUserNameTable ----------------------*/
  199. /**
  200.  * This class holds USM users with PASSWORDS.
  201.  *
  202.  * Whenever the USM has to process a message of a user that is not
  203.  * found in the USMUserTable, this table is queried for the
  204.  * properties of the user. If the user is found, a localized entry
  205.  * for the USMUserTable is created and used for processing the message.
  206.  */
  207. class USMUserNameTable : public SnmpSynchronized
  208. {
  209. public:
  210.   USMUserNameTable(int &result);
  211.   ~USMUserNameTable();
  212.   /**
  213.    * Add a new user to the usmUserNameTable. If the userName is already
  214.    * known, the old entry is replaced.
  215.    *
  216.    * It is not recommended to add users with userName != securityName.
  217.    *
  218.    * @param user_name     - Unique userName
  219.    * @param security_name - Unique securityName
  220.    * @param auth_proto    - Possible values are:
  221.    *                        SNMP_AUTHPROTOCOL_NONE,
  222.    *                        SNMP_AUTHPROTOCOL_HMACMD5,
  223.    *                        SNMP_AUTHPROTOCOL_HMACSHA
  224.    * @param priv_proto    - Possible values are:
  225.    *                        SNMP_PRIVPROTOCOL_NONE,
  226.    *                        SNMP_PRIVPROTOCOL_DES,
  227.    *                        SNMP_PRIVPROTOCOL_IDEA
  228.    * @param auth_pass     - Secret password for authentication
  229.    * @param priv_pass     - Secret password for privacy
  230.    *
  231.    * @return - SNMPv3_USM_OK or
  232.    *           SNMP_v3_USM_ERROR (memory error, not initialized)
  233.    */
  234.   int add_entry(const OctetStr& user_name,
  235. const OctetStr& security_name,
  236. const long int  auth_proto,
  237. const long int  priv_proto,
  238. const OctetStr& auth_pass,
  239. const OctetStr& priv_pass);
  240.   /**
  241.    * Delete all occurences of the user with the given securityName
  242.    * from the table.
  243.    *
  244.    * @param security_name - the securityName of the user
  245.    *
  246.    * @return - SNMPv3_USM_OK, SNMPv3_USM_ERROR (not initialized)
  247.    */
  248.   int delete_security_name(const OctetStr& security_name);
  249.   /**
  250.    * Get the entry with the given securityName from the usmUserNameTable
  251.    *
  252.    * @note Use lock() and unlock() for thread synchronizytion.
  253.    *
  254.    * @param security_name     -
  255.    *
  256.    * @return - pointer to the struct or NULL (no need to delete anything)
  257.    */
  258.   const struct UsmUserNameTableEntry* get_entry(const OctetStr &security_name);
  259.   /**
  260.    * Get a clone of the entry with the given securityName from the usmUserNameTable
  261.    *
  262.    * @note call delete_cloned_entry() with the retruned pointer.
  263.    *
  264.    * @param security_name     -
  265.    *
  266.    * @return - pointer to the struct or NULL
  267.    */
  268.   struct UsmUserNameTableEntry* get_cloned_entry(const OctetStr &security_name);
  269.   /**
  270.    * Deletes a entry created through get_cloned_entry().
  271.    *
  272.    * @param entry     -
  273.    */
  274.   void delete_cloned_entry(struct UsmUserNameTableEntry* &entry);
  275.   /**
  276.    * Get the securityName from a userName
  277.    *
  278.    * @param user_name         -
  279.    * @param user_name_len     -
  280.    * @param security_name     - Buffer for the securityName
  281.    *
  282.    * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
  283.    *           SNMPv3_USM_OK
  284.    */
  285.   int get_security_name(const unsigned char *user_name,
  286. const long int user_name_len,
  287. OctetStr &security_name);
  288.   /**
  289.    * Get the userName from a securityName
  290.    *
  291.    * @param user_name         - Buffer for the userName
  292.    * @param user_name_len     - Has to be set to the max length of the
  293.    *                            buffer. Is set to the length of the found
  294.    *                            securityName or to 0 if not found.
  295.    * @param security_name     -
  296.    * @param security_name_len -
  297.    *
  298.    * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
  299.    *           SNMPv3_USM_OK
  300.    */
  301.   int get_user_name(unsigned char *user_name, long int *user_name_len,
  302.     const unsigned char *security_name,
  303.     const long int security_name_len);
  304.   /**
  305.    * Save all entries into a file.
  306.    */
  307.   int save_to_file(const char *name, AuthPriv *ap);
  308.   /**
  309.    * Load the table from a file.
  310.    */
  311.   int load_from_file(const char *name, AuthPriv *ap);
  312.   const UsmUserNameTableEntry *peek_first() const
  313.     { if (entries > 0) return table; return 0; };
  314.   const UsmUserNameTableEntry *peek_next(const UsmUserNameTableEntry *e) const;
  315. private:
  316.   struct UsmUserNameTableEntry *table;
  317.   int max_entries; ///< the maximum number of entries
  318.   int entries;     ///< the current amount of entries
  319. };
  320. /* ---------------------------- UsmUserTable ------------------- */
  321. /**
  322.  * This class holds USM users with localized KEYS.
  323.  */
  324. class USMUserTable : public SnmpSynchronized
  325. {
  326. public:
  327.   USMUserTable(int &result);
  328.   ~USMUserTable();
  329.   /**
  330.    * Get the number of valid entries in the table.
  331.    *
  332.    * @return - number of entries
  333.    */
  334.   int size() const { return entries; };
  335.   /**
  336.    * Get the userName from a securityName
  337.    *
  338.    * @param user_name     - Buffer for the userName
  339.    * @param user_name_len - Has to be set to the max length of the
  340.    *                        buffer. Is set to the length of the found
  341.    *                        securityName or to 0 if not found.
  342.    * @param sec_name      -
  343.    * @param sec_name_len  -
  344.    *
  345.    * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
  346.    *           SNMPv3_USM_OK
  347.    */
  348.   int get_user_name(unsigned char *user_name, long int *user_name_len,
  349.                     const unsigned char *sec_name, const long sec_name_len);
  350.   /**
  351.    * Get the sec_name from a userName
  352.    *
  353.    * @param user_name       -
  354.    * @param user_name_len   -
  355.    * @param sec_name        - Object for the security name
  356.    *
  357.    * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
  358.    *           SNMPv3_USM_OK
  359.    */
  360.   int get_security_name(const unsigned char *user_name,
  361.                         const long user_name_len,
  362.                         OctetStr &sec_name);
  363.   /**
  364.    * Delete all entries of this user from the usmUserTable
  365.    *
  366.    * @param user_name - The userName that should be deleted
  367.    *
  368.    * @return - SNMPv3_USM_ERROR (not initialized),
  369.    *           SNMPv3_USM_OK (user deleted or not in table)
  370.    */
  371.   int delete_entries(const OctetStr& user_name);
  372.   /**
  373.    * Delete all entries with this engine id from the table.
  374.    *
  375.    * @param engine id - The engine id
  376.    *
  377.    * @return - SNMPv3_USM_ERROR (not initialized),
  378.    *           SNMPv3_USM_OK (user deleted or not in table)
  379.    */
  380.   int delete_engine_id(const OctetStr& engine_id);
  381.   /**
  382.    * Delete the entry with the given userName and engineID
  383.    * from the usmUserTable
  384.    *
  385.    * @param engine_id  - The engine id
  386.    * @param user_name - The userName that should be deleted
  387.    *
  388.    * @return - SNMPv3_USM_ERROR (not initialized),
  389.    *           SNMPv3_USM_OK (user deleted or not in table)
  390.    */
  391.   int delete_entry(const OctetStr& engine_id, const OctetStr& user_name);
  392.   /**
  393.    * Protected (for agent++):
  394.    *
  395.    * Get the user at the specified position of the usmUserTable.
  396.    *
  397.    * @note Use lock() and unlock() for thread synchronization.
  398.    *
  399.    * @param number - get the entry at position number (1...)
  400.    *
  401.    * @return - a pointer to the structure or NULL if number is out
  402.    *           of range (no need to delete anything)
  403.    */
  404.   const struct UsmUserTableEntry *get_entry(const int number);
  405.   /**
  406.    * Get a user of the usmUserTable.
  407.    *
  408.    * @note Use lock() and unlock() for thread synchronization.
  409.    *
  410.    * @param engine_id - Get a user for this engine id
  411.    * @param sec_name  - Get the user with this security name
  412.    *
  413.    * @return - a pointer to the structure or NULL if the user is not
  414.    *           found (no need to delete anything)
  415.    */
  416.   const struct UsmUserTableEntry *get_entry(const OctetStr &engine_id,
  417.     const OctetStr &sec_name);
  418.   /**
  419.    * Get a user of the usmUserTable.
  420.    *
  421.    * @note call delete_cloned_entry() with the retruned pointer.
  422.    *
  423.    * @param engine_id - Get a user for this engine id
  424.    * @param sec_name  - Get the user with this security name
  425.    *
  426.    * @return - a pointer to the structure or NULL if the user is not
  427.    *           found
  428.    */
  429.   struct UsmUserTableEntry *get_cloned_entry(const OctetStr &engine_id,
  430.      const OctetStr &sec_name);
  431.   /**
  432.    * Deletes a entry created through get_cloned_entry().
  433.    *
  434.    * @param entry     -
  435.    */
  436.   void delete_cloned_entry(struct UsmUserTableEntry* &entry);
  437.   /**
  438.    * Get a user of the usmUserTable.
  439.    *
  440.    * There could be more than one entry with the given
  441.    * sec_name. Always the first entry that is found is returned.
  442.    *
  443.    * @note Use lock() and unlock() for thread synchronization.
  444.    *
  445.    * @param sec_name - security name to search for
  446.    *
  447.    * @return - a pointer to the structure or NULL if the user is not
  448.    *           found (no need to delete anything)
  449.    */
  450.   const struct UsmUserTableEntry *get_entry(const OctetStr &sec_name);
  451.   /**
  452.    * Public:
  453.    *
  454.    * Add or replace a user in the usmUserTable. The usmUserTable stores
  455.    * users with their localized keys.
  456.    *
  457.    * @param engine_id     - The engine_id, the key was localized with
  458.    * @param user_name     - The name of the user (in the USM)
  459.    * @param sec_name      - The security name of the user, this name
  460.    *                                is the same for all securityModels
  461.    * @param auth_proto    - Possible values are:
  462.    *                                SNMP_AUTHPROTOCOL_NONE,
  463.    *                                SNMP_AUTHPROTOCOL_HMACMD5,
  464.    *                                SNMP_AUTHPROTOCOL_HMACSHA
  465.    * @param auth_key      - The key used for authentications
  466.    * @param priv_proto    - Possible values are:
  467.    *                                SNMP_PRIVPROTOCOL_NONE,
  468.    *                                SNMP_PRIVPROTOCOL_DES,
  469.    *                                SNMP_PRIVPROTOCOL_IDEA
  470.    * @param priv_key      - The key used for privacy
  471.    *
  472.    * @return - SNMPv3_USM_OK
  473.    *           SNMP_v3_USM_ERROR (not initialized, no memory)
  474.    */
  475.   int add_entry(const OctetStr &engine_id,
  476. const OctetStr &user_name,  const OctetStr &sec_name,
  477. const long int  auth_proto, const OctetStr &auth_key,
  478. const long int  priv_proto, const OctetStr &priv_key);
  479.   /**
  480.    * Replace a localized key of the user and engine_id in the
  481.    * usmUserTable.
  482.    *
  483.    * @param user_name     - The name of the user in the USM
  484.    * @param engine_id     - Change the localized key for the SNMP
  485.    *                        entity with this engine_id
  486.    * @param new_key       - The new key
  487.    * @param key_type      - AUTHKEY, OWNAUTHKEY, PRIVKEY or OWNPRIVKEY
  488.    *
  489.    * @return - SNMPv3_USM_ERROR (no such entry or not initialized),
  490.    *           SNMPv3_USM_OK
  491.    */
  492.   int update_key(const OctetStr &user_name,
  493.                  const OctetStr &engine_id,
  494.                  const OctetStr &new_key,
  495.                  const int key_type);
  496.   /**
  497.    * Save all entries into a file.
  498.    */
  499.   int save_to_file(const char *name, AuthPriv *ap);
  500.   /**
  501.    * Load the table from a file.
  502.    */
  503.   int load_from_file(const char *name, AuthPriv *ap);
  504.   const UsmUserTableEntry *peek_first() const
  505.     { if (entries > 0) return table; return 0; };
  506.   const UsmUserTableEntry *peek_next(const UsmUserTableEntry *e) const;
  507. private:
  508.   void delete_entry(const int nr);
  509.   struct UsmUserTableEntry *table;
  510.   int max_entries; ///< the maximum number of entries
  511.   int entries;     ///< the current amount of entries
  512. };
  513. struct UsmSecurityParameters {
  514.   unsigned char  msgAuthoritativeEngineID[MAXLENGTH_ENGINEID];
  515.   long int       msgAuthoritativeEngineIDLength;
  516.   long int       msgAuthoritativeEngineBoots;
  517.   long int       msgAuthoritativeEngineTime;
  518.   unsigned char  msgUserName[MAXLEN_USMUSERNAME];
  519.   long int       msgUserNameLength;
  520.   unsigned char *msgAuthenticationParameters;
  521.   long int       msgAuthenticationParametersLength;
  522.   unsigned char *msgPrivacyParameters;
  523.   unsigned int   msgPrivacyParametersLength;
  524. };
  525. struct SecurityStateReference
  526. {
  527.   unsigned char  msgUserName[MAXLEN_USMUSERNAME]; int msgUserNameLength;
  528.   unsigned char *securityName;                    int securityNameLength;
  529.   unsigned char *securityEngineID;                int securityEngineIDLength;
  530.   int authProtocol;
  531.   unsigned char* authKey;                         int authKeyLength;
  532.   int privProtocol;
  533.   unsigned char* privKey;                         int privKeyLength;
  534.   int securityLevel;
  535. };
  536. void USM::inc_stats_unsupported_sec_levels()
  537. {
  538.   if (usmStatsUnsupportedSecLevels == MAXUINT32)
  539.     usmStatsUnsupportedSecLevels = 0;
  540.   else
  541.     usmStatsUnsupportedSecLevels++;
  542. }
  543. void USM::inc_stats_not_in_time_windows()
  544. {
  545.   if (usmStatsNotInTimeWindows == MAXUINT32)
  546.     usmStatsNotInTimeWindows = 0;
  547.   else
  548.     usmStatsNotInTimeWindows++;
  549. }
  550. void USM::inc_stats_unknown_user_names()
  551. {
  552.   if (usmStatsUnknownUserNames == MAXUINT32)
  553.     usmStatsUnknownUserNames = 0;
  554.   else
  555.     usmStatsUnknownUserNames++;
  556. }
  557. void USM::inc_stats_unknown_engine_ids()
  558. {
  559.   if (usmStatsUnknownEngineIDs == MAXUINT32)
  560.     usmStatsUnknownEngineIDs = 0;
  561.   else
  562.     usmStatsUnknownEngineIDs++;
  563. }
  564. void USM::inc_stats_wrong_digests()
  565. {
  566.   if (usmStatsWrongDigests == MAXUINT32)
  567.     usmStatsWrongDigests = 0;
  568.   else
  569.     usmStatsWrongDigests++;
  570. }
  571. void USM::inc_stats_decryption_errors()
  572. {
  573.   if (usmStatsDecryptionErrors == MAXUINT32)
  574.     usmStatsDecryptionErrors = 0;
  575.   else
  576.     usmStatsDecryptionErrors++;
  577. }
  578. void USM::delete_sec_state_reference(struct SecurityStateReference *ssr)
  579. {
  580.   if (ssr)
  581.   {
  582.     ssr->msgUserName[0] = 0;
  583.     if (ssr->securityName) delete [] ssr->securityName;
  584.     if (ssr->securityEngineID) delete [] ssr->securityEngineID;
  585.     if (ssr->authKey)
  586.     {
  587.       memset(ssr->authKey, 0, ssr->authKeyLength);
  588.       delete [] ssr->authKey;
  589.     }
  590.     if (ssr->privKey)
  591.     {
  592.       memset(ssr->privKey, 0, ssr->privKeyLength);
  593.       delete [] ssr->privKey;
  594.     }
  595.   }
  596.   delete ssr;
  597. }
  598. struct SecurityStateReference *USM::get_new_sec_state_reference()
  599. {
  600.   struct SecurityStateReference *res = new SecurityStateReference;
  601.   if (!res)
  602.     return NULL;
  603.   memset(res, 0, sizeof(struct SecurityStateReference));
  604.   return res;
  605. }
  606. USM::USM(unsigned int engine_boots, const OctetStr &engine_id,
  607.  const v3MP *v3_mp,
  608.  unsigned int *msgID, int &result)
  609.   : local_snmp_engine_id (engine_id),
  610.     v3mp (v3_mp),
  611.     discovery_mode (TRUE),
  612.     usmStatsUnsupportedSecLevels (0),
  613.     usmStatsNotInTimeWindows     (0),
  614.     usmStatsUnknownUserNames     (0),
  615.     usmStatsUnknownEngineIDs     (0),
  616.     usmStatsWrongDigests         (0),
  617.     usmStatsDecryptionErrors     (0),
  618.     usm_add_user_cb (0)
  619. {
  620.   auth_priv = new AuthPriv(result);
  621.   if (result != SNMPv3_USM_OK)
  622.     return;
  623.   auth_priv->add_default_modules();
  624.   usm_user_name_table = new USMUserNameTable(result);
  625.   if (result != SNMPv3_USM_OK)
  626.     return;
  627.   usm_user_table = new USMUserTable(result);
  628.   if (result != SNMPv3_USM_OK)
  629.     return;
  630. #ifdef _TEST
  631.   printf(" Testing DES:n");
  632.   PrivDES pd;
  633.   pp_uint64 testsalt=0xbabec0de;
  634.   pd.set_salt(&testsalt);
  635.   const char *desplaintext[10];
  636.   desplaintext[0] = "abcdefghijklmnopqrstuvwxyz123456";
  637.   desplaintext[1] = "abcdefghijklmnopqrstuvwxyz1234567";
  638.   desplaintext[2] = "abcdefghijklmnopqrstuvwxyz12345678";
  639.   desplaintext[3] = "abcdefghijklmnopqrstuvwxyz123456789";
  640.   desplaintext[4] = "abcdefghijklmnopqrstuvwxyz123456789A";
  641.   desplaintext[5] = "abcdefghijklmnopqrstuvwxyz123456789AB";
  642.   desplaintext[6] = "abcdefghijklmnopqrstuvwxyz123456789ABC";
  643.   desplaintext[7] = "abcdefghijklmnopqrstuvwxyz123456789ABCD";
  644.   desplaintext[8] = "abcdefghijklmnopqrstuvwxyz123456789ABCDE";
  645.   desplaintext[9] = "abcdefghijklmnopqrstuvwxyz123456789ABCDEF";
  646.   
  647.   unsigned char desencrypted[80];
  648.   unsigned char desdecrypted[80];
  649.   unsigned char desprivparams[8];
  650.   unsigned char deskey[17] = "illegal_des_key!";
  651.   for (int i=0; i<9; i++)
  652.   {
  653.       unsigned int encrypt_len = 80;
  654.       unsigned int decrypt_len = 80;
  655.       unsigned int desprivparamslen = 8;
  656.       memset(desencrypted, 'x', 80);
  657.       memset(desdecrypted, 'y', 80);
  658.       debughexcprintf(1, "Plaintext", (unsigned char*)desplaintext[i],
  659.       strlen(desplaintext[i]));
  660.       int res = pd.encrypt(deskey, 16,
  661.    (unsigned char*)desplaintext[i],
  662.    strlen(desplaintext[i]),
  663.    desencrypted, &encrypt_len,
  664.    desprivparams, &desprivparamslen,
  665.    0x2340abcd, 0);
  666.       printf("%d: Result of encryption is %dn", i, res);
  667.       debughexcprintf(1, "Encrypted", desencrypted, encrypt_len);
  668.       res = pd.decrypt(deskey, 16,
  669.        desencrypted, encrypt_len,
  670.        desdecrypted, &decrypt_len,
  671.        desprivparams, desprivparamslen,
  672.        0x2340abcd, 0);
  673.       printf("%d: Result of decryption is %dn", i, res);
  674.       debughexcprintf(1, "Decrypted", desdecrypted, decrypt_len);
  675.       if (memcmp(desplaintext[i], desdecrypted, strlen(desplaintext[i])))
  676.   printf("n********* FAILED **********n");
  677.       else
  678.   printf("nOKn");
  679.   }
  680. #if 0
  681.   printf(" Testing SHA:n");
  682.   // test password2key-algor:
  683.   unsigned char keysha[50];
  684.   auth_priv->password_to_key_auth(...(unsigned char*)"maplesyrup",10,
  685.                      (unsigned char*)"2",12,keysha);
  686.   printf("Output of PasswordToKey-algorithm for SHA:n");
  687.   for (int i=0; i< 20; i++) {
  688.     printf("%02X ", keysha[i]);
  689.     if ((i+1)%4==0) printf(" ");
  690.     if ((i+1)%16==0) printf("n");
  691.   }
  692.   printf("nOutput should be (draft-ietf-snmpv3-usm-v2-02.txt):n");
  693.   printf("66 95 fe bc  92 88 e3 62  82 23 5f c7  15 1f 12 84n97 b3 8f 3fn");
  694.   printf("nTesting MD5:n");
  695.   unsigned char keymd5[50];
  696.   apPasswordToKeyMD5((unsigned char*)"maplesyrup",10,
  697.                      (unsigned char*)"2",12,keymd5);
  698.   printf("Output of PasswordToKey-algorithm for MD5:n");
  699.   for (int i=0; i< 16; i++) {
  700.     printf("%02X ", keymd5[i]);
  701.     if ((i+1)%4==0) printf(" ");
  702.     if ((i+1)%16==0) printf("n");
  703.   }
  704.   printf("Output ahould be (draft-ietf-snmpv3-usm-v2-02.txt):n");
  705.   printf("52 6f 5e ed  9f cc e2 6f  89 64 c2 93  07 87 d8 2bn");
  706.   printf("nTesting IDEA:n");
  707.   unsigned char source[35] = "Hallo, das ist ein test!", encrypted[35], decrypted[35], params[8];
  708.   int len_encrypted = 35, len_decrypted = 35;
  709.   apIDEAEncryptData((unsigned char*)"1234567890abcdef",
  710.                     source, 25, encrypted, &len_encrypted, params);
  711.   apIDEADecryptData((unsigned char*)"1234567890abcdef",
  712.                     encrypted, len_encrypted,
  713.                      decrypted, &len_decrypted, params);
  714.   printf("params:n");
  715.   for (int i=0; i< 8; i++) {
  716.     printf("%02X ", params[i]);
  717.     if ((i+1)%4==0) printf(" ");
  718.     if ((i+1)%16==0) printf("n");
  719.   }
  720.   printf("nsource:n");
  721.   for (int i=0; i< 25; i++) {
  722.     printf("%02X ", source[i]);
  723.     if ((i+1)%4==0) printf(" ");
  724.     if ((i+1)%16==0) printf("n");
  725.   }
  726.   printf("n");
  727.   printf("encrypted:n");
  728.   for (int i=0; i< 25; i++) {
  729.     printf("%02X ", encrypted[i]);
  730.     if ((i+1)%4==0) printf(" ");
  731.     if ((i+1)%16==0) printf("n");
  732.   }
  733.   printf("n");
  734.   printf("decrypted:n");
  735.   for (int i=0; i< 25; i++) {
  736.     printf("%02X ", decrypted[i]);
  737.     if ((i+1)%4==0) printf(" ");
  738.     if ((i+1)%16==0) printf("n");
  739.   }
  740.   printf("n");
  741.   for (int i=0; i<25; i++)
  742.     if (source[i]!=decrypted[i]) {
  743.       printf("n*** source != decrypted ****nn");
  744.       break;
  745.     }
  746.   // test keyUpdate md5
  747.   printf("n Test KeyUpdate Algorithm:n");
  748.   printf("Test MD5:n");
  749.   OctetStr oldKey = OctetStr(keymd5, SNMPv3_AP_OUTPUT_LENGTH_MD5);
  750.   unsigned char newkeymd5[50];
  751.   apPasswordToKeyMD5((unsigned char*)"newsyrup",8,
  752.                      (unsigned char*)"2",12,newkeymd5);
  753.   printf("Output of PasswordToKey-algorithm for MD5:n");
  754.   for (int i=0; i< 16; i++) {
  755.     printf("%02X ", newkeymd5[i]);
  756.     if ((i+1)%4==0) printf(" ");
  757.     if ((i+1)%16==0) printf("n");
  758.   }
  759.   printf("Output ahould be (draft-ietf-snmpv3-usm-v2-02.txt):n");
  760.   printf("87 02 1d 7b  d9 d1 01 ba  05 ea 6e 3b  f9 d9 bd 4an");
  761.   OctetStr result;
  762.   apNewKey(oldKey, OctetStr(newkeymd5, SNMPv3_AP_OUTPUT_LENGTH_MD5),
  763.             result, SNMPv3_usmHMACMD5AuthProtocol);
  764.   // test keyUpdate sha (auth)
  765.   printf("nTest SHA for authPassword:n");
  766.   oldKey = OctetStr(keysha, SNMPv3_AP_OUTPUT_LENGTH_SHA);
  767.   unsigned char newkeysha[50];
  768.   apPasswordToKeySHA((unsigned char*)"newsyrup",8,
  769.                      (unsigned char*)"2",12,newkeysha);
  770.   printf("Output of PasswordToKey-algorithm for sha:n");
  771.   for (int i=0; i< SNMPv3_AP_OUTPUT_LENGTH_SHA; i++) {
  772.     printf("%02X ", newkeysha[i]);
  773.     if ((i+1)%4==0) printf(" ");
  774.     if ((i+1)%16==0) printf("n");
  775.   }
  776.   printf("Output ahould be (draft-ietf-snmpv3-usm-v2-02.txt):n");
  777.   printf("78 e2 dc ce  79 d5 94 03  b5 8c 1b ba  a5 bf f4 63 n91 f1 cd 25n");
  778.   apNewKey(oldKey, OctetStr(newkeysha, SNMPv3_AP_OUTPUT_LENGTH_SHA),
  779.             result, SNMPv3_usmHMACSHAAuthProtocol);
  780.   // test keyUpdate sha (privPassword DES)
  781.   printf("nTest SHA for privPassword:n");
  782.   oldKey = OctetStr(keysha, SNMPv3_AP_OUTPUT_LENGTH_MD5);
  783.   apNewKey(oldKey, OctetStr(newkeysha, SNMPv3_AP_OUTPUT_LENGTH_MD5),
  784.             result, SNMPv3_usmHMACSHAAuthProtocol);
  785.   printf("Result should be:n");
  786.   printf("00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00n");
  787.   printf("7e f8 d8 a4  c9 cd b2 6b  47 59 1c d8  52 ff 88 b5n");
  788. #endif
  789.   /* test AES key extension algorithm */
  790.   unsigned char key_sha[SNMPv3_USM_MAX_KEY_LEN];
  791.   unsigned int key_sha_len = SNMPv3_USM_MAX_KEY_LEN;
  792.   int res = auth_priv->password_to_key_priv(
  793.     SNMP_AUTHPROTOCOL_HMACSHA,
  794.     SNMP_PRIVPROTOCOL_AES256,
  795.     (unsigned char*)"maplesyrup", 10,
  796.     (unsigned char*)"2", 12,
  797.     key_sha, &key_sha_len);
  798.   debugprintf(0, "aes key extension result %i, key_sha_len = %i.",
  799.       res, key_sha_len);
  800.   debughexcprintf(0, "key_sha", key_sha, key_sha_len);
  801.   unsigned char pt[56] = "This is a secret message, nobody is allowed to read it!";
  802.   unsigned char *plaintext = pt;
  803.   unsigned char ct[56];
  804.   unsigned char *cipher = ct;
  805.   unsigned int cipherlen = 56;
  806.   unsigned char privpar[8];
  807.   unsigned int privparlen = 8;
  808.   Priv *priv = auth_priv->get_priv(SNMP_PRIVPROTOCOL_AES256);
  809.   pp_uint64 salt = 0;
  810.   priv->set_salt(&salt);
  811.   auth_priv->encrypt_msg(SNMP_PRIVPROTOCOL_AES256,
  812.  key_sha, key_sha_len,
  813.  plaintext, 55, cipher, &cipherlen,
  814.  privpar, &privparlen,
  815.  0xdeadc0deUL, 0xbeefdedeUL);
  816.   auth_priv->decrypt_msg(SNMP_PRIVPROTOCOL_AES256,
  817.  key_sha, key_sha_len,
  818.  cipher, 55, plaintext, &cipherlen,
  819.  privpar, privparlen,
  820.  0xdeadc0deUL, 0xbeefdedeUL);
  821. #endif // _TEST
  822.   usm_time_table = new USMTimeTable(this, engine_boots, result);
  823.   if (result != SNMPv3_USM_OK)
  824.     return;
  825.   *msgID = (engine_boots & 0x7FFF) << 16;
  826. }
  827. USM::~USM()
  828. {
  829.   if (usm_time_table)
  830.     delete usm_time_table;
  831.   usm_time_table = NULL;
  832.   if (usm_user_table)
  833.     delete usm_user_table;
  834.   usm_user_table = NULL;
  835.   if (usm_user_name_table)
  836.   {
  837.     delete usm_user_name_table;
  838.     usm_user_name_table = NULL;
  839.   }
  840.   if (auth_priv)
  841.   {
  842.     delete auth_priv;
  843.     auth_priv = NULL;
  844.   }
  845. }
  846. // Delete this engine id form all USM tables (users and engine time).
  847. int USM::remove_engine_id(const OctetStr &engine_id)
  848. {
  849.   int retval1, retval2;
  850.   retval1 = usm_time_table->delete_entry(engine_id);
  851.   retval2 = usm_user_table->delete_entries(engine_id);
  852.   if ((retval1 == SNMPv3_USM_ERROR) ||
  853.       (retval2 == SNMPv3_USM_ERROR))
  854.     return SNMPv3_USM_ERROR;
  855.   return SNMPv3_USM_OK;
  856. }
  857. int USM::update_key(const unsigned char* user_name,
  858.     const long int user_name_len,
  859.     const unsigned char* engine_id,
  860.     const long int engine_id_len,
  861.     const unsigned char* new_key,
  862.     const long int new_key_len,
  863.     const int type_of_key)
  864. {
  865.   OctetStr key(new_key, new_key_len);
  866.   int res;
  867.   res = usm_user_table->update_key(OctetStr(user_name, user_name_len),
  868.    OctetStr(engine_id, engine_id_len),
  869.    key, type_of_key);
  870.   key.clear();
  871.   return res;
  872. }
  873. int USM::add_localized_user(const OctetStr &engine_id,
  874.     const OctetStr &user_name,
  875.     const OctetStr &security_name,
  876.     const long auth_protocol,
  877.     const OctetStr &auth_key,
  878.     const long priv_protocol,
  879.     const OctetStr &priv_key)
  880. {
  881.    return usm_user_table->add_entry(engine_id, user_name, security_name,
  882.                                     auth_protocol, auth_key,
  883.                                     priv_protocol, priv_key);
  884. }
  885. int USM::add_usm_user(const OctetStr& user_name,
  886.       const OctetStr& security_name,
  887.       const long int  auth_protocol,
  888.       const long int  priv_protocol,
  889.       const OctetStr& auth_password,
  890.       const OctetStr& priv_password)
  891. {
  892.   /*  delete localized entries if some exists */
  893.   delete_localized_user(user_name);
  894.   int result = usm_user_name_table->add_entry(user_name,security_name,
  895.       auth_protocol, priv_protocol,
  896.       auth_password, priv_password);
  897.   if (result != SNMPv3_USM_OK)
  898.     return result;
  899.   struct UsmUser *dummy;
  900.   dummy = get_user(local_snmp_engine_id, security_name);
  901.   if (dummy) free_user(dummy);
  902.   return SNMPv3_USM_OK;
  903. }
  904. int USM::add_usm_user(const OctetStr& user_name,
  905.       const OctetStr& security_name,
  906.       const long int  auth_protocol,
  907.       const long int  priv_protocol,
  908.       const OctetStr& auth_password,
  909.       const OctetStr& priv_password,
  910.       const OctetStr& engine_id)
  911. {
  912.   OctetStr auth_key;
  913.   OctetStr priv_key;
  914.   auth_key.set_len(SNMPv3_USM_MAX_KEY_LEN);
  915.   priv_key.set_len(SNMPv3_USM_MAX_KEY_LEN);
  916.   unsigned int auth_key_len = auth_key.len();
  917.   unsigned int priv_key_len = priv_key.len();
  918.   int res = build_localized_keys(engine_id, auth_protocol, priv_protocol,
  919.  auth_password.data(), auth_password.len(),
  920.  priv_password.data(), priv_password.len(),
  921.  auth_key.data(), &auth_key_len,
  922.  priv_key.data(), &priv_key_len);
  923.   if (res != SNMPv3_USM_OK)
  924.     return res;
  925.   auth_key.set_len(auth_key_len);
  926.   priv_key.set_len(priv_key_len);
  927.   res = usm_user_table->add_entry(engine_id, user_name, security_name,
  928.   auth_protocol, auth_key,
  929.   priv_protocol, priv_key);
  930.   auth_key.clear();
  931.   priv_key.clear();
  932.   return res;
  933. }
  934. int USM::add_usm_user(const OctetStr& security_name,
  935.       const long int  auth_protocol,
  936.       const long int  priv_protocol,
  937.       const OctetStr& auth_password,
  938.       const OctetStr& priv_password)
  939. {
  940.   // usmUserName:     UserName for UserbasedSecurityModel
  941.   // usmSecurityName: UserName for all SecurityModels
  942.   return add_usm_user(security_name, security_name,
  943.       auth_protocol, priv_protocol,
  944.       auth_password, priv_password);
  945. }
  946. int USM::delete_localized_user(const OctetStr& usmUserName)
  947. {
  948.   return usm_user_table->delete_entries(usmUserName);
  949. }
  950. int USM::delete_localized_user(const OctetStr& engine_id,
  951.        const OctetStr& user_name)
  952. {
  953.   return usm_user_table->delete_entry(engine_id, user_name);
  954. }
  955. int USM::build_localized_keys(const OctetStr      &engine_id,
  956.       const int            auth_prot,
  957.       const int            priv_prot,
  958.       const unsigned char *auth_password,
  959.       const unsigned int   auth_password_len,
  960.       const unsigned char *priv_password,
  961.       const unsigned int   priv_password_len,
  962.       unsigned char *auth_key,
  963.       unsigned int  *auth_key_len,
  964.       unsigned char *priv_key,
  965.       unsigned int  *priv_key_len)
  966. {
  967.   int res = auth_priv->password_to_key_auth(
  968.                           auth_prot, auth_password,
  969.   auth_password_len,
  970.   engine_id.data(), engine_id.len(),
  971.   auth_key, auth_key_len);
  972.   if (res != SNMPv3_USM_OK)
  973.   {
  974.     if (res == SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL)
  975.     {
  976. LOG_BEGIN(ERROR_LOG | 4);
  977. LOG("Could not generate localized key: Unsupported auth protocol");
  978. LOG(auth_prot);
  979. LOG_END;
  980.     }
  981.     else
  982.     {
  983. LOG_BEGIN(ERROR_LOG | 4);
  984. LOG("Could not generate localized auth key, error code");
  985. LOG(res);
  986. LOG_END;
  987.     }
  988.     return res;
  989.   }
  990.   res = auth_priv->password_to_key_priv(auth_prot, priv_prot, priv_password,
  991. priv_password_len,
  992. engine_id.data(), engine_id.len(),
  993. priv_key, priv_key_len);
  994.   if (res != SNMPv3_USM_OK)
  995.   {
  996.     if (res == SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL)
  997.     {
  998. LOG_BEGIN(ERROR_LOG | 4);
  999. LOG("Could not generate localized key: Unsupported priv protocol");
  1000. LOG(priv_prot);
  1001. LOG_END;
  1002.     }
  1003.     else
  1004.     {
  1005. LOG_BEGIN(ERROR_LOG | 4);
  1006. LOG("Could not generate localized priv key, error code");
  1007. LOG(res);
  1008. LOG_END;
  1009.     }
  1010.     return res;
  1011.   }
  1012.   return res; // OK
  1013. }
  1014. struct UsmUser *USM::get_user(const OctetStr &engine_id,
  1015.       const OctetStr &security_name)
  1016. {
  1017.   debugprintf(7,"USM::get_user: user (%s) engine_id (%s)",
  1018.               security_name.get_printable(),engine_id.get_printable());
  1019.   struct UsmUserNameTableEntry *name_table_entry = NULL;
  1020.   struct UsmUserTableEntry *user_table_entry = NULL;
  1021.   user_table_entry = usm_user_table->get_cloned_entry(engine_id,
  1022.       security_name);
  1023.   if (!user_table_entry)
  1024.   {
  1025.     name_table_entry = usm_user_name_table->get_cloned_entry(security_name);
  1026.     if (!name_table_entry)
  1027.     {
  1028.       const struct UsmUserTableEntry *entry;
  1029.       BEGIN_AUTO_LOCK(usm_user_table);
  1030.       entry = usm_user_table->get_entry(security_name);
  1031.       if ((entry) && (engine_id.len() == 0))
  1032.       {
  1033.         // there is a entry for this security_name in the usmUserTable
  1034.         // so return an entry for this user to do engine_id discovery
  1035.         struct UsmUser *res = new UsmUser;
  1036.         if (!res)
  1037.           return 0;
  1038.         res->engineID = 0;
  1039.         res->engineIDLength = 0;
  1040.         res->usmUserName = v3strcpy(entry->usmUserName,
  1041.     entry->usmUserNameLength);
  1042.         res->usmUserNameLength = entry->usmUserNameLength;
  1043.         res->securityName = v3strcpy(entry->usmUserSecurityName,
  1044.      entry->usmUserSecurityNameLength);
  1045.         res->securityNameLength = entry->usmUserSecurityNameLength;
  1046.         res->authProtocol = SNMPv3_usmNoAuthProtocol;
  1047.         res->authKey = 0;        res->authKeyLength = 0;
  1048.         res->privProtocol = SNMPv3_usmNoPrivProtocol;
  1049.         res->privKey = 0;        res->privKeyLength = 0;
  1050. if ((res->usmUserNameLength  && !res->usmUserName) ||
  1051.     (res->securityNameLength && !res->securityName))
  1052. {
  1053.     free_user(res);
  1054. }
  1055.         return res;
  1056.       }
  1057.       else
  1058.       {
  1059.         debugprintf(1, "USM::get_user: User unknown");
  1060.         return NULL;
  1061.       }
  1062.     }
  1063.     // here we have valid name_table_entry but not user_table_entry
  1064.     if (engine_id.len() == 0)
  1065.     {
  1066.       // do not add a user
  1067.       struct UsmUser *res = new UsmUser;
  1068.       if (!res)
  1069.       {
  1070. usm_user_name_table->delete_cloned_entry(name_table_entry);
  1071.         return 0;
  1072.       }
  1073.       res->engineID           = 0;
  1074.       res->engineIDLength     = 0;
  1075.       res->usmUserName        = v3strcpy(name_table_entry->usmUserName.data(),
  1076.  name_table_entry->usmUserName.len());
  1077.       res->usmUserNameLength  = name_table_entry->usmUserName.len();
  1078.       res->securityName       = v3strcpy(
  1079.                           name_table_entry->usmUserSecurityName.data(),
  1080.   name_table_entry->usmUserSecurityName.len());
  1081.       res->securityNameLength = name_table_entry->usmUserSecurityName.len();
  1082.       res->authProtocol       = SNMPv3_usmNoAuthProtocol;
  1083.       res->authKey            = 0;
  1084.       res->authKeyLength      = 0;
  1085.       res->privProtocol       = SNMPv3_usmNoPrivProtocol;
  1086.       res->privKey            = 0;
  1087.       res->privKeyLength      = 0;
  1088.       if ((res->usmUserNameLength  && !res->usmUserName) ||
  1089.   (res->securityNameLength && !res->securityName))
  1090.       {
  1091.   free_user(res);
  1092.       }
  1093.       usm_user_name_table->delete_cloned_entry(name_table_entry);
  1094.       return res;
  1095.     }
  1096.     else
  1097.     {
  1098.       // We can add a new user:
  1099.       unsigned char privKey[SNMPv3_USM_MAX_KEY_LEN];
  1100.       unsigned char authKey[SNMPv3_USM_MAX_KEY_LEN];
  1101.       unsigned int authKeyLength = SNMPv3_USM_MAX_KEY_LEN;
  1102.       unsigned int privKeyLength = SNMPv3_USM_MAX_KEY_LEN;
  1103.       int res = build_localized_keys(engine_id,
  1104.  name_table_entry->usmUserAuthProtocol,
  1105.  name_table_entry->usmUserPrivProtocol,
  1106.  name_table_entry->authPassword,
  1107.  name_table_entry->authPasswordLength,
  1108.  name_table_entry->privPassword,
  1109.  name_table_entry->privPasswordLength,
  1110.  authKey, &authKeyLength,
  1111.  privKey, &privKeyLength);
  1112.       if (res != SNMPv3_USM_OK)
  1113.       {
  1114. LOG_BEGIN(ERROR_LOG | 4);
  1115. LOG("Cannot add User: error code");
  1116. LOG(res);
  1117. LOG_END;
  1118. usm_user_name_table->delete_cloned_entry(name_table_entry);
  1119.         return 0;
  1120.       }
  1121.       OctetStr akey(authKey, authKeyLength);
  1122.       OctetStr pkey(privKey, privKeyLength);
  1123.       add_localized_user(
  1124.         engine_id,
  1125.         name_table_entry->usmUserName,
  1126.         name_table_entry->usmUserSecurityName,
  1127.         name_table_entry->usmUserAuthProtocol, akey,
  1128.         name_table_entry->usmUserPrivProtocol, pkey);
  1129.       if (usm_add_user_cb)
  1130.       {
  1131.         // inform agent++ about new user
  1132.         debugprintf(5, "Informing agent++ about newly created user");
  1133.         usm_add_user_cb(engine_id,
  1134.                         name_table_entry->usmUserName,
  1135.                         name_table_entry->usmUserSecurityName,
  1136.                         name_table_entry->usmUserAuthProtocol, akey,
  1137.                         name_table_entry->usmUserPrivProtocol, pkey);
  1138.       }
  1139.       akey.clear();
  1140.       pkey.clear();
  1141.       user_table_entry = usm_user_table->get_cloned_entry(engine_id,
  1142.   security_name);
  1143.       if (!user_table_entry)
  1144.       {
  1145. LOG_BEGIN(ERROR_LOG | 1);
  1146. LOG("Get of just added localized entry failed (sec name) (engine id)");
  1147. LOG(security_name.get_printable());
  1148. LOG(engine_id.get_printable());
  1149. LOG_END;
  1150. usm_user_name_table->delete_cloned_entry(name_table_entry);
  1151.         return 0;
  1152.       }
  1153.     }
  1154.     usm_user_name_table->delete_cloned_entry(name_table_entry);
  1155.   }
  1156.   struct UsmUser *res = new UsmUser;
  1157.   if (!res)
  1158.   {
  1159.     usm_user_table->delete_cloned_entry(user_table_entry);
  1160.     return 0;
  1161.   }
  1162.   res->engineID           = user_table_entry->usmUserEngineID;
  1163.   res->engineIDLength     = user_table_entry->usmUserEngineIDLength;
  1164.   res->usmUserName        = user_table_entry->usmUserName;
  1165.   res->usmUserNameLength  = user_table_entry->usmUserNameLength;
  1166.   res->securityName       = user_table_entry->usmUserSecurityName;
  1167.   res->securityNameLength = user_table_entry->usmUserSecurityNameLength;
  1168.   res->authProtocol       = user_table_entry->usmUserAuthProtocol;
  1169.   res->authKey            = user_table_entry->usmUserAuthKey;
  1170.   res->authKeyLength      = user_table_entry->usmUserAuthKeyLength;
  1171.   res->privProtocol       = user_table_entry->usmUserPrivProtocol;
  1172.   res->privKey            = user_table_entry->usmUserPrivKey;
  1173.   res->privKeyLength      = user_table_entry->usmUserPrivKeyLength;
  1174.   user_table_entry->usmUserEngineID = 0;
  1175.   user_table_entry->usmUserName = 0;
  1176.   user_table_entry->usmUserSecurityName = 0;
  1177.   user_table_entry->usmUserAuthKey = 0;
  1178.   user_table_entry->usmUserPrivKey = 0;
  1179.   usm_user_table->delete_cloned_entry(user_table_entry);
  1180.  
  1181.   return res;
  1182. }
  1183. // Free the structure returned from get_user().
  1184. void USM::free_user(struct UsmUser *&user)
  1185. {
  1186.   if (!user) return;
  1187.   if (user->engineID)     delete [] user->engineID;
  1188.   if (user->usmUserName)  delete [] user->usmUserName;
  1189.   if (user->securityName) delete [] user->securityName;
  1190.   if (user->authKey)
  1191.   {
  1192.     memset(user->authKey, 0, user->authKeyLength);
  1193.     delete [] user->authKey;
  1194.   }
  1195.   if (user->privKey)
  1196.   {
  1197.     memset(user->privKey, 0, user->privKeyLength);
  1198.     delete [] user->privKey;
  1199.   }
  1200.   delete user;
  1201.   user = 0;
  1202. }
  1203. int USM::delete_usm_user(const OctetStr& security_name)
  1204. {
  1205.   usm_user_name_table->delete_security_name(security_name);
  1206.   unsigned char username[MAXLEN_USMUSERNAME + 1];
  1207.   long int length = MAXLEN_USMUSERNAME;
  1208.   if ((get_user_name(username, &length,
  1209.      security_name.data(), security_name.len()))
  1210.       == SNMPv3_USM_OK)
  1211.     return delete_localized_user(OctetStr(username, length));
  1212.   return SNMPv3_USM_ERROR;
  1213. }
  1214. int USM::get_security_name(const unsigned char *user_name,
  1215.    const long int user_name_len,
  1216.    OctetStr &security_name)
  1217. {
  1218.   debugprintf(20,"USM::get_security_name: get  user (%s)",
  1219.               OctetStr(user_name,user_name_len).get_printable());
  1220.   int result;
  1221.   result = usm_user_name_table->get_security_name(user_name, user_name_len,
  1222.                                                   security_name);
  1223.   if (result == SNMPv3_USM_OK)
  1224.     return SNMPv3_USM_OK;
  1225.   result = usm_user_table->get_security_name(user_name, user_name_len,
  1226.                                              security_name);
  1227.   if (result == SNMPv3_USM_OK)
  1228.     return SNMPv3_USM_OK;
  1229.   debugprintf(1, "USM::get_security_name: User unknown");
  1230.   return SNMPv3_USM_ERROR;
  1231. }
  1232. int USM::get_user_name(unsigned char *user_name, long int *user_name_len,
  1233.        const unsigned char *security_name,
  1234.        const long int security_name_len)
  1235. {
  1236.   int result;
  1237.   long int  buf_len = *user_name_len;
  1238.   result = usm_user_name_table->get_user_name(user_name, user_name_len,
  1239.                                               security_name,
  1240.       security_name_len);
  1241.   if (result == SNMPv3_USM_OK)
  1242.     return SNMPv3_USM_OK;
  1243.   *user_name_len = buf_len;
  1244.   result = usm_user_table->get_user_name(user_name, user_name_len,
  1245.                                          security_name, security_name_len);
  1246.   if (result == SNMPv3_USM_OK)
  1247.     return SNMPv3_USM_OK;
  1248.   debugprintf(1, "usmGetUsmUserName: User unknown");
  1249.   return SNMPv3_USM_ERROR;
  1250. }
  1251. void USM::delete_sec_parameters( struct UsmSecurityParameters *usp)
  1252. {
  1253.   usp->msgAuthoritativeEngineID[0] = 0;
  1254.   usp->msgAuthoritativeEngineIDLength = 0;
  1255.   usp->msgAuthoritativeEngineBoots = 0;
  1256.   usp->msgAuthoritativeEngineTime = 0;
  1257.   usp->msgUserName[0] = 0;
  1258.   usp->msgUserNameLength = 0;
  1259.   if (usp->msgAuthenticationParameters) {
  1260.     delete [] usp->msgAuthenticationParameters;
  1261.     usp->msgAuthenticationParameters = NULL;
  1262.   }
  1263.   usp->msgAuthenticationParametersLength = 0;
  1264.   if (usp->msgPrivacyParameters) {
  1265.     delete [] usp->msgPrivacyParameters;
  1266.     usp->msgPrivacyParameters = NULL;
  1267.   }
  1268.   usp->msgPrivacyParametersLength = 0;
  1269. }
  1270. const struct UsmUserTableEntry *USM::get_user(int number)
  1271. {
  1272.   return usm_user_table->get_entry(number);
  1273. }
  1274. const struct UsmUserNameTableEntry *USM::get_user(const OctetStr &security_name)
  1275. {
  1276.   return usm_user_name_table->get_entry(security_name);
  1277. }
  1278. int USM::get_user_count() const
  1279. {
  1280.   return usm_user_table->size();
  1281. }
  1282. DLLOPT void USM::add_user_added_callback(const usm_add_user_callback cb)
  1283. {
  1284.  usm_add_user_cb = cb;
  1285. }
  1286. int USM::get_time(const OctetStr &engine_id,
  1287.   long int *engine_boots, long int *engine_time)
  1288. {
  1289.   return usm_time_table->get_time(engine_id, *engine_boots, *engine_time);
  1290. }
  1291. int USM::get_local_time(long int *engine_boots, long int *engine_time) const
  1292. {
  1293.   return usm_time_table->get_local_time(*engine_boots, *engine_time);
  1294. }
  1295. AuthPriv *USM::get_auth_priv()
  1296. {
  1297.   return auth_priv;
  1298. }
  1299. struct UsmKeyUpdate* USM::key_update_prepare(const OctetStr& securityName,
  1300.      SnmpTarget& target,
  1301.      const OctetStr& newPassword,
  1302.      Pdu& pdu, int type,
  1303.      int &status,
  1304.      const OctetStr& oldpass,
  1305.      const OctetStr& oldengid,
  1306.      const OctetStr& newengid)
  1307. {
  1308.   // check address
  1309.   GenAddress genaddress;
  1310.   target.get_address(genaddress);
  1311.   UdpAddress udp_address(genaddress);
  1312.   if (!udp_address.valid()) {
  1313.     debugprintf(0, "usmPrepareKeyUpdate: Address invalid.");
  1314.     status = SNMPv3_USM_ADDRESS_ERROR;
  1315.     return NULL;
  1316.   }
  1317.   OctetStr engineID = "";
  1318.   // get engineID
  1319.   if (v3mp->get_from_engine_id_table(engineID,
  1320.      (char*)udp_address.get_printable())
  1321.       != SNMPv3_MP_OK ) {
  1322.     debugprintf(0, "usmPrepareKeyUpdate: Could not find engineID of given address.");
  1323.     status = SNMPv3_USM_ADDRESS_ERROR;
  1324.     return NULL;
  1325.   }
  1326.   // get user
  1327.   struct UsmUser* user;
  1328.   user = get_user(engineID, securityName);
  1329.   if (user == NULL) {
  1330.     debugprintf(0, "usmPrepareKeyUpdate: Could not find user in usmTables.");
  1331.     status =  SNMPv3_USM_UNKNOWN_SECURITY_NAME;
  1332.     return NULL;
  1333.   }
  1334.   /* set old and new key */
  1335.   unsigned char key[SNMPv3_USM_MAX_KEY_LEN];
  1336.   unsigned int  key_len = SNMPv3_USM_MAX_KEY_LEN;
  1337.   OctetStr      newKey;
  1338.   OctetStr      oldKey;
  1339.   switch (type) {
  1340.     case AUTHKEY:
  1341.     case OWNAUTHKEY: {
  1342.       status = auth_priv->password_to_key_auth(
  1343.                                          user->authProtocol,
  1344.                                          newPassword.data(), newPassword.len(),
  1345.                                          engineID.data(), engineID.len(),
  1346.                                          key, &key_len);
  1347.       oldKey = OctetStr(user->authKey, user->authKeyLength);
  1348.       break;
  1349.     }
  1350.     case PRIVKEY:
  1351.     case OWNPRIVKEY: {
  1352.       status = auth_priv->password_to_key_priv(
  1353.                                          user->authProtocol,
  1354.                                          user->privProtocol,
  1355.                                          newPassword.data(), newPassword.len(),
  1356.                                          engineID.data(), engineID.len(),
  1357.                                          key, &key_len);
  1358.       oldKey = OctetStr(user->privKey, user->privKeyLength);
  1359.       break;
  1360.     }
  1361.     default: {
  1362.       debugprintf(0, "usmPrepareKeyUpdate: wrong type specified.");
  1363.       status = SNMPv3_USM_ERROR;
  1364.       free_user(user);
  1365.       return NULL;
  1366.     }
  1367.   }
  1368.   if (status != SNMPv3_USM_OK)
  1369.   {
  1370.     debugprintf(0, "usmPrepareKeyUpdate: password_to_key failed (code %i).",
  1371.                 status);
  1372.     free_user(user);
  1373.     return NULL;
  1374.   }
  1375.   newKey = OctetStr(key, key_len);
  1376.   /* get value to set and random value */
  1377.   OctetStr newValue;
  1378.   OctetStr random_value;
  1379.   auth_priv->get_keychange_value(user->authProtocol,
  1380.                                  oldKey, newKey, newValue);
  1381.   char tmp_rand;
  1382.   for (int i = 0; i<30; i++) {
  1383.     tmp_rand = rand();
  1384.     random_value += tmp_rand;
  1385.   }
  1386.   // Oid in usmUserTable
  1387.   Oid userOid = Oid(oidUsmUserEntry);
  1388.   Oid publicOid  = Oid(oidUsmUserEntry);
  1389.   publicOid += "11";
  1390.   switch (type) {
  1391.     case AUTHKEY: {
  1392.       userOid += "6";
  1393.       break;
  1394.     }
  1395.     case OWNAUTHKEY: {
  1396.       userOid += "7";
  1397.       break;
  1398.     }
  1399.     case PRIVKEY: {
  1400.        userOid += "9";
  1401.        break;
  1402.     }
  1403.     case OWNPRIVKEY: {
  1404.       userOid += "10";
  1405.       break;
  1406.     }
  1407.     default: {
  1408.       debugprintf(0, "KeyChange error: wrong type:");
  1409.       status = SNMPv3_USM_ERROR;
  1410.       free_user(user);
  1411.       return NULL;
  1412.     }
  1413.   }
  1414.   userOid += engineID.len();
  1415.   publicOid += engineID.len();
  1416.   for (unsigned int j=0; j<engineID.len(); j++) {
  1417.     userOid += (engineID)[j];
  1418.     publicOid += (engineID)[j];
  1419.   }
  1420.   OctetStr os = securityName;
  1421.   userOid += os.len();
  1422.   publicOid += os.len();
  1423.   for (unsigned int k=0; k<os.len(); k++) {
  1424.     userOid += os[k];
  1425.     publicOid += os[k];
  1426.   }
  1427.   Vb vb;
  1428.   vb.set_oid(userOid);
  1429.   vb.set_value(newValue);
  1430.   pdu += vb;
  1431.   vb.set_oid(publicOid);
  1432.   vb.set_value(random_value);
  1433.   pdu += vb;
  1434.   struct UsmKeyUpdate *uku = new struct UsmKeyUpdate;
  1435.   uku->engineID = engineID;
  1436.   uku->securityName = securityName;
  1437.   uku->newPassword = newPassword;
  1438.   uku->newKey = newKey;
  1439.   uku->type = type;
  1440.   free_user(user);
  1441.   status = SNMPv3_USM_OK;
  1442.   return uku;
  1443. }
  1444. void USM::key_update_abort(struct UsmKeyUpdate *uku)
  1445. {
  1446.   delete uku;
  1447. }
  1448. int USM::key_update_commit(struct UsmKeyUpdate *uku, int update_type)
  1449. {
  1450.   if (!uku) return SNMPv3_USM_ERROR;
  1451.   int result;
  1452.   OctetStr userName;
  1453.   switch (update_type)
  1454.   {
  1455.     case USM_KeyUpdate: {
  1456.       result = update_key(uku->securityName.data(), uku->securityName.len(),
  1457.   uku->engineID.data(), uku->engineID.len(),
  1458.   uku->newKey.data(), uku->newKey.len(),
  1459.   uku->type);
  1460.       delete uku;
  1461.       return result;
  1462.     }
  1463.     case USM_PasswordKeyUpdate: {
  1464.       result = update_key(uku->securityName.data(), uku->securityName.len(),
  1465.   uku->engineID.data(), uku->engineID.len(),
  1466.   uku->newKey.data(), uku->newKey.len(),
  1467.   uku->type);
  1468.       struct UsmUserNameTableEntry *entry;
  1469.       entry = usm_user_name_table->get_cloned_entry(uku->securityName);
  1470.       if (!entry || (result != SNMPv3_USM_OK)) {
  1471.         delete uku;
  1472.         if (entry)
  1473.           usm_user_name_table->delete_cloned_entry(entry);
  1474.         return SNMPv3_USM_ERROR;
  1475.       }
  1476.       result = SNMPv3_USM_ERROR;
  1477.       switch (uku->type) {
  1478.         case OWNAUTHKEY:
  1479.         case AUTHKEY: {
  1480.           OctetStr privPass(entry->privPassword, entry->privPasswordLength);
  1481.           result = add_usm_user(uku->securityName, entry->usmUserName,
  1482. entry->usmUserAuthProtocol,
  1483. entry->usmUserPrivProtocol,
  1484. uku->newPassword, privPass);
  1485.   break;
  1486.         }
  1487.         case OWNPRIVKEY:
  1488.         case PRIVKEY: {
  1489.           OctetStr authPass(entry->privPassword, entry->privPasswordLength);
  1490.           result = add_usm_user(uku->securityName, entry->usmUserName,
  1491. entry->usmUserAuthProtocol,
  1492. entry->usmUserPrivProtocol,
  1493. authPass, uku->newPassword);
  1494.   break;
  1495.         }
  1496.       }
  1497.       delete uku;
  1498.       usm_user_name_table->delete_cloned_entry(entry);
  1499.       return result;
  1500.     }
  1501.     case USM_PasswordAllKeyUpdate: {
  1502.       struct UsmUserNameTableEntry *entry;
  1503.       entry = usm_user_name_table->get_cloned_entry(uku->securityName);
  1504.       if (!entry) {
  1505.         delete uku;
  1506.         return SNMPv3_USM_ERROR;
  1507.       }
  1508.       result = SNMPv3_USM_ERROR;
  1509.       switch (uku->type) {
  1510.         case OWNAUTHKEY:
  1511.         case AUTHKEY: {
  1512.           OctetStr privPass = OctetStr(entry->privPassword,
  1513.                                        entry->privPasswordLength);
  1514.           delete_usm_user(uku->securityName);
  1515.           result = add_usm_user(uku->securityName, entry->usmUserName,
  1516. entry->usmUserAuthProtocol,
  1517. entry->usmUserPrivProtocol,
  1518. uku->newPassword, privPass);
  1519.   break;
  1520.         }
  1521.         case OWNPRIVKEY:
  1522.         case PRIVKEY: {
  1523.           OctetStr authPass = OctetStr(entry->authPassword,
  1524.                                        entry->authPasswordLength);
  1525.           delete_usm_user(uku->securityName);
  1526.           result = add_usm_user(uku->securityName, entry->usmUserName,
  1527. entry->usmUserAuthProtocol,
  1528. entry->usmUserPrivProtocol,
  1529. authPass, uku->newPassword);
  1530.   break;
  1531.         }
  1532.       }
  1533.       delete uku;
  1534.       usm_user_name_table->delete_cloned_entry(entry);
  1535.       return result;
  1536.     }
  1537.   }
  1538.   delete uku;
  1539.   return SNMPv3_USM_ERROR;
  1540. }
  1541. int USM::generate_msg(
  1542.              unsigned char *globalData,       // message header, admin data
  1543.              int globalDataLength,
  1544.              int maxMessageSize,              // of the sending SNMP entity
  1545.              const OctetStr &securityEngineID,// authoritative SNMP entity
  1546.              const OctetStr &securityName,    // on behalf of this principal
  1547.              int  securityLevel,              // Level of Security requested
  1548.              unsigned char  *scopedPDU,       // message (plaintext) payload
  1549.              int scopedPDULength,
  1550.              struct SecurityStateReference *securityStateReference,
  1551.              unsigned char *wholeMsg,         // OUT complete generated message
  1552.              int *wholeMsgLength)             // OUT length of generated message
  1553. {
  1554.   Buffer<unsigned char> buffer(MAX_SNMP_PACKET);
  1555.   Buffer<unsigned char> buffer2(MAX_SNMP_PACKET);
  1556.   unsigned char *bufPtr = buffer.get_ptr();
  1557.   unsigned char *buf2Ptr = buffer2.get_ptr();
  1558.   if (!bufPtr || !buf2Ptr)
  1559.     return SNMPv3_USM_ERROR;
  1560.   unsigned char *wholeMsgPtr;
  1561.   int startAuthPar = 0;
  1562.   struct UsmUser *user = NULL;
  1563.   struct UsmSecurityParameters usmSecurityParams;
  1564.   int bufLength = 0;
  1565.   unsigned int buf2Length = 0;
  1566.   int totalLength = 0;             // Bytes encoded
  1567.   int restLength = maxMessageSize; // max Bytes left in packet-buffer
  1568.   int rc;
  1569.   int responseMsg = 0;
  1570.   if (securityStateReference) {
  1571.     // this is a response message
  1572.     responseMsg = 1;
  1573.     user = new UsmUser;
  1574.     if (!user)
  1575.       return SNMPv3_USM_ERROR;
  1576.     if (securityStateReference->securityEngineID) {
  1577.       user->engineIDLength = securityStateReference->securityEngineIDLength;
  1578.       user->engineID       = securityStateReference->securityEngineID;
  1579.     } else {
  1580.       user->engineIDLength = securityEngineID.len();
  1581.       user->engineID       = v3strcpy(securityEngineID.data(),
  1582.       securityEngineID.len());
  1583.     }
  1584.     user->usmUserName = new unsigned char[MAXLEN_USMUSERNAME + 1];
  1585.     if (securityStateReference->securityName)
  1586.     {
  1587.       user->securityName       = securityStateReference->securityName;
  1588.       user->securityNameLength = securityStateReference->securityNameLength;
  1589.       memcpy(user->usmUserName, securityStateReference->msgUserName,
  1590.      securityStateReference->msgUserNameLength);
  1591.       user->usmUserNameLength  = securityStateReference->msgUserNameLength;
  1592.     }
  1593.     else
  1594.     {
  1595.       user->securityNameLength = securityName.len();
  1596.       user->securityName = v3strcpy(securityName.data(), securityName.len());
  1597.       if (securityStateReference->msgUserNameLength)
  1598.       {
  1599.         securityStateReference->msgUserName[0] = 0;
  1600.         securityStateReference->msgUserNameLength = 0;
  1601.       }
  1602.       user->usmUserNameLength = MAXLEN_USMUSERNAME;
  1603.       get_user_name(user->usmUserName, &user->usmUserNameLength,
  1604.     securityName.data(), securityName.len());
  1605.       if ((user->usmUserNameLength == 0) &&
  1606.           (securityName.len() <= MAXLEN_USMUSERNAME)) {
  1607.         memcpy(user->usmUserName, securityName.data(), securityName.len());
  1608. user->usmUserName[securityName.len()] = 0;
  1609.         user->usmUserNameLength = securityName.len();
  1610.       }
  1611.     }
  1612.     user->authProtocol       = securityStateReference->authProtocol;
  1613.     user->authKey            = securityStateReference->authKey;
  1614.     user->authKeyLength      = securityStateReference->authKeyLength;
  1615.     user->privProtocol       = securityStateReference->privProtocol;
  1616.     user->privKeyLength      = securityStateReference->privKeyLength;
  1617.     user->privKey            = securityStateReference->privKey;
  1618.     delete securityStateReference;
  1619.     securityStateReference = NULL;
  1620.   }
  1621.   else
  1622.   {
  1623.     if (securityEngineID.len() == 0)
  1624.     {
  1625.       // discovery
  1626.       user = new UsmUser;
  1627.       if (!user)
  1628. return SNMPv3_USM_ERROR;
  1629.       memset(user, 0, sizeof(UsmUser));
  1630.     }
  1631.     else
  1632.     {
  1633.       // search for user in usmUserTable
  1634.       user = get_user(securityEngineID, securityName);
  1635.       if (!user) {
  1636. debugprintf(0, "USM: User unknown!");
  1637. return SNMPv3_USM_UNKNOWN_SECURITY_NAME;
  1638.       }
  1639.     }
  1640.   }
  1641.   if (securityEngineID.len() > MAXLENGTH_ENGINEID)
  1642.   {
  1643.     debugprintf(0, "engine_id too long %i > %i",
  1644. securityEngineID.len(), MAXLENGTH_ENGINEID);
  1645.     free_user(user);
  1646.     return SNMPv3_USM_ERROR;
  1647.   }
  1648.   if (user->usmUserNameLength > MAXLEN_USMUSERNAME)
  1649.   {
  1650.     debugprintf(0, "user name too long %i > %i",
  1651. user->usmUserNameLength, MAXLEN_USMUSERNAME);
  1652.     free_user(user);
  1653.     return SNMPv3_USM_ERROR;
  1654.   }
  1655.   usmSecurityParams.msgAuthoritativeEngineIDLength = securityEngineID.len();
  1656.   usmSecurityParams.msgUserNameLength = user->usmUserNameLength;
  1657.   memcpy(usmSecurityParams.msgUserName,
  1658.          user->usmUserName, user->usmUserNameLength);
  1659.   memcpy(usmSecurityParams.msgAuthoritativeEngineID,
  1660.          securityEngineID.data(), securityEngineID.len());
  1661.   usmSecurityParams.msgPrivacyParametersLength = 0;
  1662.   usmSecurityParams.msgPrivacyParameters = NULL;
  1663.   usmSecurityParams.msgAuthenticationParametersLength = 0;
  1664.   usmSecurityParams.msgAuthenticationParameters = NULL;
  1665.   if (securityLevel >= SNMP_SECURITY_LEVEL_AUTH_NOPRIV)
  1666.   {
  1667.     // get engineBoots, engineTime
  1668.     rc = usm_time_table->get_time(
  1669.                            securityEngineID,
  1670.                            usmSecurityParams.msgAuthoritativeEngineBoots,
  1671.                            usmSecurityParams.msgAuthoritativeEngineTime);
  1672.     if (rc == SNMPv3_USM_UNKNOWN_ENGINEID) {
  1673.       usm_time_table->add_entry(securityEngineID,
  1674.                                 usmSecurityParams.msgAuthoritativeEngineBoots,
  1675.                                 usmSecurityParams.msgAuthoritativeEngineTime);
  1676.     }
  1677.     if (rc == SNMPv3_USM_ERROR) {
  1678.       debugprintf(0, "usm: usmGetTime error.");
  1679.       free_user(user);
  1680.       return SNMPv3_USM_ERROR;
  1681.     }
  1682.   }
  1683.   if (securityLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV)
  1684.   {
  1685.     usmSecurityParams.msgPrivacyParametersLength
  1686.              = auth_priv->get_priv_params_len(user->privProtocol);
  1687.     usmSecurityParams.msgPrivacyParameters
  1688.              = new unsigned char[usmSecurityParams.msgPrivacyParametersLength];
  1689.     // encrypt Message
  1690.     int enc_result = auth_priv->encrypt_msg(
  1691.                                user->privProtocol,
  1692.        user->privKey, user->privKeyLength,
  1693.                                scopedPDU, scopedPDULength,
  1694.                                buf2Ptr, &buf2Length,
  1695.                                usmSecurityParams.msgPrivacyParameters,
  1696.                                &usmSecurityParams.msgPrivacyParametersLength,
  1697.                                usmSecurityParams.msgAuthoritativeEngineBoots,
  1698.        usmSecurityParams.msgAuthoritativeEngineTime);
  1699.     if (enc_result != SNMPv3_USM_OK)
  1700.     {
  1701.       int return_value;
  1702.       if (user->privProtocol == SNMP_PRIVPROTOCOL_NONE)
  1703.       {
  1704.         debugprintf(0, "usm: Privacy requested, but no UserPrivProtocol");
  1705.         return_value = SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL;
  1706.       }
  1707.       else
  1708.       {
  1709.         return_value = SNMPv3_USM_ENCRYPTION_ERROR;
  1710.       }
  1711.       debugprintf(0, "usm: Encryption error (result %i).", enc_result);
  1712.       delete_sec_parameters(&usmSecurityParams);
  1713.       free_user(user);
  1714.       return return_value;
  1715.     }
  1716.     bufPtr = asn_build_string(bufPtr, &restLength,
  1717.                               (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  1718.                               buf2Ptr, buf2Length);
  1719.     if (!bufPtr) {
  1720.       debugprintf(0, "usm: Encoding Error");
  1721.       free_user(user);
  1722.       return SNMPv3_USM_ERROR;
  1723.     }
  1724.     bufLength = SAFE_INT_CAST(bufPtr - buffer.get_ptr());
  1725.     totalLength =  bufLength;
  1726.     bufPtr = buffer.get_ptr();
  1727.     memcpy(buf2Ptr, bufPtr, bufLength);
  1728.     buf2Length = bufLength;
  1729.   } else { // (securityLevel != SNMP_SECURITY_LEVEL_AUTH_PRIV)
  1730.     buf2Ptr = scopedPDU;
  1731.     buf2Length = scopedPDULength;
  1732.     totalLength = scopedPDULength;
  1733.   }
  1734.   if (!bufPtr) {
  1735.     debugprintf(0, "usm: Encoding Error");
  1736.     free_user(user);
  1737.     return SNMPv3_USM_ERROR;
  1738.   }
  1739.   totalLength += SAFE_INT_CAST(bufPtr - buffer.get_ptr());
  1740.   memcpy(bufPtr, buf2Ptr, buf2Length);
  1741.   bufLength = totalLength;
  1742.   debugprintf(21, "buf after privacy:");
  1743.   debughexprintf(21, buffer.get_ptr(), bufLength);
  1744.   wholeMsgPtr = wholeMsg;
  1745.   if (securityLevel >= SNMP_SECURITY_LEVEL_AUTH_NOPRIV)
  1746.   {
  1747.     /* Build message with authentication */
  1748.     usmSecurityParams.msgAuthenticationParametersLength
  1749.                          = auth_priv->get_auth_params_len(user->authProtocol);
  1750.     usmSecurityParams.msgAuthenticationParameters
  1751.       = new unsigned char[usmSecurityParams.msgAuthenticationParametersLength];
  1752.     memset((char*)(usmSecurityParams.msgAuthenticationParameters), 0,
  1753.            usmSecurityParams.msgAuthenticationParametersLength);
  1754.     wholeMsgPtr = build_whole_msg(wholeMsgPtr, &maxMessageSize,
  1755.   globalData, globalDataLength,
  1756.   &startAuthPar, // for MD5, SHA,...
  1757.   usmSecurityParams,
  1758.   buffer.get_ptr(),
  1759.   bufLength);   // the msgData
  1760.     if (wholeMsgPtr == NULL)
  1761.     {
  1762.       debugprintf(0, "usm: could not generate wholeMsg");
  1763.       delete_sec_parameters(&usmSecurityParams);
  1764.       free_user(user);
  1765.       return SNMPv3_USM_ERROR;
  1766.     }
  1767.     *wholeMsgLength = SAFE_INT_CAST(wholeMsgPtr - wholeMsg);
  1768.     rc = auth_priv->auth_out_msg(user->authProtocol,
  1769.                                  user->authKey,
  1770.                                  wholeMsg, *wholeMsgLength,
  1771.                                  wholeMsg + startAuthPar);
  1772.     if (rc!=SNMPv3_USM_OK)
  1773.     {
  1774.       debugprintf(0, "usm: Authentication error for outgoing message."
  1775.                   " error code (%i).", rc);
  1776.       delete_sec_parameters(&usmSecurityParams);
  1777.       free_user(user);
  1778.       return rc;
  1779.     }
  1780.   }
  1781.   else
  1782.   {
  1783.     //build Message without authentication
  1784.     // Set engineBoots and enigneTime to zero!
  1785.     usmSecurityParams.msgAuthoritativeEngineBoots = 0;
  1786.     usmSecurityParams.msgAuthoritativeEngineTime  = 0;
  1787.     usmSecurityParams.msgAuthenticationParametersLength = 0;
  1788.     usmSecurityParams.msgAuthenticationParameters = 0;
  1789.     wholeMsgPtr = build_whole_msg(wholeMsgPtr, &maxMessageSize,
  1790.   globalData, globalDataLength,
  1791.   &startAuthPar, // dummy ( no auth)
  1792.   usmSecurityParams,
  1793.   buffer.get_ptr(),
  1794.   bufLength);   // the msgData
  1795.     if (wholeMsgPtr == NULL) {
  1796.       debugprintf(0, "usm: could not generate wholeMsg");
  1797.       delete_sec_parameters(&usmSecurityParams);
  1798.       free_user(user);
  1799.       return SNMPv3_USM_ERROR;
  1800.     }
  1801.     *wholeMsgLength = SAFE_INT_CAST(wholeMsgPtr - wholeMsg);
  1802.   }
  1803.   debugprintf(21, "Complete Whole Msg:");
  1804.   debughexprintf(21, wholeMsg, *wholeMsgLength);
  1805.   delete_sec_parameters(&usmSecurityParams);
  1806.   free_user(user);
  1807.   return SNMPv3_USM_OK;
  1808. }
  1809. int USM::process_msg(
  1810.             int maxMessageSize,               // of the sending SNMP entity
  1811.             unsigned char *securityParameters,// for the received message
  1812.             int securityParametersLength,
  1813.             int securityParametersPosition,
  1814.             long int securityLevel,           // Level of Security
  1815.             unsigned char *wholeMsg,          // as received on the wire
  1816.             int wholeMsgLength,               // length as received on the wire
  1817.             unsigned char *msgData,
  1818.             int msgDataLength,
  1819.     OctetStr &security_engine_id,     // authoritative SNMP entity
  1820.     OctetStr &security_name,          //identification of the principal
  1821.             unsigned char *scopedPDU,         // message (plaintext) payload
  1822.             int *scopedPDULength,
  1823.             long *maxSizeResponseScopedPDU, // maximum size of the Response PDU
  1824.             struct SecurityStateReference *securityStateReference,
  1825.                                             // reference to security state
  1826.                                             // information, needed for response
  1827.             const UdpAddress &fromAddress)
  1828. {
  1829.   unsigned char* sp = securityParameters;
  1830.   int spLength = securityParametersLength;
  1831.   unsigned char type;
  1832.   long int engineBoots, engineTime;
  1833.   unsigned char authParam[SNMPv3_AP_MAXLENGTH_AUTHPARAM];
  1834.   unsigned char privParam[SNMPv3_AP_MAXLENGTH_PRIVPARAM];
  1835.   int authParamLength = SNMPv3_AP_MAXLENGTH_AUTHPARAM;
  1836.   int privParamLength = SNMPv3_AP_MAXLENGTH_PRIVPARAM;
  1837.   Buffer<unsigned char> encryptedScopedPDU(MAX_SNMP_PACKET);
  1838.   int encryptedScopedPDULength = msgDataLength;
  1839.   struct UsmUser *user = NULL;
  1840.   int rc;
  1841.   int notInTime = 0;
  1842.   // check securityParameters
  1843.   sp = asn_parse_header( sp, &spLength, &type);
  1844.   if (sp == NULL){
  1845.     debugprintf(0, "bad header of securityParameters");
  1846.     return SNMPv3_USM_PARSE_ERROR;
  1847.   }
  1848.   debugprintf(3, "Parsed securityParametersLength = 0x%x", spLength);
  1849.   if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)){
  1850.     debugprintf(0, "wrong type in header of securityParameters");
  1851.     return SNMPv3_USM_PARSE_ERROR;
  1852.   }
  1853.   // extract security parameters
  1854.   {
  1855.     int len = MAXLENGTH_ENGINEID + 1;
  1856.     unsigned char data[MAXLENGTH_ENGINEID + 1];
  1857.     sp = asn_parse_string( sp, &spLength, &type, data, &len);
  1858.     debugprintf(3, "Parsed securityEngineID, length = 0x%x", len);
  1859.     if (sp==NULL) {
  1860.       debugprintf(0, "bad parse of securityEngineID");
  1861.       return SNMPv3_USM_PARSE_ERROR;
  1862.     }
  1863.     security_engine_id.set_data(data, len);
  1864.   }
  1865.   sp = asn_parse_int(sp, &spLength,
  1866.                      &type, &engineBoots, sizeof(engineBoots));
  1867.   if ((sp == NULL) || (engineBoots < 0)) {
  1868.     debugprintf(0, "bad parse of engineBoots");
  1869.     return SNMPv3_USM_PARSE_ERROR;
  1870.   }
  1871.   sp = asn_parse_int(sp, &spLength,
  1872.                      &type, &engineTime, sizeof(engineTime));
  1873.   if ((sp == NULL) || (engineTime < 0)) {
  1874.     debugprintf(0, "bad parse of engineTime");
  1875.     return SNMPv3_USM_PARSE_ERROR;
  1876.   }
  1877.   debugprintf(3, "Parsed engineBoots(0x%lx), engineTime(0x%lx)",
  1878.       engineTime, engineBoots);
  1879.   unsigned char usmUserName[MAXLEN_USMUSERNAME + 1];
  1880.   int usmUserNameLength = MAXLEN_USMUSERNAME;
  1881.   sp = asn_parse_string( sp, &spLength, &type,
  1882.                          (unsigned char*)&usmUserName, &usmUserNameLength);
  1883.   if (sp==NULL) {
  1884.     debugprintf(0, "bad parse of usmUserName");
  1885.     return SNMPv3_USM_PARSE_ERROR;
  1886.   }
  1887.   sp = asn_parse_string( sp, &spLength, &type,
  1888.                          (unsigned char*)&authParam, &authParamLength);
  1889.   if (sp==NULL) {
  1890.     debugprintf(0, "bad parse of msgAuthenticationParameters");
  1891.     return SNMPv3_USM_PARSE_ERROR;
  1892.   }
  1893.   int authParametersPosition = securityParametersPosition +
  1894.                                SAFE_INT_CAST(sp - securityParameters) - authParamLength;
  1895.   sp = asn_parse_string( sp, &spLength, &type,
  1896.                          (unsigned char*)&privParam, &privParamLength);
  1897.   if (sp==NULL) {
  1898.     debugprintf(0, "bad parse of msgPrivacyParameters");
  1899.     return SNMPv3_USM_PARSE_ERROR;
  1900.   }
  1901.   if (spLength !=0) {
  1902.     debugprintf(0, "Error Parsing msgPrivacyParameters");
  1903.     return SNMPv3_USM_PARSE_ERROR;
  1904.   }
  1905.   debugprintf(5, "Parsed usmUserName length(0x%x)"
  1906.       " msgAuthenticationParameters length(0x%x)"
  1907.       " msgPrivacyParameters length(0x%x)",
  1908.       usmUserNameLength, authParamLength, privParamLength);
  1909.   // prepare securityStateReference
  1910.   if (usmUserNameLength > MAXLEN_USMUSERNAME)
  1911.   {
  1912.     debugprintf(0, "user name too long: %i > %i.",
  1913. usmUserNameLength, MAXLEN_USMUSERNAME);
  1914.     return SNMPv3_USM_PARSE_ERROR;
  1915.   }
  1916.   securityStateReference->msgUserNameLength = usmUserNameLength;
  1917.   memcpy(securityStateReference->msgUserName, usmUserName,
  1918.          securityStateReference->msgUserNameLength);
  1919.   securityStateReference->securityEngineIDLength = security_engine_id.len();
  1920.   securityStateReference->securityEngineID =
  1921.     new unsigned char [securityStateReference->securityEngineIDLength];
  1922.   memcpy(securityStateReference->securityEngineID, security_engine_id.data(),
  1923.          securityStateReference->securityEngineIDLength);
  1924.   securityStateReference->securityLevel = securityLevel;
  1925.   securityStateReference->securityNameLength = 0;
  1926.   securityStateReference->securityName = NULL;
  1927.   securityStateReference->authProtocol = 1;
  1928.   securityStateReference->privProtocol = 1;
  1929.   securityStateReference->authKey = NULL;
  1930.   securityStateReference->privKey = NULL;
  1931.   // in case we return with error,
  1932.   // perhaps v3MP can decode it (requestID!!!)
  1933.   memcpy(scopedPDU, msgData, msgDataLength);
  1934.   *scopedPDULength = msgDataLength;
  1935.   if ((security_engine_id.len() == 0) ||
  1936.       (usm_time_table->check_engine_id(security_engine_id) != SNMPv3_USM_OK ))
  1937.   {
  1938.     inc_stats_unknown_engine_ids();
  1939.     // *+* REPORT *+*
  1940.     securityStateReference->securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
  1941.     security_name.set_data(usmUserName, usmUserNameLength);
  1942.     debugprintf(2, "USM: EngineID unknown");
  1943.     return SNMPv3_USM_UNKNOWN_ENGINEID;
  1944.   }
  1945.   // get securityName:
  1946.   if ((usmUserNameLength) ||
  1947.       (securityLevel != SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV))
  1948.   {
  1949.     rc = get_security_name(usmUserName, usmUserNameLength, security_name);
  1950.     if (rc != SNMPv3_USM_OK) {
  1951.       inc_stats_unknown_user_names();
  1952.       security_name.set_data(usmUserName, usmUserNameLength);
  1953.       debugprintf(2,"usmProcessMsg: unknown user (%s)",
  1954.   security_name.get_printable());
  1955.       return SNMPv3_USM_UNKNOWN_SECURITY_NAME;
  1956.     }
  1957.   }
  1958.   else
  1959.   {
  1960.     debugprintf(2, "Accepting zero length user/security name.");
  1961.     security_name = "";
  1962.   }
  1963.   securityStateReference->securityNameLength = security_name.len();
  1964.   securityStateReference->securityName =
  1965.     new unsigned char [securityStateReference->securityNameLength];
  1966.   memcpy(securityStateReference->securityName, security_name.data(),
  1967.          securityStateReference->securityNameLength);
  1968.   // get user from LCD (usmUserTable)
  1969.   if (usmUserNameLength)
  1970.   {
  1971.     user = get_user(security_engine_id, security_name);
  1972.     if (!user) {
  1973.       inc_stats_unknown_user_names();
  1974.       debugprintf(0, "usmProcessMsg: unknown user");
  1975.       return SNMPv3_USM_UNKNOWN_SECURITY_NAME;
  1976.     }
  1977.   }
  1978.   else
  1979.   {
  1980.     user = new UsmUser;
  1981.     if (!user)
  1982.     {
  1983.       debugprintf(0, "Memory error");
  1984.       return SNMPv3_USM_ERROR;
  1985.     }
  1986.     memset(user, 0, sizeof(UsmUser));
  1987.   }
  1988.   if (((securityLevel > SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV) &&
  1989.        (user->authProtocol == SNMPv3_usmNoAuthProtocol)) ||
  1990.       ((securityLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV) &&
  1991.        (user->privProtocol == SNMPv3_usmNoPrivProtocol))) {
  1992.     inc_stats_unsupported_sec_levels();
  1993.     debugprintf(0, "usmProcessMsg: unsupported Securitylevel");
  1994.     free_user(user);
  1995.     return SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL;
  1996.   }
  1997.   if (securityLevel > SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV)
  1998.   {
  1999.     rc = auth_priv->auth_inc_msg(user->authProtocol,
  2000.                                  user->authKey,
  2001.                                  wholeMsg, wholeMsgLength,
  2002.                                  wholeMsg + authParametersPosition,
  2003.  authParamLength);
  2004.     if (rc != SNMPv3_USM_OK)
  2005.     {
  2006.       switch (rc)
  2007.       {
  2008.         case SNMPv3_USM_AUTHENTICATION_FAILURE:
  2009.           debugprintf(0, "usmProcessMsg: Authentication failure.");
  2010.   inc_stats_wrong_digests();
  2011.           /* set securityLevel for Report */
  2012.           break;
  2013.         case SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL:
  2014.           debugprintf(0, "usmProcessMsg: unknown AuthProtocol");
  2015.   inc_stats_unsupported_sec_levels();
  2016.         default:
  2017.           debugprintf(0, "usmProcessMsg: error authenticating msg."
  2018.                       " Error code (%i).", rc);
  2019.           // todo: is it ok to increment this counter?
  2020.   inc_stats_unsupported_sec_levels();
  2021.           break;
  2022.       }
  2023.       securityStateReference->securityLevel= SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
  2024.       free_user(user);
  2025.       return rc;
  2026.     }
  2027.     rc = usm_time_table->check_time(security_engine_id,
  2028.     engineBoots, engineTime);
  2029.     if (rc == SNMPv3_USM_NOT_IN_TIME_WINDOW)
  2030.     {
  2031.       inc_stats_not_in_time_windows();
  2032.       debugprintf(2, "***Message not in TimeWindow!");
  2033.       notInTime = 1;
  2034.     }
  2035.     if (rc == SNMPv3_USM_UNKNOWN_ENGINEID)
  2036.     {
  2037.       debugprintf(0, "***EngineID not in timeTable!");
  2038.       free_user(user);
  2039.       return rc;
  2040.     }
  2041.   }
  2042.   *scopedPDULength = MAX_SNMP_PACKET;
  2043.   // decrypt ScopedPDU if message is in time window
  2044.   if ((securityLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV)
  2045.       && (!notInTime)) {
  2046.     msgData = asn_parse_string( msgData, &msgDataLength, &type,
  2047.                                 encryptedScopedPDU.get_ptr(),
  2048. &encryptedScopedPDULength);
  2049.     if (msgData == NULL){
  2050.       debugprintf(0, "usmProcessMsg: bad header of encryptedPDU");
  2051.       free_user(user);
  2052.       return SNMPv3_USM_PARSE_ERROR;
  2053.     }
  2054.     // decrypt Message
  2055.     unsigned int tmp_length = *scopedPDULength;
  2056.     int dec_result = auth_priv->decrypt_msg(
  2057.                                   user->privProtocol,
  2058.                                   user->privKey, user->privKeyLength,
  2059.                                   encryptedScopedPDU.get_ptr(),
  2060.   encryptedScopedPDULength,
  2061.                                   scopedPDU, &tmp_length,
  2062.                                   (unsigned char*)&privParam, privParamLength,
  2063.   engineBoots, engineTime);
  2064.     *scopedPDULength = tmp_length;
  2065.     if (dec_result != SNMPv3_USM_OK)
  2066.     {
  2067.       int return_value;
  2068.       if (dec_result == SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL)
  2069.       {
  2070.         debugprintf(0, "usmProcessMsg: unknown PrivacyProtocol");
  2071. inc_stats_unsupported_sec_levels();
  2072.         return_value = SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL;
  2073.       }
  2074.       else // catch all
  2075.       {
  2076.         debugprintf(0, "usmProcessMsg: Decryption error (result %i).",
  2077.     dec_result);
  2078. inc_stats_decryption_errors();
  2079.         return_value = SNMPv3_USM_DECRYPTION_ERROR;
  2080.       }
  2081.       free_user(user);
  2082.       return return_value;
  2083.     }
  2084.     debugprintf(21, "scopedPDU(1):");
  2085.     debughexprintf(21, scopedPDU, *scopedPDULength);
  2086.     // test for decryption error
  2087.     // first byte 0x30
  2088.     if (scopedPDU[0] != (ASN_CONSTRUCTOR | ASN_SEQUENCE)) {
  2089.       debugprintf(0, "Decryption error detected");
  2090.       inc_stats_decryption_errors();
  2091.       free_user(user);
  2092.       return SNMPv3_USM_DECRYPTION_ERROR;
  2093.     }
  2094.   }
  2095.   else {
  2096.     // message was not encrypted
  2097.     memcpy(scopedPDU, msgData, msgDataLength);
  2098.     *scopedPDULength = msgDataLength;
  2099.   }
  2100.   *maxSizeResponseScopedPDU = maxMessageSize - (wholeMsgLength - *scopedPDULength);
  2101.   security_name.set_data(user->securityName, user->securityNameLength);
  2102.   securityStateReference->authProtocol = user->authProtocol;
  2103.   securityStateReference->privProtocol = user->privProtocol;
  2104.   securityStateReference->authKeyLength = user->authKeyLength;
  2105.   securityStateReference->authKey = user->authKey;
  2106.   securityStateReference->privKeyLength = user->privKeyLength;
  2107.   securityStateReference->privKey = user->privKey;
  2108.   user->authKey = 0;
  2109.   user->privKey = 0;
  2110.   free_user(user);
  2111.   if (notInTime)
  2112.     return SNMPv3_USM_NOT_IN_TIME_WINDOW;
  2113.   return SNMPv3_USM_OK;
  2114. }
  2115. unsigned char *USM::build_sec_params(unsigned char *outBuf, int *maxLength,
  2116.      struct UsmSecurityParameters sp,
  2117.      int *position)
  2118. {
  2119.   Buffer<unsigned char> buf(MAX_SNMP_PACKET);
  2120.   unsigned char *bufPtr = buf.get_ptr();
  2121.   unsigned char *outBufPtr = outBuf;
  2122.   int length = *maxLength;
  2123.   int totalLength;
  2124.   debugprintf(5, "Coding octstr sp.msgAuthoritativeEngineID, length = 0x%lx",
  2125.       sp.msgAuthoritativeEngineIDLength);
  2126.   bufPtr = asn_build_string(bufPtr, &length,
  2127.                             (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  2128.                             sp.msgAuthoritativeEngineID,
  2129.                             sp.msgAuthoritativeEngineIDLength);
  2130.   if (bufPtr == NULL) {
  2131.     debugprintf(0, "usmBuildSecurityParameters error coding engineid");
  2132.     return NULL;
  2133.   }
  2134.   debugprintf(5, "Coding int sp.msgAuthoritativeEngineBoots = 0x%lx",
  2135.       sp.msgAuthoritativeEngineBoots);
  2136.   bufPtr = asn_build_int(bufPtr, &length,
  2137.                          (unsigned char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  2138.                          (long*)&sp.msgAuthoritativeEngineBoots,
  2139.                          sizeof(sp.msgAuthoritativeEngineBoots));
  2140.   if (bufPtr == NULL) {
  2141.     debugprintf(0, "usmBuildSecurityParameters error coding engineboots");
  2142.     return NULL;
  2143.   }
  2144.   debugprintf(5, "Coding int sp.msgAuthoritativeEngineTime = 0x%lx",
  2145.       sp.msgAuthoritativeEngineTime);
  2146.   bufPtr = asn_build_int(bufPtr, &length,
  2147.                          (unsigned char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  2148.                          (long*)&sp.msgAuthoritativeEngineTime,
  2149.                          sizeof(sp.msgAuthoritativeEngineTime));
  2150.   if (bufPtr == NULL) {
  2151.     debugprintf(0, "usmBuildSecurityParameters error coding enginetime");
  2152.     return NULL;
  2153.   }
  2154.   debugprintf(5, "Coding octstr sp.msgUserName, length = 0x%lx",
  2155.       sp.msgUserNameLength);
  2156.   bufPtr = asn_build_string(bufPtr, &length,
  2157.                             (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  2158.                             sp.msgUserName,
  2159.                             sp.msgUserNameLength);
  2160.   if (bufPtr == NULL) {
  2161.     debugprintf(0, "usmBuildSecurityParameters error coding msgusername");
  2162.     return NULL;
  2163.   }
  2164.   *position = SAFE_INT_CAST(bufPtr - buf.get_ptr()) + 2;
  2165.   debugprintf(5, "Coding octstr sp.msgAu..Para.. , length = 0x%lx",
  2166.       sp.msgAuthenticationParametersLength);
  2167.   bufPtr = asn_build_string(bufPtr, &length,
  2168.                             (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  2169.                             sp.msgAuthenticationParameters,
  2170.                             sp.msgAuthenticationParametersLength);
  2171.   if (bufPtr == NULL) {
  2172.     debugprintf(0, "usmBuildSecurityParameters error coding authparams");
  2173.     return NULL;
  2174.   }
  2175.   debugprintf(5, "Coding octstr sp.msgPr..Para.. , length = 0x%lx",
  2176.       sp.msgPrivacyParametersLength);
  2177.   bufPtr = asn_build_string(bufPtr, &length,
  2178.                             (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  2179.                             sp.msgPrivacyParameters,
  2180.                             sp.msgPrivacyParametersLength);
  2181.   if (bufPtr == NULL) {
  2182.     debugprintf(0, "usmBuildSecurityParameters error coding privparams");
  2183.     return NULL;
  2184.   }
  2185.   totalLength = SAFE_INT_CAST(bufPtr - buf.get_ptr());
  2186.   debugprintf(5, "Coding sequence (securityPar), length = 0x%x", totalLength);
  2187.   outBufPtr = asn_build_sequence(outBufPtr, maxLength,
  2188.                                  (unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
  2189.                                  totalLength);
  2190.   if (outBufPtr == NULL) {
  2191.     debugprintf(0, "usm: usmBuildSecurityParameters error coding secparams");
  2192.     return NULL;
  2193.   }
  2194.   if (*maxLength < totalLength) {
  2195.     debugprintf(0, "usm: usmBuildSecurityParameters error (length mismatch)");
  2196.     return NULL;
  2197.   }
  2198.   *position += SAFE_INT_CAST(outBufPtr - outBuf);
  2199.   memcpy(outBufPtr, buf.get_ptr(), totalLength);
  2200.   outBufPtr += totalLength;
  2201.   *maxLength -= totalLength;
  2202.   debugprintf(21, "bufSecurityData:");
  2203.   debughexprintf(21, outBuf, SAFE_INT_CAST(outBufPtr - outBuf));
  2204.   return outBufPtr;
  2205. }
  2206. unsigned char *USM::build_whole_msg(
  2207.                          unsigned char *outBuf, int *maxLength,
  2208.  unsigned char *globalData, long int globalDataLength,
  2209.  int *positionAuthPar,
  2210.  struct UsmSecurityParameters  securityParameters,
  2211.  unsigned char *msgData, long int msgDataLength)
  2212. {
  2213.   Buffer<unsigned char> buf(MAX_SNMP_PACKET);
  2214.   unsigned char *bufPtr = buf.get_ptr();
  2215.   Buffer<unsigned char> secPar(MAX_SNMP_PACKET);
  2216.   unsigned char *secParPtr = secPar.get_ptr();
  2217.   unsigned char *outBufPtr = outBuf;
  2218.   long int secParLength;
  2219.   int length = *maxLength;
  2220.   int totalLength;
  2221.   int dummy = *maxLength;
  2222.   secParPtr = build_sec_params(secParPtr, &dummy, securityParameters,
  2223.        positionAuthPar);
  2224.   if (!secParPtr)
  2225.     return NULL;
  2226.   secParLength = SAFE_INT_CAST(secParPtr - secPar.get_ptr());
  2227.   long int dummyVersion = 3;
  2228.   debugprintf(3, "Coding int snmpVersion = 0x%lx",dummyVersion);
  2229.   bufPtr = asn_build_int(bufPtr, &length,
  2230.                          (unsigned char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  2231.                          (long*)&dummyVersion,
  2232.                          sizeof(dummyVersion));
  2233.   if (bufPtr == NULL) {
  2234.     debugprintf(0, "usmBuildWholeMsg error");
  2235.     return NULL;
  2236.   }
  2237.   // globalData is encoded as sequence
  2238.   length -= globalDataLength;
  2239.   if (length < 0) {
  2240.     debugprintf(0, "usmBuildWholeMsg error");
  2241.     return NULL;
  2242.   }
  2243.   memcpy(bufPtr, globalData, globalDataLength);
  2244.   bufPtr += globalDataLength;
  2245.   *positionAuthPar += SAFE_INT_CAST(bufPtr - buf.get_ptr()) +2;
  2246.   if (secParLength> 0x7f)
  2247.     *positionAuthPar += 2;
  2248.   debugprintf(3, "Coding octstr securityParameter, length = 0x%lx",
  2249.               secParLength);
  2250.   bufPtr = asn_build_string(bufPtr, &length,
  2251.                             (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  2252.                             secPar.get_ptr(), secParLength);
  2253.   if (bufPtr == NULL) {
  2254.     debugprintf(0, "usmBuildWholeMsg error2");
  2255.     return NULL;
  2256.   }
  2257.   // msgData (ScopedPduData) is encoded
  2258.   length -=msgDataLength;
  2259.   if (length < 0) {
  2260.     debugprintf(10, "usmBuildWholeMsg error: msgDataLength = %i",
  2261.                 msgDataLength);
  2262.     debugprintf(10, "maxLength = %i, encoded = %i", *maxLength,
  2263.                 SAFE_INT_CAST(bufPtr - buf.get_ptr()));
  2264.     return NULL;
  2265.   }
  2266.   memcpy(bufPtr, msgData, msgDataLength);
  2267.   bufPtr += msgDataLength;
  2268.   totalLength = SAFE_INT_CAST(bufPtr - buf.get_ptr());
  2269.   debugprintf(3, "Coding sequence (wholeMsg), length = 0x%x", totalLength);
  2270.   outBufPtr = asn_build_sequence(outBufPtr, maxLength,
  2271.                                  (unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
  2272.                                  totalLength);
  2273.   if (outBufPtr == NULL) {
  2274.     debugprintf(0, "usm: usmBuildWholeMsg error");
  2275.     return NULL;
  2276.   }
  2277.   if (*maxLength < totalLength) {
  2278.     debugprintf(0, "usm: usmBuildWholeMsg error");
  2279.     return NULL;
  2280.   }
  2281.   *positionAuthPar += SAFE_INT_CAST(outBufPtr - outBuf);
  2282.   memcpy(outBufPtr, buf.get_ptr(), totalLength);
  2283.   outBufPtr += totalLength;
  2284.   *maxLength -= totalLength;
  2285.   debugprintf(21,"bufWholeMsg:");
  2286.   debughexprintf(21, outBuf, SAFE_INT_CAST(outBufPtr - outBuf));
  2287.   return outBufPtr;
  2288. }
  2289. inline void USM::delete_user_ptr(struct UsmUser *user)
  2290. {
  2291.   if (!user) return;
  2292.   if (user->engineID) {
  2293.     delete [] user->engineID;
  2294.     user->engineID = NULL;
  2295.   }
  2296.   if (user->usmUserName) {
  2297.     delete [] user->usmUserName;
  2298.     user->usmUserName = NULL;
  2299.   }
  2300.   if (user->securityName) {
  2301.     delete [] user->securityName;
  2302.     user->securityName = NULL;
  2303.   }
  2304.   if (user->authKey) {
  2305.     memset(user->authKey, 0, user->authKeyLength);
  2306.     delete [] user->authKey;
  2307.     user->authKey = NULL;
  2308.   }
  2309.   if (user->privKey) {
  2310.     memset(user->privKey, 0, user->privKeyLength);
  2311.     delete [] user->privKey;
  2312.     user->authKey = NULL;
  2313.   }
  2314. }
  2315. // Save all localized users into a file.
  2316. int USM::save_localized_users(const char *file)
  2317. {
  2318.   return usm_user_table->save_to_file(file, auth_priv);
  2319. }
  2320. // Load localized users from a file.
  2321. int USM::load_localized_users(const char *file)
  2322. {
  2323.   return usm_user_table->load_from_file(file, auth_priv);
  2324. }
  2325. // Safe all users with their passwords into a file.
  2326. int USM::save_users(const char *file)
  2327. {
  2328.   return usm_user_name_table->save_to_file(file, auth_priv);
  2329. }
  2330. // Load users with their passwords from a file.
  2331. int USM::load_users(const char *file)
  2332. {
  2333.   return usm_user_name_table->load_from_file(file, auth_priv);
  2334. }
  2335. // Lock the UsmUserNameTable for access through peek_first/next_user()
  2336. void USM::lock_user_name_table()
  2337. {
  2338.   usm_user_name_table->lock();
  2339. }
  2340. // Get a const pointer to the first entry of the UsmUserNameTable.
  2341. const UsmUserNameTableEntry *USM::peek_first_user()
  2342. {
  2343.   return usm_user_name_table->peek_first();
  2344. }
  2345. // Get a const pointer to the next entry of the UsmUserNameTable.
  2346. const UsmUserNameTableEntry *USM::peek_next_user(const UsmUserNameTableEntry *e)
  2347. {
  2348.   return usm_user_name_table->peek_next(e);
  2349. }
  2350. // Unlock the UsmUserNameTable after access through peek_first/next_user()
  2351. void USM::unlock_user_name_table()
  2352. {
  2353.   usm_user_name_table->unlock();
  2354. }
  2355. // Lock the UsmUserTable for access through peek_first/next_luser()
  2356. void USM::lock_user_table()
  2357. {
  2358.   usm_user_table->lock();
  2359. }
  2360. // Get a const pointer to the first entry of the UsmUserTable.
  2361. const UsmUserTableEntry *USM::peek_first_luser()
  2362. {
  2363.   return usm_user_table->peek_first();
  2364. }
  2365. // Get a const pointer to the next entry of the UsmUserTable.
  2366. const UsmUserTableEntry *USM::peek_next_luser(const UsmUserTableEntry *e)
  2367. {
  2368.   return usm_user_table->peek_next(e);
  2369. }
  2370. // Unlock the UsmUserTable after access through peek_first/next_luser()
  2371. void USM::unlock_user_table()
  2372. {
  2373.   usm_user_table->unlock();
  2374. }
  2375. /* ----------------------- class USMTimeTable --------------------*/
  2376. USMTimeTable::USMTimeTable(const USM *owner,
  2377.    const unsigned int engine_boots, int &result)
  2378. {
  2379.   time_t now;
  2380.   table = new struct Entry_T[5];
  2381.   if (!table)
  2382.   {
  2383.     LOG_BEGIN(ERROR_LOG | 1);
  2384.     LOG("USMTimeTable: error constructing table.");
  2385.     LOG_END;
  2386.     result = SNMPv3_USM_ERROR;
  2387.     return;
  2388.   }
  2389.   usm = owner;
  2390.   /* the first entry always contains the local engine id and time */
  2391.   time(&now);
  2392.   table[0].time_diff     = - SAFE_LONG_CAST(now);
  2393.   table[0].engine_boots  = engine_boots;
  2394.   table[0].engine_id_len = min(usm->get_local_engine_id().len(),
  2395.        MAXLENGTH_ENGINEID);
  2396.   memcpy(table[0].engine_id, usm->get_local_engine_id().data(),
  2397.  table[0].engine_id_len);
  2398.   entries = 1;
  2399.   max_entries = 5;
  2400.   result = SNMPv3_USM_OK;
  2401. }
  2402. USMTimeTable::~USMTimeTable()
  2403. {
  2404.   if (table)
  2405.   {
  2406.     delete [] table;
  2407.     table = NULL;
  2408.   }
  2409.   entries = 0;
  2410.   max_entries = 0;
  2411. }
  2412. int USMTimeTable::add_entry(const OctetStr &engine_id,
  2413.                             const long int engine_boots,
  2414.                             const long int engine_time)
  2415. {
  2416.   if (!table)
  2417.     return SNMPv3_USM_ERROR;
  2418.   LOG_BEGIN(INFO_LOG | 11);
  2419.   LOG("USMTimeTable: Adding entry (engine id) (boot) (time)");
  2420.   LOG(engine_id.get_printable());
  2421.   LOG(engine_boots);
  2422.   LOG(engine_time);
  2423.   LOG_END;
  2424.   BEGIN_REENTRANT_CODE_BLOCK;
  2425.   if (entries == max_entries)
  2426.   {
  2427.     /* resize Table */
  2428.     struct Entry_T *tmp = new struct Entry_T[4 * max_entries];
  2429.     if (!tmp)
  2430.       return SNMPv3_USM_ERROR;
  2431.     memcpy(tmp, table, entries * sizeof(Entry_T));
  2432.     struct Entry_T *victim = table;
  2433.     table = tmp;
  2434.     delete [] victim;
  2435.     max_entries *= 4;
  2436.   }
  2437.   time_t now;
  2438.   time(&now);
  2439.   table[entries].engine_boots = engine_boots;
  2440.   table[entries].latest_received_time = engine_time;
  2441.   table[entries].time_diff = engine_time - SAFE_ULONG_CAST(now);
  2442.   table[entries].engine_id_len = engine_id.len();
  2443.   table[entries].engine_id_len = min(table[entries].engine_id_len,
  2444.                                      MAXLENGTH_ENGINEID);
  2445.   memcpy(table[entries].engine_id,
  2446.  engine_id.data(), table[entries].engine_id_len);
  2447.   entries++;
  2448.   return SNMPv3_USM_OK;
  2449. }
  2450. // Delete this engine id from the table.
  2451. int USMTimeTable::delete_entry(const OctetStr &engine_id)
  2452. {
  2453.   if (!table)
  2454.     return SNMPv3_USM_ERROR;
  2455.   LOG_BEGIN(INFO_LOG | 12);
  2456.   LOG("USMTimeTable: Deleting entry (engine id)");
  2457.   LOG(engine_id.get_printable());
  2458.   LOG_END;
  2459.   BEGIN_REENTRANT_CODE_BLOCK;
  2460.   for (int i=1; i < entries; i++) /* start from 1 */
  2461.     if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
  2462.                             engine_id.data(), engine_id.len()))
  2463.     {
  2464.       if (i != entries - 1)
  2465. table[i] = table[entries - 1];
  2466.       entries--;
  2467.     
  2468.       return SNMPv3_USM_OK;
  2469.     }
  2470.   return SNMPv3_USM_OK;
  2471. }
  2472. unsigned long USMTimeTable::get_local_time()
  2473. {
  2474.   if (!table)
  2475.     return 0;
  2476.   BEGIN_REENTRANT_CODE_BLOCK;
  2477.   time_t now;
  2478.   time(&now);
  2479.   return table[0].time_diff + SAFE_ULONG_CAST(now);
  2480. }
  2481. int USMTimeTable::get_local_time(long int &engine_boots,
  2482.                                  long int &engine_time)
  2483. {
  2484.   if (!table)
  2485.     return SNMPv3_USM_ERROR;
  2486.   BEGIN_REENTRANT_CODE_BLOCK;
  2487.   time_t now;
  2488.   time(&now);
  2489.   engine_boots = table[0].engine_boots;
  2490.   engine_time  = table[0].time_diff + SAFE_ULONG_CAST(now);
  2491.   LOG_BEGIN(DEBUG_LOG | 11);
  2492.   LOG("USMTimeTable: returning local time (boots) (time)");
  2493.   LOG(engine_boots);
  2494.   LOG(engine_time);
  2495.   LOG_END;
  2496.   return SNMPv3_USM_OK;
  2497. }
  2498. int USMTimeTable::get_time(const OctetStr &engine_id,
  2499.                            long int &engine_boots, long int &engine_time)
  2500. {
  2501.   if (!table)
  2502.     return SNMPv3_USM_ERROR;
  2503.   BEGIN_REENTRANT_CODE_BLOCK;
  2504.   for (int i=0; i < entries; i++)
  2505.     if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
  2506.                             engine_id.data(), engine_id.len()))
  2507.     {
  2508.       /* Entry found */
  2509.       time_t now;
  2510.       time(&now);
  2511.       engine_boots = table[i].engine_boots;
  2512.       engine_time  = table[i].time_diff + SAFE_ULONG_CAST(now);
  2513.       LOG_BEGIN(INFO_LOG | 4);
  2514.       LOG("USMTimeTable: Returning time (engine id) (boot) (time)");
  2515.       LOG(engine_id.get_printable());
  2516.       LOG(engine_boots);
  2517.       LOG(engine_time);
  2518.       LOG_END;
  2519.       return SNMPv3_USM_OK;
  2520.     }
  2521.   /* no entry */
  2522.   engine_boots = 0;
  2523.   engine_time = 0;
  2524.   LOG_BEGIN(INFO_LOG | 4);
  2525.   LOG("USMTimeTable: No entry found for (engine id)");
  2526.   LOG(engine_id.get_printable());
  2527.   LOG_END;
  2528.   return SNMPv3_USM_UNKNOWN_ENGINEID;
  2529. }
  2530. int USMTimeTable::check_time(const OctetStr &engine_id,
  2531.                              const long int engine_boots,
  2532.                              const long int engine_time)
  2533. {
  2534.   if (!table)
  2535.     return SNMPv3_USM_ERROR;
  2536.   BEGIN_REENTRANT_CODE_BLOCK;
  2537.   time_t now;
  2538.   time(&now);
  2539.   /* table[0] contains the local engine_id and time */
  2540.   if (unsignedCharCompare(table[0].engine_id, table[0].engine_id_len,
  2541.                           engine_id.data(), engine_id.len()))
  2542.   {
  2543.     /* Entry found, we are authoritative */
  2544.     if ((table[0].engine_boots == 2147483647) ||
  2545.         (table[0].engine_boots != engine_boots) ||
  2546.         (labs(SAFE_ULONG_CAST(now) + table[0].time_diff - engine_time) > 150))
  2547.     {
  2548.       LOG_BEGIN(DEBUG_LOG | 9);
  2549.       LOG("USMTimeTable: Check time failed, authoritative (id) (boot) (time)");
  2550.       LOG(engine_id.get_printable());
  2551.       LOG(engine_boots);
  2552.       LOG(engine_time);
  2553.       LOG_END;
  2554.       return SNMPv3_USM_NOT_IN_TIME_WINDOW;
  2555.     }
  2556.     else
  2557.     {
  2558.       LOG_BEGIN(DEBUG_LOG | 9);
  2559.       LOG("USMTimeTable: Check time ok, authoritative (id)");
  2560.       LOG(engine_id.get_printable());
  2561.       LOG_END;
  2562.       return SNMPv3_USM_OK;
  2563.     }
  2564.   }
  2565.   for (int i=1; i < entries; i++)
  2566.     if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
  2567.                             engine_id.data(), engine_id.len()))
  2568.     {
  2569.       /* Entry found we are not authoritative */
  2570.       if ((engine_boots < table[i].engine_boots) ||
  2571.           ((engine_boots == table[i].engine_boots) &&
  2572.            (table[i].time_diff + now > engine_time + 150)) ||
  2573.           (table[i].engine_boots == 2147483647))
  2574.       {
  2575. LOG_BEGIN(DEBUG_LOG | 9);
  2576. LOG("USMTimeTable: Check time failed, not authoritative (id)");
  2577. LOG(engine_id.get_printable());
  2578. LOG_END;
  2579.         return SNMPv3_USM_NOT_IN_TIME_WINDOW;
  2580.       }
  2581.       else
  2582.       {
  2583.         if ((engine_boots > table[i].engine_boots) ||
  2584.             ((engine_boots == table[i].engine_boots) &&
  2585.              (engine_time > table[i].latest_received_time)))
  2586.         {
  2587.           /* time ok, update values */
  2588.           table[i].engine_boots = engine_boots;
  2589.           table[i].latest_received_time  = engine_time;
  2590.           table[i].time_diff = engine_time - SAFE_ULONG_CAST(now);
  2591.         }
  2592. LOG_BEGIN(DEBUG_LOG | 9);
  2593. LOG("USMTimeTable: Check time ok, not authoritative, updated (id)");
  2594. LOG(engine_id.get_printable());
  2595. LOG_END;
  2596.         return SNMPv3_USM_OK;
  2597.       }
  2598.     }
  2599.   LOG_BEGIN(DEBUG_LOG | 9);
  2600.   LOG("USMTimeTable: Check time, engine id not found");
  2601.   LOG(engine_id.get_printable());
  2602.   LOG_END;
  2603.   return SNMPv3_USM_UNKNOWN_ENGINEID;
  2604. }
  2605. int USMTimeTable::check_engine_id(const OctetStr &engine_id)
  2606. {
  2607.   if (!table)
  2608.     return SNMPv3_USM_ERROR;
  2609.   {
  2610.     // Begin reentrant code block
  2611.     BEGIN_REENTRANT_CODE_BLOCK;
  2612.     for (int i=0; i < entries; i++)
  2613.       if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
  2614.       engine_id.data(), engine_id.len()))
  2615. return SNMPv3_USM_OK;
  2616.   }
  2617.   /* if in discovery mode:  accept all EngineID's (rfc2264 page 26) */
  2618.   if (usm->is_discovery_enabled())
  2619.     return add_entry(engine_id, 0, 0);
  2620.   LOG_BEGIN(DEBUG_LOG | 9);
  2621.   LOG("USMTimeTable: Check id, not found (id)");
  2622.   LOG(engine_id.get_printable());
  2623.   LOG_END;
  2624.   return SNMPv3_USM_ERROR;
  2625. }
  2626. /* ------------------------- USMUserNameTable ----------------------*/
  2627. USMUserNameTable::USMUserNameTable(int &result)
  2628. {
  2629.   /* init Table */
  2630.   table = new struct UsmUserNameTableEntry[10];
  2631.   if (!table)
  2632.   {
  2633.     result = SNMPv3_USM_ERROR;
  2634.     return;
  2635.   }
  2636.   max_entries = 10;
  2637.   entries = 0;
  2638.   result = SNMPv3_USM_OK;
  2639. }
  2640. USMUserNameTable::~USMUserNameTable()
  2641. {
  2642.   if (table)
  2643.   {
  2644.     for (int i=0; i < entries; i++)
  2645.     {
  2646.       if (table[i].authPassword)
  2647.       {
  2648.         memset(table[i].authPassword, 0, table[i].authPasswordLength);
  2649.         delete [] table[i].authPassword;
  2650.       }
  2651.       if (table[i].privPassword)
  2652.       {
  2653.         memset(table[i].privPassword, 0, table[i].privPasswordLength);
  2654.         delete [] table[i].privPassword;
  2655.       }
  2656.     }
  2657.     delete [] table;
  2658.     table = NULL;
  2659.   }
  2660.   entries = 0;
  2661.   max_entries = 0;
  2662. }
  2663. int USMUserNameTable::add_entry(const OctetStr& user_name,
  2664.                                 const OctetStr& security_name,
  2665.                                 const long int  auth_proto,
  2666.                                 const long int  priv_proto,
  2667.                                 const OctetStr& auth_pass,
  2668.                                 const OctetStr& priv_pass)
  2669. {
  2670.   if (!table)
  2671.     return SNMPv3_USM_ERROR;
  2672.   BEGIN_REENTRANT_CODE_BLOCK;
  2673.   int found=0;
  2674.   int i;
  2675.   for (i = 0; i < entries; i++)
  2676.     if (table[i].usmUserName == user_name)
  2677.     {
  2678.       found=1;
  2679.       break;
  2680.     }
  2681.   if (found)
  2682.   {
  2683.     /* replace user */
  2684.     table[i].usmUserSecurityName = security_name;
  2685.     table[i].usmUserAuthProtocol = auth_proto;
  2686.     table[i].usmUserPrivProtocol = priv_proto;
  2687.     if (table[i].authPassword)
  2688.     {
  2689.       memset(table[i].authPassword, 0, table[i].authPasswordLength);
  2690.       delete [] table[i].authPassword;
  2691.     }
  2692.     table[i].authPassword = v3strcpy(auth_pass.data(), auth_pass.len());
  2693.     table[i].authPasswordLength = auth_pass.len();
  2694.     if (table[i].privPassword)
  2695.     {
  2696.       memset(table[i].privPassword, 0, table[i].privPasswordLength);
  2697.       delete [] table[i].privPassword;
  2698.     }
  2699.     table[i].privPassword = v3strcpy(priv_pass.data(), priv_pass.len());
  2700.     table[i].privPasswordLength = priv_pass.len();
  2701.   }
  2702.   else
  2703.   {
  2704.     if (entries == max_entries)
  2705.     {
  2706.       /* resize Table */
  2707.       struct UsmUserNameTableEntry *tmp;
  2708.       tmp = new struct UsmUserNameTableEntry[4 * max_entries];
  2709.       if (!tmp)
  2710.         return SNMPv3_USM_ERROR;
  2711.       for (i=0; i < entries; i++)
  2712.         tmp[i] = table[i];
  2713.       struct UsmUserNameTableEntry *victim = table;
  2714.       table = tmp;
  2715.       delete [] victim;
  2716.       max_entries *= 4;
  2717.     }
  2718.     table[entries].usmUserName          = user_name;
  2719.     table[entries].usmUserSecurityName  = security_name;
  2720.     table[entries].usmUserAuthProtocol  = auth_proto;
  2721.     table[entries].usmUserPrivProtocol  = priv_proto;
  2722.     table[entries].authPasswordLength = auth_pass.len();
  2723.     table[entries].authPassword = v3strcpy(auth_pass.data(), auth_pass.len());
  2724.     if (!table[entries].authPassword)
  2725.       return SNMPv3_USM_ERROR;
  2726.     table[entries].privPasswordLength = priv_pass.len();
  2727.     table[entries].privPassword = v3strcpy(priv_pass.data(), priv_pass.len());
  2728.     if (!table[entries].privPassword)
  2729.       return SNMPv3_USM_ERROR;
  2730.     entries++;
  2731.   }
  2732.   return SNMPv3_USM_OK;
  2733. }
  2734. int USMUserNameTable::delete_security_name(const OctetStr& security_name)
  2735. {
  2736.   if (!table)
  2737.     return SNMPv3_USM_ERROR;
  2738.   BEGIN_REENTRANT_CODE_BLOCK;
  2739.   for (int i = 0; i < entries; i++)
  2740.     if (table[i].usmUserSecurityName == security_name)
  2741.     {
  2742.       memset(table[i].authPassword, 0, table[i].authPasswordLength);
  2743.       delete [] table[i].authPassword;
  2744.       memset(table[i].privPassword, 0, table[i].privPasswordLength);
  2745.       delete [] table[i].privPassword;
  2746.       entries--;
  2747.       if (entries > i)
  2748.         table[i] = table[entries];
  2749.       break;
  2750.     }
  2751.   return SNMPv3_USM_OK;
  2752. }
  2753. const struct UsmUserNameTableEntry* USMUserNameTable::get_entry(
  2754.                                           const OctetStr &security_name)
  2755. {
  2756.   if (!table)
  2757.     return NULL;
  2758.   for (int i = 0; i < entries; i++)
  2759.     if (table[i].usmUserSecurityName == security_name)
  2760.       return &table[i];
  2761.   return NULL;
  2762. }
  2763. struct UsmUserNameTableEntry* USMUserNameTable::get_cloned_entry(const OctetStr &security_name)
  2764. {
  2765.   lock();
  2766.   const struct UsmUserNameTableEntry *e = get_entry(security_name);
  2767.   struct UsmUserNameTableEntry *res = 0;
  2768.   if (e)
  2769.   {
  2770.     res = new struct UsmUserNameTableEntry;
  2771.   }
  2772.   if (res)
  2773.   {
  2774.     res->usmUserName = e->usmUserName;
  2775.     res->usmUserSecurityName = e->usmUserSecurityName;
  2776.     res->usmUserAuthProtocol = e->usmUserAuthProtocol;
  2777.     res->usmUserPrivProtocol = e->usmUserPrivProtocol;
  2778.     res->authPassword = v3strcpy(e->authPassword, e->authPasswordLength);
  2779.     res->authPasswordLength = e->authPasswordLength;
  2780.     res->privPassword = v3strcpy(e->privPassword, e->privPasswordLength);
  2781.     res->privPasswordLength = e->privPasswordLength;
  2782.     if ((res->authPasswordLength && !res->authPassword) ||
  2783. (res->privPasswordLength && !res->privPassword))
  2784.     {
  2785.       delete_cloned_entry(res);
  2786.     }
  2787.   }
  2788.   unlock();
  2789.   return res;
  2790. }
  2791. void USMUserNameTable::delete_cloned_entry(struct UsmUserNameTableEntry* &entry)
  2792. {
  2793.   if (!entry) return;
  2794.   if (entry->authPassword)
  2795.   {
  2796.     memset(entry->authPassword, 0, entry->authPasswordLength);
  2797.     delete [] entry->authPassword;
  2798.   }
  2799.   if (entry->privPassword)
  2800.   {
  2801.     memset(entry->privPassword, 0, entry->privPasswordLength);
  2802.     delete [] entry->privPassword;
  2803.   }
  2804.   delete entry;
  2805.   entry = 0;
  2806. }
  2807. int USMUserNameTable::get_security_name(const unsigned char *user_name,
  2808. const long int user_name_len,
  2809. OctetStr &security_name)
  2810. {
  2811.   if (!table)
  2812.     return SNMPv3_USM_ERROR;
  2813.   BEGIN_REENTRANT_CODE_BLOCK;
  2814.   for (int i = 0; i < entries; i++)
  2815.     if (unsignedCharCompare(table[i].usmUserName.data(),
  2816.     table[i].usmUserName.len(),
  2817.                             user_name, user_name_len))
  2818.     {
  2819.       security_name = table[i].usmUserSecurityName;
  2820.       LOG_BEGIN(INFO_LOG | 9);
  2821.       LOG("USMUserNameTable: Translated (user name) to (security name)");
  2822.       LOG(table[i].usmUserName.get_printable());
  2823.       LOG(security_name.get_printable());
  2824.       LOG_END;
  2825.   
  2826.       return SNMPv3_USM_OK;
  2827.     }
  2828.   LOG_BEGIN(WARNING_LOG | 5);
  2829.   LOG("USMUserNameTable: No entry for (user name) in table");
  2830.   LOG(OctetStr(user_name, user_name_len).get_printable());
  2831.   LOG_END;
  2832.   return SNMPv3_USM_ERROR;
  2833. }
  2834. int USMUserNameTable::get_user_name(unsigned char *user_name,
  2835.                                     long int *user_name_len,
  2836.                                     const unsigned char *security_name,
  2837.                                     const long int security_name_len)
  2838. {
  2839.   unsigned long buf_len = *user_name_len;
  2840.   *user_name_len = 0;
  2841.   if (!table)
  2842.     return SNMPv3_USM_ERROR;
  2843.   BEGIN_REENTRANT_CODE_BLOCK;
  2844.   for (int i = 0; i < entries; i++)
  2845.     if (unsignedCharCompare(table[i].usmUserSecurityName.data(),
  2846.                             table[i].usmUserSecurityName.len(),
  2847.                             security_name, security_name_len))
  2848.     {
  2849.       if (buf_len < table[i].usmUserName.len())
  2850.       {
  2851. LOG(ERROR_LOG | 1);
  2852. LOG("USMUserNameTable: Buffer for user name too small (is) (should)");
  2853. LOG(buf_len);
  2854. LOG(table[i].usmUserName.len());
  2855.         return SNMPv3_USM_ERROR;
  2856.       }
  2857.       *user_name_len = table[i].usmUserName.len();
  2858.       memcpy(user_name, table[i].usmUserName.data(),
  2859.      table[i].usmUserName.len());
  2860.       LOG_BEGIN(INFO_LOG | 9);
  2861.       LOG("USMUserNameTable: Translated (security name) to (user name)");
  2862.       LOG(table[i].usmUserSecurityName.get_printable());
  2863.       LOG(table[i].usmUserName.get_printable());
  2864.       LOG_END;
  2865.   
  2866.       return SNMPv3_USM_OK;
  2867.     }
  2868.   LOG_BEGIN(WARNING_LOG | 5);
  2869.   LOG("USMUserNameTable: No entry for (security  name) in table");
  2870.   LOG(OctetStr(security_name, security_name_len).get_printable());
  2871.   LOG_END;
  2872.   return SNMPv3_USM_ERROR;
  2873. }
  2874. // Save all entries into a file.
  2875. int USMUserNameTable::save_to_file(const char *name, AuthPriv *ap)
  2876. {
  2877.   char encoded[MAX_LINE_LEN * 2];
  2878.   FILE *file_out;
  2879.   char tmp_file_name[MAXLENGTH_FILENAME];
  2880.   bool failed = false;
  2881.   if (!name || !ap)
  2882.   {
  2883.     LOG_BEGIN(ERROR_LOG | 1);
  2884.     LOG("USMUserNameTable: save_to_file called with illegal param");
  2885.     if (!name)
  2886.     {
  2887.       LOG("filename");
  2888.     }
  2889.     if (!ap)
  2890.     {
  2891.       LOG("AuthPriv pointer");
  2892.     }
  2893.     LOG_END;
  2894.     return SNMPv3_USM_ERROR;
  2895.   }
  2896.   LOG_BEGIN(INFO_LOG | 4);
  2897.   LOG("USMUserNameTable: Saving users to file");
  2898.   LOG(name);
  2899.   LOG_END;
  2900.   sprintf(tmp_file_name, "%s.tmp", name);
  2901.   file_out = fopen(tmp_file_name, "w");
  2902.   if (!file_out)
  2903.   {
  2904.     LOG_BEGIN(ERROR_LOG | 1);
  2905.     LOG("USMUserNameTable: could not create tmpfile");
  2906.     LOG(tmp_file_name);
  2907.     LOG_END;
  2908.     return SNMPv3_USM_FILECREATE_ERROR;
  2909.   }
  2910.   {
  2911.     // Begin reentrant code block
  2912.     BEGIN_REENTRANT_CODE_BLOCK;
  2913.     for (int i=0; i < entries; ++i)
  2914.     {
  2915.       LOG_BEGIN(INFO_LOG | 8);
  2916.       LOG("USMUserNameTable: Saving user to file");
  2917.       LOG(table[i].usmUserName.get_printable());
  2918.       LOG_END;
  2919.       encodeString(table[i].usmUserName.data(), table[i].usmUserName.len(),
  2920.    encoded);
  2921.       encoded[2 * table[i].usmUserName.len()] = 'n';
  2922.       if (fwrite(encoded, 2 * table[i].usmUserName.len() + 1, 1,
  2923.  file_out) != 1)
  2924.       { failed = true; break; }
  2925.       encodeString(table[i].usmUserSecurityName.data(),
  2926.    table[i].usmUserSecurityName.len(), encoded);
  2927.       encoded[2 * table[i].usmUserSecurityName.len()] = 'n';
  2928.       if (fwrite(encoded, 2 * table[i].usmUserSecurityName.len() + 1, 1,
  2929.  file_out) != 1)
  2930.       { failed = true; break; }
  2931.       encodeString(table[i].authPassword, table[i].authPasswordLength,
  2932.    encoded);
  2933.       encoded[2 * table[i].authPasswordLength] = 'n';
  2934.       if (fwrite(encoded, 2 * table[i].authPasswordLength + 1, 1,
  2935.  file_out) != 1)
  2936.       { failed = true; break; }
  2937.       encodeString(table[i].privPassword, table[i].privPasswordLength,
  2938.    encoded);
  2939.       encoded[2 * table[i].privPasswordLength] = 'n';
  2940.       if (fwrite(encoded, 2 * table[i].privPasswordLength + 1, 1,
  2941.  file_out) != 1)
  2942.       { failed = true; break; }
  2943.     
  2944.       if (table[i].usmUserAuthProtocol == SNMP_AUTHPROTOCOL_NONE)
  2945.       {
  2946. if (fwrite("nonen", 5, 1, file_out) != 1)
  2947. { failed = true; break; }
  2948.       }
  2949.       else
  2950.       {
  2951. const Auth *a = ap->get_auth(table[i].usmUserAuthProtocol);
  2952. if (!a) { failed = true; break; }
  2953. sprintf(encoded, "%sn", a->get_id_string());
  2954. if (fwrite(encoded, strlen(a->get_id_string()) + 1, 1, file_out) != 1)
  2955. { failed = true; break; }
  2956.       }
  2957.       if (table[i].usmUserPrivProtocol == SNMP_PRIVPROTOCOL_NONE)
  2958.       {
  2959. if (fwrite("nonen", 5, 1, file_out) != 1)
  2960. { failed = true; break; }
  2961.       }
  2962.       else
  2963.       {
  2964. const Priv *p = ap->get_priv(table[i].usmUserPrivProtocol);
  2965. if (!p) { failed = true; break; }
  2966. sprintf(encoded, "%sn", p->get_id_string());
  2967. if (fwrite(encoded, strlen(p->get_id_string()) + 1, 1, file_out) != 1)
  2968. { failed = true; break; }
  2969.       }
  2970.     }
  2971.   }
  2972.   fclose(file_out);
  2973.   if (failed)
  2974.   {
  2975.     LOG_BEGIN(ERROR_LOG | 1);
  2976.     LOG("USMUserNameTable: Failed to write table entries.");
  2977.     LOG_END;
  2978. #ifdef WIN32
  2979.     _unlink(tmp_file_name);
  2980. #else
  2981.     unlink(tmp_file_name);
  2982. #endif
  2983.     return SNMPv3_USM_FILEWRITE_ERROR;
  2984.   }
  2985. #ifdef WIN32
  2986.   _unlink(name);
  2987. #else
  2988.   unlink(name);
  2989. #endif
  2990.   if (rename(tmp_file_name, name))
  2991.   {
  2992.     LOG_BEGIN(ERROR_LOG | 1);
  2993.     LOG("USMUserNameTable: Could not rename file (from) (to)");
  2994.     LOG(tmp_file_name);
  2995.     LOG(name);
  2996.     LOG_END;
  2997.     return SNMPv3_USM_FILERENAME_ERROR;
  2998.   }
  2999.   LOG_BEGIN(INFO_LOG | 4);
  3000.   LOG("USMUserNameTable: Saving users to file finished");
  3001.   LOG_END;
  3002.   return SNMPv3_USM_OK;
  3003. }
  3004. // Load the table from a file.
  3005. int USMUserNameTable::load_from_file(const char *name, AuthPriv *ap)
  3006. {
  3007.   char decoded[MAX_LINE_LEN];
  3008.   FILE *file_in;
  3009.   unsigned char line[MAX_LINE_LEN * 2];
  3010.   if (!name || !ap)
  3011.   {
  3012.     LOG_BEGIN(ERROR_LOG | 1);
  3013.     LOG("USMUserNameTable: load_to_file called with illegal param");
  3014.     if (!name)
  3015.     {
  3016.       LOG("filename");
  3017.     }
  3018.     if (!ap)
  3019.     {
  3020.       LOG("AuthPriv pointer");
  3021.     }
  3022.     LOG_END;
  3023.     return SNMPv3_USM_ERROR;
  3024.   }
  3025.   LOG_BEGIN(INFO_LOG | 4);
  3026.   LOG("USMUserNameTable: Loading users from file");
  3027.   LOG(name);
  3028.   LOG_END;
  3029.   file_in = fopen(name, "r");
  3030.   if (!file_in)
  3031.   {
  3032.     LOG_BEGIN(ERROR_LOG | 1);
  3033.     LOG("USMUserNameTable: could not open file");
  3034.     LOG(name);
  3035.     LOG_END;
  3036.     return SNMPv3_USM_FILEOPEN_ERROR;
  3037.   }
  3038.   int len;
  3039.   bool failed = false;
  3040.   while (fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3041.   {
  3042.     // user_name
  3043.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3044.     decodeString(line, len, decoded);
  3045.     OctetStr user_name((unsigned char*)decoded, len / 2);
  3046.     // security_name
  3047.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3048.     { failed = true; break; }
  3049.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3050.     decodeString(line, len, decoded);
  3051.     OctetStr user_security_name((unsigned char*)decoded, len / 2);
  3052.     // auth password
  3053.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3054.     { failed = true; break; }
  3055.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3056.     decodeString(line, len, decoded);
  3057.     OctetStr auth_pass((unsigned char*)decoded, len / 2);
  3058.     // priv password
  3059.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3060.     { failed = true; break; }
  3061.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3062.     decodeString(line, len, decoded);
  3063.     OctetStr priv_pass((unsigned char*)decoded, len / 2);
  3064.     // auth protocol
  3065.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3066.     { failed = true; break; }
  3067.     line[strlen((char*)line) - 1] = 0;
  3068.     int auth_prot = SNMP_AUTHPROTOCOL_NONE;
  3069.     if (strcmp((char*)line, "none") != 0)
  3070.     {
  3071.       auth_prot = ap->get_auth_id((char*)line);
  3072.       if (auth_prot < 0)
  3073.       { failed = true; break; }
  3074.     }
  3075.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3076.     { failed = true; break; }
  3077.     line[strlen((char*)line) - 1] = 0;
  3078.     int priv_prot = SNMP_PRIVPROTOCOL_NONE;
  3079.     if (strcmp((char*)line, "none") != 0)
  3080.     {
  3081.       priv_prot = ap->get_priv_id((char*)line);
  3082.       if (priv_prot < 0)
  3083.       { failed = true; break; }
  3084.     }
  3085.     LOG_BEGIN(INFO_LOG | 7);
  3086.     LOG("USMUserNameTable: Adding user (user name) (sec name) (auth) (priv)");
  3087.     LOG(user_name.get_printable());
  3088.     LOG(user_security_name.get_printable());
  3089.     LOG(auth_prot);
  3090.     LOG(priv_prot);
  3091.     LOG_END;
  3092.     if (add_entry(user_name, user_security_name, auth_prot, priv_prot,
  3093.   auth_pass, priv_pass) == SNMPv3_USM_ERROR)
  3094.     {
  3095.       failed = true;
  3096.       LOG_BEGIN(ERROR_LOG | 1);
  3097.       LOG("USMUserNameTable: Error adding (user name)");
  3098.       LOG(user_name.get_printable());
  3099.       LOG_END;
  3100.     }
  3101.   }
  3102.   fclose(file_in);
  3103.   if (failed)
  3104.   {
  3105.     LOG_BEGIN(ERROR_LOG | 1);
  3106.     LOG("USMUserNameTable: Failed to read table entries");
  3107.     LOG_END;
  3108.     return SNMPv3_USM_FILEREAD_ERROR;
  3109.   }
  3110.   LOG_BEGIN(INFO_LOG | 4);
  3111.   LOG("USMUserNameTable: Loaded all users from file");
  3112.   LOG_END;
  3113.   return SNMPv3_USM_OK;
  3114. }
  3115. const UsmUserNameTableEntry *USMUserNameTable::peek_next(
  3116.                        const UsmUserNameTableEntry *e) const
  3117. {
  3118.   if (e == 0) return 0;
  3119.   if (e - table < 0) return 0;
  3120.   if (e - table >= entries - 1) return 0;
  3121.   return (e + 1);
  3122. }
  3123. /* ---------------------------- USMUserTable ------------------- */
  3124. USMUserTable::USMUserTable(int &result)
  3125. {
  3126.   entries = 0;
  3127.   table = new struct UsmUserTableEntry[10];
  3128.   if (!table)
  3129.   {
  3130.     result = SNMPv3_USM_ERROR;
  3131.     return;
  3132.   }
  3133.   max_entries = 10;
  3134. }
  3135. USMUserTable::~USMUserTable()
  3136. {
  3137.   if (table)
  3138.   {
  3139.     for (int i = 0; i < entries; i++)
  3140.     {
  3141.       if (table[i].usmUserEngineID)
  3142. delete [] table[i].usmUserEngineID;
  3143.       if (table[i].usmUserName)
  3144. delete [] table[i].usmUserName;
  3145.       if (table[i].usmUserSecurityName)
  3146. delete [] table[i].usmUserSecurityName;
  3147.       if (table[i].usmUserAuthKey)
  3148.       {
  3149. memset(table[i].usmUserAuthKey, 0, table[i].usmUserAuthKeyLength);
  3150. delete [] table[i].usmUserAuthKey;
  3151.       }
  3152.       if (table[i].usmUserPrivKey)
  3153.       {
  3154. memset(table[i].usmUserPrivKey, 0, table[i].usmUserPrivKeyLength);
  3155. delete [] table[i].usmUserPrivKey;
  3156.       }
  3157.     }
  3158.     delete [] table;
  3159.     table = NULL;
  3160.     max_entries = 0;
  3161.     entries = 0;
  3162.   }
  3163. }
  3164. int USMUserTable::get_user_name(unsigned char       *user_name,
  3165. long int            *user_name_len,
  3166. const unsigned char *sec_name,
  3167. const long           sec_name_len)
  3168. {
  3169.   long buf_len = *user_name_len;
  3170.   *user_name_len = 0;
  3171.   if (!table)
  3172.     return SNMPv3_USM_ERROR;
  3173.   BEGIN_REENTRANT_CODE_BLOCK;
  3174.   for (int i=0; i < entries; i++)
  3175.     if (unsignedCharCompare(table[i].usmUserSecurityName,
  3176.     table[i].usmUserSecurityNameLength,
  3177.     sec_name, sec_name_len))
  3178.     {
  3179.       if (buf_len < table[i].usmUserNameLength)
  3180.       {
  3181. LOG_BEGIN(ERROR_LOG | 1);
  3182. LOG("USMUserTable: Buffer for user name too small (is) (should)");
  3183. LOG(buf_len);
  3184. LOG(table[i].usmUserNameLength);
  3185. LOG_END;
  3186. return SNMPv3_USM_ERROR;
  3187.       }
  3188.       *user_name_len = table[i].usmUserNameLength;
  3189.       memcpy(user_name, table[i].usmUserName, table[i].usmUserNameLength);
  3190.       LOG_BEGIN(INFO_LOG | 9);
  3191.       LOG("USMUserTable: Translated (security name) to (user name)");
  3192.       LOG(OctetStr(sec_name, sec_name_len).get_printable());
  3193.       LOG(OctetStr(table[i].usmUserName, table[i].usmUserNameLength).get_printable());
  3194.       LOG_END;
  3195.       return SNMPv3_USM_OK;
  3196.     }
  3197.   LOG_BEGIN(WARNING_LOG | 5);
  3198.   LOG("USMUserTable: No entry for (security  name) in table");
  3199.   LOG(OctetStr(sec_name, sec_name_len).get_printable());
  3200.   LOG_END;
  3201.   return SNMPv3_USM_ERROR;
  3202. }
  3203. int USMUserTable::get_security_name(const unsigned char *user_name,
  3204.     const long user_name_len,
  3205.     OctetStr &sec_name)
  3206. {
  3207.   if (!table)
  3208.     return SNMPv3_USM_ERROR;
  3209.   BEGIN_REENTRANT_CODE_BLOCK;
  3210.   for (int i=0; i < entries; i++)
  3211.     if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
  3212.     user_name, user_name_len))
  3213.     {
  3214.       sec_name.set_data(table[i].usmUserSecurityName,
  3215. table[i].usmUserSecurityNameLength);
  3216.       LOG_BEGIN(INFO_LOG | 9);
  3217.       LOG("USMUserTable: Translated (user name) to (security name)");
  3218.       LOG(OctetStr(table[i].usmUserName, table[i].usmUserNameLength).get_printable());
  3219.       LOG(sec_name.get_printable());
  3220.       LOG_END;
  3221.   
  3222.       return SNMPv3_USM_OK;
  3223.     }
  3224.   LOG_BEGIN(WARNING_LOG | 5);
  3225.   LOG("USMUserTable: No entry for (user name) in table");
  3226.   LOG(OctetStr(user_name, user_name_len).get_printable());
  3227.   LOG_END;
  3228.   return SNMPv3_USM_ERROR;
  3229. }
  3230. int USMUserTable::delete_entries(const OctetStr& user_name)
  3231. {
  3232.   if (!table)
  3233.     return SNMPv3_USM_ERROR;
  3234.   BEGIN_REENTRANT_CODE_BLOCK;
  3235.   for (int i = 0; i < entries; i++)
  3236.     if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
  3237.     user_name.data(), user_name.len()))
  3238.     {
  3239.       /* delete this entry and recheck this position */
  3240.       delete_entry(i);
  3241.       i--;
  3242.     }
  3243.   return SNMPv3_USM_OK;
  3244. }
  3245. // Delete all entries of this user from the usmUserTable
  3246. int USMUserTable::delete_engine_id(const OctetStr& engine_id)
  3247. {
  3248.   if (!table)
  3249.     return SNMPv3_USM_ERROR;
  3250.   BEGIN_REENTRANT_CODE_BLOCK;
  3251.   for (int i = 0; i < entries; i++)
  3252.     if (unsignedCharCompare(table[i].usmUserEngineID,
  3253.     table[i].usmUserEngineIDLength,
  3254.     engine_id.data(), engine_id.len()))
  3255.     {
  3256.       /* delete this entry and recheck this position*/
  3257.       delete_entry(i);
  3258.       i--;
  3259.     }
  3260.   return SNMPv3_USM_OK;
  3261. }
  3262. int USMUserTable::delete_entry(const OctetStr& engine_id,
  3263.        const OctetStr& user_name)
  3264. {
  3265.   if (!table)
  3266.     return SNMPv3_USM_ERROR;
  3267.   BEGIN_REENTRANT_CODE_BLOCK;
  3268.   for (int i = 0; i < entries; i++)
  3269.     if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
  3270.     user_name.data(), user_name.len()))
  3271.       if (unsignedCharCompare(table[i].usmUserEngineID,
  3272.       table[i].usmUserEngineIDLength,
  3273.       engine_id.data(), engine_id.len()))
  3274.       {
  3275. /* delete this entry and recheck this position*/
  3276. delete_entry(i);
  3277. i--;
  3278.       }
  3279.   return SNMPv3_USM_OK;
  3280. }
  3281. const struct UsmUserTableEntry *USMUserTable::get_entry(const int number)
  3282. {
  3283.   if ((entries < number) || (number < 1))
  3284.     return NULL;
  3285.   return &table[number - 1];
  3286. }
  3287. const struct UsmUserTableEntry *USMUserTable::get_entry(const OctetStr &engine_id,
  3288. const OctetStr &sec_name)
  3289. {
  3290.   if (!table)
  3291.     return NULL;
  3292.   for (int i = 0; i < entries; i++)
  3293.     if (unsignedCharCompare(table[i].usmUserSecurityName,
  3294.     table[i].usmUserSecurityNameLength,
  3295.     sec_name.data(), sec_name.len()))
  3296.       if (unsignedCharCompare(table[i].usmUserEngineID,
  3297.       table[i].usmUserEngineIDLength,
  3298.       engine_id.data(), engine_id.len()))
  3299. return &table[i];
  3300.   return NULL;
  3301. }
  3302. struct UsmUserTableEntry *USMUserTable::get_cloned_entry(
  3303.                                  const OctetStr &engine_id,
  3304.  const OctetStr &sec_name)
  3305. {
  3306.   lock();
  3307.   const struct UsmUserTableEntry *e = get_entry(engine_id, sec_name);
  3308.   struct UsmUserTableEntry *res = 0;
  3309.   if (e)
  3310.   {
  3311.     res = new struct UsmUserTableEntry;
  3312.   }
  3313.   if (res)
  3314.   {
  3315.     res->usmUserEngineID       = v3strcpy(e->usmUserEngineID,
  3316.   e->usmUserEngineIDLength);
  3317.     res->usmUserEngineIDLength = e->usmUserEngineIDLength;
  3318.     res->usmUserName           = v3strcpy(e->usmUserName,
  3319.   e->usmUserNameLength);
  3320.     res->usmUserNameLength     = e->usmUserNameLength;
  3321.     res->usmUserSecurityName   = v3strcpy(e->usmUserSecurityName,
  3322.   e->usmUserSecurityNameLength);
  3323.     res->usmUserSecurityNameLength = e->usmUserSecurityNameLength;
  3324.     res->usmUserAuthProtocol   = e->usmUserAuthProtocol;
  3325.     res->usmUserAuthKey        = v3strcpy(e->usmUserAuthKey,
  3326.   e->usmUserAuthKeyLength);
  3327.     res->usmUserAuthKeyLength  = e->usmUserAuthKeyLength;
  3328.     res->usmUserPrivProtocol   = e->usmUserPrivProtocol;
  3329.     res->usmUserPrivKey        = v3strcpy(e->usmUserPrivKey,
  3330.   e->usmUserPrivKeyLength);
  3331.     res->usmUserPrivKeyLength  = e->usmUserPrivKeyLength;
  3332.     if ((res->usmUserEngineIDLength && !res->usmUserEngineID) ||
  3333. (res->usmUserNameLength && !res->usmUserName) ||
  3334. (res->usmUserSecurityNameLength && !res->usmUserSecurityName) ||
  3335. (res->usmUserAuthKeyLength && !res->usmUserAuthKey) ||
  3336. (res->usmUserPrivKeyLength && !res->usmUserPrivKey))
  3337.     {
  3338.       delete_cloned_entry(res);
  3339.     }
  3340.   }
  3341.   unlock();
  3342.   return res;
  3343. }
  3344. void USMUserTable::delete_cloned_entry(struct UsmUserTableEntry* &entry)
  3345. {
  3346.   if (!entry) return;
  3347.   if (entry->usmUserEngineID) delete [] entry->usmUserEngineID;
  3348.   if (entry->usmUserName)     delete [] entry->usmUserName;
  3349.   if (entry->usmUserSecurityName) delete [] entry->usmUserSecurityName;
  3350.   if (entry->usmUserAuthKey)
  3351.   {
  3352.     memset(entry->usmUserAuthKey, 0, entry->usmUserAuthKeyLength);
  3353.     delete [] entry->usmUserAuthKey;
  3354.   }
  3355.   if (entry->usmUserPrivKey)
  3356.   {
  3357.     memset(entry->usmUserPrivKey, 0, entry->usmUserPrivKeyLength);
  3358.     delete [] entry->usmUserPrivKey;
  3359.   }
  3360.   delete entry;
  3361.   entry = 0;
  3362. }
  3363. const struct UsmUserTableEntry *USMUserTable::get_entry(const OctetStr &sec_name)
  3364. {
  3365.   if (!table)
  3366.     return NULL;
  3367.   for (int i = 0; i < entries; i++)
  3368.     if (unsignedCharCompare(table[i].usmUserSecurityName,
  3369.     table[i].usmUserSecurityNameLength,
  3370.     sec_name.data(), sec_name.len()))
  3371.       return &table[i];
  3372.   return NULL;
  3373. }
  3374. int USMUserTable::add_entry(
  3375.                       const OctetStr &engine_id,
  3376.       const OctetStr &user_name,  const OctetStr &sec_name,
  3377.       const long int  auth_proto, const OctetStr &auth_key,
  3378.       const long int  priv_proto, const OctetStr &priv_key)
  3379. {
  3380.   LOG_BEGIN(INFO_LOG | 7);
  3381.   LOG("USMUserTable: Adding user (user name) (engine id) (auth) (priv)");
  3382.   LOG(user_name.get_printable());
  3383.   LOG(engine_id.get_printable());
  3384.   LOG(auth_proto);
  3385.   LOG(priv_proto);
  3386.   LOG_END;
  3387.   if (!table)
  3388.     return SNMPv3_USM_ERROR;
  3389.   BEGIN_REENTRANT_CODE_BLOCK;
  3390.   if (entries == max_entries)
  3391.   {
  3392.     /* resize Table */
  3393.     struct UsmUserTableEntry *tmp;
  3394.     tmp = new struct UsmUserTableEntry[4 * max_entries];
  3395.     if (!tmp) return SNMPv3_USM_ERROR;
  3396.     for (int i = 0; i < entries; i++)
  3397.       tmp[i] = table[i];
  3398.     delete [] table;
  3399.     table = tmp;
  3400.     max_entries *= 4;
  3401.   }
  3402.   for (int i = 0; i < entries; i++)
  3403.     if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
  3404.     user_name.data(), user_name.len()))
  3405.       if (unsignedCharCompare(table[i].usmUserEngineID,
  3406.       table[i].usmUserEngineIDLength,
  3407.       engine_id.data(), engine_id.len()))
  3408.       {
  3409. /* delete this entry */
  3410. delete_entry(i);
  3411. break;
  3412.       }
  3413.   /* add user at the last position */
  3414.   table[entries].usmUserEngineIDLength = engine_id.len();
  3415.   table[entries].usmUserEngineID       = v3strcpy(engine_id.data(),
  3416.   engine_id.len());
  3417.   table[entries].usmUserNameLength     = user_name.len();
  3418.   table[entries].usmUserName           = v3strcpy(user_name.data(),
  3419.   user_name.len());
  3420.   table[entries].usmUserSecurityNameLength = sec_name.len();
  3421.   table[entries].usmUserSecurityName   = v3strcpy(sec_name.data(),
  3422.   sec_name.len());
  3423.   table[entries].usmUserAuthProtocol   = auth_proto;
  3424.   table[entries].usmUserAuthKeyLength  = auth_key.len();
  3425.   table[entries].usmUserAuthKey        = v3strcpy(auth_key.data(),
  3426.   auth_key.len());
  3427.   table[entries].usmUserPrivProtocol   = priv_proto;
  3428.   table[entries].usmUserPrivKeyLength  = priv_key.len();
  3429.   table[entries].usmUserPrivKey        = v3strcpy(priv_key.data(),
  3430.   priv_key.len());
  3431.   entries++;
  3432.   return SNMPv3_USM_OK;
  3433. }
  3434. int USMUserTable::update_key(const OctetStr &user_name,
  3435.      const OctetStr &engine_id,
  3436.      const OctetStr &new_key,
  3437.      const int key_type)
  3438. {
  3439.   LOG_BEGIN(INFO_LOG | 7);
  3440.   LOG("USMUserTable: Update key for user (name) (engine id) (type)");
  3441.   LOG(user_name.get_printable());
  3442.   LOG(engine_id.get_printable());
  3443.   LOG(key_type);
  3444.   LOG_END;
  3445.   if (!table)
  3446.     return SNMPv3_USM_ERROR;
  3447.   BEGIN_REENTRANT_CODE_BLOCK;
  3448.   for (int i = 0; i < entries; i++)
  3449.     if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
  3450.     user_name.data(), user_name.len()))
  3451.       if (unsignedCharCompare(table[i].usmUserEngineID,
  3452.       table[i].usmUserEngineIDLength,
  3453.       engine_id.data(), engine_id.len()))
  3454.       {
  3455. LOG_BEGIN(DEBUG_LOG | 15);
  3456. LOG("USMUserTable: New key");
  3457. LOG(new_key.get_printable());
  3458. LOG_END;
  3459. /* update key: */
  3460. switch (key_type)
  3461. {
  3462.   case AUTHKEY:
  3463.   case OWNAUTHKEY:
  3464.   {
  3465.     if (table[i].usmUserAuthKey)
  3466.     {
  3467.       memset(table[i].usmUserAuthKey, 0,
  3468.      table[i].usmUserAuthKeyLength);
  3469.       delete [] table[i].usmUserAuthKey;
  3470.     }
  3471.     table[i].usmUserAuthKeyLength = new_key.len();
  3472.     table[i].usmUserAuthKey = v3strcpy(new_key.data(), new_key.len());
  3473.     return SNMPv3_USM_OK;
  3474.   }
  3475.   case PRIVKEY:
  3476.   case OWNPRIVKEY:
  3477.   {
  3478.     if (table[i].usmUserPrivKey)
  3479.     {
  3480.       memset(table[i].usmUserPrivKey, 0,
  3481.      table[i].usmUserPrivKeyLength);
  3482.       delete [] table[i].usmUserPrivKey;
  3483.     }
  3484.     table[i].usmUserPrivKeyLength = new_key.len();
  3485.     table[i].usmUserPrivKey = v3strcpy(new_key.data(), new_key.len());
  3486.     return SNMPv3_USM_OK;
  3487.   }
  3488.   default:
  3489.   {
  3490.     LOG_BEGIN(WARNING_LOG | 3);
  3491.     LOG("USMUserTable: setting new key failed (wrong type).");
  3492.     LOG_END;
  3493.     return SNMPv3_USM_ERROR;
  3494.   }
  3495. }
  3496.       }
  3497.   LOG_BEGIN(INFO_LOG | 7);
  3498.   LOG("USMUserTable: setting new key failed (user) not found");
  3499.   LOG(user_name.get_printable());
  3500.   LOG_END;
  3501.   return SNMPv3_USM_ERROR;
  3502. }
  3503. void USMUserTable::delete_entry(const int nr)
  3504. {
  3505.   /* Table is locked through caller, so do NOT lock table!
  3506.    * All checks have been made, so dont check again!
  3507.    */
  3508.   if (table[nr].usmUserEngineID)     delete [] table[nr].usmUserEngineID;
  3509.   if (table[nr].usmUserName)         delete [] table[nr].usmUserName;
  3510.   if (table[nr].usmUserSecurityName) delete [] table[nr].usmUserSecurityName;
  3511.   if (table[nr].usmUserAuthKey)
  3512.   {
  3513.     memset(table[nr].usmUserAuthKey, 0, table[nr].usmUserAuthKeyLength);
  3514.     delete [] table[nr].usmUserAuthKey;
  3515.   }
  3516.   if (table[nr].usmUserPrivKey)
  3517.   {
  3518.     memset(table[nr].usmUserPrivKey, 0, table[nr].usmUserPrivKeyLength);
  3519.     delete [] table[nr].usmUserPrivKey;
  3520.   }
  3521.   /* We have now one entry less */
  3522.   entries--;
  3523.   if (entries > nr)
  3524.   {
  3525.     /* move the last entry to the deleted position */
  3526.     table[nr] = table[entries];
  3527.   }
  3528. }
  3529. // Save all entries into a file.
  3530. int USMUserTable::save_to_file(const char *name, AuthPriv *ap)
  3531. {
  3532.   char encoded[MAX_LINE_LEN * 2];
  3533.   FILE *file_out;
  3534.   char tmp_file_name[MAXLENGTH_FILENAME];
  3535.   bool failed = false;
  3536.   if (!name || !ap)
  3537.   {
  3538.     LOG_BEGIN(ERROR_LOG | 1);
  3539.     LOG("USMUserTable: save_to_file called with illegal param");
  3540.     if (!name)
  3541.     {
  3542.       LOG("filename");
  3543.     }
  3544.     if (!ap)
  3545.     {
  3546.       LOG("AuthPriv pointer");
  3547.     }
  3548.     LOG_END;
  3549.     return SNMPv3_USM_ERROR;
  3550.   }
  3551.   LOG_BEGIN(INFO_LOG | 4);
  3552.   LOG("USMUserTable: Saving users to file");
  3553.   LOG(name);
  3554.   LOG_END;
  3555.   sprintf(tmp_file_name, "%s.tmp", name);
  3556.   file_out = fopen(tmp_file_name, "w");
  3557.   if (!file_out)
  3558.   {
  3559.     LOG_BEGIN(ERROR_LOG | 1);
  3560.     LOG("USMUserTable: could not create tmpfile");
  3561.     LOG(tmp_file_name);
  3562.     LOG_END;
  3563.     return SNMPv3_USM_FILECREATE_ERROR;
  3564.   }
  3565.   {
  3566.     // Begin reentrant code block
  3567.     BEGIN_REENTRANT_CODE_BLOCK;
  3568.     for (int i=0; i < entries; ++i)
  3569.     {
  3570.       LOG_BEGIN(INFO_LOG | 8);
  3571.       LOG("USMUserTable: Saving user to file");
  3572.       LOG(OctetStr(table[i].usmUserName, table[i].usmUserNameLength)
  3573.           .get_printable());
  3574.       LOG_END;
  3575.       encodeString(table[i].usmUserEngineID, table[i].usmUserEngineIDLength,
  3576.    encoded);
  3577.       encoded[2 * table[i].usmUserEngineIDLength] = 'n';
  3578.       if (fwrite(encoded, 2 * table[i].usmUserEngineIDLength + 1, 1,
  3579.  file_out) != 1)
  3580.       { failed = true; break; }
  3581.       encodeString(table[i].usmUserName, table[i].usmUserNameLength, encoded);
  3582.       encoded[2 * table[i].usmUserNameLength] = 'n';
  3583.       if (fwrite(encoded, 2 * table[i].usmUserNameLength + 1, 1,
  3584.  file_out) != 1)
  3585.       { failed = true; break; }
  3586.       encodeString(table[i].usmUserSecurityName,
  3587.    table[i].usmUserSecurityNameLength, encoded);
  3588.       encoded[2 * table[i].usmUserSecurityNameLength] = 'n';
  3589.       if (fwrite(encoded, 2 * table[i].usmUserSecurityNameLength + 1, 1,
  3590.  file_out) != 1)
  3591.       { failed = true; break; }
  3592.       encodeString(table[i].usmUserAuthKey, table[i].usmUserAuthKeyLength,
  3593.    encoded);
  3594.       encoded[2 * table[i].usmUserAuthKeyLength] = 'n';
  3595.       if (fwrite(encoded, 2 * table[i].usmUserAuthKeyLength + 1, 1,
  3596.  file_out) != 1)
  3597.       { failed = true; break; }
  3598.       encodeString(table[i].usmUserPrivKey, table[i].usmUserPrivKeyLength,
  3599.    encoded);
  3600.       encoded[2 * table[i].usmUserPrivKeyLength] = 'n';
  3601.       if (fwrite(encoded, 2 * table[i].usmUserPrivKeyLength + 1, 1,
  3602.  file_out) != 1)
  3603.       { failed = true; break; }
  3604.     
  3605.       if (table[i].usmUserAuthProtocol == SNMP_AUTHPROTOCOL_NONE)
  3606.       {
  3607. if (fwrite("nonen", 5, 1, file_out) != 1)
  3608. { failed = true; break; }
  3609.       }
  3610.       else
  3611.       {
  3612. const Auth *a = ap->get_auth(table[i].usmUserAuthProtocol);
  3613. if (!a) { failed = true; break; }
  3614. sprintf(encoded, "%sn", a->get_id_string());
  3615. if (fwrite(encoded, strlen(a->get_id_string()) + 1, 1, file_out) != 1)
  3616. { failed = true; break; }
  3617.       }
  3618.       if (table[i].usmUserPrivProtocol == SNMP_PRIVPROTOCOL_NONE)
  3619.       {
  3620. if (fwrite("nonen", 5, 1, file_out) != 1)
  3621. { failed = true; break; }
  3622.       }
  3623.       else
  3624.       {
  3625. const Priv *p = ap->get_priv(table[i].usmUserPrivProtocol);
  3626. if (!p) { failed = true; break; }
  3627. sprintf(encoded, "%sn", p->get_id_string());
  3628. if (fwrite(encoded, strlen(p->get_id_string()) + 1, 1, file_out) != 1)
  3629. { failed = true; break; }
  3630.       }
  3631.     }
  3632.   }
  3633.   fclose(file_out);
  3634.   if (failed)
  3635.   {
  3636.     LOG_BEGIN(ERROR_LOG | 1);
  3637.     LOG("USMUserTable: Failed to write table entries.");
  3638.     LOG_END;
  3639. #ifdef WIN32
  3640.     _unlink(tmp_file_name);
  3641. #else
  3642.     unlink(tmp_file_name);
  3643. #endif
  3644.     return SNMPv3_USM_FILEWRITE_ERROR;
  3645.   }
  3646. #ifdef WIN32
  3647.   _unlink(name);
  3648. #else
  3649.   unlink(name);
  3650. #endif
  3651.   if (rename(tmp_file_name, name))
  3652.   {
  3653.     LOG_BEGIN(ERROR_LOG | 1);
  3654.     LOG("USMUserTable: Could not rename file (from) (to)");
  3655.     LOG(tmp_file_name);
  3656.     LOG(name);
  3657.     LOG_END;
  3658.     return SNMPv3_USM_FILERENAME_ERROR;
  3659.   }
  3660.   LOG_BEGIN(INFO_LOG | 4);
  3661.   LOG("USMUserTable: Saving users to file finished");
  3662.   LOG_END;
  3663.   return SNMPv3_USM_OK;
  3664. }
  3665. // Load the table from a file.
  3666. int USMUserTable::load_from_file(const char *name, AuthPriv *ap)
  3667. {
  3668.   char decoded[MAX_LINE_LEN];
  3669.   FILE *file_in;
  3670.   unsigned char line[MAX_LINE_LEN * 2];
  3671.   if (!name || !ap)
  3672.   {
  3673.     LOG_BEGIN(ERROR_LOG | 1);
  3674.     LOG("USMUserTable: load_from_file called with illegal param");
  3675.     if (!name)
  3676.     {
  3677.       LOG("filename");
  3678.     }
  3679.     if (!ap)
  3680.     {
  3681.       LOG("AuthPriv pointer");
  3682.     }
  3683.     LOG_END;
  3684.     return SNMPv3_USM_ERROR;
  3685.   }
  3686.   LOG_BEGIN(INFO_LOG | 4);
  3687.   LOG("USMUserTable: Loading users from file");
  3688.   LOG(name);
  3689.   LOG_END;
  3690.   file_in = fopen(name, "r");
  3691.   if (!file_in)
  3692.   {
  3693.     LOG_BEGIN(ERROR_LOG | 1);
  3694.     LOG("USMUserTable: could not open file");
  3695.     LOG(name);
  3696.     LOG_END;
  3697.     return SNMPv3_USM_FILEOPEN_ERROR;
  3698.   }
  3699.   bool failed = false;
  3700.   int len;
  3701.   while (fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3702.   {
  3703.     // engine_id
  3704.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3705.     decodeString(line, len, decoded);
  3706.     OctetStr engine_id((unsigned char*)decoded, len / 2);
  3707.     // user_name
  3708.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3709.     { failed = true; break; }
  3710.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3711.     decodeString(line, len, decoded);
  3712.     OctetStr user_name((unsigned char*)decoded, len / 2);
  3713.     // security_name
  3714.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3715.     { failed = true; break; }
  3716.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3717.     decodeString(line, len, decoded);
  3718.     OctetStr user_security_name((unsigned char*)decoded, len / 2);
  3719.     // auth key
  3720.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3721.     { failed = true; break; }
  3722.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3723.     decodeString(line, len, decoded);
  3724.     OctetStr auth_key((unsigned char*)decoded, len / 2);
  3725.     // priv key
  3726.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3727.     { failed = true; break; }
  3728.     len = SAFE_INT_CAST(strlen((char*)line)) - 1;
  3729.     decodeString(line, len, decoded);
  3730.     OctetStr priv_key((unsigned char*)decoded, len / 2);
  3731.     // auth protocol
  3732.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3733.     { failed = true; break; }
  3734.     line[strlen((char*)line) - 1] = 0;
  3735.     int auth_prot = SNMP_AUTHPROTOCOL_NONE;
  3736.     if (strcmp((char*)line, "none") != 0)
  3737.     {
  3738.       auth_prot = ap->get_auth_id((char*)line);
  3739.       if (auth_prot < 0)
  3740.       { failed = true; break; }
  3741.     }
  3742.     if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
  3743.     { failed = true; break; }
  3744.     line[strlen((char*)line) - 1] = 0;
  3745.     int priv_prot = SNMP_PRIVPROTOCOL_NONE;
  3746.     if (strcmp((char*)line, "none") != 0)
  3747.     {
  3748.       priv_prot = ap->get_priv_id((char*)line);
  3749.       if (priv_prot < 0)
  3750.       { failed = true; break; }
  3751.     }
  3752.     LOG_BEGIN(INFO_LOG | 7);
  3753.     LOG("USMUserTable: Adding localized (user name) (eng id) (auth) (priv)");
  3754.     LOG(user_name.get_printable());
  3755.     LOG(engine_id.get_printable());
  3756.     LOG(auth_prot);
  3757.     LOG(priv_prot);
  3758.     LOG_END;
  3759.     if (add_entry(engine_id, user_name, user_security_name,
  3760.   auth_prot, auth_key, priv_prot, priv_key)
  3761. == SNMPv3_USM_ERROR)
  3762.     {
  3763.       failed = true;
  3764.       LOG_BEGIN(ERROR_LOG | 1);
  3765.       LOG("USMUserTable: Error adding (user name)");
  3766.       LOG(user_name.get_printable());
  3767.       LOG_END;
  3768.     }
  3769.   }
  3770.   fclose(file_in);
  3771.   if (failed)
  3772.   {
  3773.     LOG_BEGIN(ERROR_LOG | 1);
  3774.     LOG("USMUserTable: Failed to read table entries");
  3775.     LOG_END;
  3776.     return SNMPv3_USM_FILEREAD_ERROR;
  3777.   }
  3778.   LOG_BEGIN(INFO_LOG | 4);
  3779.   LOG("USMUserTable: Loaded all users from file");
  3780.   LOG_END;
  3781.   return SNMPv3_USM_OK;
  3782. }
  3783. const UsmUserTableEntry *USMUserTable::peek_next(
  3784.                    const UsmUserTableEntry *e) const
  3785. {
  3786.   if (e == 0) return 0;
  3787.   if (e - table < 0) return 0;
  3788.   if (e - table >= entries - 1) return 0;
  3789.   return (e + 1);
  3790. }
  3791. #ifdef SNMP_PP_NAMESPACE
  3792. }; // end of namespace Snmp_pp
  3793. #endif 
  3794. #endif // _SNMPv3