Blame apps/snmptrapd_auth.c

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