static struct scache_entry * find_or_add(const char *name) { int hash_index; struct scache_entry *ptr; ptr = scache_hash[hash_index = sc_hash(name)]; for (; ptr; ptr = ptr->next) { if(!irccmp(ptr->name, name)) return ptr; } ptr = (struct scache_entry *) rb_malloc(sizeof(struct scache_entry)); s_assert(0 != ptr); rb_strlcpy(ptr->name, name, sizeof(ptr->name)); ptr->info[0] = '\0'; ptr->flags = 0; ptr->known_since = rb_current_time(); ptr->last_connect = 0; ptr->last_split = 0; ptr->next = scache_hash[hash_index]; scache_hash[hash_index] = ptr; return ptr; }
/*******************************************************************-o-****** * hash_engineID * * Parameters: * *engineID * engineID_len * * Returns: * >0 etimelist index for this engineID. * SNMPERR_GENERR Error. * * * Use a cheap hash to build an index into the etimelist. Method is * to hash the engineID, then split the hash into u_int's and add them up * and modulo the size of the list. * */ int hash_engineID (const u_char * engineID, u_int engineID_len) { int rval = SNMPERR_GENERR; size_t buf_len = SNMP_MAXBUF; u_int additive = 0; u_char *bufp, buf[SNMP_MAXBUF]; void *context = NULL; /* * Sanity check. */ if (!engineID || (engineID_len <= 0)) { QUITFUN (SNMPERR_GENERR, hash_engineID_quit); } /* * Hash engineID into a list index. */ #ifndef NETSNMP_DISABLE_MD5 rval = sc_hash (usmHMACMD5AuthProtocol, sizeof (usmHMACMD5AuthProtocol) / sizeof (oid), engineID, engineID_len, buf, &buf_len); #else rval = sc_hash (usmHMACSHA1AuthProtocol, sizeof (usmHMACSHA1AuthProtocol) / sizeof (oid), engineID, engineID_len, buf, &buf_len); #endif QUITFUN (rval, hash_engineID_quit); for (bufp = buf; (bufp - buf) < (int) buf_len; bufp += 4) { additive += (u_int) * bufp; } hash_engineID_quit: SNMP_FREE (context); memset (buf, 0, SNMP_MAXBUF); return (rval < 0) ? rval : (int) (additive % ETIMELIST_SIZE); } /* end hash_engineID() */
const char * find_or_add(const char *name) { int hash_index; SCACHE *ptr; ptr = scache_hash[hash_index = sc_hash(name)]; for (; ptr; ptr = ptr->next) { if(!irccmp(ptr->name, name)) return (ptr->name); } ptr = (SCACHE *) MyMalloc(sizeof(SCACHE)); s_assert(0 != ptr); strlcpy(ptr->name, name, sizeof(ptr->name)); ptr->next = scache_hash[hash_index]; scache_hash[hash_index] = ptr; return ptr->name; }
_KEYTOOLS_NOT_AVAILABLE #endif /* internal or openssl */ /*******************************************************************-o-****** * decode_keychange * * Parameters: * *hashtype MIB OID of the hash transform to use. * hashtype_len Length of the hash transform MIB OID. * *oldkey Old key that is used to encode the new key. * oldkey_len Length of oldkey in bytes. * *kcstring Encoded KeyString buffer containing the new key. * kcstring_len Length of kcstring in bytes. * *newkey Buffer to hold the extracted new key. * *newkey_len Length of newkey in bytes. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errors. * * * Decodes a string of bits encoded according to the KeyChange TC described * in RFC 2274, Section 5. The new key is extracted from *kcstring with * the aid of the old key. * * Upon successful return, *newkey_len contains the length of the new key. * * * ASSUMES Old key is exactly 1/2 the length of the KeyChange buffer, * although this length may be less than the hash transform * output. Thus the new key length will be equal to the old * key length. */ /* XXX: if the newkey is not long enough, it should be freed and remalloced */ int decode_keychange( oid *hashtype, u_int hashtype_len, u_char *oldkey, size_t oldkey_len, u_char *kcstring, size_t kcstring_len, u_char *newkey, size_t *newkey_len) #if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) { int rval = SNMPERR_SUCCESS; size_t properlength = 0; u_int nbytes = 0; u_char *bufp, tmp_buf[SNMP_MAXBUF]; size_t tmp_buf_len = SNMP_MAXBUF; void *context = NULL; u_char *tmpbuf = NULL; /* * Sanity check. */ if ( !hashtype || !oldkey || !kcstring || !newkey || !newkey_len || (oldkey_len<=0) || (kcstring_len<=0) || (*newkey_len<=0) || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) { QUITFUN(SNMPERR_GENERR, decode_keychange_quit); } /* * Setup for the transform type. */ properlength = sc_get_properlength(hashtype, hashtype_len); if (properlength == SNMPERR_GENERR) QUITFUN(SNMPERR_GENERR, decode_keychange_quit); if ( ((oldkey_len*2) != kcstring_len) || (*newkey_len < oldkey_len) ) { QUITFUN(SNMPERR_GENERR, decode_keychange_quit); } properlength = oldkey_len; *newkey_len = properlength; /* * Use the old key and the given KeyChange TC string to recover * the new key: * . Hash (oldkey | random_bytes) (into newkey), * . XOR hash and encoded (second) half of kcstring (into newkey). */ tmpbuf = (u_char *)malloc(properlength*2); if (tmpbuf) { memcpy(tmpbuf, oldkey, properlength); memcpy(tmpbuf+properlength, kcstring, properlength); rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2, tmp_buf, &tmp_buf_len); QUITFUN(rval, decode_keychange_quit); memcpy(newkey, tmp_buf, properlength); bufp = kcstring+properlength; nbytes = 0; while ((int)(nbytes++) < properlength) { *newkey++ = *newkey ^ *bufp++; } } decode_keychange_quit: if (rval != SNMPERR_SUCCESS) { memset(newkey, 0, properlength); } memset(tmp_buf, 0, SNMP_MAXBUF); SNMP_FREE(context); if (tmpbuf != NULL) SNMP_FREE(tmpbuf); return rval; } /* end decode_keychange() */
_KEYTOOLS_NOT_AVAILABLE #endif /* internal or openssl */ /*******************************************************************-o-****** * encode_keychange * * Parameters: * *hashtype MIB OID for the hash transform type. * hashtype_len Length of the MIB OID hash transform type. * *oldkey Old key that is used to encodes the new key. * oldkey_len Length of oldkey in bytes. * *newkey New key that is encoded using the old key. * newkey_len Length of new key in bytes. * *kcstring Buffer to contain the KeyChange TC string. * *kcstring_len Length of kcstring buffer. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errors. * * * Uses oldkey and acquired random bytes to encode newkey into kcstring * according to the rules of the KeyChange TC described in RFC 2274, Section 5. * * Upon successful return, *kcstring_len contains the length of the * encoded string. * * ASSUMES Old and new key are always equal to each other, although * this may be less than the transform type hash output * output length (eg, using KeyChange for a DESPriv key when * the user also uses SHA1Auth). This also implies that the * hash placed in the second 1/2 of the key change string * will be truncated before the XOR'ing when the hash output is * larger than that 1/2 of the key change string. * * *kcstring_len will be returned as exactly twice that same * length though the input buffer may be larger. * * XXX FIX: Does not handle varibable length keys. * XXX FIX: Does not handle keys larger than the hash algorithm used. */ int encode_keychange( oid *hashtype, u_int hashtype_len, u_char *oldkey, size_t oldkey_len, u_char *newkey, size_t newkey_len, u_char *kcstring, size_t *kcstring_len) #if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) { int rval = SNMPERR_SUCCESS; size_t properlength; size_t nbytes = 0; u_char *tmpbuf = NULL; void *context = NULL; /* * Sanity check. */ if ( !hashtype || !oldkey || !newkey || !kcstring || !kcstring_len || (oldkey_len<=0) || (newkey_len<=0) || (*kcstring_len<=0) || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) { QUITFUN(SNMPERR_GENERR, encode_keychange_quit); } /* * Setup for the transform type. */ properlength = sc_get_properlength(hashtype, hashtype_len); if (properlength == SNMPERR_GENERR) QUITFUN(SNMPERR_GENERR, encode_keychange_quit); if ( (oldkey_len != newkey_len) || (*kcstring_len < (2*oldkey_len)) ) { QUITFUN(SNMPERR_GENERR, encode_keychange_quit); } properlength = SNMP_MIN((int)oldkey_len, properlength); /* * Use the old key and some random bytes to encode the new key * in the KeyChange TC format: * . Get random bytes (store in first half of kcstring), * . Hash (oldkey | random_bytes) (into second half of kcstring), * . XOR hash and newkey (into second half of kcstring). * * Getting the wrong number of random bytes is considered an error. */ nbytes = properlength; #if defined(SNMP_TESTING_CODE) && defined(RANDOMZEROS) memset(kcstring, 0, nbytes); DEBUGMSG(("encode_keychange", "** Using all zero bits for \"random\" delta of )" "the keychange string! **\n")); #else /* !SNMP_TESTING_CODE */ rval = sc_random(kcstring, &nbytes); QUITFUN(rval, encode_keychange_quit); if ((int)nbytes != properlength) { QUITFUN(SNMPERR_GENERR, encode_keychange_quit); } #endif /* !SNMP_TESTING_CODE */ tmpbuf = (u_char *)malloc(properlength*2); if (tmpbuf) { memcpy(tmpbuf, oldkey, properlength); memcpy(tmpbuf+properlength, kcstring, properlength); *kcstring_len -= properlength; rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2, kcstring+properlength, kcstring_len); QUITFUN(rval, encode_keychange_quit); *kcstring_len = (properlength*2); kcstring += properlength; nbytes = 0; while ((int)(nbytes++) < properlength) { *kcstring++ = *kcstring ^ *newkey++; } } encode_keychange_quit: if (rval != SNMPERR_SUCCESS) memset(kcstring, 0, *kcstring_len); SNMP_FREE(tmpbuf); SNMP_FREE(context); return rval; } /* end encode_keychange() */
_KEYTOOLS_NOT_AVAILABLE #endif /* internal or openssl */ /*******************************************************************-o-****** * generate_kul * * Parameters: * *hashtype * hashtype_len * *engineID * engineID_len * *Ku Master key for a given user. * ku_len Length of Ku in bytes. * *Kul Localized key for a given user at engineID. * *kul_len Length of Kul buffer (IN); Length of Kul key (OUT). * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errors. * * * Ku MUST be the proper length (currently fixed) for the given hashtype. * * Upon successful return, Kul contains the localized form of Ku at * engineID, and the length of the key is stored in kul_len. * * The localized key method is defined in RFC2274, Sections 2.6 and A.2, and * originally documented in: * U. Blumenthal, N. C. Hien, B. Wijnen, * "Key Derivation for Network Management Applications", * IEEE Network Magazine, April/May issue, 1997. * * * ASSUMES SNMP_MAXBUF >= sizeof(Ku + engineID + Ku). * * NOTE Localized keys for privacy transforms are generated via * the authentication transform held by the same usmUser. * * XXX An engineID of any length is accepted, even if larger than * what is spec'ed for the textual convention. */ int generate_kul( oid *hashtype, u_int hashtype_len, u_char *engineID, size_t engineID_len, u_char *Ku, size_t ku_len, u_char *Kul, size_t *kul_len) #if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) { int rval = SNMPERR_SUCCESS; u_int nbytes = 0; size_t properlength; u_char buf[SNMP_MAXBUF]; void *context = NULL; #ifdef SNMP_TESTING_CODE int i; #endif /* * Sanity check. */ if ( !hashtype || !engineID || !Ku || !Kul || !kul_len || (engineID_len<=0) || (ku_len<=0) || (*kul_len<=0) || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) { QUITFUN(SNMPERR_GENERR, generate_kul_quit); } properlength = sc_get_properlength(hashtype, hashtype_len); if (properlength == SNMPERR_GENERR) QUITFUN(SNMPERR_GENERR, generate_kul_quit); if (((int)*kul_len < properlength) || ((int)ku_len < properlength) ) { QUITFUN(SNMPERR_GENERR, generate_kul_quit); } /* * Concatenate Ku and engineID properly, then hash the result. * Store it in Kul. */ nbytes = 0; memcpy(buf, Ku, properlength); nbytes += properlength; memcpy(buf+nbytes, engineID, engineID_len); nbytes += engineID_len; memcpy(buf+nbytes, Ku, properlength); nbytes += properlength; rval = sc_hash(hashtype, hashtype_len, buf, nbytes, Kul, kul_len); #ifdef SNMP_TESTING_CODE DEBUGMSGTL(("generate_kul", "generating Kul (from Ku): ")); for(i=0; i < *kul_len; i++) DEBUGMSG(("generate_kul", "%02x",Kul[i])); DEBUGMSG(("generate_kul", "keytools\n")); #endif /* SNMP_TESTING_CODE */ QUITFUN(rval, generate_kul_quit); generate_kul_quit: SNMP_FREE(context); return rval; } /* end generate_kul() */