Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Jan 2018 08:48:14 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r328160 - head/contrib/bsnmp/snmpd
Message-ID:  <201801190848.w0J8mEKg091042@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Fri Jan 19 08:48:14 2018
New Revision: 328160
URL: https://svnweb.freebsd.org/changeset/base/328160

Log:
  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

Modified:
  head/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt
  head/contrib/bsnmp/snmpd/action.c
  head/contrib/bsnmp/snmpd/main.c
  head/contrib/bsnmp/snmpd/snmpd.config
  head/contrib/bsnmp/snmpd/snmpmod.h
  head/contrib/bsnmp/snmpd/tree.def

Modified: head/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt
==============================================================================
--- head/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt	Fri Jan 19 04:34:06 2018	(r328159)
+++ head/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt	Fri Jan 19 08:48:14 2018	(r328160)
@@ -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
@@ -309,6 +310,14 @@ begemotSnmpdCommunityDescr OBJECT-TYPE
     DESCRIPTION
 	    "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

Modified: head/contrib/bsnmp/snmpd/action.c
==============================================================================
--- head/contrib/bsnmp/snmpd/action.c	Fri Jan 19 04:34:06 2018	(r328159)
+++ head/contrib/bsnmp/snmpd/action.c	Fri Jan 19 08:48:14 2018	(r328160)
@@ -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 index;
 	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_val
 		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);
-		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:
 		if (which == LEAF_begemotSnmpdCommunityString) {
@@ -786,6 +822,8 @@ op_community(struct snmp_context *ctx, struct snmp_val
 				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_val
 				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_val
 
 	  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();
 }

Modified: head/contrib/bsnmp/snmpd/main.c
==============================================================================
--- head/contrib/bsnmp/snmpd/main.c	Fri Jan 19 04:34:06 2018	(r328159)
+++ head/contrib/bsnmp/snmpd/main.c	Fri Jan 19 08:48:14 2018	(r328160)
@@ -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 *er
 /*
  * 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 *index,
+    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 = 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, "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 lmod
 	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 = *index;
 	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 lmod
 	}
 	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 index, *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 = &index;
+		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);
 }
 

Modified: head/contrib/bsnmp/snmpd/snmpd.config
==============================================================================
--- head/contrib/bsnmp/snmpd/snmpd.config	Fri Jan 19 04:34:06 2018	(r328159)
+++ head/contrib/bsnmp/snmpd/snmpd.config	Fri Jan 19 08:48:14 2018	(r328160)
@@ -68,6 +68,7 @@ begemotSnmpdDebugSyslogPri	= 7
 #
 begemotSnmpdCommunityString.0.1	= $(read)
 # begemotSnmpdCommunityString.0.2	= $(write)
+# begemotSnmpdCommunityString.0.3	= "otherPublic"
 begemotSnmpdCommunityDisable	= 1
 
 # open standard SNMP ports

Modified: head/contrib/bsnmp/snmpd/snmpmod.h
==============================================================================
--- head/contrib/bsnmp/snmpd/snmpmod.h	Fri Jan 19 04:34:06 2018	(r328159)
+++ head/contrib/bsnmp/snmpd/snmpmod.h	Fri Jan 19 08:48:14 2018	(r328160)
@@ -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 */

Modified: head/contrib/bsnmp/snmpd/tree.def
==============================================================================
--- head/contrib/bsnmp/snmpd/tree.def	Fri Jan 19 04:34:06 2018	(r328159)
+++ head/contrib/bsnmp/snmpd/tree.def	Fri Jan 19 08:48:14 2018	(r328160)
@@ -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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801190848.w0J8mEKg091042>