⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snmpksm.c

📁 snmp up 2
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * snmpksm.c * * This code implements the Kerberos Security Model (KSM) for SNMP. * * Security number - 2066432 */#include <net-snmp/net-snmp-config.h>#include <sys/types.h>#if HAVE_WINSOCK_H#include <winsock.h>#endif#include <stdio.h>#ifdef HAVE_STDLIB_H#include <stdlib.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#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#include <errno.h>#if HAVE_DMALLOC_H#include <dmalloc.h>#endif#include <krb5.h>#include <com_err.h>#include <net-snmp/output_api.h>#include <net-snmp/config_api.h>#include <net-snmp/utilities.h>#include <net-snmp/library/asn1.h>#include <net-snmp/library/snmp_api.h>#include <net-snmp/library/callback.h>#include <net-snmp/library/keytools.h>#include <net-snmp/library/snmpv3.h>#include <net-snmp/library/lcd_time.h>#include <net-snmp/library/scapi.h>#include <net-snmp/library/callback.h>#include <net-snmp/library/snmp_secmod.h>#include <net-snmp/library/snmpksm.h>static krb5_context kcontext = NULL;static krb5_rcache rcache = NULL;static int      ksm_session_init(netsnmp_session *);static void     ksm_free_state_ref(void *);static int      ksm_free_pdu(netsnmp_pdu *);static int      ksm_clone_pdu(netsnmp_pdu *, netsnmp_pdu *);static int      ksm_insert_cache(long, krb5_auth_context, u_char *,                                 size_t);static void     ksm_decrement_ref_count(long);static void     ksm_increment_ref_count(long);static struct ksm_cache_entry *ksm_get_cache(long);#define HASHSIZE	64/* * Our information stored for the response PDU. */struct ksm_secStateRef {    krb5_auth_context auth_context;    krb5_cksumtype  cksumtype;};/* * A KSM outgoing pdu cache entry */struct ksm_cache_entry {    long            msgid;    int             refcount;    krb5_auth_context auth_context;    u_char         *secName;    size_t          secNameLen;    struct ksm_cache_entry *next;};/* * Poor man's hash table */static struct ksm_cache_entry *ksm_hash_table[HASHSIZE];/* * Initialize all of the state required for Kerberos (right now, just call * krb5_init_context). */voidinit_ksm(void){    krb5_error_code retval;    struct snmp_secmod_def *def;    int             i;    if (kcontext == NULL) {        retval = krb5_init_context(&kcontext);        if (retval) {            DEBUGMSGTL(("ksm", "krb5_init_context failed (%s), not "                        "registering KSM\n", error_message(retval)));            return;        }    }    for (i = 0; i < HASHSIZE; i++)        ksm_hash_table[i] = NULL;    def = SNMP_MALLOC_STRUCT(snmp_secmod_def);    if (!def) {        DEBUGMSGTL(("ksm", "Unable to malloc snmp_secmod struct, not "                    "registering KSM\n"));        return;    }    def->encode_reverse = ksm_rgenerate_out_msg;    def->decode = ksm_process_in_msg;    def->session_open = ksm_session_init;    def->pdu_free_state_ref = ksm_free_state_ref;    def->pdu_free = ksm_free_pdu;    def->pdu_clone = ksm_clone_pdu;    register_sec_mod(2066432, "ksm", def);}/* * These routines implement a simple cache for information we need to * process responses.  When we send out a request, it contains an AP_REQ; * we get back an AP_REP, and we need the authorization context from the * AP_REQ to decrypt the AP_REP.  But because right now there's nothing * that gets preserved across calls to rgenerate_out_msg to process_in_msg, * we cache these internally based on the message ID (we also cache the * passed-in security name, for reasons that are mostly stupid). */static intksm_insert_cache(long msgid, krb5_auth_context auth_context,                 u_char * secName, size_t secNameLen){    struct ksm_cache_entry *entry;    int             bucket;    int             retval;    entry = SNMP_MALLOC_STRUCT(ksm_cache_entry);    if (!entry)        return SNMPERR_MALLOC;    entry->msgid = msgid;    entry->auth_context = auth_context;    entry->refcount = 1;    retval = memdup(&entry->secName, secName, secNameLen);    if (retval != SNMPERR_SUCCESS) {        free(entry);        return retval;    }    entry->secNameLen = secNameLen;    bucket = msgid % HASHSIZE;    entry->next = ksm_hash_table[bucket];    ksm_hash_table[bucket] = entry;    return SNMPERR_SUCCESS;}static struct ksm_cache_entry *ksm_get_cache(long msgid){    struct ksm_cache_entry *entry;    int             bucket;    bucket = msgid % HASHSIZE;    for (entry = ksm_hash_table[bucket]; entry != NULL;         entry = entry->next)        if (entry->msgid == msgid)            return entry;    return NULL;}static voidksm_decrement_ref_count(long msgid){    struct ksm_cache_entry *entry, *entry1;    int             bucket;    bucket = msgid % HASHSIZE;    if (ksm_hash_table[bucket] && ksm_hash_table[bucket]->msgid == msgid) {        entry = ksm_hash_table[bucket];        /*         * If the reference count is zero, then free it         */        if (--entry->refcount <= 0) {            DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n", msgid));            krb5_auth_con_free(kcontext, entry->auth_context);            free(entry->secName);            ksm_hash_table[bucket] = entry->next;            free(entry);        }        return;    } else if (ksm_hash_table[bucket])        for (entry1 = ksm_hash_table[bucket], entry = entry1->next;             entry != NULL; entry1 = entry, entry = entry->next)            if (entry->msgid == msgid) {                if (--entry->refcount <= 0) {                    DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n",                                msgid));                    krb5_auth_con_free(kcontext, entry->auth_context);                    free(entry->secName);                    entry1->next = entry->next;                    free(entry);                }                return;            }    DEBUGMSGTL(("ksm",                "KSM: Unable to decrement cache entry for msgid %ld.\n",                msgid));}static voidksm_increment_ref_count(long msgid){    struct ksm_cache_entry *entry = ksm_get_cache(msgid);    if (!entry) {        DEBUGMSGTL(("ksm", "Unable to find cache entry for msgid %ld "                    "for increment\n", msgid));        return;    }    entry->refcount++;}/* * Initialize specific session information (right now, just set up things to * not do an engineID probe) */static intksm_session_init(netsnmp_session * sess){    DEBUGMSGTL(("ksm",                "KSM: Reached our session initialization callback\n"));    sess->flags |= SNMP_FLAGS_DONT_PROBE;    return SNMPERR_SUCCESS;}/* * Free our state information (this is only done on the agent side) */static voidksm_free_state_ref(void *ptr){    struct ksm_secStateRef *ref = (struct ksm_secStateRef *) ptr;    DEBUGMSGTL(("ksm", "KSM: Freeing state reference\n"));    krb5_auth_con_free(kcontext, ref->auth_context);    free(ref);}/* * This is called when the PDU is freed; this will decrement reference counts * for entries in our state cache. */static intksm_free_pdu(netsnmp_pdu *pdu){    ksm_decrement_ref_count(pdu->msgid);    DEBUGMSGTL(("ksm", "Decrementing cache entry for PDU msgid %ld\n",                pdu->msgid));    return SNMPERR_SUCCESS;}/* * This is called when a PDU is cloned (to increase reference counts) */static intksm_clone_pdu(netsnmp_pdu *pdu, netsnmp_pdu *pdu2){    ksm_increment_ref_count(pdu->msgid);    DEBUGMSGTL(("ksm", "Incrementing cache entry for PDU msgid %ld\n",                pdu->msgid));    return SNMPERR_SUCCESS;}/**************************************************************************** * * ksm_generate_out_msg * * Parameters: *	(See list below...) * * Returns: *	SNMPERR_GENERIC                        On success. *	SNMPERR_KRB5 *	... and others * * * Generate an outgoing message. * ****************************************************************************/intksm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms){    krb5_auth_context auth_context = NULL;    krb5_error_code retcode;    krb5_ccache     cc = NULL;    int             retval = SNMPERR_SUCCESS;    krb5_data       outdata, ivector;    krb5_keyblock  *subkey = NULL;#ifdef MIT_NEW_CRYPTO    krb5_data       input;    krb5_enc_data   output;#else                           /* MIT_NEW_CRYPTO */    krb5_encrypt_block eblock;#endif                          /* MIT_NEW_CRYPTO */    size_t          blocksize, encrypted_length;    unsigned char  *encrypted_data = NULL;    int             zero = 0, i;    u_char         *cksum_pointer, *endp = *parms->wholeMsg;    krb5_cksumtype  cksumtype = CKSUMTYPE_RSA_MD5_DES;    krb5_checksum   pdu_checksum;    u_char         **wholeMsg = parms->wholeMsg;    size_t	   *offset = parms->wholeMsgOffset, seq_offset;    struct ksm_secStateRef *ksm_state = (struct ksm_secStateRef *)        parms->secStateRef;    int rc;    DEBUGMSGTL(("ksm", "Starting KSM processing\n"));    outdata.length = 0;    outdata.data = NULL;    ivector.length = 0;    ivector.data = NULL;    pdu_checksum.contents = NULL;    if (!ksm_state) {        /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -