1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
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.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
29 char usm_v3_cpp_version[]="@(#) SNMP++ $Id: usm_v3.cpp 1788 2010-07-23 20:02:38Z katz $";
31 #if defined(_AIX) || defined(__APPLE__)
42 #include "snmp_pp/config_snmp_pp.h"
46 #include "snmp_pp/v3.h"
47 #include "snmp_pp/usm_v3.h"
48 #include "snmp_pp/auth_priv.h"
49 #include "snmp_pp/reentrant.h"
50 #include "snmp_pp/mp_v3.h"
51 #include "snmp_pp/asn1.h"
52 #include "snmp_pp/vb.h"
53 #include "snmp_pp/pdu.h"
54 #include "snmp_pp/log.h"
56 #ifdef SNMP_PP_NAMESPACE
60 // Use locking on access methods in an multithreading enviroment.
62 #define BEGIN_REENTRANT_CODE_BLOCK SnmpSynchronize auto_lock(*this)
63 #define BEGIN_REENTRANT_CODE_BLOCK_CONST \
64 SnmpSynchronize auto_lock(*(PP_CONST_CAST(SnmpSynchronized*, this)))
65 #define BEGIN_AUTO_LOCK(obj) SnmpSynchronize auto_lock(*obj)
67 #define BEGIN_REENTRANT_CODE_BLOCK
68 #define BEGIN_REENTRANT_CODE_BLOCK_CONST
69 #define BEGIN_AUTO_LOCK(obj)
73 #define min(a,b) ( (a) < (b) ? (a) : (b) )
76 #define MAX_LINE_LEN 2048 // Max line length in usm user files
78 // structure for key update
82 OctetStr securityName;
88 /* ------------------------- UsmTimeTable --------------------------*/
91 * This class provides a table for the time values (engine boots and
92 * engine time) for snmp entities that are identified through their
97 class USMTimeTable : public SnmpSynchronized
102 * Initialize the usmTimeTable.
104 * The usmTimeTable stores for each known engineID the engineBoots
105 * and the difference to the local system time
107 * @param owner - Pointer to the USM object that created this table
108 * @param engine_boots - The new value for the snmpEngineBoots counter
109 * @param result - OUT: Result of the creation of the table
111 USMTimeTable(const USM *owner, const unsigned int engine_boots, int &result);
116 * Add a new entry to the usmTimeTable. The caller is responsible for
117 * not adding an engineID twice.
119 * @param engine_id - The engineID of the SNMP entity
120 * @param engine_boots - The engine boot counter
121 * @param engine_time - The engine time
123 * @return - SNMPv3_USM_ERROR (no memory) or SNMPv3_USM_OK
125 int add_entry(const OctetStr &engine_id,
126 const long int engine_boots, const long int engine_time);
129 * Delete this engine id from the table.
131 * @param engine_id - The engineID of the SNMP entity
133 * @return - SNMPv3_USM_ERROR (no memory) or SNMPv3_USM_OK
135 int delete_entry(const OctetStr &engine_id);
138 * Return engineBoots and engineTime for a given engineID
140 * @param engine_id - The engineID of the SNMP entity
141 * @param engine_boots - OUT: boot counter (0 if not found)
142 * @param engine_time - OUT: engine time (0 if not found)
144 * @return - SNMPv3_USM_ERROR (not initialized),
145 * SNMPv3_USM_OK (entry found, values are filled)
146 * SNMPv3_USM_UNKNOWN_ENGINEID ( not found)
148 int get_time(const OctetStr &engine_id,
149 long int &engine_boots, long int &engine_time);
152 * Return the engineBoots and engineTime of this snmp entity.
154 * @param engine_boots - OUT: boot counter (0 if not found)
155 * @param engine_time - OUT: engine time (0 if not found)
157 * @return - SNMPv3_USM_ERROR (not initialized),
158 * SNMPv3_USM_OK (entry found, values are filled)
160 int get_local_time(long int &engine_boots, long int &engine_time);
163 * Return the engineBoots value of this snmp entity.
165 * @return - engine_boots value if initialized, 0 else
167 unsigned long get_local_boots()
168 { return (table ? table[0].engine_boots : 0); };
171 * Return the engineTime value of this snmp entity.
173 * @return - engine_time value if initialized, 0 else
175 unsigned long get_local_time();
178 * Check if the given values for engineBoots and engineTime are
179 * in the time window. If the time values are ok, the entry in
180 * the usmTimeTable is updated with the given time values.
182 * @param engine_id - The engineID of the SNMP entity
183 * @param engine_boots - The boot counter
184 * @param engine_time - The engine time
186 * @return - SNMPv3_USM_ERROR (not initialized),
187 * SNMPv3_USM_NOT_IN_TIME_WINDOW,
188 * SNMPv3_USM_OK (time ok),
189 * SNMPv3_USM_UNKNOWN_ENGINEID
191 int check_time(const OctetStr &engine_id,
192 const long int engine_boots, const long int engine_time);
195 * Check if the given engineID is known: If the USM is in
196 * the discovery mode, all engineIDs are accepted and entries
197 * in the timeTable are created.
199 * @param engine_id - engine id to check
201 * @return - SNMPv3_USM_ERROR (not found and no discovery)
202 * SNMPv3_USM_OK (found or discovery set)
204 int check_engine_id(const OctetStr &engine_id);
209 unsigned char engine_id[MAXLENGTH_ENGINEID];
211 long int engine_boots;
213 long int latest_received_time;
216 struct Entry_T *table; ///< Array of entries
217 const USM *usm; ///< Pointer to the USM, this table belongs to
218 int max_entries; ///< the maximum number of entries
219 int entries; ///< the current amount of entries
223 /* ------------------------- UsmUserNameTable ----------------------*/
226 * This class holds USM users with PASSWORDS.
228 * Whenever the USM has to process a message of a user that is not
229 * found in the USMUserTable, this table is queried for the
230 * properties of the user. If the user is found, a localized entry
231 * for the USMUserTable is created and used for processing the message.
233 class USMUserNameTable : public SnmpSynchronized
236 USMUserNameTable(int &result);
240 * Add a new user to the usmUserNameTable. If the userName is already
241 * known, the old entry is replaced.
243 * It is not recommended to add users with userName != securityName.
245 * @param user_name - Unique userName
246 * @param security_name - Unique securityName
247 * @param auth_proto - Possible values are:
248 * SNMP_AUTHPROTOCOL_NONE,
249 * SNMP_AUTHPROTOCOL_HMACMD5,
250 * SNMP_AUTHPROTOCOL_HMACSHA
251 * @param priv_proto - Possible values are:
252 * SNMP_PRIVPROTOCOL_NONE,
253 * SNMP_PRIVPROTOCOL_DES,
254 * SNMP_PRIVPROTOCOL_IDEA
255 * @param auth_pass - Secret password for authentication
256 * @param priv_pass - Secret password for privacy
258 * @return - SNMPv3_USM_OK or
259 * SNMP_v3_USM_ERROR (memory error, not initialized)
261 int add_entry(const OctetStr& user_name,
262 const OctetStr& security_name,
263 const long int auth_proto,
264 const long int priv_proto,
265 const OctetStr& auth_pass,
266 const OctetStr& priv_pass);
269 * Delete all occurences of the user with the given securityName
272 * @param security_name - the securityName of the user
274 * @return - SNMPv3_USM_OK, SNMPv3_USM_ERROR (not initialized)
276 int delete_security_name(const OctetStr& security_name);
279 * Get the entry with the given securityName from the usmUserNameTable
281 * @note Use lock() and unlock() for thread synchronizytion.
283 * @param security_name -
285 * @return - pointer to the struct or NULL (no need to delete anything)
287 const struct UsmUserNameTableEntry* get_entry(const OctetStr &security_name);
290 * Get a clone of the entry with the given securityName from the usmUserNameTable
292 * @note call delete_cloned_entry() with the retruned pointer.
294 * @param security_name -
296 * @return - pointer to the struct or NULL
298 struct UsmUserNameTableEntry* get_cloned_entry(const OctetStr &security_name);
301 * Deletes a entry created through get_cloned_entry().
305 void delete_cloned_entry(struct UsmUserNameTableEntry* &entry);
308 * Get the securityName from a userName
311 * @param user_name_len -
312 * @param security_name - Buffer for the securityName
314 * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
317 int get_security_name(const unsigned char *user_name,
318 const long int user_name_len,
319 OctetStr &security_name);
322 * Get the userName from a securityName
324 * @param user_name - Buffer for the userName
325 * @param user_name_len - Has to be set to the max length of the
326 * buffer. Is set to the length of the found
327 * securityName or to 0 if not found.
328 * @param security_name -
329 * @param security_name_len -
331 * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
334 int get_user_name(unsigned char *user_name, long int *user_name_len,
335 const unsigned char *security_name,
336 const long int security_name_len);
339 * Save all entries into a file.
341 int save_to_file(const char *name, AuthPriv *ap);
344 * Load the table from a file.
346 int load_from_file(const char *name, AuthPriv *ap);
348 const UsmUserNameTableEntry *peek_first() const
349 { if (entries > 0) return table; return 0; };
351 const UsmUserNameTableEntry *peek_next(const UsmUserNameTableEntry *e) const;
354 struct UsmUserNameTableEntry *table;
356 int max_entries; ///< the maximum number of entries
357 int entries; ///< the current amount of entries
361 /* ---------------------------- UsmUserTable ------------------- */
364 * This class holds USM users with localized KEYS.
366 class USMUserTable : public SnmpSynchronized
369 USMUserTable(int &result);
374 * Get the number of valid entries in the table.
376 * @return - number of entries
378 int size() const { return entries; };
381 * Get the userName from a securityName
383 * @param user_name - Buffer for the userName
384 * @param user_name_len - Has to be set to the max length of the
385 * buffer. Is set to the length of the found
386 * securityName or to 0 if not found.
388 * @param sec_name_len -
390 * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
393 int get_user_name(unsigned char *user_name, long int *user_name_len,
394 const unsigned char *sec_name, const long sec_name_len);
397 * Get the sec_name from a userName
400 * @param user_name_len -
401 * @param sec_name - Object for the security name
403 * @return - SNMPv3_USM_ERROR (not initialized, not found, buffer too small),
406 int get_security_name(const unsigned char *user_name,
407 const long user_name_len,
411 * Delete all entries of this user from the usmUserTable
413 * @param user_name - The userName that should be deleted
415 * @return - SNMPv3_USM_ERROR (not initialized),
416 * SNMPv3_USM_OK (user deleted or not in table)
418 int delete_entries(const OctetStr& user_name);
421 * Delete all entries with this engine id from the table.
423 * @param engine id - The engine id
425 * @return - SNMPv3_USM_ERROR (not initialized),
426 * SNMPv3_USM_OK (user deleted or not in table)
428 int delete_engine_id(const OctetStr& engine_id);
431 * Delete the entry with the given userName and engineID
432 * from the usmUserTable
434 * @param engine_id - The engine id
435 * @param user_name - The userName that should be deleted
437 * @return - SNMPv3_USM_ERROR (not initialized),
438 * SNMPv3_USM_OK (user deleted or not in table)
440 int delete_entry(const OctetStr& engine_id, const OctetStr& user_name);
443 * Protected (for agent++):
445 * Get the user at the specified position of the usmUserTable.
447 * @note Use lock() and unlock() for thread synchronization.
449 * @param number - get the entry at position number (1...)
451 * @return - a pointer to the structure or NULL if number is out
452 * of range (no need to delete anything)
454 const struct UsmUserTableEntry *get_entry(const int number);
457 * Get a user of the usmUserTable.
459 * @note Use lock() and unlock() for thread synchronization.
461 * @param engine_id - Get a user for this engine id
462 * @param sec_name - Get the user with this security name
464 * @return - a pointer to the structure or NULL if the user is not
465 * found (no need to delete anything)
467 const struct UsmUserTableEntry *get_entry(const OctetStr &engine_id,
468 const OctetStr &sec_name);
471 * Get a user of the usmUserTable.
473 * @note call delete_cloned_entry() with the retruned pointer.
475 * @param engine_id - Get a user for this engine id
476 * @param sec_name - Get the user with this security name
478 * @return - a pointer to the structure or NULL if the user is not
481 struct UsmUserTableEntry *get_cloned_entry(const OctetStr &engine_id,
482 const OctetStr &sec_name);
485 * Deletes a entry created through get_cloned_entry().
489 void delete_cloned_entry(struct UsmUserTableEntry* &entry);
492 * Get a user of the usmUserTable.
494 * There could be more than one entry with the given
495 * sec_name. Always the first entry that is found is returned.
497 * @note Use lock() and unlock() for thread synchronization.
499 * @param sec_name - security name to search for
501 * @return - a pointer to the structure or NULL if the user is not
502 * found (no need to delete anything)
504 const struct UsmUserTableEntry *get_entry(const OctetStr &sec_name);
509 * Add or replace a user in the usmUserTable. The usmUserTable stores
510 * users with their localized keys.
512 * @param engine_id - The engine_id, the key was localized with
513 * @param user_name - The name of the user (in the USM)
514 * @param sec_name - The security name of the user, this name
515 * is the same for all securityModels
516 * @param auth_proto - Possible values are:
517 * SNMP_AUTHPROTOCOL_NONE,
518 * SNMP_AUTHPROTOCOL_HMACMD5,
519 * SNMP_AUTHPROTOCOL_HMACSHA
520 * @param auth_key - The key used for authentications
521 * @param priv_proto - Possible values are:
522 * SNMP_PRIVPROTOCOL_NONE,
523 * SNMP_PRIVPROTOCOL_DES,
524 * SNMP_PRIVPROTOCOL_IDEA
525 * @param priv_key - The key used for privacy
527 * @return - SNMPv3_USM_OK
528 * SNMP_v3_USM_ERROR (not initialized, no memory)
530 int add_entry(const OctetStr &engine_id,
531 const OctetStr &user_name, const OctetStr &sec_name,
532 const long int auth_proto, const OctetStr &auth_key,
533 const long int priv_proto, const OctetStr &priv_key);
536 * Replace a localized key of the user and engine_id in the
539 * @param user_name - The name of the user in the USM
540 * @param engine_id - Change the localized key for the SNMP
541 * entity with this engine_id
542 * @param new_key - The new key
543 * @param key_type - AUTHKEY, OWNAUTHKEY, PRIVKEY or OWNPRIVKEY
545 * @return - SNMPv3_USM_ERROR (no such entry or not initialized),
548 int update_key(const OctetStr &user_name,
549 const OctetStr &engine_id,
550 const OctetStr &new_key,
554 * Save all entries into a file.
556 int save_to_file(const char *name, AuthPriv *ap);
559 * Load the table from a file.
561 int load_from_file(const char *name, AuthPriv *ap);
563 const UsmUserTableEntry *peek_first() const
564 { if (entries > 0) return table; return 0; };
566 const UsmUserTableEntry *peek_next(const UsmUserTableEntry *e) const;
569 void delete_entry(const int nr);
571 struct UsmUserTableEntry *table;
573 int max_entries; ///< the maximum number of entries
574 int entries; ///< the current amount of entries
579 struct UsmSecurityParameters {
580 unsigned char msgAuthoritativeEngineID[MAXLENGTH_ENGINEID];
581 long int msgAuthoritativeEngineIDLength;
582 long int msgAuthoritativeEngineBoots;
583 long int msgAuthoritativeEngineTime;
584 unsigned char msgUserName[MAXLEN_USMUSERNAME];
585 long int msgUserNameLength;
586 unsigned char *msgAuthenticationParameters;
587 long int msgAuthenticationParametersLength;
588 unsigned char *msgPrivacyParameters;
589 unsigned int msgPrivacyParametersLength;
595 struct SecurityStateReference
597 unsigned char msgUserName[MAXLEN_USMUSERNAME]; int msgUserNameLength;
598 unsigned char *securityName; int securityNameLength;
599 unsigned char *securityEngineID; int securityEngineIDLength;
601 unsigned char* authKey; int authKeyLength;
603 unsigned char* privKey; int privKeyLength;
610 void USM::inc_stats_unsupported_sec_levels()
612 if (usmStatsUnsupportedSecLevels == MAXUINT32)
613 usmStatsUnsupportedSecLevels = 0;
615 usmStatsUnsupportedSecLevels++;
618 void USM::inc_stats_not_in_time_windows()
620 if (usmStatsNotInTimeWindows == MAXUINT32)
621 usmStatsNotInTimeWindows = 0;
623 usmStatsNotInTimeWindows++;
626 void USM::inc_stats_unknown_user_names()
628 if (usmStatsUnknownUserNames == MAXUINT32)
629 usmStatsUnknownUserNames = 0;
631 usmStatsUnknownUserNames++;
634 void USM::inc_stats_unknown_engine_ids()
636 if (usmStatsUnknownEngineIDs == MAXUINT32)
637 usmStatsUnknownEngineIDs = 0;
639 usmStatsUnknownEngineIDs++;
642 void USM::inc_stats_wrong_digests()
644 if (usmStatsWrongDigests == MAXUINT32)
645 usmStatsWrongDigests = 0;
647 usmStatsWrongDigests++;
650 void USM::inc_stats_decryption_errors()
652 if (usmStatsDecryptionErrors == MAXUINT32)
653 usmStatsDecryptionErrors = 0;
655 usmStatsDecryptionErrors++;
659 void USM::delete_sec_state_reference(struct SecurityStateReference *ssr)
663 ssr->msgUserName[0] = 0;
664 if (ssr->securityName) delete [] ssr->securityName;
665 if (ssr->securityEngineID) delete [] ssr->securityEngineID;
668 memset(ssr->authKey, 0, ssr->authKeyLength);
669 delete [] ssr->authKey;
673 memset(ssr->privKey, 0, ssr->privKeyLength);
674 delete [] ssr->privKey;
680 struct SecurityStateReference *USM::get_new_sec_state_reference()
682 struct SecurityStateReference *res = new SecurityStateReference;
687 memset(res, 0, sizeof(struct SecurityStateReference));
692 USM::USM(unsigned int engine_boots, const OctetStr &engine_id,
694 unsigned int *msgID, int &result)
695 : local_snmp_engine_id (engine_id),
698 discovery_mode (TRUE),
700 usmStatsUnsupportedSecLevels (0),
701 usmStatsNotInTimeWindows (0),
702 usmStatsUnknownUserNames (0),
703 usmStatsUnknownEngineIDs (0),
704 usmStatsWrongDigests (0),
705 usmStatsDecryptionErrors (0),
709 auth_priv = new AuthPriv(result);
710 if (result != SNMPv3_USM_OK)
712 auth_priv->add_default_modules();
714 usm_user_name_table = new USMUserNameTable(result);
715 if (result != SNMPv3_USM_OK)
718 usm_user_table = new USMUserTable(result);
719 if (result != SNMPv3_USM_OK)
724 printf("\nTesting 3DES starts\n\n");
725 OctetStr engineId = OctetStr::from_hex_string("00 00 00 00 00 00 "
726 "00 00 00 00 00 02");
728 OctetStr oldKey, newKey, delta;
731 unsigned int key_len=64;
733 debughexcprintf(0,"engineID", engineId.data(), engineId.len());
735 auth_priv->password_to_key_priv(SNMP_AUTHPROTOCOL_HMACSHA,
736 SNMP_PRIVPROTOCOL_3DESEDE,
737 (unsigned char*)"maplesyrup", 10,
738 engineId.data(), engineId.len(),
741 oldKey.set_len(key_len);
743 auth_priv->password_to_key_priv(SNMP_AUTHPROTOCOL_HMACSHA,
744 SNMP_PRIVPROTOCOL_3DESEDE,
745 (unsigned char*)"newsyrup", 8,
746 engineId.data(), engineId.len(),
749 newKey.set_len(key_len);
751 OctetStr expectedKey = OctetStr::from_hex_string("78 e2 dc ce 79 d5 94 03 b5 8c 1b ba a5 bf f4 63 91 f1 cd 25 97 74 35 55 f9 fc f9 4a c3 e7 e9 22");
753 if (newKey != expectedKey)
755 printf("newKey != expectedKey\n");
756 printf("newKey: %s\n", newKey.get_printable_hex());
757 printf("expected: %s\n", expectedKey.get_printable_hex());
760 auth_priv->get_keychange_value(SNMP_AUTHPROTOCOL_HMACSHA,
761 oldKey, newKey, delta);
763 OctetStr expectedDelta = OctetStr::from_hex_string(
764 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
765 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
766 "ce 13 28 fb 9a 9c 19 ce c1 51 a3 5a 77 f9 20 39 "
767 "ca ff 00 c9 b3 9b 19 a0 5e 01 75 55 94 37 6a 57");
769 if (delta != expectedDelta)
771 printf("delta != expectedDelta\n");
772 printf("delta: %s\n", delta.get_printable_hex());
773 printf("expected: %s\n", expectedDelta.get_printable_hex());
776 printf("\nTesting 3DES finished\n\n");
778 printf(" Testing DES:\n");
780 pp_uint64 testsalt=0xbabec0de;
781 pd.set_salt(&testsalt);
783 const char *desplaintext[10];
784 desplaintext[0] = "abcdefghijklmnopqrstuvwxyz123456";
785 desplaintext[1] = "abcdefghijklmnopqrstuvwxyz1234567";
786 desplaintext[2] = "abcdefghijklmnopqrstuvwxyz12345678";
787 desplaintext[3] = "abcdefghijklmnopqrstuvwxyz123456789";
788 desplaintext[4] = "abcdefghijklmnopqrstuvwxyz123456789A";
789 desplaintext[5] = "abcdefghijklmnopqrstuvwxyz123456789AB";
790 desplaintext[6] = "abcdefghijklmnopqrstuvwxyz123456789ABC";
791 desplaintext[7] = "abcdefghijklmnopqrstuvwxyz123456789ABCD";
792 desplaintext[8] = "abcdefghijklmnopqrstuvwxyz123456789ABCDE";
793 desplaintext[9] = "abcdefghijklmnopqrstuvwxyz123456789ABCDEF";
795 unsigned char desencrypted[80];
796 unsigned char desdecrypted[80];
797 unsigned char desprivparams[8];
798 unsigned char deskey[17] = "illegal_des_key!";
800 for (int i=0; i<9; i++)
802 unsigned int encrypt_len = 80;
803 unsigned int decrypt_len = 80;
804 unsigned int desprivparamslen = 8;
806 memset(desencrypted, 'x', 80);
807 memset(desdecrypted, 'y', 80);
809 debughexcprintf(1, "Plaintext", (unsigned char*)desplaintext[i],
810 strlen(desplaintext[i]));
812 int res = pd.encrypt(deskey, 16,
813 (unsigned char*)desplaintext[i],
814 strlen(desplaintext[i]),
815 desencrypted, &encrypt_len,
816 desprivparams, &desprivparamslen,
819 printf("%d: Result of encryption is %d\n", i, res);
820 debughexcprintf(1, "Encrypted", desencrypted, encrypt_len);
822 res = pd.decrypt(deskey, 16,
823 desencrypted, encrypt_len,
824 desdecrypted, &decrypt_len,
825 desprivparams, desprivparamslen,
827 printf("%d: Result of decryption is %d\n", i, res);
828 debughexcprintf(1, "Decrypted", desdecrypted, decrypt_len);
830 if (memcmp(desplaintext[i], desdecrypted, strlen(desplaintext[i])))
831 printf("\n********* FAILED **********\n");
840 printf(" Testing SHA:\n");
842 // test password2key-algor:
843 unsigned char keysha[50];
844 auth_priv->password_to_key_auth(...(unsigned char*)"maplesyrup",10,
845 (unsigned char*)"\0\0\0\0\0\0\0\0\0\0\0\2",12,keysha);
846 printf("Output of PasswordToKey-algorithm for SHA:\n");
847 for (int i=0; i< 20; i++) {
848 printf("%02X ", keysha[i]);
849 if ((i+1)%4==0) printf(" ");
850 if ((i+1)%16==0) printf("\n");
852 printf("\nOutput should be (draft-ietf-snmpv3-usm-v2-02.txt):\n");
853 printf("66 95 fe bc 92 88 e3 62 82 23 5f c7 15 1f 12 84\n97 b3 8f 3f\n");
854 printf("\nTesting MD5:\n");
855 unsigned char keymd5[50];
856 apPasswordToKeyMD5((unsigned char*)"maplesyrup",10,
857 (unsigned char*)"\0\0\0\0\0\0\0\0\0\0\0\2",12,keymd5);
858 printf("Output of PasswordToKey-algorithm for MD5:\n");
859 for (int i=0; i< 16; i++) {
860 printf("%02X ", keymd5[i]);
861 if ((i+1)%4==0) printf(" ");
862 if ((i+1)%16==0) printf("\n");
864 printf("Output ahould be (draft-ietf-snmpv3-usm-v2-02.txt):\n");
865 printf("52 6f 5e ed 9f cc e2 6f 89 64 c2 93 07 87 d8 2b\n");
867 printf("\nTesting IDEA:\n");
868 unsigned char source[35] = "Hallo, das ist ein test!", encrypted[35], decrypted[35], params[8];
869 int len_encrypted = 35, len_decrypted = 35;
870 apIDEAEncryptData((unsigned char*)"1234567890abcdef",
871 source, 25, encrypted, &len_encrypted, params);
873 apIDEADecryptData((unsigned char*)"1234567890abcdef",
874 encrypted, len_encrypted,
875 decrypted, &len_decrypted, params);
879 for (int i=0; i< 8; i++) {
880 printf("%02X ", params[i]);
881 if ((i+1)%4==0) printf(" ");
882 if ((i+1)%16==0) printf("\n");
884 printf("\nsource:\n");
885 for (int i=0; i< 25; i++) {
886 printf("%02X ", source[i]);
887 if ((i+1)%4==0) printf(" ");
888 if ((i+1)%16==0) printf("\n");
891 printf("encrypted:\n");
892 for (int i=0; i< 25; i++) {
893 printf("%02X ", encrypted[i]);
894 if ((i+1)%4==0) printf(" ");
895 if ((i+1)%16==0) printf("\n");
898 printf("decrypted:\n");
899 for (int i=0; i< 25; i++) {
900 printf("%02X ", decrypted[i]);
901 if ((i+1)%4==0) printf(" ");
902 if ((i+1)%16==0) printf("\n");
905 for (int i=0; i<25; i++)
906 if (source[i]!=decrypted[i]) {
907 printf("\n*** source != decrypted ****\n\n");
911 // test keyUpdate md5
912 printf("\n Test KeyUpdate Algorithm:\n");
913 printf("Test MD5:\n");
914 OctetStr oldKey = OctetStr(keymd5, SNMPv3_AP_OUTPUT_LENGTH_MD5);
916 unsigned char newkeymd5[50];
917 apPasswordToKeyMD5((unsigned char*)"newsyrup",8,
918 (unsigned char*)"\0\0\0\0\0\0\0\0\0\0\0\2",12,newkeymd5);
919 printf("Output of PasswordToKey-algorithm for MD5:\n");
920 for (int i=0; i< 16; i++) {
921 printf("%02X ", newkeymd5[i]);
922 if ((i+1)%4==0) printf(" ");
923 if ((i+1)%16==0) printf("\n");
925 printf("Output ahould be (draft-ietf-snmpv3-usm-v2-02.txt):\n");
926 printf("87 02 1d 7b d9 d1 01 ba 05 ea 6e 3b f9 d9 bd 4a\n");
928 apNewKey(oldKey, OctetStr(newkeymd5, SNMPv3_AP_OUTPUT_LENGTH_MD5),
929 result, SNMPv3_usmHMACMD5AuthProtocol);
931 // test keyUpdate sha (auth)
932 printf("\nTest SHA for authPassword:\n");
933 oldKey = OctetStr(keysha, SNMPv3_AP_OUTPUT_LENGTH_SHA);
935 unsigned char newkeysha[50];
936 apPasswordToKeySHA((unsigned char*)"newsyrup",8,
937 (unsigned char*)"\0\0\0\0\0\0\0\0\0\0\0\2",12,newkeysha);
938 printf("Output of PasswordToKey-algorithm for sha:\n");
939 for (int i=0; i< SNMPv3_AP_OUTPUT_LENGTH_SHA; i++) {
940 printf("%02X ", newkeysha[i]);
941 if ((i+1)%4==0) printf(" ");
942 if ((i+1)%16==0) printf("\n");
944 printf("Output ahould be (draft-ietf-snmpv3-usm-v2-02.txt):\n");
945 printf("78 e2 dc ce 79 d5 94 03 b5 8c 1b ba a5 bf f4 63 \n91 f1 cd 25\n");
947 apNewKey(oldKey, OctetStr(newkeysha, SNMPv3_AP_OUTPUT_LENGTH_SHA),
948 result, SNMPv3_usmHMACSHAAuthProtocol);
949 // test keyUpdate sha (privPassword DES)
950 printf("\nTest SHA for privPassword:\n");
952 oldKey = OctetStr(keysha, SNMPv3_AP_OUTPUT_LENGTH_MD5);
953 apNewKey(oldKey, OctetStr(newkeysha, SNMPv3_AP_OUTPUT_LENGTH_MD5),
954 result, SNMPv3_usmHMACSHAAuthProtocol);
955 printf("Result should be:\n");
956 printf("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n");
957 printf("7e f8 d8 a4 c9 cd b2 6b 47 59 1c d8 52 ff 88 b5\n");
959 /* test AES key extension algorithm */
960 unsigned char key_sha[SNMPv3_USM_MAX_KEY_LEN];
961 unsigned int key_sha_len = SNMPv3_USM_MAX_KEY_LEN;
963 int res = auth_priv->password_to_key_priv(
964 SNMP_AUTHPROTOCOL_HMACSHA,
965 SNMP_PRIVPROTOCOL_AES256,
966 (unsigned char*)"maplesyrup", 10,
967 (unsigned char*)"\0\0\0\0\0\0\0\0\0\0\0\2", 12,
968 key_sha, &key_sha_len);
970 debugprintf(0, "aes key extension result %i, key_sha_len = %i.",
972 debughexcprintf(0, "key_sha", key_sha, key_sha_len);
974 unsigned char pt[56] = "This is a secret message, nobody is allowed to read it!";
975 unsigned char *plaintext = pt;
976 unsigned char ct[56];
977 unsigned char *cipher = ct;
978 unsigned int cipherlen = 56;
979 unsigned char privpar[8];
980 unsigned int privparlen = 8;
982 Priv *priv = auth_priv->get_priv(SNMP_PRIVPROTOCOL_AES256);
984 priv->set_salt(&salt);
985 auth_priv->encrypt_msg(SNMP_PRIVPROTOCOL_AES256,
986 key_sha, key_sha_len,
987 plaintext, 55, cipher, &cipherlen,
988 privpar, &privparlen,
989 0xdeadc0deUL, 0xbeefdedeUL);
991 auth_priv->decrypt_msg(SNMP_PRIVPROTOCOL_AES256,
992 key_sha, key_sha_len,
993 cipher, 55, plaintext, &cipherlen,
995 0xdeadc0deUL, 0xbeefdedeUL);
999 usm_time_table = new USMTimeTable(this, engine_boots, result);
1000 if (result != SNMPv3_USM_OK)
1003 *msgID = (engine_boots & 0x7FFF) << 16;
1009 delete usm_time_table;
1010 usm_time_table = NULL;
1013 delete usm_user_table;
1014 usm_user_table = NULL;
1016 if (usm_user_name_table)
1018 delete usm_user_name_table;
1019 usm_user_name_table = NULL;
1029 // Delete this engine id form all USM tables (users and engine time).
1030 int USM::remove_engine_id(const OctetStr &engine_id)
1032 int retval1, retval2;
1034 retval1 = usm_time_table->delete_entry(engine_id);
1036 retval2 = usm_user_table->delete_entries(engine_id);
1038 if ((retval1 == SNMPv3_USM_ERROR) ||
1039 (retval2 == SNMPv3_USM_ERROR))
1040 return SNMPv3_USM_ERROR;
1042 return SNMPv3_USM_OK;
1045 // Delete the time information for the given engine id
1046 int USM::remove_time_information(const OctetStr &engine_id)
1048 if (usm_time_table->delete_entry(engine_id) == SNMPv3_USM_ERROR)
1049 return SNMPv3_USM_ERROR;
1051 return SNMPv3_USM_OK;
1054 int USM::update_key(const unsigned char* user_name,
1055 const long int user_name_len,
1056 const unsigned char* engine_id,
1057 const long int engine_id_len,
1058 const unsigned char* new_key,
1059 const long int new_key_len,
1060 const int type_of_key)
1062 OctetStr key(new_key, new_key_len);
1064 res = usm_user_table->update_key(OctetStr(user_name, user_name_len),
1065 OctetStr(engine_id, engine_id_len),
1071 int USM::add_localized_user(const OctetStr &engine_id,
1072 const OctetStr &user_name,
1073 const OctetStr &security_name,
1074 const long auth_protocol,
1075 const OctetStr &auth_key,
1076 const long priv_protocol,
1077 const OctetStr &priv_key)
1079 return usm_user_table->add_entry(engine_id, user_name, security_name,
1080 auth_protocol, auth_key,
1081 priv_protocol, priv_key);
1085 int USM::add_usm_user(const OctetStr& user_name,
1086 const OctetStr& security_name,
1087 const long int auth_protocol,
1088 const long int priv_protocol,
1089 const OctetStr& auth_password,
1090 const OctetStr& priv_password)
1092 /* delete localized entries if some exists */
1093 delete_localized_user(user_name);
1095 int result = usm_user_name_table->add_entry(user_name,security_name,
1096 auth_protocol, priv_protocol,
1097 auth_password, priv_password);
1098 if (result != SNMPv3_USM_OK)
1101 struct UsmUser *dummy;
1102 dummy = get_user(local_snmp_engine_id, security_name);
1103 if (dummy) free_user(dummy);
1105 return SNMPv3_USM_OK;
1108 int USM::add_usm_user(const OctetStr& user_name,
1109 const OctetStr& security_name,
1110 const long int auth_protocol,
1111 const long int priv_protocol,
1112 const OctetStr& auth_password,
1113 const OctetStr& priv_password,
1114 const OctetStr& engine_id)
1119 auth_key.set_len(SNMPv3_USM_MAX_KEY_LEN);
1120 priv_key.set_len(SNMPv3_USM_MAX_KEY_LEN);
1122 unsigned int auth_key_len = auth_key.len();
1123 unsigned int priv_key_len = priv_key.len();
1125 int res = build_localized_keys(engine_id, auth_protocol, priv_protocol,
1126 auth_password.data(), auth_password.len(),
1127 priv_password.data(), priv_password.len(),
1128 auth_key.data(), &auth_key_len,
1129 priv_key.data(), &priv_key_len);
1131 if (res != SNMPv3_USM_OK)
1134 auth_key.set_len(auth_key_len);
1135 priv_key.set_len(priv_key_len);
1137 res = usm_user_table->add_entry(engine_id, user_name, security_name,
1138 auth_protocol, auth_key,
1139 priv_protocol, priv_key);
1147 int USM::add_usm_user(const OctetStr& security_name,
1148 const long int auth_protocol,
1149 const long int priv_protocol,
1150 const OctetStr& auth_password,
1151 const OctetStr& priv_password)
1153 // usmUserName: UserName for UserbasedSecurityModel
1154 // usmSecurityName: UserName for all SecurityModels
1155 return add_usm_user(security_name, security_name,
1156 auth_protocol, priv_protocol,
1157 auth_password, priv_password);
1160 int USM::delete_localized_user(const OctetStr& usmUserName)
1162 return usm_user_table->delete_entries(usmUserName);
1165 int USM::delete_localized_user(const OctetStr& engine_id,
1166 const OctetStr& user_name)
1168 return usm_user_table->delete_entry(engine_id, user_name);
1172 int USM::build_localized_keys(const OctetStr &engine_id,
1173 const int auth_prot,
1174 const int priv_prot,
1175 const unsigned char *auth_password,
1176 const unsigned int auth_password_len,
1177 const unsigned char *priv_password,
1178 const unsigned int priv_password_len,
1179 unsigned char *auth_key,
1180 unsigned int *auth_key_len,
1181 unsigned char *priv_key,
1182 unsigned int *priv_key_len)
1184 int res = auth_priv->password_to_key_auth(
1185 auth_prot, auth_password,
1187 engine_id.data(), engine_id.len(),
1188 auth_key, auth_key_len);
1190 if (res != SNMPv3_USM_OK)
1192 if (res == SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL)
1194 LOG_BEGIN(ERROR_LOG | 4);
1195 LOG("Could not generate localized key: Unsupported auth protocol");
1201 LOG_BEGIN(ERROR_LOG | 4);
1202 LOG("Could not generate localized auth key, error code");
1209 res = auth_priv->password_to_key_priv(auth_prot, priv_prot, priv_password,
1211 engine_id.data(), engine_id.len(),
1212 priv_key, priv_key_len);
1214 if (res != SNMPv3_USM_OK)
1216 if (res == SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL)
1218 LOG_BEGIN(ERROR_LOG | 4);
1219 LOG("Could not generate localized key: Unsupported priv protocol");
1225 LOG_BEGIN(ERROR_LOG | 4);
1226 LOG("Could not generate localized priv key, error code");
1236 struct UsmUser *USM::get_user(const OctetStr &engine_id,
1237 const OctetStr &security_name)
1239 debugprintf(7,"USM::get_user: user (%s) engine_id (%s)",
1240 security_name.get_printable(),engine_id.get_printable());
1242 struct UsmUserNameTableEntry *name_table_entry = NULL;
1243 struct UsmUserTableEntry *user_table_entry = NULL;
1245 user_table_entry = usm_user_table->get_cloned_entry(engine_id,
1247 if (!user_table_entry)
1249 name_table_entry = usm_user_name_table->get_cloned_entry(security_name);
1250 if (!name_table_entry)
1252 const struct UsmUserTableEntry *entry;
1254 BEGIN_AUTO_LOCK(usm_user_table);
1256 entry = usm_user_table->get_entry(security_name);
1258 if ((entry) && (engine_id.len() == 0))
1260 // there is a entry for this security_name in the usmUserTable
1261 // so return an entry for this user to do engine_id discovery
1262 struct UsmUser *res = new UsmUser;
1267 res->engineIDLength = 0;
1268 res->usmUserName = v3strcpy(entry->usmUserName,
1269 entry->usmUserNameLength);
1270 res->usmUserNameLength = entry->usmUserNameLength;
1271 res->securityName = v3strcpy(entry->usmUserSecurityName,
1272 entry->usmUserSecurityNameLength);
1273 res->securityNameLength = entry->usmUserSecurityNameLength;
1274 res->authProtocol = SNMP_AUTHPROTOCOL_NONE;
1275 res->authKey = 0; res->authKeyLength = 0;
1276 res->privProtocol = SNMP_PRIVPROTOCOL_NONE;
1277 res->privKey = 0; res->privKeyLength = 0;
1279 if ((res->usmUserNameLength && !res->usmUserName) ||
1280 (res->securityNameLength && !res->securityName))
1288 debugprintf(1, "USM::get_user: User unknown");
1292 // here we have valid name_table_entry but not user_table_entry
1293 if (engine_id.len() == 0)
1295 // do not add a user
1296 struct UsmUser *res = new UsmUser;
1299 usm_user_name_table->delete_cloned_entry(name_table_entry);
1303 res->engineIDLength = 0;
1304 res->usmUserName = v3strcpy(name_table_entry->usmUserName.data(),
1305 name_table_entry->usmUserName.len());
1306 res->usmUserNameLength = name_table_entry->usmUserName.len();
1307 res->securityName = v3strcpy(
1308 name_table_entry->usmUserSecurityName.data(),
1309 name_table_entry->usmUserSecurityName.len());
1310 res->securityNameLength = name_table_entry->usmUserSecurityName.len();
1311 res->authProtocol = SNMP_AUTHPROTOCOL_NONE;
1313 res->authKeyLength = 0;
1314 res->privProtocol = SNMP_PRIVPROTOCOL_NONE;
1316 res->privKeyLength = 0;
1318 if ((res->usmUserNameLength && !res->usmUserName) ||
1319 (res->securityNameLength && !res->securityName))
1323 usm_user_name_table->delete_cloned_entry(name_table_entry);
1328 // We can add a new user:
1329 unsigned char privKey[SNMPv3_USM_MAX_KEY_LEN];
1330 unsigned char authKey[SNMPv3_USM_MAX_KEY_LEN];
1331 unsigned int authKeyLength = SNMPv3_USM_MAX_KEY_LEN;
1332 unsigned int privKeyLength = SNMPv3_USM_MAX_KEY_LEN;
1334 int res = build_localized_keys(engine_id,
1335 name_table_entry->usmUserAuthProtocol,
1336 name_table_entry->usmUserPrivProtocol,
1337 name_table_entry->authPassword,
1338 name_table_entry->authPasswordLength,
1339 name_table_entry->privPassword,
1340 name_table_entry->privPasswordLength,
1341 authKey, &authKeyLength,
1342 privKey, &privKeyLength);
1344 if (res != SNMPv3_USM_OK)
1346 LOG_BEGIN(ERROR_LOG | 4);
1347 LOG("Cannot add User: error code");
1351 usm_user_name_table->delete_cloned_entry(name_table_entry);
1355 OctetStr akey(authKey, authKeyLength);
1356 OctetStr pkey(privKey, privKeyLength);
1359 name_table_entry->usmUserName,
1360 name_table_entry->usmUserSecurityName,
1361 name_table_entry->usmUserAuthProtocol, akey,
1362 name_table_entry->usmUserPrivProtocol, pkey);
1364 if (usm_add_user_cb)
1366 // inform agent++ about new user
1367 debugprintf(5, "Informing agent++ about newly created user");
1368 usm_add_user_cb(engine_id,
1369 name_table_entry->usmUserName,
1370 name_table_entry->usmUserSecurityName,
1371 name_table_entry->usmUserAuthProtocol, akey,
1372 name_table_entry->usmUserPrivProtocol, pkey);
1377 user_table_entry = usm_user_table->get_cloned_entry(engine_id,
1379 if (!user_table_entry)
1381 LOG_BEGIN(ERROR_LOG | 1);
1382 LOG("Get of just added localized entry failed (sec name) (engine id)");
1383 LOG(security_name.get_printable());
1384 LOG(engine_id.get_printable());
1386 usm_user_name_table->delete_cloned_entry(name_table_entry);
1390 usm_user_name_table->delete_cloned_entry(name_table_entry);
1392 struct UsmUser *res = new UsmUser;
1395 usm_user_table->delete_cloned_entry(user_table_entry);
1398 res->engineID = user_table_entry->usmUserEngineID;
1399 res->engineIDLength = user_table_entry->usmUserEngineIDLength;
1400 res->usmUserName = user_table_entry->usmUserName;
1401 res->usmUserNameLength = user_table_entry->usmUserNameLength;
1402 res->securityName = user_table_entry->usmUserSecurityName;
1403 res->securityNameLength = user_table_entry->usmUserSecurityNameLength;
1404 res->authProtocol = user_table_entry->usmUserAuthProtocol;
1405 res->authKey = user_table_entry->usmUserAuthKey;
1406 res->authKeyLength = user_table_entry->usmUserAuthKeyLength;
1407 res->privProtocol = user_table_entry->usmUserPrivProtocol;
1408 res->privKey = user_table_entry->usmUserPrivKey;
1409 res->privKeyLength = user_table_entry->usmUserPrivKeyLength;
1411 user_table_entry->usmUserEngineID = 0;
1412 user_table_entry->usmUserName = 0;
1413 user_table_entry->usmUserSecurityName = 0;
1414 user_table_entry->usmUserAuthKey = 0;
1415 user_table_entry->usmUserPrivKey = 0;
1417 usm_user_table->delete_cloned_entry(user_table_entry);
1422 // Free the structure returned from get_user().
1423 void USM::free_user(struct UsmUser *&user)
1427 if (user->engineID) delete [] user->engineID;
1428 if (user->usmUserName) delete [] user->usmUserName;
1429 if (user->securityName) delete [] user->securityName;
1433 memset(user->authKey, 0, user->authKeyLength);
1434 delete [] user->authKey;
1439 memset(user->privKey, 0, user->privKeyLength);
1440 delete [] user->privKey;
1448 void USM::delete_usm_user(const OctetStr& security_name)
1450 usm_user_name_table->delete_security_name(security_name);
1452 unsigned char username[MAXLEN_USMUSERNAME + 1];
1453 long int length = MAXLEN_USMUSERNAME;
1455 if ((get_user_name(username, &length,
1456 security_name.data(), security_name.len()))
1458 delete_localized_user(OctetStr(username, length));
1461 int USM::get_security_name(const unsigned char *user_name,
1462 const long int user_name_len,
1463 OctetStr &security_name)
1465 debugprintf(20,"USM::get_security_name: get user (%s)",
1466 OctetStr(user_name,user_name_len).get_printable());
1470 result = usm_user_name_table->get_security_name(user_name, user_name_len,
1472 if (result == SNMPv3_USM_OK)
1473 return SNMPv3_USM_OK;
1475 result = usm_user_table->get_security_name(user_name, user_name_len,
1477 if (result == SNMPv3_USM_OK)
1478 return SNMPv3_USM_OK;
1480 debugprintf(1, "USM::get_security_name: User unknown");
1481 return SNMPv3_USM_ERROR;
1484 int USM::get_user_name(unsigned char *user_name, long int *user_name_len,
1485 const unsigned char *security_name,
1486 const long int security_name_len)
1489 long int buf_len = *user_name_len;
1491 result = usm_user_name_table->get_user_name(user_name, user_name_len,
1495 if (result == SNMPv3_USM_OK)
1496 return SNMPv3_USM_OK;
1498 *user_name_len = buf_len;
1500 result = usm_user_table->get_user_name(user_name, user_name_len,
1501 security_name, security_name_len);
1503 if (result == SNMPv3_USM_OK)
1504 return SNMPv3_USM_OK;
1506 debugprintf(1, "usmGetUsmUserName: User unknown");
1507 return SNMPv3_USM_ERROR;
1511 void USM::delete_sec_parameters( struct UsmSecurityParameters *usp)
1513 usp->msgAuthoritativeEngineID[0] = 0;
1514 usp->msgAuthoritativeEngineIDLength = 0;
1515 usp->msgAuthoritativeEngineBoots = 0;
1516 usp->msgAuthoritativeEngineTime = 0;
1517 usp->msgUserName[0] = 0;
1518 usp->msgUserNameLength = 0;
1520 if (usp->msgAuthenticationParameters) {
1521 delete [] usp->msgAuthenticationParameters;
1522 usp->msgAuthenticationParameters = NULL;
1524 usp->msgAuthenticationParametersLength = 0;
1525 if (usp->msgPrivacyParameters) {
1526 delete [] usp->msgPrivacyParameters;
1527 usp->msgPrivacyParameters = NULL;
1529 usp->msgPrivacyParametersLength = 0;
1533 const struct UsmUserTableEntry *USM::get_user(int number)
1535 return usm_user_table->get_entry(number);
1538 const struct UsmUserNameTableEntry *USM::get_user(const OctetStr &security_name)
1540 return usm_user_name_table->get_entry(security_name);
1543 int USM::get_user_count() const
1545 return usm_user_table->size();
1548 DLLOPT void USM::add_user_added_callback(const usm_add_user_callback cb)
1550 usm_add_user_cb = cb;
1553 int USM::get_time(const OctetStr &engine_id,
1554 long int *engine_boots, long int *engine_time)
1556 return usm_time_table->get_time(engine_id, *engine_boots, *engine_time);
1559 int USM::get_local_time(long int *engine_boots, long int *engine_time) const
1561 return usm_time_table->get_local_time(*engine_boots, *engine_time);
1564 AuthPriv *USM::get_auth_priv()
1569 struct UsmKeyUpdate* USM::key_update_prepare(const OctetStr& securityName,
1571 const OctetStr& newPassword,
1574 const OctetStr& oldpass,
1575 const OctetStr& oldengid,
1576 const OctetStr& newengid)
1580 GenAddress genaddress;
1581 target.get_address(genaddress);
1582 UdpAddress udp_address(genaddress);
1583 if (!udp_address.valid()) {
1584 debugprintf(0, "usmPrepareKeyUpdate: Address invalid.");
1585 status = SNMPv3_USM_ADDRESS_ERROR;
1589 OctetStr engineID = "";
1591 if (v3mp->get_from_engine_id_table(engineID,
1592 (char*)udp_address.get_printable())
1594 debugprintf(0, "usmPrepareKeyUpdate: Could not find engineID of given address.");
1595 status = SNMPv3_USM_ADDRESS_ERROR;
1600 struct UsmUser* user;
1601 user = get_user(engineID, securityName);
1604 debugprintf(0, "usmPrepareKeyUpdate: Could not find user in usmTables.");
1605 status = SNMPv3_USM_UNKNOWN_SECURITY_NAME;
1609 /* set old and new key */
1610 unsigned char key[SNMPv3_USM_MAX_KEY_LEN];
1611 unsigned int key_len = SNMPv3_USM_MAX_KEY_LEN;
1618 status = auth_priv->password_to_key_auth(
1620 newPassword.data(), newPassword.len(),
1621 engineID.data(), engineID.len(),
1623 oldKey = OctetStr(user->authKey, user->authKeyLength);
1628 status = auth_priv->password_to_key_priv(
1631 newPassword.data(), newPassword.len(),
1632 engineID.data(), engineID.len(),
1634 oldKey = OctetStr(user->privKey, user->privKeyLength);
1638 debugprintf(0, "usmPrepareKeyUpdate: wrong type specified.");
1639 status = SNMPv3_USM_ERROR;
1645 if (status != SNMPv3_USM_OK)
1647 debugprintf(0, "usmPrepareKeyUpdate: password_to_key failed (code %i).",
1653 newKey = OctetStr(key, key_len);
1655 /* get value to set and random value */
1657 OctetStr random_value;
1659 auth_priv->get_keychange_value(user->authProtocol,
1660 oldKey, newKey, newValue);
1663 for (int i = 0; i<30; i++) {
1665 random_value += tmp_rand;
1668 // Oid in usmUserTable
1669 Oid userOid = Oid(oidUsmUserEntry);
1670 Oid publicOid = Oid(oidUsmUserEntry);
1692 debugprintf(0, "KeyChange error: wrong type:");
1693 status = SNMPv3_USM_ERROR;
1699 userOid += engineID.len();
1700 publicOid += engineID.len();
1702 for (unsigned int j=0; j<engineID.len(); j++) {
1703 userOid += (engineID)[j];
1704 publicOid += (engineID)[j];
1707 OctetStr os = securityName;
1708 userOid += os.len();
1709 publicOid += os.len();
1711 for (unsigned int k=0; k<os.len(); k++) {
1717 vb.set_oid(userOid);
1718 vb.set_value(newValue);
1721 vb.set_oid(publicOid);
1722 vb.set_value(random_value);
1725 struct UsmKeyUpdate *uku = new struct UsmKeyUpdate;
1726 uku->engineID = engineID;
1727 uku->securityName = securityName;
1728 uku->newPassword = newPassword;
1729 uku->newKey = newKey;
1733 status = SNMPv3_USM_OK;
1737 void USM::key_update_abort(struct UsmKeyUpdate *uku)
1742 int USM::key_update_commit(struct UsmKeyUpdate *uku, int update_type)
1744 if (!uku) return SNMPv3_USM_ERROR;
1749 switch (update_type)
1751 case USM_KeyUpdate: {
1752 result = update_key(uku->securityName.data(), uku->securityName.len(),
1753 uku->engineID.data(), uku->engineID.len(),
1754 uku->newKey.data(), uku->newKey.len(),
1759 case USM_PasswordKeyUpdate: {
1760 result = update_key(uku->securityName.data(), uku->securityName.len(),
1761 uku->engineID.data(), uku->engineID.len(),
1762 uku->newKey.data(), uku->newKey.len(),
1764 struct UsmUserNameTableEntry *entry;
1765 entry = usm_user_name_table->get_cloned_entry(uku->securityName);
1766 if (!entry || (result != SNMPv3_USM_OK)) {
1769 usm_user_name_table->delete_cloned_entry(entry);
1770 return SNMPv3_USM_ERROR;
1773 result = SNMPv3_USM_ERROR;
1775 switch (uku->type) {
1778 OctetStr privPass(entry->privPassword, entry->privPasswordLength);
1779 result = add_usm_user(uku->securityName, entry->usmUserName,
1780 entry->usmUserAuthProtocol,
1781 entry->usmUserPrivProtocol,
1782 uku->newPassword, privPass);
1787 OctetStr authPass(entry->privPassword, entry->privPasswordLength);
1788 result = add_usm_user(uku->securityName, entry->usmUserName,
1789 entry->usmUserAuthProtocol,
1790 entry->usmUserPrivProtocol,
1791 authPass, uku->newPassword);
1796 usm_user_name_table->delete_cloned_entry(entry);
1799 case USM_PasswordAllKeyUpdate: {
1800 struct UsmUserNameTableEntry *entry;
1801 entry = usm_user_name_table->get_cloned_entry(uku->securityName);
1804 return SNMPv3_USM_ERROR;
1807 result = SNMPv3_USM_ERROR;
1809 switch (uku->type) {
1812 OctetStr privPass = OctetStr(entry->privPassword,
1813 entry->privPasswordLength);
1814 delete_usm_user(uku->securityName);
1815 result = add_usm_user(uku->securityName, entry->usmUserName,
1816 entry->usmUserAuthProtocol,
1817 entry->usmUserPrivProtocol,
1818 uku->newPassword, privPass);
1823 OctetStr authPass = OctetStr(entry->authPassword,
1824 entry->authPasswordLength);
1825 delete_usm_user(uku->securityName);
1826 result = add_usm_user(uku->securityName, entry->usmUserName,
1827 entry->usmUserAuthProtocol,
1828 entry->usmUserPrivProtocol,
1829 authPass, uku->newPassword);
1834 usm_user_name_table->delete_cloned_entry(entry);
1839 return SNMPv3_USM_ERROR;
1842 int USM::generate_msg(
1843 unsigned char *globalData, // message header, admin data
1844 int globalDataLength,
1845 int maxMessageSize, // of the sending SNMP entity
1846 const OctetStr &securityEngineID,// authoritative SNMP entity
1847 const OctetStr &securityName, // on behalf of this principal
1848 int securityLevel, // Level of Security requested
1849 unsigned char *scopedPDU, // message (plaintext) payload
1850 int scopedPDULength,
1851 struct SecurityStateReference *securityStateReference,
1852 unsigned char *wholeMsg, // OUT complete generated message
1853 int *wholeMsgLength) // OUT length of generated message
1855 Buffer<unsigned char> buffer(MAX_SNMP_PACKET);
1856 Buffer<unsigned char> buffer2(MAX_SNMP_PACKET);
1857 unsigned char *bufPtr = buffer.get_ptr();
1858 unsigned char *buf2Ptr = buffer2.get_ptr();
1860 if (!bufPtr || !buf2Ptr)
1861 return SNMPv3_USM_ERROR;
1863 unsigned char *wholeMsgPtr;
1864 int startAuthPar = 0;
1865 struct UsmUser *user = NULL;
1866 struct UsmSecurityParameters usmSecurityParams;
1869 unsigned int buf2Length = 0;
1870 int totalLength = 0; // Bytes encoded
1871 int restLength = maxMessageSize; // max Bytes left in packet-buffer
1873 int responseMsg = 0;
1875 if (securityStateReference) {
1876 // this is a response message
1880 return SNMPv3_USM_ERROR;
1881 if (securityStateReference->securityEngineID) {
1882 user->engineIDLength = securityStateReference->securityEngineIDLength;
1883 user->engineID = securityStateReference->securityEngineID;
1885 user->engineIDLength = securityEngineID.len();
1886 user->engineID = v3strcpy(securityEngineID.data(),
1887 securityEngineID.len());
1890 user->usmUserName = new unsigned char[MAXLEN_USMUSERNAME + 1];
1891 if (securityStateReference->securityName)
1893 user->securityName = securityStateReference->securityName;
1894 user->securityNameLength = securityStateReference->securityNameLength;
1895 memcpy(user->usmUserName, securityStateReference->msgUserName,
1896 securityStateReference->msgUserNameLength);
1897 user->usmUserNameLength = securityStateReference->msgUserNameLength;
1901 user->securityNameLength = securityName.len();
1902 user->securityName = v3strcpy(securityName.data(), securityName.len());
1903 if (securityStateReference->msgUserNameLength)
1905 securityStateReference->msgUserName[0] = 0;
1906 securityStateReference->msgUserNameLength = 0;
1908 user->usmUserNameLength = MAXLEN_USMUSERNAME;
1909 get_user_name(user->usmUserName, &user->usmUserNameLength,
1910 securityName.data(), securityName.len());
1911 if ((user->usmUserNameLength == 0) &&
1912 (securityName.len() <= MAXLEN_USMUSERNAME)) {
1913 memcpy(user->usmUserName, securityName.data(), securityName.len());
1914 user->usmUserName[securityName.len()] = 0;
1915 user->usmUserNameLength = securityName.len();
1918 user->authProtocol = securityStateReference->authProtocol;
1919 user->authKey = securityStateReference->authKey;
1920 user->authKeyLength = securityStateReference->authKeyLength;
1921 user->privProtocol = securityStateReference->privProtocol;
1922 user->privKeyLength = securityStateReference->privKeyLength;
1923 user->privKey = securityStateReference->privKey;
1925 delete securityStateReference;
1926 securityStateReference = NULL;
1930 if (securityEngineID.len() == 0)
1935 return SNMPv3_USM_ERROR;
1936 memset(user, 0, sizeof(UsmUser));
1940 // search for user in usmUserTable
1941 user = get_user(securityEngineID, securityName);
1944 debugprintf(0, "USM: User unknown!");
1945 return SNMPv3_USM_UNKNOWN_SECURITY_NAME;
1950 if (securityEngineID.len() > MAXLENGTH_ENGINEID)
1952 debugprintf(0, "engine_id too long %i > %i",
1953 securityEngineID.len(), MAXLENGTH_ENGINEID);
1955 return SNMPv3_USM_ERROR;
1958 if (user->usmUserNameLength > MAXLEN_USMUSERNAME)
1960 debugprintf(0, "user name too long %i > %i",
1961 user->usmUserNameLength, MAXLEN_USMUSERNAME);
1963 return SNMPv3_USM_ERROR;
1966 usmSecurityParams.msgAuthoritativeEngineIDLength = securityEngineID.len();
1967 usmSecurityParams.msgUserNameLength = user->usmUserNameLength;
1968 memcpy(usmSecurityParams.msgUserName,
1969 user->usmUserName, user->usmUserNameLength);
1970 memcpy(usmSecurityParams.msgAuthoritativeEngineID,
1971 securityEngineID.data(), securityEngineID.len());
1973 usmSecurityParams.msgPrivacyParametersLength = 0;
1974 usmSecurityParams.msgPrivacyParameters = NULL;
1976 usmSecurityParams.msgAuthenticationParametersLength = 0;
1977 usmSecurityParams.msgAuthenticationParameters = NULL;
1979 if (securityLevel >= SNMP_SECURITY_LEVEL_AUTH_NOPRIV)
1981 // get engineBoots, engineTime
1982 rc = usm_time_table->get_time(
1984 usmSecurityParams.msgAuthoritativeEngineBoots,
1985 usmSecurityParams.msgAuthoritativeEngineTime);
1986 if (rc == SNMPv3_USM_UNKNOWN_ENGINEID) {
1987 usm_time_table->add_entry(securityEngineID,
1988 usmSecurityParams.msgAuthoritativeEngineBoots,
1989 usmSecurityParams.msgAuthoritativeEngineTime);
1991 if (rc == SNMPv3_USM_ERROR) {
1992 debugprintf(0, "usm: usmGetTime error.");
1994 return SNMPv3_USM_ERROR;
1998 if (securityLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV)
2000 usmSecurityParams.msgPrivacyParametersLength
2001 = auth_priv->get_priv_params_len(user->privProtocol);
2002 usmSecurityParams.msgPrivacyParameters
2003 = new unsigned char[usmSecurityParams.msgPrivacyParametersLength];
2006 int enc_result = auth_priv->encrypt_msg(
2008 user->privKey, user->privKeyLength,
2009 scopedPDU, scopedPDULength,
2010 buf2Ptr, &buf2Length,
2011 usmSecurityParams.msgPrivacyParameters,
2012 &usmSecurityParams.msgPrivacyParametersLength,
2013 usmSecurityParams.msgAuthoritativeEngineBoots,
2014 usmSecurityParams.msgAuthoritativeEngineTime);
2015 if (enc_result != SNMPv3_USM_OK)
2019 if (user->privProtocol == SNMP_PRIVPROTOCOL_NONE)
2021 debugprintf(0, "usm: Privacy requested, but no UserPrivProtocol");
2022 return_value = SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL;
2026 return_value = SNMPv3_USM_ENCRYPTION_ERROR;
2029 debugprintf(0, "usm: Encryption error (result %i).", enc_result);
2031 delete_sec_parameters(&usmSecurityParams);
2033 return return_value;
2036 bufPtr = asn_build_string(bufPtr, &restLength, ASN_UNI_PRIM | ASN_OCTET_STR,
2037 buf2Ptr, buf2Length);
2039 debugprintf(0, "usm: Encoding Error");
2041 return SNMPv3_USM_ERROR;
2043 bufLength = SAFE_INT_CAST(bufPtr - buffer.get_ptr());
2044 totalLength = bufLength;
2045 bufPtr = buffer.get_ptr();
2046 memcpy(buf2Ptr, bufPtr, bufLength);
2047 buf2Length = bufLength;
2049 } else { // (securityLevel != SNMP_SECURITY_LEVEL_AUTH_PRIV)
2050 buf2Ptr = scopedPDU;
2051 buf2Length = scopedPDULength;
2052 totalLength = scopedPDULength;
2055 debugprintf(0, "usm: Encoding Error");
2057 return SNMPv3_USM_ERROR;
2060 totalLength += SAFE_INT_CAST(bufPtr - buffer.get_ptr());
2061 memcpy(bufPtr, buf2Ptr, buf2Length);
2062 bufLength = totalLength;
2064 debugprintf(21, "buf after privacy:");
2065 debughexprintf(21, buffer.get_ptr(), bufLength);
2067 wholeMsgPtr = wholeMsg;
2069 if (securityLevel >= SNMP_SECURITY_LEVEL_AUTH_NOPRIV)
2071 /* Build message with authentication */
2072 usmSecurityParams.msgAuthenticationParametersLength
2073 = auth_priv->get_auth_params_len(user->authProtocol);
2074 usmSecurityParams.msgAuthenticationParameters
2075 = new unsigned char[usmSecurityParams.msgAuthenticationParametersLength];
2076 memset((char*)(usmSecurityParams.msgAuthenticationParameters), 0,
2077 usmSecurityParams.msgAuthenticationParametersLength);
2079 wholeMsgPtr = build_whole_msg(wholeMsgPtr, &maxMessageSize,
2080 globalData, globalDataLength,
2081 &startAuthPar, // for MD5, SHA,...
2084 bufLength); // the msgData
2085 if (wholeMsgPtr == NULL)
2087 debugprintf(0, "usm: could not generate wholeMsg");
2088 delete_sec_parameters(&usmSecurityParams);
2090 return SNMPv3_USM_ERROR;
2092 *wholeMsgLength = SAFE_INT_CAST(wholeMsgPtr - wholeMsg);
2094 rc = auth_priv->auth_out_msg(user->authProtocol,
2096 wholeMsg, *wholeMsgLength,
2097 wholeMsg + startAuthPar);
2099 if (rc!=SNMPv3_USM_OK)
2101 debugprintf(0, "usm: Authentication error for outgoing message."
2102 " error code (%i).", rc);
2103 delete_sec_parameters(&usmSecurityParams);
2110 //build Message without authentication
2112 // Set engineBoots and enigneTime to zero!
2113 usmSecurityParams.msgAuthoritativeEngineBoots = 0;
2114 usmSecurityParams.msgAuthoritativeEngineTime = 0;
2116 usmSecurityParams.msgAuthenticationParametersLength = 0;
2117 usmSecurityParams.msgAuthenticationParameters = 0;
2119 wholeMsgPtr = build_whole_msg(wholeMsgPtr, &maxMessageSize,
2120 globalData, globalDataLength,
2121 &startAuthPar, // dummy ( no auth)
2124 bufLength); // the msgData
2125 if (wholeMsgPtr == NULL) {
2126 debugprintf(0, "usm: could not generate wholeMsg");
2127 delete_sec_parameters(&usmSecurityParams);
2129 return SNMPv3_USM_ERROR;
2131 *wholeMsgLength = SAFE_INT_CAST(wholeMsgPtr - wholeMsg);
2134 debugprintf(21, "Complete Whole Msg:");
2135 debughexprintf(21, wholeMsg, *wholeMsgLength);
2137 delete_sec_parameters(&usmSecurityParams);
2139 return SNMPv3_USM_OK;
2142 int USM::process_msg(
2143 int maxMessageSize, // of the sending SNMP entity
2144 unsigned char *securityParameters,// for the received message
2145 int securityParametersLength,
2146 int securityParametersPosition,
2147 long int securityLevel, // Level of Security
2148 unsigned char *wholeMsg, // as received on the wire
2149 int wholeMsgLength, // length as received on the wire
2150 unsigned char *msgData,
2152 OctetStr &security_engine_id, // authoritative SNMP entity
2153 OctetStr &security_name, //identification of the principal
2154 unsigned char *scopedPDU, // message (plaintext) payload
2155 int *scopedPDULength,
2156 long *maxSizeResponseScopedPDU, // maximum size of the Response PDU
2157 struct SecurityStateReference *securityStateReference,
2158 // reference to security state
2159 // information, needed for response
2160 const UdpAddress &fromAddress)
2162 unsigned char* sp = securityParameters;
2163 int spLength = securityParametersLength;
2165 long int engineBoots, engineTime;
2166 unsigned char authParam[SNMPv3_AP_MAXLENGTH_AUTHPARAM];
2167 unsigned char privParam[SNMPv3_AP_MAXLENGTH_PRIVPARAM];
2168 int authParamLength = SNMPv3_AP_MAXLENGTH_AUTHPARAM;
2169 int privParamLength = SNMPv3_AP_MAXLENGTH_PRIVPARAM;
2170 Buffer<unsigned char> encryptedScopedPDU(MAX_SNMP_PACKET);
2171 int encryptedScopedPDULength = msgDataLength;
2172 struct UsmUser *user = NULL;
2176 // check securityParameters
2177 sp = asn_parse_header( sp, &spLength, &type);
2179 debugprintf(0, "bad header of securityParameters");
2180 return SNMPv3_USM_PARSE_ERROR;
2182 debugprintf(3, "Parsed securityParametersLength = 0x%x", spLength);
2184 if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)){
2185 debugprintf(0, "wrong type in header of securityParameters");
2186 return SNMPv3_USM_PARSE_ERROR;
2189 // extract security parameters
2191 int len = MAXLENGTH_ENGINEID + 1;
2192 unsigned char data[MAXLENGTH_ENGINEID + 1];
2193 sp = asn_parse_string( sp, &spLength, &type, data, &len);
2195 debugprintf(3, "Parsed securityEngineID, length = 0x%x", len);
2197 debugprintf(0, "bad parse of securityEngineID");
2198 return SNMPv3_USM_PARSE_ERROR;
2200 security_engine_id.set_data(data, len);
2203 sp = asn_parse_int(sp, &spLength, &type, &engineBoots);
2204 if ((sp == NULL) || (engineBoots < 0)) {
2205 debugprintf(0, "bad parse of engineBoots");
2206 return SNMPv3_USM_PARSE_ERROR;
2209 sp = asn_parse_int(sp, &spLength, &type, &engineTime);
2210 if ((sp == NULL) || (engineTime < 0)) {
2211 debugprintf(0, "bad parse of engineTime");
2212 return SNMPv3_USM_PARSE_ERROR;
2215 debugprintf(3, "Parsed engineBoots(0x%lx), engineTime(0x%lx)",
2216 engineTime, engineBoots);
2218 unsigned char usmUserName[MAXLEN_USMUSERNAME + 1];
2219 int usmUserNameLength = MAXLEN_USMUSERNAME;
2221 sp = asn_parse_string( sp, &spLength, &type,
2222 (unsigned char*)&usmUserName, &usmUserNameLength);
2225 debugprintf(0, "bad parse of usmUserName");
2226 return SNMPv3_USM_PARSE_ERROR;
2229 sp = asn_parse_string( sp, &spLength, &type,
2230 (unsigned char*)&authParam, &authParamLength);
2233 debugprintf(0, "bad parse of msgAuthenticationParameters");
2234 return SNMPv3_USM_PARSE_ERROR;
2236 int authParametersPosition = securityParametersPosition +
2237 SAFE_INT_CAST(sp - securityParameters) - authParamLength;
2239 sp = asn_parse_string( sp, &spLength, &type,
2240 (unsigned char*)&privParam, &privParamLength);
2243 debugprintf(0, "bad parse of msgPrivacyParameters");
2244 return SNMPv3_USM_PARSE_ERROR;
2247 debugprintf(0, "Error Parsing msgPrivacyParameters");
2248 return SNMPv3_USM_PARSE_ERROR;
2250 debugprintf(5, "Parsed usmUserName length(0x%x)"
2251 " msgAuthenticationParameters length(0x%x)"
2252 " msgPrivacyParameters length(0x%x)",
2253 usmUserNameLength, authParamLength, privParamLength);
2255 // prepare securityStateReference
2256 if (usmUserNameLength > MAXLEN_USMUSERNAME)
2258 debugprintf(0, "user name too long: %i > %i.",
2259 usmUserNameLength, MAXLEN_USMUSERNAME);
2260 return SNMPv3_USM_PARSE_ERROR;
2263 securityStateReference->msgUserNameLength = usmUserNameLength;
2264 memcpy(securityStateReference->msgUserName, usmUserName,
2265 securityStateReference->msgUserNameLength);
2267 securityStateReference->securityEngineIDLength = security_engine_id.len();
2268 securityStateReference->securityEngineID =
2269 new unsigned char [securityStateReference->securityEngineIDLength];
2270 memcpy(securityStateReference->securityEngineID, security_engine_id.data(),
2271 securityStateReference->securityEngineIDLength);
2273 securityStateReference->securityLevel = securityLevel;
2275 securityStateReference->securityNameLength = 0;
2276 securityStateReference->securityName = NULL;
2277 securityStateReference->authProtocol = 1;
2278 securityStateReference->privProtocol = 1;
2279 securityStateReference->authKey = NULL;
2280 securityStateReference->privKey = NULL;
2282 // in case we return with error,
2283 // perhaps v3MP can decode it (requestID!!!)
2284 memcpy(scopedPDU, msgData, msgDataLength);
2285 *scopedPDULength = msgDataLength;
2287 if ((security_engine_id.len() == 0) ||
2288 (usm_time_table->check_engine_id(security_engine_id) != SNMPv3_USM_OK ))
2290 inc_stats_unknown_engine_ids();
2293 securityStateReference->securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
2294 security_name.set_data(usmUserName, usmUserNameLength);
2296 debugprintf(2, "USM: EngineID unknown");
2297 return SNMPv3_USM_UNKNOWN_ENGINEID;
2300 // get securityName:
2301 if ((usmUserNameLength) ||
2302 (securityLevel != SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV))
2304 rc = get_security_name(usmUserName, usmUserNameLength, security_name);
2305 if (rc != SNMPv3_USM_OK) {
2306 inc_stats_unknown_user_names();
2307 security_name.set_data(usmUserName, usmUserNameLength);
2309 debugprintf(2,"usmProcessMsg: unknown user (%s)",
2310 security_name.get_printable());
2311 return SNMPv3_USM_UNKNOWN_SECURITY_NAME;
2316 debugprintf(2, "Accepting zero length user/security name.");
2320 securityStateReference->securityNameLength = security_name.len();
2321 securityStateReference->securityName =
2322 new unsigned char [securityStateReference->securityNameLength];
2323 memcpy(securityStateReference->securityName, security_name.data(),
2324 securityStateReference->securityNameLength);
2326 // get user from LCD (usmUserTable)
2327 if (usmUserNameLength)
2329 user = get_user(security_engine_id, security_name);
2332 inc_stats_unknown_user_names();
2333 debugprintf(0, "usmProcessMsg: unknown user");
2334 return SNMPv3_USM_UNKNOWN_SECURITY_NAME;
2342 debugprintf(0, "Memory error");
2343 return SNMPv3_USM_ERROR;
2345 memset(user, 0, sizeof(UsmUser));
2348 if (((securityLevel > SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV) &&
2349 (user->authProtocol == SNMP_AUTHPROTOCOL_NONE)) ||
2350 ((securityLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV) &&
2351 (user->privProtocol == SNMP_PRIVPROTOCOL_NONE))) {
2352 inc_stats_unsupported_sec_levels();
2353 debugprintf(0, "usmProcessMsg: unsupported Securitylevel");
2355 return SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL;
2358 if (securityLevel > SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV)
2360 rc = auth_priv->auth_inc_msg(user->authProtocol,
2362 wholeMsg, wholeMsgLength,
2363 wholeMsg + authParametersPosition,
2365 if (rc != SNMPv3_USM_OK)
2369 case SNMPv3_USM_AUTHENTICATION_FAILURE:
2370 debugprintf(0, "usmProcessMsg: Authentication failure.");
2371 inc_stats_wrong_digests();
2372 /* set securityLevel for Report */
2374 case SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL:
2375 debugprintf(0, "usmProcessMsg: unknown AuthProtocol");
2376 inc_stats_unsupported_sec_levels();
2378 debugprintf(0, "usmProcessMsg: error authenticating msg."
2379 " Error code (%i).", rc);
2380 // todo: is it ok to increment this counter?
2381 inc_stats_unsupported_sec_levels();
2384 securityStateReference->securityLevel= SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
2389 rc = usm_time_table->check_time(security_engine_id,
2390 engineBoots, engineTime);
2391 if (rc == SNMPv3_USM_NOT_IN_TIME_WINDOW)
2393 inc_stats_not_in_time_windows();
2394 debugprintf(2, "***Message not in TimeWindow!");
2397 if (rc == SNMPv3_USM_UNKNOWN_ENGINEID)
2399 debugprintf(0, "***EngineID not in timeTable!");
2405 *scopedPDULength = MAX_SNMP_PACKET;
2407 // decrypt ScopedPDU if message is in time window
2408 if ((securityLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV)
2410 msgData = asn_parse_string( msgData, &msgDataLength, &type,
2411 encryptedScopedPDU.get_ptr(),
2412 &encryptedScopedPDULength);
2413 if (msgData == NULL){
2414 debugprintf(0, "usmProcessMsg: bad header of encryptedPDU");
2416 return SNMPv3_USM_PARSE_ERROR;
2420 unsigned int tmp_length = *scopedPDULength;
2421 int dec_result = auth_priv->decrypt_msg(
2423 user->privKey, user->privKeyLength,
2424 encryptedScopedPDU.get_ptr(),
2425 encryptedScopedPDULength,
2426 scopedPDU, &tmp_length,
2427 (unsigned char*)&privParam, privParamLength,
2428 engineBoots, engineTime);
2429 *scopedPDULength = tmp_length;
2430 if (dec_result != SNMPv3_USM_OK)
2433 if (dec_result == SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL)
2435 debugprintf(0, "usmProcessMsg: unknown PrivacyProtocol");
2436 inc_stats_unsupported_sec_levels();
2437 return_value = SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL;
2441 debugprintf(0, "usmProcessMsg: Decryption error (result %i).",
2443 inc_stats_decryption_errors();
2444 return_value = SNMPv3_USM_DECRYPTION_ERROR;
2447 return return_value;
2450 debugprintf(21, "scopedPDU(1):");
2451 debughexprintf(21, scopedPDU, *scopedPDULength);
2453 // test for decryption error
2455 if (scopedPDU[0] != (ASN_CONSTRUCTOR | ASN_SEQUENCE)) {
2456 debugprintf(0, "Decryption error detected");
2457 inc_stats_decryption_errors();
2459 return SNMPv3_USM_DECRYPTION_ERROR;
2463 // message was not encrypted
2464 memcpy(scopedPDU, msgData, msgDataLength);
2465 *scopedPDULength = msgDataLength;
2468 *maxSizeResponseScopedPDU = maxMessageSize - (wholeMsgLength - *scopedPDULength);
2470 security_name.set_data(user->securityName, user->securityNameLength);
2472 securityStateReference->authProtocol = user->authProtocol;
2473 securityStateReference->privProtocol = user->privProtocol;
2475 securityStateReference->authKeyLength = user->authKeyLength;
2476 securityStateReference->authKey = user->authKey;
2478 securityStateReference->privKeyLength = user->privKeyLength;
2479 securityStateReference->privKey = user->privKey;
2487 return SNMPv3_USM_NOT_IN_TIME_WINDOW;
2489 return SNMPv3_USM_OK;
2492 unsigned char *USM::build_sec_params(unsigned char *outBuf, int *maxLength,
2493 struct UsmSecurityParameters sp,
2496 Buffer<unsigned char> buf(MAX_SNMP_PACKET);
2497 unsigned char *bufPtr = buf.get_ptr();
2498 unsigned char *outBufPtr = outBuf;
2499 int length = *maxLength;
2502 debugprintf(5, "Coding octstr sp.msgAuthoritativeEngineID, length = 0x%lx",
2503 sp.msgAuthoritativeEngineIDLength);
2504 bufPtr = asn_build_string(bufPtr, &length,
2505 ASN_UNI_PRIM | ASN_OCTET_STR,
2506 sp.msgAuthoritativeEngineID,
2507 sp.msgAuthoritativeEngineIDLength);
2508 if (bufPtr == NULL) {
2509 debugprintf(0, "usmBuildSecurityParameters error coding engineid");
2513 debugprintf(5, "Coding int sp.msgAuthoritativeEngineBoots = 0x%lx",
2514 sp.msgAuthoritativeEngineBoots);
2515 bufPtr = asn_build_int(bufPtr, &length, ASN_UNI_PRIM | ASN_INTEGER,
2516 &sp.msgAuthoritativeEngineBoots);
2518 if (bufPtr == NULL) {
2519 debugprintf(0, "usmBuildSecurityParameters error coding engineboots");
2523 debugprintf(5, "Coding int sp.msgAuthoritativeEngineTime = 0x%lx",
2524 sp.msgAuthoritativeEngineTime);
2525 bufPtr = asn_build_int(bufPtr, &length, ASN_UNI_PRIM | ASN_INTEGER,
2526 &sp.msgAuthoritativeEngineTime);
2528 if (bufPtr == NULL) {
2529 debugprintf(0, "usmBuildSecurityParameters error coding enginetime");
2533 debugprintf(5, "Coding octstr sp.msgUserName, length = 0x%lx",
2534 sp.msgUserNameLength);
2535 bufPtr = asn_build_string(bufPtr, &length, ASN_UNI_PRIM | ASN_OCTET_STR,
2536 sp.msgUserName, sp.msgUserNameLength);
2537 if (bufPtr == NULL) {
2538 debugprintf(0, "usmBuildSecurityParameters error coding msgusername");
2542 *position = SAFE_INT_CAST(bufPtr - buf.get_ptr()) + 2;
2544 debugprintf(5, "Coding octstr sp.msgAu..Para.. , length = 0x%lx",
2545 sp.msgAuthenticationParametersLength);
2546 bufPtr = asn_build_string(bufPtr, &length, ASN_UNI_PRIM | ASN_OCTET_STR,
2547 sp.msgAuthenticationParameters,
2548 sp.msgAuthenticationParametersLength);
2550 if (bufPtr == NULL) {
2551 debugprintf(0, "usmBuildSecurityParameters error coding authparams");
2555 debugprintf(5, "Coding octstr sp.msgPr..Para.. , length = 0x%lx",
2556 sp.msgPrivacyParametersLength);
2557 bufPtr = asn_build_string(bufPtr, &length, ASN_UNI_PRIM | ASN_OCTET_STR,
2558 sp.msgPrivacyParameters,
2559 sp.msgPrivacyParametersLength);
2561 if (bufPtr == NULL) {
2562 debugprintf(0, "usmBuildSecurityParameters error coding privparams");
2566 totalLength = SAFE_INT_CAST(bufPtr - buf.get_ptr());
2568 debugprintf(5, "Coding sequence (securityPar), length = 0x%x", totalLength);
2569 outBufPtr = asn_build_sequence(outBufPtr, maxLength, ASN_SEQ_CON,
2572 if (outBufPtr == NULL) {
2573 debugprintf(0, "usm: usmBuildSecurityParameters error coding secparams");
2577 if (*maxLength < totalLength) {
2578 debugprintf(0, "usm: usmBuildSecurityParameters error (length mismatch)");
2581 *position += SAFE_INT_CAST(outBufPtr - outBuf);
2582 memcpy(outBufPtr, buf.get_ptr(), totalLength);
2583 outBufPtr += totalLength;
2584 *maxLength -= totalLength;
2586 debugprintf(21, "bufSecurityData:");
2587 debughexprintf(21, outBuf, SAFE_INT_CAST(outBufPtr - outBuf));
2592 unsigned char *USM::build_whole_msg(
2593 unsigned char *outBuf, int *maxLength,
2594 unsigned char *globalData, long int globalDataLength,
2595 int *positionAuthPar,
2596 struct UsmSecurityParameters securityParameters,
2597 unsigned char *msgData, long int msgDataLength)
2599 Buffer<unsigned char> buf(MAX_SNMP_PACKET);
2600 unsigned char *bufPtr = buf.get_ptr();
2601 Buffer<unsigned char> secPar(MAX_SNMP_PACKET);
2602 unsigned char *secParPtr = secPar.get_ptr();
2603 unsigned char *outBufPtr = outBuf;
2604 long int secParLength;
2605 int length = *maxLength;
2608 int dummy = *maxLength;
2610 secParPtr = build_sec_params(secParPtr, &dummy, securityParameters,
2615 secParLength = SAFE_INT_CAST(secParPtr - secPar.get_ptr());
2617 long int dummyVersion = 3;
2618 debugprintf(3, "Coding int snmpVersion = 0x%lx",dummyVersion);
2619 bufPtr = asn_build_int(bufPtr, &length, ASN_UNI_PRIM | ASN_INTEGER,
2621 if (bufPtr == NULL) {
2622 debugprintf(0, "usmBuildWholeMsg error");
2626 // globalData is encoded as sequence
2627 length -= globalDataLength;
2629 debugprintf(0, "usmBuildWholeMsg error");
2632 memcpy(bufPtr, globalData, globalDataLength);
2633 bufPtr += globalDataLength;
2635 *positionAuthPar += SAFE_INT_CAST(bufPtr - buf.get_ptr()) +2;
2636 if (secParLength> 0x7f)
2637 *positionAuthPar += 2;
2639 debugprintf(3, "Coding octstr securityParameter, length = 0x%lx",
2641 bufPtr = asn_build_string(bufPtr, &length, ASN_UNI_PRIM | ASN_OCTET_STR,
2642 secPar.get_ptr(), secParLength);
2644 if (bufPtr == NULL) {
2645 debugprintf(0, "usmBuildWholeMsg error2");
2649 // msgData (ScopedPduData) is encoded
2650 length -=msgDataLength;
2652 debugprintf(10, "usmBuildWholeMsg error: msgDataLength = %i",
2654 debugprintf(10, "maxLength = %i, encoded = %i", *maxLength,
2655 SAFE_INT_CAST(bufPtr - buf.get_ptr()));
2658 memcpy(bufPtr, msgData, msgDataLength);
2659 bufPtr += msgDataLength;
2661 totalLength = SAFE_INT_CAST(bufPtr - buf.get_ptr());
2663 debugprintf(3, "Coding sequence (wholeMsg), length = 0x%x", totalLength);
2665 outBufPtr = asn_build_sequence(outBufPtr, maxLength, ASN_SEQ_CON,
2668 if (outBufPtr == NULL) {
2669 debugprintf(0, "usm: usmBuildWholeMsg error");
2673 if (*maxLength < totalLength) {
2674 debugprintf(0, "usm: usmBuildWholeMsg error");
2677 *positionAuthPar += SAFE_INT_CAST(outBufPtr - outBuf);
2678 memcpy(outBufPtr, buf.get_ptr(), totalLength);
2679 outBufPtr += totalLength;
2680 *maxLength -= totalLength;
2682 debugprintf(21,"bufWholeMsg:");
2683 debughexprintf(21, outBuf, SAFE_INT_CAST(outBufPtr - outBuf));
2688 inline void USM::delete_user_ptr(struct UsmUser *user)
2691 if (user->engineID) {
2692 delete [] user->engineID;
2693 user->engineID = NULL;
2695 if (user->usmUserName) {
2696 delete [] user->usmUserName;
2697 user->usmUserName = NULL;
2699 if (user->securityName) {
2700 delete [] user->securityName;
2701 user->securityName = NULL;
2703 if (user->authKey) {
2704 memset(user->authKey, 0, user->authKeyLength);
2705 delete [] user->authKey;
2706 user->authKey = NULL;
2708 if (user->privKey) {
2709 memset(user->privKey, 0, user->privKeyLength);
2710 delete [] user->privKey;
2711 user->authKey = NULL;
2715 // Save all localized users into a file.
2716 int USM::save_localized_users(const char *file)
2718 return usm_user_table->save_to_file(file, auth_priv);
2721 // Load localized users from a file.
2722 int USM::load_localized_users(const char *file)
2724 return usm_user_table->load_from_file(file, auth_priv);
2727 // Safe all users with their passwords into a file.
2728 int USM::save_users(const char *file)
2730 return usm_user_name_table->save_to_file(file, auth_priv);
2733 // Load users with their passwords from a file.
2734 int USM::load_users(const char *file)
2736 return usm_user_name_table->load_from_file(file, auth_priv);
2739 // Lock the UsmUserNameTable for access through peek_first/next_user()
2740 void USM::lock_user_name_table()
2742 usm_user_name_table->lock();
2745 // Get a const pointer to the first entry of the UsmUserNameTable.
2746 const UsmUserNameTableEntry *USM::peek_first_user()
2748 return usm_user_name_table->peek_first();
2751 // Get a const pointer to the next entry of the UsmUserNameTable.
2752 const UsmUserNameTableEntry *USM::peek_next_user(const UsmUserNameTableEntry *e)
2754 return usm_user_name_table->peek_next(e);
2757 // Unlock the UsmUserNameTable after access through peek_first/next_user()
2758 void USM::unlock_user_name_table()
2760 usm_user_name_table->unlock();
2763 // Lock the UsmUserTable for access through peek_first/next_luser()
2764 void USM::lock_user_table()
2766 usm_user_table->lock();
2769 // Get a const pointer to the first entry of the UsmUserTable.
2770 const UsmUserTableEntry *USM::peek_first_luser()
2772 return usm_user_table->peek_first();
2775 // Get a const pointer to the next entry of the UsmUserTable.
2776 const UsmUserTableEntry *USM::peek_next_luser(const UsmUserTableEntry *e)
2778 return usm_user_table->peek_next(e);
2781 // Unlock the UsmUserTable after access through peek_first/next_luser()
2782 void USM::unlock_user_table()
2784 usm_user_table->unlock();
2788 /* ----------------------- class USMTimeTable --------------------*/
2790 USMTimeTable::USMTimeTable(const USM *owner,
2791 const unsigned int engine_boots, int &result)
2795 table = new struct Entry_T[5];
2799 LOG_BEGIN(ERROR_LOG | 1);
2800 LOG("USMTimeTable: error constructing table.");
2803 result = SNMPv3_USM_ERROR;
2809 /* the first entry always contains the local engine id and time */
2812 table[0].time_diff = - SAFE_LONG_CAST(now);
2813 table[0].engine_boots = engine_boots;
2814 table[0].engine_id_len = min(usm->get_local_engine_id().len(),
2815 MAXLENGTH_ENGINEID);
2816 memcpy(table[0].engine_id, usm->get_local_engine_id().data(),
2817 table[0].engine_id_len);
2822 result = SNMPv3_USM_OK;
2825 USMTimeTable::~USMTimeTable()
2836 int USMTimeTable::add_entry(const OctetStr &engine_id,
2837 const long int engine_boots,
2838 const long int engine_time)
2841 return SNMPv3_USM_ERROR;
2843 LOG_BEGIN(INFO_LOG | 11);
2844 LOG("USMTimeTable: Adding entry (engine id) (boot) (time)");
2845 LOG(engine_id.get_printable());
2850 BEGIN_REENTRANT_CODE_BLOCK;
2852 if (entries == max_entries)
2855 struct Entry_T *tmp = new struct Entry_T[4 * max_entries];
2858 return SNMPv3_USM_ERROR;
2860 memcpy(tmp, table, entries * sizeof(Entry_T));
2862 struct Entry_T *victim = table;
2872 table[entries].engine_boots = engine_boots;
2873 table[entries].latest_received_time = engine_time;
2874 table[entries].time_diff = engine_time - SAFE_ULONG_CAST(now);
2875 table[entries].engine_id_len = engine_id.len();
2876 table[entries].engine_id_len = min(table[entries].engine_id_len,
2877 MAXLENGTH_ENGINEID);
2878 memcpy(table[entries].engine_id,
2879 engine_id.data(), table[entries].engine_id_len);
2883 return SNMPv3_USM_OK;
2886 // Delete this engine id from the table.
2887 int USMTimeTable::delete_entry(const OctetStr &engine_id)
2890 return SNMPv3_USM_ERROR;
2892 LOG_BEGIN(INFO_LOG | 12);
2893 LOG("USMTimeTable: Deleting entry (engine id)");
2894 LOG(engine_id.get_printable());
2897 BEGIN_REENTRANT_CODE_BLOCK;
2899 for (int i=1; i < entries; i++) /* start from 1 */
2900 if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
2901 engine_id.data(), engine_id.len()))
2903 if (i != entries - 1)
2904 table[i] = table[entries - 1];
2908 return SNMPv3_USM_OK;
2911 return SNMPv3_USM_OK;
2914 unsigned long USMTimeTable::get_local_time()
2919 BEGIN_REENTRANT_CODE_BLOCK;
2924 return table[0].time_diff + SAFE_ULONG_CAST(now);
2927 int USMTimeTable::get_local_time(long int &engine_boots,
2928 long int &engine_time)
2931 return SNMPv3_USM_ERROR;
2933 BEGIN_REENTRANT_CODE_BLOCK;
2938 engine_boots = table[0].engine_boots;
2939 engine_time = table[0].time_diff + SAFE_ULONG_CAST(now);
2941 LOG_BEGIN(DEBUG_LOG | 11);
2942 LOG("USMTimeTable: returning local time (boots) (time)");
2947 return SNMPv3_USM_OK;
2950 int USMTimeTable::get_time(const OctetStr &engine_id,
2951 long int &engine_boots, long int &engine_time)
2954 return SNMPv3_USM_ERROR;
2956 BEGIN_REENTRANT_CODE_BLOCK;
2958 for (int i=0; i < entries; i++)
2959 if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
2960 engine_id.data(), engine_id.len()))
2966 engine_boots = table[i].engine_boots;
2967 engine_time = table[i].time_diff + SAFE_ULONG_CAST(now);
2969 LOG_BEGIN(INFO_LOG | 4);
2970 LOG("USMTimeTable: Returning time (engine id) (boot) (time)");
2971 LOG(engine_id.get_printable());
2976 return SNMPv3_USM_OK;
2983 LOG_BEGIN(INFO_LOG | 4);
2984 LOG("USMTimeTable: No entry found for (engine id)");
2985 LOG(engine_id.get_printable());
2988 return SNMPv3_USM_UNKNOWN_ENGINEID;
2991 int USMTimeTable::check_time(const OctetStr &engine_id,
2992 const long int engine_boots,
2993 const long int engine_time)
2997 return SNMPv3_USM_ERROR;
2999 BEGIN_REENTRANT_CODE_BLOCK;
3004 /* table[0] contains the local engine_id and time */
3005 if (unsignedCharCompare(table[0].engine_id, table[0].engine_id_len,
3006 engine_id.data(), engine_id.len()))
3008 /* Entry found, we are authoritative */
3009 if ((table[0].engine_boots == 2147483647) ||
3010 (table[0].engine_boots != engine_boots) ||
3011 (labs(SAFE_ULONG_CAST(now) + table[0].time_diff - engine_time) > 150))
3013 LOG_BEGIN(DEBUG_LOG | 9);
3014 LOG("USMTimeTable: Check time failed, authoritative (id) (boot) (time)");
3015 LOG(engine_id.get_printable());
3020 return SNMPv3_USM_NOT_IN_TIME_WINDOW;
3024 LOG_BEGIN(DEBUG_LOG | 9);
3025 LOG("USMTimeTable: Check time ok, authoritative (id)");
3026 LOG(engine_id.get_printable());
3029 return SNMPv3_USM_OK;
3033 for (int i=1; i < entries; i++)
3034 if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
3035 engine_id.data(), engine_id.len()))
3037 /* Entry found we are not authoritative */
3038 if ((engine_boots < table[i].engine_boots) ||
3039 ((engine_boots == table[i].engine_boots) &&
3040 (table[i].time_diff + now > engine_time + 150)) ||
3041 (table[i].engine_boots == 2147483647))
3043 LOG_BEGIN(DEBUG_LOG | 9);
3044 LOG("USMTimeTable: Check time failed, not authoritative (id)");
3045 LOG(engine_id.get_printable());
3048 return SNMPv3_USM_NOT_IN_TIME_WINDOW;
3052 if ((engine_boots > table[i].engine_boots) ||
3053 ((engine_boots == table[i].engine_boots) &&
3054 (engine_time > table[i].latest_received_time)))
3056 /* time ok, update values */
3057 table[i].engine_boots = engine_boots;
3058 table[i].latest_received_time = engine_time;
3059 table[i].time_diff = engine_time - SAFE_ULONG_CAST(now);
3062 LOG_BEGIN(DEBUG_LOG | 9);
3063 LOG("USMTimeTable: Check time ok, not authoritative, updated (id)");
3064 LOG(engine_id.get_printable());
3067 return SNMPv3_USM_OK;
3071 LOG_BEGIN(DEBUG_LOG | 9);
3072 LOG("USMTimeTable: Check time, engine id not found");
3073 LOG(engine_id.get_printable());
3076 return SNMPv3_USM_UNKNOWN_ENGINEID;
3080 int USMTimeTable::check_engine_id(const OctetStr &engine_id)
3083 return SNMPv3_USM_ERROR;
3086 // Begin reentrant code block
3087 BEGIN_REENTRANT_CODE_BLOCK;
3089 for (int i=0; i < entries; i++)
3090 if (unsignedCharCompare(table[i].engine_id, table[i].engine_id_len,
3091 engine_id.data(), engine_id.len()))
3092 return SNMPv3_USM_OK;
3095 /* if in discovery mode: accept all EngineID's (rfc2264 page 26) */
3096 if (usm->is_discovery_enabled())
3097 return add_entry(engine_id, 0, 0);
3099 LOG_BEGIN(DEBUG_LOG | 9);
3100 LOG("USMTimeTable: Check id, not found (id)");
3101 LOG(engine_id.get_printable());
3104 return SNMPv3_USM_ERROR;
3109 /* ------------------------- USMUserNameTable ----------------------*/
3111 USMUserNameTable::USMUserNameTable(int &result)
3114 table = new struct UsmUserNameTableEntry[10];
3117 result = SNMPv3_USM_ERROR;
3122 result = SNMPv3_USM_OK;
3125 USMUserNameTable::~USMUserNameTable()
3129 for (int i=0; i < entries; i++)
3131 if (table[i].authPassword)
3133 memset(table[i].authPassword, 0, table[i].authPasswordLength);
3134 delete [] table[i].authPassword;
3137 if (table[i].privPassword)
3139 memset(table[i].privPassword, 0, table[i].privPasswordLength);
3140 delete [] table[i].privPassword;
3150 int USMUserNameTable::add_entry(const OctetStr& user_name,
3151 const OctetStr& security_name,
3152 const long int auth_proto,
3153 const long int priv_proto,
3154 const OctetStr& auth_pass,
3155 const OctetStr& priv_pass)
3158 return SNMPv3_USM_ERROR;
3160 BEGIN_REENTRANT_CODE_BLOCK;
3164 for (i = 0; i < entries; i++)
3165 if (table[i].usmUserName == user_name)
3174 table[i].usmUserSecurityName = security_name;
3175 table[i].usmUserAuthProtocol = auth_proto;
3176 table[i].usmUserPrivProtocol = priv_proto;
3178 if (table[i].authPassword)
3180 memset(table[i].authPassword, 0, table[i].authPasswordLength);
3181 delete [] table[i].authPassword;
3183 table[i].authPassword = v3strcpy(auth_pass.data(), auth_pass.len());
3184 table[i].authPasswordLength = auth_pass.len();
3186 if (table[i].privPassword)
3188 memset(table[i].privPassword, 0, table[i].privPasswordLength);
3189 delete [] table[i].privPassword;
3191 table[i].privPassword = v3strcpy(priv_pass.data(), priv_pass.len());
3192 table[i].privPasswordLength = priv_pass.len();
3196 if (entries == max_entries)
3199 struct UsmUserNameTableEntry *tmp;
3200 tmp = new struct UsmUserNameTableEntry[4 * max_entries];
3202 return SNMPv3_USM_ERROR;
3203 for (i=0; i < entries; i++)
3206 struct UsmUserNameTableEntry *victim = table;
3213 table[entries].usmUserName = user_name;
3214 table[entries].usmUserSecurityName = security_name;
3215 table[entries].usmUserAuthProtocol = auth_proto;
3216 table[entries].usmUserPrivProtocol = priv_proto;
3218 table[entries].authPasswordLength = auth_pass.len();
3219 table[entries].authPassword = v3strcpy(auth_pass.data(), auth_pass.len());
3220 if (!table[entries].authPassword)
3221 return SNMPv3_USM_ERROR;
3223 table[entries].privPasswordLength = priv_pass.len();
3224 table[entries].privPassword = v3strcpy(priv_pass.data(), priv_pass.len());
3225 if (!table[entries].privPassword)
3226 return SNMPv3_USM_ERROR;
3231 return SNMPv3_USM_OK;
3234 int USMUserNameTable::delete_security_name(const OctetStr& security_name)
3237 return SNMPv3_USM_ERROR;
3239 BEGIN_REENTRANT_CODE_BLOCK;
3241 for (int i = 0; i < entries; i++)
3242 if (table[i].usmUserSecurityName == security_name)
3244 memset(table[i].authPassword, 0, table[i].authPasswordLength);
3245 delete [] table[i].authPassword;
3246 memset(table[i].privPassword, 0, table[i].privPasswordLength);
3247 delete [] table[i].privPassword;
3250 table[i] = table[entries];
3253 return SNMPv3_USM_OK;
3256 const struct UsmUserNameTableEntry* USMUserNameTable::get_entry(
3257 const OctetStr &security_name)
3262 for (int i = 0; i < entries; i++)
3263 if (table[i].usmUserSecurityName == security_name)
3268 struct UsmUserNameTableEntry* USMUserNameTable::get_cloned_entry(const OctetStr &security_name)
3271 const struct UsmUserNameTableEntry *e = get_entry(security_name);
3272 struct UsmUserNameTableEntry *res = 0;
3276 res = new struct UsmUserNameTableEntry;
3281 res->usmUserName = e->usmUserName;
3282 res->usmUserSecurityName = e->usmUserSecurityName;
3283 res->usmUserAuthProtocol = e->usmUserAuthProtocol;
3284 res->usmUserPrivProtocol = e->usmUserPrivProtocol;
3285 res->authPassword = v3strcpy(e->authPassword, e->authPasswordLength);
3286 res->authPasswordLength = e->authPasswordLength;
3287 res->privPassword = v3strcpy(e->privPassword, e->privPasswordLength);
3288 res->privPasswordLength = e->privPasswordLength;
3290 if ((res->authPasswordLength && !res->authPassword) ||
3291 (res->privPasswordLength && !res->privPassword))
3293 delete_cloned_entry(res);
3301 void USMUserNameTable::delete_cloned_entry(struct UsmUserNameTableEntry* &entry)
3305 if (entry->authPassword)
3307 memset(entry->authPassword, 0, entry->authPasswordLength);
3308 delete [] entry->authPassword;
3311 if (entry->privPassword)
3313 memset(entry->privPassword, 0, entry->privPasswordLength);
3314 delete [] entry->privPassword;
3323 int USMUserNameTable::get_security_name(const unsigned char *user_name,
3324 const long int user_name_len,
3325 OctetStr &security_name)
3328 return SNMPv3_USM_ERROR;
3330 BEGIN_REENTRANT_CODE_BLOCK;
3332 for (int i = 0; i < entries; i++)
3333 if (unsignedCharCompare(table[i].usmUserName.data(),
3334 table[i].usmUserName.len(),
3335 user_name, user_name_len))
3337 security_name = table[i].usmUserSecurityName;
3339 LOG_BEGIN(INFO_LOG | 9);
3340 LOG("USMUserNameTable: Translated (user name) to (security name)");
3341 LOG(table[i].usmUserName.get_printable());
3342 LOG(security_name.get_printable());
3345 return SNMPv3_USM_OK;
3348 int logclass = WARNING_LOG;
3349 if (user_name_len == 0) logclass = INFO_LOG;
3350 LOG_BEGIN(logclass | 5);
3351 LOG("USMUserNameTable: No entry for (user name) in table");
3352 LOG(OctetStr(user_name, user_name_len).get_printable());
3355 return SNMPv3_USM_ERROR;
3358 int USMUserNameTable::get_user_name(unsigned char *user_name,
3359 long int *user_name_len,
3360 const unsigned char *security_name,
3361 const long int security_name_len)
3363 unsigned long buf_len = *user_name_len;
3367 return SNMPv3_USM_ERROR;
3369 BEGIN_REENTRANT_CODE_BLOCK;
3371 for (int i = 0; i < entries; i++)
3372 if (unsignedCharCompare(table[i].usmUserSecurityName.data(),
3373 table[i].usmUserSecurityName.len(),
3374 security_name, security_name_len))
3376 if (buf_len < table[i].usmUserName.len())
3378 LOG_BEGIN(ERROR_LOG | 1);
3379 LOG("USMUserNameTable: Buffer for user name too small (is) (should)");
3381 LOG(table[i].usmUserName.len());
3384 return SNMPv3_USM_ERROR;
3386 *user_name_len = table[i].usmUserName.len();
3387 memcpy(user_name, table[i].usmUserName.data(),
3388 table[i].usmUserName.len());
3390 LOG_BEGIN(INFO_LOG | 9);
3391 LOG("USMUserNameTable: Translated (security name) to (user name)");
3392 LOG(table[i].usmUserSecurityName.get_printable());
3393 LOG(table[i].usmUserName.get_printable());
3396 return SNMPv3_USM_OK;
3399 int logclass = WARNING_LOG;
3400 if (security_name_len == 0) logclass = INFO_LOG;
3401 LOG_BEGIN(logclass | 5);
3402 LOG("USMUserNameTable: No entry for (security name) in table");
3403 LOG(OctetStr(security_name, security_name_len).get_printable());
3406 return SNMPv3_USM_ERROR;
3409 // Save all entries into a file.
3410 int USMUserNameTable::save_to_file(const char *name, AuthPriv *ap)
3412 char encoded[MAX_LINE_LEN * 2];
3414 char tmp_file_name[MAXLENGTH_FILENAME];
3415 bool failed = false;
3419 LOG_BEGIN(ERROR_LOG | 1);
3420 LOG("USMUserNameTable: save_to_file called with illegal param");
3427 LOG("AuthPriv pointer");
3431 return SNMPv3_USM_ERROR;
3434 LOG_BEGIN(INFO_LOG | 4);
3435 LOG("USMUserNameTable: Saving users to file");
3439 sprintf(tmp_file_name, "%s.tmp", name);
3440 file_out = fopen(tmp_file_name, "w");
3443 LOG_BEGIN(ERROR_LOG | 1);
3444 LOG("USMUserNameTable: could not create tmpfile");
3448 return SNMPv3_USM_FILECREATE_ERROR;
3452 // Begin reentrant code block
3453 BEGIN_REENTRANT_CODE_BLOCK;
3455 for (int i=0; i < entries; ++i)
3457 LOG_BEGIN(INFO_LOG | 8);
3458 LOG("USMUserNameTable: Saving user to file");
3459 LOG(table[i].usmUserName.get_printable());
3462 encodeString(table[i].usmUserName.data(), table[i].usmUserName.len(),
3464 encoded[2 * table[i].usmUserName.len()] = '\n';
3465 if (fwrite(encoded, 2 * table[i].usmUserName.len() + 1, 1,
3467 { failed = true; break; }
3469 encodeString(table[i].usmUserSecurityName.data(),
3470 table[i].usmUserSecurityName.len(), encoded);
3471 encoded[2 * table[i].usmUserSecurityName.len()] = '\n';
3472 if (fwrite(encoded, 2 * table[i].usmUserSecurityName.len() + 1, 1,
3474 { failed = true; break; }
3476 encodeString(table[i].authPassword, table[i].authPasswordLength,
3478 encoded[2 * table[i].authPasswordLength] = '\n';
3479 if (fwrite(encoded, 2 * table[i].authPasswordLength + 1, 1,
3481 { failed = true; break; }
3483 encodeString(table[i].privPassword, table[i].privPasswordLength,
3485 encoded[2 * table[i].privPasswordLength] = '\n';
3486 if (fwrite(encoded, 2 * table[i].privPasswordLength + 1, 1,
3488 { failed = true; break; }
3490 if (table[i].usmUserAuthProtocol == SNMP_AUTHPROTOCOL_NONE)
3492 if (fwrite("none\n", 5, 1, file_out) != 1)
3493 { failed = true; break; }
3497 const Auth *a = ap->get_auth(table[i].usmUserAuthProtocol);
3498 if (!a) { failed = true; break; }
3499 sprintf(encoded, "%s\n", a->get_id_string());
3500 if (fwrite(encoded, strlen(a->get_id_string()) + 1, 1, file_out) != 1)
3501 { failed = true; break; }
3504 if (table[i].usmUserPrivProtocol == SNMP_PRIVPROTOCOL_NONE)
3506 if (fwrite("none\n", 5, 1, file_out) != 1)
3507 { failed = true; break; }
3511 const Priv *p = ap->get_priv(table[i].usmUserPrivProtocol);
3512 if (!p) { failed = true; break; }
3513 sprintf(encoded, "%s\n", p->get_id_string());
3514 if (fwrite(encoded, strlen(p->get_id_string()) + 1, 1, file_out) != 1)
3515 { failed = true; break; }
3523 LOG_BEGIN(ERROR_LOG | 1);
3524 LOG("USMUserNameTable: Failed to write table entries.");
3528 _unlink(tmp_file_name);
3530 unlink(tmp_file_name);
3532 return SNMPv3_USM_FILEWRITE_ERROR;
3539 if (rename(tmp_file_name, name))
3541 LOG_BEGIN(ERROR_LOG | 1);
3542 LOG("USMUserNameTable: Could not rename file (from) (to)");
3547 return SNMPv3_USM_FILERENAME_ERROR;
3550 LOG_BEGIN(INFO_LOG | 4);
3551 LOG("USMUserNameTable: Saving users to file finished");
3554 return SNMPv3_USM_OK;
3557 // Load the table from a file.
3558 int USMUserNameTable::load_from_file(const char *name, AuthPriv *ap)
3560 char decoded[MAX_LINE_LEN];
3562 unsigned char line[MAX_LINE_LEN * 2];
3566 LOG_BEGIN(ERROR_LOG | 1);
3567 LOG("USMUserNameTable: load_to_file called with illegal param");
3574 LOG("AuthPriv pointer");
3578 return SNMPv3_USM_ERROR;
3581 LOG_BEGIN(INFO_LOG | 4);
3582 LOG("USMUserNameTable: Loading users from file");
3586 file_in = fopen(name, "r");
3589 LOG_BEGIN(ERROR_LOG | 1);
3590 LOG("USMUserNameTable: could not open file");
3594 return SNMPv3_USM_FILEOPEN_ERROR;
3598 bool failed = false;
3599 while (fgets((char*)line, MAX_LINE_LEN * 2, file_in))
3602 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
3603 decodeString(line, len, decoded);
3604 OctetStr user_name((unsigned char*)decoded, len / 2);
3607 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
3608 { failed = true; break; }
3609 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
3610 decodeString(line, len, decoded);
3611 OctetStr user_security_name((unsigned char*)decoded, len / 2);
3614 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
3615 { failed = true; break; }
3616 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
3617 decodeString(line, len, decoded);
3618 OctetStr auth_pass((unsigned char*)decoded, len / 2);
3621 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
3622 { failed = true; break; }
3623 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
3624 decodeString(line, len, decoded);
3625 OctetStr priv_pass((unsigned char*)decoded, len / 2);
3628 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
3629 { failed = true; break; }
3630 line[strlen((char*)line) - 1] = 0;
3631 int auth_prot = SNMP_AUTHPROTOCOL_NONE;
3632 if (strcmp((char*)line, "none") != 0)
3634 auth_prot = ap->get_auth_id((char*)line);
3636 { failed = true; break; }
3639 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
3640 { failed = true; break; }
3641 line[strlen((char*)line) - 1] = 0;
3642 int priv_prot = SNMP_PRIVPROTOCOL_NONE;
3643 if (strcmp((char*)line, "none") != 0)
3645 priv_prot = ap->get_priv_id((char*)line);
3647 { failed = true; break; }
3650 LOG_BEGIN(INFO_LOG | 7);
3651 LOG("USMUserNameTable: Adding user (user name) (sec name) (auth) (priv)");
3652 LOG(user_name.get_printable());
3653 LOG(user_security_name.get_printable());
3658 if (add_entry(user_name, user_security_name, auth_prot, priv_prot,
3659 auth_pass, priv_pass) == SNMPv3_USM_ERROR)
3663 LOG_BEGIN(ERROR_LOG | 1);
3664 LOG("USMUserNameTable: Error adding (user name)");
3665 LOG(user_name.get_printable());
3673 LOG_BEGIN(ERROR_LOG | 1);
3674 LOG("USMUserNameTable: Failed to read table entries");
3677 return SNMPv3_USM_FILEREAD_ERROR;
3680 LOG_BEGIN(INFO_LOG | 4);
3681 LOG("USMUserNameTable: Loaded all users from file");
3684 return SNMPv3_USM_OK;
3687 const UsmUserNameTableEntry *USMUserNameTable::peek_next(
3688 const UsmUserNameTableEntry *e) const
3690 if (e == 0) return 0;
3691 if (e - table < 0) return 0;
3692 if (e - table >= entries - 1) return 0;
3696 /* ---------------------------- USMUserTable ------------------- */
3698 USMUserTable::USMUserTable(int &result)
3702 table = new struct UsmUserTableEntry[10];
3705 result = SNMPv3_USM_ERROR;
3711 USMUserTable::~USMUserTable()
3715 for (int i = 0; i < entries; i++)
3717 if (table[i].usmUserEngineID)
3718 delete [] table[i].usmUserEngineID;
3719 if (table[i].usmUserName)
3720 delete [] table[i].usmUserName;
3721 if (table[i].usmUserSecurityName)
3722 delete [] table[i].usmUserSecurityName;
3723 if (table[i].usmUserAuthKey)
3725 memset(table[i].usmUserAuthKey, 0, table[i].usmUserAuthKeyLength);
3726 delete [] table[i].usmUserAuthKey;
3728 if (table[i].usmUserPrivKey)
3730 memset(table[i].usmUserPrivKey, 0, table[i].usmUserPrivKeyLength);
3731 delete [] table[i].usmUserPrivKey;
3741 int USMUserTable::get_user_name(unsigned char *user_name,
3742 long int *user_name_len,
3743 const unsigned char *sec_name,
3744 const long sec_name_len)
3747 long buf_len = *user_name_len;
3751 return SNMPv3_USM_ERROR;
3753 BEGIN_REENTRANT_CODE_BLOCK;
3755 for (int i=0; i < entries; i++)
3756 if (unsignedCharCompare(table[i].usmUserSecurityName,
3757 table[i].usmUserSecurityNameLength,
3758 sec_name, sec_name_len))
3760 if (buf_len < table[i].usmUserNameLength)
3762 LOG_BEGIN(ERROR_LOG | 1);
3763 LOG("USMUserTable: Buffer for user name too small (is) (should)");
3765 LOG(table[i].usmUserNameLength);
3768 return SNMPv3_USM_ERROR;
3770 *user_name_len = table[i].usmUserNameLength;
3771 memcpy(user_name, table[i].usmUserName, table[i].usmUserNameLength);
3773 LOG_BEGIN(INFO_LOG | 9);
3774 LOG("USMUserTable: Translated (security name) to (user name)");
3775 LOG(OctetStr(sec_name, sec_name_len).get_printable());
3776 LOG(OctetStr(table[i].usmUserName, table[i].usmUserNameLength).get_printable());
3779 return SNMPv3_USM_OK;
3782 int logclass = WARNING_LOG;
3783 if (sec_name_len == 0) logclass = INFO_LOG;
3784 LOG_BEGIN(logclass | 5);
3785 LOG("USMUserTable: No entry for (security name) in table");
3786 LOG(OctetStr(sec_name, sec_name_len).get_printable());
3789 return SNMPv3_USM_ERROR;
3792 int USMUserTable::get_security_name(const unsigned char *user_name,
3793 const long user_name_len,
3797 return SNMPv3_USM_ERROR;
3799 BEGIN_REENTRANT_CODE_BLOCK;
3801 for (int i=0; i < entries; i++)
3802 if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
3803 user_name, user_name_len))
3805 sec_name.set_data(table[i].usmUserSecurityName,
3806 table[i].usmUserSecurityNameLength);
3807 LOG_BEGIN(INFO_LOG | 9);
3808 LOG("USMUserTable: Translated (user name) to (security name)");
3809 LOG(OctetStr(table[i].usmUserName, table[i].usmUserNameLength).get_printable());
3810 LOG(sec_name.get_printable());
3813 return SNMPv3_USM_OK;
3816 int logclass = WARNING_LOG;
3817 if (user_name_len == 0) logclass = INFO_LOG;
3818 LOG_BEGIN(logclass | 5);
3819 LOG("USMUserTable: No entry for (user name) in table");
3820 LOG(OctetStr(user_name, user_name_len).get_printable());
3823 return SNMPv3_USM_ERROR;
3826 int USMUserTable::delete_entries(const OctetStr& user_name)
3829 return SNMPv3_USM_ERROR;
3831 BEGIN_REENTRANT_CODE_BLOCK;
3833 for (int i = 0; i < entries; i++)
3834 if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
3835 user_name.data(), user_name.len()))
3837 /* delete this entry and recheck this position */
3841 return SNMPv3_USM_OK;
3844 // Delete all entries of this user from the usmUserTable
3845 int USMUserTable::delete_engine_id(const OctetStr& engine_id)
3848 return SNMPv3_USM_ERROR;
3850 BEGIN_REENTRANT_CODE_BLOCK;
3852 for (int i = 0; i < entries; i++)
3853 if (unsignedCharCompare(table[i].usmUserEngineID,
3854 table[i].usmUserEngineIDLength,
3855 engine_id.data(), engine_id.len()))
3857 /* delete this entry and recheck this position*/
3861 return SNMPv3_USM_OK;
3864 int USMUserTable::delete_entry(const OctetStr& engine_id,
3865 const OctetStr& user_name)
3868 return SNMPv3_USM_ERROR;
3870 BEGIN_REENTRANT_CODE_BLOCK;
3872 for (int i = 0; i < entries; i++)
3873 if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
3874 user_name.data(), user_name.len()))
3875 if (unsignedCharCompare(table[i].usmUserEngineID,
3876 table[i].usmUserEngineIDLength,
3877 engine_id.data(), engine_id.len()))
3879 /* delete this entry and recheck this position*/
3883 return SNMPv3_USM_OK;
3886 const struct UsmUserTableEntry *USMUserTable::get_entry(const int number)
3888 if ((entries < number) || (number < 1))
3891 return &table[number - 1];
3894 const struct UsmUserTableEntry *USMUserTable::get_entry(const OctetStr &engine_id,
3895 const OctetStr &sec_name)
3900 for (int i = 0; i < entries; i++)
3901 if (unsignedCharCompare(table[i].usmUserSecurityName,
3902 table[i].usmUserSecurityNameLength,
3903 sec_name.data(), sec_name.len()))
3904 if (unsignedCharCompare(table[i].usmUserEngineID,
3905 table[i].usmUserEngineIDLength,
3906 engine_id.data(), engine_id.len()))
3911 struct UsmUserTableEntry *USMUserTable::get_cloned_entry(
3912 const OctetStr &engine_id,
3913 const OctetStr &sec_name)
3916 const struct UsmUserTableEntry *e = get_entry(engine_id, sec_name);
3917 struct UsmUserTableEntry *res = 0;
3921 res = new struct UsmUserTableEntry;
3926 res->usmUserEngineID = v3strcpy(e->usmUserEngineID,
3927 e->usmUserEngineIDLength);
3928 res->usmUserEngineIDLength = e->usmUserEngineIDLength;
3929 res->usmUserName = v3strcpy(e->usmUserName,
3930 e->usmUserNameLength);
3931 res->usmUserNameLength = e->usmUserNameLength;
3932 res->usmUserSecurityName = v3strcpy(e->usmUserSecurityName,
3933 e->usmUserSecurityNameLength);
3934 res->usmUserSecurityNameLength = e->usmUserSecurityNameLength;
3935 res->usmUserAuthProtocol = e->usmUserAuthProtocol;
3936 res->usmUserAuthKey = v3strcpy(e->usmUserAuthKey,
3937 e->usmUserAuthKeyLength);
3938 res->usmUserAuthKeyLength = e->usmUserAuthKeyLength;
3939 res->usmUserPrivProtocol = e->usmUserPrivProtocol;
3940 res->usmUserPrivKey = v3strcpy(e->usmUserPrivKey,
3941 e->usmUserPrivKeyLength);
3942 res->usmUserPrivKeyLength = e->usmUserPrivKeyLength;
3944 if ((res->usmUserEngineIDLength && !res->usmUserEngineID) ||
3945 (res->usmUserNameLength && !res->usmUserName) ||
3946 (res->usmUserSecurityNameLength && !res->usmUserSecurityName) ||
3947 (res->usmUserAuthKeyLength && !res->usmUserAuthKey) ||
3948 (res->usmUserPrivKeyLength && !res->usmUserPrivKey))
3950 delete_cloned_entry(res);
3958 void USMUserTable::delete_cloned_entry(struct UsmUserTableEntry* &entry)
3962 if (entry->usmUserEngineID) delete [] entry->usmUserEngineID;
3963 if (entry->usmUserName) delete [] entry->usmUserName;
3964 if (entry->usmUserSecurityName) delete [] entry->usmUserSecurityName;
3966 if (entry->usmUserAuthKey)
3968 memset(entry->usmUserAuthKey, 0, entry->usmUserAuthKeyLength);
3969 delete [] entry->usmUserAuthKey;
3972 if (entry->usmUserPrivKey)
3974 memset(entry->usmUserPrivKey, 0, entry->usmUserPrivKeyLength);
3975 delete [] entry->usmUserPrivKey;
3984 const struct UsmUserTableEntry *USMUserTable::get_entry(const OctetStr &sec_name)
3989 for (int i = 0; i < entries; i++)
3990 if (unsignedCharCompare(table[i].usmUserSecurityName,
3991 table[i].usmUserSecurityNameLength,
3992 sec_name.data(), sec_name.len()))
3997 int USMUserTable::add_entry(
3998 const OctetStr &engine_id,
3999 const OctetStr &user_name, const OctetStr &sec_name,
4000 const long int auth_proto, const OctetStr &auth_key,
4001 const long int priv_proto, const OctetStr &priv_key)
4003 LOG_BEGIN(INFO_LOG | 7);
4004 LOG("USMUserTable: Adding user (user name) (engine id) (auth) (priv)");
4005 LOG(user_name.get_printable());
4006 LOG(engine_id.get_printable());
4012 return SNMPv3_USM_ERROR;
4014 BEGIN_REENTRANT_CODE_BLOCK;
4016 if (entries == max_entries)
4019 struct UsmUserTableEntry *tmp;
4020 tmp = new struct UsmUserTableEntry[4 * max_entries];
4021 if (!tmp) return SNMPv3_USM_ERROR;
4022 for (int i = 0; i < entries; i++)
4029 for (int i = 0; i < entries; i++)
4030 if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
4031 user_name.data(), user_name.len()))
4032 if (unsignedCharCompare(table[i].usmUserEngineID,
4033 table[i].usmUserEngineIDLength,
4034 engine_id.data(), engine_id.len()))
4036 /* delete this entry */
4041 /* add user at the last position */
4042 table[entries].usmUserEngineIDLength = engine_id.len();
4043 table[entries].usmUserEngineID = v3strcpy(engine_id.data(),
4045 table[entries].usmUserNameLength = user_name.len();
4046 table[entries].usmUserName = v3strcpy(user_name.data(),
4048 table[entries].usmUserSecurityNameLength = sec_name.len();
4049 table[entries].usmUserSecurityName = v3strcpy(sec_name.data(),
4051 table[entries].usmUserAuthProtocol = auth_proto;
4052 table[entries].usmUserAuthKeyLength = auth_key.len();
4053 table[entries].usmUserAuthKey = v3strcpy(auth_key.data(),
4055 table[entries].usmUserPrivProtocol = priv_proto;
4056 table[entries].usmUserPrivKeyLength = priv_key.len();
4057 table[entries].usmUserPrivKey = v3strcpy(priv_key.data(),
4060 return SNMPv3_USM_OK;
4063 int USMUserTable::update_key(const OctetStr &user_name,
4064 const OctetStr &engine_id,
4065 const OctetStr &new_key,
4068 LOG_BEGIN(INFO_LOG | 7);
4069 LOG("USMUserTable: Update key for user (name) (engine id) (type)");
4070 LOG(user_name.get_printable());
4071 LOG(engine_id.get_printable());
4076 return SNMPv3_USM_ERROR;
4078 BEGIN_REENTRANT_CODE_BLOCK;
4080 for (int i = 0; i < entries; i++)
4081 if (unsignedCharCompare(table[i].usmUserName, table[i].usmUserNameLength,
4082 user_name.data(), user_name.len()))
4083 if (unsignedCharCompare(table[i].usmUserEngineID,
4084 table[i].usmUserEngineIDLength,
4085 engine_id.data(), engine_id.len()))
4087 LOG_BEGIN(DEBUG_LOG | 15);
4088 LOG("USMUserTable: New key");
4089 LOG(new_key.get_printable());
4098 if (table[i].usmUserAuthKey)
4100 memset(table[i].usmUserAuthKey, 0,
4101 table[i].usmUserAuthKeyLength);
4102 delete [] table[i].usmUserAuthKey;
4104 table[i].usmUserAuthKeyLength = new_key.len();
4105 table[i].usmUserAuthKey = v3strcpy(new_key.data(), new_key.len());
4106 return SNMPv3_USM_OK;
4111 if (table[i].usmUserPrivKey)
4113 memset(table[i].usmUserPrivKey, 0,
4114 table[i].usmUserPrivKeyLength);
4115 delete [] table[i].usmUserPrivKey;
4117 table[i].usmUserPrivKeyLength = new_key.len();
4118 table[i].usmUserPrivKey = v3strcpy(new_key.data(), new_key.len());
4119 return SNMPv3_USM_OK;
4123 LOG_BEGIN(WARNING_LOG | 3);
4124 LOG("USMUserTable: setting new key failed (wrong type).");
4127 return SNMPv3_USM_ERROR;
4132 LOG_BEGIN(INFO_LOG | 7);
4133 LOG("USMUserTable: setting new key failed (user) not found");
4134 LOG(user_name.get_printable());
4137 return SNMPv3_USM_ERROR;
4140 void USMUserTable::delete_entry(const int nr)
4142 /* Table is locked through caller, so do NOT lock table!
4143 * All checks have been made, so dont check again!
4146 if (table[nr].usmUserEngineID) delete [] table[nr].usmUserEngineID;
4147 if (table[nr].usmUserName) delete [] table[nr].usmUserName;
4148 if (table[nr].usmUserSecurityName) delete [] table[nr].usmUserSecurityName;
4149 if (table[nr].usmUserAuthKey)
4151 memset(table[nr].usmUserAuthKey, 0, table[nr].usmUserAuthKeyLength);
4152 delete [] table[nr].usmUserAuthKey;
4154 if (table[nr].usmUserPrivKey)
4156 memset(table[nr].usmUserPrivKey, 0, table[nr].usmUserPrivKeyLength);
4157 delete [] table[nr].usmUserPrivKey;
4160 /* We have now one entry less */
4165 /* move the last entry to the deleted position */
4166 table[nr] = table[entries];
4170 // Save all entries into a file.
4171 int USMUserTable::save_to_file(const char *name, AuthPriv *ap)
4173 char encoded[MAX_LINE_LEN * 2];
4175 char tmp_file_name[MAXLENGTH_FILENAME];
4176 bool failed = false;
4180 LOG_BEGIN(ERROR_LOG | 1);
4181 LOG("USMUserTable: save_to_file called with illegal param");
4188 LOG("AuthPriv pointer");
4192 return SNMPv3_USM_ERROR;
4195 LOG_BEGIN(INFO_LOG | 4);
4196 LOG("USMUserTable: Saving users to file");
4200 sprintf(tmp_file_name, "%s.tmp", name);
4201 file_out = fopen(tmp_file_name, "w");
4204 LOG_BEGIN(ERROR_LOG | 1);
4205 LOG("USMUserTable: could not create tmpfile");
4209 return SNMPv3_USM_FILECREATE_ERROR;
4213 // Begin reentrant code block
4214 BEGIN_REENTRANT_CODE_BLOCK;
4216 for (int i=0; i < entries; ++i)
4218 LOG_BEGIN(INFO_LOG | 8);
4219 LOG("USMUserTable: Saving user to file");
4220 LOG(OctetStr(table[i].usmUserName, table[i].usmUserNameLength)
4224 encodeString(table[i].usmUserEngineID, table[i].usmUserEngineIDLength,
4226 encoded[2 * table[i].usmUserEngineIDLength] = '\n';
4227 if (fwrite(encoded, 2 * table[i].usmUserEngineIDLength + 1, 1,
4229 { failed = true; break; }
4231 encodeString(table[i].usmUserName, table[i].usmUserNameLength, encoded);
4232 encoded[2 * table[i].usmUserNameLength] = '\n';
4233 if (fwrite(encoded, 2 * table[i].usmUserNameLength + 1, 1,
4235 { failed = true; break; }
4237 encodeString(table[i].usmUserSecurityName,
4238 table[i].usmUserSecurityNameLength, encoded);
4239 encoded[2 * table[i].usmUserSecurityNameLength] = '\n';
4240 if (fwrite(encoded, 2 * table[i].usmUserSecurityNameLength + 1, 1,
4242 { failed = true; break; }
4244 encodeString(table[i].usmUserAuthKey, table[i].usmUserAuthKeyLength,
4246 encoded[2 * table[i].usmUserAuthKeyLength] = '\n';
4247 if (fwrite(encoded, 2 * table[i].usmUserAuthKeyLength + 1, 1,
4249 { failed = true; break; }
4251 encodeString(table[i].usmUserPrivKey, table[i].usmUserPrivKeyLength,
4253 encoded[2 * table[i].usmUserPrivKeyLength] = '\n';
4254 if (fwrite(encoded, 2 * table[i].usmUserPrivKeyLength + 1, 1,
4256 { failed = true; break; }
4258 if (table[i].usmUserAuthProtocol == SNMP_AUTHPROTOCOL_NONE)
4260 if (fwrite("none\n", 5, 1, file_out) != 1)
4261 { failed = true; break; }
4265 const Auth *a = ap->get_auth(table[i].usmUserAuthProtocol);
4266 if (!a) { failed = true; break; }
4267 sprintf(encoded, "%s\n", a->get_id_string());
4268 if (fwrite(encoded, strlen(a->get_id_string()) + 1, 1, file_out) != 1)
4269 { failed = true; break; }
4272 if (table[i].usmUserPrivProtocol == SNMP_PRIVPROTOCOL_NONE)
4274 if (fwrite("none\n", 5, 1, file_out) != 1)
4275 { failed = true; break; }
4279 const Priv *p = ap->get_priv(table[i].usmUserPrivProtocol);
4280 if (!p) { failed = true; break; }
4281 sprintf(encoded, "%s\n", p->get_id_string());
4282 if (fwrite(encoded, strlen(p->get_id_string()) + 1, 1, file_out) != 1)
4283 { failed = true; break; }
4291 LOG_BEGIN(ERROR_LOG | 1);
4292 LOG("USMUserTable: Failed to write table entries.");
4296 _unlink(tmp_file_name);
4298 unlink(tmp_file_name);
4300 return SNMPv3_USM_FILEWRITE_ERROR;
4307 if (rename(tmp_file_name, name))
4309 LOG_BEGIN(ERROR_LOG | 1);
4310 LOG("USMUserTable: Could not rename file (from) (to)");
4315 return SNMPv3_USM_FILERENAME_ERROR;
4318 LOG_BEGIN(INFO_LOG | 4);
4319 LOG("USMUserTable: Saving users to file finished");
4322 return SNMPv3_USM_OK;
4325 // Load the table from a file.
4326 int USMUserTable::load_from_file(const char *name, AuthPriv *ap)
4328 char decoded[MAX_LINE_LEN];
4330 unsigned char line[MAX_LINE_LEN * 2];
4334 LOG_BEGIN(ERROR_LOG | 1);
4335 LOG("USMUserTable: load_from_file called with illegal param");
4342 LOG("AuthPriv pointer");
4346 return SNMPv3_USM_ERROR;
4349 LOG_BEGIN(INFO_LOG | 4);
4350 LOG("USMUserTable: Loading users from file");
4354 file_in = fopen(name, "r");
4357 LOG_BEGIN(ERROR_LOG | 1);
4358 LOG("USMUserTable: could not open file");
4362 return SNMPv3_USM_FILEOPEN_ERROR;
4365 bool failed = false;
4367 while (fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4370 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
4371 decodeString(line, len, decoded);
4372 OctetStr engine_id((unsigned char*)decoded, len / 2);
4375 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4376 { failed = true; break; }
4377 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
4378 decodeString(line, len, decoded);
4379 OctetStr user_name((unsigned char*)decoded, len / 2);
4382 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4383 { failed = true; break; }
4384 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
4385 decodeString(line, len, decoded);
4386 OctetStr user_security_name((unsigned char*)decoded, len / 2);
4389 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4390 { failed = true; break; }
4391 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
4392 decodeString(line, len, decoded);
4393 OctetStr auth_key((unsigned char*)decoded, len / 2);
4396 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4397 { failed = true; break; }
4398 len = SAFE_INT_CAST(strlen((char*)line)) - 1;
4399 decodeString(line, len, decoded);
4400 OctetStr priv_key((unsigned char*)decoded, len / 2);
4403 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4404 { failed = true; break; }
4405 line[strlen((char*)line) - 1] = 0;
4406 int auth_prot = SNMP_AUTHPROTOCOL_NONE;
4407 if (strcmp((char*)line, "none") != 0)
4409 auth_prot = ap->get_auth_id((char*)line);
4411 { failed = true; break; }
4414 if (!fgets((char*)line, MAX_LINE_LEN * 2, file_in))
4415 { failed = true; break; }
4416 line[strlen((char*)line) - 1] = 0;
4417 int priv_prot = SNMP_PRIVPROTOCOL_NONE;
4418 if (strcmp((char*)line, "none") != 0)
4420 priv_prot = ap->get_priv_id((char*)line);
4422 { failed = true; break; }
4425 LOG_BEGIN(INFO_LOG | 7);
4426 LOG("USMUserTable: Adding localized (user name) (eng id) (auth) (priv)");
4427 LOG(user_name.get_printable());
4428 LOG(engine_id.get_printable());
4433 if (add_entry(engine_id, user_name, user_security_name,
4434 auth_prot, auth_key, priv_prot, priv_key)
4435 == SNMPv3_USM_ERROR)
4439 LOG_BEGIN(ERROR_LOG | 1);
4440 LOG("USMUserTable: Error adding (user name)");
4441 LOG(user_name.get_printable());
4449 LOG_BEGIN(ERROR_LOG | 1);
4450 LOG("USMUserTable: Failed to read table entries");
4453 return SNMPv3_USM_FILEREAD_ERROR;
4456 LOG_BEGIN(INFO_LOG | 4);
4457 LOG("USMUserTable: Loaded all users from file");
4460 return SNMPv3_USM_OK;
4463 const UsmUserTableEntry *USMUserTable::peek_next(
4464 const UsmUserTableEntry *e) const
4466 if (e == 0) return 0;
4467 if (e - table < 0) return 0;
4468 if (e - table >= entries - 1) return 0;
4472 #ifdef SNMP_PP_NAMESPACE
4473 }; // end of namespace Snmp_pp