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 MFC after: 2 weeks Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D13785
This commit is contained in:
parent
d3f8974a32
commit
f3afd27f5f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=328160
@ -44,7 +44,7 @@ IMPORTS
|
|||||||
FROM BEGEMOT-MIB;
|
FROM BEGEMOT-MIB;
|
||||||
|
|
||||||
begemotSnmpd MODULE-IDENTITY
|
begemotSnmpd MODULE-IDENTITY
|
||||||
LAST-UPDATED "200212040000Z"
|
LAST-UPDATED "201801190000Z"
|
||||||
ORGANIZATION "Fraunhofer FOKUS, CATS"
|
ORGANIZATION "Fraunhofer FOKUS, CATS"
|
||||||
CONTACT-INFO
|
CONTACT-INFO
|
||||||
" Hartmut Brandt
|
" Hartmut Brandt
|
||||||
@ -274,7 +274,8 @@ BegemotSnmpdCommunityEntry ::= SEQUENCE {
|
|||||||
begemotSnmpdCommunityModule SectionName,
|
begemotSnmpdCommunityModule SectionName,
|
||||||
begemotSnmpdCommunityIndex Unsigned32,
|
begemotSnmpdCommunityIndex Unsigned32,
|
||||||
begemotSnmpdCommunityString OCTET STRING,
|
begemotSnmpdCommunityString OCTET STRING,
|
||||||
begemotSnmpdCommunityDescr OCTET STRING
|
begemotSnmpdCommunityDescr OCTET STRING,
|
||||||
|
begemotSnmpdCommunityPermission INTEGER
|
||||||
}
|
}
|
||||||
|
|
||||||
begemotSnmpdCommunityModule OBJECT-TYPE
|
begemotSnmpdCommunityModule OBJECT-TYPE
|
||||||
@ -310,6 +311,14 @@ begemotSnmpdCommunityDescr OBJECT-TYPE
|
|||||||
"A description what this community is good for."
|
"A description what this community is good for."
|
||||||
::= { begemotSnmpdCommunityEntry 4 }
|
::= { 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
|
-- Module table
|
||||||
--
|
--
|
||||||
|
@ -751,8 +751,9 @@ int
|
|||||||
op_community(struct snmp_context *ctx, struct snmp_value *value,
|
op_community(struct snmp_context *ctx, struct snmp_value *value,
|
||||||
u_int sub, u_int iidx __unused, enum snmp_op op)
|
u_int sub, u_int iidx __unused, enum snmp_op op)
|
||||||
{
|
{
|
||||||
asn_subid_t which = value->var.subs[sub - 1];
|
struct asn_oid index;
|
||||||
struct community *c;
|
struct community *c;
|
||||||
|
asn_subid_t which = value->var.subs[sub - 1];
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
|
||||||
@ -770,12 +771,47 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SNMP_OP_SET:
|
case SNMP_OP_SET:
|
||||||
if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
|
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)
|
|
||||||
return (SNMP_ERR_NOT_WRITEABLE);
|
return (SNMP_ERR_NOT_WRITEABLE);
|
||||||
return (string_save(value, ctx, -1, &c->string));
|
index.len = 2;
|
||||||
|
index.subs[0] = 0;
|
||||||
|
index.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(&index, &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",
|
||||||
|
&index, 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 (SNMP_ERR_NOERROR);
|
||||||
|
|
||||||
case SNMP_OP_ROLLBACK:
|
case SNMP_OP_ROLLBACK:
|
||||||
if (which == LEAF_begemotSnmpdCommunityString) {
|
if (which == LEAF_begemotSnmpdCommunityString) {
|
||||||
@ -786,6 +822,8 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
|
|||||||
string_rollback(ctx, &c->string);
|
string_rollback(ctx, &c->string);
|
||||||
return (SNMP_ERR_NOERROR);
|
return (SNMP_ERR_NOERROR);
|
||||||
}
|
}
|
||||||
|
if (which == LEAF_begemotSnmpdCommunityPermission)
|
||||||
|
return (SNMP_ERR_NOERROR);
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
case SNMP_OP_COMMIT:
|
case SNMP_OP_COMMIT:
|
||||||
@ -797,6 +835,8 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
|
|||||||
string_commit(ctx);
|
string_commit(ctx);
|
||||||
return (SNMP_ERR_NOERROR);
|
return (SNMP_ERR_NOERROR);
|
||||||
}
|
}
|
||||||
|
if (which == LEAF_begemotSnmpdCommunityPermission)
|
||||||
|
return (SNMP_ERR_NOERROR);
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -810,6 +850,12 @@ op_community(struct snmp_context *ctx, struct snmp_value *value,
|
|||||||
|
|
||||||
case LEAF_begemotSnmpdCommunityDescr:
|
case LEAF_begemotSnmpdCommunityDescr:
|
||||||
return (string_get(value, c->descr, -1));
|
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();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -1160,8 +1160,8 @@ snmpd_input(struct port_input *pi, struct tport *tport)
|
|||||||
*/
|
*/
|
||||||
if (pdu.version < SNMP_V3 &&
|
if (pdu.version < SNMP_V3 &&
|
||||||
((pi->cred && !pi->priv && pdu.type == SNMP_PDU_SET) ||
|
((pi->cred && !pi->priv && pdu.type == SNMP_PDU_SET) ||
|
||||||
(community != COMM_WRITE &&
|
(comm != NULL && comm->private != COMM_WRITE &&
|
||||||
(pdu.type == SNMP_PDU_SET || community != COMM_READ)))) {
|
(pdu.type == SNMP_PDU_SET || comm->private != COMM_READ)))) {
|
||||||
snmpd_stats.inBadCommunityUses++;
|
snmpd_stats.inBadCommunityUses++;
|
||||||
snmp_pdu_free(&pdu);
|
snmp_pdu_free(&pdu);
|
||||||
snmp_input_consume(pi);
|
snmp_input_consume(pi);
|
||||||
@ -1609,8 +1609,8 @@ main(int argc, char *argv[])
|
|||||||
/*
|
/*
|
||||||
* Get standard communities
|
* Get standard communities
|
||||||
*/
|
*/
|
||||||
(void)comm_define(1, "SNMP read", NULL, NULL);
|
comm_define(COMM_READ, "SNMP read", NULL, NULL);
|
||||||
(void)comm_define(2, "SNMP write", NULL, NULL);
|
comm_define(COMM_WRITE, "SNMP write", NULL, NULL);
|
||||||
community = COMM_INITIALIZE;
|
community = COMM_INITIALIZE;
|
||||||
|
|
||||||
trap_reqid = reqid_allocate(512, NULL);
|
trap_reqid = reqid_allocate(512, NULL);
|
||||||
@ -2027,11 +2027,58 @@ asn_error_func(const struct asn_buf *b, const char *err, ...)
|
|||||||
/*
|
/*
|
||||||
* Create a new community
|
* Create a new community
|
||||||
*/
|
*/
|
||||||
|
struct community*
|
||||||
|
comm_define_ordered(u_int priv, const char *descr, struct asn_oid *index,
|
||||||
|
struct lmodule *owner, const char *str)
|
||||||
|
{
|
||||||
|
struct community *c, *p;
|
||||||
|
u_int ncomm;
|
||||||
|
|
||||||
|
ncomm = index->subs[index->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, "%s: %m", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
c->owner = owner;
|
||||||
|
c->value = ncomm;
|
||||||
|
c->descr = descr;
|
||||||
|
c->string = NULL;
|
||||||
|
c->private = priv;
|
||||||
|
|
||||||
|
if (str != NULL) {
|
||||||
|
if((c->string = malloc(strlen(str)+1)) == NULL) {
|
||||||
|
free(c);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
strcpy(c->string, str);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Insert ordered
|
||||||
|
*/
|
||||||
|
c->index = *index;
|
||||||
|
TAILQ_FOREACH(p, &community_list, link) {
|
||||||
|
if (asn_compare_oid(&p->index, &c->index) > 0) {
|
||||||
|
TAILQ_INSERT_BEFORE(p, c, link);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p == NULL)
|
||||||
|
TAILQ_INSERT_TAIL(&community_list, c, link);
|
||||||
|
return (c);
|
||||||
|
}
|
||||||
|
|
||||||
u_int
|
u_int
|
||||||
comm_define(u_int priv, const char *descr, struct lmodule *owner,
|
comm_define(u_int priv, const char *descr, struct lmodule *owner,
|
||||||
const char *str)
|
const char *str)
|
||||||
{
|
{
|
||||||
struct community *c, *p;
|
struct asn_oid index, *p;
|
||||||
|
struct community *c;
|
||||||
u_int ncomm;
|
u_int ncomm;
|
||||||
|
|
||||||
/* generate an identifier */
|
/* generate an identifier */
|
||||||
@ -2043,44 +2090,18 @@ comm_define(u_int priv, const char *descr, struct lmodule *owner,
|
|||||||
break;
|
break;
|
||||||
} while (c != NULL);
|
} while (c != NULL);
|
||||||
|
|
||||||
if ((c = malloc(sizeof(struct community))) == NULL) {
|
|
||||||
syslog(LOG_ERR, "comm_define: %m");
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
c->owner = owner;
|
|
||||||
c->value = ncomm;
|
|
||||||
c->descr = descr;
|
|
||||||
c->string = NULL;
|
|
||||||
c->private = priv;
|
|
||||||
|
|
||||||
if (str != NULL) {
|
|
||||||
if((c->string = malloc(strlen(str)+1)) == NULL) {
|
|
||||||
free(c);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
strcpy(c->string, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make index */
|
/* make index */
|
||||||
if (c->owner == NULL) {
|
if (owner != NULL)
|
||||||
c->index.len = 1;
|
p = &owner->index;
|
||||||
c->index.subs[0] = 0;
|
else {
|
||||||
} else {
|
p = &index;
|
||||||
c->index = c->owner->index;
|
p->len = 1;
|
||||||
|
p->subs[0] = 0;
|
||||||
}
|
}
|
||||||
c->index.subs[c->index.len++] = c->private;
|
p->subs[p->len++] = ncomm;
|
||||||
|
c = comm_define_ordered(priv, descr, p, owner, str);
|
||||||
/*
|
if (c == NULL)
|
||||||
* Insert ordered
|
return (0);
|
||||||
*/
|
|
||||||
TAILQ_FOREACH(p, &community_list, link) {
|
|
||||||
if (asn_compare_oid(&p->index, &c->index) > 0) {
|
|
||||||
TAILQ_INSERT_BEFORE(p, c, link);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p == NULL)
|
|
||||||
TAILQ_INSERT_TAIL(&community_list, c, link);
|
|
||||||
return (c->value);
|
return (c->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ begemotSnmpdDebugSyslogPri = 7
|
|||||||
#
|
#
|
||||||
begemotSnmpdCommunityString.0.1 = $(read)
|
begemotSnmpdCommunityString.0.1 = $(read)
|
||||||
# begemotSnmpdCommunityString.0.2 = $(write)
|
# begemotSnmpdCommunityString.0.2 = $(write)
|
||||||
|
# begemotSnmpdCommunityString.0.3 = "otherPublic"
|
||||||
begemotSnmpdCommunityDisable = 1
|
begemotSnmpdCommunityDisable = 1
|
||||||
|
|
||||||
# open standard SNMP ports
|
# open standard SNMP ports
|
||||||
|
@ -334,6 +334,8 @@ extern struct systemg systemg;
|
|||||||
#define COMM_WRITE 2
|
#define COMM_WRITE 2
|
||||||
|
|
||||||
u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str);
|
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);
|
const char * comm_string(u_int);
|
||||||
|
|
||||||
/* community for current packet */
|
/* community for current packet */
|
||||||
|
@ -135,6 +135,7 @@ typedef RowStatus ENUM (
|
|||||||
(2 begemotSnmpdCommunityIndex UNSIGNED32)
|
(2 begemotSnmpdCommunityIndex UNSIGNED32)
|
||||||
(3 begemotSnmpdCommunityString OCTETSTRING GET SET)
|
(3 begemotSnmpdCommunityString OCTETSTRING GET SET)
|
||||||
(4 begemotSnmpdCommunityDescr OCTETSTRING GET)
|
(4 begemotSnmpdCommunityDescr OCTETSTRING GET)
|
||||||
|
(5 begemotSnmpdCommunityPermission INTEGER GET SET)
|
||||||
))
|
))
|
||||||
#
|
#
|
||||||
# Module table
|
# Module table
|
||||||
|
Loading…
Reference in New Issue
Block a user