-/* $OpenBSD: parse.y,v 1.63 2021/01/22 06:33:26 martijn Exp $ */
+/* $OpenBSD: parse.y,v 1.64 2021/06/20 19:55:48 martijn Exp $ */
/*
* Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
%}
%token INCLUDE
-%token LISTEN ON READ WRITE NOTIFY
+%token LISTEN ON READ WRITE NOTIFY SNMPV1 SNMPV2 SNMPV3
%token SYSTEM CONTACT DESCR LOCATION NAME OBJECTID SERVICES RTFILTER
%token READONLY READWRITE OCTETSTRING INTEGER COMMUNITY TRAP RECEIVER
-%token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR DISABLED
+%token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR
%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER PORT
%token <v.string> STRING
%token <v.number> NUMBER
}
free($3);
}
- | READWRITE DISABLED {
- conf->sc_readonly = 1;
- }
| TRAP COMMUNITY STRING {
if (strlcpy(conf->sc_trcommunity, $3,
sizeof(conf->sc_trcommunity)) >=
listenopt : READ { $$ = ADDRESS_FLAG_READ; }
| WRITE { $$ = ADDRESS_FLAG_WRITE; }
| NOTIFY { $$ = ADDRESS_FLAG_NOTIFY; }
+ | SNMPV1 { $$ = ADDRESS_FLAG_SNMPV1; }
+ | SNMPV2 { $$ = ADDRESS_FLAG_SNMPV2; }
+ | SNMPV3 { $$ = ADDRESS_FLAG_SNMPV3; }
;
listen_udp : STRING port listenopts {
char *port = $2;
if (port == NULL) {
- if ($3 == ADDRESS_FLAG_NOTIFY)
+ if (($3 & ADDRESS_FLAG_PERM) ==
+ ADDRESS_FLAG_NOTIFY)
port = SNMPTRAP_PORT;
else
port = SNMP_PORT;
char *port = $2;
if (port == NULL) {
- if ($3 == ADDRESS_FLAG_NOTIFY)
+ if (($3 & ADDRESS_FLAG_PERM) ==
+ ADDRESS_FLAG_NOTIFY)
port = SNMPTRAP_PORT;
else
port = SNMP_PORT;
{ "contact", CONTACT },
{ "default", DEFAULT },
{ "description", DESCR },
- { "disabled", DISABLED},
{ "enc", ENC },
{ "enckey", ENCKEY },
{ "filter-pf-addresses", PFADDRFILTER },
{ "receiver", RECEIVER },
{ "seclevel", SECLEVEL },
{ "services", SERVICES },
+ { "snmpv1", SNMPV1 },
+ { "snmpv2c", SNMPV2 },
+ { "snmpv3", SNMPV3 },
{ "source-address", SRCADDR },
{ "string", OCTETSTRING },
{ "system", SYSTEM },
struct sockaddr_storage ss;
struct sym *sym, *next;
struct address *h;
- int found;
+ struct trap_address *tr;
+ const struct usmuser *up;
+ const char *errstr;
+ int found;
if ((conf = calloc(1, sizeof(*conf))) == NULL) {
log_warn("%s", __func__);
conf->sc_flags = flags;
conf->sc_confpath = filename;
TAILQ_INIT(&conf->sc_addresses);
- strlcpy(conf->sc_rdcommunity, "public", SNMPD_MAXCOMMUNITYLEN);
- strlcpy(conf->sc_rwcommunity, "private", SNMPD_MAXCOMMUNITYLEN);
- strlcpy(conf->sc_trcommunity, "public", SNMPD_MAXCOMMUNITYLEN);
TAILQ_INIT(&conf->sc_trapreceivers);
+ conf->sc_min_seclevel = SNMP_MSGFLAG_AUTH | SNMP_MSGFLAG_PRIV;
if ((file = pushfile(filename, 0)) == NULL) {
free(conf);
if (listen_add(&ss, SOCK_DGRAM, 0) == -1)
fatal("calloc");
}
+
+ if ((up = usm_check_mincred(conf->sc_min_seclevel, &errstr)) != NULL)
+ fatalx("user '%s': %s", up->uu_name, errstr);
+
found = 0;
TAILQ_FOREACH(h, &conf->sc_addresses, entry) {
if (h->flags & ADDRESS_FLAG_NOTIFY)
return (NULL);
}
+ if (conf->sc_trcommunity[0] == '\0') {
+ TAILQ_FOREACH(tr, &conf->sc_trapreceivers, entry) {
+ if (tr->sa_community == NULL) {
+ log_warnx("trap receiver: missing community");
+ free(conf);
+ return (NULL);
+ }
+ }
+ }
+
/* Free macros and check which have not been used. */
TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
if ((conf->sc_flags & SNMPD_F_VERBOSE) && !sym->used)
h->port = ntohs(sin6->sin6_port);
}
h->type = type;
- if ((h->flags = flags) == 0) {
+ if (((h->flags = flags) & ADDRESS_FLAG_PERM) == 0) {
if (h->port == 162)
- h->flags = ADDRESS_FLAG_NOTIFY;
+ h->flags |= ADDRESS_FLAG_NOTIFY;
else
- h->flags = ADDRESS_FLAG_READ | ADDRESS_FLAG_WRITE;
+ h->flags |= ADDRESS_FLAG_READ | ADDRESS_FLAG_WRITE;
}
+ if ((h->flags & ADDRESS_FLAG_MPS) == 0)
+ h->flags |= ADDRESS_FLAG_SNMPV3;
TAILQ_INSERT_TAIL(&(conf->sc_addresses), h, entry);
return 0;
-.\" $OpenBSD: snmpd.conf.5,v 1.48 2021/06/14 12:28:58 sthen Exp $
+.\" $OpenBSD: snmpd.conf.5,v 1.49 2021/06/20 19:55:48 martijn Exp $
.\"
.\" Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
.\"
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 14 2021 $
+.Dd $Mdocdate: June 20 2021 $
.Dt SNMPD.CONF 5
.Os
.Sh NAME
reduced during bulk updates.
The default is
.Ic no .
-.It Ic listen on Oo Ic tcp | udp Oc Ar address Oo Ic port Ar port Oc Op Ic read | Ic write | Ic notify
+.It Ic listen on Oo Ic tcp | udp Oc Ar address Oo Ic port Ar port Oc Op Ar flags
Specify the local address
.Xr snmpd 8
should listen on for incoming SNMP messages.
+.Pp
The
-.Ic read
-flag specifies if the listen address accepts get, getnext and bulkget
+.Ar flags
+are as follows:
+.Bl -tag -width Ds
+.It Ic read
+Specifies if the listen address accepts get, getnext and bulkget
requests.
-The
-.Ic write
-flag specifies if the listen address accepts set requests
-and the
-.Ic notify
-flag specifies if the listen address accepts trapv1 and trapv2 requests.
+.It Ic write
+Specifies if the listen address accepts set requests.
+.It Ic notify
+Specifies if the listen address accepts trapv1 and trapv2 requests.
+.It Ic snmpv1
+Enables SNMPv1 subsystem on the listen address.
+.It Ic snmpv2c
+Enables SNMPv2c subsystem on the listen address.
+.It Ic snmpv3
+Enables SNMPv3 subsystem on the listen address.
+.El
+.Pp
Multiple
.Ic listen on
statements are supported.
.Ar port
is 161, unless
.Ic notify
-is the only listen flags
-which sets the
+is the only permission flag; which sets the
.Ar port
to 162.
-If no flags are specified it defaults to
+If no permission flags are specified it defaults to
.Dq Ic read Ic write ,
or
.Ic notify
when
.Ar port
is 162.
+If no subsystem flags are specified it defaults to
+.Ic snmpv3 .
+.Pp
Having
.Ic notify
set requires at least one
statement.
.It Ic read-only community Ar string
Specify the name of the read-only community.
-The default value is
-.Ar public .
-.It Ic read-write Pq Ic community Ar string Ic | disabled
-Specify the name of the read-write community, or disallow writes completely.
-The default value is
-.Ar private .
+There is no default value.
+.It Ic read-write Ic community Ar string
+Specify the name of the read-write community.
+There is no default value.
.It Ic seclevel Pq Ic none | auth | enc
Specify the lowest security level that
.Xr snmpd 8
-accepts:
+accepts on SNMPv3:
.Bl -tag -width "auth" -offset ident
.It Ic none
Both authentication and encryption of messages is optional.
-This is the default value.
.It Ic auth
Authentication of messages is mandatory.
.Xr snmpd 8
.It Ic enc
Messages must be encrypted and must have a valid digest for authentication.
Otherwise they will be discarded.
+This is the default value.
.El
-.Pp
-If the chosen value is different from
-.Ic none
-.Xr snmpd 8
-will accept only SNMPv3 requests since older versions neither support
-authentication nor encryption.
.It Ic system contact Ar string
Specify the name or description of the system contact, typically a
name or an email address.
.\"XXX describe the complicated services alg here
.It Ic trap community Ar string
Specify the name of the trap community.
-The default value is
-.Ar public .
+There is no default value.
.It Ic trap handle Ar oid Qq Ar command
Execute
.Ic command
.Sh EXAMPLES
The following example will tell
.Xr snmpd 8
-to listen on localhost, override the default system OID, set the
-magic services value and provides some custom OID values:
+to listen on localhost for SNMPv2c messages only with the public community,
+override the default system OID, set the magic services value and provides some
+custom OID values:
.Bd -literal -offset indent
-listen on 127.0.0.1
+listen on 127.0.0.1 snmpv2c
+read-only community public
system oid 1.3.6.1.4.1.30155.23.2
system services 74
-/* $OpenBSD: snmpd.h,v 1.95 2021/05/20 08:53:12 martijn Exp $ */
+/* $OpenBSD: snmpd.h,v 1.96 2021/06/20 19:55:48 martijn Exp $ */
/*
* Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
};
TAILQ_HEAD(addresslist, address);
-#define ADDRESS_FLAG_READ 0x1
-#define ADDRESS_FLAG_WRITE 0x2
-#define ADDRESS_FLAG_NOTIFY 0x4
+#define ADDRESS_FLAG_READ 0x01
+#define ADDRESS_FLAG_WRITE 0x02
+#define ADDRESS_FLAG_NOTIFY 0x04
+#define ADDRESS_FLAG_PERM \
+ (ADDRESS_FLAG_READ | ADDRESS_FLAG_WRITE | ADDRESS_FLAG_NOTIFY)
+#define ADDRESS_FLAG_SNMPV1 0x10
+#define ADDRESS_FLAG_SNMPV2 0x20
+#define ADDRESS_FLAG_SNMPV3 0x40
+#define ADDRESS_FLAG_MPS \
+ (ADDRESS_FLAG_SNMPV1 | ADDRESS_FLAG_SNMPV2 | ADDRESS_FLAG_SNMPV3)
struct trap_address {
struct sockaddr_storage ss;
int sc_pfaddrfilter;
int sc_min_seclevel;
- int sc_readonly;
int sc_traphandler;
struct privsep sc_ps;
struct ber_element *usm_encrypt(struct snmp_message *, struct ber_element *);
void usm_finalize_digest(struct snmp_message *, char *, ssize_t);
void usm_make_report(struct snmp_message *);
+const struct usmuser *usm_check_mincred(int, const char **);
/* proc.c */
enum privsep_procid
-/* $OpenBSD: snmpe.c,v 1.71 2021/05/20 08:53:12 martijn Exp $ */
+/* $OpenBSD: snmpe.c,v 1.72 2021/06/20 19:55:48 martijn Exp $ */
/*
* Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
msg->sm_version = ver;
switch (msg->sm_version) {
case SNMP_V1:
+ if (!(msg->sm_aflags & ADDRESS_FLAG_SNMPV1)) {
+ msg->sm_errstr = "SNMPv1 disabled";
+ goto badversion;
+ }
case SNMP_V2:
- if (env->sc_min_seclevel != 0)
+ if (msg->sm_version == SNMP_V2 &&
+ !(msg->sm_aflags & ADDRESS_FLAG_SNMPV2)) {
+ msg->sm_errstr = "SNMPv2c disabled";
goto badversion;
+ }
if (ober_scanf_elements(a, "seS$", &comn, &msg->sm_pdu) != 0)
goto parsefail;
if (strlcpy(msg->sm_community, comn,
- sizeof(msg->sm_community)) >= sizeof(msg->sm_community)) {
+ sizeof(msg->sm_community)) >= sizeof(msg->sm_community) ||
+ msg->sm_community[0] == '\0') {
stats->snmp_inbadcommunitynames++;
- msg->sm_errstr = "community name too long";
+ msg->sm_errstr = "invalid community name";
goto fail;
}
break;
case SNMP_V3:
+ if (!(msg->sm_aflags & ADDRESS_FLAG_SNMPV3)) {
+ msg->sm_errstr = "SNMPv3 disabled";
+ goto badversion;
+ }
if (ober_scanf_elements(a, "{iisi$}e",
&msg->sm_msgid, &msg->sm_max_msg_size, &flagstr,
&msg->sm_secmodel, &a) != 0)
msg->sm_ctxname[len] = '\0';
break;
default:
- badversion:
+ msg->sm_errstr = "unsupported snmp version";
+badversion:
stats->snmp_inbadversions++;
- msg->sm_errstr = "bad snmp version";
goto fail;
}
}
if (msg->sm_version != SNMP_V3 &&
strcmp(env->sc_rdcommunity, msg->sm_community) != 0 &&
- (env->sc_readonly ||
- strcmp(env->sc_rwcommunity, msg->sm_community) != 0)) {
+ strcmp(env->sc_rwcommunity, msg->sm_community) != 0) {
stats->snmp_inbadcommunitynames++;
msg->sm_errstr = "wrong read community";
goto fail;
goto fail;
}
if (msg->sm_version != SNMP_V3 &&
- (env->sc_readonly ||
- strcmp(env->sc_rwcommunity, msg->sm_community) != 0)) {
+ strcmp(env->sc_rwcommunity, msg->sm_community) != 0) {
if (strcmp(env->sc_rdcommunity, msg->sm_community) != 0)
stats->snmp_inbadcommunitynames++;
else
stats->snmp_intotalreqvars++;
break;
case SNMP_C_SETREQ:
- if (snmpd_env->sc_readonly == 0) {
- /*
- * XXX A set varbind should only be committed if
- * all variables are staged
- */
- if (mps_setreq(msg, value, &o) == 0) {
- /* XXX Adjust after fixing staging */
- stats->snmp_intotalsetvars++;
- break;
- }
+ /*
+ * XXX A set varbind should only be committed if
+ * all variables are staged
+ */
+ if (mps_setreq(msg, value, &o) == 0) {
+ stats->snmp_intotalsetvars++;
+ break;
}
msg->sm_error = SNMP_ERROR_READONLY;
goto varfail;
-/* $OpenBSD: usm.c,v 1.19 2021/05/20 08:53:12 martijn Exp $ */
+/* $OpenBSD: usm.c,v 1.20 2021/06/20 19:55:48 martijn Exp $ */
/*
* Copyright (c) 2012 GeNUA mbH
return up;
}
+const struct usmuser *
+usm_check_mincred(int minlevel, const char **errstr)
+{
+ struct usmuser *up;
+
+ if (minlevel == 0)
+ return NULL;
+
+ SLIST_FOREACH(up, &usmuserlist, uu_next) {
+ if (minlevel & SNMP_MSGFLAG_PRIV && up->uu_privkey == NULL) {
+ *errstr = "missing enckey";
+ return up;
+ }
+ if (minlevel & SNMP_MSGFLAG_AUTH && up->uu_authkey == NULL) {
+ *errstr = "missing authkey";
+ return up;
+ }
+ }
+ return NULL;
+}
+
struct usmuser *
usm_finduser(char *name)
{