summaryrefslogtreecommitdiff
path: root/agent/mibgroup/mibII/vacm_conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/mibII/vacm_conf.c')
-rw-r--r--agent/mibgroup/mibII/vacm_conf.c1494
1 files changed, 1494 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/vacm_conf.c b/agent/mibgroup/mibII/vacm_conf.c
new file mode 100644
index 0000000..7e19314
--- /dev/null
+++ b/agent/mibgroup/mibII/vacm_conf.c
@@ -0,0 +1,1494 @@
+/*
+ * SNMPv3 View-based Access Control Model
+ */
+/* 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 © 2003 Sun Microsystems, 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>
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include <net-snmp/agent/agent_callbacks.h>
+#include "vacm_conf.h"
+#include "util_funcs.h"
+
+#ifdef USING_MIBII_SYSORTABLE_MODULE
+#if TIME_WITH_SYS_TIME
+# ifdef WIN32
+# include <sys/timeb.h>
+# else
+# include <sys/time.h>
+# endif
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#include "sysORTable.h"
+#endif
+
+#include "snmpd.h"
+
+/**
+ * Registers the VACM token handlers for inserting rows into the vacm tables.
+ * These tokens will be recognised by both 'snmpd' and 'snmptrapd'.
+ */
+void
+init_vacm_config_tokens(void) {
+ snmpd_register_config_handler("group", vacm_parse_group,
+ vacm_free_group,
+ "name v1|v2c|usm|... security");
+ snmpd_register_config_handler("access", vacm_parse_access,
+ vacm_free_access,
+ "name context model level prefix read write notify");
+ snmpd_register_config_handler("setaccess", vacm_parse_setaccess,
+ vacm_free_access,
+ "name context model level prefix viewname viewval");
+ snmpd_register_config_handler("view", vacm_parse_view, vacm_free_view,
+ "name type subtree [mask]");
+ snmpd_register_config_handler("vacmView", vacm_parse_config_view, NULL,
+ NULL);
+ snmpd_register_config_handler("vacmGroup", vacm_parse_config_group,
+ NULL, NULL);
+ snmpd_register_config_handler("vacmAccess", vacm_parse_config_access,
+ NULL, NULL);
+ snmpd_register_config_handler("vacmAuthAccess", vacm_parse_config_auth_access,
+ NULL, NULL);
+
+ /* easy community auth handler */
+ snmpd_register_config_handler("authcommunity",
+ vacm_parse_authcommunity,
+ NULL, "authtype1,authtype2 community [default|hostname|network/bits [oid|-V view]]");
+
+ /* easy user auth handler */
+ snmpd_register_config_handler("authuser",
+ vacm_parse_authuser,
+ NULL, "authtype1,authtype2 [-s secmodel] user [noauth|auth|priv [oid|-V view]]");
+ /* easy group auth handler */
+ snmpd_register_config_handler("authgroup",
+ vacm_parse_authuser,
+ NULL, "authtype1,authtype2 [-s secmodel] group [noauth|auth|priv [oid|-V view]]");
+
+ snmpd_register_config_handler("authaccess", vacm_parse_authaccess,
+ vacm_free_access,
+ "name authtype1,authtype2 [-s secmodel] group view [noauth|auth|priv [context|context*]]");
+
+ /*
+ * Define standard views "_all_" and "_none_"
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY,
+ SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
+ vacm_standard_views, NULL);
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY,
+ SNMP_CALLBACK_POST_READ_CONFIG,
+ vacm_warn_if_not_configured, NULL);
+}
+
+/**
+ * Registers the easier-to-use VACM token handlers for quick access rules.
+ * These tokens will only be recognised by 'snmpd'.
+ */
+void
+init_vacm_snmpd_easy_tokens(void) {
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+ snmpd_register_config_handler("rwcommunity", vacm_parse_rwcommunity, NULL,
+ "community [default|hostname|network/bits [oid]]");
+ snmpd_register_config_handler("rocommunity", vacm_parse_rocommunity, NULL,
+ "community [default|hostname|network/bits [oid]]");
+#ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
+ snmpd_register_config_handler("rwcommunity6", vacm_parse_rwcommunity6, NULL,
+ "community [default|hostname|network/bits [oid]]");
+ snmpd_register_config_handler("rocommunity6", vacm_parse_rocommunity6, NULL,
+ "community [default|hostname|network/bits [oid]]");
+#endif
+#endif /* support for community based SNMP */
+ snmpd_register_config_handler("rwuser", vacm_parse_rwuser, NULL,
+ "user [noauth|auth|priv [oid]]");
+ snmpd_register_config_handler("rouser", vacm_parse_rouser, NULL,
+ "user [noauth|auth|priv [oid]]");
+}
+
+void
+init_vacm_conf(void)
+{
+ init_vacm_config_tokens();
+ init_vacm_snmpd_easy_tokens();
+ /*
+ * register ourselves to handle access control ('snmpd' only)
+ */
+ snmp_register_callback(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_ACM_CHECK, vacm_in_view_callback,
+ NULL);
+ snmp_register_callback(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_ACM_CHECK_INITIAL,
+ vacm_in_view_callback, NULL);
+ snmp_register_callback(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_ACM_CHECK_SUBTREE,
+ vacm_in_view_callback, NULL);
+}
+
+
+
+void
+vacm_parse_group(const char *token, char *param)
+{
+ char *group, *model, *security;
+ int imodel;
+ struct vacm_groupEntry *gp = NULL;
+ char *st;
+
+ group = strtok_r(param, " \t\n", &st);
+ model = strtok_r(NULL, " \t\n", &st);
+ security = strtok_r(NULL, " \t\n", &st);
+
+ if (group == NULL || *group == 0) {
+ config_perror("missing GROUP parameter");
+ return;
+ }
+ if (model == NULL || *model == 0) {
+ config_perror("missing MODEL parameter");
+ return;
+ }
+ if (security == NULL || *security == 0) {
+ config_perror("missing SECURITY parameter");
+ return;
+ }
+ if (strcasecmp(model, "v1") == 0)
+ imodel = SNMP_SEC_MODEL_SNMPv1;
+ else if (strcasecmp(model, "v2c") == 0)
+ imodel = SNMP_SEC_MODEL_SNMPv2c;
+ else if (strcasecmp(model, "any") == 0) {
+ config_perror
+ ("bad security model \"any\" should be: v1, v2c, usm or a registered security plugin name - installing anyway");
+ imodel = SNMP_SEC_MODEL_ANY;
+ } else {
+ if ((imodel = se_find_value_in_slist("snmp_secmods", model)) ==
+ SE_DNE) {
+ config_perror
+ ("bad security model, should be: v1, v2c or usm or a registered security plugin name");
+ return;
+ }
+ }
+ if (strlen(security) + 1 > sizeof(gp->groupName)) {
+ config_perror("security name too long");
+ return;
+ }
+ gp = vacm_createGroupEntry(imodel, security);
+ if (!gp) {
+ config_perror("failed to create group entry");
+ return;
+ }
+ strncpy(gp->groupName, group, sizeof(gp->groupName));
+ gp->groupName[ sizeof(gp->groupName)-1 ] = 0;
+ gp->storageType = SNMP_STORAGE_PERMANENT;
+ gp->status = SNMP_ROW_ACTIVE;
+ free(gp->reserved);
+ gp->reserved = NULL;
+}
+
+void
+vacm_free_group(void)
+{
+ vacm_destroyAllGroupEntries();
+}
+
+#define PARSE_CONT 0
+#define PARSE_FAIL 1
+
+int
+_vacm_parse_access_common(const char *token, char *param, char **st,
+ char **name, char **context, int *imodel,
+ int *ilevel, int *iprefix)
+{
+ char *model, *level, *prefix;
+
+ *name = strtok_r(param, " \t\n", st);
+ if (!*name) {
+ config_perror("missing NAME parameter");
+ return PARSE_FAIL;
+ }
+ *context = strtok_r(NULL, " \t\n", st);
+ if (!*context) {
+ config_perror("missing CONTEXT parameter");
+ return PARSE_FAIL;
+ }
+
+ model = strtok_r(NULL, " \t\n", st);
+ if (!model) {
+ config_perror("missing MODEL parameter");
+ return PARSE_FAIL;
+ }
+ level = strtok_r(NULL, " \t\n", st);
+ if (!level) {
+ config_perror("missing LEVEL parameter");
+ return PARSE_FAIL;
+ }
+ prefix = strtok_r(NULL, " \t\n", st);
+ if (!prefix) {
+ config_perror("missing PREFIX parameter");
+ return PARSE_FAIL;
+ }
+
+ if (strcmp(*context, "\"\"") == 0)
+ **context = 0;
+ if (strcasecmp(model, "any") == 0)
+ *imodel = SNMP_SEC_MODEL_ANY;
+ else if (strcasecmp(model, "v1") == 0)
+ *imodel = SNMP_SEC_MODEL_SNMPv1;
+ else if (strcasecmp(model, "v2c") == 0)
+ *imodel = SNMP_SEC_MODEL_SNMPv2c;
+ else {
+ if ((*imodel = se_find_value_in_slist("snmp_secmods", model))
+ == SE_DNE) {
+ config_perror
+ ("bad security model, should be: v1, v2c or usm or a registered security plugin name");
+ return PARSE_FAIL;
+ }
+ }
+
+ if (strcasecmp(level, "noauth") == 0)
+ *ilevel = SNMP_SEC_LEVEL_NOAUTH;
+ else if (strcasecmp(level, "noauthnopriv") == 0)
+ *ilevel = SNMP_SEC_LEVEL_NOAUTH;
+ else if (strcasecmp(level, "auth") == 0)
+ *ilevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ else if (strcasecmp(level, "authnopriv") == 0)
+ *ilevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ else if (strcasecmp(level, "priv") == 0)
+ *ilevel = SNMP_SEC_LEVEL_AUTHPRIV;
+ else if (strcasecmp(level, "authpriv") == 0)
+ *ilevel = SNMP_SEC_LEVEL_AUTHPRIV;
+ else {
+ config_perror
+ ("bad security level (noauthnopriv, authnopriv, authpriv)");
+ return PARSE_FAIL;
+ }
+
+ if (strcmp(prefix, "exact") == 0)
+ *iprefix = 1;
+ else if (strcmp(prefix, "prefix") == 0)
+ *iprefix = 2;
+ else if (strcmp(prefix, "0") == 0) {
+ config_perror
+ ("bad prefix match parameter \"0\", should be: exact or prefix - installing anyway");
+ *iprefix = 1;
+ } else {
+ config_perror
+ ("bad prefix match parameter, should be: exact or prefix");
+ return PARSE_FAIL;
+ }
+
+ return PARSE_CONT;
+}
+
+/* **************************************/
+/* authorization parsing token handlers */
+/* **************************************/
+
+int
+vacm_parse_authtokens(const char *token, char **confline)
+{
+ char authspec[SNMP_MAXBUF_MEDIUM];
+ char *strtok_state;
+ char *type;
+ int viewtype, viewtypes = 0;
+
+ *confline = copy_nword(*confline, authspec, sizeof(authspec));
+
+ DEBUGMSGTL(("vacm_parse_authtokens","parsing %s",authspec));
+ if (!*confline) {
+ config_perror("Illegal configuration line: missing fields");
+ return -1;
+ }
+
+ type = strtok_r(authspec, ",|:", &strtok_state);
+ while(type && *type != '\0') {
+ viewtype = se_find_value_in_slist(VACM_VIEW_ENUM_NAME, type);
+ if (viewtype < 0 || viewtype >= VACM_MAX_VIEWS) {
+ config_perror("Illegal view name");
+ } else {
+ viewtypes |= (1 << viewtype);
+ }
+ type = strtok_r(NULL, ",|:", &strtok_state);
+ }
+ DEBUGMSG(("vacm_parse_authtokens"," .. result = 0x%x\n",viewtypes));
+ return viewtypes;
+}
+
+void
+vacm_parse_authuser(const char *token, char *confline)
+{
+ int viewtypes = vacm_parse_authtokens(token, &confline);
+ if (viewtypes != -1)
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_V3, viewtypes);
+}
+
+void
+vacm_parse_authcommunity(const char *token, char *confline)
+{
+ int viewtypes = vacm_parse_authtokens(token, &confline);
+ if (viewtypes != -1)
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COM, viewtypes);
+}
+
+void
+vacm_parse_authaccess(const char *token, char *confline)
+{
+ char *group, *view, *context, *tmp;
+ int model = SNMP_SEC_MODEL_ANY;
+ int level, prefix;
+ int i;
+ char *st;
+ struct vacm_accessEntry *ap;
+ int viewtypes = vacm_parse_authtokens(token, &confline);
+
+ if (viewtypes == -1)
+ return;
+
+ group = strtok_r(confline, " \t\n", &st);
+ if (!group) {
+ config_perror("missing GROUP parameter");
+ return;
+ }
+ view = strtok_r(NULL, " \t\n", &st);
+ if (!view) {
+ config_perror("missing VIEW parameter");
+ return;
+ }
+
+ /*
+ * Check for security model option
+ */
+ if ( strcasecmp(view, "-s") == 0 ) {
+ tmp = strtok_r(NULL, " \t\n", &st);
+ if (tmp) {
+ if (strcasecmp(tmp, "any") == 0)
+ model = SNMP_SEC_MODEL_ANY;
+ else if (strcasecmp(tmp, "v1") == 0)
+ model = SNMP_SEC_MODEL_SNMPv1;
+ else if (strcasecmp(tmp, "v2c") == 0)
+ model = SNMP_SEC_MODEL_SNMPv2c;
+ else {
+ model = se_find_value_in_slist("snmp_secmods", tmp);
+ if (model == SE_DNE) {
+ config_perror
+ ("bad security model, should be: v1, v2c or usm or a registered security plugin name");
+ return;
+ }
+ }
+ } else {
+ config_perror("missing SECMODEL parameter");
+ return;
+ }
+ view = strtok_r(NULL, " \t\n", &st);
+ if (!view) {
+ config_perror("missing VIEW parameter");
+ return;
+ }
+ }
+ if (strlen(view) >= VACMSTRINGLEN ) {
+ config_perror("View value too long");
+ return;
+ }
+
+ /*
+ * Now parse optional fields, or provide default values
+ */
+
+ tmp = strtok_r(NULL, " \t\n", &st);
+ if (tmp) {
+ if (strcasecmp(tmp, "noauth") == 0)
+ level = SNMP_SEC_LEVEL_NOAUTH;
+ else if (strcasecmp(tmp, "noauthnopriv") == 0)
+ level = SNMP_SEC_LEVEL_NOAUTH;
+ else if (strcasecmp(tmp, "auth") == 0)
+ level = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ else if (strcasecmp(tmp, "authnopriv") == 0)
+ level = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ else if (strcasecmp(tmp, "priv") == 0)
+ level = SNMP_SEC_LEVEL_AUTHPRIV;
+ else if (strcasecmp(tmp, "authpriv") == 0)
+ level = SNMP_SEC_LEVEL_AUTHPRIV;
+ else {
+ config_perror
+ ("bad security level (noauthnopriv, authnopriv, authpriv)");
+ return;
+ }
+ } else {
+ /* What about SNMP_SEC_MODEL_ANY ?? */
+ if ( model == SNMP_SEC_MODEL_SNMPv1 ||
+ model == SNMP_SEC_MODEL_SNMPv2c )
+ level = SNMP_SEC_LEVEL_NOAUTH;
+ else
+ level = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ }
+
+
+ context = strtok_r(NULL, " \t\n", &st);
+ if (context) {
+ tmp = (context + strlen(context)-1);
+ if (tmp && *tmp == '*') {
+ *tmp = '\0';
+ prefix = 2;
+ } else {
+ prefix = 1;
+ }
+ } else {
+ context = "";
+ prefix = 1; /* Or prefix(2) ?? */
+ }
+
+ /*
+ * Now we can create the access entry
+ */
+ ap = vacm_getAccessEntry(group, context, model, level);
+ if (!ap) {
+ ap = vacm_createAccessEntry(group, context, model, level);
+ DEBUGMSGTL(("vacm:conf:authaccess",
+ "no existing access found; creating a new one\n"));
+ } else {
+ DEBUGMSGTL(("vacm:conf:authaccess",
+ "existing access found, using it\n"));
+ }
+ if (!ap) {
+ config_perror("failed to create access entry");
+ return;
+ }
+
+ for (i = 0; i <= VACM_MAX_VIEWS; i++) {
+ if (viewtypes & (1 << i)) {
+ strcpy(ap->views[i], view);
+ }
+ }
+ ap->contextMatch = prefix;
+ ap->storageType = SNMP_STORAGE_PERMANENT;
+ ap->status = SNMP_ROW_ACTIVE;
+ if (ap->reserved)
+ free(ap->reserved);
+ ap->reserved = NULL;
+}
+
+void
+vacm_parse_setaccess(const char *token, char *param)
+{
+ char *name, *context, *viewname, *viewval;
+ int imodel, ilevel, iprefix;
+ int viewnum;
+ char *st;
+ struct vacm_accessEntry *ap;
+
+ if (_vacm_parse_access_common(token, param, &st, &name,
+ &context, &imodel, &ilevel, &iprefix)
+ == PARSE_FAIL) {
+ return;
+ }
+
+ viewname = strtok_r(NULL, " \t\n", &st);
+ if (!viewname) {
+ config_perror("missing viewname parameter");
+ return;
+ }
+ viewval = strtok_r(NULL, " \t\n", &st);
+ if (!viewval) {
+ config_perror("missing viewval parameter");
+ return;
+ }
+
+ if (strlen(viewval) + 1 > sizeof(ap->views[VACM_VIEW_NOTIFY])) {
+ config_perror("View value too long");
+ return;
+ }
+
+ viewnum = se_find_value_in_slist(VACM_VIEW_ENUM_NAME, viewname);
+ if (viewnum < 0 || viewnum >= VACM_MAX_VIEWS) {
+ config_perror("Illegal view name");
+ return;
+ }
+
+ ap = vacm_getAccessEntry(name, context, imodel, ilevel);
+ if (!ap) {
+ ap = vacm_createAccessEntry(name, context, imodel, ilevel);
+ DEBUGMSGTL(("vacm:conf:setaccess",
+ "no existing access found; creating a new one\n"));
+ } else {
+ DEBUGMSGTL(("vacm:conf:setaccess",
+ "existing access found, using it\n"));
+ }
+ if (!ap) {
+ config_perror("failed to create access entry");
+ return;
+ }
+ if (!ap) {
+ config_perror("failed to create access entry");
+ return;
+ }
+
+ strcpy(ap->views[viewnum], viewval);
+ ap->contextMatch = iprefix;
+ ap->storageType = SNMP_STORAGE_PERMANENT;
+ ap->status = SNMP_ROW_ACTIVE;
+ free(ap->reserved);
+ ap->reserved = NULL;
+}
+
+void
+vacm_parse_access(const char *token, char *param)
+{
+ char *name, *context, *readView, *writeView, *notify;
+ int imodel, ilevel, iprefix;
+ struct vacm_accessEntry *ap;
+ char *st;
+
+
+ if (_vacm_parse_access_common(token, param, &st, &name,
+ &context, &imodel, &ilevel, &iprefix)
+ == PARSE_FAIL) {
+ return;
+ }
+
+ readView = strtok_r(NULL, " \t\n", &st);
+ if (!readView) {
+ config_perror("missing readView parameter");
+ return;
+ }
+ writeView = strtok_r(NULL, " \t\n", &st);
+ if (!writeView) {
+ config_perror("missing writeView parameter");
+ return;
+ }
+ notify = strtok_r(NULL, " \t\n", &st);
+ if (!notify) {
+ config_perror("missing notifyView parameter");
+ return;
+ }
+
+ if (strlen(readView) + 1 > sizeof(ap->views[VACM_VIEW_READ])) {
+ config_perror("readView too long");
+ return;
+ }
+ if (strlen(writeView) + 1 > sizeof(ap->views[VACM_VIEW_WRITE])) {
+ config_perror("writeView too long");
+ return;
+ }
+ if (strlen(notify) + 1 > sizeof(ap->views[VACM_VIEW_NOTIFY])) {
+ config_perror("notifyView too long");
+ return;
+ }
+ ap = vacm_createAccessEntry(name, context, imodel, ilevel);
+ if (!ap) {
+ config_perror("failed to create access entry");
+ return;
+ }
+ strcpy(ap->views[VACM_VIEW_READ], readView);
+ strcpy(ap->views[VACM_VIEW_WRITE], writeView);
+ strcpy(ap->views[VACM_VIEW_NOTIFY], notify);
+ ap->contextMatch = iprefix;
+ ap->storageType = SNMP_STORAGE_PERMANENT;
+ ap->status = SNMP_ROW_ACTIVE;
+ free(ap->reserved);
+ ap->reserved = NULL;
+}
+
+void
+vacm_free_access(void)
+{
+ vacm_destroyAllAccessEntries();
+}
+
+void
+vacm_parse_view(const char *token, char *param)
+{
+ char *name, *type, *subtree, *mask;
+ int inclexcl;
+ struct vacm_viewEntry *vp;
+ oid suboid[MAX_OID_LEN];
+ size_t suboid_len = 0;
+ size_t mask_len = 0;
+ u_char viewMask[VACMSTRINGLEN];
+ int i;
+ char *st;
+
+ name = strtok_r(param, " \t\n", &st);
+ if (!name) {
+ config_perror("missing NAME parameter");
+ return;
+ }
+ type = strtok_r(NULL, " \n\t", &st);
+ if (!type) {
+ config_perror("missing TYPE parameter");
+ return;
+ }
+ subtree = strtok_r(NULL, " \t\n", &st);
+ if (!subtree) {
+ config_perror("missing SUBTREE parameter");
+ return;
+ }
+ mask = strtok_r(NULL, "\0", &st);
+
+ if (strcmp(type, "included") == 0)
+ inclexcl = SNMP_VIEW_INCLUDED;
+ else if (strcmp(type, "excluded") == 0)
+ inclexcl = SNMP_VIEW_EXCLUDED;
+ else {
+ config_perror("TYPE must be included/excluded?");
+ return;
+ }
+ suboid_len = strlen(subtree)-1;
+ if (subtree[suboid_len] == '.')
+ subtree[suboid_len] = '\0'; /* stamp on a trailing . */
+ suboid_len = MAX_OID_LEN;
+ if (!snmp_parse_oid(subtree, suboid, &suboid_len)) {
+ config_perror("bad SUBTREE object id");
+ return;
+ }
+ if (mask) {
+ int val;
+ i = 0;
+ for (mask = strtok_r(mask, " .:", &st); mask; mask = strtok_r(NULL, " .:", &st)) {
+ if (i >= sizeof(viewMask)) {
+ config_perror("MASK too long");
+ return;
+ }
+ if (sscanf(mask, "%x", &val) == 0) {
+ config_perror("invalid MASK");
+ return;
+ }
+ viewMask[i] = val;
+ i++;
+ }
+ mask_len = i;
+ } else {
+ for (i = 0; i < sizeof(viewMask); i++)
+ viewMask[i] = 0xff;
+ }
+ vp = vacm_createViewEntry(name, suboid, suboid_len);
+ if (!vp) {
+ config_perror("failed to create view entry");
+ return;
+ }
+ memcpy(vp->viewMask, viewMask, sizeof(viewMask));
+ vp->viewMaskLen = mask_len;
+ vp->viewType = inclexcl;
+ vp->viewStorageType = SNMP_STORAGE_PERMANENT;
+ vp->viewStatus = SNMP_ROW_ACTIVE;
+ free(vp->reserved);
+ vp->reserved = NULL;
+}
+
+void
+vacm_free_view(void)
+{
+ vacm_destroyAllViewEntries();
+}
+
+void
+vacm_gen_com2sec(int commcount, char *community, char *addressname,
+ char *publishtoken,
+ void (*parser)(const char *, char *),
+ char *secname, size_t secname_len,
+ char *viewname, size_t viewname_len, int version)
+{
+ char line[SPRINT_MAX_LEN];
+
+ /*
+ * com2sec6|comsec anonymousSecNameNUM ADDRESS COMMUNITY
+ */
+ snprintf(secname, secname_len-1, "comm%d", commcount);
+ secname[secname_len-1] = '\0';
+ if (viewname) {
+ snprintf(viewname, viewname_len-1, "viewComm%d", commcount);
+ viewname[viewname_len-1] = '\0';
+ }
+ snprintf(line, sizeof(line), "%s %s '%s'",
+ secname, addressname, community);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((publishtoken, "passing: %s %s\n", publishtoken, line));
+ (*parser)(publishtoken, line);
+
+ /*
+ * sec->group mapping
+ */
+ /*
+ * group anonymousGroupNameNUM any anonymousSecNameNUM
+ */
+ if ( version & SNMP_SEC_MODEL_SNMPv1 ) {
+ snprintf(line, sizeof(line),
+ "grp%.28s v1 %s", secname, secname);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((publishtoken, "passing: %s %s\n", "group", line));
+ vacm_parse_group("group", line);
+ }
+
+ if ( version & SNMP_SEC_MODEL_SNMPv2c ) {
+ snprintf(line, sizeof(line),
+ "grp%.28s v2c %s", secname, secname);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((publishtoken, "passing: %s %s\n", "group", line));
+ vacm_parse_group("group", line);
+ }
+}
+
+void
+vacm_parse_rwuser(const char *token, char *confline)
+{
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_V3,
+ VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT);
+}
+
+void
+vacm_parse_rouser(const char *token, char *confline)
+{
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_V3,
+ VACM_VIEW_READ_BIT);
+}
+
+void
+vacm_parse_rocommunity(const char *token, char *confline)
+{
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV4,
+ VACM_VIEW_READ_BIT);
+}
+
+void
+vacm_parse_rwcommunity(const char *token, char *confline)
+{
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV4,
+ VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT);
+}
+
+void
+vacm_parse_rocommunity6(const char *token, char *confline)
+{
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV6,
+ VACM_VIEW_READ_BIT);
+}
+
+void
+vacm_parse_rwcommunity6(const char *token, char *confline)
+{
+ vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV6,
+ VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT);
+}
+
+
+void
+vacm_create_simple(const char *token, char *confline,
+ int parsetype, int viewtypes)
+{
+ char line[SPRINT_MAX_LEN];
+ char community[COMMUNITY_MAX_LEN];
+ char theoid[SPRINT_MAX_LEN];
+ char viewname[SPRINT_MAX_LEN];
+ char *view_ptr = viewname;
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+ char addressname[SPRINT_MAX_LEN];
+#endif
+ const char *rw = "none";
+ char model[SPRINT_MAX_LEN];
+ char *cp, *tmp;
+ char secname[SPRINT_MAX_LEN];
+ char grpname[SPRINT_MAX_LEN];
+ char authlevel[SPRINT_MAX_LEN];
+ char context[SPRINT_MAX_LEN];
+ int ctxprefix = 1; /* Default to matching all contexts */
+ static int commcount = 0;
+ /* Conveniently, the community-based security
+ model values can also be used as bit flags */
+ int commversion = SNMP_SEC_MODEL_SNMPv1 |
+ SNMP_SEC_MODEL_SNMPv2c;
+
+ /*
+ * init
+ */
+ strcpy(model, "any");
+ memset(context, 0, sizeof(context));
+ memset(secname, 0, sizeof(secname));
+ memset(grpname, 0, sizeof(grpname));
+
+ /*
+ * community name or user name
+ */
+ cp = copy_nword(confline, community, sizeof(community));
+
+ if (parsetype == VACM_CREATE_SIMPLE_V3) {
+ /*
+ * maybe security model type
+ */
+ if (strcmp(community, "-s") == 0) {
+ /*
+ * -s model ...
+ */
+ if (cp)
+ cp = copy_nword(cp, model, sizeof(model));
+ if (!cp) {
+ config_perror("illegal line");
+ return;
+ }
+ if (cp)
+ cp = copy_nword(cp, community, sizeof(community));
+ } else {
+ strcpy(model, "usm");
+ }
+ /*
+ * authentication level
+ */
+ if (cp && *cp)
+ cp = copy_nword(cp, authlevel, sizeof(authlevel));
+ else
+ strcpy(authlevel, "auth");
+ DEBUGMSGTL((token, "setting auth level: \"%s\"\n", authlevel));
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+ } else {
+ if (strcmp(community, "-v") == 0) {
+ /*
+ * -v version ...
+ */
+ if (cp)
+ cp = copy_nword(cp, model, sizeof(model));
+ if (!cp) {
+ config_perror("illegal line");
+ return;
+ }
+ if ( strcasecmp( model, "1" ) == 0 )
+ strcpy(model, "v1");
+ if ( strcasecmp( model, "v1" ) == 0 )
+ commversion = SNMP_SEC_MODEL_SNMPv1;
+ if ( strcasecmp( model, "2c" ) == 0 )
+ strcpy(model, "v2c");
+ if ( strcasecmp( model, "v2c" ) == 0 )
+ commversion = SNMP_SEC_MODEL_SNMPv2c;
+ if (cp)
+ cp = copy_nword(cp, community, sizeof(community));
+ }
+ /*
+ * source address
+ */
+ if (cp && *cp) {
+ cp = copy_nword(cp, addressname, sizeof(addressname));
+ } else {
+ strcpy(addressname, "default");
+ }
+ /*
+ * authlevel has to be noauth
+ */
+ strcpy(authlevel, "noauth");
+#endif /* support for community based SNMP */
+ }
+
+ /*
+ * oid they can touch
+ */
+ if (cp && *cp) {
+ if (strncmp(cp, "-V ", 3) == 0) {
+ cp = skip_token(cp);
+ cp = copy_nword(cp, viewname, sizeof(viewname));
+ view_ptr = NULL;
+ } else {
+ cp = copy_nword(cp, theoid, sizeof(theoid));
+ }
+ } else {
+ strcpy(theoid, ".1");
+ strcpy(viewname, "_all_");
+ view_ptr = NULL;
+ }
+ /*
+ * optional, non-default context
+ */
+ if (cp && *cp) {
+ cp = copy_nword(cp, context, sizeof(context));
+ tmp = (context + strlen(context)-1);
+ if (tmp && *tmp == '*') {
+ *tmp = '\0';
+ ctxprefix = 1;
+ } else {
+ /*
+ * If no context field is given, then we default to matching
+ * all contexts (for compatability with previous releases).
+ * But if a field context is specified (not ending with '*')
+ * then this should be taken as an exact match.
+ * Specifying a context field of "" will match the default
+ * context (and *only* the default context).
+ */
+ ctxprefix = 0;
+ }
+ }
+
+ if (viewtypes & VACM_VIEW_WRITE_BIT)
+ rw = viewname;
+
+ commcount++;
+
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+ if (parsetype == VACM_CREATE_SIMPLE_COMIPV4 ||
+ parsetype == VACM_CREATE_SIMPLE_COM) {
+ vacm_gen_com2sec(commcount, community, addressname,
+ "com2sec", &netsnmp_udp_parse_security,
+ secname, sizeof(secname),
+ view_ptr, sizeof(viewname), commversion);
+ }
+
+#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
+ if (parsetype == VACM_CREATE_SIMPLE_COMUNIX ||
+ parsetype == VACM_CREATE_SIMPLE_COM) {
+ snprintf(line, sizeof(line), "%s %s '%s'",
+ secname, addressname, community);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((token, "passing: %s %s\n", "com2secunix", line));
+ netsnmp_unix_parse_security("com2secunix", line);
+ }
+#endif
+
+#ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
+ if (parsetype == VACM_CREATE_SIMPLE_COMIPV6 ||
+ parsetype == VACM_CREATE_SIMPLE_COM) {
+ vacm_gen_com2sec(commcount, community, addressname,
+ "com2sec6", &netsnmp_udp6_parse_security,
+ secname, sizeof(secname),
+ view_ptr, sizeof(viewname), commversion);
+ }
+#endif
+#endif /* support for community based SNMP */
+
+ if (parsetype == VACM_CREATE_SIMPLE_V3) {
+ /* support for SNMPv3 user names */
+ if (view_ptr) {
+ sprintf(viewname,"viewUSM%d",commcount);
+ }
+ if ( strcmp( token, "authgroup" ) == 0 ) {
+ strncpy(grpname, community, sizeof(grpname));
+ grpname[ sizeof(grpname)-1 ] = 0;
+ } else {
+ strncpy(secname, community, sizeof(secname));
+ secname[ sizeof(secname)-1 ] = 0;
+
+ /*
+ * sec->group mapping
+ */
+ /*
+ * group anonymousGroupNameNUM any anonymousSecNameNUM
+ */
+ snprintf(grpname, sizeof(grpname), "grp%.28s", secname);
+ for (tmp=grpname; *tmp; tmp++)
+ if (!isalnum(*tmp))
+ *tmp = '_';
+ snprintf(line, sizeof(line),
+ "%s %s %s", grpname, model, secname);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((token, "passing: %s %s\n", "group", line));
+ vacm_parse_group("group", line);
+ }
+ } else {
+ snprintf(grpname, sizeof(grpname), "grp%.28s", secname);
+ for (tmp=grpname; *tmp; tmp++)
+ if (!isalnum(*tmp))
+ *tmp = '_';
+ }
+
+ /*
+ * view definition
+ */
+ /*
+ * view anonymousViewNUM included OID
+ */
+ if (view_ptr) {
+ snprintf(line, sizeof(line), "%s included %s", viewname, theoid);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((token, "passing: %s %s\n", "view", line));
+ vacm_parse_view("view", line);
+ }
+
+ /*
+ * map everything together
+ */
+ if ((viewtypes == VACM_VIEW_READ_BIT) ||
+ (viewtypes == (VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT))) {
+ /* Use the simple line access command */
+ /*
+ * access anonymousGroupNameNUM "" MODEL AUTHTYPE prefix anonymousViewNUM [none/anonymousViewNUM] [none/anonymousViewNUM]
+ */
+ snprintf(line, sizeof(line),
+ "%s %s %s %s %s %s %s %s",
+ grpname, context[0] ? context : "\"\"",
+ model, authlevel,
+ (ctxprefix ? "prefix" : "exact"),
+ viewname, rw, rw);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((token, "passing: %s %s\n", "access", line));
+ vacm_parse_access("access", line);
+ } else {
+ /* Use one setaccess line per access type */
+ /*
+ * setaccess anonymousGroupNameNUM "" MODEL AUTHTYPE prefix viewname viewval
+ */
+ int i;
+ DEBUGMSGTL((token, " checking view levels for %x\n", viewtypes));
+ for(i = 0; i <= VACM_MAX_VIEWS; i++) {
+ if (viewtypes & (1 << i)) {
+ snprintf(line, sizeof(line),
+ "%s %s %s %s %s %s %s",
+ grpname, context[0] ? context : "\"\"",
+ model, authlevel,
+ (ctxprefix ? "prefix" : "exact"),
+ se_find_label_in_slist(VACM_VIEW_ENUM_NAME, i),
+ viewname);
+ line[ sizeof(line)-1 ] = 0;
+ DEBUGMSGTL((token, "passing: %s %s\n", "setaccess", line));
+ vacm_parse_setaccess("setaccess", line);
+ }
+ }
+ }
+}
+
+int
+vacm_standard_views(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SPRINT_MAX_LEN];
+
+ memset(line, 0, sizeof(line));
+
+ snprintf(line, sizeof(line), "_all_ included .0");
+ vacm_parse_view("view", line);
+ snprintf(line, sizeof(line), "_all_ included .1");
+ vacm_parse_view("view", line);
+ snprintf(line, sizeof(line), "_all_ included .2");
+ vacm_parse_view("view", line);
+
+ snprintf(line, sizeof(line), "_none_ excluded .0");
+ vacm_parse_view("view", line);
+ snprintf(line, sizeof(line), "_none_ excluded .1");
+ vacm_parse_view("view", line);
+ snprintf(line, sizeof(line), "_none_ excluded .2");
+ vacm_parse_view("view", line);
+
+ return SNMP_ERR_NOERROR;
+}
+
+int
+vacm_warn_if_not_configured(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ const char * name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_APPTYPE);
+ const int agent_mode = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_ROLE);
+ if (NULL==name)
+ name = "snmpd";
+
+ if (!vacm_is_configured()) {
+ /*
+ * An AgentX subagent relies on the master agent to apply suitable
+ * access control checks, so doesn't need local VACM configuration.
+ * The trap daemon has a separate check (see below).
+ *
+ * Otherwise, an AgentX master or SNMP standalone agent requires some
+ * form of VACM configuration. No config means that no incoming
+ * requests will be accepted, so warn the user accordingly.
+ */
+ if ((MASTER_AGENT == agent_mode) && (strcmp(name, "snmptrapd") != 0)) {
+ snmp_log(LOG_WARNING,
+ "Warning: no access control information configured.\n"
+ " (Config search path: %s)\n"
+ " It's unlikely this agent can serve any useful purpose in this state.\n"
+ " Run \"snmpconf -g basic_setup\" to help you "
+ "configure the %s.conf file for this agent.\n",
+ get_configuration_directory(), name);
+ }
+
+ /*
+ * The trap daemon implements VACM-style access control for incoming
+ * notifications, but offers a way of turning this off (for backwards
+ * compatability). Check for this explicitly, and warn if necessary.
+ *
+ * NB: The NETSNMP_DS_APP_NO_AUTHORIZATION definition is a duplicate
+ * of an identical setting in "apps/snmptrapd_ds.h".
+ * These two need to be kept in synch.
+ */
+#ifndef NETSNMP_DS_APP_NO_AUTHORIZATION
+#define NETSNMP_DS_APP_NO_AUTHORIZATION 17
+#endif
+ if (!strcmp(name, "snmptrapd") &&
+ !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_APP_NO_AUTHORIZATION)) {
+ snmp_log(LOG_WARNING,
+ "Warning: no access control information configured.\n"
+ " (Config search path: %s)\n"
+ "This receiver will *NOT* accept any incoming notifications.\n",
+ get_configuration_directory());
+ }
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+vacm_in_view_callback(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ struct view_parameters *view_parms =
+ (struct view_parameters *) serverarg;
+ int retval;
+
+ if (view_parms == NULL)
+ return 1;
+ retval = vacm_in_view(view_parms->pdu, view_parms->name,
+ view_parms->namelen, view_parms->check_subtree);
+ if (retval != 0)
+ view_parms->errorcode = retval;
+ return retval;
+}
+
+
+/**
+ * vacm_in_view: decides if a given PDU can be acted upon
+ *
+ * Parameters:
+ * *pdu
+ * *name
+ * namelen
+ * check_subtree
+ *
+ * Returns:
+ * VACM_SUCCESS(0) On success.
+ * VACM_NOSECNAME(1) Missing security name.
+ * VACM_NOGROUP(2) Missing group
+ * VACM_NOACCESS(3) Missing access
+ * VACM_NOVIEW(4) Missing view
+ * VACM_NOTINVIEW(5) Not in view
+ * VACM_NOSUCHCONTEXT(6) No Such Context
+ * VACM_SUBTREE_UNKNOWN(7) When testing an entire subtree, UNKNOWN (ie, the entire
+ * subtree has both allowed and disallowed portions)
+ *
+ * Debug output listed as follows:
+ * \<securityName\> \<groupName\> \<viewName\> \<viewType\>
+ */
+int
+vacm_in_view(netsnmp_pdu *pdu, oid * name, size_t namelen,
+ int check_subtree)
+{
+ int viewtype;
+
+ switch (pdu->command) {
+ case SNMP_MSG_GET:
+ case SNMP_MSG_GETNEXT:
+ case SNMP_MSG_GETBULK:
+ viewtype = VACM_VIEW_READ;
+ break;
+ case SNMP_MSG_SET:
+ viewtype = VACM_VIEW_WRITE;
+ break;
+ case SNMP_MSG_TRAP:
+ case SNMP_MSG_TRAP2:
+ case SNMP_MSG_INFORM:
+ viewtype = VACM_VIEW_NOTIFY;
+ break;
+ default:
+ snmp_log(LOG_ERR, "bad msg type in vacm_in_view: %d\n",
+ pdu->command);
+ viewtype = VACM_VIEW_READ;
+ }
+ return vacm_check_view(pdu, name, namelen, check_subtree, viewtype);
+}
+
+/**
+ * vacm_check_view: decides if a given PDU can be taken based on a view type
+ *
+ * Parameters:
+ * *pdu
+ * *name
+ * namelen
+ * check_subtree
+ * viewtype
+ *
+ * Returns:
+ * VACM_SUCCESS(0) On success.
+ * VACM_NOSECNAME(1) Missing security name.
+ * VACM_NOGROUP(2) Missing group
+ * VACM_NOACCESS(3) Missing access
+ * VACM_NOVIEW(4) Missing view
+ * VACM_NOTINVIEW(5) Not in view
+ * VACM_NOSUCHCONTEXT(6) No Such Context
+ * VACM_SUBTREE_UNKNOWN(7) When testing an entire subtree, UNKNOWN (ie, the entire
+ * subtree has both allowed and disallowed portions)
+ *
+ * Debug output listed as follows:
+ * \<securityName\> \<groupName\> \<viewName\> \<viewType\>
+ */
+int
+vacm_check_view(netsnmp_pdu *pdu, oid * name, size_t namelen,
+ int check_subtree, int viewtype)
+{
+ struct vacm_accessEntry *ap;
+ struct vacm_groupEntry *gp;
+ struct vacm_viewEntry *vp;
+ char vacm_default_context[1] = "";
+ char *contextName = vacm_default_context;
+ char *sn = NULL;
+ char *vn;
+ char *pdu_community;
+
+ /*
+ * len defined by the vacmContextName object
+ */
+#define CONTEXTNAMEINDEXLEN 32
+ char contextNameIndex[CONTEXTNAMEINDEXLEN + 1];
+
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+#if defined(NETSNMP_DISABLE_SNMPV1)
+ if (pdu->version == SNMP_VERSION_2c)
+#else
+#if defined(NETSNMP_DISABLE_SNMPV2C)
+ if (pdu->version == SNMP_VERSION_1)
+#else
+ if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c)
+#endif
+#endif
+ {
+ pdu_community = pdu->community;
+ if (!pdu_community)
+ pdu_community = "";
+ if (snmp_get_do_debugging()) {
+ char *buf;
+ if (pdu->community) {
+ buf = (char *) malloc(1 + pdu->community_len);
+ memcpy(buf, pdu->community, pdu->community_len);
+ buf[pdu->community_len] = '\0';
+ } else {
+ DEBUGMSGTL(("mibII/vacm_vars", "NULL community"));
+ buf = strdup("NULL");
+ }
+
+ DEBUGMSGTL(("mibII/vacm_vars",
+ "vacm_in_view: ver=%d, community=%s\n",
+ pdu->version, buf));
+ free(buf);
+ }
+
+ /*
+ * Okay, if this PDU was received from a UDP or a TCP transport then
+ * ask the transport abstraction layer to map its source address and
+ * community string to a security name for us.
+ */
+
+ if (pdu->tDomain == netsnmpUDPDomain
+#ifdef NETSNMP_TRANSPORT_TCP_DOMAIN
+ || pdu->tDomain == netsnmp_snmpTCPDomain
+#endif
+ ) {
+ if (!netsnmp_udp_getSecName(pdu->transport_data,
+ pdu->transport_data_length,
+ (char *) pdu_community,
+ pdu->community_len, &sn,
+ &contextName)) {
+ /*
+ * There are no com2sec entries.
+ */
+ sn = NULL;
+ }
+ /* force the community -> context name mapping here */
+ SNMP_FREE(pdu->contextName);
+ pdu->contextName = strdup(contextName);
+ pdu->contextNameLen = strlen(contextName);
+#ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
+ } else if (pdu->tDomain == netsnmp_UDPIPv6Domain
+#ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN
+ || pdu->tDomain == netsnmp_TCPIPv6Domain
+#endif
+ ) {
+ if (!netsnmp_udp6_getSecName(pdu->transport_data,
+ pdu->transport_data_length,
+ (char *) pdu_community,
+ pdu->community_len, &sn,
+ &contextName)) {
+ /*
+ * There are no com2sec entries.
+ */
+ sn = NULL;
+ }
+ /* force the community -> context name mapping here */
+ SNMP_FREE(pdu->contextName);
+ pdu->contextName = strdup(contextName);
+ pdu->contextNameLen = strlen(contextName);
+#endif
+#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
+ } else if (pdu->tDomain == netsnmp_UnixDomain){
+ if (!netsnmp_unix_getSecName(pdu->transport_data,
+ pdu->transport_data_length,
+ (char *) pdu_community,
+ pdu->community_len, &sn,
+ &contextName)) {
+ sn = NULL;
+ }
+ /* force the community -> context name mapping here */
+ SNMP_FREE(pdu->contextName);
+ pdu->contextName = strdup(contextName);
+ pdu->contextNameLen = strlen(contextName);
+#endif
+ } else {
+ /*
+ * Map other <community, transport-address> pairs to security names
+ * here. For now just let non-IPv4 transport always succeed.
+ *
+ * WHAAAATTTT. No, we don't let non-IPv4 transports
+ * succeed! You must fix this to make it usable, sorry.
+ * From a security standpoint this is insane. -- Wes
+ */
+ /** @todo alternate com2sec mappings for non v4 transports.
+ Should be implemented via registration */
+ sn = NULL;
+ }
+
+ } else
+#endif /* support for community based SNMP */
+ if (find_sec_mod(pdu->securityModel)) {
+ /*
+ * any legal defined v3 security model
+ */
+ DEBUGMSG(("mibII/vacm_vars",
+ "vacm_in_view: ver=%d, model=%d, secName=%s\n",
+ pdu->version, pdu->securityModel, pdu->securityName));
+ sn = pdu->securityName;
+ contextName = pdu->contextName;
+ } else {
+ sn = NULL;
+ }
+
+ if (sn == NULL) {
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+ snmp_increment_statistic(STAT_SNMPINBADCOMMUNITYNAMES);
+#endif
+ DEBUGMSGTL(("mibII/vacm_vars",
+ "vacm_in_view: No security name found\n"));
+ return VACM_NOSECNAME;
+ }
+
+ if (pdu->contextNameLen > CONTEXTNAMEINDEXLEN) {
+ DEBUGMSGTL(("mibII/vacm_vars",
+ "vacm_in_view: bad ctxt length %d\n",
+ pdu->contextNameLen));
+ return VACM_NOSUCHCONTEXT;
+ }
+ /*
+ * NULL termination of the pdu field is ugly here. Do in PDU parsing?
+ */
+ if (pdu->contextName)
+ strncpy(contextNameIndex, pdu->contextName, pdu->contextNameLen);
+ else
+ contextNameIndex[0] = '\0';
+
+ contextNameIndex[pdu->contextNameLen] = '\0';
+ if (!netsnmp_subtree_find_first(contextNameIndex)) {
+ /*
+ * rfc 3415 section 3.2, step 1
+ * no such context here; return no such context error
+ */
+ DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: no such ctxt \"%s\"\n",
+ contextNameIndex));
+ return VACM_NOSUCHCONTEXT;
+ }
+
+ DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: sn=%s", sn));
+
+ gp = vacm_getGroupEntry(pdu->securityModel, sn);
+ if (gp == NULL) {
+ DEBUGMSG(("mibII/vacm_vars", "\n"));
+ return VACM_NOGROUP;
+ }
+ DEBUGMSG(("mibII/vacm_vars", ", gn=%s", gp->groupName));
+
+ ap = vacm_getAccessEntry(gp->groupName, contextNameIndex,
+ pdu->securityModel, pdu->securityLevel);
+ if (ap == NULL) {
+ DEBUGMSG(("mibII/vacm_vars", "\n"));
+ return VACM_NOACCESS;
+ }
+
+ if (name == 0) { /* only check the setup of the vacm for the request */
+ DEBUGMSG(("mibII/vacm_vars", ", Done checking setup\n"));
+ return VACM_SUCCESS;
+ }
+
+ if (viewtype < 0 || viewtype >= VACM_MAX_VIEWS) {
+ DEBUGMSG(("mibII/vacm_vars", " illegal view type\n"));
+ return VACM_NOACCESS;
+ }
+ vn = ap->views[viewtype];
+ DEBUGMSG(("mibII/vacm_vars", ", vn=%s", vn));
+
+ if (check_subtree) {
+ DEBUGMSG(("mibII/vacm_vars", "\n"));
+ return vacm_checkSubtree(vn, name, namelen);
+ }
+
+ vp = vacm_getViewEntry(vn, name, namelen, VACM_MODE_FIND);
+
+ if (vp == NULL) {
+ DEBUGMSG(("mibII/vacm_vars", "\n"));
+ return VACM_NOVIEW;
+ }
+ DEBUGMSG(("mibII/vacm_vars", ", vt=%d\n", vp->viewType));
+
+ if (vp->viewType == SNMP_VIEW_EXCLUDED) {
+#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
+#if defined(NETSNMP_DISABLE_SNMPV1)
+ if (pdu->version == SNMP_VERSION_2c)
+#else
+#if defined(NETSNMP_DISABLE_SNMPV2C)
+ if (pdu->version == SNMP_VERSION_1)
+#else
+ if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c)
+#endif
+#endif
+ {
+ snmp_increment_statistic(STAT_SNMPINBADCOMMUNITYUSES);
+ }
+#endif
+ return VACM_NOTINVIEW;
+ }
+
+ return VACM_SUCCESS;
+
+} /* end vacm_in_view() */
+
+