summaryrefslogtreecommitdiffstats
path: root/contrib/bsnmp/snmp_usm
diff options
context:
space:
mode:
authorsyrinx <syrinx@FreeBSD.org>2010-12-08 13:51:38 +0000
committersyrinx <syrinx@FreeBSD.org>2010-12-08 13:51:38 +0000
commited79f703fb1803e10222fccd98100334741138ff (patch)
tree30b62404bfa57932ef78fb729b57635b158c2a4a /contrib/bsnmp/snmp_usm
parent6e855a313aac604a57c7b9d8561a9a4e5c2f6666 (diff)
downloadFreeBSD-src-ed79f703fb1803e10222fccd98100334741138ff.zip
FreeBSD-src-ed79f703fb1803e10222fccd98100334741138ff.tar.gz
In bsnmpd(1) add support for SNMPv3 message processing model, including message authentication, packet encryption & view-based access control (RFC 3412, 3414, 3415).
Sponsored by: The FreeBSD Foundation Reviewed by: philip@ (mostly) Approved by: philip@
Diffstat (limited to 'contrib/bsnmp/snmp_usm')
-rwxr-xr-xcontrib/bsnmp/snmp_usm/snmp_usm.3132
-rwxr-xr-xcontrib/bsnmp/snmp_usm/usm_snmp.c614
-rwxr-xr-xcontrib/bsnmp/snmp_usm/usm_tree.def109
3 files changed, 855 insertions, 0 deletions
diff --git a/contrib/bsnmp/snmp_usm/snmp_usm.3 b/contrib/bsnmp/snmp_usm/snmp_usm.3
new file mode 100755
index 0000000..7fd0817
--- /dev/null
+++ b/contrib/bsnmp/snmp_usm/snmp_usm.3
@@ -0,0 +1,132 @@
+.\"-
+.\" Copyright (C) 2010 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Shteryana Sotirova Shopova under
+.\" sponsorship from the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 9, 2010
+.Dt SNMP_USM 3
+.Os
+.Sh NAME
+.Nm snmp_usm
+.Nd "user-based security module for
+.Xr bsnmpd 1
+.Sh LIBRARY
+.Pq begemotSnmpdModulePath."usm" = "/usr/lib/snmp_usm.so"
+.Sh DESCRIPTION
+The
+.Nm snmp_usm
+module implements SNMPv3 User-Based Security Model MIB as defined in RFC 3414.
+The module is used to manage the internal list of SNMPv3 USM active users in
+.Nm bsnmpd .
+The module must be loaded for
+.Nm bsnmpd
+to receive and process SNMPv3 USM PDUs correctly.
+.Sh IMPLEMENTATION NOTES
+A short description of the objects in the MIB follows.
+.Bl -tag -width "XXXXXXXXX"
+.It Va usmStats
+The subtree contains statistics for the User-based Security Model PDU processing.
+The statistics are reset each time the module is loaded.
+.It Va usmUserSpinLock
+An advisory lock used to coordinate several Command Generator Applications when
+altering the SNMP USM users.
+.It Va usmUserTable
+The table contains all SNMP USM users configured in
+.Nm bsnmpd.
+The table contains the following objects
+.Bl -tag -width ".It Va usmUserEngineID"
+.It Va usmUserEngineID
+An SNMP engine's administratively-unique identifier. Must be set to the same
+Engine ID as
+.Nm bsnmpd
+so that the user will actually be allowed to communicate with the daemon.
+The column is used as entry key and is not accessible for GET or SET operations.
+.It Va usmUserName
+The USM user name. The second entry key, again not accessible for GET or SET
+operations.
+.It Va usmUserSecurityName
+The column has the exact same value as the
+.Va usmUserName
+column, however is accessible for GET operations.
+.It Va usmUserCloneFrom
+A GET on this column will return an empty OID. SET operations are currently not
+supported.
+.It Va usmUserAuthProtocol
+The value of this column contains the OID corresponding to the authentication
+protocol used by the USM user. The following protocols and their OIDs are known to
+.Nm
+module
+.Bl -tag -width ".It Va NoAuthProtocol"
+.It NoAuthProtocol 1.3.6.1.6.3.10.1.1.1
+.It HMACMD5AuthProtocol 1.3.6.1.6.3.10.1.1.2
+.It HMACSHAAuthProtocol 1.3.6.1.6.3.10.1.1.3
+.El
+.It Va usmUserAuthKeyChange , Va usmUserOwnAuthKeyChange
+These columns may be used to change the user's authentication key.
+.It Va usmUserPrivProtocol
+The value of this column contains the OID corresponding to the privacy
+protocol used by the USM user. The following protocols and their OIDs are known to
+.Nm
+module
+.Bl -tag -width ".It Va NoPrivProtocol"
+.It NoPrivProtocol 1.3.6.1.6.3.10.1.2.1
+.It DESPrivProtoco 1.3.6.1.6.3.10.1.2.2
+.It AesCfb128Protocol 1.3.6.1.6.3.10.1.2.4
+.El
+.It Va usmUserPrivKeyChange , Va usmUserOwnPrivKeyChange
+These columns may be used to change the user's privacy key.
+.It Va usmUserPublic
+An arbitrary octet string that may be modified to confirm a SET operation on any
+of the columns was successfull.
+.It Va usmUserStorageType
+This column always has either of two values. Entries created via
+.Nm bsnmpd's
+configuration file always have this column set to readOnly (5) and
+it is not possible to modify those entries. Entries created by Command Generator
+Applications always have this column set to volatile(2) and such entries are
+lost when the module is restarted. A SET operation on this column is not
+allowed.
+.It Va usmUserStatus
+This column is used to create new USM user entries or delete exsiting ones from
+the table.
+.El
+.EL
+.Sh FILES
+.Bl -tag -width "XXXXXXXXX"
+.It Pa /usr/share/snmp/defs/usm_tree.def
+The description of the MIB tree implemented by
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr bsnmpd 1 ,
+.Xr gensnmptree 1 ,
+.Xr snmpmod 3
+.Sh STANDARDS
+IETF RFC 3414
+.Sh AUTHORS
+.An Shteryana Shopova Aq syrinx@FreeBSD.org
diff --git a/contrib/bsnmp/snmp_usm/usm_snmp.c b/contrib/bsnmp/snmp_usm/usm_snmp.c
new file mode 100755
index 0000000..d5350bc
--- /dev/null
+++ b/contrib/bsnmp/snmp_usm/usm_snmp.c
@@ -0,0 +1,614 @@
+/*-
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Shteryana Sotirova Shopova under
+ * sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "asn1.h"
+#include "snmp.h"
+#include "snmpmod.h"
+
+#include "usm_tree.h"
+#include "usm_oid.h"
+
+static struct lmodule *usm_module;
+/* For the registration. */
+static const struct asn_oid oid_usm = OIDX_snmpUsmMIB;
+
+static const struct asn_oid oid_usmNoAuthProtocol = OIDX_usmNoAuthProtocol;
+static const struct asn_oid oid_usmHMACMD5AuthProtocol = \
+ OIDX_usmHMACMD5AuthProtocol;
+static const struct asn_oid oid_usmHMACSHAAuthProtocol = \
+ OIDX_usmHMACSHAAuthProtocol;
+
+static const struct asn_oid oid_usmNoPrivProtocol = OIDX_usmNoPrivProtocol;
+static const struct asn_oid oid_usmDESPrivProtocol = OIDX_usmDESPrivProtocol;
+static const struct asn_oid oid_usmAesCfb128Protocol = OIDX_usmAesCfb128Protocol;
+
+static const struct asn_oid oid_usmUserSecurityName = OIDX_usmUserSecurityName;
+
+/* The registration. */
+static uint reg_usm;
+
+static int32_t usm_lock;
+
+static struct usm_user * usm_get_user(const struct asn_oid *, uint);
+static struct usm_user * usm_get_next_user(const struct asn_oid *, uint);
+static void usm_append_userindex(struct asn_oid *, uint,
+ const struct usm_user *);
+static int usm_user_index_decode(const struct asn_oid *, uint, uint8_t *,
+ uint32_t *, char *);
+
+int
+op_usm_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub __unused, uint32_t iidx __unused, enum snmp_op op)
+{
+ struct snmpd_usmstat *usmstats;
+
+ if (op == SNMP_OP_SET)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ if ((usmstats = bsnmpd_get_usm_stats()) == NULL)
+ return (SNMP_ERR_GENERR);
+
+ if (op == SNMP_OP_GET) {
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_usmStatsUnsupportedSecLevels:
+ val->v.uint32 = usmstats->unsupported_seclevels;
+ break;
+ case LEAF_usmStatsNotInTimeWindows:
+ val->v.uint32 = usmstats->not_in_time_windows;
+ break;
+ case LEAF_usmStatsUnknownUserNames:
+ val->v.uint32 = usmstats->unknown_users;
+ break;
+ case LEAF_usmStatsUnknownEngineIDs:
+ val->v.uint32 = usmstats->unknown_engine_ids;
+ break;
+ case LEAF_usmStatsWrongDigests:
+ val->v.uint32 = usmstats->wrong_digests;
+ break;
+ case LEAF_usmStatsDecryptionErrors:
+ val->v.uint32 = usmstats->decrypt_errors;
+ break;
+ default:
+ return (SNMP_ERR_NOSUCHNAME);
+ }
+ return (SNMP_ERR_NOERROR);
+ }
+ abort();
+}
+
+int
+op_usm_lock(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ if (val->var.subs[sub - 1] != LEAF_usmUserSpinLock)
+ return (SNMP_ERR_NOSUCHNAME);
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if (++usm_lock == INT32_MAX)
+ usm_lock = 0;
+ val->v.integer = usm_lock;
+ break;
+ case SNMP_OP_GETNEXT:
+ abort();
+ case SNMP_OP_SET:
+ if (val->v.integer != usm_lock)
+ return (SNMP_ERR_INCONS_VALUE);
+ break;
+ case SNMP_OP_ROLLBACK:
+ /* FALLTHROUGH */
+ case SNMP_OP_COMMIT:
+ break;
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_usm_users(struct snmp_context *ctx, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ uint32_t elen;
+ struct usm_user *uuser, *clone;
+ char uname[SNMP_ADM_STR32_SIZ];
+ uint8_t eid[SNMP_ENGINE_ID_SIZ];
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((uuser = usm_get_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((uuser = usm_get_next_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ usm_append_userindex(&val->var, sub, uuser);
+ break;
+
+ case SNMP_OP_SET:
+ if ((uuser = usm_get_user(&val->var, sub)) == NULL &&
+ val->var.subs[sub - 1] != LEAF_usmUserStatus &&
+ val->var.subs[sub - 1] != LEAF_usmUserCloneFrom)
+ return (SNMP_ERR_NOSUCHNAME);
+
+ if (community != COMM_INITIALIZE &&
+ uuser->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_usmUserSecurityName:
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ case LEAF_usmUserCloneFrom:
+ if (uuser != NULL || usm_user_index_decode(&val->var,
+ sub, eid, &elen, uname) < 0 ||
+ !(asn_is_suboid(&oid_usmUserSecurityName, &val->v.oid)))
+ return (SNMP_ERR_WRONG_VALUE);
+ if ((clone = usm_get_user(&val->v.oid, sub)) == NULL)
+ return (SNMP_ERR_INCONS_VALUE);
+ if ((uuser = usm_new_user(eid, elen, uname)) == NULL)
+ return (SNMP_ERR_GENERR);
+ uuser->status = RowStatus_notReady;
+ if (community != COMM_INITIALIZE)
+ uuser->type = StorageType_volatile;
+ else
+ uuser->type = StorageType_readOnly;
+
+ uuser->suser.auth_proto = clone->suser.auth_proto;
+ uuser->suser.priv_proto = clone->suser.priv_proto;
+ memcpy(uuser->suser.auth_key, clone->suser.auth_key,
+ sizeof(uuser->suser.auth_key));
+ memcpy(uuser->suser.priv_key, clone->suser.priv_key,
+ sizeof(uuser->suser.priv_key));
+ ctx->scratch->int1 = RowStatus_createAndWait;
+ break;
+
+ case LEAF_usmUserAuthProtocol:
+ ctx->scratch->int1 = uuser->suser.auth_proto;
+ if (asn_compare_oid(&oid_usmNoAuthProtocol,
+ &val->v.oid) == 0)
+ uuser->suser.auth_proto = SNMP_AUTH_NOAUTH;
+ else if (asn_compare_oid(&oid_usmHMACMD5AuthProtocol,
+ &val->v.oid) == 0)
+ uuser->suser.auth_proto = SNMP_AUTH_HMAC_MD5;
+ else if (asn_compare_oid(&oid_usmHMACSHAAuthProtocol,
+ &val->v.oid) == 0)
+ uuser->suser.auth_proto = SNMP_AUTH_HMAC_SHA;
+ else
+ return (SNMP_ERR_WRONG_VALUE);
+ break;
+
+ case LEAF_usmUserAuthKeyChange:
+ case LEAF_usmUserOwnAuthKeyChange:
+ if (val->var.subs[sub - 1] ==
+ LEAF_usmUserOwnAuthKeyChange &&
+ (usm_user == NULL || strcmp(uuser->suser.sec_name,
+ usm_user->suser.sec_name) != 0))
+ return (SNMP_ERR_NO_ACCESS);
+ if (val->v.octetstring.len > SNMP_AUTH_KEY_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->ptr1 = malloc(SNMP_AUTH_KEY_SIZ);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ memcpy(ctx->scratch->ptr1, uuser->suser.auth_key,
+ SNMP_AUTH_KEY_SIZ);
+ memcpy(uuser->suser.auth_key, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ break;
+
+ case LEAF_usmUserPrivProtocol:
+ ctx->scratch->int1 = uuser->suser.priv_proto;
+ if (asn_compare_oid(&oid_usmNoPrivProtocol,
+ &val->v.oid) == 0)
+ uuser->suser.priv_proto = SNMP_PRIV_NOPRIV;
+ else if (asn_compare_oid(&oid_usmDESPrivProtocol,
+ &val->v.oid) == 0)
+ uuser->suser.priv_proto = SNMP_PRIV_DES;
+ else if (asn_compare_oid(&oid_usmAesCfb128Protocol,
+ &val->v.oid) == 0)
+ uuser->suser.priv_proto = SNMP_PRIV_AES;
+ else
+ return (SNMP_ERR_WRONG_VALUE);
+ break;
+
+ case LEAF_usmUserPrivKeyChange:
+ case LEAF_usmUserOwnPrivKeyChange:
+ if (val->var.subs[sub - 1] ==
+ LEAF_usmUserOwnPrivKeyChange &&
+ (usm_user == NULL || strcmp(uuser->suser.sec_name,
+ usm_user->suser.sec_name) != 0))
+ return (SNMP_ERR_NO_ACCESS);
+ if (val->v.octetstring.len > SNMP_PRIV_KEY_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->ptr1 = malloc(SNMP_PRIV_KEY_SIZ);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ memcpy(ctx->scratch->ptr1, uuser->suser.priv_key,
+ SNMP_PRIV_KEY_SIZ);
+ memcpy(uuser->suser.priv_key, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ break;
+
+ case LEAF_usmUserPublic:
+ if (val->v.octetstring.len > SNMP_ADM_STR32_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ if (uuser->user_public_len > 0) {
+ ctx->scratch->ptr2 =
+ malloc(uuser->user_public_len);
+ if (ctx->scratch->ptr2 == NULL)
+ return (SNMP_ERR_GENERR);
+ memcpy(ctx->scratch->ptr2, uuser->user_public,
+ uuser->user_public_len);
+ ctx->scratch->int2 = uuser->user_public_len;
+ }
+ if (val->v.octetstring.len > 0) {
+ memcpy(uuser->user_public,
+ val->v.octetstring.octets,
+ val->v.octetstring.len);
+ uuser->user_public_len = val->v.octetstring.len;
+ } else {
+ memset(uuser->user_public, 0,
+ SNMP_ADM_STR32_SIZ);
+ uuser->user_public_len = 0;
+ }
+ break;
+
+ case LEAF_usmUserStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+
+ case LEAF_usmUserStatus:
+ if (uuser == NULL) {
+ if (val->v.integer != RowStatus_createAndWait ||
+ usm_user_index_decode(&val->var, sub, eid,
+ &elen, uname) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ uuser = usm_new_user(eid, elen, uname);
+ if (uuser == NULL)
+ return (SNMP_ERR_GENERR);
+ uuser->status = RowStatus_notReady;
+ if (community != COMM_INITIALIZE)
+ uuser->type = StorageType_volatile;
+ else
+ uuser->type = StorageType_readOnly;
+ } else if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+
+ uuser->status = val->v.integer;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_usmUserAuthKeyChange:
+ case LEAF_usmUserOwnAuthKeyChange:
+ case LEAF_usmUserPrivKeyChange:
+ case LEAF_usmUserOwnPrivKeyChange:
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_usmUserPublic:
+ if (ctx->scratch->ptr2 != NULL)
+ free(ctx->scratch->ptr2);
+ break;
+ case LEAF_usmUserStatus:
+ if (val->v.integer != RowStatus_destroy)
+ break;
+ if ((uuser = usm_get_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ usm_delete_user(uuser);
+ break;
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((uuser = usm_get_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_usmUserAuthProtocol:
+ uuser->suser.auth_proto = ctx->scratch->int1;
+ break;
+ case LEAF_usmUserAuthKeyChange:
+ case LEAF_usmUserOwnAuthKeyChange:
+ memcpy(uuser->suser.auth_key, ctx->scratch->ptr1,
+ SNMP_AUTH_KEY_SIZ);
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_usmUserPrivProtocol:
+ uuser->suser.priv_proto = ctx->scratch->int1;
+ break;
+ case LEAF_usmUserPrivKeyChange:
+ case LEAF_usmUserOwnPrivKeyChange:
+ memcpy(uuser->suser.priv_key, ctx->scratch->ptr1,
+ SNMP_AUTH_KEY_SIZ);
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_usmUserPublic:
+ if (ctx->scratch->ptr2 != NULL) {
+ memcpy(uuser->user_public, ctx->scratch->ptr2,
+ ctx->scratch->int2);
+ uuser->user_public_len = ctx->scratch->int2;
+ free(ctx->scratch->ptr2);
+ } else {
+ memset(uuser->user_public, 0,
+ SNMP_ADM_STR32_SIZ);
+ uuser->user_public_len = 0;
+ }
+ break;
+ case LEAF_usmUserCloneFrom:
+ case LEAF_usmUserStatus:
+ if (ctx->scratch->int1 == RowStatus_createAndWait)
+ usm_delete_user(uuser);
+ break;
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ default:
+ abort();
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_usmUserSecurityName:
+ return (string_get(val, uuser->suser.sec_name, -1));
+ case LEAF_usmUserCloneFrom:
+ memcpy(&val->v.oid, &oid_zeroDotZero, sizeof(oid_zeroDotZero));
+ break;
+ case LEAF_usmUserAuthProtocol:
+ switch (uuser->suser.auth_proto) {
+ case SNMP_AUTH_HMAC_MD5:
+ memcpy(&val->v.oid, &oid_usmHMACMD5AuthProtocol,
+ sizeof(oid_usmHMACMD5AuthProtocol));
+ break;
+ case SNMP_AUTH_HMAC_SHA:
+ memcpy(&val->v.oid, &oid_usmHMACSHAAuthProtocol,
+ sizeof(oid_usmHMACSHAAuthProtocol));
+ break;
+ default:
+ memcpy(&val->v.oid, &oid_usmNoAuthProtocol,
+ sizeof(oid_usmNoAuthProtocol));
+ break;
+ }
+ break;
+ case LEAF_usmUserAuthKeyChange:
+ case LEAF_usmUserOwnAuthKeyChange:
+ return (string_get(val, (char *)uuser->suser.auth_key, 0));
+ case LEAF_usmUserPrivProtocol:
+ switch (uuser->suser.priv_proto) {
+ case SNMP_PRIV_DES:
+ memcpy(&val->v.oid, &oid_usmDESPrivProtocol,
+ sizeof(oid_usmDESPrivProtocol));
+ break;
+ case SNMP_PRIV_AES:
+ memcpy(&val->v.oid, &oid_usmAesCfb128Protocol,
+ sizeof(oid_usmAesCfb128Protocol));
+ break;
+ default:
+ memcpy(&val->v.oid, &oid_usmNoPrivProtocol,
+ sizeof(oid_usmNoPrivProtocol));
+ break;
+ }
+ break;
+ case LEAF_usmUserPrivKeyChange:
+ case LEAF_usmUserOwnPrivKeyChange:
+ return (string_get(val, (char *)uuser->suser.priv_key, 0));
+ case LEAF_usmUserPublic:
+ return (string_get(val, uuser->user_public,
+ uuser->user_public_len));
+ case LEAF_usmUserStorageType:
+ val->v.integer = uuser->type;
+ break;
+ case LEAF_usmUserStatus:
+ val->v.integer = uuser->status;
+ break;
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+static int
+usm_user_index_decode(const struct asn_oid *oid, uint sub, uint8_t *engine,
+ uint32_t *elen, char *uname)
+{
+ uint32_t i, nlen;
+ int uname_off;
+
+ if (oid->subs[sub] > SNMP_ENGINE_ID_SIZ)
+ return (-1);
+
+ for (i = 0; i < oid->subs[sub]; i++)
+ engine[i] = oid->subs[sub + i + 1];
+ *elen = i;
+
+ uname_off = sub + oid->subs[sub] + 1;
+ if ((nlen = oid->subs[uname_off]) >= SNMP_ADM_STR32_SIZ)
+ return (-1);
+
+ for (i = 0; i < nlen; i++)
+ uname[i] = oid->subs[uname_off + i + 1];
+ uname[nlen] = '\0';
+
+ return (0);
+}
+
+static void
+usm_append_userindex(struct asn_oid *oid, uint sub,
+ const struct usm_user *uuser)
+{
+ uint32_t i;
+
+ oid->len = sub + uuser->user_engine_len + strlen(uuser->suser.sec_name);
+ oid->len += 2;
+ oid->subs[sub] = uuser->user_engine_len;
+ for (i = 1; i < uuser->user_engine_len + 1; i++)
+ oid->subs[sub + i] = uuser->user_engine_id[i - 1];
+
+ sub += uuser->user_engine_len + 1;
+ oid->subs[sub] = strlen(uuser->suser.sec_name);
+ for (i = 1; i <= oid->subs[sub]; i++)
+ oid->subs[sub + i] = uuser->suser.sec_name[i - 1];
+}
+
+static struct usm_user *
+usm_get_user(const struct asn_oid *oid, uint sub)
+{
+ uint32_t enginelen;
+ char username[SNMP_ADM_STR32_SIZ];
+ uint8_t engineid[SNMP_ENGINE_ID_SIZ];
+
+ if (usm_user_index_decode(oid, sub, engineid, &enginelen, username) < 0)
+ return (NULL);
+
+ return (usm_find_user(engineid, enginelen, username));
+}
+
+static struct usm_user *
+usm_get_next_user(const struct asn_oid *oid, uint sub)
+{
+ uint32_t enginelen;
+ char username[SNMP_ADM_STR32_SIZ];
+ uint8_t engineid[SNMP_ENGINE_ID_SIZ];
+ struct usm_user *uuser;
+
+ if (oid->len - sub == 0)
+ return (usm_first_user());
+
+ if (usm_user_index_decode(oid, sub, engineid, &enginelen, username) < 0)
+ return (NULL);
+
+ if ((uuser = usm_find_user(engineid, enginelen, username)) != NULL)
+ return (usm_next_user(uuser));
+
+ return (NULL);
+}
+
+/*
+ * USM snmp module initialization hook.
+ * Returns 0 on success, < 0 on error.
+ */
+static int
+usm_init(struct lmodule * mod, int argc __unused, char *argv[] __unused)
+{
+ usm_module = mod;
+ usm_lock = random();
+ bsnmpd_reset_usm_stats();
+ return (0);
+}
+
+/*
+ * USM snmp module finalization hook.
+ */
+static int
+usm_fini(void)
+{
+ usm_flush_users();
+ or_unregister(reg_usm);
+
+ return (0);
+}
+
+/*
+ * USM snmp module start operation.
+ */
+static void
+usm_start(void)
+{
+ reg_usm = or_register(&oid_usm,
+ "The MIB module for managing SNMP User-Based Security Model.",
+ usm_module);
+}
+
+static void
+usm_dump(void)
+{
+ struct usm_user *uuser;
+ struct snmpd_usmstat *usmstats;
+ const char *const authstr[] = {
+ "noauth",
+ "md5",
+ "sha",
+ NULL
+ };
+ const char *const privstr[] = {
+ "nopriv",
+ "des",
+ "aes",
+ NULL
+ };
+
+ if ((usmstats = bsnmpd_get_usm_stats()) != NULL) {
+ syslog(LOG_ERR, "UnsupportedSecLevels\t\t%u",
+ usmstats->unsupported_seclevels);
+ syslog(LOG_ERR, "NotInTimeWindows\t\t%u",
+ usmstats->not_in_time_windows);
+ syslog(LOG_ERR, "UnknownUserNames\t\t%u",
+ usmstats->unknown_users);
+ syslog(LOG_ERR, "UnknownEngineIDs\t\t%u",
+ usmstats->unknown_engine_ids);
+ syslog(LOG_ERR, "WrongDigests\t\t%u",
+ usmstats->wrong_digests);
+ syslog(LOG_ERR, "DecryptionErrors\t\t%u",
+ usmstats->decrypt_errors);
+ }
+
+ syslog(LOG_ERR, "USM users");
+ for (uuser = usm_first_user(); uuser != NULL;
+ (uuser = usm_next_user(uuser)))
+ syslog(LOG_ERR, "user %s\t\t%s, %s", uuser->suser.sec_name,
+ authstr[uuser->suser.auth_proto],
+ privstr[uuser->suser.priv_proto]);
+}
+
+const char usm_comment[] = \
+"This module implements SNMP User-based Security Model defined in RFC 3414.";
+
+const struct snmp_module config = {
+ .comment = usm_comment,
+ .init = usm_init,
+ .fini = usm_fini,
+ .start = usm_start,
+ .tree = usm_ctree,
+ .dump = usm_dump,
+ .tree_size = usm_CTREE_SIZE,
+};
diff --git a/contrib/bsnmp/snmp_usm/usm_tree.def b/contrib/bsnmp/snmp_usm/usm_tree.def
new file mode 100755
index 0000000..8358d7b
--- /dev/null
+++ b/contrib/bsnmp/snmp_usm/usm_tree.def
@@ -0,0 +1,109 @@
+#-
+# Copyright (C) 2010 The FreeBSD Foundation
+# All rights reserved.
+#
+# This software was developed by Shteryana Sotirova Shopova under
+# sponsorship from the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+typedef StorageType ENUM (
+ 1 other
+ 2 volatile
+ 3 nonVolatile
+ 4 permanent
+ 5 readOnly
+)
+
+typedef RowStatus ENUM (
+ 1 active
+ 2 notInService
+ 3 notReady
+ 4 createAndGo
+ 5 createAndWait
+ 6 destroy
+)
+
+(1 internet
+ (6 snmpV2
+ (3 snmpModules
+ (10 snmpFrameworkMIB
+ (1 snmpFrameworkAdmin
+ (1 snmpAuthProtocols
+ (1 usmNoAuthProtocol
+ )
+ (2 usmHMACMD5AuthProtocol
+ )
+ (3 usmHMACSHAAuthProtocol
+ )
+ )
+ (2 snmpPrivProtocols
+ (1 usmNoPrivProtocol
+ )
+ (2 usmDESPrivProtocol
+ )
+ (4 usmAesCfb128Protocol
+ )
+ )
+ )
+ )
+ (15 snmpUsmMIB
+ (1 usmMIBObjects
+ (1 usmStats
+ (1 usmStatsUnsupportedSecLevels COUNTER op_usm_stats GET)
+ (2 usmStatsNotInTimeWindows COUNTER op_usm_stats GET)
+ (3 usmStatsUnknownUserNames COUNTER op_usm_stats GET)
+ (4 usmStatsUnknownEngineIDs COUNTER op_usm_stats GET)
+ (5 usmStatsWrongDigests COUNTER op_usm_stats GET)
+ (6 usmStatsDecryptionErrors COUNTER op_usm_stats GET)
+ )
+ (2 usmUser
+ (1 usmUserSpinLock INTEGER op_usm_lock GET SET)
+ (2 usmUserTable
+ (1 usmUserEntry : OCTETSTRING | SnmpEngineID OCTETSTRING op_usm_users
+ (1 usmUserEngineID OCTETSTRING | SnmpEngineID)
+ (2 usmUserName OCTETSTRING)
+ (3 usmUserSecurityName OCTETSTRING | SnmpAdminString GET)
+ (4 usmUserCloneFrom OID GET SET)
+ (5 usmUserAuthProtocol OID GET SET)
+ (6 usmUserAuthKeyChange OCTETSTRING | KeyChange GET SET)
+ (7 usmUserOwnAuthKeyChange OCTETSTRING | KeyChange GET SET)
+ (8 usmUserPrivProtocol OID GET SET)
+ (9 usmUserPrivKeyChange OCTETSTRING | KeyChange GET SET)
+ (10 usmUserOwnPrivKeyChange OCTETSTRING | KeyChange GET SET)
+ (11 usmUserPublic OCTETSTRING GET SET)
+ (12 usmUserStorageType StorageType GET SET)
+ (13 usmUserStatus RowStatus GET SET)
+ )
+ )
+ )
+ )
+ )
+ (20 snmpUsmAesMIB
+ )
+ )
+ )
+)
+
OpenPOWER on IntegriCloud