snmpv3.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:29k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /*
  2.  * snmpv3.c
  3.  */
  4. #include <config.h>
  5. #include <assert.h>
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #if TIME_WITH_SYS_TIME
  9. # ifdef WIN32
  10. #  include <sys/timeb.h>
  11. # else
  12. #  include <time.h>
  13. # endif
  14. # include <time.h>
  15. #else
  16. # if HAVE_SYS_TIME_H
  17. #  include <sys/time.h>
  18. # else
  19. #  include <time.h>
  20. # endif
  21. #endif
  22. #ifdef OS_VXWORKS
  23. #include <sys/times.h>
  24. #endif
  25. #if HAVE_STRING_H
  26. #include <string.h>
  27. #else
  28. #include <strings.h>
  29. #endif
  30. #if HAVE_NETINET_IN_H
  31. #include <netinet/in.h>
  32. #endif
  33. #if HAVE_UNISTD_H
  34. #include <unistd.h>
  35. #endif
  36. #if HAVE_WINSOCK_H
  37. #include <ip/socket.h>
  38. #endif
  39. #if HAVE_SYS_SOCKET_H
  40. #include <sys/socket.h>
  41. #endif
  42. #if HAVE_NETDB_H
  43. #include <netdb.h>
  44. #endif
  45. #if HAVE_STDLIB_H
  46. #       include <stdlib.h>
  47. #endif
  48. #if HAVE_DMALLOC_H
  49. #include <dmalloc.h>
  50. #endif
  51. #include "system.h"
  52. #include "asn1.h"
  53. #include "snmpv3.h"
  54. #include "callback.h"
  55. #include "snmpusm.h"
  56. #include "snmp.h"
  57. #include "parse.h"
  58. #include "snmp_api.h"
  59. #include "snmp_impl.h"
  60. #include "read_config.h"
  61. #include "lcd_time.h"
  62. #include "scapi.h"
  63. #include "tools.h"
  64. #include "keytools.h"
  65. #include "lcd_time.h"
  66. #include "snmp_debug.h"
  67. #include "snmp_logging.h"
  68. #include "default_store.h"
  69. #include <ip/netdb.h>
  70. #include "transform_oids.h"
  71. #include <snmp/agent_trap.h>
  72. #include <snmp/snmp_command.h>
  73. #include <boot/convert.h>
  74. #include <libvty/log.h>
  75. static u_long  engineBoots    = 1;
  76. static unsigned char *engineID    = NULL;
  77. static size_t  engineIDLength    = 0;
  78. static unsigned char *oldEngineID    = NULL;
  79. static size_t  oldEngineIDLength = 0;
  80. static struct timeval  snmpv3starttime;
  81. extern char *strdup (char*);
  82. extern int strcasecmp(const char*, const char*);
  83. /* 
  84.  * Set up default snmpv3 parameter value storage.
  85.  */
  86. static oid *defaultAuthType = NULL;
  87. static size_t  defaultAuthTypeLen = 0;
  88. static oid *defaultPrivType = NULL;
  89. static size_t  defaultPrivTypeLen = 0;
  90. void
  91. snmpv3_authtype_conf(const char *word, char *cptr)
  92. {
  93.   if (strcasecmp(cptr,"MD5") == 0)
  94.     defaultAuthType = usmHMACMD5AuthProtocol;
  95.   else if (strcasecmp(cptr,"SHA") == 0)
  96.     defaultAuthType = usmHMACMD5AuthProtocol;
  97.   else
  98.     config_perror("Unknown authentication type");
  99.   defaultAuthTypeLen = USM_LENGTH_OID_TRANSFORM;
  100.   DEBUGMSGTL(("snmpv3","set default authentication type: %sn", cptr));
  101. }
  102. oid *
  103. get_default_authtype(size_t *len)
  104. {
  105.   if (defaultAuthType == NULL) {
  106.     defaultAuthType = SNMP_DEFAULT_AUTH_PROTO;
  107.     defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN;
  108.   }
  109.   if (len)
  110.     *len = defaultAuthTypeLen;
  111.   return defaultAuthType;
  112. }
  113. void
  114. snmpv3_privtype_conf(const char *word, char *cptr)
  115. {
  116.   if (strcasecmp(cptr,"DES") == 0)
  117.     defaultPrivType = SNMP_DEFAULT_PRIV_PROTO;
  118.   else
  119.     config_perror("Unknown privacy type");
  120.   defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN;
  121.   DEBUGMSGTL(("snmpv3","set default privacy type: %sn", cptr));
  122. }
  123. oid *
  124. get_default_privtype(size_t *len)
  125. {
  126.   if (defaultAuthType == NULL) {
  127.     defaultAuthType = usmDESPrivProtocol;
  128.     defaultPrivTypeLen = USM_LENGTH_OID_TRANSFORM;
  129.   }
  130.   if (len)
  131.     *len = defaultPrivTypeLen;
  132.   return defaultPrivType;
  133. }
  134. /*******************************************************************-o-******
  135.  * snmpv3_secLevel_conf
  136.  *
  137.  * Parameters:
  138.  * *word
  139.  * *cptr
  140.  *
  141.  * Line syntax:
  142.  * defSecurityLevel "noAuthNoPriv" | "authNoPriv" | "authPriv"
  143.  */
  144. void
  145. snmpv3_secLevel_conf(const char *word, char *cptr)
  146. {
  147.   char buf[1024];
  148.   
  149.   if (strcasecmp(cptr,"noAuthNoPriv") == 0 || strcmp(cptr, "1") == 0
  150. || strcasecmp(cptr, "nanp") == 0)
  151.     ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_NOAUTH);
  152.   else if (strcasecmp(cptr,"authNoPriv") == 0 || strcmp(cptr, "2") == 0
  153. || strcasecmp(cptr, "anp") == 0)
  154.     ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHNOPRIV);
  155.   else if (strcasecmp(cptr,"authPriv") == 0 || strcmp(cptr, "3") == 0
  156. || strcasecmp(cptr, "ap") == 0)
  157.     ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHPRIV);
  158.   else {
  159.     sprintf(buf,"Unknown security level: %s", cptr);
  160.     config_perror(buf);
  161.   }
  162.   DEBUGMSGTL(("snmpv3","default secLevel set to: %s = %dn", cptr,
  163.               ds_get_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL)));
  164. }
  165. /*******************************************************************-o-******
  166.  * setup_engineID
  167.  *
  168.  * Parameters:
  169.  * **eidp
  170.  *  *text Printable (?) text to be plugged into the snmpEngineID.
  171.  *
  172.  * Return:
  173.  * Length of allocated engineID string in bytes,  -OR-
  174.  * -1 on error.
  175.  *
  176.  *
  177.  * Create an snmpEngineID using text and the local IP address.  If eidp
  178.  * is defined, use it to return a pointer to the newly allocated data.
  179.  * Otherwise, use the result to define engineID defined in this module.
  180.  *
  181.  * Line syntax:
  182.  * engineID <text> | NULL
  183.  *
  184.  * XXX What if a node has multiple interfaces?
  185.  * XXX What if multiple engines all choose the same address?
  186.  *      (answer:  You're screwed, because you might need a kul database
  187.  *       which is dependant on the current engineID.  Enumeration and other
  188.  *       tricks won't work). 
  189.  */
  190. int
  191. setup_engineID(u_char **eidp, const char *text)
  192. {
  193.   int   enterpriseid = htonl(default_enterprise[6]),
  194.   localsetup = (eidp) ? 0 : 1;
  195. /* Use local engineID if *eidp == NULL.  */
  196. #ifdef HAVE_GETHOSTNAME
  197.   u_char   buf[SNMP_MAXBUF_SMALL];
  198.   struct hostent *hent;
  199. #endif
  200.   u_char     *bufp = NULL;
  201.   size_t   len;
  202. #if 0
  203.   if (eprom_extend()&&eprom_oem())
  204.   {
  205.      char company_name[100];
  206.      
  207.   if (!get_extend_info_string(INFO_COMPANY_NAME,company_name))
  208.   {
  209.   if (!strcasecmp(company_name,DIGITAL_CHINA_VENDOR_NAME))
  210.   {
  211.    enterpriseid = htonl(DIGITAL_CHINA_ENTERPRISE_NUMBER);
  212.    default_enterprise[6]=DIGITAL_CHINA_ENTERPRISE_NUMBER;
  213.   }
  214.   if (!strcasecmp(company_name,DLINK_VENDOR_NAME))
  215.   {
  216.    enterpriseid = htonl(DLINK_ENTERPRISE_NUMBER);
  217.    default_enterprise[6]=DLINK_ENTERPRISE_NUMBER;
  218.   }
  219.      }
  220.   }
  221. #endif
  222.   /*
  223.    * Determine length of the engineID string.
  224.    */
  225.   if (text) {
  226.     len = 5+strlen(text); /* 5 leading bytes+text. */
  227.   } else {
  228.     len = 5 + 4; /* 5 leading bytes + four byte IPv4 address */
  229. #ifdef HAVE_GETHOSTNAME
  230.     gethostname((char *)buf, sizeof(buf));
  231.     hent = gethostbyname((char *)buf);
  232. #ifdef AF_INET6
  233.     if (hent && hent->h_addrtype == AF_INET6)
  234.       len += 12; /* 16 bytes total for IPv6 address. */
  235. #endif
  236. #endif /* HAVE_GETHOSTNAME */
  237.   }  /* endif -- text (1) */
  238.   /*
  239.    * Allocate memory and store enterprise ID.
  240.    */
  241.   if ((bufp = (u_char *) malloc(len)) == NULL) {
  242.     snmp_log_perror("setup_engineID malloc");
  243.     return -1;
  244.   }
  245.   memcpy(bufp, &enterpriseid, sizeof(enterpriseid)); /* XXX Must be 4 bytes! */
  246.   bufp[0] |= 0x80;
  247.   
  248.   /*
  249.    * Store the given text  -OR-   the first found IP address.
  250.    */
  251.   if (text) {
  252.     bufp[4] = 4;
  253.     memcpy((char *)bufp+5, text, strlen(text));
  254.   } else {
  255.     bufp[4] = 1;
  256. #ifdef HAVE_GETHOSTNAME
  257.     gethostname((char *)buf, sizeof(buf));
  258.     hent = gethostbyname((char *)buf);
  259.     if (hent && hent->h_addrtype == AF_INET) {
  260.       memcpy(bufp+5, hent->h_addr_list[0], hent->h_length);
  261. #ifdef AF_INET6
  262.     } else if (hent && hent->h_addrtype == AF_INET6) {
  263.       bufp[4] = 2;
  264.       memcpy(bufp+5, hent->h_addr_list[0], hent->h_length);
  265. #endif
  266.     } else { /* Unknown address type.  Default to 127.0.0.1. */
  267.       bufp[5] = 127;
  268.       bufp[6] = 0;
  269.       bufp[7] = 0;
  270.       bufp[8] = 1;
  271.     }
  272. #else /* HAVE_GETHOSTNAME */
  273.     /* Unknown address type.  Default to 127.0.0.1. */
  274.     
  275.     bufp[5] = 127;
  276.     bufp[6] = 0;
  277.     bufp[7] = 0;
  278.     bufp[8] = 1;
  279. #endif /* HAVE_GETHOSTNAME */
  280.     
  281.   }  /* endif -- text (2) */
  282.   /*
  283.    * Pass the string back to the calling environment, or use it for
  284.    * our local engineID.
  285.    */
  286.   if (localsetup) {
  287. SNMP_FREE(engineID);
  288. engineID = bufp;
  289. engineIDLength = len;
  290.   } else {
  291. *eidp = bufp;
  292.   }
  293.   return len;
  294. }  /* end setup_engineID() */
  295. void
  296. usm_parse_create_usmUser(const char *token, char *line) {
  297.   char *cp;
  298.   char buf[SNMP_MAXBUF_MEDIUM];
  299.   struct usmUser *newuser;
  300.   u_char   userKey[SNMP_MAXBUF_SMALL];
  301.   size_t   userKeyLen = SNMP_MAXBUF_SMALL;
  302.   size_t ret;
  303.   newuser = usm_create_user();
  304.   /* READ: Security Name */
  305.   cp = copy_word(line, buf);
  306.   newuser->secName = strdup(buf);
  307.   newuser->name = strdup(buf);
  308.   newuser->engineID = snmpv3_generate_engineID(&ret);
  309.   if ( ret < 0 ) {
  310.     usm_free_user(newuser);
  311.     return;
  312.   }
  313.   newuser->engineIDLen = ret;
  314.   if (!cp)
  315.     goto add; /* no authentication or privacy type */
  316.   /* READ: Authentication Type */
  317.   if (strncmp(cp, "MD5", 3) == 0) {
  318.     memcpy(newuser->authProtocol, usmHMACMD5AuthProtocol,
  319.            sizeof(usmHMACMD5AuthProtocol));
  320.   } else if (strncmp(cp, "SHA", 3) == 0) {
  321.     memcpy(newuser->authProtocol, usmHMACSHA1AuthProtocol,
  322.            sizeof(usmHMACSHA1AuthProtocol));
  323.   } else {
  324.     config_perror("Unknown authentication protocol");
  325.     usm_free_user(newuser);
  326.     return;
  327.   }
  328.   cp = skip_token(cp);
  329.   /* READ: Authentication Pass Phrase */
  330.   if (!cp) {
  331.     config_perror("no authentication pass phrase");
  332.     usm_free_user(newuser);
  333.     return;
  334.   }
  335.   cp = copy_word(cp, buf);
  336.   /* And turn it into a localized key */
  337.   ret = generate_Ku(newuser->authProtocol, newuser->authProtocolLen,
  338.     (u_char *)buf, strlen(buf),
  339.     userKey, &userKeyLen );
  340.   if (ret != SNMPERR_SUCCESS) {
  341.     config_perror("Error generating auth key from pass phrase.");
  342.     usm_free_user(newuser);
  343.     return;
  344.   }
  345.   newuser->authKeyLen =
  346.     sc_get_properlength(newuser->authProtocol, newuser->authProtocolLen);
  347.   newuser->authKey = (u_char *) malloc(newuser->authKeyLen);
  348.   ret = generate_kul(newuser->authProtocol, newuser->authProtocolLen,
  349.      newuser->engineID, newuser->engineIDLen,
  350.      userKey, userKeyLen,
  351.      newuser->authKey, &newuser->authKeyLen );
  352.   if (ret != SNMPERR_SUCCESS) {
  353.     config_perror("Error generating localized auth key (Kul) from Ku.");
  354.     usm_free_user(newuser);
  355.     return;
  356.   }
  357.   if (!cp)
  358.     goto add; /* no privacy type (which is legal) */
  359.   
  360.   /* READ: Privacy Type */
  361.   if (strncmp(cp, "DES", 3) == 0) {
  362.     memcpy(newuser->privProtocol, usmDESPrivProtocol,
  363.            sizeof(usmDESPrivProtocol));
  364.   } else {
  365.     config_perror("Unknown privacy protocol");
  366.     usm_free_user(newuser);
  367.     return;
  368.   }
  369.   cp = skip_token(cp);
  370.   /* READ: Authentication Pass Phrase */
  371.   if (!cp) {
  372.     /* assume the same as the authentication key */
  373.     snmp_memdup(&newuser->privKey, newuser->authKey, newuser->authKeyLen);
  374.   } else {
  375.     cp = copy_word(cp, buf);
  376.     /* And turn it into a localized key */
  377.     ret = generate_Ku(newuser->authProtocol, newuser->authProtocolLen,
  378.                       (u_char *)buf, strlen(buf),
  379.                       userKey, &userKeyLen );
  380.     if (ret != SNMPERR_SUCCESS) {
  381.       config_perror("Error generating priv key from pass phrase.");
  382.       usm_free_user(newuser);
  383.       return;
  384.     }
  385.     ret = sc_get_properlength(newuser->authProtocol, newuser->authProtocolLen);
  386.     if (ret < 0) {
  387.       config_perror("Error getting proper key length for priv algorithm.");
  388.       usm_free_user(newuser);
  389.       return;
  390.     }
  391.     newuser->privKeyLen = ret;
  392.       
  393.     newuser->privKey = (u_char *) malloc(newuser->privKeyLen);
  394.     ret = generate_kul(newuser->authProtocol, newuser->authProtocolLen,
  395.                        newuser->engineID, newuser->engineIDLen,
  396.                        userKey, userKeyLen,
  397.                        newuser->privKey, &newuser->privKeyLen );
  398.     if (ret != SNMPERR_SUCCESS) {
  399.       config_perror("Error generating localized priv key (Kul) from Ku.");
  400.       usm_free_user(newuser);
  401.       return;
  402.     }
  403.   }
  404. add:
  405.   usm_add_user(newuser);
  406.   DEBUGMSGTL(("usmUser","created a new user %sn", newuser->secName));
  407. }
  408. /*******************************************************************-o-******
  409.  * engineBoots_conf
  410.  *
  411.  * Parameters:
  412.  * *word
  413.  * *cptr
  414.  *
  415.  * Line syntax:
  416.  * engineBoots <num_boots>
  417.  */
  418. void
  419. engineBoots_conf(const char *word, char *cptr)
  420. {
  421.   engineBoots = atoi(cptr)+1;
  422.   DEBUGMSGTL(("snmpv3","engineBoots: %dn",engineBoots));
  423. }
  424. /*******************************************************************-o-******
  425.  * engineID_conf
  426.  *
  427.  * Parameters:
  428.  * *word
  429.  * *cptr
  430.  *
  431.  * This function reads a string from the configuration file and uses that
  432.  * string to initialize the engineID.  It's assumed to be human readable.
  433.  */
  434. void
  435. engineID_conf(const char *word, char *cptr)
  436. {
  437.   setup_engineID(NULL, cptr);
  438.   DEBUGMSGTL(("snmpv3","initialized engineID with: %sn",cptr));
  439. }
  440. void
  441. version_conf(const char *word, char *cptr)
  442. {
  443.   if (strcmp(cptr,"1") == 0) {
  444.     ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_1);
  445.   } else if (strcasecmp(cptr,"2c") == 0) {
  446.     ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_2c);
  447.   } else if (strcmp(cptr,"3") == 0) {
  448.     ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_3);
  449.   } else {
  450.     config_perror("Unknown version specification");
  451.     return;
  452.   }
  453.   DEBUGMSGTL(("snmpv3","set default version to %dn",
  454.               ds_get_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION)));
  455. }
  456. /* engineID_old_conf(const char *, char *):
  457.    Reads a octet string encoded engineID into the oldEngineID and
  458.    oldEngineIDLen pointers.
  459. */
  460. void
  461. oldengineID_conf(const char *word, char *cptr)
  462. {
  463.   read_config_read_octet_string(cptr, &oldEngineID, &oldEngineIDLength);
  464. }
  465. /*******************************************************************-o-******
  466.  * init_snmpv3
  467.  *
  468.  * Parameters:
  469.  * *type Label for the config file "type" used by calling entity.
  470.  *      
  471.  * Set time and engineID.
  472.  * Set parsing functions for config file tokens.
  473.  * Initialize SNMP Crypto API (SCAPI).
  474.  */
  475. void
  476. init_snmpv3(const char *type) {
  477.   gettimeofday(&snmpv3starttime, NULL);
  478.   if (type == NULL)
  479.      type = "snmpapp";
  480.   if (type && !strcmp(type,"snmpapp")) {
  481.      setup_engineID(NULL,"__snmpapp__");
  482.   } else {
  483.      setup_engineID(NULL, NULL);
  484.   }
  485.   /* initialize submodules */
  486.   init_usm();
  487.   /* we need to be called back later */
  488.   snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
  489.                          init_snmpv3_post_config, NULL);
  490.   /* we need to be called back later */
  491.   snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
  492.                          snmpv3_store, (void *) type);
  493. #if !defined(USE_INTERNAL_MD5)
  494.   /* doesn't belong here at all */
  495.   sc_init();
  496. #endif /* !USE_INTERNAL_MD5 */
  497.   /* register all our configuration handlers (ack, there's a lot) */
  498.   /* handle engineID setup before everything else which may depend on it */
  499.   register_premib_handler(type,"engineID", engineID_conf, NULL, "string");
  500.   register_premib_handler(type,"oldEngineID", oldengineID_conf, NULL, NULL);
  501.   register_config_handler(type,"engineBoots", engineBoots_conf, NULL, NULL);
  502.   /* default store config entries */
  503.   ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityName", DS_LIBRARY_ID,
  504.                      DS_LIB_SECNAME);
  505.   ds_register_config(ASN_OCTET_STR, "snmp", "defContext", DS_LIBRARY_ID,
  506.                      DS_LIB_CONTEXT);
  507.   ds_register_config(ASN_OCTET_STR, "snmp", "defPassphrase", DS_LIBRARY_ID,
  508.                      DS_LIB_PASSPHRASE);
  509.   ds_register_config(ASN_OCTET_STR, "snmp", "defAuthPassphrase", DS_LIBRARY_ID,
  510.                      DS_LIB_AUTHPASSPHRASE);
  511.   ds_register_config(ASN_OCTET_STR, "snmp", "defPrivPassphrase", DS_LIBRARY_ID,
  512.                      DS_LIB_PRIVPASSPHRASE);
  513.   register_config_handler("snmp","defVersion", version_conf, NULL, "1|2c|3");
  514.   register_config_handler("snmp","defAuthType", snmpv3_authtype_conf, NULL,
  515.                           "MD5|SHA");
  516.   register_config_handler("snmp","defPrivType", snmpv3_privtype_conf, NULL,
  517.                           "DES (currently the only possible value)");
  518.   register_config_handler("snmp","defSecurityLevel", snmpv3_secLevel_conf,
  519.                           NULL, "noAuthNoPriv|authNoPriv|authPriv");
  520.   register_config_handler(type,"userSetAuthPass", usm_set_password, NULL,
  521.                           "secname engineIDLen engineID pass");
  522.   register_config_handler(type,"userSetPrivPass", usm_set_password, NULL,
  523.                           "secname engineIDLen engineID pass");
  524.   register_config_handler(type,"userSetAuthKey", usm_set_password, NULL,
  525.                           "secname engineIDLen engineID KuLen Ku");
  526.   register_config_handler(type,"userSetPrivKey", usm_set_password, NULL,
  527.                           "secname engineIDLen engineID KuLen Ku");
  528.   register_config_handler(type,"userSetAuthLocalKey", usm_set_password, NULL,
  529.                           "secname engineIDLen engineID KulLen Kul");
  530.   register_config_handler(type,"userSetPrivLocalKey", usm_set_password, NULL,
  531.                           "secname engineIDLen engineID KulLen Kul");
  532. }
  533. /*
  534.  * initializations for SNMPv3 to be called after the configuration files
  535.  * have been read.
  536.  */
  537. int
  538. init_snmpv3_post_config(int majorid, int minorid, void *serverarg,
  539.                         void *clientarg) {
  540.   size_t engineIDLen;
  541.   u_char *c_engineID;
  542.   c_engineID = snmpv3_generate_engineID(&engineIDLen);
  543.   if ( engineIDLen < 0 ) {
  544.     /* Somethine went wrong - help! */
  545.     return SNMPERR_GENERR;
  546.   }
  547.   /* if our engineID has changed at all, the boots record must be set to 1 */
  548.   if (engineIDLen != (int)oldEngineIDLength ||
  549.       oldEngineID == NULL || c_engineID == NULL ||
  550.       memcmp(oldEngineID, c_engineID, engineIDLen) != 0) {
  551.     engineBoots = 1;
  552.   }
  553.   /* set our local engineTime in the LCD timing cache */
  554.   set_enginetime(c_engineID, engineIDLen, 
  555.                  snmpv3_local_snmpEngineBoots(), 
  556.                  snmpv3_local_snmpEngineTime(),
  557.                  TRUE);
  558.   free(c_engineID);
  559.   return SNMPERR_SUCCESS;
  560. }
  561. /*******************************************************************-o-******
  562.  * store_snmpv3
  563.  *
  564.  * Parameters:
  565.  * *type
  566.  */
  567. int
  568. snmpv3_store(int majorID, int minorID, void *serverarg, void *clientarg) {
  569.   char line[SNMP_MAXBUF_SMALL];
  570.   u_char c_engineID[SNMP_MAXBUF_SMALL];
  571.   int  engineIDLen;
  572.   const char *type = (const char *) clientarg;
  573.   if (type == NULL)  /* should never happen, since the arg is ours */
  574.     type = "unknown";
  575.   sprintf(line, "engineBoots %ld", engineBoots);
  576.   read_config_store(type, line);
  577.   engineIDLen = snmpv3_get_engineID(c_engineID, SNMP_MAXBUF_SMALL);
  578.   if (engineIDLen) {
  579.     /* store the engineID used for this run */
  580.     sprintf(line, "oldEngineID ");
  581.     read_config_save_octet_string(line+strlen(line), c_engineID,
  582.                                   engineIDLen);
  583.     read_config_store(type, line);
  584.   }
  585.   return SNMPERR_SUCCESS;
  586. }  /* snmpv3_store() */
  587. u_long
  588. snmpv3_local_snmpEngineBoots(void)
  589. {
  590.   return engineBoots;
  591. }
  592. /*******************************************************************-o-******
  593.  * snmpv3_get_engineID
  594.  *
  595.  * Parameters:
  596.  * *buf
  597.  *  buflen
  598.  *      
  599.  * Returns:
  600.  * Length of engineID On Success
  601.  * SNMPERR_GENERR Otherwise.
  602.  *
  603.  *
  604.  * Store engineID in buf; return the length.
  605.  *
  606.  */
  607. int
  608. snmpv3_get_engineID(u_char *buf, size_t buflen)
  609. {
  610.   /*
  611.    * Sanity check.
  612.    */
  613.   if ( !buf || (buflen < engineIDLength) ) {
  614.     return SNMPERR_GENERR;
  615.   }
  616.   memcpy(buf,engineID,engineIDLength);
  617.   return engineIDLength;
  618. }  /* end snmpv3_get_engineID() */
  619. /*******************************************************************-o-******
  620.  * snmpv3_clone_engineID
  621.  *
  622.  * Parameters:
  623.  * **dest
  624.  *       *dest_len
  625.  *       src
  626.  *  srclen
  627.  *      
  628.  * Returns:
  629.  * Length of engineID On Success
  630.  * 0         Otherwise.
  631.  *
  632.  *
  633.  * Clones engineID, creates memory
  634.  *
  635.  */
  636. int
  637. snmpv3_clone_engineID(u_char **dest, size_t* destlen, u_char*src, size_t srclen)
  638. {
  639.   if ( !dest || !destlen ) return 0;
  640.   *dest = NULL; *destlen = 0;
  641.   if (srclen && src) {
  642.     *dest = (u_char*)malloc((unsigned)srclen * sizeof(u_char));
  643.     if (*dest == NULL) return 0;
  644.     memmove(*dest, src, srclen * sizeof(u_char));
  645.     *destlen = srclen;
  646.   }
  647.   return *destlen;
  648. }  /* end snmpv3_clone_engineID() */
  649. /*******************************************************************-o-******
  650.  * snmpv3_generate_engineID
  651.  *
  652.  * Parameters:
  653.  * *length
  654.  *      
  655.  * Returns:
  656.  * Pointer to copy of engineID On Success.
  657.  * NULL If malloc() or snmpv3_get_engineID()
  658.  * fail.
  659.  *
  660.  * Generates a malloced copy of our engineID.
  661.  *
  662.  * 'length' is set to the length of engineID  -OR-  < 0 on failure.
  663.  */
  664. u_char *
  665. snmpv3_generate_engineID(size_t *length)
  666. {
  667.   u_char *newID;
  668.   newID = (u_char *) malloc(engineIDLength);
  669.   if (newID) {
  670.     *length = snmpv3_get_engineID(newID, engineIDLength);
  671.   }
  672.   if (*length < 0) {
  673.     SNMP_FREE(newID);
  674.     newID = NULL;
  675.   }
  676.   return newID;
  677. }  /* end snmpv3_generate_engineID() */
  678. /* snmpv3_local_snmpEngineTime(): return the number of seconds since the
  679.    snmpv3 engine last incremented engine_boots */
  680. u_long
  681. snmpv3_local_snmpEngineTime(void)
  682. {
  683.   struct timeval now;
  684.   gettimeofday(&now, NULL);
  685.   return calculate_time_diff(&now, &snmpv3starttime)/100;
  686. }
  687. #ifdef SNMP_TESTING_CODE
  688. /* snmpv3_set_engineBootsAndTime(): this function does not exist.  Go away. */
  689. /*   It certainly should never be used, unless in a testing scenero,
  690.      which is why it was created */
  691. void
  692. snmpv3_set_engineBootsAndTime(int boots, int ttime) {
  693.   engineBoots = boots;
  694.   gettimeofday(&snmpv3starttime, NULL);
  695.   snmpv3starttime.tv_sec -= ttime;
  696. }
  697. #endif
  698. #ifdef INCLUDE_SNMPV3
  699. /*Sunxi, 26, Feb 2004 */
  700. /*the flowing code is to manage snmpEngineIDs on remote hosts*/
  701. struct snmp_remote_engineID{
  702.     u_char remote_addr[16];/*SNMP engine on which host*/
  703.     u_short remote_port;/*on which port received SNMP messages(specially notification messages)*/
  704.     u_char remote_engineID[SNMP_MAX_ENG_SIZE];/*snmpEngineID*/
  705.     u_int reference_count;
  706.     struct snmp_remote_engineID *next;
  707. };
  708. struct snmp_remote_engineID *snmp_remote_engineID_list = NULL;
  709. #define FOREACH_ENGINE(pe) 
  710.     for(pe = snmp_remote_engineID_list; pe != NULL; pe = pe->next)
  711. /*is engineID Greater/Equal*/
  712. #define COMPARE_EID(eid1, eid2, op) 
  713.     (strcmp(eid1->remote_addr, eid2->remote_addr) op 0)
  714. void snmpv3_add_remote_engineID(u_char* ipaddr, u_short port, u_char *engineID, size_t engineIDLen)
  715. {
  716.     struct snmp_remote_engineID *eID = malloc(sizeof(struct snmp_remote_engineID)), *ptr, *prev = NULL;
  717.     if (eID == NULL)
  718.         return;
  719.     memset((void *)eID, 0, sizeof(struct snmp_remote_engineID));
  720.     strncpy(eID->remote_addr, ipaddr, sizeof(eID->remote_addr));
  721.     eID->remote_port = port;
  722.     memcpy(eID->remote_engineID, engineID, engineIDLen);
  723.     if (snmp_remote_engineID_list == NULL) {
  724.         snmp_remote_engineID_list = eID;
  725.         return;
  726.     }
  727.     FOREACH_ENGINE(ptr) {
  728.         if (COMPARE_EID(ptr, eID, >)) {
  729.             prev = ptr;
  730.             continue;
  731.         }
  732.         if (COMPARE_EID(ptr, eID, ==)) {
  733.             if (ptr->remote_port == eID->remote_port) {
  734.                 /*duplicate remote engine ID*/
  735.                 /*update remote user list and host list*/
  736.                 refreshV3TrapSession(ipaddr, engineID, engineIDLen);
  737.                 refresh_snmp_user_engineID(ptr->remote_engineID, SNMP_MAX_ENG_SIZE, engineID, engineIDLen);
  738.                 /*replace the old one*/
  739.                 memset((void*)ptr->remote_engineID, 0, sizeof(ptr->remote_engineID));
  740.                 memcpy(ptr->remote_engineID, engineID, engineIDLen);
  741.                 free(eID);
  742.                 return;
  743.             }
  744.         } else /*ptr < eID*/
  745.             break;
  746.     }
  747.     if (ptr == NULL) {
  748.         /*add to tail*/
  749.         prev->next = eID;
  750.     } else if (prev == NULL) {
  751.         /*add to head*/
  752.         eID->next = snmp_remote_engineID_list;
  753.         snmp_remote_engineID_list = eID;
  754.     } else {
  755.         eID->next = prev->next;
  756.         prev->next = eID;
  757.     }
  758. }
  759. void snmpv3_delete_remote_engineID(u_char *ipaddr, u_short port)
  760. {
  761.     struct snmp_remote_engineID *ptr, *prev = NULL, temp;
  762.     strncpy(temp.remote_addr, ipaddr, sizeof(temp.remote_addr));
  763.     temp.remote_port = port;
  764.     FOREACH_ENGINE(ptr) {
  765.         if (COMPARE_EID(ptr, (&temp), >)) {
  766.             prev = ptr;
  767.             continue;
  768.         }
  769.         if (COMPARE_EID(ptr, (&temp), ==)) {
  770.             if (ptr->remote_port == port) {
  771.                 /*found it!!!*/
  772.                 if (ptr->reference_count != 0) {
  773.                     syslog(LOG_WARNING, "%%SNMP-%d-ENGINEID: The engineID is used by SNMP-hosts or SNMP users. It can't be deletedn", LOG_WARNING);
  774.                     return;
  775.                 }
  776.                 if (prev == NULL) {
  777.                     /*first remote engine ID to be removed*/
  778.                     snmp_remote_engineID_list = ptr->next;
  779.                 } else
  780.                     prev->next = ptr->next;
  781.                 free(ptr);
  782.                 return;
  783.             }
  784.         } else /*not found*/
  785.             return;
  786.     }
  787. }
  788. char *snmpv3_get_remote_engineID(u_char *ipaddr, u_short port)
  789. {
  790.     struct snmp_remote_engineID *ptr, temp;
  791.     strncpy(temp.remote_addr, ipaddr, sizeof(temp.remote_addr));
  792.     temp.remote_port = port;
  793.     FOREACH_ENGINE(ptr) {
  794.         if (COMPARE_EID(ptr, (&temp), >))
  795.             continue;
  796.         if (COMPARE_EID(ptr, (&temp), ==)) {
  797.             if (ptr->remote_port == port) {
  798.                 /*found it!!!*/
  799.                 return ptr->remote_engineID;
  800.             }
  801.         } else /*not found*/
  802.             return NULL;
  803.     }
  804.     return NULL;
  805. }
  806. void snmpv3_get_remote_host_info_by_engineID(u_char *snmpEngineID, u_char **addr, u_short *port)
  807. {
  808.     struct snmp_remote_engineID *ptr;
  809.     assert(snmpEngineID && addr && port);
  810.     *addr = NULL;
  811.     *port = 0;
  812.     FOREACH_ENGINE(ptr) {
  813.         if (memcmp(snmpEngineID, ptr->remote_engineID, sizeof(ptr->remote_engineID)) == 0) {
  814.             *addr = ptr->remote_addr;
  815.             *port = ptr->remote_port;
  816.             return;
  817.         }
  818.     }
  819. }
  820. void snmpv3_inc_remote_engineID_reference(u_char *ipaddr, u_short port)
  821. {
  822.     struct snmp_remote_engineID *ptr, temp;
  823.     strncpy(temp.remote_addr, ipaddr, sizeof(temp.remote_addr));
  824.     temp.remote_port = port;
  825.     FOREACH_ENGINE(ptr) {
  826.         if (COMPARE_EID(ptr, (&temp), >))
  827.             continue;
  828.         if (COMPARE_EID(ptr, (&temp), ==)) {
  829.             if (ptr->remote_port == port) {
  830.                 /*found it!!!*/
  831.                 ptr->reference_count++;
  832.                 return;
  833.             }
  834.         } else /*not found*/
  835.             return;
  836.     }
  837.     return ;
  838. }
  839. void snmpv3_dec_remote_engineID_reference(u_char *ipaddr, u_short port)
  840. {
  841.     struct snmp_remote_engineID *ptr, temp;
  842.     strncpy(temp.remote_addr, ipaddr, sizeof(temp.remote_addr));
  843.     temp.remote_port = port;
  844.     FOREACH_ENGINE(ptr) {
  845.         if (COMPARE_EID(ptr, (&temp), >))
  846.             continue;
  847.         if (COMPARE_EID(ptr, (&temp), ==)) {
  848.             if (ptr->remote_port == port) {
  849.                 /*found it!!!*/
  850.                 ptr->reference_count--;
  851.                 return;
  852.             }
  853.         } else /*not found*/
  854.             return;
  855.     }
  856.     return ;
  857. }
  858. void snmpv3_engineID2str(char *engineID, size_t engineIDLen, char *dest)
  859. {
  860.     int i;
  861.     assert(engineID && dest);
  862.     for(i=0;i<engineIDLen;i++)
  863.         sprintf(dest + i * 2, "%02x", (int)(engineID[i]));
  864.     /*trunc endding zeros'*/
  865.     for(i=engineIDLen * 2 - 1;i>=0;i--)
  866.         if (dest[i] == '0')
  867.             dest[i] = 0;
  868.         else
  869.             return;
  870. }
  871. void do_show_snmpv3_remote_engineID()
  872. {
  873.     struct snmp_remote_engineID *ptr;
  874.     char engineIDstr[SNMP_MAX_ENG_SIZE * 2 + 1];
  875.     vty_printf("Remote Engine ID                IP-addr    Portn");
  876.     FOREACH_ENGINE(ptr) {
  877.         memset((void *)engineIDstr, 0, sizeof(engineIDstr));
  878.         snmpv3_engineID2str(ptr->remote_engineID, SNMP_MAX_ENG_SIZE, engineIDstr);
  879.         if (strlen(engineIDstr) <= 32)
  880.             vty_printf("%.32s %.16s     %dn",
  881.                 engineIDstr, ptr->remote_addr, ptr->remote_port);
  882.         else
  883.             vty_printf("%s n                                  %.16s     %dn",
  884.                 engineIDstr, ptr->remote_addr, ptr->remote_port);
  885.     }
  886. }
  887. BOOL do_showrunning_snmpv3_remote_engineID()
  888. {
  889.     struct snmp_remote_engineID *ptr;
  890.     char engineIDstr[SNMP_MAX_ENG_SIZE * 2 + 1];
  891.     if (snmp_remote_engineID_list == NULL)
  892.         return FALSE;
  893.     FOREACH_ENGINE(ptr) {
  894.         memset((void *)engineIDstr, 0, sizeof(engineIDstr));
  895.         snmpv3_engineID2str(ptr->remote_engineID, SNMP_MAX_ENG_SIZE, engineIDstr);
  896.         vty_printf("snmp-server engineID remote %s ", ptr->remote_addr);
  897.         if (ptr->remote_port != SNMP_TRAP_PORT)
  898.             vty_printf("udp-port %d ", ptr->remote_port);
  899.         vty_printf("%sn", engineIDstr);
  900.     }
  901.     return TRUE;
  902. }
  903. /*end add*/
  904. #endif /*INCLUDE_SNMPV3*/