summaryrefslogtreecommitdiff
path: root/apps/snmptrapd_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/snmptrapd_auth.c')
-rw-r--r--apps/snmptrapd_auth.c182
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);
+}
+