diff options
author | ae <ae@FreeBSD.org> | 2018-02-02 07:48:46 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2018-02-02 07:48:46 +0000 |
commit | 73f9a6a8284d34b704d330261b85973b93e47ed2 (patch) | |
tree | 1986622c1f620a3fd673b865f5d0bb5490977c2d | |
parent | 330151004a6f6a1c10107a928648ccc380eafe71 (diff) | |
download | FreeBSD-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.txt | 13 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/action.c | 58 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/main.c | 77 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/snmpd.config | 1 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/snmpmod.h | 2 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/tree.def | 1 |
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 |