diff options
Diffstat (limited to 'apps/snmptrapd_auth.c')
-rw-r--r-- | apps/snmptrapd_auth.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/apps/snmptrapd_auth.c b/apps/snmptrapd_auth.c new file mode 100644 index 0000000..be21e5e --- /dev/null +++ b/apps/snmptrapd_auth.c @@ -0,0 +1,182 @@ +/* + * snmptrapd_auth.c - authorize notifications for further processing + * + */ +#include <net-snmp/net-snmp-config.h> + +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include "snmptrapd_handlers.h" +#include "snmptrapd_auth.h" +#include "snmptrapd_ds.h" + +#include <net-snmp/agent/agent_module_config.h> +#include <net-snmp/agent/mib_module_config.h> + +#ifdef USING_MIBII_VACM_CONF_MODULE +#include "mibII/vacm_conf.h" +#endif + +#include <net-snmp/agent/agent_trap.h> + +/** + * initializes the snmptrapd authorization code registering needed + * handlers and config parsers. + */ +void +init_netsnmp_trapd_auth(void) +{ + /* register our function as a authorization handler */ + netsnmp_trapd_handler *traph; + traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_AUTH_HANDLER, + netsnmp_trapd_auth); + traph->authtypes = TRAP_AUTH_NONE; + +#ifdef USING_MIBII_VACM_CONF_MODULE + /* register our configuration tokens for VACM configs */ + init_vacm_config_tokens(); +#endif + + /* register a config token for turning off the authorization entirely */ + netsnmp_ds_register_config(ASN_BOOLEAN, "snmptrapd", "disableAuthorization", + NETSNMP_DS_APPLICATION_ID, + NETSNMP_DS_APP_NO_AUTHORIZATION); +} + +/* XXX: store somewhere in the PDU instead */ +static int lastlookup; + +/** + * Authorizes incoming notifications for further processing + */ +int +netsnmp_trapd_auth(netsnmp_pdu *pdu, + netsnmp_transport *transport, + netsnmp_trapd_handler *handler) +{ + int ret = 0; + oid snmptrapoid[] = { 1,3,6,1,6,3,1,1,4,1,0 }; + size_t snmptrapoid_len = OID_LENGTH(snmptrapoid); + int i; + netsnmp_pdu *newpdu = pdu; + netsnmp_variable_list *var; + + /* check to see if authorization was not disabled */ + if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, + NETSNMP_DS_APP_NO_AUTHORIZATION)) { + DEBUGMSGTL(("snmptrapd:auth", + "authorization turned off: not checking\n")); + return NETSNMPTRAPD_HANDLER_OK; + } + + /* bail early if called illegally */ + if (!pdu || !transport || !handler) + return NETSNMPTRAPD_HANDLER_FINISH; + + /* convert to v2 so we can check it in a consistent manner */ +#ifndef NETSNMP_DISABLE_SNMPV1 + if (pdu->version == SNMP_VERSION_1) { + newpdu = convert_v1pdu_to_v2(pdu); + if (!newpdu) { + snmp_log(LOG_ERR, "Failed to duplicate incoming PDU. Refusing to authorize.\n"); + return NETSNMPTRAPD_HANDLER_FINISH; + } + } +#endif + + if (!vacm_is_configured()) { +#ifndef NETSNMP_DISABLE_SNMPV1 + if (newpdu != pdu) + snmp_free_pdu(newpdu); +#endif + snmp_log(LOG_WARNING, "No access configuration - dropping trap.\n"); + return NETSNMPTRAPD_HANDLER_FINISH; + } + + /* loop through each variable and find the snmpTrapOID.0 var + indicating what the trap is we're staring at. */ + for (var = newpdu->variables; var != NULL; var = var->next_variable) { + if (netsnmp_oid_equals(var->name, var->name_length, + snmptrapoid, snmptrapoid_len) == 0) + break; + } + + /* make sure we can continue: we found the snmpTrapOID.0 and its an oid */ + if (!var || var->type != ASN_OBJECT_ID) { + snmp_log(LOG_ERR, "Can't determine trap identifier; refusing to authorize it\n"); +#ifndef NETSNMP_DISABLE_SNMPV1 + if (newpdu != pdu) + snmp_free_pdu(newpdu); +#endif + return NETSNMPTRAPD_HANDLER_FINISH; + } + +#ifdef USING_MIBII_VACM_CONF_MODULE + /* check the pdu against each typo of VACM access we may want to + check up on later. We cache the results for future lookup on + each call to netsnmp_trapd_check_auth */ + for(i = 0; i < VACM_MAX_VIEWS; i++) { + /* pass the PDU to the VACM routine for handling authorization */ + DEBUGMSGTL(("snmptrapd:auth", "Calling VACM for checking phase %d:%s\n", + i, se_find_label_in_slist(VACM_VIEW_ENUM_NAME, i))); + if (vacm_check_view_contents(newpdu, var->val.objid, + var->val_len/sizeof(oid), 0, i, + VACM_CHECK_VIEW_CONTENTS_DNE_CONTEXT_OK) + == VACM_SUCCESS) { + DEBUGMSGTL(("snmptrapd:auth", " result: authorized\n")); + ret |= 1 << i; + } else { + DEBUGMSGTL(("snmptrapd:auth", " result: not authorized\n")); + } + } + DEBUGMSGTL(("snmptrapd:auth", "Final bitmask auth: %x\n", ret)); +#endif + + if (ret) { + /* we have policy to at least do "something". Remember and continue. */ + lastlookup = ret; +#ifndef NETSNMP_DISABLE_SNMPV1 + if (newpdu != pdu) + snmp_free_pdu(newpdu); +#endif + return NETSNMPTRAPD_HANDLER_OK; + } + + /* No policy was met, so we drop the PDU from further processing */ + DEBUGMSGTL(("snmptrapd:auth", "Dropping unauthorized message\n")); +#ifndef NETSNMP_DISABLE_SNMPV1 + if (newpdu != pdu) + snmp_free_pdu(newpdu); +#endif + return NETSNMPTRAPD_HANDLER_FINISH; +} + +/** + * Checks to see if the pdu is authorized for a set of given action types. + * @returns 1 if authorized, 0 if not. + */ +int +netsnmp_trapd_check_auth(int authtypes) +{ + if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, + NETSNMP_DS_APP_NO_AUTHORIZATION)) { + DEBUGMSGTL(("snmptrapd:auth", "authorization turned off\n")); + return 1; + } + + DEBUGMSGTL(("snmptrapd:auth", + "Comparing auth types: result=%d, request=%d, result=%d\n", + lastlookup, authtypes, + ((authtypes & lastlookup) == authtypes))); + return ((authtypes & lastlookup) == authtypes); +} + |