/* * snmptrapd_auth.c - authorize notifications for further processing * * Portions of this file are copyrighted by: * Copyright (c) 2016 VMware, Inc. All rights reserved. * Use is subject to license terms specified in the COPYING file * distributed with the Net-SNMP package. * */ #include #if HAVE_SYS_TYPES_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETDB_H #include #endif #include #include "snmptrapd_handlers.h" #include "snmptrapd_auth.h" #include "snmptrapd_ds.h" #include #include #ifdef USING_MIBII_VACM_CONF_MODULE #include "mibII/vacm_conf.h" #endif #include /** * 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); netsnmp_pdu *newpdu = pdu; netsnmp_variable_list *var; #ifdef USING_MIBII_VACM_CONF_MODULE int i; #endif /* 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); }