summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2018-02-02 07:48:46 +0000
committerae <ae@FreeBSD.org>2018-02-02 07:48:46 +0000
commit73f9a6a8284d34b704d330261b85973b93e47ed2 (patch)
tree1986622c1f620a3fd673b865f5d0bb5490977c2d
parent330151004a6f6a1c10107a928648ccc380eafe71 (diff)
downloadFreeBSD-src-73f9a6a8284d34b704d330261b85973b93e47ed2.zip
FreeBSD-src-73f9a6a8284d34b704d330261b85973b93e47ed2.tar.gz
MFC r328160:
Add to bsnmpd(1) ability to specify multiple community strings with different access rights. By default there are two community strings with index 1 and 2, one for read-only access and second for read-write access: begemotSnmpdCommunityString.0.1 = $(read) begemotSnmpdCommunityString.0.2 = $(write) Now it is possible to define additional community strings using different indexes: begemotSnmpdCommunityString.0.3 = "SomeString1" begemotSnmpdCommunityPermission.0.3 = 1 begemotSnmpdCommunityString.0.4 = "SomeString2" begemotSnmpdCommunityPermission.0.4 = 2 begemotSnmpdCommunityString.0.5 = "SomeString3" begemotSnmpdCommunityString.0.6 = "SomeString4" New attribute begemotSnmpdCommunityPermission can be used to specify access rights: 1 means "read-only" access, 2 means "read-write" access. If attribute is not specified for some index this means "read-only" rights. Community strings must be unique, i.e. must not be the same for different indexes. Obtained from: Yandex LLC Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D13785 MFC r328171: Rename "index" variable to "idx" since gcc complains that it shadows index(3) function declaration.
-rw-r--r--contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt13
-rw-r--r--contrib/bsnmp/snmpd/action.c58
-rw-r--r--contrib/bsnmp/snmpd/main.c77
-rw-r--r--contrib/bsnmp/snmpd/snmpd.config1
-rw-r--r--contrib/bsnmp/snmpd/snmpmod.h2
-rw-r--r--contrib/bsnmp/snmpd/tree.def1
6 files changed, 116 insertions, 36 deletions
diff --git a/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt b/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt
index d87e78e..0a68ed9 100644
--- a/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt
+++ b/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt
@@ -44,7 +44,7 @@ IMPORTS
FROM BEGEMOT-MIB;
begemotSnmpd MODULE-IDENTITY
- LAST-UPDATED "200212040000Z"
+ LAST-UPDATED "201801190000Z"
ORGANIZATION "Fraunhofer FOKUS, CATS"
CONTACT-INFO
" Hartmut Brandt
@@ -274,7 +274,8 @@ BegemotSnmpdCommunityEntry ::= SEQUENCE {
begemotSnmpdCommunityModule SectionName,
begemotSnmpdCommunityIndex Unsigned32,
begemotSnmpdCommunityString OCTET STRING,
- begemotSnmpdCommunityDescr OCTET STRING
+ begemotSnmpdCommunityDescr OCTET STRING,
+ begemotSnmpdCommunityPermission INTEGER
}
begemotSnmpdCommunityModule OBJECT-TYPE
@@ -310,6 +311,14 @@ begemotSnmpdCommunityDescr OBJECT-TYPE
"A description what this community is good for."
::= { begemotSnmpdCommunityEntry 4 }
+begemotSnmpdCommunityPermission OBJECT-TYPE
+ SYNTAX INTEGER (1..4294967295)
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The numerical value of access rights granted to the community."
+ ::= { begemotSnmpdCommunityEntry 5 }
+
--
-- Module table
--
diff --git a/contrib/bsnmp/snmpd/action.c b/contrib/bsnmp/snmpd/action.c
index 54a5d29..4e0be6a 100644
--- a/contrib/bsnmp/snmpd/action.c
+++ b/contrib/bsnmp/snmpd/action.c
@@ -751,8 +751,9 @@ int
op_community(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
- asn_subid_t which = value->var.subs[sub - 1];
+ struct asn_oid idx;
struct community *c;
+ asn_subid_t which = value->var.subs[sub - 1];
switch (op) {
@@ -770,12 +771,47 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
break;
case SNMP_OP_SET:
- if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
- (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
- return (SNMP_ERR_NO_CREATION);
- if (which != LEAF_begemotSnmpdCommunityString)
+ if (community != COMM_INITIALIZE && snmpd.comm_dis)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ idx.len = 2;
+ idx.subs[0] = 0;
+ idx.subs[1] = value->var.subs[value->var.len - 1];
+ switch (which) {
+ case LEAF_begemotSnmpdCommunityString:
+ /* check that given string is unique */
+ TAILQ_FOREACH(c, &community_list, link) {
+ if (!asn_compare_oid(&idx, &c->index))
+ continue;
+ if (c->string != NULL && strcmp(c->string,
+ value->v.octetstring.octets) == 0)
+ return (SNMP_ERR_WRONG_VALUE);
+ }
+ case LEAF_begemotSnmpdCommunityPermission:
+ break;
+ default:
+ return (SNMP_ERR_NOT_WRITEABLE);
+ }
+ if ((c = FIND_OBJECT_OID(&community_list, &value->var,
+ sub)) == NULL) {
+ /* create new community and use user sepcified index */
+ c = comm_define_ordered(COMM_READ, "SNMP Custom Community",
+ &idx, NULL, NULL);
+ if (c == NULL)
+ return (SNMP_ERR_NO_CREATION);
+ }
+ switch (which) {
+ case LEAF_begemotSnmpdCommunityString:
+ return (string_save(value, ctx, -1, &c->string));
+ case LEAF_begemotSnmpdCommunityPermission:
+ if (value->v.integer != COMM_READ &&
+ value->v.integer != COMM_WRITE)
+ return (SNMP_ERR_WRONG_VALUE);
+ c->private = value->v.integer;
+ break;
+ default:
return (SNMP_ERR_NOT_WRITEABLE);
- return (string_save(value, ctx, -1, &c->string));
+ }
+ return (SNMP_ERR_NOERROR);
case SNMP_OP_ROLLBACK:
if (which == LEAF_begemotSnmpdCommunityString) {
@@ -786,6 +822,8 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
string_rollback(ctx, &c->string);
return (SNMP_ERR_NOERROR);
}
+ if (which == LEAF_begemotSnmpdCommunityPermission)
+ return (SNMP_ERR_NOERROR);
abort();
case SNMP_OP_COMMIT:
@@ -797,6 +835,8 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
string_commit(ctx);
return (SNMP_ERR_NOERROR);
}
+ if (which == LEAF_begemotSnmpdCommunityPermission)
+ return (SNMP_ERR_NOERROR);
abort();
default:
@@ -810,6 +850,12 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
case LEAF_begemotSnmpdCommunityDescr:
return (string_get(value, c->descr, -1));
+
+ case LEAF_begemotSnmpdCommunityPermission:
+ value->v.integer = c->private;
+ return (SNMP_ERR_NOERROR);
+ default:
+ return (SNMP_ERR_NOT_WRITEABLE);
}
abort();
}
diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c
index 7037833..939b350 100644
--- a/contrib/bsnmp/snmpd/main.c
+++ b/contrib/bsnmp/snmpd/main.c
@@ -1160,8 +1160,8 @@ snmpd_input(struct port_input *pi, struct tport *tport)
*/
if (pdu.version < SNMP_V3 &&
((pi->cred && !pi->priv && pdu.type == SNMP_PDU_SET) ||
- (community != COMM_WRITE &&
- (pdu.type == SNMP_PDU_SET || community != COMM_READ)))) {
+ (comm != NULL && comm->private != COMM_WRITE &&
+ (pdu.type == SNMP_PDU_SET || comm->private != COMM_READ)))) {
snmpd_stats.inBadCommunityUses++;
snmp_pdu_free(&pdu);
snmp_input_consume(pi);
@@ -1609,8 +1609,8 @@ main(int argc, char *argv[])
/*
* Get standard communities
*/
- (void)comm_define(1, "SNMP read", NULL, NULL);
- (void)comm_define(2, "SNMP write", NULL, NULL);
+ comm_define(COMM_READ, "SNMP read", NULL, NULL);
+ comm_define(COMM_WRITE, "SNMP write", NULL, NULL);
community = COMM_INITIALIZE;
trap_reqid = reqid_allocate(512, NULL);
@@ -2027,25 +2027,23 @@ asn_error_func(const struct asn_buf *b, const char *err, ...)
/*
* Create a new community
*/
-u_int
-comm_define(u_int priv, const char *descr, struct lmodule *owner,
- const char *str)
+struct community*
+comm_define_ordered(u_int priv, const char *descr, struct asn_oid *idx,
+ struct lmodule *owner, const char *str)
{
struct community *c, *p;
u_int ncomm;
- /* generate an identifier */
- do {
- if ((ncomm = next_community_index++) == UINT_MAX)
- next_community_index = 1;
- TAILQ_FOREACH(c, &community_list, link)
- if (c->value == ncomm)
- break;
- } while (c != NULL);
+ ncomm = idx->subs[idx->len - 1];
+
+ /* check that community doesn't already exist */
+ TAILQ_FOREACH(c, &community_list, link)
+ if (c->value == ncomm)
+ return (c);
if ((c = malloc(sizeof(struct community))) == NULL) {
- syslog(LOG_ERR, "comm_define: %m");
- return (0);
+ syslog(LOG_ERR, "%s: %m", __func__);
+ return (NULL);
}
c->owner = owner;
c->value = ncomm;
@@ -2056,23 +2054,14 @@ comm_define(u_int priv, const char *descr, struct lmodule *owner,
if (str != NULL) {
if((c->string = malloc(strlen(str)+1)) == NULL) {
free(c);
- return (0);
+ return (NULL);
}
strcpy(c->string, str);
}
-
- /* make index */
- if (c->owner == NULL) {
- c->index.len = 1;
- c->index.subs[0] = 0;
- } else {
- c->index = c->owner->index;
- }
- c->index.subs[c->index.len++] = c->private;
-
/*
* Insert ordered
*/
+ c->index = *idx;
TAILQ_FOREACH(p, &community_list, link) {
if (asn_compare_oid(&p->index, &c->index) > 0) {
TAILQ_INSERT_BEFORE(p, c, link);
@@ -2081,6 +2070,38 @@ comm_define(u_int priv, const char *descr, struct lmodule *owner,
}
if (p == NULL)
TAILQ_INSERT_TAIL(&community_list, c, link);
+ return (c);
+}
+
+u_int
+comm_define(u_int priv, const char *descr, struct lmodule *owner,
+ const char *str)
+{
+ struct asn_oid idx, *p;
+ struct community *c;
+ u_int ncomm;
+
+ /* generate an identifier */
+ do {
+ if ((ncomm = next_community_index++) == UINT_MAX)
+ next_community_index = 1;
+ TAILQ_FOREACH(c, &community_list, link)
+ if (c->value == ncomm)
+ break;
+ } while (c != NULL);
+
+ /* make index */
+ if (owner != NULL)
+ p = &owner->index;
+ else {
+ p = &idx;
+ p->len = 1;
+ p->subs[0] = 0;
+ }
+ p->subs[p->len++] = ncomm;
+ c = comm_define_ordered(priv, descr, p, owner, str);
+ if (c == NULL)
+ return (0);
return (c->value);
}
diff --git a/contrib/bsnmp/snmpd/snmpd.config b/contrib/bsnmp/snmpd/snmpd.config
index 2b93553..f9f8841 100644
--- a/contrib/bsnmp/snmpd/snmpd.config
+++ b/contrib/bsnmp/snmpd/snmpd.config
@@ -68,6 +68,7 @@ begemotSnmpdDebugSyslogPri = 7
#
begemotSnmpdCommunityString.0.1 = $(read)
# begemotSnmpdCommunityString.0.2 = $(write)
+# begemotSnmpdCommunityString.0.3 = "otherPublic"
begemotSnmpdCommunityDisable = 1
# open standard SNMP ports
diff --git a/contrib/bsnmp/snmpd/snmpmod.h b/contrib/bsnmp/snmpd/snmpmod.h
index c9e609f..cc6b14e 100644
--- a/contrib/bsnmp/snmpd/snmpmod.h
+++ b/contrib/bsnmp/snmpd/snmpmod.h
@@ -334,6 +334,8 @@ extern struct systemg systemg;
#define COMM_WRITE 2
u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str);
+struct community *comm_define_ordered(u_int priv, const char *descr,
+ struct asn_oid *index, struct lmodule *owner, const char *str);
const char * comm_string(u_int);
/* community for current packet */
diff --git a/contrib/bsnmp/snmpd/tree.def b/contrib/bsnmp/snmpd/tree.def
index eb8dac2..2b6a9b9 100644
--- a/contrib/bsnmp/snmpd/tree.def
+++ b/contrib/bsnmp/snmpd/tree.def
@@ -135,6 +135,7 @@ typedef RowStatus ENUM (
(2 begemotSnmpdCommunityIndex UNSIGNED32)
(3 begemotSnmpdCommunityString OCTETSTRING GET SET)
(4 begemotSnmpdCommunityDescr OCTETSTRING GET)
+ (5 begemotSnmpdCommunityPermission INTEGER GET SET)
))
#
# Module table
OpenPOWER on IntegriCloud