diff options
Diffstat (limited to 'agent/mibgroup/snmpv3')
-rw-r--r-- | agent/mibgroup/snmpv3/snmpEngine.c | 246 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/snmpEngine.h | 33 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/snmpMPDStats.c | 69 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/snmpMPDStats.h | 30 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/snmpMPDStats_5_5.c | 51 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/snmpMPDStats_5_5.h | 10 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmConf.c | 9 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmConf.h | 8 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmStats.c | 76 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmStats.h | 35 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmStats_5_5.c | 51 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmStats_5_5.h | 10 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmUser.c | 1608 | ||||
-rw-r--r-- | agent/mibgroup/snmpv3/usmUser.h | 69 |
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 */ |