From 614c3698b09c8fb9a934c8ae12544cccda8677fa Mon Sep 17 00:00:00 2001 From: martijn Date: Thu, 30 Jun 2022 11:28:36 +0000 Subject: [PATCH] Introduce a blocklist backend and keyword. This allows the admin to specify a full region of the OID tree to be blocked and simply returns NOSUCHOBJECT/ENDOFMIBVIEW. This deprecates filter-pf-addresses in favour of: blocklist pfTblAddrTable OK tb@ --- usr.sbin/snmpd/Makefile | 3 +- usr.sbin/snmpd/application.c | 4 +- usr.sbin/snmpd/application.h | 6 +- usr.sbin/snmpd/application_blocklist.c | 141 +++++++++++++++++++++++++ usr.sbin/snmpd/mib.c | 8 +- usr.sbin/snmpd/parse.y | 38 ++++++- usr.sbin/snmpd/snmpd.conf.5 | 20 ++-- usr.sbin/snmpd/snmpd.h | 5 +- 8 files changed, 199 insertions(+), 26 deletions(-) create mode 100644 usr.sbin/snmpd/application_blocklist.c diff --git a/usr.sbin/snmpd/Makefile b/usr.sbin/snmpd/Makefile index 9fbe1aecdc0..f49829c0221 100644 --- a/usr.sbin/snmpd/Makefile +++ b/usr.sbin/snmpd/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.18 2022/01/19 11:00:56 martijn Exp $ +# $OpenBSD: Makefile,v 1.19 2022/06/30 11:28:36 martijn Exp $ PROG= snmpd MAN= snmpd.8 snmpd.conf.5 SRCS= parse.y log.c snmpe.c application.c application_legacy.c \ + application_blocklist.c \ mps.c trap.c mib.c smi.c kroute.c snmpd.c timer.c \ pf.c proc.c usm.c traphandler.c util.c diff --git a/usr.sbin/snmpd/application.c b/usr.sbin/snmpd/application.c index 4727beed9ff..0fb8a456255 100644 --- a/usr.sbin/snmpd/application.c +++ b/usr.sbin/snmpd/application.c @@ -1,4 +1,4 @@ -/* $OpenBSD: application.c,v 1.5 2022/06/27 10:31:17 martijn Exp $ */ +/* $OpenBSD: application.c,v 1.6 2022/06/30 11:28:36 martijn Exp $ */ /* * Copyright (c) 2021 Martijn van Duren @@ -148,6 +148,7 @@ RB_PROTOTYPE_STATIC(appl_requests, appl_request_downstream, ard_entry, void appl_init(void) { + appl_blocklist_init(); appl_legacy_init(); } @@ -156,6 +157,7 @@ appl_shutdown(void) { struct appl_context *ctx, *tctx; + appl_blocklist_shutdown(); appl_legacy_shutdown(); TAILQ_FOREACH_SAFE(ctx, &contexts, ac_entries, tctx) { diff --git a/usr.sbin/snmpd/application.h b/usr.sbin/snmpd/application.h index e65c6e74013..fd5b8146335 100644 --- a/usr.sbin/snmpd/application.h +++ b/usr.sbin/snmpd/application.h @@ -1,4 +1,4 @@ -/* $OpenBSD: application.h,v 1.1 2022/01/19 10:59:35 martijn Exp $ */ +/* $OpenBSD: application.h,v 1.2 2022/06/30 11:28:36 martijn Exp $ */ /* * Copyright (c) 2021 Martijn van Duren @@ -133,3 +133,7 @@ struct ber_element *appl_exception(enum appl_exception); /* application_legacy.c */ void appl_legacy_init(void); void appl_legacy_shutdown(void); + +/* application_blocklist.c */ +void appl_blocklist_init(void); +void appl_blocklist_shutdown(void); diff --git a/usr.sbin/snmpd/application_blocklist.c b/usr.sbin/snmpd/application_blocklist.c new file mode 100644 index 00000000000..e3bb1b94c07 --- /dev/null +++ b/usr.sbin/snmpd/application_blocklist.c @@ -0,0 +1,141 @@ +/* $OpenBSD: application_blocklist.c,v 1.1 2022/06/30 11:28:36 martijn Exp $ */ + +/* + * Copyright (c) 2022 Martijn van Duren + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "application.h" +#include "snmpd.h" + +struct appl_varbind *appl_blocklist_response(size_t); +void appl_blocklist_get(struct appl_backend *, int32_t, int32_t, const char *, + struct appl_varbind *); +void appl_blocklist_getnext(struct appl_backend *, int32_t, int32_t, + const char *, struct appl_varbind *); + +struct appl_backend_functions appl_blocklist_functions = { + .ab_get = appl_blocklist_get, + .ab_getnext = appl_blocklist_getnext, + .ab_getbulk = NULL, +}; + +struct appl_backend appl_blocklist = { + .ab_name = "blocklist", + .ab_cookie = NULL, + .ab_retries = 0, + .ab_fn = &appl_blocklist_functions +}; + +static struct appl_varbind *response = NULL; +static size_t responsesz = 0; + +struct appl_varbind * +appl_blocklist_response(size_t nvarbind) +{ + struct appl_varbind *tmp; + size_t i; + + if (responsesz < nvarbind) { + if ((tmp = recallocarray(response, responsesz, nvarbind, + sizeof(*response))) == NULL) { + log_warn(NULL); + return NULL; + } + responsesz = nvarbind; + response = tmp; + } + for (i = 0; i < nvarbind; i++) + response[i].av_next = i + 1 == nvarbind ? + NULL : &(response[i + 1]); + return response; +} + +void +appl_blocklist_init(void) +{ + extern struct snmpd *snmpd_env; + size_t i; + + for (i = 0; i < snmpd_env->sc_nblocklist; i++) + appl_register(NULL, 150, 1, &(snmpd_env->sc_blocklist[i]), + 0, 1, 0, 0, &appl_blocklist); +} + +void +appl_blocklist_shutdown(void) +{ + appl_close(&appl_blocklist); + free(response); +} + +void +appl_blocklist_get(struct appl_backend *backend, __unused int32_t transactionid, + int32_t requestid, __unused const char *ctx, struct appl_varbind *vblist) +{ + struct appl_varbind *vb, *rvb, *rvblist; + size_t i; + + for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next) + i++; + if ((rvblist = appl_blocklist_response(i)) == NULL) + goto fail; + rvb = rvblist; + for (vb = vblist; vb != NULL; vb = vb->av_next, rvb = rvb->av_next) { + rvb->av_oid = vb->av_oid; + rvb->av_value = appl_exception(APPL_EXC_NOSUCHOBJECT); + if (rvb->av_value == NULL) + goto fail; + } + + appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, rvblist); + return; + fail: + for (rvb = rvblist; rvb != NULL && rvb->av_value != NULL; + rvb = rvb->av_next) + ober_free_elements(rvb->av_value); + appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vb); +} + +void +appl_blocklist_getnext(struct appl_backend *backend, + __unused int32_t transactionid, int32_t requestid, __unused const char *ctx, + struct appl_varbind *vblist) +{ + struct appl_varbind *vb, *rvb, *rvblist; + size_t i; + + for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next) + i++; + if ((rvblist = appl_blocklist_response(i)) == NULL) + goto fail; + rvb = rvblist; + for (vb = vblist; vb != NULL; vb = vb->av_next, rvb = rvb->av_next) { + rvb->av_oid = vb->av_oid; + rvb->av_value = appl_exception(APPL_EXC_ENDOFMIBVIEW); + if (rvb->av_value == NULL) + goto fail; + } + + appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, rvblist); + return; + fail: + for (rvb = rvblist; rvb != NULL && rvb->av_value != NULL; + rvb = rvb->av_next) + ober_free_elements(rvb->av_value); + appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vb); +} diff --git a/usr.sbin/snmpd/mib.c b/usr.sbin/snmpd/mib.c index a1570646a7e..b034ab8eac6 100644 --- a/usr.sbin/snmpd/mib.c +++ b/usr.sbin/snmpd/mib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mib.c,v 1.102 2021/09/01 15:54:40 deraadt Exp $ */ +/* $OpenBSD: mib.c,v 1.103 2022/06/30 11:28:36 martijn Exp $ */ /* * Copyright (c) 2012 Joel Knight @@ -2223,9 +2223,6 @@ mib_pftableaddrs(struct oid *oid, struct ber_oid *o, struct ber_element **elm) struct pfr_astats as; int tblidx; - if (snmpd_env->sc_pfaddrfilter) - return (-1); - tblidx = o->bo_id[OIDIDX_pfTblAddr + 1]; mps_decodeinaddr(o, &as.pfras_a.pfra_ip4addr, OIDIDX_pfTblAddr + 2); as.pfras_a.pfra_net = o->bo_id[OIDIDX_pfTblAddr + 6]; @@ -2314,9 +2311,6 @@ mib_pftableaddrstable(struct oid *oid, struct ber_oid *o, struct ber_oid *no) struct oid a, b; u_int32_t id, tblidx; - if (snmpd_env->sc_pfaddrfilter) - return (NULL); - bcopy(&oid->o_id, no, sizeof(*no)); id = oid->o_oidlen - 1; diff --git a/usr.sbin/snmpd/parse.y b/usr.sbin/snmpd/parse.y index b390ff65606..a64df11805c 100644 --- a/usr.sbin/snmpd/parse.y +++ b/usr.sbin/snmpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.74 2022/06/28 09:11:33 martijn Exp $ */ +/* $OpenBSD: parse.y,v 1.75 2022/06/30 11:28:36 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter @@ -130,7 +130,7 @@ typedef struct { %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 -%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER PORT +%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER BLOCKLIST PORT %token STRING %token NUMBER %type usmuser community optcommunity @@ -255,6 +255,20 @@ main : LISTEN ON listen_udptcp } conf->sc_traphandler = 1; } + | BLOCKLIST oid { + struct ber_oid *blocklist; + + blocklist = recallocarray(conf->sc_blocklist, + conf->sc_nblocklist, conf->sc_nblocklist + 1, + sizeof(*blocklist)); + if (blocklist == NULL) { + yyerror("malloc"); + YYERROR; + } + conf->sc_blocklist = blocklist; + blocklist[conf->sc_nblocklist++] = *$2; + free($2); + } | RTFILTER yesno { if ($2 == 1) conf->sc_rtfilter = ROUTE_FILTER(RTM_NEWADDR) | @@ -264,8 +278,25 @@ main : LISTEN ON listen_udptcp else conf->sc_rtfilter = 0; } + /* XXX Remove after 7.4 */ | PFADDRFILTER yesno { - conf->sc_pfaddrfilter = $2; + struct ber_oid *blocklist; + + log_warnx("filter-pf-addresses is deprecated. " + "Please use blocklist instead."); + if ($2) { + blocklist = recallocarray(conf->sc_blocklist, + conf->sc_nblocklist, + conf->sc_nblocklist + 1, + sizeof(*blocklist)); + if (blocklist == NULL) { + yyerror("malloc"); + YYERROR; + } + conf->sc_blocklist = blocklist; + smi_string2oid("pfTblAddrTable", + &(blocklist[conf->sc_nblocklist++])); + } } | seclevel { conf->sc_min_seclevel = $1; @@ -995,6 +1026,7 @@ lookup(char *s) { "agentid", AGENTID }, { "auth", AUTH }, { "authkey", AUTHKEY }, + { "blocklist", BLOCKLIST }, { "community", COMMUNITY }, { "contact", CONTACT }, { "default", DEFAULT }, diff --git a/usr.sbin/snmpd/snmpd.conf.5 b/usr.sbin/snmpd/snmpd.conf.5 index fa8483899d7..a415f0391d3 100644 --- a/usr.sbin/snmpd/snmpd.conf.5 +++ b/usr.sbin/snmpd/snmpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: snmpd.conf.5,v 1.59 2022/03/31 17:27:31 naddy Exp $ +.\" $OpenBSD: snmpd.conf.5,v 1.60 2022/06/30 11:28:36 martijn Exp $ .\" .\" Copyright (c) 2007, 2008, 2012 Reyk Floeter .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 31 2022 $ +.Dd $Mdocdate: June 30 2022 $ .Dt SNMPD.CONF 5 .Os .Sh NAME @@ -78,15 +78,13 @@ listen on $ext_addr .Sh GLOBAL CONFIGURATION The following options can be set globally: .Bl -tag -width Ds -.It Ic filter-pf-addresses Pq Ic yes | no -If set to -.Ic yes , -.Xr snmpd 8 -will filter out the OPENBSD-PF-MIB::pfTblAddrTable tree. -Addresses stored in PF tables will not be available, but CPU use will be -reduced during bulk walks. -The default is -.Ic no . +.It Ic blocklist Ar oid +Remove the +.Ar oid +subtree from view. +Multiple +.Ic blocklist +statements are supported. .It Ic filter-routes Pq Ic yes | no If set to .Ic yes , diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index e86a8d376b1..fa4d9aef015 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.102 2022/01/19 10:25:04 martijn Exp $ */ +/* $OpenBSD: snmpd.h,v 1.103 2022/06/30 11:28:36 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter @@ -591,8 +591,9 @@ struct snmpd { int sc_ncpu; int64_t *sc_cpustates; + struct ber_oid *sc_blocklist; + size_t sc_nblocklist; int sc_rtfilter; - int sc_pfaddrfilter; int sc_min_seclevel; int sc_traphandler; -- 2.20.1