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