diff options
Diffstat (limited to 'snmplib/snmp_secmod.c')
-rw-r--r-- | snmplib/snmp_secmod.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/snmplib/snmp_secmod.c b/snmplib/snmp_secmod.c new file mode 100644 index 0000000..9e60a42 --- /dev/null +++ b/snmplib/snmp_secmod.c @@ -0,0 +1,206 @@ +/* + * security service wrapper to support pluggable security models + */ + +#include <net-snmp/net-snmp-config.h> +#include <stdio.h> +#include <ctype.h> +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if HAVE_DMALLOC_H +#include <dmalloc.h> +#endif + +#include <net-snmp/types.h> +#include <net-snmp/output_api.h> +#include <net-snmp/config_api.h> +#include <net-snmp/utilities.h> + +#include <net-snmp/library/snmp_api.h> +#include <net-snmp/library/snmp_enum.h> +#include <net-snmp/library/callback.h> +#include <net-snmp/library/snmp_secmod.h> +#include <net-snmp/library/snmpv3-security-includes.h> + +#include <net-snmp/net-snmp-features.h> + +static struct snmp_secmod_list *registered_services = NULL; + +static SNMPCallback set_default_secmod; + +void +init_secmod(void) +{ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, + SNMP_CALLBACK_SESSION_INIT, set_default_secmod, + NULL); + + netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityModel", + NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL); + /* + * this file is generated by configure for all the stuff we're using + */ +#include "snmpsm_init.h" +} + +void +shutdown_secmod(void) +{ + #include "snmpsm_shutdown.h" +} + +int +register_sec_mod(int secmod, const char *modname, + struct snmp_secmod_def *newdef) +{ + int result; + struct snmp_secmod_list *sptr; + char *othername; + + for (sptr = registered_services; sptr; sptr = sptr->next) { + if (sptr->securityModel == secmod) { + return SNMPERR_GENERR; + } + } + sptr = SNMP_MALLOC_STRUCT(snmp_secmod_list); + if (sptr == NULL) + return SNMPERR_MALLOC; + sptr->secDef = newdef; + sptr->securityModel = secmod; + sptr->next = registered_services; + registered_services = sptr; + if ((result = + se_add_pair_to_slist("snmp_secmods", strdup(modname), secmod)) + != SE_OK) { + switch (result) { + case SE_NOMEM: + snmp_log(LOG_CRIT, "snmp_secmod: no memory\n"); + break; + + case SE_ALREADY_THERE: + othername = se_find_label_in_slist("snmp_secmods", secmod); + if (strcmp(othername, modname) != 0) { + snmp_log(LOG_ERR, + "snmp_secmod: two security modules %s and %s registered with the same security number\n", + modname, othername); + } + break; + + default: + snmp_log(LOG_ERR, + "snmp_secmod: unknown error trying to register a new security module\n"); + break; + } + return SNMPERR_GENERR; + } + return SNMPERR_SUCCESS; +} + +netsnmp_feature_child_of(unregister_sec_mod, netsnmp_unused) +#ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD +int +unregister_sec_mod(int secmod) +{ + struct snmp_secmod_list *sptr, *lptr; + + for (sptr = registered_services, lptr = NULL; sptr; + lptr = sptr, sptr = sptr->next) { + if (sptr->securityModel == secmod) { + if ( lptr ) + lptr->next = sptr->next; + else + registered_services = sptr->next; + SNMP_FREE(sptr->secDef); + SNMP_FREE(sptr); + return SNMPERR_SUCCESS; + } + } + /* + * not registered + */ + return SNMPERR_GENERR; +} +#endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD */ + +void +clear_sec_mod(void) +{ + struct snmp_secmod_list *tmp = registered_services, *next = NULL; + + while (tmp != NULL) { + next = tmp->next; + SNMP_FREE(tmp->secDef); + SNMP_FREE(tmp); + tmp = next; + } + registered_services = NULL; +} + + +struct snmp_secmod_def * +find_sec_mod(int secmod) +{ + struct snmp_secmod_list *sptr; + + for (sptr = registered_services; sptr; sptr = sptr->next) { + if (sptr->securityModel == secmod) { + return sptr->secDef; + } + } + /* + * not registered + */ + return NULL; +} + +/* try to pick a reasonable security module default based on what was + compiled into the net-snmp package */ +#ifdef USM_SEC_MODEL_NUMBER +#define NETSNMP_SECMOD_DEFAULT_MODEL USM_SEC_MODEL_NUMBER +#elif defined(TSM_SEC_MODEL_NUMBER) +#define NETSNMP_SECMOD_DEFAULT_MODEL TSM_SEC_MODEL_NUMBER +#elif defined(KSM_SEC_MODEL_NUMBER) +#define NETSNMP_SECMOD_DEFAULT_MODEL KSM_SEC_MODEL_NUMBER +#else +/* else we give up and leave it blank */ +#define NETSNMP_SECMOD_DEFAULT_MODEL -1 +#endif + +static int +set_default_secmod(int major, int minor, void *serverarg, void *clientarg) +{ + netsnmp_session *sess = (netsnmp_session *) serverarg; + char *cptr; + int model; + + if (!sess) + return SNMPERR_GENERR; + if (sess->securityModel == SNMP_DEFAULT_SECMODEL) { + if ((cptr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_SECMODEL)) != NULL) { + if ((model = se_find_value_in_slist("snmp_secmods", cptr)) + != SE_DNE) { + sess->securityModel = model; + } else { + snmp_log(LOG_ERR, + "unknown security model name: %s. Forcing USM instead.\n", + cptr); + sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL; + return SNMPERR_GENERR; + } + } else { + sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL; + } + } + return SNMPERR_SUCCESS; +} |