📄 scapi.c
字号:
/* * scapi.c * */#include <net-snmp/net-snmp-config.h>#include <sys/types.h>#if HAVE_WINSOCK_H#include <winsock.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#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#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_DMALLOC_H#include <dmalloc.h>#endif#include <net-snmp/types.h>#include <net-snmp/output_api.h>#include <net-snmp/utilities.h>#ifdef USE_INTERNAL_MD5#include <net-snmp/library/md5.h>#endif#include <net-snmp/library/snmp_api.h>#include <net-snmp/library/callback.h>#include <net-snmp/library/snmp_secmod.h>#include <net-snmp/library/snmpusm.h>#include <net-snmp/library/keytools.h>#include <net-snmp/library/scapi.h>#include <net-snmp/library/mib.h>#include <net-snmp/library/transform_oids.h>#ifdef USE_OPENSSL#include <openssl/hmac.h>#include <openssl/evp.h>#include <openssl/rand.h>#include <openssl/des.h>#ifdef HAVE_AES#include <openssl/aes.h>#endif#ifdef STRUCT_DES_KS_STRUCT_HAS_WEAK_KEY/* these are older names for newer structures that exist in openssl .9.7 */#define DES_key_schedule des_key_schedule #define DES_cblock des_cblock #define DES_key_sched des_key_sched #define DES_ncbc_encrypt des_ncbc_encrypt#define DES_cbc_encrypt des_cbc_encrypt#define OLD_DES#endif#endif /* HAVE_OPENSSL */#ifdef QUITFUN#undef QUITFUN#define QUITFUN(e, l) \ if (e != SNMPERR_SUCCESS) { \ rval = SNMPERR_SC_GENERAL_FAILURE; \ goto l ; \ }#endif/* * sc_get_properlength(oid *hashtype, u_int hashtype_len): * * Given a hashing type ("hashtype" and its length hashtype_len), return * the length of the hash result. * * Returns either the length or SNMPERR_GENERR for an unknown hashing type. */intsc_get_properlength(const oid * hashtype, u_int hashtype_len){ DEBUGTRACE; /* * Determine transform type hash length. */ if (ISTRANSFORM(hashtype, HMACMD5Auth)) { return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5); } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1); } return SNMPERR_GENERR;}/*******************************************************************-o-****** * sc_init * * Returns: * SNMPERR_SUCCESS Success. */intsc_init(void){ int rval = SNMPERR_SUCCESS;#ifndef USE_OPENSSL#ifdef USE_INTERNAL_MD5 struct timeval tv; DEBUGTRACE; gettimeofday(&tv, (struct timezone *) 0); srandom(tv.tv_sec ^ tv.tv_usec);#else rval = SNMPERR_SC_NOT_CONFIGURED;#endif /* * XXX ogud: The only reason to do anything here with openssl is to * * XXX ogud: seed random number generator */#endif /* ifndef USE_OPENSSL */ return rval;} /* end sc_init() *//*******************************************************************-o-****** * sc_random * * Parameters: * *buf Pre-allocated buffer. * *buflen Size of buffer. * * Returns: * SNMPERR_SUCCESS Success. */intsc_random(u_char * buf, size_t * buflen)#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL){ int rval = SNMPERR_SUCCESS;#ifdef USE_INTERNAL_MD5 int i; int rndval; u_char *ucp = buf;#endif DEBUGTRACE;#ifdef USE_OPENSSL RAND_bytes(buf, *buflen); /* will never fail */#else /* USE_INTERNAL_MD5 */ /* * fill the buffer with random integers. Note that random() * is defined in config.h and may not be truly the random() * system call if something better existed */ rval = *buflen - *buflen % sizeof(rndval); for (i = 0; i < rval; i += sizeof(rndval)) { rndval = random(); memcpy(ucp, &rndval, sizeof(rndval)); ucp += sizeof(rndval); } rndval = random(); memcpy(ucp, &rndval, *buflen % sizeof(rndval)); rval = SNMPERR_SUCCESS;#endif /* USE_OPENSSL */ return rval;} /* end sc_random() */#else_SCAPI_NOT_CONFIGURED#endif /* *//*******************************************************************-o-****** * sc_generate_keyed_hash * * Parameters: * authtype Type of authentication transform. * authtypelen * *key Pointer to key (Kul) to use in keyed hash. * keylen Length of key in bytes. * *message Pointer to the message to hash. * msglen Length of the message. * *MAC Will be returned with allocated bytes containg hash. * *maclen Length of the hash buffer in bytes; also indicates * whether the MAC should be truncated. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errs * * * A hash of the first msglen bytes of message using a keyed hash defined * by authtype is created and stored in MAC. MAC is ASSUMED to be a buffer * of at least maclen bytes. If the length of the hash is greater than * maclen, it is truncated to fit the buffer. If the length of the hash is * less than maclen, maclen set to the number of hash bytes generated. * * ASSUMED that the number of hash bits is a multiple of 8. */intsc_generate_keyed_hash(const oid * authtype, size_t authtypelen, u_char * key, u_int keylen, u_char * message, u_int msglen, u_char * MAC, size_t * maclen)#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL){ int rval = SNMPERR_SUCCESS; int properlength; u_char buf[SNMP_MAXBUF_SMALL];#if defined(USE_OPENSSL) int buf_len = sizeof(buf);#endif DEBUGTRACE;#ifdef SNMP_TESTING_CODE { int i; DEBUGMSG(("sc_generate_keyed_hash", "sc_generate_keyed_hash(): key=0x")); for (i = 0; i < keylen; i++) DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff)); DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen)); }#endif /* SNMP_TESTING_CODE */ /* * Sanity check. */ if (!authtype || !key || !message || !MAC || !maclen || (keylen <= 0) || (msglen <= 0) || (*maclen <= 0) || (authtypelen != USM_LENGTH_OID_TRANSFORM)) { QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); } properlength = sc_get_properlength(authtype, authtypelen); if (properlength == SNMPERR_GENERR) return properlength; if (((int) keylen < properlength)) { QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); }#ifdef USE_OPENSSL /* * Determine transform type. */ if (ISTRANSFORM(authtype, HMACMD5Auth)) HMAC(EVP_md5(), key, keylen, message, msglen, buf, &buf_len); else if (ISTRANSFORM(authtype, HMACSHA1Auth)) HMAC(EVP_sha1(), key, keylen, message, msglen, buf, &buf_len); else { QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); } if (buf_len != properlength) { QUITFUN(rval, sc_generate_keyed_hash_quit); } if (*maclen > buf_len) *maclen = buf_len; memcpy(MAC, buf, *maclen);#else if ((int) *maclen > properlength) *maclen = properlength; if (MDsign(message, msglen, MAC, *maclen, key, keylen)) { rval = SNMPERR_GENERR; goto sc_generate_keyed_hash_quit; }#endif /* USE_OPENSSL */#ifdef SNMP_TESTING_CODE { char *s; int len = binary_to_hex(MAC, *maclen, &s); DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s)); SNMP_ZERO(s, len); SNMP_FREE(s); }#endif sc_generate_keyed_hash_quit: SNMP_ZERO(buf, SNMP_MAXBUF_SMALL); return rval;} /* end sc_generate_keyed_hash() */#else _SCAPI_NOT_CONFIGURED#endif /* *//* * sc_hash(): a generic wrapper around whatever hashing package we are using. * * IN: * hashtype - oid pointer to a hash type * hashtypelen - length of oid pointer * buf - u_char buffer to be hashed * buf_len - integer length of buf data * MAC_len - length of the passed MAC buffer size. * * OUT: * MAC - pre-malloced space to store hash output. * MAC_len - length of MAC output to the MAC buffer. * * Returns: * SNMPERR_SUCCESS Success. * SNMP_SC_GENERAL_FAILURE Any error. */intsc_hash(const oid * hashtype, size_t hashtypelen, u_char * buf, size_t buf_len, u_char * MAC, size_t * MAC_len)#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL){#ifdef USE_OPENSSL int rval = SNMPERR_SUCCESS; EVP_MD *hash(void); HMAC_CTX *c = NULL;#endif DEBUGTRACE; if (hashtype == NULL || hashtypelen < 0 || buf == NULL || buf_len < 0 || MAC == NULL || MAC_len == NULL || (int) (*MAC_len) < sc_get_properlength(hashtype, hashtypelen)) return (SNMPERR_GENERR);#ifdef USE_OPENSSL /* * Determine transform type. */ c = malloc(sizeof(HMAC_CTX)); if (c == NULL) return (SNMPERR_GENERR); if (ISTRANSFORM(hashtype, HMACMD5Auth)) { EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_md5()); } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_sha1()); } else { return (SNMPERR_GENERR); } EVP_DigestUpdate(&c->md_ctx, buf, buf_len); EVP_DigestFinal(&(c->md_ctx), MAC, MAC_len); free(c); return (rval);#else /* USE_INTERNAL_MD5 */ if (MDchecksum(buf, buf_len, MAC, *MAC_len)) { return SNMPERR_GENERR; } if (*MAC_len > 16) *MAC_len = 16; return SNMPERR_SUCCESS;#endif /* USE_OPENSSL */}#else /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */_SCAPI_NOT_CONFIGURED#endif /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) *//*******************************************************************-o-****** * sc_check_keyed_hash * * Parameters: * authtype Transform type of authentication hash. * *key Key bits in a string of bytes. * keylen Length of key in bytes. * *message Message for which to check the hash. * msglen Length of message. * *MAC Given hash. * maclen Length of given hash; indicates truncation if it is * shorter than the normal size of output for * given hash transform. * Returns: * SNMPERR_SUCCESS Success. * SNMP_SC_GENERAL_FAILURE Any error * * * Check the hash given in MAC against the hash of message. If the length * of MAC is less than the length of the transform hash output, only maclen * bytes are compared. The length of MAC cannot be greater than the * length of the hash transform output. */intsc_check_keyed_hash(const oid * authtype, size_t authtypelen, u_char * key, u_int keylen, u_char * message, u_int msglen, u_char * MAC, u_int maclen)#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL){ int rval = SNMPERR_SUCCESS; size_t buf_len = SNMP_MAXBUF_SMALL; u_char buf[SNMP_MAXBUF_SMALL]; DEBUGTRACE;#ifdef SNMP_TESTING_CODE { int i; DEBUGMSG(("scapi", "sc_check_keyed_hash(): key=0x")); for (i = 0; i < keylen; i++) DEBUGMSG(("scapi", "%02x", key[i] & 0xff)); DEBUGMSG(("scapi", " (%d)\n", keylen)); }#endif /* SNMP_TESTING_CODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -