diff --git a/contrib/bsnmp/lib/snmpcrypto.c b/contrib/bsnmp/lib/snmpcrypto.c index 92c7ede7b97f..f29fa89bf603 100644 --- a/contrib/bsnmp/lib/snmpcrypto.c +++ b/contrib/bsnmp/lib/snmpcrypto.c @@ -1,435 +1,434 @@ /*- * 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 #include #include #include #include #include #ifdef HAVE_STDINT_H #include #elif defined(HAVE_INTTYPES_H) #include #endif #include #include #include #include #ifdef HAVE_LIBCRYPTO #include #endif #include "asn1.h" #include "snmp.h" #include "snmppriv.h" #define SNMP_PRIV_AES_IV_SIZ 16 #define SNMP_EXTENDED_KEY_SIZ 64 #define SNMP_AUTH_KEY_LOOPCNT 1048576 #define SNMP_AUTH_BUF_SIZE 72 #ifdef HAVE_LIBCRYPTO static const uint8_t ipad = 0x36; static const uint8_t opad = 0x5c; static int32_t snmp_digest_init(const struct snmp_user *user, EVP_MD_CTX *ctx, const EVP_MD **dtype, uint32_t *keylen) { if (user->auth_proto == SNMP_AUTH_HMAC_MD5) { *dtype = EVP_md5(); *keylen = SNMP_AUTH_HMACMD5_KEY_SIZ; } else if (user->auth_proto == SNMP_AUTH_HMAC_SHA) { *dtype = EVP_sha1(); *keylen = SNMP_AUTH_HMACSHA_KEY_SIZ; } else if (user->auth_proto == SNMP_AUTH_NOAUTH) return (0); else { snmp_error("unknown authentication option - %d", user->auth_proto); return (-1); } if (EVP_DigestInit(ctx, *dtype) != 1) return (-1); return (1); } enum snmp_code snmp_pdu_calc_digest(const struct snmp_pdu *pdu, uint8_t *digest) { uint8_t md[EVP_MAX_MD_SIZE], extkey[SNMP_EXTENDED_KEY_SIZ]; uint8_t key1[SNMP_EXTENDED_KEY_SIZ], key2[SNMP_EXTENDED_KEY_SIZ]; uint32_t i, keylen, olen; int32_t err; const EVP_MD *dtype; EVP_MD_CTX *ctx; ctx = EVP_MD_CTX_new(); if (ctx == NULL) return (SNMP_CODE_FAILED); err = snmp_digest_init(&pdu->user, ctx, &dtype, &keylen); if (err <= 0) EVP_MD_CTX_free(ctx); if (err < 0) return (SNMP_CODE_BADDIGEST); else if (err == 0) return (SNMP_CODE_OK); memset(pdu->digest_ptr, 0, sizeof(pdu->msg_digest)); memcpy(extkey, pdu->user.auth_key, keylen); memset(extkey + keylen, 0, sizeof(extkey) - keylen); for (i = 0; i < SNMP_EXTENDED_KEY_SIZ; i++) { key1[i] = extkey[i] ^ ipad; key2[i] = extkey[i] ^ opad; } if (EVP_DigestUpdate(ctx, key1, SNMP_EXTENDED_KEY_SIZ) != 1 || EVP_DigestUpdate(ctx, pdu->outer_ptr, pdu->outer_len) != 1 || EVP_DigestFinal(ctx, md, &olen) != 1) goto failed; if (EVP_DigestInit(ctx, dtype) != 1 || EVP_DigestUpdate(ctx, key2, SNMP_EXTENDED_KEY_SIZ) != 1 || EVP_DigestUpdate(ctx, md, olen) != 1 || EVP_DigestFinal(ctx, md, &olen) != 1) goto failed; if (olen < SNMP_USM_AUTH_SIZE) { snmp_error("bad digest size - %d", olen); EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } memcpy(digest, md, SNMP_USM_AUTH_SIZE); EVP_MD_CTX_free(ctx); return (SNMP_CODE_OK); failed: EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } static int32_t snmp_pdu_cipher_init(const struct snmp_pdu *pdu, int32_t len, const EVP_CIPHER **ctype, uint8_t *piv) { int i; uint32_t netint; if (pdu->user.priv_proto == SNMP_PRIV_DES) { if (len % 8 != 0) return (-1); *ctype = EVP_des_cbc(); memcpy(piv, pdu->msg_salt, sizeof(pdu->msg_salt)); for (i = 0; i < 8; i++) piv[i] = piv[i] ^ pdu->user.priv_key[8 + i]; } else if (pdu->user.priv_proto == SNMP_PRIV_AES) { *ctype = EVP_aes_128_cfb128(); netint = htonl(pdu->engine.engine_boots); memcpy(piv, &netint, sizeof(netint)); piv += sizeof(netint); netint = htonl(pdu->engine.engine_time); memcpy(piv, &netint, sizeof(netint)); piv += sizeof(netint); memcpy(piv, pdu->msg_salt, sizeof(pdu->msg_salt)); } else if (pdu->user.priv_proto == SNMP_PRIV_NOPRIV) return (0); else { snmp_error("unknown privacy option - %d", pdu->user.priv_proto); return (-1); } return (1); } enum snmp_code snmp_pdu_encrypt(const struct snmp_pdu *pdu) { int32_t err, olen; uint8_t iv[SNMP_PRIV_AES_IV_SIZ]; const EVP_CIPHER *ctype; EVP_CIPHER_CTX *ctx; err = snmp_pdu_cipher_init(pdu, pdu->scoped_len, &ctype, iv); if (err < 0) return (SNMP_CODE_EDECRYPT); else if (err == 0) return (SNMP_CODE_OK); ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return (SNMP_CODE_FAILED); if (EVP_EncryptInit(ctx, ctype, pdu->user.priv_key, iv) != 1) goto failed; if (EVP_EncryptUpdate(ctx, pdu->scoped_ptr, &olen, pdu->scoped_ptr, pdu->scoped_len) != 1 || EVP_EncryptFinal(ctx, pdu->scoped_ptr + olen, &olen) != 1) goto failed; EVP_CIPHER_CTX_free(ctx); return (SNMP_CODE_OK); failed: EVP_CIPHER_CTX_free(ctx); return (SNMP_CODE_FAILED); } enum snmp_code snmp_pdu_decrypt(const struct snmp_pdu *pdu) { int32_t err, olen; uint8_t iv[SNMP_PRIV_AES_IV_SIZ]; const EVP_CIPHER *ctype; EVP_CIPHER_CTX *ctx; err = snmp_pdu_cipher_init(pdu, pdu->scoped_len, &ctype, iv); if (err < 0) return (SNMP_CODE_EDECRYPT); else if (err == 0) return (SNMP_CODE_OK); ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return (SNMP_CODE_FAILED); if (EVP_DecryptInit(ctx, ctype, pdu->user.priv_key, iv) != 1 || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) goto failed; if (EVP_DecryptUpdate(ctx, pdu->scoped_ptr, &olen, pdu->scoped_ptr, pdu->scoped_len) != 1 || EVP_DecryptFinal(ctx, pdu->scoped_ptr + olen, &olen) != 1) goto failed; EVP_CIPHER_CTX_free(ctx); return (SNMP_CODE_OK); failed: EVP_CIPHER_CTX_free(ctx); return (SNMP_CODE_EDECRYPT); } /* [RFC 3414] - A.2. Password to Key Algorithm */ enum snmp_code snmp_passwd_to_keys(struct snmp_user *user, char *passwd) { int err, loop, i, pwdlen; uint32_t keylen, olen; const EVP_MD *dtype; EVP_MD_CTX *ctx; uint8_t authbuf[SNMP_AUTH_BUF_SIZE]; if (passwd == NULL || user == NULL) return (SNMP_CODE_FAILED); ctx = EVP_MD_CTX_new(); if (ctx == NULL) return (SNMP_CODE_FAILED); err = snmp_digest_init(user, ctx, &dtype, &keylen); if (err <= 0) EVP_MD_CTX_free(ctx); if (err < 0) return (SNMP_CODE_BADDIGEST); else if (err == 0) return (SNMP_CODE_OK); memset(user->auth_key, 0, sizeof(user->auth_key)); pwdlen = strlen(passwd); for (loop = 0; loop < SNMP_AUTH_KEY_LOOPCNT; loop += i) { for (i = 0; i < SNMP_EXTENDED_KEY_SIZ; i++) authbuf[i] = passwd[(loop + i) % pwdlen]; if (EVP_DigestUpdate(ctx, authbuf, SNMP_EXTENDED_KEY_SIZ) != 1) goto failed; } if (EVP_DigestFinal(ctx, user->auth_key, &olen) != 1) goto failed; EVP_MD_CTX_free(ctx); return (SNMP_CODE_OK); failed: EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } /* [RFC 3414] - 2.6. Key Localization Algorithm */ enum snmp_code snmp_get_local_keys(struct snmp_user *user, uint8_t *eid, uint32_t elen) { int err; uint32_t keylen, olen; const EVP_MD *dtype; EVP_MD_CTX *ctx; uint8_t authbuf[SNMP_AUTH_BUF_SIZE]; if (user == NULL || eid == NULL || elen > SNMP_ENGINE_ID_SIZ) return (SNMP_CODE_FAILED); ctx = EVP_MD_CTX_new(); if (ctx == NULL) return (SNMP_CODE_FAILED); memset(user->priv_key, 0, sizeof(user->priv_key)); memset(authbuf, 0, sizeof(authbuf)); err = snmp_digest_init(user, ctx, &dtype, &keylen); if (err <= 0) EVP_MD_CTX_free(ctx); if (err < 0) return (SNMP_CODE_BADDIGEST); else if (err == 0) return (SNMP_CODE_OK); memcpy(authbuf, user->auth_key, keylen); memcpy(authbuf + keylen, eid, elen); memcpy(authbuf + keylen + elen, user->auth_key, keylen); if (EVP_DigestUpdate(ctx, authbuf, 2 * keylen + elen) != 1 || EVP_DigestFinal(ctx, user->auth_key, &olen) != 1) { EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } EVP_MD_CTX_free(ctx); if (user->priv_proto != SNMP_PRIV_NOPRIV) memcpy(user->priv_key, user->auth_key, sizeof(user->priv_key)); return (SNMP_CODE_OK); } enum snmp_code snmp_calc_keychange(struct snmp_user *user, uint8_t *keychange) { int32_t err, rvalue[SNMP_AUTH_HMACSHA_KEY_SIZ / 4]; uint32_t i, keylen, olen; const EVP_MD *dtype; EVP_MD_CTX *ctx; ctx = EVP_MD_CTX_new(); if (ctx == NULL) return (SNMP_CODE_FAILED); err = snmp_digest_init(user, ctx, &dtype, &keylen); if (err <= 0) EVP_MD_CTX_free(ctx); if (err < 0) return (SNMP_CODE_BADDIGEST); else if (err == 0) return (SNMP_CODE_OK); for (i = 0; i < keylen / 4; i++) rvalue[i] = random(); memcpy(keychange, user->auth_key, keylen); memcpy(keychange + keylen, rvalue, keylen); if (EVP_DigestUpdate(ctx, keychange, 2 * keylen) != 1 || EVP_DigestFinal(ctx, keychange, &olen) != 1) { EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } EVP_MD_CTX_free(ctx); return (SNMP_CODE_OK); } #else /* !HAVE_LIBCRYPTO */ enum snmp_code snmp_pdu_calc_digest(const struct snmp_pdu *pdu, uint8_t *digest __unused) { if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH) return (SNMP_CODE_BADSECLEVEL); return (SNMP_CODE_OK); } enum snmp_code snmp_pdu_encrypt(const struct snmp_pdu *pdu) { if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV) return (SNMP_CODE_BADSECLEVEL); return (SNMP_CODE_OK); } enum snmp_code snmp_pdu_decrypt(const struct snmp_pdu *pdu) { if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV) return (SNMP_CODE_BADSECLEVEL); return (SNMP_CODE_OK); } enum snmp_code snmp_passwd_to_keys(struct snmp_user *user, char *passwd __unused) { if (user->auth_proto == SNMP_AUTH_NOAUTH && user->priv_proto == SNMP_PRIV_NOPRIV) return (SNMP_CODE_OK); errno = EPROTONOSUPPORT; return (SNMP_CODE_FAILED); } enum snmp_code snmp_get_local_keys(struct snmp_user *user, uint8_t *eid __unused, uint32_t elen __unused) { if (user->auth_proto == SNMP_AUTH_NOAUTH && user->priv_proto == SNMP_PRIV_NOPRIV) return (SNMP_CODE_OK); errno = EPROTONOSUPPORT; return (SNMP_CODE_FAILED); } enum snmp_code snmp_calc_keychange(struct snmp_user *user __unused, uint8_t *keychange __unused) { errno = EPROTONOSUPPORT; return (SNMP_CODE_FAILED); } #endif /* HAVE_LIBCRYPTO */ diff --git a/contrib/bsnmp/lib/tc.def b/contrib/bsnmp/lib/tc.def index 1c408b844122..b43d467eba48 100644 --- a/contrib/bsnmp/lib/tc.def +++ b/contrib/bsnmp/lib/tc.def @@ -1,56 +1,55 @@ #- # 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 RowStatus ENUM ( 1 active 2 notInService 3 notReady 4 createAndGo 5 createAndWait 6 destroy ) typedef StorageType ENUM ( 1 other 2 volatile 3 nonVolatile 4 permanent 5 readOnly ) typedef InetAddressType ENUM ( 0 unknown 1 ipv4 2 ipv6 3 ipv4z 4 ipv6z 16 dns ) diff --git a/contrib/bsnmp/snmp_target/snmp_target.3 b/contrib/bsnmp/snmp_target/snmp_target.3 index c9e01a39bc51..262023c185a6 100644 --- a/contrib/bsnmp/snmp_target/snmp_target.3 +++ b/contrib/bsnmp/snmp_target/snmp_target.3 @@ -1,204 +1,203 @@ .\"- .\" 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 December 16, 2010 .Dt SNMP_TARGET 3 .Os .Sh NAME .Nm snmp_target .Nd "Target addresses and notifications module for" .Xr bsnmpd 1 .Sh LIBRARY .Pq begemotSnmpdModulePath."target" = "/usr/lib/snmp_target.so" .Sh DESCRIPTION The .Nm snmp_target module implements SNMPv3 Management Target MIB and basic functionality from Notification MIB as defined in RFC 3413. The module is used to manage the internal list of SNMPv3 notification target addresses in .Nm bsnmpd and their associated transport and encapsulation parameters. The module must be loaded for .Nm bsnmpd to send SNMPv3 Trap-PDUs to the configured notification target addresses. .Sh IMPLEMENTATION NOTES A short description of the objects implemented in the module follows. .Bl -tag -width "XXXXXXXXX" .It Va snmpTargetSpinLock An advisory lock used to coordinate several Command Generator Applications when altering the SNMP Target addresses and their associated parameters. .It Va snmpTargetAddrTable The table contains the transport addresses to be used in generation of SNMP messages. The table contains the following objects .Bl -tag -width ".It Va snmpTargetAddrName" .It Va snmpTargetAddrName A unique local identifier used as entry key. Not accessible for GET or SET operations. .It Va snmpTargetAddrTDomain The transport domain of the target address. Currently only UDP over IPv4 is supported and any attempt to SET the value of this object will return an "inconsistentValue" error. Additional transport domains will be supported in future via the object definitions in TRANSPORT-ADDRESS-MIB (RFC 3419). .It Va snmpTargetAddrTAddress The transport address of this entry interpreted within the context of the value of .Va snmpTargetAddrTDomain . For UDP over IPv4, this is a 6-byte long octetstring, with the first 4 bytes representing the IPv4 address and the last 2 bytes the UDP port number in network-byte order. .It Va snmpTargetAddrTimeout The value of this object is only relevant when the receiver of the SNMP message is to send an acknowledgment that the message was received, i.e for SNMP notifications it is relevant if the notification is SNMP Inform rather than SNMP Trap. Currently .Nm bsnmpd supports only SNMP Trap notifications, so the value of this object is meaningless. .It Va snmpTargetAddrRetryCount As with .Va snmpTargetAddrTimeout the value of this object currently is meaningless. .It Va snmpTargetAddrTagList A list of human-readable tag values used to select target addresses for a particular operation. Recognized ASCII delimiting characters between tags are space (0x20), tab (0x20), carriage return (0xOD) and line feed (0x0A). .It Va snmpTargetAddrParams The value of this object contains the value of a key in snmpTargetParamsTable containing SNMP parameters used when generating messages to this transport address. .It Va snmpTargetAddrStorageType 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 snmpTargetAddrRowStatus This column is used to create new target address entries or delete existing ones from the table. .El .It Va snmpTargetParamsTable The table contains the target information to be used in generation of SNMP messages. The table contains the following objects .Bl -tag -width ".It Va snmpTargetParamsName" .It Va snmpTargetParamsName A unique local identifier used as entry key. Not accessible for GET or SET operations. .It Va snmpTargetParamsMPModel The Message Processing Model to be used when generating SNMP PDUs using this entry. Supported values are 0 for SNMPv1, 1 for SNMPv2c and 3 for SNMPv3. .It Va snmpTargetParamsSecurityModel The Security Model to be used when generating SNMP PDUs using this entry. Supported values are 1 for SNMPv1, 2 for SNMPv2c and 3 for SNMPv3 User-Based Security Model. .It Va snmpTargetParamsSecurityName The securityName which identifies the Principal on whose behalf SNMP PDUs will be generated using this entry. For SNMPv1 and SNMPv2c this is the name of a community configured in .Nm bsnmpd , and for SNMPv3 USM, this is the name of an existing user configured via the .Nm snmp_usm module. .It Va snmpTargetParamsSecurityLevel The Security Level to be used when generating SNMP PDUs using this entry. Supported values are noAuthNoPriv(1) for plain-text PDUs with no authentication, authNoPriv(2) for authenticated plain-text PDUs and authPriv(3) for encrypted PDUs. .It Va snmpTargetParamsStorageType As with .Va snmpTargetAddrStorageType this column always has either of two values. Entries created via .Nm bsnmpd's configuration file always have this column set to readOnly (5), while entries created by Command Generator Applications always have this column set to volatile(2). A SET operation on this column is not allowed. .It Va snmpTargetParamsRowStatus This column is used to create new target address parameters entries or delete existing ones from the table. .El .It Va snmpNotifyTable The table is used to select the management targets which should receive SNMP notifications. The table contains the following objects .Bl -tag -width ".It Va snmpNotifyName" .It Va snmpNotifyName A unique local identifier used as entry key. Not accessible for GET or SET operations. .It Va snmpNotifyTag This object contains a single tag value used to select target addresses from the .Va snmpTargetAddrTable to which the notifications will be send. .It Va snmpNotifyType The type of SNMP notifications that will be send to the target addresses matching the corresponding .Va snmpNotifyTag . Possible values are Trap (1) or Inform (2). Currently only SNMP Traps are supported and any attempt to SET the value of this object will return an "inconsistentValue" error. .It Va snmpNotifyStorageType Again this column always has either of two values. Entries created via .Nm bsnmpd's configuration file always have this column set to readOnly (5), while entries created by Command Generator Applications always have this column set to volatile(2). A SET operation on this column is not allowed. .It Va snmpNotifyRowStatus This column is used to create new notification target entries or delete existing ones from the table. .El .El .Pp The .Va snmpNotifyFilterProfileTable and .Va snmpNotifyFilterTable tables from the SNMP-NOTIFICATION-MIB are not supported by the module. Notification filtering is supported via the .Xr snmp_vacm 3 module instead. .Sh FILES .Bl -tag -width "XXXXXXXXX" .It Pa /usr/share/snmp/defs/target_tree.def The description of the MIB tree implemented by .Nm . .El .Sh SEE ALSO .Xr bsnmpd 1 , .Xr gensnmptree 1 , .Xr snmpmod 3 , .Xr snmp_usm 3 , .Xr snmp_vacm 3 .Sh STANDARDS IETF RFC 3413 .Sh AUTHORS .An Shteryana Shopova Aq syrinx@FreeBSD.org diff --git a/contrib/bsnmp/snmp_target/target_snmp.c b/contrib/bsnmp/snmp_target/target_snmp.c index 7ea47db0491a..8d733d4b733e 100644 --- a/contrib/bsnmp/snmp_target/target_snmp.c +++ b/contrib/bsnmp/snmp_target/target_snmp.c @@ -1,842 +1,841 @@ /*- * Copyright (c) 2010,2018 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 #include #include #include #include #include #include #include #include #include "asn1.h" #include "snmp.h" #include "snmpmod.h" #define SNMPTREE_TYPES #include "target_tree.h" #include "target_oid.h" static struct lmodule *target_module; /* For the registration. */ static const struct asn_oid oid_target = OIDX_snmpTargetMIB; static const struct asn_oid oid_notification = OIDX_snmpNotificationMIB; static uint reg_target; static uint reg_notification; static int32_t target_lock; static const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain; /* * Internal datastructures and forward declarations. */ static void target_append_index(struct asn_oid *, uint, const char *); static int target_decode_index(const struct asn_oid *, uint, char *); static struct target_address *target_get_address(const struct asn_oid *, uint); static struct target_address *target_get_next_address(const struct asn_oid *, uint); static struct target_param *target_get_param(const struct asn_oid *, uint); static struct target_param *target_get_next_param(const struct asn_oid *, uint); static struct target_notify *target_get_notify(const struct asn_oid *, uint); static struct target_notify *target_get_next_notify(const struct asn_oid *, uint); int op_snmp_target(struct snmp_context *ctx __unused, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { struct snmpd_target_stats *ctx_stats; if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) { switch (op) { case SNMP_OP_GET: if (++target_lock == INT32_MAX) target_lock = 0; val->v.integer = target_lock; break; case SNMP_OP_GETNEXT: abort(); case SNMP_OP_SET: if (val->v.integer != target_lock) return (SNMP_ERR_INCONS_VALUE); break; case SNMP_OP_ROLLBACK: /* FALLTHROUGH */ case SNMP_OP_COMMIT: break; } return (SNMP_ERR_NOERROR); } else if (op == SNMP_OP_SET) return (SNMP_ERR_NOT_WRITEABLE); if ((ctx_stats = bsnmpd_get_target_stats()) == NULL) return (SNMP_ERR_GENERR); if (op == SNMP_OP_GET) { switch (val->var.subs[sub - 1]) { case LEAF_snmpUnavailableContexts: val->v.uint32 = ctx_stats->unavail_contexts; break; case LEAF_snmpUnknownContexts: val->v.uint32 = ctx_stats->unknown_contexts; break; default: return (SNMP_ERR_NOSUCHNAME); } return (SNMP_ERR_NOERROR); } abort(); } int op_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { char aname[SNMP_ADM_STR32_SIZ]; struct target_address *addrs; switch (op) { case SNMP_OP_GET: if ((addrs = target_get_address(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((addrs = target_get_next_address(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); target_append_index(&val->var, sub, addrs->name); break; case SNMP_OP_SET: if ((addrs = target_get_address(&val->var, sub)) == NULL && (val->var.subs[sub - 1] != LEAF_snmpTargetAddrRowStatus || val->v.integer != RowStatus_createAndWait)) return (SNMP_ERR_NOSUCHNAME); if (addrs != NULL) { if (community != COMM_INITIALIZE && addrs->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); if (addrs->status == RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); } switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetAddrTDomain: return (SNMP_ERR_INCONS_VALUE); case LEAF_snmpTargetAddrTAddress: if (val->v.octetstring.len != SNMP_UDP_ADDR_SIZ) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->ptr1 = malloc(SNMP_UDP_ADDR_SIZ); if (ctx->scratch->ptr1 == NULL) return (SNMP_ERR_GENERR); memcpy(ctx->scratch->ptr1, addrs->address, SNMP_UDP_ADDR_SIZ); memcpy(addrs->address, val->v.octetstring.octets, SNMP_UDP_ADDR_SIZ); break; case LEAF_snmpTargetAddrTagList: if (val->v.octetstring.len >= SNMP_TAG_SIZ) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = strlen(addrs->taglist) + 1; ctx->scratch->ptr1 = malloc(ctx->scratch->int1); if (ctx->scratch->ptr1 == NULL) return (SNMP_ERR_GENERR); strlcpy(ctx->scratch->ptr1, addrs->taglist, ctx->scratch->int1); memcpy(addrs->taglist, val->v.octetstring.octets, val->v.octetstring.len); addrs->taglist[val->v.octetstring.len] = '\0'; break; case LEAF_snmpTargetAddrParams: if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = strlen(addrs->paramname) + 1; ctx->scratch->ptr1 = malloc(ctx->scratch->int1); if (ctx->scratch->ptr1 == NULL) return (SNMP_ERR_GENERR); strlcpy(ctx->scratch->ptr1, addrs->paramname, ctx->scratch->int1); memcpy(addrs->paramname, val->v.octetstring.octets, val->v.octetstring.len); addrs->paramname[val->v.octetstring.len] = '\0'; break; case LEAF_snmpTargetAddrRetryCount: ctx->scratch->int1 = addrs->retry; addrs->retry = val->v.integer; break; case LEAF_snmpTargetAddrTimeout: ctx->scratch->int1 = addrs->timeout; addrs->timeout = val->v.integer / 10; break; case LEAF_snmpTargetAddrStorageType: return (SNMP_ERR_INCONS_VALUE); case LEAF_snmpTargetAddrRowStatus: if (addrs != NULL) { if (val->v.integer != RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); if (val->v.integer == RowStatus_active && (addrs->address[0] == 0 || strlen(addrs->taglist) == 0 || strlen(addrs->paramname) == 0)) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = addrs->status; addrs->status = val->v.integer; return (SNMP_ERR_NOERROR); } if (val->v.integer != RowStatus_createAndWait || target_decode_index(&val->var, sub, aname) < 0) return (SNMP_ERR_INCONS_VALUE); if ((addrs = target_new_address(aname)) == NULL) return (SNMP_ERR_GENERR); addrs->status = RowStatus_destroy; if (community != COMM_INITIALIZE) addrs->type = StorageType_volatile; else addrs->type = StorageType_readOnly; break; } return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetAddrTAddress: case LEAF_snmpTargetAddrTagList: case LEAF_snmpTargetAddrParams: free(ctx->scratch->ptr1); break; case LEAF_snmpTargetAddrRowStatus: if ((addrs = target_get_address(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); if (val->v.integer == RowStatus_destroy) return (target_delete_address(addrs)); else if (val->v.integer == RowStatus_active) return (target_activate_address(addrs)); break; default: break; } return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: if ((addrs = target_get_address(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetAddrTAddress: memcpy(addrs->address, ctx->scratch->ptr1, SNMP_UDP_ADDR_SIZ); free(ctx->scratch->ptr1); break; case LEAF_snmpTargetAddrTagList: strlcpy(addrs->taglist, ctx->scratch->ptr1, ctx->scratch->int1); free(ctx->scratch->ptr1); break; case LEAF_snmpTargetAddrParams: strlcpy(addrs->paramname, ctx->scratch->ptr1, ctx->scratch->int1); free(ctx->scratch->ptr1); break; case LEAF_snmpTargetAddrRetryCount: addrs->retry = ctx->scratch->int1; break; case LEAF_snmpTargetAddrTimeout: addrs->timeout = ctx->scratch->int1; break; case LEAF_snmpTargetAddrRowStatus: if (ctx->scratch->int1 == RowStatus_destroy) return (target_delete_address(addrs)); break; default: break; } return (SNMP_ERR_NOERROR); default: abort(); } switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetAddrTDomain: return (oid_get(val, &oid_udp_domain)); case LEAF_snmpTargetAddrTAddress: return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ)); case LEAF_snmpTargetAddrTimeout: val->v.integer = addrs->timeout; break; case LEAF_snmpTargetAddrRetryCount: val->v.integer = addrs->retry; break; case LEAF_snmpTargetAddrTagList: return (string_get(val, addrs->taglist, -1)); case LEAF_snmpTargetAddrParams: return (string_get(val, addrs->paramname, -1)); case LEAF_snmpTargetAddrStorageType: val->v.integer = addrs->type; break; case LEAF_snmpTargetAddrRowStatus: val->v.integer = addrs->status; break; default: abort(); } return (SNMP_ERR_NOERROR); } int op_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { char pname[SNMP_ADM_STR32_SIZ]; struct target_param *param; switch (op) { case SNMP_OP_GET: if ((param = target_get_param(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((param = target_get_next_param(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); target_append_index(&val->var, sub, param->name); break; case SNMP_OP_SET: if ((param = target_get_param(&val->var, sub)) == NULL && (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || val->v.integer != RowStatus_createAndWait)) return (SNMP_ERR_NOSUCHNAME); if (param != NULL) { if (community != COMM_INITIALIZE && param->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); if (param->status == RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); } switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetParamsMPModel: if (val->v.integer != SNMP_MPM_SNMP_V1 && val->v.integer != SNMP_MPM_SNMP_V2c && val->v.integer != SNMP_MPM_SNMP_V3) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = param->mpmodel; param->mpmodel = val->v.integer; break; case LEAF_snmpTargetParamsSecurityModel: if (val->v.integer != SNMP_SECMODEL_SNMPv1 && val->v.integer != SNMP_SECMODEL_SNMPv2c && val->v.integer != SNMP_SECMODEL_USM) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = param->sec_model; param->sec_model = val->v.integer; break; case LEAF_snmpTargetParamsSecurityName: if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = strlen(param->secname) + 1; ctx->scratch->ptr1 = malloc(ctx->scratch->int1); if (ctx->scratch->ptr1 == NULL) return (SNMP_ERR_GENERR); strlcpy(ctx->scratch->ptr1, param->secname, ctx->scratch->int1); memcpy(param->secname, val->v.octetstring.octets, val->v.octetstring.len); param->secname[val->v.octetstring.len] = '\0'; break; case LEAF_snmpTargetParamsSecurityLevel: if (val->v.integer != SNMP_noAuthNoPriv && val->v.integer != SNMP_authNoPriv && val->v.integer != SNMP_authPriv) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = param->sec_level; param->sec_level = val->v.integer; break; case LEAF_snmpTargetParamsStorageType: return (SNMP_ERR_INCONS_VALUE); case LEAF_snmpTargetParamsRowStatus: if (param != NULL) { if (val->v.integer != RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); if (val->v.integer == RowStatus_active && (param->sec_model == 0 || param->sec_level == 0 || strlen(param->secname) == 0)) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = param->status; param->status = val->v.integer; return (SNMP_ERR_NOERROR); } if (val->v.integer != RowStatus_createAndWait || target_decode_index(&val->var, sub, pname) < 0) return (SNMP_ERR_INCONS_VALUE); if ((param = target_new_param(pname)) == NULL) return (SNMP_ERR_GENERR); param->status = RowStatus_destroy; if (community != COMM_INITIALIZE) param->type = StorageType_volatile; else param->type = StorageType_readOnly; break; } return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetParamsSecurityName: free(ctx->scratch->ptr1); break; case LEAF_snmpTargetParamsRowStatus: if ((param = target_get_param(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); if (val->v.integer == RowStatus_destroy) return (target_delete_param(param)); break; default: break; } return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: if ((param = target_get_param(&val->var, sub)) == NULL && (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || val->v.integer != RowStatus_createAndWait)) return (SNMP_ERR_GENERR); switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetParamsMPModel: param->mpmodel = ctx->scratch->int1; break; case LEAF_snmpTargetParamsSecurityModel: param->sec_model = ctx->scratch->int1; break; case LEAF_snmpTargetParamsSecurityName: strlcpy(param->secname, ctx->scratch->ptr1, sizeof(param->secname)); free(ctx->scratch->ptr1); break; case LEAF_snmpTargetParamsSecurityLevel: param->sec_level = ctx->scratch->int1; break; case LEAF_snmpTargetParamsRowStatus: if (ctx->scratch->int1 == RowStatus_destroy) return (target_delete_param(param)); break; default: break; } return (SNMP_ERR_NOERROR); default: abort(); } switch (val->var.subs[sub - 1]) { case LEAF_snmpTargetParamsMPModel: val->v.integer = param->mpmodel; break; case LEAF_snmpTargetParamsSecurityModel: val->v.integer = param->sec_model; break; case LEAF_snmpTargetParamsSecurityName: return (string_get(val, param->secname, -1)); case LEAF_snmpTargetParamsSecurityLevel: val->v.integer = param->sec_level; break; case LEAF_snmpTargetParamsStorageType: val->v.integer = param->type; break; case LEAF_snmpTargetParamsRowStatus: val->v.integer = param->status; break; default: abort(); } return (SNMP_ERR_NOERROR); } int op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { char nname[SNMP_ADM_STR32_SIZ]; struct target_notify *notify; switch (op) { case SNMP_OP_GET: if ((notify = target_get_notify(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((notify = target_get_next_notify(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); target_append_index(&val->var, sub, notify->name); break; case SNMP_OP_SET: if ((notify = target_get_notify(&val->var, sub)) == NULL && (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus || val->v.integer != RowStatus_createAndGo)) return (SNMP_ERR_NOSUCHNAME); if (notify != NULL) { if (community != COMM_INITIALIZE && notify->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); } switch (val->var.subs[sub - 1]) { case LEAF_snmpNotifyTag: if (val->v.octetstring.len >= SNMP_TAG_SIZ) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = strlen(notify->taglist) + 1; ctx->scratch->ptr1 = malloc(ctx->scratch->int1); if (ctx->scratch->ptr1 == NULL) return (SNMP_ERR_GENERR); strlcpy(ctx->scratch->ptr1, notify->taglist, ctx->scratch->int1); memcpy(notify->taglist, val->v.octetstring.octets, val->v.octetstring.len); notify->taglist[val->v.octetstring.len] = '\0'; break; case LEAF_snmpNotifyType: /* FALLTHROUGH */ case LEAF_snmpNotifyStorageType: return (SNMP_ERR_INCONS_VALUE); case LEAF_snmpNotifyRowStatus: if (notify != NULL) { if (val->v.integer != RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = notify->status; notify->status = val->v.integer; return (SNMP_ERR_NOERROR); } if (val->v.integer != RowStatus_createAndGo || target_decode_index(&val->var, sub, nname) < 0) return (SNMP_ERR_INCONS_VALUE); if ((notify = target_new_notify(nname)) == NULL) return (SNMP_ERR_GENERR); notify->status = RowStatus_destroy; if (community != COMM_INITIALIZE) notify->type = StorageType_volatile; else notify->type = StorageType_readOnly; break; } return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: switch (val->var.subs[sub - 1]) { case LEAF_snmpNotifyTag: free(ctx->scratch->ptr1); break; case LEAF_snmpNotifyRowStatus: notify = target_get_notify(&val->var, sub); if (notify == NULL) return (SNMP_ERR_GENERR); if (val->v.integer == RowStatus_destroy) return (target_delete_notify(notify)); else notify->status = RowStatus_active; break; default: break; } return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: if ((notify = target_get_notify(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->var.subs[sub - 1]) { case LEAF_snmpNotifyTag: strlcpy(notify->taglist, ctx->scratch->ptr1, ctx->scratch->int1); free(ctx->scratch->ptr1); break; case LEAF_snmpNotifyRowStatus: if (ctx->scratch->int1 == RowStatus_destroy) return (target_delete_notify(notify)); break; default: break; } return (SNMP_ERR_NOERROR); default: abort(); } switch (val->var.subs[sub - 1]) { case LEAF_snmpNotifyTag: return (string_get(val, notify->taglist, -1)); case LEAF_snmpNotifyType: val->v.integer = snmpNotifyType_trap; break; case LEAF_snmpNotifyStorageType: val->v.integer = notify->type; break; case LEAF_snmpNotifyRowStatus: val->v.integer = notify->status; break; default: abort(); } return (SNMP_ERR_NOERROR); } static void target_append_index(struct asn_oid *oid, uint sub, const char *name) { uint32_t i; oid->len = sub + strlen(name); for (i = 0; i < strlen(name); i++) oid->subs[sub + i] = name[i]; } static int target_decode_index(const struct asn_oid *oid, uint sub, char *name) { uint32_t i; if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (-1); for (i = 0; i < oid->subs[sub]; i++) name[i] = oid->subs[sub + i + 1]; name[i] = '\0'; return (0); } static struct target_address * target_get_address(const struct asn_oid *oid, uint sub) { char aname[SNMP_ADM_STR32_SIZ]; struct target_address *addrs; if (target_decode_index(oid, sub, aname) < 0) return (NULL); for (addrs = target_first_address(); addrs != NULL; addrs = target_next_address(addrs)) if (strcmp(aname, addrs->name) == 0) return (addrs); return (NULL); } static struct target_address * target_get_next_address(const struct asn_oid * oid, uint sub) { char aname[SNMP_ADM_STR32_SIZ]; struct target_address *addrs; if (oid->len - sub == 0) return (target_first_address()); if (target_decode_index(oid, sub, aname) < 0) return (NULL); for (addrs = target_first_address(); addrs != NULL; addrs = target_next_address(addrs)) if (strcmp(aname, addrs->name) == 0) return (target_next_address(addrs)); return (NULL); } static struct target_param * target_get_param(const struct asn_oid *oid, uint sub) { char pname[SNMP_ADM_STR32_SIZ]; struct target_param *param; if (target_decode_index(oid, sub, pname) < 0) return (NULL); for (param = target_first_param(); param != NULL; param = target_next_param(param)) if (strcmp(pname, param->name) == 0) return (param); return (NULL); } static struct target_param * target_get_next_param(const struct asn_oid *oid, uint sub) { char pname[SNMP_ADM_STR32_SIZ]; struct target_param *param; if (oid->len - sub == 0) return (target_first_param()); if (target_decode_index(oid, sub, pname) < 0) return (NULL); for (param = target_first_param(); param != NULL; param = target_next_param(param)) if (strcmp(pname, param->name) == 0) return (target_next_param(param)); return (NULL); } static struct target_notify * target_get_notify(const struct asn_oid *oid, uint sub) { char nname[SNMP_ADM_STR32_SIZ]; struct target_notify *notify; if (target_decode_index(oid, sub, nname) < 0) return (NULL); for (notify = target_first_notify(); notify != NULL; notify = target_next_notify(notify)) if (strcmp(nname, notify->name) == 0) return (notify); return (NULL); } static struct target_notify * target_get_next_notify(const struct asn_oid *oid, uint sub) { char nname[SNMP_ADM_STR32_SIZ]; struct target_notify *notify; if (oid->len - sub == 0) return (target_first_notify()); if (target_decode_index(oid, sub, nname) < 0) return (NULL); for (notify = target_first_notify(); notify != NULL; notify = target_next_notify(notify)) if (strcmp(nname, notify->name) == 0) return (target_next_notify(notify)); return (NULL); } static int target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) { target_module = mod; target_lock = random(); return (0); } static int target_fini(void) { target_flush_all(); or_unregister(reg_target); or_unregister(reg_notification); return (0); } static void target_start(void) { reg_target = or_register(&oid_target, "The MIB module for managing SNMP Management Targets.", target_module); reg_notification = or_register(&oid_notification, "The MIB module for configuring generation of SNMP notifications.", target_module); } static void target_dump(void) { /* XXX: dump the module stats & list of mgmt targets */ } static const char target_comment[] = \ "This module implements SNMP Management Target MIB Module defined in RFC 3413."; extern const struct snmp_module config; const struct snmp_module config = { .comment = target_comment, .init = target_init, .fini = target_fini, .start = target_start, .tree = target_ctree, .dump = target_dump, .tree_size = target_CTREE_SIZE, }; diff --git a/contrib/bsnmp/snmp_target/target_tree.def b/contrib/bsnmp/snmp_target/target_tree.def index 14424b00bdc6..d7baedd189b2 100644 --- a/contrib/bsnmp/snmp_target/target_tree.def +++ b/contrib/bsnmp/snmp_target/target_tree.def @@ -1,87 +1,86 @@ #- # 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$ # include "tc.def" (1 internet (6 snmpV2 (1 snmpDomains (1 snmpUDPDomain ) ) (3 snmpModules (12 snmpTargetMIB (1 snmpTargetObjects (1 snmpTargetSpinLock INTEGER op_snmp_target GET SET) (2 snmpTargetAddrTable (1 snmpTargetAddrEntry : OCTETSTRING op_snmp_target_addrs (1 snmpTargetAddrName OCTETSTRING) (2 snmpTargetAddrTDomain OID GET SET) (3 snmpTargetAddrTAddress OCTETSTRING | TAddress GET SET) (4 snmpTargetAddrTimeout INTEGER GET SET) (5 snmpTargetAddrRetryCount INTEGER GET SET) (6 snmpTargetAddrTagList OCTETSTRING | SnmpTagList GET SET) (7 snmpTargetAddrParams OCTETSTRING GET SET) (8 snmpTargetAddrStorageType StorageType GET SET) (9 snmpTargetAddrRowStatus RowStatus GET SET) ) ) (3 snmpTargetParamsTable (1 snmpTargetParamsEntry : OCTETSTRING op_snmp_target_params (1 snmpTargetParamsName OCTETSTRING) (2 snmpTargetParamsMPModel INTEGER GET SET) (3 snmpTargetParamsSecurityModel INTEGER GET SET) (4 snmpTargetParamsSecurityName OCTETSTRING | SnmpAdminString GET SET) (5 snmpTargetParamsSecurityLevel ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ) GET SET) (6 snmpTargetParamsStorageType StorageType GET SET) (7 snmpTargetParamsRowStatus RowStatus GET SET) ) ) (4 snmpUnavailableContexts COUNTER op_snmp_target GET) (5 snmpUnknownContexts COUNTER op_snmp_target GET) ) ) (13 snmpNotificationMIB (1 snmpNotifyObjects (1 snmpNotifyTable (1 snmpNotifyEntry : OCTETSTRING op_snmp_notify (1 snmpNotifyName OCTETSTRING) (2 snmpNotifyTag OCTETSTRING | SnmpTagValue GET SET) (3 snmpNotifyType ENUM ( 1 trap 2 inform ) GET SET) (4 snmpNotifyStorageType StorageType GET SET) (5 snmpNotifyRowStatus RowStatus GET SET) ) ) ) ) ) ) ) diff --git a/contrib/bsnmp/snmp_usm/snmp_usm.3 b/contrib/bsnmp/snmp_usm/snmp_usm.3 index 03959ede0cd2..4dd88b68e8ea 100644 --- a/contrib/bsnmp/snmp_usm/snmp_usm.3 +++ b/contrib/bsnmp/snmp_usm/snmp_usm.3 @@ -1,132 +1,131 @@ .\"- .\" 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 successful. .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 existing 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 index 67a971644e7d..6304af021375 100644 --- a/contrib/bsnmp/snmp_usm/usm_snmp.c +++ b/contrib/bsnmp/snmp_usm/usm_snmp.c @@ -1,620 +1,619 @@ /*- * Copyright (c) 2010,2018 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 #include #include #include #include #include #include #include #include #include "asn1.h" #include "snmp.h" #include "snmpmod.h" #define SNMPTREE_TYPES #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); /* * XXX (ngie): need to investigate the MIB to determine how * this is possible given some of the transitions below. */ if (community != COMM_INITIALIZE && uuser != NULL && 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, sizeof(uuser->suser.priv_key)); 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, sizeof(uuser->user_public)); 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, sizeof(uuser->suser.auth_key)); 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, sizeof(uuser->suser.priv_key)); 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, sizeof(uuser->user_public)); 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]); } static const char usm_comment[] = "This module implements SNMP User-based Security Model defined in RFC 3414."; extern const struct snmp_module config; 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 index 84b52956e167..2d6929f63c1a 100644 --- a/contrib/bsnmp/snmp_usm/usm_tree.def +++ b/contrib/bsnmp/snmp_usm/usm_tree.def @@ -1,94 +1,93 @@ #- # 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$ # include "tc.def" (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 ) ) ) ) diff --git a/contrib/bsnmp/snmp_vacm/snmp_vacm.3 b/contrib/bsnmp/snmp_vacm/snmp_vacm.3 index e1213d90097d..b184e30d808e 100644 --- a/contrib/bsnmp/snmp_vacm/snmp_vacm.3 +++ b/contrib/bsnmp/snmp_vacm/snmp_vacm.3 @@ -1,94 +1,93 @@ .\"- .\" 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 October 7, 2010 .Dt SNMP_VACM 3 .Os .Sh NAME .Nm snmp_vacm .Nd "View-based Access Control module for" .Xr bsnmpd 1 .Sh LIBRARY .Pq begemotSnmpdModulePath."vacm" = "/usr/lib/snmp_vacm.so" .Sh DESCRIPTION The .Nm snmp_vacm module implements SNMPv3 View-based Access Control Model MIB as defined in RFC 3415. The module is used to manage the internal lists of SNMPv1, v2c and v3 user names and groups and their access rights to fetch or modify the values of the MIB objects maintained by .Nm bsnmpd and the modules loaded in the daemon. The module must be loaded for .Nm bsnmpd to implement proper view-based access control. If the module is not loaded, access is granted to all configured SNMPv1 & SNMPv2c communities and SNMPv3 USM users. .Sh IMPLEMENTATION NOTES An entry in any table implemented by this MIB may be created by setting the relevant RowStatus column to createAndGo (4) - in fact, any other value for those columns in a SET operation will cause an error. When an entry is created, any of its columns that is not used as index, is set to the default value as specified in the SNMP-VIEW-BASED-ACM-MIB. All entries maintained by the module are persistent after reboot if created via .Nm bsnmpd 's config file, otherwise entries created via SNMP are lost after reboot. A short description of the objects in the MIB follows. .Bl -tag -width "XXXXXXXXX" .It Va vacmContextTable A read-only table that consists of a list of SNMP contexts available in .Nm bsnmpd . .It Va vacmSecurityToGroupTable The table contains a list of SNMPv1, v2c and v3 user names and the groups they belong to. .It Va vacmAccessTable The table contains a list of SNMP contexts to groups mappings and respectively the names of the SNMP views under those contexts, to which users in the group are granted read-only, read-write access or receive notifications for the objects under the subtree in the relevant view. .It Va vacmViewTreeFamilyTable The table contains a list of SNMP views, i.e. entries specifying the OID of a MIB subtree and whether access to the objects under this subtree is to be allowed or forbidden. .El .Sh FILES .Bl -tag -width "XXXXXXXXX" .It Pa /usr/share/snmp/defs/vacm_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 3415 .Sh AUTHORS .An Shteryana Shopova Aq syrinx@FreeBSD.org diff --git a/contrib/bsnmp/snmp_vacm/vacm_snmp.c b/contrib/bsnmp/snmp_vacm/vacm_snmp.c index 192de2d63722..39371176e493 100644 --- a/contrib/bsnmp/snmp_vacm/vacm_snmp.c +++ b/contrib/bsnmp/snmp_vacm/vacm_snmp.c @@ -1,1028 +1,1027 @@ /*- * Copyright (c) 2010,2018 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 #include #include #include #include #include #include #include #include #include "asn1.h" #include "snmp.h" #include "snmpmod.h" #define SNMPTREE_TYPES #include "vacm_tree.h" #include "vacm_oid.h" static struct lmodule *vacm_module; /* For the registration. */ static const struct asn_oid oid_vacm = OIDX_snmpVacmMIB; static uint reg_vacm; static int32_t vacm_lock; /* * Internal datastructures and forward declarations. */ static void vacm_append_userindex(struct asn_oid *, uint, const struct vacm_user *); static int vacm_user_index_decode(const struct asn_oid *, uint, int32_t *, char *); static struct vacm_user *vacm_get_user(const struct asn_oid *, uint); static struct vacm_user *vacm_get_next_user(const struct asn_oid *, uint); static void vacm_append_access_rule_index(struct asn_oid *, uint, const struct vacm_access *); static int vacm_access_rule_index_decode(const struct asn_oid *, uint, char *, char *, int32_t *, int32_t *); static struct vacm_access * vacm_get_access_rule(const struct asn_oid *, uint); static struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *, uint); static int vacm_view_index_decode(const struct asn_oid *, uint, char *, struct asn_oid *); static void vacm_append_viewindex(struct asn_oid *, uint, const struct vacm_view *); static struct vacm_view *vacm_get_view(const struct asn_oid *, uint); static struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint); static struct vacm_view *vacm_get_view_by_name(u_char *, u_int); static struct vacm_context *vacm_get_context(const struct asn_oid *, uint); static struct vacm_context *vacm_get_next_context(const struct asn_oid *, uint); static void vacm_append_ctxindex(struct asn_oid *, uint, const struct vacm_context *); int op_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { char cname[SNMP_ADM_STR32_SIZ]; size_t cnamelen; struct vacm_context *vacm_ctx; if (val->var.subs[sub - 1] != LEAF_vacmContextName) abort(); switch (op) { case SNMP_OP_GET: if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); vacm_append_ctxindex(&val->var, sub, vacm_ctx); break; case SNMP_OP_SET: if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL) return (SNMP_ERR_WRONG_VALUE); if (community != COMM_INITIALIZE) return (SNMP_ERR_NOT_WRITEABLE); if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ) return (SNMP_ERR_WRONG_VALUE); if (index_decode(&val->var, sub, iidx, &cname, &cnamelen)) return (SNMP_ERR_GENERR); cname[cnamelen] = '\0'; if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL) return (SNMP_ERR_GENERR); return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: /* FALLTHROUGH*/ case SNMP_OP_ROLLBACK: return (SNMP_ERR_NOERROR); default: abort(); } return (string_get(val, vacm_ctx->ctxname, -1)); } int op_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { int32_t smodel; char uname[SNMP_ADM_STR32_SIZ]; struct vacm_user *user; switch (op) { case SNMP_OP_GET: if ((user = vacm_get_user(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((user = vacm_get_next_user(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); vacm_append_userindex(&val->var, sub, user); break; case SNMP_OP_SET: if ((user = vacm_get_user(&val->var, sub)) == NULL && val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus) return (SNMP_ERR_NOSUCHNAME); if (user != NULL) { if (community != COMM_INITIALIZE && user->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); if (user->status == RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); } switch (val->var.subs[sub - 1]) { case LEAF_vacmGroupName: ctx->scratch->ptr1 = user->group->groupname; ctx->scratch->int1 = strlen(user->group->groupname); return (vacm_user_set_group(user, val->v.octetstring.octets,val->v.octetstring.len)); case LEAF_vacmSecurityToGroupStorageType: return (SNMP_ERR_INCONS_VALUE); case LEAF_vacmSecurityToGroupStatus: if (user == NULL) { if (val->v.integer != RowStatus_createAndGo || vacm_user_index_decode(&val->var, sub, &smodel, uname) < 0) return (SNMP_ERR_INCONS_VALUE); user = vacm_new_user(smodel, uname); if (user == NULL) return (SNMP_ERR_GENERR); user->status = RowStatus_destroy; if (community != COMM_INITIALIZE) user->type = StorageType_volatile; else user->type = StorageType_readOnly; } else if (val->v.integer != RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = user->status; user->status = val->v.integer; break; } return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus) return (SNMP_ERR_NOERROR); if ((user = vacm_get_user(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->v.integer) { case RowStatus_destroy: return (vacm_delete_user(user)); case RowStatus_createAndGo: user->status = RowStatus_active; break; default: break; } return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: if ((user = vacm_get_user(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->var.subs[sub - 1]) { case LEAF_vacmGroupName: return (vacm_user_set_group(user, ctx->scratch->ptr1, ctx->scratch->int1)); case LEAF_vacmSecurityToGroupStatus: if (ctx->scratch->int1 == RowStatus_destroy) return (vacm_delete_user(user)); user->status = ctx->scratch->int1; break; default: break; } return (SNMP_ERR_NOERROR); default: abort(); } switch (val->var.subs[sub - 1]) { case LEAF_vacmGroupName: return (string_get(val, user->group->groupname, -1)); case LEAF_vacmSecurityToGroupStorageType: val->v.integer = user->type; break; case LEAF_vacmSecurityToGroupStatus: val->v.integer = user->status; break; default: abort(); } return (SNMP_ERR_NOERROR); } int op_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { int32_t smodel, slevel; char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ]; struct vacm_access *acl; switch (op) { case SNMP_OP_GET: if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); vacm_append_access_rule_index(&val->var, sub, acl); break; case SNMP_OP_SET: if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL && val->var.subs[sub - 1] != LEAF_vacmAccessStatus) return (SNMP_ERR_NOSUCHNAME); if (acl != NULL && community != COMM_INITIALIZE && acl->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); switch (val->var.subs[sub - 1]) { case LEAF_vacmAccessContextMatch: ctx->scratch->int1 = acl->ctx_match; if (val->v.integer == vacmAccessContextMatch_exact) acl->ctx_match = 1; else if (val->v.integer == vacmAccessContextMatch_prefix) acl->ctx_match = 0; else return (SNMP_ERR_WRONG_VALUE); break; case LEAF_vacmAccessReadViewName: ctx->scratch->ptr1 = acl->read_view; acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len); if (acl->read_view == NULL) { acl->read_view = ctx->scratch->ptr1; return (SNMP_ERR_INCONS_VALUE); } return (SNMP_ERR_NOERROR); case LEAF_vacmAccessWriteViewName: ctx->scratch->ptr1 = acl->write_view; if ((acl->write_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len)) == NULL) { acl->write_view = ctx->scratch->ptr1; return (SNMP_ERR_INCONS_VALUE); } break; case LEAF_vacmAccessNotifyViewName: ctx->scratch->ptr1 = acl->notify_view; if ((acl->notify_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len)) == NULL) { acl->notify_view = ctx->scratch->ptr1; return (SNMP_ERR_INCONS_VALUE); } break; case LEAF_vacmAccessStorageType: return (SNMP_ERR_INCONS_VALUE); case LEAF_vacmAccessStatus: if (acl == NULL) { if (val->v.integer != RowStatus_createAndGo || vacm_access_rule_index_decode(&val->var, sub, gname, cprefix, &smodel, &slevel) < 0) return (SNMP_ERR_INCONS_VALUE); if ((acl = vacm_new_access_rule(gname, cprefix, smodel, slevel)) == NULL) return (SNMP_ERR_GENERR); acl->status = RowStatus_destroy; if (community != COMM_INITIALIZE) acl->type = StorageType_volatile; else acl->type = StorageType_readOnly; } else if (val->v.integer != RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = acl->status; acl->status = val->v.integer; break; } return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus) return (SNMP_ERR_NOERROR); if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); if (val->v.integer == RowStatus_destroy) return (vacm_delete_access_rule(acl)); else acl->status = RowStatus_active; return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->var.subs[sub - 1]) { case LEAF_vacmAccessContextMatch: acl->ctx_match = ctx->scratch->int1; break; case LEAF_vacmAccessReadViewName: acl->read_view = ctx->scratch->ptr1; break; case LEAF_vacmAccessWriteViewName: acl->write_view = ctx->scratch->ptr1; break; case LEAF_vacmAccessNotifyViewName: acl->notify_view = ctx->scratch->ptr1; break; case LEAF_vacmAccessStatus: if (ctx->scratch->int1 == RowStatus_destroy) return (vacm_delete_access_rule(acl)); default: break; } return (SNMP_ERR_NOERROR); default: abort(); } switch (val->var.subs[sub - 1]) { case LEAF_vacmAccessContextMatch: return (string_get(val, acl->ctx_prefix, -1)); case LEAF_vacmAccessReadViewName: if (acl->read_view != NULL) return (string_get(val, acl->read_view->viewname, -1)); else return (string_get(val, NULL, 0)); case LEAF_vacmAccessWriteViewName: if (acl->write_view != NULL) return (string_get(val, acl->write_view->viewname, -1)); else return (string_get(val, NULL, 0)); case LEAF_vacmAccessNotifyViewName: if (acl->notify_view != NULL) return (string_get(val, acl->notify_view->viewname, -1)); else return (string_get(val, NULL, 0)); case LEAF_vacmAccessStorageType: val->v.integer = acl->type; break; case LEAF_vacmAccessStatus: val->v.integer = acl->status; break; default: abort(); } return (SNMP_ERR_NOERROR); } int op_vacm_view_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_vacmViewSpinLock) return (SNMP_ERR_NOSUCHNAME); switch (op) { case SNMP_OP_GET: if (++vacm_lock == INT32_MAX) vacm_lock = 0; val->v.integer = vacm_lock; break; case SNMP_OP_GETNEXT: abort(); case SNMP_OP_SET: if (val->v.integer != vacm_lock) return (SNMP_ERR_INCONS_VALUE); break; case SNMP_OP_ROLLBACK: /* FALLTHROUGH */ case SNMP_OP_COMMIT: break; } return (SNMP_ERR_NOERROR); } int op_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, uint32_t iidx __unused, enum snmp_op op) { char vname[SNMP_ADM_STR32_SIZ]; struct asn_oid oid; struct vacm_view *view; switch (op) { case SNMP_OP_GET: if ((view = vacm_get_view(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); break; case SNMP_OP_GETNEXT: if ((view = vacm_get_next_view(&val->var, sub)) == NULL) return (SNMP_ERR_NOSUCHNAME); vacm_append_viewindex(&val->var, sub, view); break; case SNMP_OP_SET: if ((view = vacm_get_view(&val->var, sub)) == NULL && val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus) return (SNMP_ERR_NOSUCHNAME); if (view != NULL) { if (community != COMM_INITIALIZE && view->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); if (view->status == RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); } switch (val->var.subs[sub - 1]) { case LEAF_vacmViewTreeFamilyMask: if (val->v.octetstring.len > sizeof(view->mask)) ctx->scratch->ptr1 = malloc(sizeof(view->mask)); if (ctx->scratch->ptr1 == NULL) return (SNMP_ERR_GENERR); memset(ctx->scratch->ptr1, 0, sizeof(view->mask)); memcpy(ctx->scratch->ptr1, view->mask, sizeof(view->mask)); memset(view->mask, 0, sizeof(view->mask)); memcpy(view->mask, val->v.octetstring.octets, val->v.octetstring.len); break; case LEAF_vacmViewTreeFamilyType: ctx->scratch->int1 = view->exclude; if (val->v.integer == vacmViewTreeFamilyType_included) view->exclude = 0; else if (val->v.integer == vacmViewTreeFamilyType_excluded) view->exclude = 1; else return (SNMP_ERR_WRONG_VALUE); break; case LEAF_vacmViewTreeFamilyStorageType: return (SNMP_ERR_INCONS_VALUE); case LEAF_vacmViewTreeFamilyStatus: if (view == NULL) { if (val->v.integer != RowStatus_createAndGo || vacm_view_index_decode(&val->var, sub, vname, &oid) < 0) return (SNMP_ERR_INCONS_VALUE); if ((view = vacm_new_view(vname, &oid)) == NULL) return (SNMP_ERR_GENERR); view->status = RowStatus_destroy; if (community != COMM_INITIALIZE) view->type = StorageType_volatile; else view->type = StorageType_readOnly; } else if (val->v.integer != RowStatus_active && val->v.integer != RowStatus_destroy) return (SNMP_ERR_INCONS_VALUE); ctx->scratch->int1 = view->status; view->status = val->v.integer; break; } return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: switch (val->var.subs[sub - 1]) { case LEAF_vacmViewTreeFamilyMask: free(ctx->scratch->ptr1); break; case LEAF_vacmViewTreeFamilyStatus: if ((view = vacm_get_view(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->v.integer) { case RowStatus_destroy: return (vacm_delete_view(view)); case RowStatus_createAndGo: view->status = RowStatus_active; break; default: /* NOTREACHED*/ return (SNMP_ERR_GENERR); } default: break; } return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: if ((view = vacm_get_view(&val->var, sub)) == NULL) return (SNMP_ERR_GENERR); switch (val->var.subs[sub - 1]) { case LEAF_vacmViewTreeFamilyMask: memcpy(view->mask, ctx->scratch->ptr1, sizeof(view->mask)); free(ctx->scratch->ptr1); break; case LEAF_vacmViewTreeFamilyType: view->exclude = ctx->scratch->int1; break; case LEAF_vacmViewTreeFamilyStatus: if (ctx->scratch->int1 == RowStatus_destroy) return (vacm_delete_view(view)); break; default: break; } return (SNMP_ERR_NOERROR); default: abort(); } switch (val->var.subs[sub - 1]) { case LEAF_vacmViewTreeFamilyMask: return (string_get(val, view->mask, sizeof(view->mask))); case LEAF_vacmViewTreeFamilyType: if (view->exclude) val->v.integer = vacmViewTreeFamilyType_excluded; else val->v.integer = vacmViewTreeFamilyType_included; break; case LEAF_vacmViewTreeFamilyStorageType: val->v.integer = view->type; break; case LEAF_vacmViewTreeFamilyStatus: val->v.integer = view->status; break; default: abort(); } return (SNMP_ERR_NOERROR); } static void vacm_append_userindex(struct asn_oid *oid, uint sub, const struct vacm_user *user) { uint32_t i; oid->len = sub + strlen(user->secname) + 2; oid->subs[sub++] = user->sec_model; oid->subs[sub] = strlen(user->secname); for (i = 1; i <= strlen(user->secname); i++) oid->subs[sub + i] = user->secname[i - 1]; } static int vacm_user_index_decode(const struct asn_oid *oid, uint sub, int32_t *smodel, char *uname) { uint32_t i; *smodel = oid->subs[sub++]; if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (-1); for (i = 0; i < oid->subs[sub]; i++) uname[i] = oid->subs[sub + i + 1]; uname[i] = '\0'; return (0); } static struct vacm_user * vacm_get_user(const struct asn_oid *oid, uint sub) { int32_t smodel; char uname[SNMP_ADM_STR32_SIZ]; struct vacm_user *user; if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0) return (NULL); for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user)) if (strcmp(uname, user->secname) == 0 && user->sec_model == smodel) return (user); return (NULL); } static struct vacm_user * vacm_get_next_user(const struct asn_oid *oid, uint sub) { int32_t smodel; char uname[SNMP_ADM_STR32_SIZ]; struct vacm_user *user; if (oid->len - sub == 0) return (vacm_first_user()); if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0) return (NULL); for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user)) if (strcmp(uname, user->secname) == 0 && user->sec_model == smodel) return (vacm_next_user(user)); return (NULL); } static void vacm_append_access_rule_index(struct asn_oid *oid, uint sub, const struct vacm_access *acl) { uint32_t i; oid->len = sub + strlen(acl->group->groupname) + strlen(acl->ctx_prefix) + 4; oid->subs[sub] = strlen(acl->group->groupname); for (i = 1; i <= strlen(acl->group->groupname); i++) oid->subs[sub + i] = acl->group->groupname[i - 1]; sub += strlen(acl->group->groupname) + 1; oid->subs[sub] = strlen(acl->ctx_prefix); for (i = 1; i <= strlen(acl->ctx_prefix); i++) oid->subs[sub + i] = acl->ctx_prefix[i - 1]; sub += strlen(acl->ctx_prefix) + 1; oid->subs[sub++] = acl->sec_model; oid->subs[sub] = acl->sec_level; } static int vacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname, char *cprefix, int32_t *smodel, int32_t *slevel) { uint32_t i; if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (-1); for (i = 0; i < oid->subs[sub]; i++) gname[i] = oid->subs[sub + i + 1]; gname[i] = '\0'; sub += strlen(gname) + 1; if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (-1); for (i = 0; i < oid->subs[sub]; i++) cprefix[i] = oid->subs[sub + i + 1]; cprefix[i] = '\0'; sub += strlen(cprefix) + 1; *smodel = oid->subs[sub++]; *slevel = oid->subs[sub]; return (0); } struct vacm_access * vacm_get_access_rule(const struct asn_oid *oid, uint sub) { int32_t smodel, slevel; char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ]; struct vacm_access *acl; if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel, &slevel) < 0) return (NULL); for (acl = vacm_first_access_rule(); acl != NULL; acl = vacm_next_access_rule(acl)) if (strcmp(gname, acl->group->groupname) == 0 && strcmp(prefix, acl->ctx_prefix) == 0 && smodel == acl->sec_model && slevel == acl->sec_level) return (acl); return (NULL); } struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused) { int32_t smodel, slevel; char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ]; struct vacm_access *acl; if (oid->len - sub == 0) return (vacm_first_access_rule()); if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel, &slevel) < 0) return (NULL); for (acl = vacm_first_access_rule(); acl != NULL; acl = vacm_next_access_rule(acl)) if (strcmp(gname, acl->group->groupname) == 0 && strcmp(prefix, acl->ctx_prefix) == 0 && smodel == acl->sec_model && slevel == acl->sec_model) return (vacm_next_access_rule(acl)); return (NULL); } static int vacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname, struct asn_oid *view_oid) { uint32_t i; int viod_off; if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (-1); for (i = 0; i < oid->subs[sub]; i++) vname[i] = oid->subs[sub + i + 1]; vname[i] = '\0'; viod_off = sub + oid->subs[sub] + 1; if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN) return (-1); memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1], view_oid->len * sizeof(view_oid->subs[0])); return (0); } static void vacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view) { uint32_t i; oid->len = sub + strlen(view->viewname) + 1; oid->subs[sub] = strlen(view->viewname); for (i = 1; i <= strlen(view->viewname); i++) oid->subs[sub + i] = view->viewname[i - 1]; sub += strlen(view->viewname) + 1; oid->subs[sub] = view->subtree.len; oid->len++; asn_append_oid(oid, &view->subtree); } struct vacm_view * vacm_get_view(const struct asn_oid *oid, uint sub) { char vname[SNMP_ADM_STR32_SIZ]; struct asn_oid subtree; struct vacm_view *view; if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0) return (NULL); for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) if (strcmp(vname, view->viewname) == 0 && asn_compare_oid(&subtree, &view->subtree)== 0) return (view); return (NULL); } struct vacm_view * vacm_get_next_view(const struct asn_oid *oid, uint sub) { char vname[SNMP_ADM_STR32_SIZ]; struct asn_oid subtree; struct vacm_view *view; if (oid->len - sub == 0) return (vacm_first_view()); if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0) return (NULL); for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) if (strcmp(vname, view->viewname) == 0 && asn_compare_oid(&subtree, &view->subtree)== 0) return (vacm_next_view(view)); return (NULL); } static struct vacm_view * vacm_get_view_by_name(u_char *octets, u_int len) { struct vacm_view *view; for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) if (strlen(view->viewname) == len && memcmp(octets, view->viewname, len) == 0) return (view); return (NULL); } static struct vacm_context * vacm_get_context(const struct asn_oid *oid, uint sub) { char cname[SNMP_ADM_STR32_SIZ]; size_t cnamelen; u_int index_count; struct vacm_context *vacm_ctx; if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (NULL); index_count = 0; index_count = SNMP_INDEX(index_count, 1); if (index_decode(oid, sub, index_count, &cname, &cnamelen)) return (NULL); for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL; vacm_ctx = vacm_next_context(vacm_ctx)) if (strcmp(cname, vacm_ctx->ctxname) == 0) return (vacm_ctx); return (NULL); } static struct vacm_context * vacm_get_next_context(const struct asn_oid *oid, uint sub) { char cname[SNMP_ADM_STR32_SIZ]; size_t cnamelen; u_int index_count; struct vacm_context *vacm_ctx; if (oid->len - sub == 0) return (vacm_first_context()); if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) return (NULL); index_count = 0; index_count = SNMP_INDEX(index_count, 1); if (index_decode(oid, sub, index_count, &cname, &cnamelen)) return (NULL); for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL; vacm_ctx = vacm_next_context(vacm_ctx)) if (strcmp(cname, vacm_ctx->ctxname) == 0) return (vacm_next_context(vacm_ctx)); return (NULL); } static void vacm_append_ctxindex(struct asn_oid *oid, uint sub, const struct vacm_context *ctx) { uint32_t i; oid->len = sub + strlen(ctx->ctxname) + 1; oid->subs[sub] = strlen(ctx->ctxname); for (i = 1; i <= strlen(ctx->ctxname); i++) oid->subs[sub + i] = ctx->ctxname[i - 1]; } /* * VACM snmp module initialization hook. * Returns 0 on success, < 0 on error. */ static int vacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) { vacm_module = mod; vacm_lock = random(); vacm_groups_init(); /* XXX: TODO - initialize structures */ return (0); } /* * VACM snmp module finalization hook. */ static int vacm_fini(void) { /* XXX: TODO - cleanup */ vacm_flush_contexts(reg_vacm); or_unregister(reg_vacm); return (0); } /* * VACM snmp module start operation. */ static void vacm_start(void) { static char dflt_ctx[] = ""; reg_vacm = or_register(&oid_vacm, "The MIB module for managing SNMP View-based Access Control Model.", vacm_module); (void)vacm_add_context(dflt_ctx, reg_vacm); } static void vacm_dump(void) { struct vacm_context *vacmctx; struct vacm_user *vuser; struct vacm_access *vacl; struct vacm_view *view; static char oidbuf[ASN_OIDSTRLEN]; syslog(LOG_ERR, "\n"); syslog(LOG_ERR, "Context list:"); for (vacmctx = vacm_first_context(); vacmctx != NULL; vacmctx = vacm_next_context(vacmctx)) syslog(LOG_ERR, "Context \"%s\", module id %d", vacmctx->ctxname, vacmctx->regid); syslog(LOG_ERR, "VACM users:"); for (vuser = vacm_first_user(); vuser != NULL; vuser = vacm_next_user(vuser)) syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname, vuser->group!= NULL?vuser->group->groupname:"Unknown", vuser->sec_model); syslog(LOG_ERR, "VACM Access rules:"); for (vacl = vacm_first_access_rule(); vacl != NULL; vacl = vacm_next_access_rule(vacl)) syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, " "RV %s, WR %s, NV %s", vacl->group!=NULL? vacl->group->groupname:"Unknown", vacl->ctx_prefix, vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL? vacl->read_view->viewname:"None", vacl->write_view!=NULL? vacl->write_view->viewname:"None", vacl->notify_view!=NULL? vacl->notify_view->viewname:"None"); syslog(LOG_ERR, "VACM Views:"); for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname, asn_oid2str_r(&view->subtree, oidbuf), view->exclude? "excluded":"included"); } static const char vacm_comment[] = "This module implements SNMP View-based Access Control Model defined in RFC 3415."; extern const struct snmp_module config; const struct snmp_module config = { .comment = vacm_comment, .init = vacm_init, .fini = vacm_fini, .start = vacm_start, .tree = vacm_ctree, .dump = vacm_dump, .tree_size = vacm_CTREE_SIZE, }; diff --git a/contrib/bsnmp/snmp_vacm/vacm_tree.def b/contrib/bsnmp/snmp_vacm/vacm_tree.def index 5418a5a6cac1..a68cc8eed103 100644 --- a/contrib/bsnmp/snmp_vacm/vacm_tree.def +++ b/contrib/bsnmp/snmp_vacm/vacm_tree.def @@ -1,89 +1,88 @@ #- # 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$ # include "tc.def" (1 internet (6 snmpV2 (3 snmpModules (16 snmpVacmMIB (1 vacmMIBObjects (1 vacmContextTable (1 vacmContextEntry : OCTETSTRING op_vacm_context (1 vacmContextName OCTETSTRING GET) ) ) (2 vacmSecurityToGroupTable (1 vacmSecurityToGroupEntry : INTEGER OCTETSTRING op_vacm_security_to_group (1 vacmSecurityModel INTEGER) (2 vacmSecurityName OCTETSTRING) (3 vacmGroupName OCTETSTRING GET SET) (4 vacmSecurityToGroupStorageType StorageType GET SET) (5 vacmSecurityToGroupStatus RowStatus GET SET) ) ) (4 vacmAccessTable (1 vacmAccessEntry : OCTETSTRING OCTETSTRING INTEGER ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ) op_vacm_access (1 vacmAccessContextPrefix OCTETSTRING) (2 vacmAccessSecurityModel INTEGER) (3 vacmAccessSecurityLevel ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv )) (4 vacmAccessContextMatch ENUM ( 1 exact 2 prefix ) GET SET) (5 vacmAccessReadViewName OCTETSTRING GET SET) (6 vacmAccessWriteViewName OCTETSTRING GET SET) (7 vacmAccessNotifyViewName OCTETSTRING GET SET) (8 vacmAccessStorageType StorageType GET SET) (9 vacmAccessStatus RowStatus GET SET) ) ) (5 vacmMIBViews (1 vacmViewSpinLock INTEGER op_vacm_view_lock GET SET) (2 vacmViewTreeFamilyTable (1 vacmViewTreeFamilyEntry : OCTETSTRING OID op_vacm_view (1 vacmViewTreeFamilyViewName OCTETSTRING) (2 vacmViewTreeFamilySubtree OID) (3 vacmViewTreeFamilyMask OCTETSTRING GET SET) (4 vacmViewTreeFamilyType ENUM ( 1 included 2 excluded ) GET SET) (5 vacmViewTreeFamilyStorageType StorageType GET SET) (6 vacmViewTreeFamilyStatus RowStatus GET SET) ) ) ) ) (2 vacmMIBConformance (1 vacmMIBCompliances ) (2 vacmMIBGroups ) ) ) ) ) )