219 lines
5.8 KiB
C
219 lines
5.8 KiB
C
/*
|
|
* security service wrapper to support pluggable security models
|
|
*
|
|
* Portions of this file are subject to the following copyright(s). See
|
|
* the Net-SNMP's COPYING file for more details and other copyrights
|
|
* that may apply:
|
|
*
|
|
* 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 <net-snmp/net-snmp-config.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#if HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#if HAVE_STRING_H
|
|
#include <string.h>
|
|
#else
|
|
#include <strings.h>
|
|
#endif
|
|
#if HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#if HAVE_DMALLOC_H
|
|
#include <dmalloc.h>
|
|
#endif
|
|
|
|
#include <net-snmp/types.h>
|
|
#include <net-snmp/output_api.h>
|
|
#include <net-snmp/config_api.h>
|
|
#include <net-snmp/utilities.h>
|
|
|
|
#include <net-snmp/library/snmp_api.h>
|
|
#include <net-snmp/library/snmp_enum.h>
|
|
#include <net-snmp/library/callback.h>
|
|
#include <net-snmp/library/snmp_secmod.h>
|
|
#include <net-snmp/library/snmpv3-security-includes.h>
|
|
|
|
#include <net-snmp/net-snmp-features.h>
|
|
|
|
static struct snmp_secmod_list *registered_services = NULL;
|
|
|
|
static SNMPCallback set_default_secmod;
|
|
|
|
void
|
|
init_secmod(void)
|
|
{
|
|
snmp_register_callback(SNMP_CALLBACK_LIBRARY,
|
|
SNMP_CALLBACK_SESSION_INIT, set_default_secmod,
|
|
NULL);
|
|
|
|
netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityModel",
|
|
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL);
|
|
/*
|
|
* this file is generated by configure for all the stuff we're using
|
|
*/
|
|
#include "snmpsm_init.h"
|
|
}
|
|
|
|
void
|
|
shutdown_secmod(void)
|
|
{
|
|
#include "snmpsm_shutdown.h"
|
|
}
|
|
|
|
int
|
|
register_sec_mod(int secmod, const char *modname,
|
|
struct snmp_secmod_def *newdef)
|
|
{
|
|
int result = 0;
|
|
struct snmp_secmod_list *sptr;
|
|
char *othername, *modname2 = NULL;
|
|
|
|
for (sptr = registered_services; sptr; sptr = sptr->next) {
|
|
if (sptr->securityModel == secmod) {
|
|
return SNMPERR_GENERR;
|
|
}
|
|
}
|
|
sptr = SNMP_MALLOC_STRUCT(snmp_secmod_list);
|
|
if (sptr == NULL)
|
|
return SNMPERR_MALLOC;
|
|
sptr->secDef = newdef;
|
|
sptr->securityModel = secmod;
|
|
sptr->next = registered_services;
|
|
registered_services = sptr;
|
|
modname2 = strdup(modname);
|
|
if (!modname2)
|
|
result = SE_NOMEM;
|
|
else
|
|
result = se_add_pair_to_slist("snmp_secmods", modname2, secmod);
|
|
if (result != SE_OK) {
|
|
switch (result) {
|
|
case SE_NOMEM:
|
|
snmp_log(LOG_CRIT, "snmp_secmod: no memory\n");
|
|
break;
|
|
|
|
case SE_ALREADY_THERE:
|
|
othername = se_find_label_in_slist("snmp_secmods", secmod);
|
|
if (strcmp(othername, modname) != 0) {
|
|
snmp_log(LOG_ERR,
|
|
"snmp_secmod: two security modules %s and %s registered with the same security number\n",
|
|
modname, othername);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
snmp_log(LOG_ERR,
|
|
"snmp_secmod: unknown error trying to register a new security module\n");
|
|
break;
|
|
}
|
|
return SNMPERR_GENERR;
|
|
}
|
|
return SNMPERR_SUCCESS;
|
|
}
|
|
|
|
netsnmp_feature_child_of(unregister_sec_mod, netsnmp_unused)
|
|
#ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD
|
|
int
|
|
unregister_sec_mod(int secmod)
|
|
{
|
|
struct snmp_secmod_list *sptr, *lptr;
|
|
|
|
for (sptr = registered_services, lptr = NULL; sptr;
|
|
lptr = sptr, sptr = sptr->next) {
|
|
if (sptr->securityModel == secmod) {
|
|
if ( lptr )
|
|
lptr->next = sptr->next;
|
|
else
|
|
registered_services = sptr->next;
|
|
SNMP_FREE(sptr->secDef);
|
|
SNMP_FREE(sptr);
|
|
return SNMPERR_SUCCESS;
|
|
}
|
|
}
|
|
/*
|
|
* not registered
|
|
*/
|
|
return SNMPERR_GENERR;
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD */
|
|
|
|
void
|
|
clear_sec_mod(void)
|
|
{
|
|
struct snmp_secmod_list *tmp = registered_services, *next = NULL;
|
|
|
|
while (tmp != NULL) {
|
|
next = tmp->next;
|
|
SNMP_FREE(tmp->secDef);
|
|
SNMP_FREE(tmp);
|
|
tmp = next;
|
|
}
|
|
registered_services = NULL;
|
|
}
|
|
|
|
|
|
struct snmp_secmod_def *
|
|
find_sec_mod(int secmod)
|
|
{
|
|
struct snmp_secmod_list *sptr;
|
|
|
|
for (sptr = registered_services; sptr; sptr = sptr->next) {
|
|
if (sptr->securityModel == secmod) {
|
|
return sptr->secDef;
|
|
}
|
|
}
|
|
/*
|
|
* not registered
|
|
*/
|
|
return NULL;
|
|
}
|
|
|
|
/* try to pick a reasonable security module default based on what was
|
|
compiled into the net-snmp package */
|
|
#ifdef USM_SEC_MODEL_NUMBER
|
|
#define NETSNMP_SECMOD_DEFAULT_MODEL USM_SEC_MODEL_NUMBER
|
|
#elif defined(TSM_SEC_MODEL_NUMBER)
|
|
#define NETSNMP_SECMOD_DEFAULT_MODEL TSM_SEC_MODEL_NUMBER
|
|
#elif defined(KSM_SEC_MODEL_NUMBER)
|
|
#define NETSNMP_SECMOD_DEFAULT_MODEL KSM_SEC_MODEL_NUMBER
|
|
#else
|
|
/* else we give up and leave it blank */
|
|
#define NETSNMP_SECMOD_DEFAULT_MODEL -1
|
|
#endif
|
|
|
|
static int
|
|
set_default_secmod(int major, int minor, void *serverarg, void *clientarg)
|
|
{
|
|
netsnmp_session *sess = (netsnmp_session *) serverarg;
|
|
char *cptr;
|
|
int model;
|
|
|
|
if (!sess)
|
|
return SNMPERR_GENERR;
|
|
if (sess->securityModel == SNMP_DEFAULT_SECMODEL) {
|
|
if ((cptr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|
NETSNMP_DS_LIB_SECMODEL)) != NULL) {
|
|
if ((model = se_find_value_in_slist("snmp_secmods", cptr))
|
|
!= SE_DNE) {
|
|
sess->securityModel = model;
|
|
} else {
|
|
snmp_log(LOG_ERR,
|
|
"unknown security model name: %s. Forcing USM instead.\n",
|
|
cptr);
|
|
sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL;
|
|
return SNMPERR_GENERR;
|
|
}
|
|
} else {
|
|
sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL;
|
|
}
|
|
}
|
|
return SNMPERR_SUCCESS;
|
|
}
|