summaryrefslogtreecommitdiff
path: root/agent/mibgroup/snmpv3
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/snmpv3')
-rw-r--r--agent/mibgroup/snmpv3/snmpEngine.c246
-rw-r--r--agent/mibgroup/snmpv3/snmpEngine.h33
-rw-r--r--agent/mibgroup/snmpv3/snmpMPDStats.c69
-rw-r--r--agent/mibgroup/snmpv3/snmpMPDStats.h30
-rw-r--r--agent/mibgroup/snmpv3/snmpMPDStats_5_5.c51
-rw-r--r--agent/mibgroup/snmpv3/snmpMPDStats_5_5.h10
-rw-r--r--agent/mibgroup/snmpv3/usmConf.c9
-rw-r--r--agent/mibgroup/snmpv3/usmConf.h8
-rw-r--r--agent/mibgroup/snmpv3/usmStats.c76
-rw-r--r--agent/mibgroup/snmpv3/usmStats.h35
-rw-r--r--agent/mibgroup/snmpv3/usmStats_5_5.c51
-rw-r--r--agent/mibgroup/snmpv3/usmStats_5_5.h10
-rw-r--r--agent/mibgroup/snmpv3/usmUser.c1608
-rw-r--r--agent/mibgroup/snmpv3/usmUser.h69
14 files changed, 2305 insertions, 0 deletions
diff --git a/agent/mibgroup/snmpv3/snmpEngine.c b/agent/mibgroup/snmpv3/snmpEngine.c
new file mode 100644
index 0000000..e756788
--- /dev/null
+++ b/agent/mibgroup/snmpv3/snmpEngine.c
@@ -0,0 +1,246 @@
+/*
+ * snmpEngine.c: implement's the SNMP-FRAMEWORK-MIB.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/sysORTable.h>
+
+#include "util_funcs/header_generic.h"
+#include "snmpEngine.h"
+
+netsnmp_feature_child_of(snmpengine_all, libnetsnmpmibs)
+
+netsnmp_feature_child_of(register_snmpEngine_scalars_context, snmpengine_all)
+
+struct variable2 snmpEngine_variables[] = {
+ {SNMPENGINEID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_snmpEngine, 1, {1}},
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+#ifdef NETSNMP_ENABLE_TESTING_CODE
+ {SNMPENGINEBOOTS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_snmpEngine, 1, {2}},
+ {SNMPENGINETIME, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_snmpEngine, 1, {3}},
+#else /* !NETSNMP_ENABLE_TESTING_CODE */
+ {SNMPENGINEBOOTS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_snmpEngine, 1, {2}},
+ {SNMPENGINETIME, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_snmpEngine, 1, {3}},
+#endif /* NETSNMP_ENABLE_TESTING_CODE */
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ {SNMPENGINEBOOTS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_snmpEngine, 1, {2}},
+ {SNMPENGINETIME, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_snmpEngine, 1, {3}},
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ {SNMPENGINEMAXMESSAGESIZE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_snmpEngine, 1, {4}},
+};
+
+/*
+ * now load this mib into the agents mib table
+ */
+oid snmpEngine_variables_oid[] =
+ { 1, 3, 6, 1, 6, 3, 10, 2, 1 };
+
+void
+register_snmpEngine_scalars(void)
+{
+ REGISTER_MIB("snmpv3/snmpEngine", snmpEngine_variables, variable2,
+ snmpEngine_variables_oid);
+}
+
+#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_SNMPENGINE_SCALARS_CONTEXT
+void
+register_snmpEngine_scalars_context(const char *contextName)
+{
+ register_mib_context("snmpv3/snmpEngine",
+ (struct variable *) snmpEngine_variables,
+ sizeof(struct variable2),
+ sizeof(snmpEngine_variables)/sizeof(struct variable2),
+ snmpEngine_variables_oid,
+ sizeof(snmpEngine_variables_oid)/sizeof(oid),
+ DEFAULT_MIB_PRIORITY, 0, 0, NULL,
+ contextName, -1, 0);
+}
+#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_SNMPENGINE_SCALARS_CONTEXT */
+
+void
+init_snmpEngine(void)
+{
+ oid reg[] = { 1, 3, 6, 1, 6, 3, 10, 3, 1, 1 };
+ REGISTER_SYSOR_ENTRY(reg, "The SNMP Management Architecture MIB.");
+ register_snmpEngine_scalars();
+}
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+#ifdef NETSNMP_ENABLE_TESTING_CODE
+int write_engineBoots(int, u_char *, u_char, size_t, u_char *,
+ oid *, size_t);
+int write_engineTime(int, u_char *, u_char, size_t, u_char *,
+ oid *, size_t);
+#endif /* NETSNMP_ENABLE_TESTING_CODE */
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+u_char *
+var_snmpEngine(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ static unsigned char engineID[SNMP_MAXBUF];
+
+ *write_method = (WriteMethod*)0; /* assume it isnt writable for the time being */
+ *var_len = sizeof(long_ret); /* assume an integer and change later if not */
+
+ if (header_generic(vp, name, length, exact, var_len, write_method))
+ return NULL;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+ case SNMPENGINEID:
+ *var_len = snmpv3_get_engineID(engineID, SNMP_MAXBUF);
+ /*
+ * XXX Set ERROR_MSG() upon error?
+ */
+ return (unsigned char *) engineID;
+
+ case SNMPENGINEBOOTS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+#ifdef NETSNMP_ENABLE_TESTING_CODE
+ *write_method = write_engineBoots;
+#endif /* NETSNMP_ENABLE_TESTING_CODE */
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ long_ret = snmpv3_local_snmpEngineBoots();
+ return (unsigned char *) &long_ret;
+
+ case SNMPENGINETIME:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+#ifdef NETSNMP_ENABLE_TESTING_CODE
+ *write_method = write_engineTime;
+#endif /* NETSNMP_ENABLE_TESTING_CODE */
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ long_ret = snmpv3_local_snmpEngineTime();
+ return (unsigned char *) &long_ret;
+
+ case SNMPENGINEMAXMESSAGESIZE:
+ long_ret = 1500;
+ return (unsigned char *) &long_ret;
+
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_snmpEngine\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+#ifdef NETSNMP_ENABLE_TESTING_CODE
+/*
+ * write_engineBoots():
+ *
+ * This is technically not writable a writable mib object, but we
+ * allow it so we can run some time synchronization tests.
+ */
+int
+write_engineBoots(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ size_t size;
+ int bigsize = SNMP_MAXBUF_MEDIUM;
+ u_char engineIDBuf[SNMP_MAXBUF_MEDIUM];
+ int engineIDBufLen = 0;
+
+ if (var_val_type != ASN_INTEGER) {
+ DEBUGMSGTL(("snmpEngine",
+ "write to engineBoots not ASN_INTEGER\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > sizeof(long_ret)) {
+ DEBUGMSGTL(("snmpEngine", "write to engineBoots: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ long_ret = *((long *) var_val);
+ if (action == COMMIT) {
+ engineIDBufLen =
+ snmpv3_get_engineID(engineIDBuf, SNMP_MAXBUF_MEDIUM);
+ /*
+ * set our local engineTime in the LCD timing cache
+ */
+ snmpv3_set_engineBootsAndTime(long_ret,
+ snmpv3_local_snmpEngineTime());
+ set_enginetime(engineIDBuf, engineIDBufLen,
+ snmpv3_local_snmpEngineBoots(),
+ snmpv3_local_snmpEngineTime(), TRUE);
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+/*
+ * write_engineTime():
+ *
+ * This is technically not a writable mib object, but we
+ * allow it so we can run some time synchronization tests.
+ */
+int
+write_engineTime(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ size_t size;
+ int bigsize = SNMP_MAXBUF_MEDIUM;
+ u_char engineIDBuf[SNMP_MAXBUF_MEDIUM];
+ int engineIDBufLen = 0;
+
+ if (var_val_type != ASN_INTEGER) {
+ DEBUGMSGTL(("snmpEngine",
+ "write to engineTime not ASN_INTEGER\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > sizeof(long_ret)) {
+ DEBUGMSGTL(("snmpEngine", "write to engineTime: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ long_ret = *((long *) var_val);
+ if (action == COMMIT) {
+ engineIDBufLen =
+ snmpv3_get_engineID(engineIDBuf, SNMP_MAXBUF_MEDIUM);
+ /*
+ * set our local engineTime in the LCD timing cache
+ */
+ snmpv3_set_engineBootsAndTime(snmpv3_local_snmpEngineBoots(),
+ long_ret);
+ set_enginetime(engineIDBuf, engineIDBufLen,
+ snmpv3_local_snmpEngineBoots(),
+ snmpv3_local_snmpEngineTime(), TRUE);
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+#endif /* NETSNMP_ENABLE_TESTING_CODE */
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/snmpv3/snmpEngine.h b/agent/mibgroup/snmpv3/snmpEngine.h
new file mode 100644
index 0000000..b62a220
--- /dev/null
+++ b/agent/mibgroup/snmpv3/snmpEngine.h
@@ -0,0 +1,33 @@
+/*
+ * snmpEngine.h
+ *
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_SNMPENGINE_H
+#define _MIBGROUP_SNMPENGINE_H
+
+/*
+ * we use header_generic from the util_funcs module
+ */
+
+config_require(util_funcs/header_generic)
+config_add_mib(SNMP-FRAMEWORK-MIB)
+
+ /*
+ * Magic number definitions:
+ */
+#define SNMPENGINEID 1
+#define SNMPENGINEBOOTS 2
+#define SNMPENGINETIME 3
+#define SNMPENGINEMAXMESSAGESIZE 4
+ /*
+ * function definitions
+ */
+ extern void init_snmpEngine(void);
+ extern void register_snmpEngine_scalars_context(const char *contextName);
+ extern FindVarMethod var_snmpEngine;
+
+#endif /* _MIBGROUP_SNMPENGINE_H */
diff --git a/agent/mibgroup/snmpv3/snmpMPDStats.c b/agent/mibgroup/snmpv3/snmpMPDStats.c
new file mode 100644
index 0000000..ae792df
--- /dev/null
+++ b/agent/mibgroup/snmpv3/snmpMPDStats.c
@@ -0,0 +1,69 @@
+/*
+ * snmpMPDStats.c: tallies errors for SNMPv3 message processing.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/sysORTable.h>
+
+#include "snmpMPDStats.h"
+#include "util_funcs/header_generic.h"
+
+
+struct variable2 snmpMPDStats_variables[] = {
+ {SNMPUNKNOWNSECURITYMODELS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_snmpMPDStats, 1, {1}},
+ {SNMPINVALIDMSGS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_snmpMPDStats, 1, {2}},
+ {SNMPUNKNOWNPDUHANDLERS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_snmpMPDStats, 1, {3}},
+};
+
+/*
+ * now load this mib into the agents mib table
+ */
+oid snmpMPDStats_variables_oid[] =
+ { 1, 3, 6, 1, 6, 3, 11, 2, 1 };
+
+void
+init_snmpMPDStats(void)
+{
+ static oid reg[] = { 1, 3, 6, 1, 6, 3, 11, 3, 1, 1 };
+ REGISTER_SYSOR_ENTRY(reg,
+ "The MIB for Message Processing and Dispatching.");
+ REGISTER_MIB("snmpv3/snmpMPDStats", snmpMPDStats_variables, variable2,
+ snmpMPDStats_variables_oid);
+}
+
+u_char *
+var_snmpMPDStats(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ int tmagic;
+
+
+ *write_method = 0; /* assume it isnt writable for the time being */
+ *var_len = sizeof(long_ret); /* assume an integer and change later if not */
+
+ if (header_generic(vp, name, length, exact, var_len, write_method))
+ return 0;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ tmagic = vp->magic;
+ if ((tmagic >= 0)
+ && (tmagic <= (STAT_MPD_STATS_END - STAT_MPD_STATS_START))) {
+ long_ret = snmp_get_statistic(tmagic + STAT_MPD_STATS_START);
+ return (unsigned char *) &long_ret;
+ }
+ return 0;
+}
diff --git a/agent/mibgroup/snmpv3/snmpMPDStats.h b/agent/mibgroup/snmpv3/snmpMPDStats.h
new file mode 100644
index 0000000..41eab1d
--- /dev/null
+++ b/agent/mibgroup/snmpv3/snmpMPDStats.h
@@ -0,0 +1,30 @@
+
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+#ifndef _MIBGROUP_SNMPMPDSTATS_H
+#define _MIBGROUP_SNMPMPDSTATS_H
+
+/*
+ * we use header_generic from the util_funcs module
+ */
+
+config_require(util_funcs/header_generic)
+config_exclude(snmpv3/snmpMPDStats_5_5)
+config_add_mib(SNMP-MPD-MIB)
+
+ /*
+ * Magic number definitions:
+ */
+#define SNMPUNKNOWNSECURITYMODELS 0
+#define SNMPINVALIDMSGS 1
+#define SNMPUNKNOWNPDUHANDLERS 2
+ /*
+ * function definitions
+ */
+ void init_snmpMPDStats(void);
+ extern FindVarMethod var_snmpMPDStats;
+
+#endif /* _MIBGROUP_SNMPMPDSTATS_H */
diff --git a/agent/mibgroup/snmpv3/snmpMPDStats_5_5.c b/agent/mibgroup/snmpv3/snmpMPDStats_5_5.c
new file mode 100644
index 0000000..a7fc2ce
--- /dev/null
+++ b/agent/mibgroup/snmpv3/snmpMPDStats_5_5.c
@@ -0,0 +1,51 @@
+/*
+ * snmpMPDStats.c: tallies errors for SNMPv3 message processing.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+
+#include <net-snmp/net-snmp-features.h>
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/sysORTable.h>
+
+#include "snmpMPDStats_5_5.h"
+
+#include <net-snmp/agent/snmp_get_statistic.h>
+
+#define snmpMPDMIB 1, 3, 6, 1, 6, 3, 11
+#define snmpMPDMIBObjects snmpMPDMIB, 2
+#define snmpMPDMIBCompliances snmpMPDMIB, 3, 1
+
+netsnmp_feature_require(helper_statistics)
+
+static oid snmpMPDStats[] = { snmpMPDMIBObjects, 1 };
+
+static netsnmp_handler_registration* snmpMPDStats_reg = NULL;
+static oid snmpMPDCompliance[] = { snmpMPDMIBCompliances, 1 };
+
+void
+init_snmpMPDStats_5_5(void)
+{
+ netsnmp_handler_registration* s =
+ netsnmp_create_handler_registration(
+ "snmpMPDStats", NULL, snmpMPDStats, OID_LENGTH(snmpMPDStats),
+ HANDLER_CAN_RONLY);
+ if (s &&
+ NETSNMP_REGISTER_STATISTIC_HANDLER(s, 1, MPD) == MIB_REGISTERED_OK) {
+ REGISTER_SYSOR_ENTRY(snmpMPDCompliance,
+ "The MIB for Message Processing and Dispatching.");
+ snmpMPDStats_reg = s;
+ }
+}
+
+void
+shutdown_snmpMPDStats_5_5(void)
+{
+ UNREGISTER_SYSOR_ENTRY(snmpMPDCompliance);
+ if (snmpMPDStats_reg) {
+ netsnmp_unregister_handler(snmpMPDStats_reg);
+ snmpMPDStats_reg = NULL;
+ }
+}
diff --git a/agent/mibgroup/snmpv3/snmpMPDStats_5_5.h b/agent/mibgroup/snmpv3/snmpMPDStats_5_5.h
new file mode 100644
index 0000000..78f3dff
--- /dev/null
+++ b/agent/mibgroup/snmpv3/snmpMPDStats_5_5.h
@@ -0,0 +1,10 @@
+#ifndef _MIBGROUP_SNMPMPDSTATS_H
+#define _MIBGROUP_SNMPMPDSTATS_H
+
+config_exclude(snmpv3/snmpMPDStats)
+config_add_mib(SNMP-MPD-MIB)
+
+void init_snmpMPDStats_5_5(void);
+void shutdown_snmpMPDStats_5_5(void);
+
+#endif /* _MIBGROUP_SNMPMPDSTATS_H */
diff --git a/agent/mibgroup/snmpv3/usmConf.c b/agent/mibgroup/snmpv3/usmConf.c
new file mode 100644
index 0000000..20bcff9
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmConf.c
@@ -0,0 +1,9 @@
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+void
+init_usmConf(void)
+{
+ init_usm_conf(NULL);
+}
diff --git a/agent/mibgroup/snmpv3/usmConf.h b/agent/mibgroup/snmpv3/usmConf.h
new file mode 100644
index 0000000..d27f12e
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmConf.h
@@ -0,0 +1,8 @@
+#ifndef _MIBGROUP_USMCONF_H
+#define _MIBGROUP_USMCONF_H
+
+#include <net-snmp/library/snmpusm.h>
+config_belongs_in(agent_module)
+extern void init_usmConf(void);
+
+#endif /* _MIBGROUP_USMCONF_H */
diff --git a/agent/mibgroup/snmpv3/usmStats.c b/agent/mibgroup/snmpv3/usmStats.c
new file mode 100644
index 0000000..718e071
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmStats.c
@@ -0,0 +1,76 @@
+
+/*
+ * usmStats.c: implements the usmStats portion of the SNMP-USER-BASED-SM-MIB
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/sysORTable.h>
+
+#include "util_funcs/header_generic.h"
+#include "usmStats.h"
+
+struct variable2 usmStats_variables[] = {
+ {USMSTATSUNSUPPORTEDSECLEVELS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_usmStats, 1, {1}},
+ {USMSTATSNOTINTIMEWINDOWS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_usmStats, 1, {2}},
+ {USMSTATSUNKNOWNUSERNAMES, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_usmStats, 1, {3}},
+ {USMSTATSUNKNOWNENGINEIDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_usmStats, 1, {4}},
+ {USMSTATSWRONGDIGESTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_usmStats, 1, {5}},
+ {USMSTATSDECRYPTIONERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_usmStats, 1, {6}},
+};
+
+/*
+ * now load this mib into the agents mib table
+ */
+oid usmStats_variables_oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1 };
+
+
+void
+init_usmStats(void)
+{
+ static oid reg[] = { 1, 3, 6, 1, 6, 3, 15, 2, 1, 1 };
+ REGISTER_SYSOR_ENTRY(reg,
+ "The management information definitions for the "
+ "SNMP User-based Security Model.");
+ REGISTER_MIB("snmpv3/usmStats", usmStats_variables, variable2,
+ usmStats_variables_oid);
+}
+
+u_char *
+var_usmStats(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ int tmagic;
+
+ *write_method = 0; /* assume it isnt writable for the time being */
+ *var_len = sizeof(long_ret); /* assume an integer and change later if not */
+
+ if (header_generic(vp, name, length, exact, var_len, write_method))
+ return 0;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ tmagic = vp->magic;
+ if ((tmagic >= 0)
+ && (tmagic <= (STAT_USM_STATS_END - STAT_USM_STATS_START))) {
+ long_ret = snmp_get_statistic(tmagic + STAT_USM_STATS_START);
+ return (unsigned char *) &long_ret;
+ }
+
+ return 0;
+}
diff --git a/agent/mibgroup/snmpv3/usmStats.h b/agent/mibgroup/snmpv3/usmStats.h
new file mode 100644
index 0000000..5685381
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmStats.h
@@ -0,0 +1,35 @@
+/*
+ * usmStats.h
+ *
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+#ifndef _MIBGROUP_USMSTATS_H
+#define _MIBGROUP_USMSTATS_H
+
+/*
+ * we use header_generic from the util_funcs module
+ */
+
+config_require(util_funcs/header_generic)
+config_exclude(snmpv3/usmStats_5_5)
+config_add_mib(SNMP-USER-BASED-SM-MIB)
+
+ /*
+ * Magic number definitions:
+ */
+#define USMSTATSUNSUPPORTEDSECLEVELS 0
+#define USMSTATSNOTINTIMEWINDOWS 1
+#define USMSTATSUNKNOWNUSERNAMES 2
+#define USMSTATSUNKNOWNENGINEIDS 3
+#define USMSTATSWRONGDIGESTS 4
+#define USMSTATSDECRYPTIONERRORS 5
+ /*
+ * function definitions
+ */
+ extern void init_usmStats(void);
+ extern FindVarMethod var_usmStats;
+
+
+#endif /* _MIBGROUP_USMSTATS_H */
diff --git a/agent/mibgroup/snmpv3/usmStats_5_5.c b/agent/mibgroup/snmpv3/usmStats_5_5.c
new file mode 100644
index 0000000..bcd04e1
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmStats_5_5.c
@@ -0,0 +1,51 @@
+/*
+ * usmStats.c: implements the usmStats portion of the SNMP-USER-BASED-SM-MIB
+ */
+
+#include <net-snmp/net-snmp-config.h>
+
+#include <net-snmp/net-snmp-features.h>
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/sysORTable.h>
+
+#include "usmStats_5_5.h"
+
+#include <net-snmp/agent/snmp_get_statistic.h>
+
+#define snmpUsmMIB 1, 3, 6, 1, 6, 3, 15
+#define usmMIBCompliances snmpUsmMIB, 2, 1
+
+static oid usmStats[] = { snmpUsmMIB, 1, 1 };
+
+static netsnmp_handler_registration* usmStats_reg = NULL;
+static oid usmMIBCompliance[] = { usmMIBCompliances, 1 };
+
+netsnmp_feature_require(helper_statistics)
+
+void
+init_usmStats_5_5(void)
+{
+ netsnmp_handler_registration* s =
+ netsnmp_create_handler_registration(
+ "usmStats", NULL, usmStats, OID_LENGTH(usmStats),
+ HANDLER_CAN_RONLY);
+ if (s &&
+ NETSNMP_REGISTER_STATISTIC_HANDLER(s, 1, USM) == MIB_REGISTERED_OK) {
+ REGISTER_SYSOR_ENTRY(usmMIBCompliance,
+ "The management information definitions for the "
+ "SNMP User-based Security Model.");
+ usmStats_reg = s;
+ }
+}
+
+void
+shutdown_usmStats_5_5(void)
+{
+ UNREGISTER_SYSOR_ENTRY(usmMIBCompliance);
+ if (usmStats_reg) {
+ netsnmp_unregister_handler(usmStats_reg);
+ usmStats_reg = NULL;
+ }
+}
diff --git a/agent/mibgroup/snmpv3/usmStats_5_5.h b/agent/mibgroup/snmpv3/usmStats_5_5.h
new file mode 100644
index 0000000..d30719e
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmStats_5_5.h
@@ -0,0 +1,10 @@
+#ifndef _MIBGROUP_USMSTATS_H
+#define _MIBGROUP_USMSTATS_H
+
+config_exclude(snmpv3/usmStats)
+config_add_mib(SNMP-USER-BASED-SM-MIB)
+
+void init_usmStats_5_5(void);
+void shutdown_usmStats_5_5(void);
+
+#endif /* _MIBGROUP_USMSTATS_H */
diff --git a/agent/mibgroup/snmpv3/usmUser.c b/agent/mibgroup/snmpv3/usmUser.c
new file mode 100644
index 0000000..41c525a
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmUser.c
@@ -0,0 +1,1608 @@
+/*
+ * usmUser.c
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <stdlib.h>
+
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "util_funcs/header_generic.h"
+#include "usmUser.h"
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int usmStatusCheck(struct usmUser *uptr);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+netsnmp_feature_child_of(usmuser_all, libnetsnmpmibs)
+netsnmp_feature_child_of(init_register_usmuser_context, usmuser_all)
+
+struct variable4 usmUser_variables[] = {
+ {USMUSERSPINLOCK, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 1, {1}},
+ {USMUSERSECURITYNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_usmUser, 3, {2, 1, 3}},
+ {USMUSERCLONEFROM, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 4}},
+ {USMUSERAUTHPROTOCOL, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 5}},
+ {USMUSERAUTHKEYCHANGE, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 6}},
+ {USMUSEROWNAUTHKEYCHANGE, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 7}},
+ {USMUSERPRIVPROTOCOL, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 8}},
+ {USMUSERPRIVKEYCHANGE, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 9}},
+ {USMUSEROWNPRIVKEYCHANGE, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 10}},
+ {USMUSERPUBLIC, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 11}},
+ {USMUSERSTORAGETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 12}},
+ {USMUSERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_usmUser, 3, {2, 1, 13}},
+
+};
+
+oid usmUser_variables_oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 2 };
+
+
+/*
+ * needed for the write_ functions to find the start of the index
+ */
+#define USM_MIB_LENGTH 12
+
+static unsigned int usmUserSpinLock = 0;
+
+void
+init_usmUser(void)
+{
+ REGISTER_MIB("snmpv3/usmUser", usmUser_variables, variable4,
+ usmUser_variables_oid);
+}
+
+#ifndef NETSNMP_FEATURE_REMOVE_INIT_REGISTER_USMUSER_CONTEXT
+void
+init_register_usmUser_context(const char *contextName) {
+ register_mib_context("snmpv3/usmUser",
+ (struct variable *) usmUser_variables,
+ sizeof(struct variable4),
+ sizeof(usmUser_variables)/sizeof(struct variable4),
+ usmUser_variables_oid,
+ sizeof(usmUser_variables_oid)/sizeof(oid),
+ DEFAULT_MIB_PRIORITY, 0, 0, NULL,
+ contextName, -1, 0);
+}
+#endif /* NETSNMP_FEATURE_REMOVE_INIT_REGISTER_USMUSER_CONTEXT */
+
+/*******************************************************************-o-******
+ * usm_generate_OID
+ *
+ * Parameters:
+ * *prefix (I) OID prefix to the usmUser table entry.
+ * prefixLen (I)
+ * *uptr (I) Pointer to a user in the user list.
+ * *length (O) Length of generated index OID.
+ *
+ * Returns:
+ * Pointer to the OID index for the user (uptr) -OR-
+ * NULL on failure.
+ *
+ *
+ * Generate the index OID for a given usmUser name. 'length' is set to
+ * the length of the index OID.
+ *
+ * Index OID format is:
+ *
+ * <...prefix>.<engineID_length>.<engineID>.<user_name_length>.<user_name>
+ */
+oid *
+usm_generate_OID(oid * prefix, size_t prefixLen, struct usmUser *uptr,
+ size_t * length)
+{
+ oid *indexOid;
+ int i;
+
+ *length = 2 + uptr->engineIDLen + strlen(uptr->name) + prefixLen;
+ indexOid = (oid *) malloc(*length * sizeof(oid));
+ if (indexOid) {
+ memmove(indexOid, prefix, prefixLen * sizeof(oid));
+
+ indexOid[prefixLen] = uptr->engineIDLen;
+ for (i = 0; i < (int) uptr->engineIDLen; i++)
+ indexOid[prefixLen + 1 + i] = (oid) uptr->engineID[i];
+
+ indexOid[prefixLen + uptr->engineIDLen + 1] = strlen(uptr->name);
+ for (i = 0; i < (int) strlen(uptr->name); i++)
+ indexOid[prefixLen + uptr->engineIDLen + 2 + i] =
+ (oid) uptr->name[i];
+ }
+ return indexOid;
+
+} /* end usm_generate_OID() */
+
+/*
+ * usm_parse_oid(): parses an index to the usmTable to break it down into
+ * a engineID component and a name component. The results are stored in:
+ *
+ * **engineID: a newly malloced string.
+ * *engineIDLen: The length of the malloced engineID string above.
+ * **name: a newly malloced string.
+ * *nameLen: The length of the malloced name string above.
+ *
+ * returns 1 if an error is encountered, or 0 if successful.
+ */
+int
+usm_parse_oid(oid * oidIndex, size_t oidLen,
+ unsigned char **engineID, size_t * engineIDLen,
+ unsigned char **name, size_t * nameLen)
+{
+ int nameL;
+ int engineIDL;
+ int i;
+
+ /*
+ * first check the validity of the oid
+ */
+ if ((oidLen <= 0) || (!oidIndex)) {
+ DEBUGMSGTL(("usmUser",
+ "parse_oid: null oid or zero length oid passed in\n"));
+ return 1;
+ }
+ engineIDL = *oidIndex; /* initial engineID length */
+ if ((int) oidLen < engineIDL + 2) {
+ DEBUGMSGTL(("usmUser",
+ "parse_oid: invalid oid length: less than the engineIDLen\n"));
+ return 1;
+ }
+ nameL = oidIndex[engineIDL + 1]; /* the initial name length */
+ if ((int) oidLen != engineIDL + nameL + 2) {
+ DEBUGMSGTL(("usmUser",
+ "parse_oid: invalid oid length: length is not exact\n"));
+ return 1;
+ }
+
+ /*
+ * its valid, malloc the space and store the results
+ */
+ if (engineID == NULL || name == NULL) {
+ DEBUGMSGTL(("usmUser",
+ "parse_oid: null storage pointer passed in.\n"));
+ return 1;
+ }
+
+ *engineID = (unsigned char *) malloc(engineIDL);
+ if (*engineID == NULL) {
+ DEBUGMSGTL(("usmUser",
+ "parse_oid: malloc of the engineID failed\n"));
+ return 1;
+ }
+ *engineIDLen = engineIDL;
+
+ *name = (unsigned char *) malloc(nameL + 1);
+ if (*name == NULL) {
+ DEBUGMSGTL(("usmUser", "parse_oid: malloc of the name failed\n"));
+ free(*engineID);
+ return 1;
+ }
+ *nameLen = nameL;
+
+ for (i = 0; i < engineIDL; i++) {
+ if (oidIndex[i + 1] > 255) {
+ goto UPO_parse_error;
+ }
+ engineID[0][i] = (unsigned char) oidIndex[i + 1];
+ }
+
+ for (i = 0; i < nameL; i++) {
+ if (oidIndex[i + 2 + engineIDL] > 255) {
+ UPO_parse_error:
+ free(*engineID);
+ free(*name);
+ return 1;
+ }
+ name[0][i] = (unsigned char) oidIndex[i + 2 + engineIDL];
+ }
+ name[0][nameL] = 0;
+
+ return 0;
+
+} /* end usm_parse_oid() */
+
+/*******************************************************************-o-******
+ * usm_parse_user
+ *
+ * Parameters:
+ * *name Complete OID indexing a given usmUser entry.
+ * name_length
+ *
+ * Returns:
+ * Pointer to a usmUser -OR-
+ * NULL if name does not convert to a usmUser.
+ *
+ * Convert an (full) OID and return a pointer to a matching user in the
+ * user list if one exists.
+ */
+struct usmUser *
+usm_parse_user(oid * name, size_t name_len)
+{
+ struct usmUser *uptr;
+
+ char *newName;
+ u_char *engineID;
+ size_t nameLen, engineIDLen;
+
+ /*
+ * get the name and engineID out of the incoming oid
+ */
+ if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
+ &engineID, &engineIDLen, (u_char **) & newName,
+ &nameLen))
+ return NULL;
+
+ /*
+ * Now see if a user exists with these index values
+ */
+ uptr = usm_get_user(engineID, engineIDLen, newName);
+ free(engineID);
+ free(newName);
+
+ return uptr;
+
+} /* end usm_parse_user() */
+
+/*******************************************************************-o-******
+ * var_usmUser
+ *
+ * Parameters:
+ * *vp (I) Variable-binding associated with this action.
+ * *name (I/O) Input name requested, output name found.
+ * *length (I/O) Length of input and output oid's.
+ * exact (I) TRUE if an exact match was requested.
+ * *var_len (O) Length of variable or 0 if function returned.
+ * (**write_method) Hook to name a write method (UNUSED).
+ *
+ * Returns:
+ * Pointer to (char *) containing related data of length 'length'
+ * (May be NULL.)
+ *
+ *
+ * Call-back function passed to the agent in order to return information
+ * for the USM MIB tree.
+ *
+ *
+ * If this invocation is not for USMUSERSPINLOCK, lookup user name
+ * in the usmUser list.
+ *
+ * If the name does not match any user and the request
+ * is for an exact match, -or- if the usmUser list is empty, create a
+ * new list entry.
+ *
+ * Finally, service the given USMUSER* var-bind. A NULL user generally
+ * results in a NULL return value.
+ */
+u_char *
+var_usmUser(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ struct usmUser *uptr = NULL, *nptr;
+ int i, rtest, result;
+ oid *indexOid;
+ size_t len;
+
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ static u_char string[1];
+ static oid objid[2]; /* for .0.0 */
+
+ if (!vp || !name || !length || !var_len)
+ return NULL;
+
+ /* assume it isnt writable for the time being */
+ *write_method = (WriteMethod*)0;
+
+ /* assume an integer and change later if not */
+ *var_len = sizeof(long_ret);
+
+ if (vp->magic != USMUSERSPINLOCK) {
+ oid newname[MAX_OID_LEN];
+ len = (*length < vp->namelen) ? *length : vp->namelen;
+ rtest = snmp_oid_compare(name, len, vp->name, len);
+ if (rtest > 0 ||
+ /*
+ * (rtest == 0 && !exact && (int) vp->namelen+1 < (int) *length) ||
+ */
+ (exact == 1 && rtest != 0)) {
+ if (var_len)
+ *var_len = 0;
+ return NULL;
+ }
+ memset(newname, 0, sizeof(newname));
+ if (((int) *length) <= (int) vp->namelen || rtest == -1) {
+ /*
+ * oid is not within our range yet
+ */
+ /*
+ * need to fail if not exact
+ */
+ uptr = usm_get_userList();
+
+ } else {
+ for (nptr = usm_get_userList(), uptr = NULL;
+ nptr != NULL; nptr = nptr->next) {
+ indexOid =
+ usm_generate_OID(vp->name, vp->namelen, nptr, &len);
+ result = snmp_oid_compare(name, *length, indexOid, len);
+ DEBUGMSGTL(("usmUser", "Checking user: %s - ",
+ nptr->name));
+ for (i = 0; i < (int) nptr->engineIDLen; i++) {
+ DEBUGMSG(("usmUser", " %x", nptr->engineID[i]));
+ }
+ DEBUGMSG(("usmUser", " - %d \n -> OID: ", result));
+ DEBUGMSGOID(("usmUser", indexOid, len));
+ DEBUGMSG(("usmUser", "\n"));
+
+ free(indexOid);
+
+ if (exact) {
+ if (result == 0) {
+ uptr = nptr;
+ }
+ } else {
+ if (result == 0) {
+ /*
+ * found an exact match. Need the next one for !exact
+ */
+ uptr = nptr->next;
+ } else if (result == -1) {
+ uptr = nptr;
+ break;
+ }
+ }
+ }
+ } /* endif -- name <= vp->name */
+
+ /*
+ * if uptr is NULL and exact we need to continue for creates
+ */
+ if (uptr == NULL && !exact)
+ return (NULL);
+
+ if (uptr) {
+ indexOid = usm_generate_OID(vp->name, vp->namelen, uptr, &len);
+ *length = len;
+ memmove(name, indexOid, len * sizeof(oid));
+
+ DEBUGMSGTL(("usmUser", "Found user: %s - ", uptr->name));
+ for (i = 0; i < (int) uptr->engineIDLen; i++) {
+ DEBUGMSG(("usmUser", " %x", uptr->engineID[i]));
+ }
+ DEBUGMSG(("usmUser", "\n -> OID: "));
+ DEBUGMSGOID(("usmUser", indexOid, len));
+ DEBUGMSG(("usmUser", "\n"));
+
+ free(indexOid);
+ }
+ } else {
+ if (header_generic(vp, name, length, exact, var_len, write_method))
+ return NULL;
+ } /* endif -- vp->magic != USMUSERSPINLOCK */
+
+ switch (vp->magic) {
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ case USMUSERSPINLOCK:
+ *write_method = write_usmUserSpinLock;
+ long_ret = usmUserSpinLock;
+ return (unsigned char *) &long_ret;
+
+ case USMUSERSECURITYNAME:
+ if (uptr) {
+ *var_len = strlen(uptr->secName);
+ return (unsigned char *) uptr->secName;
+ }
+ return NULL;
+
+ case USMUSERCLONEFROM:
+ *write_method = write_usmUserCloneFrom;
+ if (uptr) {
+ objid[0] = 0; /* "When this object is read, the ZeroDotZero OID */
+ objid[1] = 0; /* is returned." */
+ *var_len = sizeof(oid) * 2;
+ return (unsigned char *) objid;
+ }
+ return NULL;
+
+ case USMUSERAUTHPROTOCOL:
+ *write_method = write_usmUserAuthProtocol;
+ if (uptr) {
+ *var_len = uptr->authProtocolLen * sizeof(oid);
+ return (u_char *) uptr->authProtocol;
+ }
+ return NULL;
+
+ case USMUSERAUTHKEYCHANGE:
+ case USMUSEROWNAUTHKEYCHANGE:
+ /*
+ * we treat these the same, and let the calling module
+ * distinguish between them
+ */
+ *write_method = write_usmUserAuthKeyChange;
+ if (uptr) {
+ *string = 0; /* always return a NULL string */
+ *var_len = 0;
+ return string;
+ }
+ return NULL;
+
+ case USMUSERPRIVPROTOCOL:
+ *write_method = write_usmUserPrivProtocol;
+ if (uptr) {
+ *var_len = uptr->privProtocolLen * sizeof(oid);
+ return (u_char *) uptr->privProtocol;
+ }
+ return NULL;
+
+ case USMUSERPRIVKEYCHANGE:
+ case USMUSEROWNPRIVKEYCHANGE:
+ /*
+ * we treat these the same, and let the calling module
+ * distinguish between them
+ */
+ *write_method = write_usmUserPrivKeyChange;
+ if (uptr) {
+ *string = 0; /* always return a NULL string */
+ *var_len = 0;
+ return string;
+ }
+ return NULL;
+
+ case USMUSERPUBLIC:
+ *write_method = write_usmUserPublic;
+ if (uptr) {
+ if (uptr->userPublicString) {
+ *var_len = uptr->userPublicStringLen;
+ return uptr->userPublicString;
+ }
+ *string = 0;
+ *var_len = 0; /* return an empty string if the public
+ * string hasn't been defined yet */
+ return string;
+ }
+ return NULL;
+
+ case USMUSERSTORAGETYPE:
+ *write_method = write_usmUserStorageType;
+ if (uptr) {
+ long_ret = uptr->userStorageType;
+ return (unsigned char *) &long_ret;
+ }
+ return NULL;
+
+ case USMUSERSTATUS:
+ *write_method = write_usmUserStatus;
+ if (uptr) {
+ long_ret = uptr->userStatus;
+ return (unsigned char *) &long_ret;
+ }
+ return NULL;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_usmUser\n",
+ vp->magic));
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ default:
+ DEBUGMSGTL(("snmpd", "no write support for var_usmUser\n"));
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return NULL;
+
+} /* end var_usmUser() */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+
+/*
+ * write_usmUserSpinLock(): called when a set is performed on the
+ * usmUserSpinLock object
+ */
+int
+write_usmUserSpinLock(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+
+ if (var_val_type != ASN_INTEGER) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserSpinLock not ASN_INTEGER\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > sizeof(long_ret)) {
+ DEBUGMSGTL(("usmUser", "write to usmUserSpinLock: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ long_ret = *((long *) var_val);
+ if (long_ret != (long) usmUserSpinLock)
+ return SNMP_ERR_INCONSISTENTVALUE;
+ if (action == COMMIT) {
+ if (usmUserSpinLock == 2147483647)
+ usmUserSpinLock = 0;
+ else
+ usmUserSpinLock++;
+ }
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserSpinLock() */
+
+/*******************************************************************-o-******
+ * write_usmUserCloneFrom
+ *
+ * Parameters:
+ * action
+ * *var_val
+ * var_val_type
+ * var_val_len
+ * *statP (UNUSED)
+ * *name OID of user to clone from.
+ * name_len
+ *
+ * Returns:
+ * SNMP_ERR_NOERROR On success -OR- If user exists
+ * and has already been cloned.
+ * SNMP_ERR_GENERR Local function call failures.
+ * SNMP_ERR_INCONSISTENTNAME 'name' does not exist in user list
+ * -OR- user to clone from != RS_ACTIVE.
+ * SNMP_ERR_WRONGLENGTH OID length > than local buffer size.
+ * SNMP_ERR_WRONGTYPE ASN_OBJECT_ID is wrong.
+ *
+ *
+ * XXX: should handle action=UNDO's.
+ */
+int
+write_usmUserCloneFrom(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct usmUser *uptr, *cloneFrom;
+
+ if (action == RESERVE1) {
+ if (var_val_type != ASN_OBJECT_ID) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserCloneFrom not ASN_OBJECT_ID\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > USM_LENGTH_OID_MAX * sizeof(oid) ||
+ var_val_len % sizeof(oid) != 0) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserCloneFrom: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ } else if (action == RESERVE2) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ /*
+ * We don't allow creations here.
+ */
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+ /*
+ * Has the user already been cloned? If so, writes to this variable
+ * are defined to have no effect and to produce no error.
+ */
+ if (uptr->cloneFrom != NULL) {
+ return SNMP_ERR_NOERROR;
+ }
+
+ cloneFrom =
+ usm_parse_user((oid *) var_val, var_val_len / sizeof(oid));
+ if (cloneFrom == NULL || cloneFrom->userStatus != SNMP_ROW_ACTIVE) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ uptr->cloneFrom = snmp_duplicate_objid((oid *) var_val,
+ var_val_len / sizeof(oid));
+ usm_cloneFrom_user(cloneFrom, uptr);
+
+ if (usmStatusCheck(uptr) && uptr->userStatus == SNMP_ROW_NOTREADY) {
+ uptr->userStatus = SNMP_ROW_NOTINSERVICE;
+ }
+ }
+
+ return SNMP_ERR_NOERROR;
+}
+
+/*******************************************************************-o-******
+ * write_usmUserAuthProtocol
+ *
+ * Parameters:
+ * action
+ * *var_val OID of auth transform to set.
+ * var_val_type
+ * var_val_len
+ * *statP
+ * *name OID of user upon which to perform set operation.
+ * name_len
+ *
+ * Returns:
+ * SNMP_ERR_NOERROR On success.
+ * SNMP_ERR_GENERR
+ * SNMP_ERR_INCONSISTENTVALUE
+ * SNMP_ERR_NOSUCHNAME
+ * SNMP_ERR_WRONGLENGTH
+ * SNMP_ERR_WRONGTYPE
+ */
+int
+write_usmUserAuthProtocol(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *optr;
+ static size_t olen;
+ static int resetOnFail;
+ struct usmUser *uptr;
+
+ if (action == RESERVE1) {
+ resetOnFail = 0;
+ if (var_val_type != ASN_OBJECT_ID) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserAuthProtocol not ASN_OBJECT_ID\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > USM_LENGTH_OID_MAX * sizeof(oid) ||
+ var_val_len % sizeof(oid) != 0) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserAuthProtocol: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ } else if (action == RESERVE2) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+ if (uptr->userStatus == RS_ACTIVE
+ || uptr->userStatus == RS_NOTREADY
+ || uptr->userStatus == RS_NOTINSERVICE) {
+ /*
+ * The authProtocol is already set. It is only legal to CHANGE it
+ * to usmNoAuthProtocol...
+ */
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmNoAuthProtocol,
+ sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0) {
+ /*
+ * ... and then only if the privProtocol is equal to
+ * usmNoPrivProtocol.
+ */
+ if (snmp_oid_compare
+ (uptr->privProtocol, uptr->privProtocolLen,
+ usmNoPrivProtocol,
+ sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ optr = uptr->authProtocol;
+ olen = uptr->authProtocolLen;
+ resetOnFail = 1;
+ uptr->authProtocol = snmp_duplicate_objid((oid *) var_val,
+ var_val_len /
+ sizeof(oid));
+ if (uptr->authProtocol == NULL) {
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->authProtocolLen = var_val_len / sizeof(oid);
+ } else
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ uptr->authProtocol, uptr->authProtocolLen) == 0) {
+ /*
+ * But it's also okay to set it to the same thing as it
+ * currently is.
+ */
+ return SNMP_ERR_NOERROR;
+ } else {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * This row is under creation. It's okay to set
+ * usmUserAuthProtocol to any valid authProtocol but it will be
+ * overwritten when usmUserCloneFrom is set (so don't write it if
+ * that has already been set).
+ */
+
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmNoAuthProtocol,
+ sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0
+#ifndef NETSNMP_DISABLE_MD5
+ || snmp_oid_compare((oid *) var_val,
+ var_val_len / sizeof(oid),
+ usmHMACMD5AuthProtocol,
+ sizeof(usmHMACMD5AuthProtocol) /
+ sizeof(oid)) == 0
+#endif
+ || snmp_oid_compare((oid *) var_val,
+ var_val_len / sizeof(oid),
+ usmHMACSHA1AuthProtocol,
+ sizeof(usmHMACSHA1AuthProtocol) /
+ sizeof(oid)) == 0) {
+ if (uptr->cloneFrom != NULL) {
+ optr = uptr->authProtocol;
+ olen = uptr->authProtocolLen;
+ resetOnFail = 1;
+ uptr->authProtocol =
+ snmp_duplicate_objid((oid *) var_val,
+ var_val_len / sizeof(oid));
+ if (uptr->authProtocol == NULL) {
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->authProtocolLen = var_val_len / sizeof(oid);
+ }
+ } else {
+ /*
+ * Unknown authentication protocol.
+ */
+ return SNMP_ERR_WRONGVALUE;
+ }
+ }
+ } else if (action == COMMIT) {
+ SNMP_FREE(optr);
+ } else if (action == FREE || action == UNDO) {
+ if ((uptr = usm_parse_user(name, name_len)) != NULL) {
+ if (resetOnFail) {
+ SNMP_FREE(uptr->authProtocol);
+ uptr->authProtocol = optr;
+ uptr->authProtocolLen = olen;
+ }
+ }
+ }
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserAuthProtocol() */
+
+/*******************************************************************-o-******
+ * write_usmUserAuthKeyChange
+ *
+ * Parameters:
+ * action
+ * *var_val Octet string representing new KeyChange value.
+ * var_val_type
+ * var_val_len
+ * *statP (UNUSED)
+ * *name OID of user upon which to perform set operation.
+ * name_len
+ *
+ * Returns:
+ * SNMP_ERR_NOERR Success.
+ * SNMP_ERR_WRONGTYPE
+ * SNMP_ERR_WRONGLENGTH
+ * SNMP_ERR_NOSUCHNAME
+ * SNMP_ERR_GENERR
+ *
+ * Note: This function handles both the usmUserAuthKeyChange and
+ * usmUserOwnAuthKeyChange objects. We are not passed the name
+ * of the user requseting the keychange, so we leave this to the
+ * calling module to verify when and if we should be called. To
+ * change this would require a change in the mib module API to
+ * pass in the securityName requesting the change.
+ *
+ * XXX: should handle action=UNDO's.
+ */
+int
+write_usmUserAuthKeyChange(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct usmUser *uptr;
+ unsigned char buf[SNMP_MAXBUF_SMALL];
+ size_t buflen = SNMP_MAXBUF_SMALL;
+ const char fnAuthKey[] = "write_usmUserAuthKeyChange";
+ const char fnOwnAuthKey[] = "write_usmUserOwnAuthKeyChange";
+ const char *fname;
+ static unsigned char *oldkey;
+ static size_t oldkeylen;
+ static int resetOnFail;
+
+ if (name[USM_MIB_LENGTH - 1] == 6) {
+ fname = fnAuthKey;
+ } else {
+ fname = fnOwnAuthKey;
+ }
+
+ if (action == RESERVE1) {
+ resetOnFail = 0;
+ if (var_val_type != ASN_OCTET_STR) {
+ DEBUGMSGTL(("usmUser", "write to %s not ASN_OCTET_STR\n",
+ fname));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len == 0) {
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ } else if (action == RESERVE2) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ } else {
+#ifndef NETSNMP_DISABLE_MD5
+ if (snmp_oid_compare(uptr->authProtocol, uptr->authProtocolLen,
+ usmHMACMD5AuthProtocol,
+ sizeof(usmHMACMD5AuthProtocol) /
+ sizeof(oid)) == 0) {
+ if (var_val_len != 0 && var_val_len != 32) {
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ } else
+#endif
+ if (snmp_oid_compare
+ (uptr->authProtocol, uptr->authProtocolLen,
+ usmHMACSHA1AuthProtocol,
+ sizeof(usmHMACSHA1AuthProtocol) / sizeof(oid)) == 0) {
+ if (var_val_len != 0 && var_val_len != 40) {
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ }
+ }
+ } else if (action == ACTION) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ if (uptr->cloneFrom == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ if (snmp_oid_compare(uptr->authProtocol, uptr->authProtocolLen,
+ usmNoAuthProtocol,
+ sizeof(usmNoAuthProtocol) / sizeof(oid)) ==
+ 0) {
+ /*
+ * "When the value of the corresponding usmUserAuthProtocol is
+ * usmNoAuthProtocol, then a set is successful, but effectively
+ * is a no-op."
+ */
+ DEBUGMSGTL(("usmUser",
+ "%s: noAuthProtocol keyChange... success!\n",
+ fname));
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * Change the key.
+ */
+ DEBUGMSGTL(("usmUser", "%s: changing auth key for user %s\n",
+ fname, uptr->secName));
+
+ if (decode_keychange(uptr->authProtocol, uptr->authProtocolLen,
+ uptr->authKey, uptr->authKeyLen,
+ var_val, var_val_len,
+ buf, &buflen) != SNMPERR_SUCCESS) {
+ DEBUGMSGTL(("usmUser", "%s: ... failed\n", fname));
+ return SNMP_ERR_GENERR;
+ }
+ DEBUGMSGTL(("usmUser", "%s: ... succeeded\n", fname));
+ resetOnFail = 1;
+ oldkey = uptr->authKey;
+ oldkeylen = uptr->authKeyLen;
+ memdup(&uptr->authKey, buf, buflen);
+ if (uptr->authKey == NULL) {
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->authKeyLen = buflen;
+ } else if (action == COMMIT) {
+ SNMP_FREE(oldkey);
+ } else if (action == UNDO) {
+ if ((uptr = usm_parse_user(name, name_len)) != NULL && resetOnFail) {
+ SNMP_FREE(uptr->authKey);
+ uptr->authKey = oldkey;
+ uptr->authKeyLen = oldkeylen;
+ }
+ }
+
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserAuthKeyChange() */
+
+int
+write_usmUserPrivProtocol(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *optr;
+ static size_t olen;
+ static int resetOnFail;
+ struct usmUser *uptr;
+
+ if (action == RESERVE1) {
+ resetOnFail = 0;
+ if (var_val_type != ASN_OBJECT_ID) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserPrivProtocol not ASN_OBJECT_ID\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > USM_LENGTH_OID_MAX * sizeof(oid) ||
+ var_val_len % sizeof(oid) != 0) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserPrivProtocol: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ } else if (action == RESERVE2) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+ if (uptr->userStatus == RS_ACTIVE
+ || uptr->userStatus == RS_NOTREADY
+ || uptr->userStatus == RS_NOTINSERVICE) {
+ /*
+ * The privProtocol is already set. It is only legal to CHANGE it
+ * to usmNoPrivProtocol.
+ */
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmNoPrivProtocol,
+ sizeof(usmNoPrivProtocol) / sizeof(oid)) == 0) {
+ resetOnFail = 1;
+ optr = uptr->privProtocol;
+ olen = uptr->privProtocolLen;
+ uptr->privProtocol = snmp_duplicate_objid((oid *) var_val,
+ var_val_len /
+ sizeof(oid));
+ if (uptr->privProtocol == NULL) {
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->privProtocolLen = var_val_len / sizeof(oid);
+ } else
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ uptr->privProtocol, uptr->privProtocolLen) == 0) {
+ /*
+ * But it's also okay to set it to the same thing as it
+ * currently is.
+ */
+ return SNMP_ERR_NOERROR;
+ } else {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * This row is under creation. It's okay to set
+ * usmUserPrivProtocol to any valid privProtocol with the proviso
+ * that if usmUserAuthProtocol is set to usmNoAuthProtocol, it may
+ * only be set to usmNoPrivProtocol. The value will be overwritten
+ * when usmUserCloneFrom is set (so don't write it if that has
+ * already been set).
+ */
+ if (snmp_oid_compare(uptr->authProtocol, uptr->authProtocolLen,
+ usmNoAuthProtocol,
+ sizeof(usmNoAuthProtocol) /
+ sizeof(oid)) == 0) {
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmNoPrivProtocol,
+ sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ if (snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmNoPrivProtocol,
+ sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0
+#ifndef NETSNMP_DISABLE_DES
+ && snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmDESPrivProtocol,
+ sizeof(usmDESPrivProtocol) / sizeof(oid)) != 0
+#endif
+ && snmp_oid_compare
+ ((oid *) var_val, var_val_len / sizeof(oid),
+ usmAESPrivProtocol,
+ sizeof(usmAESPrivProtocol) / sizeof(oid)) != 0) {
+ return SNMP_ERR_WRONGVALUE;
+ }
+ }
+ resetOnFail = 1;
+ optr = uptr->privProtocol;
+ olen = uptr->privProtocolLen;
+ uptr->privProtocol = snmp_duplicate_objid((oid *) var_val,
+ var_val_len /
+ sizeof(oid));
+ if (uptr->privProtocol == NULL) {
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->privProtocolLen = var_val_len / sizeof(oid);
+ }
+ } else if (action == COMMIT) {
+ SNMP_FREE(optr);
+ } else if (action == FREE || action == UNDO) {
+ if ((uptr = usm_parse_user(name, name_len)) != NULL) {
+ if (resetOnFail) {
+ SNMP_FREE(uptr->privProtocol);
+ uptr->privProtocol = optr;
+ uptr->privProtocolLen = olen;
+ }
+ }
+ }
+
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserPrivProtocol() */
+
+/*
+ * Note: This function handles both the usmUserPrivKeyChange and
+ * usmUserOwnPrivKeyChange objects. We are not passed the name
+ * of the user requseting the keychange, so we leave this to the
+ * calling module to verify when and if we should be called. To
+ * change this would require a change in the mib module API to
+ * pass in the securityName requesting the change.
+ *
+ */
+int
+write_usmUserPrivKeyChange(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct usmUser *uptr;
+ unsigned char buf[SNMP_MAXBUF_SMALL];
+ size_t buflen = SNMP_MAXBUF_SMALL;
+ const char fnPrivKey[] = "write_usmUserPrivKeyChange";
+ const char fnOwnPrivKey[] = "write_usmUserOwnPrivKeyChange";
+ const char *fname;
+ static unsigned char *oldkey;
+ static size_t oldkeylen;
+ static int resetOnFail;
+
+ if (name[USM_MIB_LENGTH - 1] == 9) {
+ fname = fnPrivKey;
+ } else {
+ fname = fnOwnPrivKey;
+ }
+
+ if (action == RESERVE1) {
+ resetOnFail = 0;
+ if (var_val_type != ASN_OCTET_STR) {
+ DEBUGMSGTL(("usmUser", "write to %s not ASN_OCTET_STR\n",
+ fname));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len == 0) {
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ } else if (action == RESERVE2) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ } else {
+#ifndef NETSNMP_DISABLE_DES
+ if (snmp_oid_compare(uptr->privProtocol, uptr->privProtocolLen,
+ usmDESPrivProtocol,
+ sizeof(usmDESPrivProtocol) /
+ sizeof(oid)) == 0) {
+ if (var_val_len != 0 && var_val_len != 32) {
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ }
+#endif
+ if (snmp_oid_compare(uptr->privProtocol, uptr->privProtocolLen,
+ usmAESPrivProtocol,
+ sizeof(usmAESPrivProtocol) /
+ sizeof(oid)) == 0) {
+ if (var_val_len != 0 && var_val_len != 32) {
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ }
+ }
+ } else if (action == ACTION) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ if (uptr->cloneFrom == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ if (snmp_oid_compare(uptr->privProtocol, uptr->privProtocolLen,
+ usmNoPrivProtocol,
+ sizeof(usmNoPrivProtocol) / sizeof(oid)) ==
+ 0) {
+ /*
+ * "When the value of the corresponding usmUserPrivProtocol is
+ * usmNoPrivProtocol, then a set is successful, but effectively
+ * is a no-op."
+ */
+ DEBUGMSGTL(("usmUser",
+ "%s: noPrivProtocol keyChange... success!\n",
+ fname));
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * Change the key.
+ */
+ DEBUGMSGTL(("usmUser", "%s: changing priv key for user %s\n",
+ fname, uptr->secName));
+
+ if (decode_keychange(uptr->authProtocol, uptr->authProtocolLen,
+ uptr->privKey, uptr->privKeyLen,
+ var_val, var_val_len,
+ buf, &buflen) != SNMPERR_SUCCESS) {
+ DEBUGMSGTL(("usmUser", "%s: ... failed\n", fname));
+ return SNMP_ERR_GENERR;
+ }
+ DEBUGMSGTL(("usmUser", "%s: ... succeeded\n", fname));
+ resetOnFail = 1;
+ oldkey = uptr->privKey;
+ oldkeylen = uptr->privKeyLen;
+ memdup(&uptr->privKey, buf, buflen);
+ if (uptr->privKey == NULL) {
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->privKeyLen = buflen;
+ } else if (action == COMMIT) {
+ SNMP_FREE(oldkey);
+ } else if (action == UNDO) {
+ if ((uptr = usm_parse_user(name, name_len)) != NULL && resetOnFail) {
+ SNMP_FREE(uptr->privKey);
+ uptr->privKey = oldkey;
+ uptr->privKeyLen = oldkeylen;
+ }
+ }
+
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserPrivKeyChange() */
+
+int
+write_usmUserPublic(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct usmUser *uptr = NULL;
+
+ if (var_val_type != ASN_OCTET_STR) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserPublic not ASN_OCTET_STR\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > 32) {
+ DEBUGMSGTL(("usmUser", "write to usmUserPublic: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ if (action == COMMIT) {
+ /*
+ * don't allow creations here
+ */
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_NOSUCHNAME;
+ }
+ if (uptr->userPublicString)
+ free(uptr->userPublicString);
+ uptr->userPublicString = (u_char *) malloc(var_val_len);
+ if (uptr->userPublicString == NULL) {
+ return SNMP_ERR_GENERR;
+ }
+ memcpy(uptr->userPublicString, var_val, var_val_len);
+ uptr->userPublicStringLen = var_val_len;
+ DEBUGMSG(("usmUser", "setting public string: %d - ", (int)var_val_len));
+ DEBUGMSGHEX(("usmUser", uptr->userPublicString, var_val_len));
+ DEBUGMSG(("usmUser", "\n"));
+ }
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserPublic() */
+
+int
+write_usmUserStorageType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ long long_ret = *((long *) var_val);
+ static long oldValue;
+ struct usmUser *uptr;
+ static int resetOnFail;
+
+ if (action == RESERVE1) {
+ resetOnFail = 0;
+ if (var_val_type != ASN_INTEGER) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserStorageType not ASN_INTEGER\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len != sizeof(long)) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserStorageType: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ if (long_ret < 1 || long_ret > 5) {
+ return SNMP_ERR_WRONGVALUE;
+ }
+ } else if (action == RESERVE2) {
+ if ((uptr = usm_parse_user(name, name_len)) == NULL) {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ if ((long_ret == ST_VOLATILE || long_ret == ST_NONVOLATILE) &&
+ (uptr->userStorageType == ST_VOLATILE ||
+ uptr->userStorageType == ST_NONVOLATILE)) {
+ oldValue = uptr->userStorageType;
+ uptr->userStorageType = long_ret;
+ resetOnFail = 1;
+ } else {
+ /*
+ * From RFC2574:
+ *
+ * "Note that any user who employs authentication or privacy must
+ * allow its secret(s) to be updated and thus cannot be 'readOnly'.
+ *
+ * If an initial set operation tries to set the value to 'readOnly'
+ * for a user who employs authentication or privacy, then an
+ * 'inconsistentValue' error must be returned. Note that if the
+ * value has been previously set (implicit or explicit) to any
+ * value, then the rules as defined in the StorageType Textual
+ * Convention apply.
+ */
+ DEBUGMSGTL(("usmUser",
+ "long_ret %ld uptr->st %d uptr->status %d\n",
+ long_ret, uptr->userStorageType,
+ uptr->userStatus));
+
+ if (long_ret == ST_READONLY &&
+ uptr->userStorageType != ST_READONLY &&
+ (uptr->userStatus == RS_ACTIVE ||
+ uptr->userStatus == RS_NOTINSERVICE)) {
+ return SNMP_ERR_WRONGVALUE;
+ } else if (long_ret == ST_READONLY &&
+ (snmp_oid_compare
+ (uptr->privProtocol, uptr->privProtocolLen,
+ usmNoPrivProtocol,
+ sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0
+ || snmp_oid_compare(uptr->authProtocol,
+ uptr->authProtocolLen,
+ usmNoAuthProtocol,
+ sizeof(usmNoAuthProtocol) /
+ sizeof(oid)) != 0)) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ } else {
+ return SNMP_ERR_WRONGVALUE;
+ }
+ }
+ } else if (action == UNDO || action == FREE) {
+ if ((uptr = usm_parse_user(name, name_len)) != NULL && resetOnFail) {
+ uptr->userStorageType = oldValue;
+ }
+ }
+ return SNMP_ERR_NOERROR;
+} /* end write_usmUserStorageType() */
+
+
+/*
+ * Return 1 if enough objects have been set up to transition rowStatus to
+ * notInService(2) or active(1).
+ */
+
+int
+usmStatusCheck(struct usmUser *uptr)
+{
+ if (uptr == NULL) {
+ return 0;
+ } else {
+ if (uptr->cloneFrom == NULL) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*******************************************************************-o-******
+ * write_usmUserStatus
+ *
+ * Parameters:
+ * action
+ * *var_val
+ * var_val_type
+ * var_val_len
+ * *statP
+ * *name
+ * name_len
+ *
+ * Returns:
+ * SNMP_ERR_NOERROR On success.
+ * SNMP_ERR_GENERR
+ * SNMP_ERR_INCONSISTENTNAME
+ * SNMP_ERR_INCONSISTENTVALUE
+ * SNMP_ERR_WRONGLENGTH
+ * SNMP_ERR_WRONGTYPE
+ */
+int
+write_usmUserStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ /*
+ * variables we may use later
+ */
+ static long long_ret;
+ unsigned char *engineID;
+ size_t engineIDLen;
+ char *newName;
+ size_t nameLen;
+ struct usmUser *uptr = NULL;
+
+ if (action == RESERVE1) {
+ if (var_val_type != ASN_INTEGER) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserStatus not ASN_INTEGER\n"));
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len != sizeof(long_ret)) {
+ DEBUGMSGTL(("usmUser",
+ "write to usmUserStatus: bad length\n"));
+ return SNMP_ERR_WRONGLENGTH;
+ }
+ long_ret = *((long *) var_val);
+ if (long_ret == RS_NOTREADY || long_ret < 1 || long_ret > 6) {
+ return SNMP_ERR_WRONGVALUE;
+ }
+
+ /*
+ * See if we can parse the oid for engineID/name first.
+ */
+ if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
+ &engineID, &engineIDLen, (u_char **) & newName,
+ &nameLen)) {
+ DEBUGMSGTL(("usmUser",
+ "can't parse the OID for engineID or name\n"));
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+ if (engineIDLen < 5 || engineIDLen > 32 || nameLen < 1
+ || nameLen > 32) {
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ return SNMP_ERR_NOCREATION;
+ }
+
+ /*
+ * Now see if a user already exists with these index values.
+ */
+ uptr = usm_get_user(engineID, engineIDLen, newName);
+
+ if (uptr != NULL) {
+ if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ long_ret = RS_NOTREADY;
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ } else {
+ if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) {
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
+ if ((uptr = usm_create_user()) == NULL) {
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->engineID = engineID;
+ uptr->name = newName;
+ uptr->secName = strdup(uptr->name);
+ if (uptr->secName == NULL) {
+ usm_free_user(uptr);
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+ }
+ uptr->engineIDLen = engineIDLen;
+
+ /*
+ * Set status to createAndGo or createAndWait so we can tell
+ * that this row is under creation.
+ */
+
+ uptr->userStatus = long_ret;
+
+ /*
+ * Add to the list of users (we will take it off again
+ * later if something goes wrong).
+ */
+
+ usm_add_user(uptr);
+ } else {
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ }
+ }
+ } else if (action == ACTION) {
+ usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
+ &engineID, &engineIDLen, (u_char **) & newName,
+ &nameLen);
+ uptr = usm_get_user(engineID, engineIDLen, newName);
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+
+ if (uptr != NULL) {
+ if (long_ret == RS_CREATEANDGO || long_ret == RS_ACTIVE) {
+ if (usmStatusCheck(uptr)) {
+ uptr->userStatus = RS_ACTIVE;
+ } else {
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else if (long_ret == RS_CREATEANDWAIT) {
+ if (usmStatusCheck(uptr)) {
+ uptr->userStatus = RS_NOTINSERVICE;
+ } else {
+ uptr->userStatus = RS_NOTREADY;
+ }
+ } else if (long_ret == RS_NOTINSERVICE) {
+ if (uptr->userStatus == RS_ACTIVE ||
+ uptr->userStatus == RS_NOTINSERVICE) {
+ uptr->userStatus = RS_NOTINSERVICE;
+ } else {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ }
+ }
+ } else if (action == COMMIT) {
+ usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
+ &engineID, &engineIDLen, (u_char **) & newName,
+ &nameLen);
+ uptr = usm_get_user(engineID, engineIDLen, newName);
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+
+ if (uptr != NULL) {
+ if (long_ret == RS_DESTROY) {
+ usm_remove_user(uptr);
+ usm_free_user(uptr);
+ }
+ }
+ } else if (action == UNDO || action == FREE) {
+ if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
+ &engineID, &engineIDLen, (u_char **) & newName,
+ &nameLen)) {
+ /* Can't extract engine info from the OID - nothing to undo */
+ return SNMP_ERR_NOERROR;
+ }
+ uptr = usm_get_user(engineID, engineIDLen, newName);
+ SNMP_FREE(engineID);
+ SNMP_FREE(newName);
+
+ if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
+ usm_remove_user(uptr);
+ usm_free_user(uptr);
+ }
+ }
+
+ return SNMP_ERR_NOERROR;
+} /* write_usmUserStatus */
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+#if 0
+
+ /*
+ * see if we can parse the oid for engineID/name first
+ */
+if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
+ &engineID, &engineIDLen, (u_char **) & newName,
+ &nameLen))
+ return SNMP_ERR_INCONSISTENTNAME;
+
+ /*
+ * Now see if a user already exists with these index values
+ */
+uptr = usm_get_user(engineID, engineIDLen, newName);
+
+
+if (uptr) { /* If so, we set the appropriate value... */
+ free(engineID);
+ free(newName);
+ if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (long_ret == RS_DESTROY) {
+ usm_remove_user(uptr);
+ usm_free_user(uptr);
+ } else {
+ uptr->userStatus = long_ret;
+ }
+
+} else { /* ...else we create a new user */
+ /*
+ * check for a valid status column set
+ */
+ if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) {
+ free(engineID);
+ free(newName);
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (long_ret == RS_DESTROY) {
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ free(engineID);
+ free(newName);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * generate a new user
+ */
+ if ((uptr = usm_create_user()) == NULL) {
+ free(engineID);
+ free(newName);
+ return SNMP_ERR_GENERR;
+ }
+
+ /*
+ * copy in the engineID
+ */
+ uptr->engineID = (unsigned char *) malloc(engineIDLen);
+ if (uptr->engineID == NULL) {
+ free(engineID);
+ free(newName);
+ usm_free_user(uptr);
+ return SNMP_ERR_GENERR;
+ }
+ uptr->engineIDLen = engineIDLen;
+ memcpy(uptr->engineID, engineID, engineIDLen);
+ free(engineID);
+
+ /*
+ * copy in the name and secname
+ */
+ if ((uptr->name = strdup(newName)) == NULL) {
+ free(newName);
+ usm_free_user(uptr);
+ return SNMP_ERR_GENERR;
+ }
+ free(newName);
+ if ((uptr->secName = strdup(uptr->name)) == NULL) {
+ usm_free_user(uptr);
+ return SNMP_ERR_GENERR;
+ }
+
+ /*
+ * set the status of the row based on the request
+ */
+ if (long_ret == RS_CREATEANDGO)
+ uptr->userStatus = RS_ACTIVE;
+ else if (long_ret == RS_CREATEANDWAIT)
+ uptr->userStatus = RS_NOTINSERVICE;
+
+ /*
+ * finally, add it to our list of users
+ */
+ usm_add_user(uptr);
+
+} /* endif -- uptr */
+} /* endif -- action==COMMIT */
+
+return SNMP_ERR_NOERROR;
+
+} /* end write_usmUserStatus() */
+#endif
diff --git a/agent/mibgroup/snmpv3/usmUser.h b/agent/mibgroup/snmpv3/usmUser.h
new file mode 100644
index 0000000..53d1412
--- /dev/null
+++ b/agent/mibgroup/snmpv3/usmUser.h
@@ -0,0 +1,69 @@
+/*
+ * usmUser.h
+ *
+ */
+
+#ifndef _MIBGROUP_USMUSER_H
+#define _MIBGROUP_USMUSER_H
+
+#include <net-snmp/library/snmpusm.h>
+
+/*
+ * <...prefix>.<engineID_length>.<engineID>.<user_name_length>.<user_name>
+ * = 1 + 32 + 1 + 32
+ */
+#define USM_LENGTH_OID_MAX 66
+
+/*
+ * we use header_generic from the util_funcs module
+ */
+
+config_require(util_funcs/header_generic)
+config_add_mib(SNMP-USER-BASED-SM-MIB)
+
+ /*
+ * Magic number definitions:
+ */
+#define USMUSERSPINLOCK 1
+#define USMUSERSECURITYNAME 2
+#define USMUSERCLONEFROM 3
+#define USMUSERAUTHPROTOCOL 4
+#define USMUSERAUTHKEYCHANGE 5
+#define USMUSEROWNAUTHKEYCHANGE 6
+#define USMUSERPRIVPROTOCOL 7
+#define USMUSERPRIVKEYCHANGE 8
+#define USMUSEROWNPRIVKEYCHANGE 9
+#define USMUSERPUBLIC 10
+#define USMUSERSTORAGETYPE 11
+#define USMUSERSTATUS 12
+ /*
+ * function definitions
+ */
+ extern void init_usmUser(void);
+ extern FindVarMethod var_usmUser;
+ void init_register_usmUser_context(const char *contextName);
+
+ void shutdown_usmUser(void);
+ int store_usmUser(int majorID, int minorID,
+ void *serverarg, void *clientarg);
+ oid *usm_generate_OID(oid * prefix, size_t prefixLen,
+ struct usmUser *uptr,
+ size_t * length);
+ int usm_parse_oid(oid * oidIndex, size_t oidLen,
+ unsigned char **engineID,
+ size_t * engineIDLen,
+ unsigned char **name, size_t * nameLen);
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_usmUserSpinLock;
+ WriteMethod write_usmUserCloneFrom;
+ WriteMethod write_usmUserAuthProtocol;
+ WriteMethod write_usmUserAuthKeyChange;
+ WriteMethod write_usmUserPrivProtocol;
+ WriteMethod write_usmUserPrivKeyChange;
+ WriteMethod write_usmUserPublic;
+ WriteMethod write_usmUserStorageType;
+ WriteMethod write_usmUserStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+#endif /* _MIBGROUP_USMUSER_H */