Mercurial > ecos
diff packages/net/snmp/lib/current/src/snmpv3.c @ 103:95f3e12a6327 ecos-sw-2000-06-23
Merge from eCos master repository on 2000-06-23-16:41:10-BST
| author | jlarmour |
|---|---|
| date | Fri, 23 Jun 2000 17:06:31 +0000 |
| parents | |
| children | e0c0827131d1 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmpv3.c @@ -0,0 +1,838 @@ +//========================================================================== +// +// ./lib/current/src/snmpv3.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, <http://ucd-snmp.ucdavis.edu/> from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpv3.c + */ + +#include <config.h> + +#include <stdio.h> +#include <sys/types.h> +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include <sys/timeb.h> +# else +# include <sys/time.h> +# endif +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_WINSOCK_H +#include <winsock.h> +#endif +#if HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if HAVE_NETDB_H +#include <netdb.h> +#endif +#if HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#if HAVE_DMALLOC_H +#include <dmalloc.h> +#endif + +#include "system.h" +#include "asn1.h" +#include "snmpv3.h" +#include "callback.h" +#include "snmpusm.h" +#include "snmp.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "read_config.h" +#include "lcd_time.h" +#include "scapi.h" +#include "tools.h" +#include "keytools.h" +#include "lcd_time.h" +#include "snmp_debug.h" +#include "snmp_logging.h" +#include "default_store.h" + +#include "transform_oids.h" + +static u_long engineBoots = 1; +static unsigned char *engineID = NULL; +static size_t engineIDLength = 0; +static unsigned char *oldEngineID = NULL; +static size_t oldEngineIDLength = 0; +static struct timeval snmpv3starttime; + +/* + * Set up default snmpv3 parameter value storage. + */ +static oid *defaultAuthType = NULL; +static size_t defaultAuthTypeLen = 0; +static oid *defaultPrivType = NULL; +static size_t defaultPrivTypeLen = 0; + +void +snmpv3_authtype_conf(const char *word, char *cptr) +{ + if (strcasecmp(cptr,"MD5") == 0) + defaultAuthType = usmHMACMD5AuthProtocol; + else if (strcasecmp(cptr,"SHA") == 0) + defaultAuthType = usmHMACMD5AuthProtocol; + else + config_perror("Unknown authentication type"); + defaultAuthTypeLen = USM_LENGTH_OID_TRANSFORM; + DEBUGMSGTL(("snmpv3","set default authentication type: %s\n", cptr)); +} + +oid * +get_default_authtype(size_t *len) +{ + if (defaultAuthType == NULL) { + defaultAuthType = SNMP_DEFAULT_AUTH_PROTO; + defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN; + } + if (len) + *len = defaultAuthTypeLen; + return defaultAuthType; +} + +void +snmpv3_privtype_conf(const char *word, char *cptr) +{ + if (strcasecmp(cptr,"DES") == 0) + defaultPrivType = SNMP_DEFAULT_PRIV_PROTO; + else + config_perror("Unknown privacy type"); + defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN; + DEBUGMSGTL(("snmpv3","set default privacy type: %s\n", cptr)); +} + +oid * +get_default_privtype(size_t *len) +{ + if (defaultAuthType == NULL) { + defaultAuthType = usmDESPrivProtocol; + defaultPrivTypeLen = USM_LENGTH_OID_TRANSFORM; + } + if (len) + *len = defaultPrivTypeLen; + return defaultPrivType; +} + +/*******************************************************************-o-****** + * snmpv3_secLevel_conf + * + * Parameters: + * *word + * *cptr + * + * Line syntax: + * defSecurityLevel "noAuthNoPriv" | "authNoPriv" | "authPriv" + */ +void +snmpv3_secLevel_conf(const char *word, char *cptr) +{ + char buf[1024]; + + if (strcasecmp(cptr,"noAuthNoPriv") == 0 || strcmp(cptr, "1") == 0 + || strcasecmp(cptr, "nanp") == 0) + ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_NOAUTH); + else if (strcasecmp(cptr,"authNoPriv") == 0 || strcmp(cptr, "2") == 0 + || strcasecmp(cptr, "anp") == 0) + ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHNOPRIV); + else if (strcasecmp(cptr,"authPriv") == 0 || strcmp(cptr, "3") == 0 + || strcasecmp(cptr, "ap") == 0) + ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHPRIV); + else { + sprintf(buf,"Unknown security level: %s", cptr); + config_perror(buf); + } + DEBUGMSGTL(("snmpv3","default secLevel set to: %s = %d\n", cptr, + ds_get_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL))); +} + +/*******************************************************************-o-****** + * setup_engineID + * + * Parameters: + * **eidp + * *text Printable (?) text to be plugged into the snmpEngineID. + * + * Return: + * Length of allocated engineID string in bytes, -OR- + * -1 on error. + * + * + * Create an snmpEngineID using text and the local IP address. If eidp + * is defined, use it to return a pointer to the newly allocated data. + * Otherwise, use the result to define engineID defined in this module. + * + * Line syntax: + * engineID <text> | NULL + * + * XXX What if a node has multiple interfaces? + * XXX What if multiple engines all choose the same address? + * (answer: You're screwed, because you might need a kul database + * which is dependant on the current engineID. Enumeration and other + * tricks won't work). + */ +int +setup_engineID(u_char **eidp, const char *text) +{ + int enterpriseid = htonl(ENTERPRISE_NUMBER), + localsetup = (eidp) ? 0 : 1; + /* Use local engineID if *eidp == NULL. */ +#ifdef HAVE_GETHOSTNAME + u_char buf[SNMP_MAXBUF_SMALL]; + struct hostent *hent; +#endif + u_char *bufp = NULL; + size_t len; + + + /* + * Determine length of the engineID string. + */ + if (text) { + len = 5+strlen(text); /* 5 leading bytes+text. */ + + } else { + len = 5 + 4; /* 5 leading bytes + four byte IPv4 address */ +#ifdef HAVE_GETHOSTNAME + gethostname((char *)buf, sizeof(buf)); + hent = gethostbyname((char *)buf); +#ifdef AF_INET6 + if (hent && hent->h_addrtype == AF_INET6) + len += 12; /* 16 bytes total for IPv6 address. */ +#endif +#endif /* HAVE_GETHOSTNAME */ + } /* endif -- text (1) */ + + + /* + * Allocate memory and store enterprise ID. + */ + if ((bufp = (u_char *) malloc(len)) == NULL) { + snmp_log_perror("setup_engineID malloc"); + return -1; + } + + memcpy(bufp, &enterpriseid, sizeof(enterpriseid)); /* XXX Must be 4 bytes! */ + bufp[0] |= 0x80; + + + /* + * Store the given text -OR- the first found IP address. + */ + if (text) { + bufp[4] = 4; + memcpy((char *)bufp+5, text, strlen(text)); + + } else { + bufp[4] = 1; +#ifdef HAVE_GETHOSTNAME + gethostname((char *)buf, sizeof(buf)); + hent = gethostbyname((char *)buf); + + if (hent && hent->h_addrtype == AF_INET) { + memcpy(bufp+5, hent->h_addr_list[0], hent->h_length); + +#ifdef AF_INET6 + } else if (hent && hent->h_addrtype == AF_INET6) { + bufp[4] = 2; + memcpy(bufp+5, hent->h_addr_list[0], hent->h_length); +#endif + + } else { /* Unknown address type. Default to 127.0.0.1. */ + + bufp[5] = 127; + bufp[6] = 0; + bufp[7] = 0; + bufp[8] = 1; + } +#else /* HAVE_GETHOSTNAME */ + /* Unknown address type. Default to 127.0.0.1. */ + + bufp[5] = 127; + bufp[6] = 0; + bufp[7] = 0; + bufp[8] = 1; +#endif /* HAVE_GETHOSTNAME */ + + } /* endif -- text (2) */ + + + /* + * Pass the string back to the calling environment, or use it for + * our local engineID. + */ + if (localsetup) { + SNMP_FREE(engineID); + engineID = bufp; + engineIDLength = len; + + } else { + *eidp = bufp; + } + + + return len; + +} /* end setup_engineID() */ + +void +usm_parse_create_usmUser(const char *token, char *line) { + char *cp; + char buf[SNMP_MAXBUF_MEDIUM]; + struct usmUser *newuser; + u_char userKey[SNMP_MAXBUF_SMALL]; + size_t userKeyLen = SNMP_MAXBUF_SMALL; + int ret; + + newuser = usm_create_user(); + + /* READ: Security Name */ + cp = copy_word(line, buf); + newuser->secName = strdup(buf); + newuser->name = strdup(buf); + + newuser->engineID = snmpv3_generate_engineID(&ret); + if ( ret < 0 ) { + usm_free_user(newuser); + return; + } + newuser->engineIDLen = ret; + + if (!cp) + goto add; /* no authentication or privacy type */ + + /* READ: Authentication Type */ + if (strncmp(cp, "MD5", 3) == 0) { + memcpy(newuser->authProtocol, usmHMACMD5AuthProtocol, + sizeof(usmHMACMD5AuthProtocol)); + } else if (strncmp(cp, "SHA", 3) == 0) { + memcpy(newuser->authProtocol, usmHMACSHA1AuthProtocol, + sizeof(usmHMACSHA1AuthProtocol)); + } else { + config_perror("Unknown authentication protocol"); + usm_free_user(newuser); + return; + } + + cp = skip_token(cp); + + /* READ: Authentication Pass Phrase */ + if (!cp) { + config_perror("no authentication pass phrase"); + usm_free_user(newuser); + return; + } + cp = copy_word(cp, buf); + /* And turn it into a localized key */ + ret = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, + (u_char *)buf, strlen(buf), + userKey, &userKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating auth key from pass phrase."); + usm_free_user(newuser); + return; + } + newuser->authKeyLen = + sc_get_properlength(newuser->authProtocol, newuser->authProtocolLen); + newuser->authKey = (u_char *) malloc(newuser->authKeyLen); + ret = generate_kul(newuser->authProtocol, newuser->authProtocolLen, + newuser->engineID, newuser->engineIDLen, + userKey, userKeyLen, + newuser->authKey, &newuser->authKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating localized auth key (Kul) from Ku."); + usm_free_user(newuser); + return; + } + + if (!cp) + goto add; /* no privacy type (which is legal) */ + + /* READ: Privacy Type */ + if (strncmp(cp, "DES", 3) == 0) { + memcpy(newuser->privProtocol, usmDESPrivProtocol, + sizeof(usmDESPrivProtocol)); + } else { + config_perror("Unknown privacy protocol"); + usm_free_user(newuser); + return; + } + + cp = skip_token(cp); + /* READ: Authentication Pass Phrase */ + if (!cp) { + /* assume the same as the authentication key */ + memdup(&newuser->privKey, newuser->authKey, newuser->authKeyLen); + } else { + cp = copy_word(cp, buf); + /* And turn it into a localized key */ + ret = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, + (u_char *)buf, strlen(buf), + userKey, &userKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating priv key from pass phrase."); + usm_free_user(newuser); + return; + } + + ret = sc_get_properlength(newuser->authProtocol, newuser->authProtocolLen); + if (ret < 0) { + config_perror("Error getting proper key length for priv algorithm."); + usm_free_user(newuser); + return; + } + newuser->privKeyLen = ret; + + newuser->privKey = (u_char *) malloc(newuser->privKeyLen); + ret = generate_kul(newuser->authProtocol, newuser->authProtocolLen, + newuser->engineID, newuser->engineIDLen, + userKey, userKeyLen, + newuser->privKey, &newuser->privKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating localized priv key (Kul) from Ku."); + usm_free_user(newuser); + return; + } + } +add: + usm_add_user(newuser); + DEBUGMSGTL(("usmUser","created a new user %s\n", newuser->secName)); +} + +/*******************************************************************-o-****** + * engineBoots_conf + * + * Parameters: + * *word + * *cptr + * + * Line syntax: + * engineBoots <num_boots> + */ +void +engineBoots_conf(const char *word, char *cptr) +{ + engineBoots = atoi(cptr)+1; + DEBUGMSGTL(("snmpv3","engineBoots: %d\n",engineBoots)); +} + + + +/*******************************************************************-o-****** + * engineID_conf + * + * Parameters: + * *word + * *cptr + * + * This function reads a string from the configuration file and uses that + * string to initialize the engineID. It's assumed to be human readable. + */ +void +engineID_conf(const char *word, char *cptr) +{ + setup_engineID(NULL, cptr); + DEBUGMSGTL(("snmpv3","initialized engineID with: %s\n",cptr)); +} + +void +version_conf(const char *word, char *cptr) +{ + if (strcmp(cptr,"1") == 0) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_1); + } else if (strcasecmp(cptr,"2c") == 0) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_2c); + } else if (strcmp(cptr,"3") == 0) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_3); + } else { + config_perror("Unknown version specification"); + return; + } + DEBUGMSGTL(("snmpv3","set default version to %d\n", + ds_get_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION))); +} + +/* engineID_old_conf(const char *, char *): + + Reads a octet string encoded engineID into the oldEngineID and + oldEngineIDLen pointers. +*/ +void +oldengineID_conf(const char *word, char *cptr) +{ + read_config_read_octet_string(cptr, &oldEngineID, &oldEngineIDLength); +} + + +/*******************************************************************-o-****** + * init_snmpv3 + * + * Parameters: + * *type Label for the config file "type" used by calling entity. + * + * Set time and engineID. + * Set parsing functions for config file tokens. + * Initialize SNMP Crypto API (SCAPI). + */ +void +init_snmpv3(const char *type) { + gettimeofday(&snmpv3starttime, NULL); + + if (type == NULL) + type = "snmpapp"; + + if (type && !strcmp(type,"snmpapp")) { + setup_engineID(NULL,"__snmpapp__"); + } else { + setup_engineID(NULL, NULL); + } + + /* initialize submodules */ + init_usm(); + + /* we need to be called back later */ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, + init_snmpv3_post_config, NULL); + /* we need to be called back later */ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, + snmpv3_store, (void *) type); + + +#if !defined(USE_INTERNAL_MD5) + /* doesn't belong here at all */ + sc_init(); +#endif /* !USE_INTERNAL_MD5 */ + + /* register all our configuration handlers (ack, there's a lot) */ + + /* handle engineID setup before everything else which may depend on it */ + register_premib_handler(type,"engineID", engineID_conf, NULL, "string"); + register_premib_handler(type,"oldEngineID", oldengineID_conf, NULL, NULL); + register_config_handler(type,"engineBoots", engineBoots_conf, NULL, NULL); + + /* default store config entries */ + ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityName", DS_LIBRARY_ID, + DS_LIB_SECNAME); + ds_register_config(ASN_OCTET_STR, "snmp", "defContext", DS_LIBRARY_ID, + DS_LIB_CONTEXT); + ds_register_config(ASN_OCTET_STR, "snmp", "defPassphrase", DS_LIBRARY_ID, + DS_LIB_PASSPHRASE); + ds_register_config(ASN_OCTET_STR, "snmp", "defAuthPassphrase", DS_LIBRARY_ID, + DS_LIB_AUTHPASSPHRASE); + ds_register_config(ASN_OCTET_STR, "snmp", "defPrivPassphrase", DS_LIBRARY_ID, + DS_LIB_PRIVPASSPHRASE); + register_config_handler("snmp","defVersion", version_conf, NULL, "1|2c|3"); + + register_config_handler("snmp","defAuthType", snmpv3_authtype_conf, NULL, + "MD5|SHA"); + register_config_handler("snmp","defPrivType", snmpv3_privtype_conf, NULL, + "DES (currently the only possible value)"); + register_config_handler("snmp","defSecurityLevel", snmpv3_secLevel_conf, + NULL, "noAuthNoPriv|authNoPriv|authPriv"); + register_config_handler(type,"userSetAuthPass", usm_set_password, NULL, + "secname engineIDLen engineID pass"); + register_config_handler(type,"userSetPrivPass", usm_set_password, NULL, + "secname engineIDLen engineID pass"); + register_config_handler(type,"userSetAuthKey", usm_set_password, NULL, + "secname engineIDLen engineID KuLen Ku"); + register_config_handler(type,"userSetPrivKey", usm_set_password, NULL, + "secname engineIDLen engineID KuLen Ku"); + register_config_handler(type,"userSetAuthLocalKey", usm_set_password, NULL, + "secname engineIDLen engineID KulLen Kul"); + register_config_handler(type,"userSetPrivLocalKey", usm_set_password, NULL, + "secname engineIDLen engineID KulLen Kul"); +} + +/* + * initializations for SNMPv3 to be called after the configuration files + * have been read. + */ + +int +init_snmpv3_post_config(int majorid, int minorid, void *serverarg, + void *clientarg) { + + int engineIDLen; + u_char *c_engineID; + + c_engineID = snmpv3_generate_engineID(&engineIDLen); + + if ( engineIDLen < 0 ) { + /* Somethine went wrong - help! */ + return SNMPERR_GENERR; + } + + /* if our engineID has changed at all, the boots record must be set to 1 */ + if (engineIDLen != (int)oldEngineIDLength || + oldEngineID == NULL || c_engineID == NULL || + memcmp(oldEngineID, c_engineID, engineIDLen) != 0) { + engineBoots = 1; + } + + /* set our local engineTime in the LCD timing cache */ + set_enginetime(c_engineID, engineIDLen, + snmpv3_local_snmpEngineBoots(), + snmpv3_local_snmpEngineTime(), + TRUE); + + free(c_engineID); + return SNMPERR_SUCCESS; +} + +/*******************************************************************-o-****** + * store_snmpv3 + * + * Parameters: + * *type + */ +int +snmpv3_store(int majorID, int minorID, void *serverarg, void *clientarg) { + char line[SNMP_MAXBUF_SMALL]; + u_char c_engineID[SNMP_MAXBUF_SMALL]; + int engineIDLen; + const char *type = (const char *) clientarg; + + if (type == NULL) /* should never happen, since the arg is ours */ + type = "unknown"; + + sprintf(line, "engineBoots %ld", engineBoots); + read_config_store(type, line); + + engineIDLen = snmpv3_get_engineID(c_engineID, SNMP_MAXBUF_SMALL); + + if (engineIDLen) { + /* store the engineID used for this run */ + sprintf(line, "oldEngineID "); + read_config_save_octet_string(line+strlen(line), c_engineID, + engineIDLen); + read_config_store(type, line); + } + return SNMPERR_SUCCESS; +} /* snmpv3_store() */ + +u_long +snmpv3_local_snmpEngineBoots(void) +{ + return engineBoots; +} + + +/*******************************************************************-o-****** + * snmpv3_get_engineID + * + * Parameters: + * *buf + * buflen + * + * Returns: + * Length of engineID On Success + * SNMPERR_GENERR Otherwise. + * + * + * Store engineID in buf; return the length. + * + */ +int +snmpv3_get_engineID(u_char *buf, size_t buflen) +{ + /* + * Sanity check. + */ + if ( !buf || (buflen < engineIDLength) ) { + return SNMPERR_GENERR; + } + + memcpy(buf,engineID,engineIDLength); + return engineIDLength; + +} /* end snmpv3_get_engineID() */ + +/*******************************************************************-o-****** + * snmpv3_clone_engineID + * + * Parameters: + * **dest + * *dest_len + * src + * srclen + * + * Returns: + * Length of engineID On Success + * 0 Otherwise. + * + * + * Clones engineID, creates memory + * + */ +int +snmpv3_clone_engineID(u_char **dest, size_t* destlen, u_char*src, size_t srclen) +{ + if ( !dest || !destlen ) return 0; + + *dest = NULL; *destlen = 0; + + if (srclen && src) { + *dest = (u_char*)malloc((unsigned)srclen * sizeof(u_char)); + if (*dest == NULL) return 0; + memmove(*dest, src, srclen * sizeof(u_char)); + *destlen = srclen; + } + return *destlen; +} /* end snmpv3_clone_engineID() */ + + +/*******************************************************************-o-****** + * snmpv3_generate_engineID + * + * Parameters: + * *length + * + * Returns: + * Pointer to copy of engineID On Success. + * NULL If malloc() or snmpv3_get_engineID() + * fail. + * + * Generates a malloced copy of our engineID. + * + * 'length' is set to the length of engineID -OR- < 0 on failure. + */ +u_char * +snmpv3_generate_engineID(int *length) +{ + u_char *newID; + newID = (u_char *) malloc(engineIDLength); + + if (newID) { + *length = snmpv3_get_engineID(newID, engineIDLength); + } + + if (*length < 0) { + SNMP_FREE(newID); + newID = NULL; + } + + return newID; + +} /* end snmpv3_generate_engineID() */ + +/* snmpv3_local_snmpEngineTime(): return the number of seconds since the + snmpv3 engine last incremented engine_boots */ +u_long +snmpv3_local_snmpEngineTime(void) +{ + struct timeval now; + + gettimeofday(&now, NULL); + return calculate_time_diff(&now, &snmpv3starttime)/100; +} + +#ifdef SNMP_TESTING_CODE +/* snmpv3_set_engineBootsAndTime(): this function does not exist. Go away. */ +/* It certainly should never be used, unless in a testing scenero, + which is why it was created */ +void +snmpv3_set_engineBootsAndTime(int boots, int ttime) { + engineBoots = boots; + gettimeofday(&snmpv3starttime, NULL); + snmpv3starttime.tv_sec -= ttime; +} +#endif
