diff options
149 files changed, 4534 insertions, 625 deletions
@@ -10,6 +10,13 @@ newline. Entries should be separated by a newline. Changes to this file should not be MFCed. +5000d023a446, 03da141d59ae: + Add a "-f" option to "kadmin -l dump" with can be used to + dump the Heimdal KDC database in a format that can be loaded + into the MIT KDC. + See https://wiki.freebsd.org/Kerberos/Heimdal2MIT_KDC_Migration + for how to use "-f" to transfer/convert the KDC database. + 9cab9fde5eda: virtual_oss is imported to base. The audio/virtual_oss port will stop being built from FreeBSD 15.0 onwards. diff --git a/contrib/blocklist/Makefile b/contrib/blocklist/Makefile index da4411d0ca75..899746d01431 100644 --- a/contrib/blocklist/Makefile +++ b/contrib/blocklist/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2015/01/22 17:49:41 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:52 christos Exp $ SUBDIR = lib .WAIT include bin etc libexec diff --git a/contrib/blocklist/Makefile.inc b/contrib/blocklist/Makefile.inc index 85c82783cd35..b22d4a801240 100644 --- a/contrib/blocklist/Makefile.inc +++ b/contrib/blocklist/Makefile.inc @@ -1,10 +1,11 @@ -# $NetBSD: Makefile.inc,v 1.3 2015/01/23 03:57:22 christos Exp $ +# $NetBSD: Makefile.inc,v 1.3 2025/02/11 17:48:30 christos Exp $ WARNS=6 .if !defined(LIB) -LDADD+= -lblacklist -DPADD+= ${LIBBLACKLIST} +LDADD+= -lblocklist +DPADD+= ${LIBBLOCKLIST} .endif CPPFLAGS+= -I${.CURDIR}/../include CPPFLAGS+=-DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_UTIL_H -DHAVE_DB_H +CPPFLAGS+=-DHAVE_SYS_CDEFS_H diff --git a/contrib/blocklist/README b/contrib/blocklist/README index 7da3317a77fe..4b34138e01ec 100644 --- a/contrib/blocklist/README +++ b/contrib/blocklist/README @@ -1,21 +1,21 @@ -# $NetBSD: README,v 1.8 2017/04/13 17:59:34 christos Exp $ +# $NetBSD: README,v 1.3 2024/02/09 00:53:30 wiz Exp $ This package contains library that can be used by network daemons to communicate with a packet filter via a daemon to enforce opening and closing ports dynamically based on policy. -The interface to the packet filter is in libexec/blacklistd-helper +The interface to the packet filter is in libexec/blocklistd-helper (this is currently designed for npf) and the configuration file -(inspired from inetd.conf) is in etc/blacklistd.conf. +(inspired from inetd.conf) is in etc/blocklistd.conf. -On NetBSD you can find an example npf.conf and blacklistd.conf in -/usr/share/examples/blacklistd; you need to adjust the interface +On NetBSD you can find an example npf.conf and blocklistd.conf in +/usr/share/examples/blocklistd; you need to adjust the interface in npf.conf and copy both files to /etc; then you just enable -blacklistd=YES in /etc/rc.conf, start it up, and you are all set. +blocklistd=YES in /etc/rc.conf, start it up, and you are all set. -There is also a startup file in etc/rc.d/blacklistd +There is also a startup file in etc/rc.d/blocklistd -Patches to various daemons to add blacklisting capabilitiers are in the +Patches to various daemons to add blocklisting capabilities are in the "diff" directory: - OpenSSH: diff/ssh.diff [tcp socket example] - Bind: diff/named.diff [both tcp and udp] @@ -23,21 +23,21 @@ Patches to various daemons to add blacklisting capabilitiers are in the These patches have been applied to NetBSD-current. -The network daemon (for example sshd) communicates to blacklistd, via -a unix socket like syslog. The library calls are simple and everything +The network daemon (for example sshd) communicates to blocklistd, via +a Unix socket like syslog. The library calls are simple and everything is handled by the library. In the simplest form the only thing the daemon needs to do is to call: - blacklist(action, acceptedfd, message); + blocklist(action, acceptedfd, message); Where: - action = 0 -> successful login clear blacklist state + action = 0 -> successful login clear blocklist state 1 -> failed login, add to the failed count acceptedfd -> the file descriptor where the server is connected to the remote client. It is used to determine the listening socket, and the remote address. This allows any program to - contact the blacklist daemon, since the verification + contact the blocklist daemon, since the verification if the program has access to the listening socket is done by virtue that the port number is retrieved from the kernel. @@ -46,13 +46,13 @@ Where: Unfortunately there is no way to get information about the "peer" from a udp socket, because there is no connection and that information is kept with the server. In that case the daemon can provide the -peer information to blacklistd via: +peer information to blocklistd via: - blacklist_sa(action, acceptedfd, sockaddr, sockaddr_len, message); + blocklist_sa(action, acceptedfd, sockaddr, sockaddr_len, message); The configuration file contains entries of the form: -# Blacklist rule +# Blocklist rule # host/Port type protocol owner name nfail disable 192.168.1.1:ssh stream tcp * -int 10 1m 8.8.8.8:ssh stream tcp * -ext 6 60m @@ -60,18 +60,18 @@ ssh stream tcp6 * * 6 60m http stream tcp * * 6 60m Here note that owner is * because the connection is done from the -child ssh socket which runs with user privs. We treat ipv4 connections +child ssh socket which runs with user privs. We treat IPv4 connections differently by maintaining two different rules one for the external interface and one from the internal We also register for both tcp and tcp6 since those are different listening sockets and addresses; -we don't bother with ipv6 and separate rules. We use nfail = 6, +we don't bother with IPv6 and separate rules. We use nfail = 6, because ssh allows 3 password attempts per connection, and this will let us have 2 connections before blocking. Finally we block for an hour; we could block forever too by specifying * in the duration column. -blacklistd and the library use syslog(3) to report errors. The -blacklist filter state is persisted automatically in /var/db/blacklistd.db +blocklistd and the library use syslog(3) to report errors. The +blocklist filter state is persisted automatically in /var/db/blocklistd.db so that if the daemon is restarted, it remembers what connections is currently handling. To start from a fresh state (if you restart npf too for example), you can use -f. To watch the daemon at work, @@ -80,27 +80,27 @@ you can use -d. The current control file is designed for npf, and it uses the dynamic rule feature. You need to create a dynamic rule in your /etc/npf.conf on the group referring to the interface you want to block -called blacklistd as follows: +called blocklistd as follows: ext_if=bge0 int_if=sk0 group "external" on $ext_if { ... - ruleset "blacklistd-ext" - ruleset "blacklistd" + ruleset "blocklistd-ext" + ruleset "blocklistd" ... } group "internal" on $int_if { ... - ruleset "blacklistd-int" + ruleset "blocklistd-int" ... } -You can use 'blacklistctl dump -a' to list all the current entries +You can use 'blocklistctl dump -a' to list all the current entries in the database; the ones that have nfail <c>/<t> where <c>urrent ->= <t>otal, should have an id assosiated with them; this means that +>= <t>otal, should have an id associated with them; this means that there is a packet filter rule added for that entry. For npf, you can examine the packet filter dynamic rule entries using 'npfctl rule <rulename> list'. The number of current entries can exceed diff --git a/contrib/blocklist/TODO b/contrib/blocklist/TODO index 9925020d54bb..d67111bd5139 100644 --- a/contrib/blocklist/TODO +++ b/contrib/blocklist/TODO @@ -1,4 +1,4 @@ -# $NetBSD: TODO,v 1.7 2015/01/23 21:34:01 christos Exp $ +# $NetBSD: TODO,v 1.3 2025/02/05 20:22:26 christos Exp $ - don't poll periodically, find the next timeout - use the socket also for commands? Or separate socket? @@ -17,5 +17,48 @@ -n block unblock -- do we need an api in blacklistctl to perform maintenance -- fix the blacklistctl output to be more user friendly +- do we need an api in blocklistctl to perform maintenance +- fix the blocklistctl output to be more user friendly + +- figure out some way to do distributed operation securely (perhaps with + a helper daemon that authenticates local sockets and then communicates + local DB changes to the central server over a secure channel -- + perhaps blocklistd-helper can have a back-end that can send updates to + a central server) + +- add "blocklistd -l" to enable filter logging on all rules by default + +- add some new options in the config file + + "/all" - block both TCP and UDP (on the proto field?) + + "/log" - enable filter logging (if not the default) (on the name field?) + "/nolog"- disable filter logging (if not the default) (on the name field?) + + The latter two probably require a new parameter for blocklistd-helper. + +- "blocklistd -f" should (also?) be a blocklistctl function!?!?! + +- if blocklistd was started with '-r' then a SIGHUP should also do a + "control flush $rulename" and then re-add all the filter rules? + +- should/could /etc/rc.conf.d/ipfilter be created with the following? + + reload_postcmd=blocklistd_reload + start_postcmd=blocklistd_start + stop_precmd=blocklistd_stop + blocklistd_reload () + { + /etc/rc.d/blocklistd reload # IFF SIGHUP does flush/re-add + # /etc/rc.d/blocklistd restart + } + blocklistd_stop () + { + /etc/rc.d/blocklistd stop + } + blocklistd_start () + { + /etc/rc.d/blocklistd start + } + + or is there a better way? diff --git a/contrib/blocklist/bin/Makefile b/contrib/blocklist/bin/Makefile index 280c72fd3af1..1856e2524f3c 100644 --- a/contrib/blocklist/bin/Makefile +++ b/contrib/blocklist/bin/Makefile @@ -1,12 +1,12 @@ -# $NetBSD: Makefile,v 1.11 2015/01/27 19:40:36 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:52 christos Exp $ BINDIR=/sbin -PROGS=blacklistd blacklistctl -MAN.blacklistd=blacklistd.8 blacklistd.conf.5 -MAN.blacklistctl=blacklistctl.8 -SRCS.blacklistd = blacklistd.c conf.c run.c state.c support.c internal.c -SRCS.blacklistctl = blacklistctl.c conf.c state.c support.c internal.c +PROGS=blocklistd blocklistctl +MAN.blocklistd=blocklistd.8 blocklistd.conf.5 +MAN.blocklistctl=blocklistctl.8 +SRCS.blocklistd = blocklistd.c conf.c run.c state.c support.c internal.c +SRCS.blocklistctl = blocklistctl.c conf.c state.c support.c internal.c DBG=-g LDADD+=-lutil diff --git a/contrib/blocklist/bin/blacklistctl.8 b/contrib/blocklist/bin/blacklistctl.8 index 7c6521117745..4d557c0c979d 100644 --- a/contrib/blocklist/bin/blacklistctl.8 +++ b/contrib/blocklist/bin/blacklistctl.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: blacklistctl.8,v 1.9 2016/06/08 12:48:37 wiz Exp $ +.\" $NetBSD: blocklistctl.8,v 1.4 2025/02/07 01:35:38 kre Exp $ .\" .\" Copyright (c) 2015 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,27 +27,43 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 7, 2016 +.Dd January 27, 2025 .Dt BLACKLISTCTL 8 .Os .Sh NAME .Nm blacklistctl -.Nd display and change the state of blacklistd +.Nd display and change the state of the blacklistd database .Sh SYNOPSIS .Nm .Cm dump .Op Fl abdnrw +.Op Fl D Ar dbname .Sh DESCRIPTION .Nm -is a program used to display the state of +is a program used to display and change the state of the .Xr blacklistd 8 +database. +The following sub-commands are supported: +.Ss dump .Pp -The following options are available: +The following options are available for the +.Cm dump +sub-command: .Bl -tag -width indent .It Fl a -Show all database entries, by default it shows only the embryonic ones. +Show all database entries, by default it shows only the active ones. +Inactive entries will be shown with a last-access (or, with +.Fl r , +the remaining) time of +.Ql never . .It Fl b Show only the blocked entries. +.It Fl D Ar dbname +Specify the location of the +.Ic blacklistd +database file to use. +The default is +.Pa /var/db/blocklistd.db . .It Fl d Increase debugging level. .It Fl n @@ -59,9 +75,43 @@ Normally the width of addresses is good for IPv4, the .Fl w flag, makes the display wide enough for IPv6 addresses. .El +.Pp +The output of the +.Cm dump +sub-command consists of a header (unless +.Fl n +was given) and one line for each record in the database, where each line +has the following columns: +.Bl -tag -width indent +.It Ql address/ma:port +The remote address, mask, and local port number of the client connection +associated with the database entry. +.It Ql id +column will show the identifier for the packet filter rule associated +with the database entry, though this may only be the word +.Ql OK +for packet filters which do not creat a unique identifier for each rule. +.It Ql nfail +The number of +.Em failures +reported for the client on the noted port, as well as the number of +failures allowed before blocking (or, with +.Fl a , +an asterisk +.Aq * ) +.It So last access Sc | So remaining time Sc +The last time a the client was reported as attempting access, or, with +.Fl r , +the time remaining before the rule blocking the client will be removed. +.El .Sh SEE ALSO .Xr blacklistd 8 .Sh NOTES +The +.Nm +program has been renamed to +.Xr blocklistctl 8 . +.Pp Sometimes the reported number of failed attempts can exceed the number of attempts that .Xr blacklistd 8 diff --git a/contrib/blocklist/bin/blacklistctl.c b/contrib/blocklist/bin/blacklistctl.c index 89b72921caf5..6298a08b10b4 100644 --- a/contrib/blocklist/bin/blacklistctl.c +++ b/contrib/blocklist/bin/blacklistctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $ */ +/* $NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $"); +#endif +__RCSID("$NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); #include <stdio.h> #include <time.h> @@ -53,7 +55,7 @@ __RCSID("$NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $"); #include "conf.h" #include "state.h" -#include "internal.h" +#include "old_internal.h" #include "support.h" static __dead void @@ -63,7 +65,8 @@ usage(int c) warnx("Missing/unknown command"); else if (c != '?') warnx("Unknown option `%c'", (char)c); - fprintf(stderr, "Usage: %s dump [-abdnrw]\n", getprogname()); + fprintf(stderr, + "Usage: %s dump [-abdnrw] [-D dbname]\n", getprogname()); exit(EXIT_FAILURE); } diff --git a/contrib/blocklist/bin/blacklistd.8 b/contrib/blocklist/bin/blacklistd.8 index 82e1f15f61c9..9ca886e9c4d3 100644 --- a/contrib/blocklist/bin/blacklistd.8 +++ b/contrib/blocklist/bin/blacklistd.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: blacklistd.8,v 1.23 2020/04/21 13:57:12 christos Exp $ +.\" $NetBSD: blocklistd.8,v 1.8 2025/02/25 22:13:34 christos Exp $ .\" .\" Copyright (c) 2015 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 21, 2020 +.Dd February 25, 2025 .Dt BLACKLISTD 8 .Os .Sh NAME @@ -53,18 +53,31 @@ for notifications from other daemons about successful or failed connection attempts. If no such file is specified, then it only listens to the socket path specified by -.Ar sockspath +.Ar sockpath or if that is not specified to -.Pa /var/run/blacklistd.sock . +.Pa /var/run/blocklistd.sock . Each notification contains an (action, port, protocol, address, owner) tuple that identifies the remote connection and the action. -This tuple is consulted against entries in -.Ar configfile -with syntax specified in +This tuple is consulted against entries from the +.Ar configfile , +with the syntax specified in .Xr blacklistd.conf 5 . If an entry is matched, a state entry is created for that tuple. Each entry contains a number of tries limit and a duration. .Pp +If +.Ar configfile +is a directory, or a directory exists with the same name as +.Ar configfile +with +.Qq .d +appended to it, each file in the directory will be read as configuration file. +If +.Ar configfile +exists as a file it will be processed before the contents of the +.Ar configfile Ns .d +directory if that also exists. +.Pp The way .Nm does configuration entry matching is by having the client side pass the @@ -152,7 +165,7 @@ The following options are available: .It Fl C Ar controlprog Use .Ar controlprog -to communicate with the packet filter, usually +to communicate with the packet filter, instead of the default, which is .Pa /usr/libexec/blacklistd-helper . The following arguments are passed to the control program: .Bl -tag -width protocol @@ -161,7 +174,7 @@ The action to perform: .Dv add , .Dv rem , or -.Dv flush +.Dv flush ; to add, remove or flush a firewall rule. .It name The rule name. @@ -183,13 +196,17 @@ identifier of the rule to be removed. The add command is expected to return the rule identifier string to stdout. .El .It Fl c Ar configuration -The name of the configuration file to read, usually +The name of the configuration file to read. +The default when +.Fl c +is not given is .Pa /etc/blacklistd.conf . .It Fl D Ar dbfile The Berkeley DB file where .Nm -stores its state, usually -.Pa /var/db/blacklistd.db . +stores its state. +It defaults to +.Pa /var/db/blocklistd.db . .It Fl d Normally, .Nm @@ -203,7 +220,7 @@ are deleted by invoking the control script as: .Bd -literal -offset indent control flush <rulename> .Ed -.It Fl P Ar sockspathsfile +.It Fl P Ar sockpathsfile A file containing a list of pathnames, one per line that .Nm will create sockets to listen to. @@ -261,16 +278,23 @@ to decrease the internal debugging level by 1. Shell script invoked to interface with the packet filter. .It Pa /etc/blacklistd.conf Configuration file. -.It Pa /var/db/blacklistd.db +.It Pa /var/db/blocklistd.db Database of current connection entries. -.It Pa /var/run/blacklistd.sock +.It Pa /var/run/blocklistd.sock Socket to receive connection notifications. .El .Sh SEE ALSO .Xr blacklistd.conf 5 , .Xr blacklistctl 8 , +.Xr ipf 8 , +.Xr ipfw 8 , .Xr pfctl 8 , .Xr syslogd 8 +.Sh NOTES +The +.Nm +daemon has been renamed to +.Xr blocklistd 8 . .Sh HISTORY .Nm first appeared in diff --git a/contrib/blocklist/bin/blacklistd.c b/contrib/blocklist/bin/blacklistd.c index 714abcbcaf0e..ded3075ed707 100644 --- a/contrib/blocklist/bin/blacklistd.c +++ b/contrib/blocklist/bin/blacklistd.c @@ -1,4 +1,4 @@ -/* $NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $ */ +/* $NetBSD: blocklistd.c,v 1.10 2025/03/26 17:09:35 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -31,8 +31,11 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif + +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $"); +#endif +__RCSID("$NetBSD: blocklistd.c,v 1.10 2025/03/26 17:09:35 christos Exp $"); #include <sys/types.h> #include <sys/socket.h> @@ -64,8 +67,8 @@ __RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $"); #include <ifaddrs.h> #include <netinet/in.h> -#include "bl.h" -#include "internal.h" +#include "old_bl.h" +#include "old_internal.h" #include "conf.h" #include "run.h" #include "state.h" @@ -175,6 +178,8 @@ process(bl_t bl) struct dbinfo dbi; struct timespec ts; + memset(&dbi, 0, sizeof(dbi)); + memset(&c, 0, sizeof(c)); if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); return; @@ -188,10 +193,11 @@ process(bl_t bl) if (getremoteaddress(bi, &rss, &rsl) == -1) goto out; - if (debug) { + if (debug || bi->bi_msg[0]) { sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss); - (*lfun)(LOG_DEBUG, "processing type=%d fd=%d remote=%s msg=%s" - " uid=%lu gid=%lu", bi->bi_type, bi->bi_fd, rbuf, + (*lfun)(bi->bi_msg[0] ? LOG_INFO : LOG_DEBUG, + "processing type=%d fd=%d remote=%s msg=%s uid=%lu gid=%lu", + bi->bi_type, bi->bi_fd, rbuf, bi->bi_msg, (unsigned long)bi->bi_uid, (unsigned long)bi->bi_gid); } @@ -334,7 +340,7 @@ static void addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd, const char *path) { - bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog); + bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog_r); if (bl == NULL || !bl_isconnected(bl)) exit(EXIT_FAILURE); if (*nfd >= *maxfd) { @@ -395,15 +401,25 @@ rules_flush(void) static void rules_restore(void) { + DB *db; struct conf c; struct dbinfo dbi; unsigned int f; - for (f = 1; state_iterate(state, &c, &dbi, f) == 1; f = 0) { + db = state_open(dbfile, O_RDONLY, 0); + if (db == NULL) { + (*lfun)(LOG_ERR, "Can't open `%s' to restore state (%m)", + dbfile); + return; + } + for (f = 1; state_iterate(db, &c, &dbi, f) == 1; f = 0) { if (dbi.id[0] == '\0') continue; (void)run_change("add", &c, dbi.id, sizeof(dbi.id)); + state_put(state, &c, &dbi); } + state_close(db); + state_sync(state); } int diff --git a/contrib/blocklist/bin/blacklistd.conf.5 b/contrib/blocklist/bin/blacklistd.conf.5 index 70036441eb4b..e775d30e7e8e 100644 --- a/contrib/blocklist/bin/blacklistd.conf.5 +++ b/contrib/blocklist/bin/blacklistd.conf.5 @@ -1,6 +1,6 @@ -.\" $NetBSD: blacklistd.conf.5,v 1.9 2019/11/06 20:33:30 para Exp $ +.\" $NetBSD: blocklistd.conf.5,v 1.7 2025/02/11 17:47:05 christos Exp $ .\" -.\" Copyright (c) 2015 The NetBSD Foundation, Inc. +.\" Copyright (c) 2015, 2025 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 18, 2020 +.Dd February 5, 2025 .Dt BLACKLISTD.CONF 5 .Os .Sh NAME @@ -48,34 +48,34 @@ Comments are denoted by a at the beginning of a line. .Pp There are two kinds of configuration lines, -.Va local +.Va [local] and -.Va remote . +.Va [remote] . By default, configuration lines are -.Va local , +.Va [local] , i.e. the address specified refers to the addresses on the local machine. To switch to between -.Va local +.Va [local] and -.Va remote +.Va [remote] configuration lines you can specify the stanzas: .Dq [local] and .Dq [remote] . .Pp On -.Va local +.Va [local] and -.Va remote +.Va [remote] lines .Dq * means use the default, or wildcard match. In addition, for -.Va remote +.Va [remote] lines .Dq = means use the values from the matched -.Va local +.Va [local] configuration line. .Pp The first four fields, @@ -85,9 +85,9 @@ The first four fields, and .Va owner are used to match the -.Va local +.Va [local] or -.Va remote +.Va [remote] addresses, whereas the last 3 fields .Va name , .Va nfail , @@ -110,8 +110,8 @@ The can be an IPv4 address in numeric format, an IPv6 address in numeric format and enclosed by square brackets, or an interface name. Mask modifiers are not allowed on interfaces because interfaces -can have multiple addresses in different protocols where the mask has a different -size. +can have multiple addresses in different protocols where the mask has a +different size. .Pp The .Dv mask @@ -143,8 +143,8 @@ The field, is the name of the packet filter rule to be used. If the .Va name -starts with a -.Dq - , +starts with a hyphen +.Pq Dq - , then the default rulename is prepended to the given name. If the .Dv name @@ -160,13 +160,13 @@ field contains the number of failed attempts before access is blocked, defaulting to .Dq * meaning never, and the last field -.Va disable +.Va duration specifies the amount of time since the last access that the blocking rule should be active, defaulting to .Dq * meaning forever. The default unit for -.Va disable +.Va duration is seconds, but one can specify suffixes for different units, such as .Dq m for minutes @@ -176,25 +176,31 @@ for hours and for days. .Pp Matching is done first by checking the -.Va local +.Va [local] rules individually, in the order of the most specific to the least specific. -If a match is found, then the -.Va remote +If a match is found, then the matching +.Va [remote] rules are applied. The .Va name , .Va nfail , and -.Va disable +.Va duration fields can be altered by the -.Va remote +.Va [remote] rule that matched. .Pp The -.Va remote +.Va [remote] rules can be used for allowing specific addresses, changing the mask -size, the rule that the packet filter uses, the number of failed attempts, -or the block duration. +size (via +.Va name ) , +the rule that the packet filter uses (also via +.Va name ) , +the number of failed attempts (via +.Va nfail ) , +or the duration to block (via +.Va duration ) . .Sh FILES .Bl -tag -width /etc/blacklistd.conf -compact .It Pa /etc/blacklistd.conf @@ -209,13 +215,20 @@ bnx0:ssh * * * * 3 6h [remote] # Never block 1.2.3.4 1.2.3.4:ssh * * * * * * -# For addresses coming from 8.8.0.0/16 block whole /24 networks instead of +# Never block the example IPv6 subnet either +[2001:db8::]/32:ssh * * * * * * +# For addresses coming from 8.8.0.0/16 block whole /24 networks instead # individual hosts, but keep the rest of the blocking parameters the same. 8.8.0.0/16:ssh * * * /24 = = .Ed .Sh SEE ALSO .Xr blacklistctl 8 , .Xr blacklistd 8 +.Sh NOTES +The +.Nm +file has been renamed to +.Xr blocklistd.conf 8 . .Sh HISTORY .Nm first appeared in diff --git a/contrib/blocklist/bin/blocklistctl.8 b/contrib/blocklist/bin/blocklistctl.8 new file mode 100644 index 000000000000..a98c16374f19 --- /dev/null +++ b/contrib/blocklist/bin/blocklistctl.8 @@ -0,0 +1,131 @@ +.\" $NetBSD: blocklistctl.8,v 1.4 2025/02/07 01:35:38 kre Exp $ +.\" +.\" Copyright (c) 2015 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd January 27, 2025 +.Dt BLOCKLISTCTL 8 +.Os +.Sh NAME +.Nm blocklistctl +.Nd display and change the state of the blocklistd database +.Sh SYNOPSIS +.Nm +.Cm dump +.Op Fl abdnrw +.Op Fl D Ar dbname +.Sh DESCRIPTION +.Nm +is a program used to display and change the state of the +.Xr blocklistd 8 +database. +The following sub-commands are supported: +.Ss dump +.Pp +The following options are available for the +.Cm dump +sub-command: +.Bl -tag -width indent +.It Fl a +Show all database entries, by default it shows only the active ones. +Inactive entries will be shown with a last-access (or, with +.Fl r , +the remaining) time of +.Ql never . +.It Fl b +Show only the blocked entries. +.It Fl D Ar dbname +Specify the location of the +.Ic blocklistd +database file to use. +The default is +.Pa /var/db/blocklistd.db . +.It Fl d +Increase debugging level. +.It Fl n +Don't display a header. +.It Fl r +Show the remaining blocked time instead of the last activity time. +.It Fl w +Normally the width of addresses is good for IPv4, the +.Fl w +flag, makes the display wide enough for IPv6 addresses. +.El +.Pp +The output of the +.Cm dump +sub-command consists of a header (unless +.Fl n +was given) and one line for each record in the database, where each line +has the following columns: +.Bl -tag -width indent +.It Ql address/ma:port +The remote address, mask, and local port number of the client connection +associated with the database entry. +.It Ql id +column will show the identifier for the packet filter rule associated +with the database entry, though this may only be the word +.Ql OK +for packet filters which do not creat a unique identifier for each rule. +.It Ql nfail +The number of +.Em failures +reported for the client on the noted port, as well as the number of +failures allowed before blocking (or, with +.Fl a , +an asterisk +.Aq * ) +.It So last access Sc | So remaining time Sc +The last time a the client was reported as attempting access, or, with +.Fl r , +the time remaining before the rule blocking the client will be removed. +.El +.Sh SEE ALSO +.Xr blocklistd 8 +.Sh NOTES +Sometimes the reported number of failed attempts can exceed the number +of attempts that +.Xr blocklistd 8 +is configured to block. +This can happen either because the rule has been removed manually, or +because there were more attempts in flight while the rule block was being +added. +This condition is normal; in that case +.Xr blocklistd 8 +will first attempt to remove the existing rule, and then it will re-add +it to make sure that there is only one rule active. +.Sh HISTORY +.Nm +first appeared in +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas diff --git a/contrib/blocklist/bin/blocklistctl.c b/contrib/blocklist/bin/blocklistctl.c new file mode 100644 index 000000000000..8c75e0430c61 --- /dev/null +++ b/contrib/blocklist/bin/blocklistctl.c @@ -0,0 +1,170 @@ +/* $NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); + +#include <stdio.h> +#include <time.h> +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#ifdef HAVE_UTIL_H +#include <util.h> +#endif +#include <fcntl.h> +#include <string.h> +#include <syslog.h> +#include <err.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> + +#include "conf.h" +#include "state.h" +#include "internal.h" +#include "support.h" + +static __dead void +usage(int c) +{ + if (c == 0) + warnx("Missing/unknown command"); + else if (c != '?') + warnx("Unknown option `%c'", (char)c); + fprintf(stderr, + "Usage: %s dump [-abdnrw] [-D dbname]\n", getprogname()); + exit(EXIT_FAILURE); +} + +static const char * +star(char *buf, size_t len, int val) +{ + if (val == -1) + return "*"; + snprintf(buf, len, "%d", val); + return buf; +} + +int +main(int argc, char *argv[]) +{ + const char *dbname = _PATH_BLSTATE; + DB *db; + struct conf c; + struct dbinfo dbi; + unsigned int i; + struct timespec ts; + int all, blocked, remain, wide, noheader; + int o; + + noheader = wide = blocked = all = remain = 0; + lfun = dlog; + + if (argc == 1 || strcmp(argv[1], "dump") != 0) + usage(0); + + argc--; + argv++; + + while ((o = getopt(argc, argv, "abD:dnrw")) != -1) + switch (o) { + case 'a': + all = 1; + blocked = 0; + break; + case 'b': + blocked = 1; + break; + case 'D': + dbname = optarg; + break; + case 'd': + debug++; + break; + case 'n': + noheader = 1; + break; + case 'r': + remain = 1; + break; + case 'w': + wide = 1; + break; + default: + usage(o); + } + + db = state_open(dbname, O_RDONLY, 0); + if (db == NULL) + err(EXIT_FAILURE, "Can't open `%s'", dbname); + + clock_gettime(CLOCK_REALTIME, &ts); + wide = wide ? 8 * 4 + 7 : 4 * 3 + 3; + if (!noheader) + printf("%*.*s/ma:port\tid\tnfail\t%s\n", wide, wide, + "address", remain ? "remaining time" : "last access"); + for (i = 1; state_iterate(db, &c, &dbi, i) != 0; i = 0) { + char buf[BUFSIZ]; + char mbuf[64], pbuf[64]; + if (!all) { + if (blocked) { + if (c.c_nfail == -1 || dbi.count < c.c_nfail) + continue; + } else { + if (dbi.count >= c.c_nfail) + continue; + } + } + sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&c.c_ss); + printf("%*.*s/%s:%s\t", wide, wide, buf, + star(mbuf, sizeof(mbuf), c.c_lmask), + star(pbuf, sizeof(pbuf), c.c_port)); + if (c.c_duration == -1) { + strlcpy(buf, "never", sizeof(buf)); + } else { + if (remain) + fmtydhms(buf, sizeof(buf), + c.c_duration - (ts.tv_sec - dbi.last)); + else + fmttime(buf, sizeof(buf), dbi.last); + } + printf("%s\t%d/%s\t%-s\n", dbi.id, dbi.count, + star(mbuf, sizeof(mbuf), c.c_nfail), buf); + } + state_close(db); + return EXIT_SUCCESS; +} diff --git a/contrib/blocklist/bin/blocklistd.8 b/contrib/blocklist/bin/blocklistd.8 new file mode 100644 index 000000000000..e0b9fb482cbd --- /dev/null +++ b/contrib/blocklist/bin/blocklistd.8 @@ -0,0 +1,303 @@ +.\" $NetBSD: blocklistd.8,v 1.8 2025/02/25 22:13:34 christos Exp $ +.\" +.\" Copyright (c) 2015 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 25, 2025 +.Dt BLOCKLISTD 8 +.Os +.Sh NAME +.Nm blocklistd +.Nd block and release ports on demand to avoid DoS abuse +.Sh SYNOPSIS +.Nm +.Op Fl dfrv +.Op Fl C Ar controlprog +.Op Fl c Ar configfile +.Op Fl D Ar dbfile +.Op Fl P Ar sockpathsfile +.Op Fl R Ar rulename +.Op Fl s Ar sockpath +.Op Fl t Ar timeout +.Sh DESCRIPTION +.Nm +is a daemon similar to +.Xr syslogd 8 +that listens to sockets at paths specified in the +.Ar sockpathsfile +for notifications from other daemons about successful or failed connection +attempts. +If no such file is specified, then it only listens to the socket path +specified by +.Ar sockpath +or if that is not specified to +.Pa /var/run/blocklistd.sock . +Each notification contains an (action, port, protocol, address, owner) tuple +that identifies the remote connection and the action. +This tuple is consulted against entries from the +.Ar configfile , +with the syntax specified in +.Xr blocklistd.conf 5 . +If an entry is matched, a state entry is created for that tuple. +Each entry contains a number of tries limit and a duration. +.Pp +If +.Ar configfile +is a directory, or a directory exists with the same name as +.Ar configfile +with +.Qq .d +appended to it, each file in the directory will be read as configuration file. +If +.Ar configfile +exists as a file it will be processed before the contents of the +.Ar configfile Ns .d +directory if that also exists. +.Pp +The way +.Nm +does configuration entry matching is by having the client side pass the +file descriptor associated with the connection the client wants to blocklist +as well as passing socket credentials. +.Pp +The file descriptor is used to retrieve information (address and port) +about the remote side with +.Xr getpeername 2 +and the local side with +.Xr getsockname 2 . +.Pp +By examining the port of the local side, +.Nm +can determine if the client program +.Dq owns +the port. +By examining the optional address portion on the local side, it can match +interfaces. +By examining the remote address, it can match specific allow or deny rules. +.Pp +Finally +.Nm +can examine the socket credentials to match the user in the configuration file. +.Pp +While this works well for TCP sockets, it cannot be relied on for unbound +UDP sockets. +It is also less meaningful when it comes to connections using non-privileged +ports. +On the other hand, if we receive a request that has a local endpoint indicating +a UDP privileged port, we can presume that the client was privileged to be +able to acquire that port. +.Pp +Once an entry is matched +.Nm +can perform various actions. +If the action is +.Dq add +and the number of tries limit is reached, then a +control script +.Ar controlprog +is invoked with arguments: +.Bd -literal -offset indent +control add <rulename> <proto> <address> <mask> <port> +.Ed +.Pp +and should invoke a packet filter command to block the connection +specified by the arguments. +The +.Ar rulename +argument can be set from the command line (default +.Dv blocklistd ) . +The script could print a numerical id to stdout as a handle for +the rule that can be used later to remove that connection, but +that is not required as all information to remove the rule is +kept. +.Pp +If the action is +.Dq rem +Then the same control script is invoked as: +.Bd -literal -offset indent +control rem <rulename> <proto> <address> <mask> <port> <id> +.Ed +.Pp +where +.Ar id +is the number returned from the +.Dq add +action. +.Pp +.Nm +maintains a database of known connections in +.Ar dbfile . +On startup it reads entries from that file, and updates its internal state. +.Pp +.Nm +checks the list of active entries every +.Ar timeout +seconds (default +.Dv 15 ) +and removes entries and block rules using the control program as necessary. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl C Ar controlprog +Use +.Ar controlprog +to communicate with the packet filter, instead of the default, which is +.Pa /usr/libexec/blocklistd-helper . +The following arguments are passed to the control program: +.Bl -tag -width protocol +.It action +The action to perform: +.Dv add , +.Dv rem , +or +.Dv flush ; +to add, remove or flush a firewall rule. +.It name +The rule name. +.It protocol +The optional protocol name (can be empty): +.Dv tcp , +.Dv tcp6 , +.Dv udp , +.Dv udp6 . +.It address +The IPv4 or IPv6 numeric address to be blocked or released. +.It mask +The numeric mask to be applied to the blocked or released address +.It port +The optional numeric port to be blocked (can be empty). +.It id +For packet filters that support removal of rules by rule identifier, the +identifier of the rule to be removed. +The add command is expected to return the rule identifier string to stdout. +.El +.It Fl c Ar configuration +The name of the configuration file to read. +The default when +.Fl c +is not given is +.Pa /etc/blocklistd.conf . +.It Fl D Ar dbfile +The Berkeley DB file where +.Nm +stores its state. +It defaults to +.Pa /var/db/blocklistd.db . +.It Fl d +Normally, +.Nm +disassociates itself from the terminal unless the +.Fl d +flag is specified, in which case it stays in the foreground. +.It Fl f +Truncate the state database and flush all the rules named +.Ar rulename +are deleted by invoking the control script as: +.Bd -literal -offset indent +control flush <rulename> +.Ed +.It Fl P Ar sockpathsfile +A file containing a list of pathnames, one per line that +.Nm +will create sockets to listen to. +This is useful for chrooted environments. +.It Fl R Ar rulename +Specify the default rule name for the packet filter rules, usually +.Dv blocklistd . +.It Fl r +Re-read the firewall rules from the internal database, then +remove and re-add them. +This helps for packet filters that do not retain state across reboots. +.It Fl s Ar sockpath +Add +.Ar sockpath +to the list of Unix sockets +.Nm +listens to. +.It Fl t Ar timeout +The interval in seconds +.Nm +polls the state file to update the rules. +.It Fl v +Cause +.Nm +to print +diagnostic messages to +.Dv stdout +instead of +.Xr syslogd 8 . +.El +.Sh SIGNAL HANDLING +.Nm +deals with the following signals: +.Bl -tag -width "USR2" +.It Dv HUP +Receipt of this signal causes +.Nm +to re-read the configuration file. +.It Dv INT , Dv TERM & Dv QUIT +These signals tell +.Nm +to exit in an orderly fashion. +.It Dv USR1 +This signal tells +.Nm +to increase the internal debugging level by 1. +.It Dv USR2 +This signal tells +.Nm +to decrease the internal debugging level by 1. +.El +.Sh FILES +.Bl -tag -width /usr/libexec/blocklistd-helper -compact +.It Pa /usr/libexec/blocklistd-helper +Shell script invoked to interface with the packet filter. +.It Pa /etc/blocklistd.conf +Configuration file. +.It Pa /var/db/blocklistd.db +Database of current connection entries. +.It Pa /var/run/blocklistd.sock +Socket to receive connection notifications. +.El +.Sh SEE ALSO +.Xr blocklistd.conf 5 , +.Xr blocklistctl 8 , +.Xr ipf 8 , +.Xr ipfw 8 , +.Xr pfctl 8 , +.Xr syslogd 8 +.Sh HISTORY +.Nm +first appeared in +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas diff --git a/contrib/blocklist/bin/blocklistd.c b/contrib/blocklist/bin/blocklistd.c new file mode 100644 index 000000000000..03a1dbbf056c --- /dev/null +++ b/contrib/blocklist/bin/blocklistd.c @@ -0,0 +1,592 @@ +/* $NetBSD: blocklistd.c,v 1.10 2025/03/26 17:09:35 christos Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: blocklistd.c,v 1.10 2025/03/26 17:09:35 christos Exp $"); + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> + +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#ifdef HAVE_UTIL_H +#include <util.h> +#endif +#include <string.h> +#include <signal.h> +#include <netdb.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <inttypes.h> +#include <syslog.h> +#include <ctype.h> +#include <limits.h> +#include <errno.h> +#include <poll.h> +#include <fcntl.h> +#include <err.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <ifaddrs.h> +#include <netinet/in.h> + +#include "bl.h" +#include "internal.h" +#include "conf.h" +#include "run.h" +#include "state.h" +#include "support.h" + +static const char *configfile = _PATH_BLCONF; +static DB *state; +static const char *dbfile = _PATH_BLSTATE; +static sig_atomic_t readconf; +static sig_atomic_t done; +static int vflag; + +static void +sigusr1(int n __unused) +{ + debug++; +} + +static void +sigusr2(int n __unused) +{ + debug--; +} + +static void +sighup(int n __unused) +{ + readconf++; +} + +static void +sigdone(int n __unused) +{ + done++; +} + +static __dead void +usage(int c) +{ + if (c != '?') + warnx("Unknown option `%c'", (char)c); + fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] " + "[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] " + "[-s <sockpath>] [-t <timeout>]\n", getprogname()); + exit(EXIT_FAILURE); +} + +static int +getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl) +{ + *rsl = sizeof(*rss); + memset(rss, 0, *rsl); + + if (getpeername(bi->bi_fd, (void *)rss, rsl) != -1) + return 0; + + if (errno != ENOTCONN) { + (*lfun)(LOG_ERR, "getpeername failed (%m)"); + return -1; + } + + if (bi->bi_slen == 0) { + (*lfun)(LOG_ERR, "unconnected socket with no peer in message"); + return -1; + } + + switch (bi->bi_ss.ss_family) { + case AF_INET: + *rsl = sizeof(struct sockaddr_in); + break; + case AF_INET6: + *rsl = sizeof(struct sockaddr_in6); + break; + default: + (*lfun)(LOG_ERR, "bad client passed socket family %u", + (unsigned)bi->bi_ss.ss_family); + return -1; + } + + if (*rsl != bi->bi_slen) { + (*lfun)(LOG_ERR, "bad client passed socket length %u != %u", + (unsigned)*rsl, (unsigned)bi->bi_slen); + return -1; + } + + memcpy(rss, &bi->bi_ss, *rsl); + +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + if (*rsl != rss->ss_len) { + (*lfun)(LOG_ERR, + "bad client passed socket internal length %u != %u", + (unsigned)*rsl, (unsigned)rss->ss_len); + return -1; + } +#endif + return 0; +} + +static void +process(bl_t bl) +{ + struct sockaddr_storage rss; + socklen_t rsl; + char rbuf[BUFSIZ]; + bl_info_t *bi; + struct conf c; + struct dbinfo dbi; + struct timespec ts; + + memset(&dbi, 0, sizeof(dbi)); + memset(&c, 0, sizeof(c)); + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); + return; + } + + if ((bi = bl_recv(bl)) == NULL) { + (*lfun)(LOG_ERR, "no message (%m)"); + return; + } + + if (getremoteaddress(bi, &rss, &rsl) == -1) + goto out; + + if (debug || bi->bi_msg[0]) { + sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss); + (*lfun)(bi->bi_msg[0] ? LOG_INFO : LOG_DEBUG, + "processing type=%d fd=%d remote=%s msg=%s uid=%lu gid=%lu", + bi->bi_type, bi->bi_fd, rbuf, + bi->bi_msg, (unsigned long)bi->bi_uid, + (unsigned long)bi->bi_gid); + } + + if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) { + (*lfun)(LOG_DEBUG, "no rule matched"); + goto out; + } + + + if (state_get(state, &c, &dbi) == -1) + goto out; + + if (debug) { + char b1[128], b2[128]; + (*lfun)(LOG_DEBUG, "%s: initial db state for %s: count=%d/%d " + "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail, + fmttime(b1, sizeof(b1), dbi.last), + fmttime(b2, sizeof(b2), ts.tv_sec)); + } + + switch (bi->bi_type) { + case BL_ABUSE: + /* + * If the application has signaled abusive behavior, + * set the number of fails to be one less than the + * configured limit. Fallthrough to the normal BL_ADD + * processing, which will increment the failure count + * to the threshhold, and block the abusive address. + */ + if (c.c_nfail != -1) + dbi.count = c.c_nfail - 1; + /*FALLTHROUGH*/ + case BL_ADD: + dbi.count++; + dbi.last = ts.tv_sec; + if (c.c_nfail != -1 && dbi.count >= c.c_nfail) { + /* + * No point in re-adding the rule. + * It might exist already due to latency in processing + * and removing the rule is the wrong thing to do as + * it allows a window to attack again. + */ + if (dbi.id[0] == '\0') { + int res = run_change("add", &c, + dbi.id, sizeof(dbi.id)); + if (res == -1) + goto out; + } + sockaddr_snprintf(rbuf, sizeof(rbuf), "%a", + (void *)&rss); + (*lfun)(LOG_INFO, + "blocked %s/%d:%d for %d seconds", + rbuf, c.c_lmask, c.c_port, c.c_duration); + } + break; + case BL_DELETE: + if (dbi.last == 0) + goto out; + dbi.count = 0; + dbi.last = 0; + break; + case BL_BADUSER: + /* ignore for now */ + break; + default: + (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type); + } + state_put(state, &c, &dbi); + +out: + close(bi->bi_fd); + + if (debug) { + char b1[128], b2[128]; + (*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d " + "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail, + fmttime(b1, sizeof(b1), dbi.last), + fmttime(b2, sizeof(b2), ts.tv_sec)); + } +} + +static void +update_interfaces(void) +{ + struct ifaddrs *oifas, *nifas; + + if (getifaddrs(&nifas) == -1) + return; + + oifas = ifas; + ifas = nifas; + + if (oifas) + freeifaddrs(oifas); +} + +static void +update(void) +{ + struct timespec ts; + struct conf c; + struct dbinfo dbi; + unsigned int f, n; + char buf[128]; + void *ss = &c.c_ss; + + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); + return; + } + +again: + for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1; + f = 0, n++) + { + time_t when = c.c_duration + dbi.last; + if (debug > 1) { + char b1[64], b2[64]; + sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss); + (*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d " + "last=%s " "now=%s", __func__, n, buf, dbi.count, + c.c_duration, fmttime(b1, sizeof(b1), dbi.last), + fmttime(b2, sizeof(b2), ts.tv_sec)); + } + if (c.c_duration == -1 || when >= ts.tv_sec) + continue; + if (dbi.id[0]) { + run_change("rem", &c, dbi.id, 0); + sockaddr_snprintf(buf, sizeof(buf), "%a", ss); + (*lfun)(LOG_INFO, "released %s/%d:%d after %d seconds", + buf, c.c_lmask, c.c_port, c.c_duration); + } + state_del(state, &c); + goto again; + } +} + +static void +addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd, + const char *path) +{ + bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog_r); + if (bl == NULL || !bl_isconnected(bl)) + exit(EXIT_FAILURE); + if (*nfd >= *maxfd) { + *maxfd += 10; + *blp = realloc(*blp, sizeof(**blp) * *maxfd); + if (*blp == NULL) + err(EXIT_FAILURE, "malloc"); + *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd); + if (*pfdp == NULL) + err(EXIT_FAILURE, "malloc"); + } + + (*pfdp)[*nfd].fd = bl_getfd(bl); + (*pfdp)[*nfd].events = POLLIN; + (*blp)[*nfd] = bl; + *nfd += 1; +} + +static void +uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c) +{ + struct conf **list = *listp; + + if (c->c_name[0] == '\0') + return; + for (size_t i = 0; i < *nlist; i++) { + if (strcmp(list[i]->c_name, c->c_name) == 0) + return; + } + if (*nlist == *mlist) { + *mlist += 10; + void *p = realloc(*listp, *mlist * sizeof(*list)); + if (p == NULL) + err(EXIT_FAILURE, "Can't allocate for rule list"); + list = *listp = p; + } + list[(*nlist)++] = c; +} + +static void +rules_flush(void) +{ + struct conf **list; + size_t nlist, mlist; + + list = NULL; + mlist = nlist = 0; + for (size_t i = 0; i < rconf.cs_n; i++) + uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]); + for (size_t i = 0; i < lconf.cs_n; i++) + uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]); + + for (size_t i = 0; i < nlist; i++) + run_flush(list[i]); + free(list); +} + +static void +rules_restore(void) +{ + DB *db; + struct conf c; + struct dbinfo dbi; + unsigned int f; + + db = state_open(dbfile, O_RDONLY, 0); + if (db == NULL) { + (*lfun)(LOG_ERR, "Can't open `%s' to restore state (%m)", + dbfile); + return; + } + for (f = 1; state_iterate(db, &c, &dbi, f) == 1; f = 0) { + if (dbi.id[0] == '\0') + continue; + (void)run_change("add", &c, dbi.id, sizeof(dbi.id)); + state_put(state, &c, &dbi); + } + state_close(db); + state_sync(state); +} + +int +main(int argc, char *argv[]) +{ + int c, tout, flags, flush, restore, ret; + const char *spath, **blsock; + size_t nblsock, maxblsock; + + setprogname(argv[0]); + + spath = NULL; + blsock = NULL; + maxblsock = nblsock = 0; + flush = 0; + restore = 0; + tout = 0; + flags = O_RDWR|O_EXCL|O_CLOEXEC; + while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) { + switch (c) { + case 'C': + controlprog = optarg; + break; + case 'c': + configfile = optarg; + break; + case 'D': + dbfile = optarg; + break; + case 'd': + debug++; + break; + case 'f': + flush++; + break; + case 'P': + spath = optarg; + break; + case 'R': + rulename = optarg; + break; + case 'r': + restore++; + break; + case 's': + if (nblsock >= maxblsock) { + maxblsock += 10; + void *p = realloc(blsock, + sizeof(*blsock) * maxblsock); + if (p == NULL) + err(EXIT_FAILURE, + "Can't allocate memory for %zu sockets", + maxblsock); + blsock = p; + } + blsock[nblsock++] = optarg; + break; + case 't': + tout = atoi(optarg) * 1000; + break; + case 'v': + vflag++; + break; + default: + usage(c); + } + } + + argc -= optind; + if (argc) + usage('?'); + + signal(SIGHUP, sighup); + signal(SIGINT, sigdone); + signal(SIGQUIT, sigdone); + signal(SIGTERM, sigdone); + signal(SIGUSR1, sigusr1); + signal(SIGUSR2, sigusr2); + + openlog(getprogname(), LOG_PID, LOG_DAEMON); + + if (debug) { + lfun = dlog; + if (tout == 0) + tout = 5000; + } else { + if (tout == 0) + tout = 15000; + } + + update_interfaces(); + conf_parse(configfile); + if (flush) { + rules_flush(); + if (!restore) + flags |= O_TRUNC; + } + + struct pollfd *pfd = NULL; + bl_t *bl = NULL; + size_t nfd = 0; + size_t maxfd = 0; + + for (size_t i = 0; i < nblsock; i++) + addfd(&pfd, &bl, &nfd, &maxfd, blsock[i]); + free(blsock); + + if (spath) { + FILE *fp = fopen(spath, "r"); + char *line; + if (fp == NULL) + err(EXIT_FAILURE, "Can't open `%s'", spath); + for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL; + free(line)) + addfd(&pfd, &bl, &nfd, &maxfd, line); + fclose(fp); + } + if (nfd == 0) + addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK); + + state = state_open(dbfile, flags, 0600); + if (state == NULL) + state = state_open(dbfile, flags | O_CREAT, 0600); + if (state == NULL) + return EXIT_FAILURE; + + if (restore) { + if (!flush) + rules_flush(); + rules_restore(); + } + + if (!debug) { + if (daemon(0, 0) == -1) + err(EXIT_FAILURE, "daemon failed"); + if (pidfile(NULL) == -1) + err(EXIT_FAILURE, "Can't create pidfile"); + } + + for (size_t t = 0; !done; t++) { + if (readconf) { + readconf = 0; + conf_parse(configfile); + } + ret = poll(pfd, (nfds_t)nfd, tout); + if (debug) + (*lfun)(LOG_DEBUG, "received %d from poll()", ret); + switch (ret) { + case -1: + if (errno == EINTR) + continue; + (*lfun)(LOG_ERR, "poll (%m)"); + return EXIT_FAILURE; + case 0: + state_sync(state); + break; + default: + for (size_t i = 0; i < nfd; i++) + if (pfd[i].revents & POLLIN) + process(bl[i]); + } + if (t % 100 == 0) + state_sync(state); + if (t % 10000 == 0) + update_interfaces(); + update(); + } + state_close(state); + return 0; +} diff --git a/contrib/blocklist/bin/blocklistd.conf.5 b/contrib/blocklist/bin/blocklistd.conf.5 new file mode 100644 index 000000000000..3a7dbfc07f58 --- /dev/null +++ b/contrib/blocklist/bin/blocklistd.conf.5 @@ -0,0 +1,237 @@ +.\" $NetBSD: blocklistd.conf.5,v 1.7 2025/02/11 17:47:05 christos Exp $ +.\" +.\" Copyright (c) 2015, 2025 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 5, 2025 +.Dt BLOCKLISTD.CONF 5 +.Os +.Sh NAME +.Nm blocklistd.conf +.Nd configuration file format for blocklistd +.Sh DESCRIPTION +The +.Nm +file contains configuration entries for +.Xr blocklistd 8 +in a fashion similar to +.Xr inetd.conf 5 . +Only one entry per line is permitted. +Every entry must have all fields populated. +Each field can be separated by a tab or a space. +Comments are denoted by a +.Dq # +at the beginning of a line. +.Pp +There are two kinds of configuration lines, +.Va [local] +and +.Va [remote] . +By default, configuration lines are +.Va [local] , +i.e. the address specified refers to the addresses on the local machine. +To switch to between +.Va [local] +and +.Va [remote] +configuration lines you can specify the stanzas: +.Dq [local] +and +.Dq [remote] . +.Pp +On +.Va [local] +and +.Va [remote] +lines +.Dq * +means use the default, or wildcard match. +In addition, for +.Va [remote] +lines +.Dq = +means use the values from the matched +.Va [local] +configuration line. +.Pp +The first four fields, +.Va location , +.Va type , +.Va proto , +and +.Va owner +are used to match the +.Va [local] +or +.Va [remote] +addresses, whereas the last 3 fields +.Va name , +.Va nfail , +and +.Va disable +are used to modify the filtering action. +.Pp +The first field denotes the +.Va location +as an address, mask, and port. +The syntax for the +.Va location +is: +.Bd -literal -offset indent + [<address>|<interface>][/<mask>][:<port>] +.Ed +.Pp +The +.Dv address +can be an IPv4 address in numeric format, an IPv6 address +in numeric format and enclosed by square brackets, or an interface name. +Mask modifiers are not allowed on interfaces because interfaces +can have multiple addresses in different protocols where the mask has a +different size. +.Pp +The +.Dv mask +is always numeric, but the +.Dv port +can be either numeric or symbolic. +.Pp +The second field is the socket +.Va type : +.Dv stream , +.Dv dgram , +or numeric. +The third field is the +.Va protocol : +.Dv tcp , +.Dv udp , +.Dv tcp6 , +.Dv udp6 , +or numeric. +The fourth field is the effective user +.Va ( owner ) +of the daemon process reporting the event, +either as a username or a userid. +.Pp +The rest of the fields control the behavior of the filter. +.Pp +The +.Va name +field, is the name of the packet filter rule to be used. +If the +.Va name +starts with a hyphen +.Pq Dq - , +then the default rulename is prepended to the given name. +If the +.Dv name +contains a +.Dq / , +the remaining portion of the name is interpreted as the mask to be +applied to the address specified in the rule, causing a single rule violation to +block the entire subnet for the configured prefix. +.Pp +The +.Va nfail +field contains the number of failed attempts before access is blocked, +defaulting to +.Dq * +meaning never, and the last field +.Va duration +specifies the amount of time since the last access that the blocking +rule should be active, defaulting to +.Dq * +meaning forever. +The default unit for +.Va duration +is seconds, but one can specify suffixes for different units, such as +.Dq m +for minutes +.Dq h +for hours and +.Dq d +for days. +.Pp +Matching is done first by checking the +.Va [local] +rules individually, in the order of the most specific to the least specific. +If a match is found, then the matching +.Va [remote] +rules are applied. +The +.Va name , +.Va nfail , +and +.Va duration +fields can be altered by the +.Va [remote] +rule that matched. +.Pp +The +.Va [remote] +rules can be used for allowing specific addresses, changing the mask +size (via +.Va name ) , +the rule that the packet filter uses (also via +.Va name ) , +the number of failed attempts (via +.Va nfail ) , +or the duration to block (via +.Va duration ) . +.Sh FILES +.Bl -tag -width /etc/blocklistd.conf -compact +.It Pa /etc/blocklistd.conf +Configuration file. +.El +.Sh EXAMPLES +.Bd -literal -offset 8n +# Block ssh, after 3 attempts for 6 hours on the bnx0 interface +[local] +# location type proto owner name nfail duration +bnx0:ssh * * * * 3 6h +[remote] +# Never block 1.2.3.4 +1.2.3.4:ssh * * * * * * +# Never block the example IPv6 subnet either +[2001:db8::]/32:ssh * * * * * * +# For addresses coming from 8.8.0.0/16 block whole /24 networks instead +# individual hosts, but keep the rest of the blocking parameters the same. +8.8.0.0/16:ssh * * * /24 = = +.Ed +.Sh SEE ALSO +.Xr blocklistctl 8 , +.Xr blocklistd 8 +.Sh HISTORY +.Nm +first appeared in +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas diff --git a/contrib/blocklist/bin/conf.c b/contrib/blocklist/bin/conf.c index 8f7e75a56be1..f469e28235cd 100644 --- a/contrib/blocklist/bin/conf.c +++ b/contrib/blocklist/bin/conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $ */ +/* $NetBSD: conf.c,v 1.10 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $"); +#endif +__RCSID("$NetBSD: conf.c,v 1.10 2025/02/11 17:48:30 christos Exp $"); #include <stdio.h> #ifdef HAVE_LIBUTIL_H @@ -58,6 +60,7 @@ __RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $"); #include <net/if.h> #include <net/route.h> #include <sys/socket.h> +#include <dirent.h> #include "bl.h" #include "internal.h" @@ -261,7 +264,7 @@ conf_gethostport(const char *f, size_t l, bool local, struct conf *c, if (debug) (*lfun)(LOG_DEBUG, "%s: host6 %s", __func__, p); if (strcmp(p, "*") != 0) { - if (inet_pton(AF_INET6, p, &sin6->sin6_addr) == -1) + if (inet_pton(AF_INET6, p, &sin6->sin6_addr) != 1) goto out; sin6->sin6_family = AF_INET6; #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN @@ -269,6 +272,8 @@ conf_gethostport(const char *f, size_t l, bool local, struct conf *c, #endif port = &sin6->sin6_port; } + if (!*pstr) + pstr = "*"; } else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) { if (pstr == p) pstr = "*"; @@ -311,7 +316,7 @@ conf_gethostport(const char *f, size_t l, bool local, struct conf *c, *port = htons((in_port_t)c->c_port); return 0; out: - (*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, pstr); + (*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, p); return -1; out1: (*lfun)(LOG_ERR, "%s: %s, %zu: Can't specify mask %d with " @@ -407,6 +412,8 @@ conf_parseline(const char *f, size_t l, char *p, struct conf *c, bool local) { int e; + c->c_lineno = l; + while (*p && isspace((unsigned char)*p)) p++; @@ -471,7 +478,6 @@ conf_amask_eq(const void *v1, const void *v2, size_t len, int mask) uint32_t m; int omask = mask; - len >>= 2; switch (mask) { case FSTAR: if (memcmp(v1, v2, len) == 0) @@ -485,7 +491,7 @@ conf_amask_eq(const void *v1, const void *v2, size_t len, int mask) break; } - for (size_t i = 0; i < len; i++) { + for (size_t i = 0; i < (len >> 2); i++) { if (mask > 32) { m = htonl((uint32_t)~0); mask -= 32; @@ -501,7 +507,6 @@ conf_amask_eq(const void *v1, const void *v2, size_t len, int mask) out: if (debug > 1) { char b1[256], b2[256]; - len <<= 2; blhexdump(b1, sizeof(b1), "a1", v1, len); blhexdump(b2, sizeof(b2), "a2", v2, len); (*lfun)(LOG_DEBUG, "%s: %s != %s [0x%x]", __func__, @@ -691,6 +696,25 @@ conf_addr_eq(const struct sockaddr_storage *s1, static int conf_eq(const struct conf *c1, const struct conf *c2) { + if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, FSTAR)) + return 0; + +#define CMP(a, b, f) \ + if ((a)->f != (b)->f) \ + return 0; + + CMP(c1, c2, c_port); + CMP(c1, c2, c_proto); + CMP(c1, c2, c_family); + CMP(c1, c2, c_uid); +#undef CMP + + return 1; +} + +static int +conf_match(const struct conf *c1, const struct conf *c2) +{ if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, c2->c_lmask)) return 0; @@ -953,13 +977,54 @@ confset_free(struct confset *cs) } static void -confset_replace(struct confset *dc, struct confset *sc) +confset_merge(struct confset *dc, struct confset *sc) { - struct confset tc; - tc = *dc; - *dc = *sc; - confset_init(sc); - confset_free(&tc); + size_t i, j; + char buf[BUFSIZ]; + + /* Check each rule of the src confset (sc) */ + for (i = 0; i < sc->cs_n; i++) { + /* Compare to each rule in the dest confset (dc) */ + for (j = 0; j < dc->cs_n; j++) { + if (conf_eq(&dc->cs_c[j], &sc->cs_c[i])) { + break; + } + } + + if (j == dc->cs_n) { + /* This is a new rule to add to the dest confset. */ + if (confset_full(dc) && confset_grow(dc) == -1) + return; + + *confset_get(dc) = sc->cs_c[i]; + confset_add(dc); + continue; + } + + /* We had a match above. */ + /* + * Check whether the rule from the src confset is more + * restrictive than the existing one. Adjust the + * existing rule if necessary. + */ + if (sc->cs_c[i].c_nfail == dc->cs_c[j].c_nfail && + sc->cs_c[i].c_duration && dc->cs_c[j].c_duration) { + (*lfun)(LOG_DEBUG, "skipping existing rule: %s", + conf_print(buf, sizeof (buf), "", "\t", &sc->cs_c[i])); + continue; + } + + if (sc->cs_c[i].c_nfail < dc->cs_c[j].c_nfail) + dc->cs_c[j].c_nfail = sc->cs_c[i].c_nfail; + + if (sc->cs_c[i].c_duration > dc->cs_c[j].c_duration) + dc->cs_c[j].c_duration = sc->cs_c[i].c_duration; + + (*lfun)(LOG_DEBUG, "adjusted existing rule: %s", + conf_print(buf, sizeof (buf), "", "\t", &dc->cs_c[j])); + } + + confset_free(sc); } static void @@ -990,7 +1055,7 @@ confset_match(const struct confset *cs, struct conf *c, if (debug) (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), "check:\t", "", &cs->cs_c[i])); - if (conf_eq(c, &cs->cs_c[i])) { + if (conf_match(c, &cs->cs_c[i])) { if (debug) (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), @@ -1160,21 +1225,14 @@ conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss, return cr; } - -void -conf_parse(const char *f) +static void +conf_parsefile(FILE *fp, const char *config_file) { - FILE *fp; char *line; size_t lineno, len; struct confset lc, rc, *cs; - if ((fp = fopen(f, "r")) == NULL) { - (*lfun)(LOG_ERR, "%s: Cannot open `%s' (%m)", __func__, f); - return; - } - - lineno = 1; + lineno = 0; confset_init(&rc); confset_init(&lc); @@ -1197,23 +1255,103 @@ conf_parse(const char *f) if (confset_grow(cs) == -1) { confset_free(&lc); confset_free(&rc); - fclose(fp); free(line); return; } } - if (conf_parseline(f, lineno, line, confset_get(cs), + if (conf_parseline(config_file, lineno, line, confset_get(cs), cs == &lc) == -1) continue; confset_add(cs); } - fclose(fp); - confset_sort(&lc); - confset_sort(&rc); + confset_merge(&rconf, &rc); + confset_merge(&lconf, &lc); +} + + +static void +conf_parsedir(DIR *dir, const char *config_path) +{ + long path_max; + struct dirent *dent; + char *path; + FILE *fp; + + if ((path_max = pathconf(config_path, _PC_PATH_MAX)) == -1) + path_max = 2048; + + if ((path = malloc((size_t)path_max)) == NULL) { + (*lfun)(LOG_ERR, "%s: Failed to allocate memory for path (%m)", + __func__); + return; + } + + while ((dent = readdir(dir)) != NULL) { + if (strcmp(dent->d_name, ".") == 0 || + strcmp(dent->d_name, "..") == 0) + continue; + + (void) snprintf(path, (size_t)path_max, "%s/%s", config_path, + dent->d_name); + if ((fp = fopen(path, "r")) == NULL) { + (*lfun)(LOG_ERR, "%s: Cannot open `%s' (%m)", __func__, + path); + continue; + } + conf_parsefile(fp, path); + fclose(fp); + } + + free(path); +} + +void +conf_parse(const char *config_path) +{ + char *path; + DIR *dir; + FILE *fp; + + if ((dir = opendir(config_path)) != NULL) { + /* + * If config_path is a directory, parse the configuration files + * in the directory. Then we're done here. + */ + conf_parsedir(dir, config_path); + closedir(dir); + goto out; + } else if ((fp = fopen(config_path, "r")) != NULL) { + /* If config_path is a file, parse it. */ + conf_parsefile(fp, config_path); + fclose(fp); + } + + /* + * Append ".d" to config_path, and if that is a directory, parse the + * configuration files in the directory. + */ + if (asprintf(&path, "%s.d", config_path) < 0) { + (*lfun)(LOG_ERR, "%s: Failed to allocate memory for path (%m)", + __func__); + goto out; + } + + if ((dir = opendir(path)) != NULL) { + conf_parsedir(dir, path); + closedir(dir); + } + free(path); + +out: + if (dir == NULL && fp == NULL) { + (*lfun)(LOG_ERR, "%s: Cannot open `%s' (%m)", __func__, + config_path); + return; + } - confset_replace(&rconf, &rc); - confset_replace(&lconf, &lc); + confset_sort(&lconf); + confset_sort(&rconf); if (debug) { confset_list(&lconf, "local", "target"); diff --git a/contrib/blocklist/bin/conf.h b/contrib/blocklist/bin/conf.h index 03f1942e3e32..8e4cd3a41fae 100644 --- a/contrib/blocklist/bin/conf.h +++ b/contrib/blocklist/bin/conf.h @@ -1,4 +1,4 @@ -/* $NetBSD: conf.h,v 1.6 2015/01/27 19:40:36 christos Exp $ */ +/* $NetBSD: conf.h,v 1.2 2025/02/05 20:09:33 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -34,6 +34,7 @@ #include <sys/socket.h> struct conf { + size_t c_lineno; struct sockaddr_storage c_ss; int c_lmask; int c_port; diff --git a/contrib/blocklist/bin/internal.c b/contrib/blocklist/bin/internal.c index 5c039e4dc5d2..625de55928d8 100644 --- a/contrib/blocklist/bin/internal.c +++ b/contrib/blocklist/bin/internal.c @@ -1,4 +1,4 @@ -/* $NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $ */ +/* $NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $"); +#endif +__RCSID("$NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #include <stdio.h> #include <syslog.h> @@ -41,7 +43,7 @@ __RCSID("$NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $"); #include "internal.h" int debug; -const char *rulename = "blacklistd"; +const char *rulename = "blocklistd"; const char *controlprog = _PATH_BLCONTROL; struct confset lconf, rconf; struct ifaddrs *ifas; diff --git a/contrib/blocklist/bin/internal.h b/contrib/blocklist/bin/internal.h index 5a40e49fbbd5..553320e7afd5 100644 --- a/contrib/blocklist/bin/internal.h +++ b/contrib/blocklist/bin/internal.h @@ -1,4 +1,4 @@ -/* $NetBSD: internal.h,v 1.14 2016/04/04 15:52:56 christos Exp $ */ +/* $NetBSD: internal.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,13 +32,13 @@ #define _INTERNAL_H #ifndef _PATH_BLCONF -#define _PATH_BLCONF "/etc/blacklistd.conf" +#define _PATH_BLCONF "/etc/blocklistd.conf" #endif #ifndef _PATH_BLCONTROL -#define _PATH_BLCONTROL "/libexec/blacklistd-helper" +#define _PATH_BLCONTROL "/usr/libexec/blocklistd-helper" #endif #ifndef _PATH_BLSTATE -#define _PATH_BLSTATE "/var/db/blacklistd.db" +#define _PATH_BLSTATE "/var/db/blocklistd.db" #endif extern struct confset rconf, lconf; diff --git a/contrib/blocklist/bin/old_internal.c b/contrib/blocklist/bin/old_internal.c new file mode 100644 index 000000000000..79093cc8b8ab --- /dev/null +++ b/contrib/blocklist/bin/old_internal.c @@ -0,0 +1,50 @@ +/* $NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); + +#include <stdio.h> +#include <syslog.h> +#include "conf.h" +#include "old_internal.h" + +int debug; +const char *rulename = "blacklistd"; +const char *controlprog = _PATH_BLCONTROL; +struct confset lconf, rconf; +struct ifaddrs *ifas; +void (*lfun)(int, const char *, ...) = syslog; diff --git a/contrib/blocklist/bin/old_internal.h b/contrib/blocklist/bin/old_internal.h new file mode 100644 index 000000000000..becee563e81d --- /dev/null +++ b/contrib/blocklist/bin/old_internal.h @@ -0,0 +1,58 @@ +/* $NetBSD: internal.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _OLD_INTERNAL_H +#define _OLD_INTERNAL_H + +#ifndef _PATH_BLCONF +#define _PATH_BLCONF "/etc/blacklistd.conf" +#endif +#ifndef _PATH_BLCONTROL +#define _PATH_BLCONTROL "/usr/libexec/blacklistd-helper" +#endif +#ifndef _PATH_BLSTATE +/* We want the new name, the old one would be incompatible after 24932b6 */ +#define _PATH_BLSTATE "/var/db/blocklistd.db" +#endif + +extern struct confset rconf, lconf; +extern int debug; +extern const char *rulename; +extern const char *controlprog; +extern struct ifaddrs *ifas; + +#if !defined(__syslog_attribute__) && !defined(__syslog__) +#define __syslog__ __printf__ +#endif + +extern void (*lfun)(int, const char *, ...) + __attribute__((__format__(__syslog__, 2, 3))); + +#endif /* _OLD_INTERNAL_H */ diff --git a/contrib/blocklist/bin/run.c b/contrib/blocklist/bin/run.c index 5588f0198c04..adcc407e65c6 100644 --- a/contrib/blocklist/bin/run.c +++ b/contrib/blocklist/bin/run.c @@ -1,4 +1,4 @@ -/* $NetBSD: run.c,v 1.14 2016/04/04 15:52:56 christos Exp $ */ +/* $NetBSD: run.c,v 1.3 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: run.c,v 1.14 2016/04/04 15:52:56 christos Exp $"); +#endif +__RCSID("$NetBSD: run.c,v 1.3 2025/02/11 17:48:30 christos Exp $"); #include <stdio.h> #ifdef HAVE_LIBUTIL_H @@ -131,7 +133,8 @@ run_change(const char *how, const struct conf *c, char *id, size_t len) prname = "udp"; break; default: - (*lfun)(LOG_ERR, "%s: bad protocol %d", __func__, c->c_proto); + (*lfun)(LOG_ERR, "%s: bad protocol %d (line %zu)", __func__, + c->c_proto, c->c_lineno); return -1; } diff --git a/contrib/blocklist/bin/run.h b/contrib/blocklist/bin/run.h index bafc3e554690..da21906e0db6 100644 --- a/contrib/blocklist/bin/run.h +++ b/contrib/blocklist/bin/run.h @@ -1,4 +1,4 @@ -/* $NetBSD: run.h,v 1.5 2015/01/27 19:40:37 christos Exp $ */ +/* $NetBSD: run.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. diff --git a/contrib/blocklist/bin/state.c b/contrib/blocklist/bin/state.c index f2622c82c251..08e2622e223f 100644 --- a/contrib/blocklist/bin/state.c +++ b/contrib/blocklist/bin/state.c @@ -1,4 +1,4 @@ -/* $NetBSD: state.c,v 1.19 2016/09/26 19:43:43 christos Exp $ */ +/* $NetBSD: state.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: state.c,v 1.19 2016/09/26 19:43:43 christos Exp $"); +#endif +__RCSID("$NetBSD: state.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #include <sys/types.h> #include <sys/socket.h> diff --git a/contrib/blocklist/bin/state.h b/contrib/blocklist/bin/state.h index 2e9257006e80..48f63a41ef33 100644 --- a/contrib/blocklist/bin/state.h +++ b/contrib/blocklist/bin/state.h @@ -1,4 +1,4 @@ -/* $NetBSD: state.h,v 1.5 2015/01/27 19:40:37 christos Exp $ */ +/* $NetBSD: state.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. diff --git a/contrib/blocklist/bin/support.c b/contrib/blocklist/bin/support.c index d560d2303223..91e40812611e 100644 --- a/contrib/blocklist/bin/support.c +++ b/contrib/blocklist/bin/support.c @@ -1,4 +1,4 @@ -/* $NetBSD: support.c,v 1.9 2018/09/18 22:12:19 christos Exp $ */ +/* $NetBSD: support.c,v 1.3 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: support.c,v 1.9 2018/09/18 22:12:19 christos Exp $"); +#endif +__RCSID("$NetBSD: support.c,v 1.3 2025/02/11 17:48:30 christos Exp $"); #include <time.h> #include <string.h> @@ -66,7 +68,8 @@ expandm(char *buf, size_t len, const char *fmt) } void -vdlog(int level __unused, const char *fmt, va_list ap) +vdlog(int level __unused, struct syslog_data *sd __unused, + const char *fmt, va_list ap) { char buf[BUFSIZ]; @@ -81,7 +84,7 @@ dlog(int level, const char *fmt, ...) va_list ap; va_start(ap, fmt); - vdlog(level, fmt, ap); + vdlog(level, NULL, fmt, ap); va_end(ap); } diff --git a/contrib/blocklist/bin/support.h b/contrib/blocklist/bin/support.h index 899649ce8319..bb865cb8fe68 100644 --- a/contrib/blocklist/bin/support.h +++ b/contrib/blocklist/bin/support.h @@ -1,4 +1,4 @@ -/* $NetBSD: support.h,v 1.7 2016/04/04 15:52:56 christos Exp $ */ +/* $NetBSD: support.h,v 1.2 2024/08/02 17:11:55 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -34,8 +34,9 @@ __BEGIN_DECLS const char *fmttime(char *, size_t, time_t); const char *fmtydhms(char *, size_t, time_t); -void vdlog(int, const char *, va_list) - __attribute__((__format__(__printf__, 2, 0))); +struct syslog_data; +void vdlog(int, struct syslog_data *, const char *, va_list) + __attribute__((__format__(__printf__, 3, 0))); void dlog(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); ssize_t blhexdump(char *, size_t, const char *, const void *, size_t); diff --git a/contrib/blocklist/diff/ftpd.diff b/contrib/blocklist/diff/ftpd.diff index d28577f3ef5f..37b43dae2295 100644 --- a/contrib/blocklist/diff/ftpd.diff +++ b/contrib/blocklist/diff/ftpd.diff @@ -2,17 +2,17 @@ +++ pfilter.c 2015-01-23 17:12:02.000000000 -0500 @@ -0,0 +1,24 @@ +#include <stdio.h> -+#include <blacklist.h> ++#include <blocklist.h> + +#include "pfilter.h" + -+static struct blacklist *blstate; ++static struct blocklist *blstate; + +void +pfilter_open(void) +{ + if (blstate == NULL) -+ blstate = blacklist_open(); ++ blstate = blocklist_open(); +} + +void @@ -23,7 +23,7 @@ + if (blstate == NULL) + return; + -+ blacklist_r(blstate, what, 0, msg); ++ blocklist_r(blstate, what, 0, msg); +} --- /dev/null 2015-01-23 17:30:40.000000000 -0500 +++ pfilter.h 2015-01-23 17:07:25.000000000 -0500 @@ -42,8 +42,8 @@ diff -u -p -u -r1.63 Makefile MLINKS= ftpusers.5 ftpchroot.5 +SRCS+= pfilter.c -+LDADD+= -lblacklist -+DPADD+= ${LIBBLACKLIST} ++LDADD+= -lblocklist ++DPADD+= ${LIBBLOCKLIST} + .if defined(NO_INTERNAL_LS) CPPFLAGS+=-DNO_INTERNAL_LS diff --git a/contrib/blocklist/diff/named.diff b/contrib/blocklist/diff/named.diff index fcd97ba7ec1f..a5069ff94df7 100644 --- a/contrib/blocklist/diff/named.diff +++ b/contrib/blocklist/diff/named.diff @@ -8,17 +8,17 @@ +#include <named/types.h> +#include <named/client.h> + -+#include <blacklist.h> ++#include <blocklist.h> + +#include "pfilter.h" + -+static struct blacklist *blstate; ++static struct blocklist *blstate; + +void +pfilter_open(void) +{ + if (blstate == NULL) -+ blstate = blacklist_open(); ++ blstate = blocklist_open(); +} + +#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) @@ -39,7 +39,7 @@ + } + if (socket == NULL) + return; -+ blacklist_sa_r(blstate, ++ blocklist_sa_r(blstate, + res != ISC_R_SUCCESS, isc_socket_getfd(socket), + &client->peeraddr.type.sa, client->peeraddr.length, msg); +} @@ -63,8 +63,8 @@ diff -u -u -r1.8 Makefile + pfilter.c tkeyconf.c tsigconf.c \ update.c xfrout.c zoneconf.c ${SRCS_UNIX} -+LDADD+=-lblacklist -+DPADD+=${LIBBLACKLIST} ++LDADD+=-lblocklist ++DPADD+=${LIBBLOCKLIST} .include <bsd.prog.mk> Index: dist/bin/named/client.c =================================================================== diff --git a/contrib/blocklist/diff/postfix.diff b/contrib/blocklist/diff/postfix.diff new file mode 100644 index 000000000000..6f14389515cf --- /dev/null +++ b/contrib/blocklist/diff/postfix.diff @@ -0,0 +1,98 @@ +Index: dist/src/smtpd/pfilter.c +=================================================================== +RCS file: dist/src/smtpd/pfilter.c +diff -N dist/src/smtpd/pfilter.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ dist/src/smtpd/pfilter.c 1 Feb 2018 03:29:09 -0000 +@@ -0,0 +1,19 @@ ++#include "pfilter.h" ++#include <stdio.h> /* for NULL */ ++#include <blocklist.h> ++ ++static struct blocklist *blstate; ++ ++void ++pfilter_notify(int a, int fd) ++{ ++ if (blstate == NULL) ++ blstate = blocklist_open(); ++ if (blstate == NULL) ++ return; ++ (void)blocklist_r(blstate, a, fd, "smtpd"); ++ if (a == 0) { ++ blocklist_close(blstate); ++ blstate = NULL; ++ } ++} +Index: dist/src/smtpd/pfilter.h +=================================================================== +RCS file: dist/src/smtpd/pfilter.h +diff -N dist/src/smtpd/pfilter.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ dist/src/smtpd/pfilter.h 1 Feb 2018 03:29:09 -0000 +@@ -0,0 +1,2 @@ ++ ++void pfilter_notify(int, int); +Index: dist/src/smtpd/smtpd.c +=================================================================== +RCS file: /cvsroot/src/external/ibm-public/postfix/dist/src/smtpd/smtpd.c,v +retrieving revision 1.14 +diff -u -r1.14 smtpd.c +--- dist/src/smtpd/smtpd.c 14 Feb 2017 01:16:48 -0000 1.14 ++++ dist/src/smtpd/smtpd.c 1 Feb 2018 03:29:09 -0000 +@@ -1197,6 +1197,8 @@ + #include <smtpd_milter.h> + #include <smtpd_expand.h> + ++#include "pfilter.h" ++ + /* + * Tunable parameters. Make sure that there is some bound on the length of + * an SMTP command, so that the mail system stays in control even when a +@@ -5048,6 +5050,7 @@ + if (state->error_count >= var_smtpd_hard_erlim) { + state->reason = REASON_ERROR_LIMIT; + state->error_mask |= MAIL_ERROR_PROTOCOL; ++ pfilter_notify(1, vstream_fileno(state->client)); + smtpd_chat_reply(state, "421 4.7.0 %s Error: too many errors", + var_myhostname); + break; +Index: libexec/smtpd/Makefile +=================================================================== +RCS file: /cvsroot/src/external/ibm-public/postfix/libexec/smtpd/Makefile,v +retrieving revision 1.6 +diff -u -r1.6 Makefile +--- libexec/smtpd/Makefile 21 May 2017 15:28:40 -0000 1.6 ++++ libexec/smtpd/Makefile 1 Feb 2018 03:29:09 -0000 +@@ -13,11 +13,14 @@ + SRCS= smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \ + smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \ + smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c smtpd_resolve.c \ +- smtpd_expand.c smtpd_haproxy.c ++ smtpd_expand.c smtpd_haproxy.c pfilter.c + + DPADD+= ${LIBPMASTER} ${LIBPMILTER} ${LIBPGLOBAL} ${LIBPDNS} ${LIBPXSASL} + LDADD+= ${LIBPMASTER} ${LIBPMILTER} ${LIBPGLOBAL} ${LIBPDNS} ${LIBPXSASL} + ++DPADD+= ${LIBBLOCKLIST} ++LDADD+= -lblocklist ++ + DPADD+= ${LIBPTLS} ${LIBSSL} ${LIBCRYPTO} + LDADD+= ${LIBPTLS} -lssl -lcrypto + +Index: dist/src/smtpd/smtpd.c +=================================================================== +RCS file: /cvsroot/src/external/ibm-public/postfix/dist/src/smtpd/smtpd.c,v +retrieving revision 1.17 +diff -u -u -r1.17 smtpd.c +--- dist/src/smtpd/smtpd.c 18 Mar 2020 19:05:20 -0000 1.17 ++++ dist/src/smtpd/smtpd.c 25 Sep 2020 12:51:52 -0000 +@@ -5795,6 +5795,8 @@ + || strcmp(state->reason, REASON_LOST_CONNECTION)) { + msg_info("%s after %s from %s", + state->reason, state->where, state->namaddr); ++ if (strcmp(state->where, SMTPD_CMD_AUTH) == 0) ++ pfilter_notify(1, vstream_fileno(state->client)); + } + } + diff --git a/contrib/blocklist/diff/proftpd.diff b/contrib/blocklist/diff/proftpd.diff index 455b7cd60c64..e8d2cc5e9e07 100644 --- a/contrib/blocklist/diff/proftpd.diff +++ b/contrib/blocklist/diff/proftpd.diff @@ -1,12 +1,12 @@ --- Make.rules.in.orig 2015-05-27 20:25:54.000000000 -0400 +++ Make.rules.in 2016-01-25 21:48:47.000000000 -0500 @@ -110,3 +110,8 @@ - + FTPWHO_OBJS=ftpwho.o scoreboard.o misc.o BUILD_FTPWHO_OBJS=utils/ftpwho.o utils/scoreboard.o utils/misc.o + -+CPPFLAGS+=-DHAVE_BLACKLIST -+LIBS+=-lblacklist ++CPPFLAGS+=-DHAVE_BLOCKLIST ++LIBS+=-lblocklist +OBJS+= pfilter.o +BUILD_OBJS+= src/pfilter.o --- /dev/null 2016-01-22 17:30:55.000000000 -0500 @@ -84,25 +84,25 @@ +#include "pfilter.h" +#include "conf.h" +#include "privs.h" -+#ifdef HAVE_BLACKLIST -+#include <blacklist.h> ++#ifdef HAVE_BLOCKLIST ++#include <blocklist.h> +#endif + -+static struct blacklist *blstate; ++static struct blocklist *blstate; + +void +pfilter_init(void) +{ -+#ifdef HAVE_BLACKLIST ++#ifdef HAVE_BLOCKLIST + if (blstate == NULL) -+ blstate = blacklist_open(); ++ blstate = blocklist_open(); +#endif +} + +void +pfilter_notify(int a) +{ -+#ifdef HAVE_BLACKLIST ++#ifdef HAVE_BLOCKLIST + conn_t *c = session.c; + int fd; + @@ -119,6 +119,6 @@ + pfilter_init(); + if (blstate == NULL) + return; -+ (void)blacklist_r(blstate, a, fd, "proftpd"); ++ (void)blocklist_r(blstate, a, fd, "proftpd"); +#endif +} diff --git a/contrib/blocklist/diff/ssh.diff b/contrib/blocklist/diff/ssh.diff index 9427fc8ddb36..17300bb5dc8d 100644 --- a/contrib/blocklist/diff/ssh.diff +++ b/contrib/blocklist/diff/ssh.diff @@ -7,14 +7,14 @@ +#include "packet.h" +#include "log.h" +#include "pfilter.h" -+#include <blacklist.h> ++#include <blocklist.h> + -+static struct blacklist *blstate; ++static struct blocklist *blstate; + +void +pfilter_init(void) +{ -+ blstate = blacklist_open(); ++ blstate = blocklist_open(); +} + +void @@ -27,9 +27,9 @@ + return; + // XXX: 3? + fd = packet_connection_is_on_socket() ? packet_get_connection_in() : 3; -+ (void)blacklist_r(blstate, a, fd, "ssh"); ++ (void)blocklist_r(blstate, a, fd, "ssh"); + if (a == 0) { -+ blacklist_close(blstate); ++ blocklist_close(blstate); + blstate = NULL; + } +} @@ -60,8 +60,8 @@ diff -u -u -r1.10 Makefile LDADD+= -lwrap DPADD+= ${LIBWRAP} + -+LDADD+= -lblacklist -+DPADD+= ${LIBBLACKLIST} ++LDADD+= -lblocklist ++DPADD+= ${LIBBLOCKLIST} diff -ru openssh-7.7p1/auth-pam.c dist/auth-pam.c --- openssh-7.7p1/auth-pam.c 2018-04-02 01:38:28.000000000 -0400 +++ dist/auth-pam.c 2018-05-23 11:56:22.206661484 -0400 diff --git a/contrib/blocklist/etc/Makefile b/contrib/blocklist/etc/Makefile index 669528ddca89..f4f2dc79f857 100644 --- a/contrib/blocklist/etc/Makefile +++ b/contrib/blocklist/etc/Makefile @@ -1,10 +1,10 @@ -# $NetBSD: Makefile,v 1.3 2015/01/26 00:18:40 christos Exp $ +# $NetBSD: Makefile,v 1.2 2025/02/05 20:24:26 christos Exp $ -SUBDIR=rc.d +SUBDIR= rc.d -FILESDIR= /usr/share/examples/blacklist -FILESMODE= 644 -FILES= blacklistd.conf npf.conf +FILESDIR= /usr/share/examples/blocklist +FILESMODE= 644 +FILES= blocklistd.conf ipf.conf npf.conf .include <bsd.files.mk> .include <bsd.subdir.mk> diff --git a/contrib/blocklist/etc/blacklistd.conf b/contrib/blocklist/etc/blocklistd.conf index f061b004ad36..b52b994fe950 100644 --- a/contrib/blocklist/etc/blacklistd.conf +++ b/contrib/blocklist/etc/blocklistd.conf @@ -1,5 +1,5 @@ -# Blacklist rule -# adr/mask:port type proto owner name nfail disable +# Blocklist rule +# adr/mask:port type proto owner name nfail duration [local] ssh stream * * * 3 6h ftp stream * * * 3 6h @@ -7,8 +7,9 @@ domain * * named * 3 12h #6161 stream tcp6 christos * 2 10m * * * * * 3 60 -# adr/mask:port type proto owner name nfail disable +# adr/mask:port type proto owner name nfail duration [remote] #129.168.0.0/16 * * * = * * +#[2001:db8::]/32:ssh * * * = * * #6161 = = = =/24 = = #* stream tcp * = = = diff --git a/contrib/blocklist/etc/ipf.conf b/contrib/blocklist/etc/ipf.conf new file mode 100644 index 000000000000..f6bec74238d6 --- /dev/null +++ b/contrib/blocklist/etc/ipf.conf @@ -0,0 +1,45 @@ +#======================================== +# +# subsection for abuse blocking +# +#======================================== +# +# This section should be included early in the main /etc/ipf.conf file, right +# after any basic generic accounting ("count") rules, and any cleanup rules to +# block invalid fragments, invalid options (e.g. "ssrr"), etc. +# +# Note these will not actually block anything since they don't include the +# "quick" flag, and are thus part of a last-match group. They simply set up a +# group such that any connection logging rule further below won't also match if +# one of the rules in the group matches, no matter when or where the subsequent +# matching rule is added. I.e. all rules in the group are checked for a match +# (and a possible "first match" with "quick") before any subsequent rules +# further below are used. Note group rules can be added at any time, including +# at runtime after all other rules have been added -- they will still belong to +# the group and once added will be checked as part of the group. +# +# head of "blocklistd" group: +# +# The "blocklistd" group will be used by blocklistd(8). +# +block in proto tcp/udp from any to any head blocklistd +# +# head of "attackers" group to block all attackers: +# +# The "attackers" group is intended to be used for manually maintained rules +# e.g. as could be added like this: +# +# echo 'block return-rst in log quick proto tcp from 118.136.0.0/15 to any flags S/SAFR group attackers' >> /etc/ipf.conf +# /etc/rc.d/ipfliter reload +# +# Note the choice in this example is to return RST packets for blocked SYN +# packets to help the other end close. This is not necessary, but it better +# mimics what the kernel does by default, thus perhaps hiding the fact a +# firewall is present. +# +# XXX This example still allows UDP services, but we would need to duplicate +# each rule with "proto udp" (and without "flags blah") due to IPF parsing +# limitations.... +# +block in proto tcp/udp from any to any head attackers +# diff --git a/contrib/blocklist/etc/npf.conf b/contrib/blocklist/etc/npf.conf index 42d56044ad6e..b1c33f2738f0 100644 --- a/contrib/blocklist/etc/npf.conf +++ b/contrib/blocklist/etc/npf.conf @@ -1,4 +1,4 @@ -# Transparent firewall example for blacklistd +# Transparent firewall example for blocklistd $ext_if = "bnx0" @@ -6,7 +6,7 @@ set bpf.jit on; alg "icmp" group "external" on $ext_if { - ruleset "blacklistd" + ruleset "blocklistd" pass final all } diff --git a/contrib/blocklist/etc/rc.d/Makefile b/contrib/blocklist/etc/rc.d/Makefile index e863d0853a0f..9e214984f7c2 100644 --- a/contrib/blocklist/etc/rc.d/Makefile +++ b/contrib/blocklist/etc/rc.d/Makefile @@ -1,6 +1,6 @@ -# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ -SCRIPTS=blacklistd +SCRIPTS=blocklistd SCRIPTSDIR=/etc/rc.d .include <bsd.prog.mk> diff --git a/contrib/blocklist/etc/rc.d/blacklistd b/contrib/blocklist/etc/rc.d/blocklistd index 278a6742e63c..89871ebda4a0 100644 --- a/contrib/blocklist/etc/rc.d/blacklistd +++ b/contrib/blocklist/etc/rc.d/blocklistd @@ -1,15 +1,15 @@ #!/bin/sh # -# $NetBSD: blacklistd,v 1.2 2016/10/17 22:47:16 christos Exp $ +# $NetBSD: blocklistd,v 1.2 2021/03/07 00:46:39 christos Exp $ # -# PROVIDE: blacklistd -# REQUIRE: npf +# PROVIDE: blocklistd +# REQUIRE: npf pf ipfilter # BEFORE: SERVERS $_rc_subr_loaded . /etc/rc.subr -name="blacklistd" +name="blocklistd" rcvar=$name command="/sbin/${name}" pidfile="/var/run/${name}.pid" @@ -18,17 +18,17 @@ start_precmd="${name}_precmd" extra_commands="reload" _sockfile="/var/run/${name}.sockets" -_sockname="blacklistd.sock" +_sockname="blocklistd.sock" -blacklistd_precmd() +blocklistd_precmd() { - # Create default list of blacklistd sockets to watch + # Create default list of blocklistd sockets to watch # ( umask 022 ; > $_sockfile ) # Find /etc/rc.d scripts with "chrootdir" rcorder(8) keyword, # and if $${app}_chrootdir is a directory, add appropriate - # blacklistd socket to list of sockets to watch. + # blocklistd socket to list of sockets to watch. # for _lr in $(rcorder -k chrootdir /etc/rc.d/*); do ( @@ -42,8 +42,8 @@ blacklistd_precmd() done # If other sockets have been provided, change run_rc_command()'s - # internal copy of $blacklistd_flags to force use of specific - # blacklistd sockets. + # internal copy of $blocklistd_flags to force use of specific + # blocklistd sockets. # if [ -s $_sockfile ]; then echo "/var/run/${_sockname}" >> $_sockfile diff --git a/contrib/blocklist/include/Makefile b/contrib/blocklist/include/Makefile index 6854907be25e..b7ce1eca278c 100644 --- a/contrib/blocklist/include/Makefile +++ b/contrib/blocklist/include/Makefile @@ -1,10 +1,10 @@ -# $NetBSD: Makefile,v 1.1 2015/01/21 16:16:00 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ # Doing a make includes builds /usr/include NOOBJ= # defined -INCS= blacklist.h +INCS= blocklist.h INCSDIR= /usr/include .include <bsd.prog.mk> diff --git a/contrib/blocklist/include/bl.h b/contrib/blocklist/include/bl.h index 8f366de912fe..c7ed517d7a6d 100644 --- a/contrib/blocklist/include/bl.h +++ b/contrib/blocklist/include/bl.h @@ -1,4 +1,4 @@ -/* $NetBSD: bl.h,v 1.13 2016/03/11 17:16:40 christos Exp $ */ +/* $NetBSD: bl.h,v 1.2 2024/08/02 17:11:55 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ #include <stdarg.h> #include <sys/param.h> #include <sys/socket.h> -#include "blacklist.h" +#include "blocklist.h" typedef enum { BL_INVALID, @@ -58,14 +58,15 @@ typedef struct { #define bi_cred bi_u._bi_cred #ifndef _PATH_BLSOCK -#define _PATH_BLSOCK "/var/run/blacklistd.sock" +#define _PATH_BLSOCK "/var/run/blocklistd.sock" #endif __BEGIN_DECLS -typedef struct blacklist *bl_t; +typedef struct blocklist *bl_t; -bl_t bl_create(bool, const char *, void (*)(int, const char *, va_list)); +bl_t bl_create(bool, const char *, + void (*)(int, struct syslog_data *, const char *, va_list)); void bl_destroy(bl_t); int bl_send(bl_t, bl_type_t, int, const struct sockaddr *, socklen_t, const char *); diff --git a/contrib/blocklist/include/blacklist.h b/contrib/blocklist/include/blacklist.h index 2f5c8ba09864..f97cf34c4bcb 100644 --- a/contrib/blocklist/include/blacklist.h +++ b/contrib/blocklist/include/blacklist.h @@ -1,4 +1,4 @@ -/* $NetBSD: blacklist.h,v 1.3 2015/01/23 18:48:56 christos Exp $ */ +/* $NetBSD: blocklist.h,v 1.4 2025/02/11 17:42:17 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,16 +32,26 @@ #define _BLACKLIST_H #include <sys/socket.h> +#include <syslog.h> -__BEGIN_DECLS +#if defined(__cplusplus) +extern "C" { +#endif + +struct syslog_data; struct blacklist *blacklist_open(void); +struct blacklist *blacklist_open2( + void (*)(int, struct syslog_data *, const char *, va_list)); void blacklist_close(struct blacklist *); int blacklist(int, int, const char *); int blacklist_r(struct blacklist *, int, int, const char *); int blacklist_sa(int, int, const struct sockaddr *, socklen_t, const char *); int blacklist_sa_r(struct blacklist *, int, int, const struct sockaddr *, socklen_t, const char *); -__END_DECLS + +#if defined(__cplusplus) +} +#endif /* action values for user applications */ #define BLACKLIST_API_ENUM 1 diff --git a/contrib/blocklist/include/blocklist.h b/contrib/blocklist/include/blocklist.h new file mode 100644 index 000000000000..f09e5139079b --- /dev/null +++ b/contrib/blocklist/include/blocklist.h @@ -0,0 +1,65 @@ +/* $NetBSD: blocklist.h,v 1.4 2025/02/11 17:42:17 christos Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _BLOCKLIST_H +#define _BLOCKLIST_H + +#include <sys/socket.h> +#include <syslog.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +struct syslog_data; +struct blocklist *blocklist_open(void); +struct blocklist *blocklist_open2( + void (*)(int, struct syslog_data *, const char *, va_list)); +void blocklist_close(struct blocklist *); +int blocklist(int, int, const char *); +int blocklist_r(struct blocklist *, int, int, const char *); +int blocklist_sa(int, int, const struct sockaddr *, socklen_t, const char *); +int blocklist_sa_r(struct blocklist *, int, int, + const struct sockaddr *, socklen_t, const char *); + +#if defined(__cplusplus) +} +#endif + +/* action values for user applications */ +#define BLOCKLIST_API_ENUM 1 +enum { + BLOCKLIST_AUTH_OK = 0, + BLOCKLIST_AUTH_FAIL, + BLOCKLIST_ABUSIVE_BEHAVIOR, + BLOCKLIST_BAD_USER +}; + +#endif /* _BLOCKLIST_H */ diff --git a/contrib/blocklist/include/old_bl.h b/contrib/blocklist/include/old_bl.h new file mode 100644 index 000000000000..1ab64a4d9b69 --- /dev/null +++ b/contrib/blocklist/include/old_bl.h @@ -0,0 +1,80 @@ +/* $NetBSD: bl.h,v 1.2 2024/08/02 17:11:55 christos Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _OLD_BL_H +#define _OLD_BL_H + +#include <stdbool.h> +#include <stdarg.h> +#include <sys/param.h> +#include <sys/socket.h> +#include "blacklist.h" + +typedef enum { + BL_INVALID, + BL_ADD, + BL_DELETE, + BL_ABUSE, + BL_BADUSER +} bl_type_t; + +typedef struct { + bl_type_t bi_type; + int bi_fd; + uid_t bi_uid; + gid_t bi_gid; + socklen_t bi_slen; + struct sockaddr_storage bi_ss; + char bi_msg[1024]; +} bl_info_t; + +#define bi_cred bi_u._bi_cred + +/* We want the new name */ +#ifndef _PATH_BLSOCK +#define _PATH_BLSOCK "/var/run/blocklistd.sock" +#endif + +__BEGIN_DECLS + +typedef struct blacklist *bl_t; + +bl_t bl_create(bool, const char *, + void (*)(int, struct syslog_data *, const char *, va_list)); +void bl_destroy(bl_t); +int bl_send(bl_t, bl_type_t, int, const struct sockaddr *, socklen_t, + const char *); +int bl_getfd(bl_t); +bl_info_t *bl_recv(bl_t); +bool bl_isconnected(bl_t); + +__END_DECLS + +#endif /* _OLD_BL_H */ diff --git a/contrib/blocklist/lib/Makefile b/contrib/blocklist/lib/Makefile index 4f1ab7717a99..147f311c4782 100644 --- a/contrib/blocklist/lib/Makefile +++ b/contrib/blocklist/lib/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.7 2019/03/08 20:40:05 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ .include <bsd.own.mk> @@ -6,14 +6,14 @@ USE_SHLIBDIR= yes CPPFLAGS+=-D_REENTRANT #LIBDPLIBS+=pthread ${NETBSDSRCDIR}/lib/libpthread -LIB=blacklist -SRCS=bl.c blacklist.c -MAN=libblacklist.3 -MLINKS+=libblacklist.3 blacklist_open.3 -MLINKS+=libblacklist.3 blacklist_close.3 -MLINKS+=libblacklist.3 blacklist.3 -MLINKS+=libblacklist.3 blacklist_r.3 -MLINKS+=libblacklist.3 blacklist_sa.3 -MLINKS+=libblacklist.3 blacklist_sa_r.3 +LIB=blocklist +SRCS=bl.c blocklist.c +MAN=libblocklist.3 +MLINKS+=libblocklist.3 blocklist_open.3 +MLINKS+=libblocklist.3 blocklist_close.3 +MLINKS+=libblocklist.3 blocklist.3 +MLINKS+=libblocklist.3 blocklist_r.3 +MLINKS+=libblocklist.3 blocklist_sa.3 +MLINKS+=libblocklist.3 blocklist_sa_r.3 .include <bsd.lib.mk> diff --git a/contrib/blocklist/lib/bl.c b/contrib/blocklist/lib/bl.c index 409317bc3fc0..80396ed12b28 100644 --- a/contrib/blocklist/lib/bl.c +++ b/contrib/blocklist/lib/bl.c @@ -1,4 +1,4 @@ -/* $NetBSD: bl.c,v 1.28 2016/07/29 17:13:09 christos Exp $ */ +/* $NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: bl.c,v 1.28 2016/07/29 17:13:09 christos Exp $"); +#endif +__RCSID("$NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -57,6 +59,10 @@ __RCSID("$NetBSD: bl.c,v 1.28 2016/07/29 17:13:09 christos Exp $"); #include <pthread.h> #endif +#if defined(SO_RECVUCRED) +#include <ucred.h> +#endif + #include "bl.h" typedef struct { @@ -68,7 +74,7 @@ typedef struct { char bl_data[]; } bl_message_t; -struct blacklist { +struct blocklist { #ifdef _REENTRANT pthread_mutex_t b_mutex; # define BL_INIT(b) pthread_mutex_init(&b->b_mutex, NULL) @@ -82,7 +88,8 @@ struct blacklist { int b_fd; int b_connected; struct sockaddr_un b_sun; - void (*b_fun)(int, const char *, va_list); + struct syslog_data b_syslog_data; + void (*b_fun)(int, struct syslog_data *, const char *, va_list); bl_info_t b_info; }; @@ -115,14 +122,16 @@ bl_reset(bl_t b, bool locked) } static void -bl_log(void (*fun)(int, const char *, va_list), int level, - const char *fmt, ...) +bl_log(bl_t b, int level, const char *fmt, ...) { va_list ap; int serrno = errno; + if (b->b_fun == NULL) + return; + va_start(ap, fmt); - (*fun)(level, fmt, ap); + (*b->b_fun)(level, &b->b_syslog_data, fmt, ap); va_end(ap); errno = serrno; } @@ -152,7 +161,7 @@ bl_init(bl_t b, bool srv) b->b_fd = socket(PF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NOSIGPIPE, 0); if (b->b_fd == -1) { - bl_log(b->b_fun, LOG_ERR, "%s: socket failed (%s)", + bl_log(b, LOG_ERR, "%s: socket failed (%s)", __func__, strerror(errno)); BL_UNLOCK(b); return -1; @@ -186,7 +195,7 @@ bl_init(bl_t b, bool srv) rv = connect(b->b_fd, (const void *)sun, (socklen_t)sizeof(*sun)); if (rv == 0) { if (srv) { - bl_log(b->b_fun, LOG_ERR, + bl_log(b, LOG_ERR, "%s: another daemon is handling `%s'", __func__, sun->sun_path); goto out; @@ -199,7 +208,7 @@ bl_init(bl_t b, bool srv) * and only log once. */ if (b->b_connected != 1) { - bl_log(b->b_fun, LOG_DEBUG, + bl_log(b, LOG_DEBUG, "%s: connect failed for `%s' (%s)", __func__, sun->sun_path, strerror(errno)); b->b_connected = 1; @@ -207,8 +216,7 @@ bl_init(bl_t b, bool srv) BL_UNLOCK(b); return -1; } - bl_log(b->b_fun, LOG_DEBUG, "Connected to blacklist server", - __func__); + bl_log(b, LOG_DEBUG, "Connected to blocklist server", __func__); } if (srv) { @@ -219,8 +227,7 @@ bl_init(bl_t b, bool srv) (void)umask(om); errno = serrno; if (rv == -1) { - bl_log(b->b_fun, LOG_ERR, - "%s: bind failed for `%s' (%s)", + bl_log(b, LOG_ERR, "%s: bind failed for `%s' (%s)", __func__, sun->sun_path, strerror(errno)); goto out; } @@ -231,8 +238,8 @@ bl_init(bl_t b, bool srv) #if defined(LOCAL_CREDS) #define CRED_LEVEL 0 #define CRED_NAME LOCAL_CREDS -#define CRED_SC_UID sc_euid -#define CRED_SC_GID sc_egid +#define CRED_SC_UID(x) (x)->sc_euid +#define CRED_SC_GID(x) (x)->sc_egid #define CRED_MESSAGE SCM_CREDS #define CRED_SIZE SOCKCREDSIZE(NGROUPS_MAX) #define CRED_TYPE struct sockcred @@ -240,12 +247,21 @@ bl_init(bl_t b, bool srv) #elif defined(SO_PASSCRED) #define CRED_LEVEL SOL_SOCKET #define CRED_NAME SO_PASSCRED -#define CRED_SC_UID uid -#define CRED_SC_GID gid +#define CRED_SC_UID(x) (x)->uid +#define CRED_SC_GID(x) (x)->gid #define CRED_MESSAGE SCM_CREDENTIALS #define CRED_SIZE sizeof(struct ucred) #define CRED_TYPE struct ucred #define GOT_CRED 2 +#elif defined(SO_RECVUCRED) +#define CRED_LEVEL SOL_SOCKET +#define CRED_NAME SO_RECVUCRED +#define CRED_SC_UID(x) ucred_geteuid(x) +#define CRED_SC_GID(x) ucred_getegid(x) +#define CRED_MESSAGE SCM_UCRED +#define CRED_SIZE ucred_size() +#define CRED_TYPE ucred_t +#define GOT_CRED 2 #else #define GOT_CRED 0 /* @@ -259,7 +275,7 @@ bl_init(bl_t b, bool srv) #ifdef CRED_LEVEL if (setsockopt(b->b_fd, CRED_LEVEL, CRED_NAME, &one, (socklen_t)sizeof(one)) == -1) { - bl_log(b->b_fun, LOG_ERR, "%s: setsockopt %s " + bl_log(b, LOG_ERR, "%s: setsockopt %s " "failed (%s)", __func__, __STRING(CRED_NAME), strerror(errno)); goto out; @@ -275,12 +291,15 @@ out: } bl_t -bl_create(bool srv, const char *path, void (*fun)(int, const char *, va_list)) +bl_create(bool srv, const char *path, + void (*fun)(int, struct syslog_data *, const char *, va_list)) { + static struct syslog_data sd = SYSLOG_DATA_INIT; bl_t b = calloc(1, sizeof(*b)); if (b == NULL) - goto out; - b->b_fun = fun == NULL ? vsyslog : fun; + return NULL; + b->b_fun = fun; + b->b_syslog_data = sd; b->b_fd = -1; b->b_connected = -1; BL_INIT(b); @@ -295,11 +314,6 @@ bl_create(bool srv, const char *path, void (*fun)(int, const char *, va_list)) bl_init(b, srv); return b; -out: - free(b); - bl_log(fun, LOG_ERR, "%s: malloc failed (%s)", __func__, - strerror(errno)); - return NULL; } void @@ -327,7 +341,7 @@ bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, family = AF_INET6; break; default: - bl_log(b->b_fun, LOG_ERR, "%s: invalid socket len %u (%s)", + bl_log(b, LOG_ERR, "%s: invalid socket len %u (%s)", __func__, (unsigned)slen, ctx); errno = EINVAL; return -1; @@ -336,7 +350,7 @@ bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, memcpy(ss, sa, slen); if (ss->ss_family != family) { - bl_log(b->b_fun, LOG_INFO, + bl_log(b, LOG_INFO, "%s: correcting socket family %d to %d (%s)", __func__, ss->ss_family, family, ctx); ss->ss_family = family; @@ -344,7 +358,7 @@ bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN if (ss->ss_len != slen) { - bl_log(b->b_fun, LOG_INFO, + bl_log(b, LOG_INFO, "%s: correcting socket len %u to %u (%s)", __func__, ss->ss_len, (unsigned)slen, ctx); ss->ss_len = (uint8_t)slen; @@ -424,10 +438,11 @@ bl_recv(bl_t b) union { char ctrl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(CRED_SIZE)]; uint32_t fd; - CRED_TYPE sc; } ua; struct cmsghdr *cmsg; +#if GOT_CRED != 0 CRED_TYPE *sc; +#endif union { bl_message_t bl; char buf[512]; @@ -450,18 +465,18 @@ bl_recv(bl_t b) msg.msg_flags = 0; msg.msg_control = ua.ctrl; - msg.msg_controllen = sizeof(ua.ctrl) + 100; + msg.msg_controllen = sizeof(ua.ctrl); rlen = recvmsg(b->b_fd, &msg, 0); if (rlen == -1) { - bl_log(b->b_fun, LOG_ERR, "%s: recvmsg failed (%s)", __func__, + bl_log(b, LOG_ERR, "%s: recvmsg failed (%s)", __func__, strerror(errno)); return NULL; } for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level != SOL_SOCKET) { - bl_log(b->b_fun, LOG_ERR, + bl_log(b, LOG_ERR, "%s: unexpected cmsg_level %d", __func__, cmsg->cmsg_level); continue; @@ -469,10 +484,15 @@ bl_recv(bl_t b) switch (cmsg->cmsg_type) { case SCM_RIGHTS: if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { - bl_log(b->b_fun, LOG_ERR, + int *fd = (void *)CMSG_DATA(cmsg); + size_t len = cmsg->cmsg_len / sizeof(int); + bl_log(b, LOG_ERR, "%s: unexpected cmsg_len %d != %zu", __func__, cmsg->cmsg_len, - CMSG_LEN(2 * sizeof(int))); + CMSG_LEN(sizeof(int))); + + for (size_t i = 0; i < len; i++) + (void)close(fd[i]); continue; } memcpy(&bi->bi_fd, CMSG_DATA(cmsg), sizeof(bi->bi_fd)); @@ -481,13 +501,13 @@ bl_recv(bl_t b) #ifdef CRED_MESSAGE case CRED_MESSAGE: sc = (void *)CMSG_DATA(cmsg); - bi->bi_uid = sc->CRED_SC_UID; - bi->bi_gid = sc->CRED_SC_GID; + bi->bi_uid = CRED_SC_UID(sc); + bi->bi_gid = CRED_SC_GID(sc); got |= GOT_CRED; break; #endif default: - bl_log(b->b_fun, LOG_ERR, + bl_log(b, LOG_ERR, "%s: unexpected cmsg_type %d", __func__, cmsg->cmsg_type); continue; @@ -496,7 +516,7 @@ bl_recv(bl_t b) } if (got != (GOT_CRED|GOT_FD)) { - bl_log(b->b_fun, LOG_ERR, "message missing %s %s", + bl_log(b, LOG_ERR, "message missing %s %s", #if GOT_CRED != 0 (got & GOT_CRED) == 0 ? "cred" : #endif @@ -506,13 +526,13 @@ bl_recv(bl_t b) rem = (size_t)rlen; if (rem < sizeof(ub.bl)) { - bl_log(b->b_fun, LOG_ERR, "message too short %zd", rlen); + bl_log(b, LOG_ERR, "message too short %zd", rlen); return NULL; } rem -= sizeof(ub.bl); if (ub.bl.bl_version != BL_VERSION) { - bl_log(b->b_fun, LOG_ERR, "bad version %d", ub.bl.bl_version); + bl_log(b, LOG_ERR, "bad version %d", ub.bl.bl_version); return NULL; } @@ -523,10 +543,12 @@ bl_recv(bl_t b) bi->bi_uid = -1; bi->bi_gid = -1; #endif - rem = MIN(sizeof(bi->bi_msg), rem); if (rem == 0) bi->bi_msg[0] = '\0'; - else - strlcpy(bi->bi_msg, ub.bl.bl_data, rem); + else { + rem = MIN(sizeof(bi->bi_msg) - 1, rem); + memcpy(bi->bi_msg, ub.bl.bl_data, rem); + bi->bi_msg[rem] = '\0'; + } return bi; } diff --git a/contrib/blocklist/lib/blacklist.c b/contrib/blocklist/lib/blacklist.c index ba376c3daf0d..12e5f83e09af 100644 --- a/contrib/blocklist/lib/blacklist.c +++ b/contrib/blocklist/lib/blacklist.c @@ -1,4 +1,4 @@ -/* $NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $ */ +/* $NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,11 +32,13 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $"); +#endif +__RCSID("$NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); #include <stdio.h> -#include <bl.h> +#include <old_bl.h> #include <stdarg.h> #include <errno.h> @@ -98,7 +100,14 @@ blacklist_r(struct blacklist *bl, int action, int rfd, const char *msg) struct blacklist * blacklist_open(void) { - return bl_create(false, NULL, vsyslog); + return bl_create(false, NULL, vsyslog_r); +} + +struct blacklist * +blacklist_open2( + void (*logger)(int, struct syslog_data *, const char *, va_list)) +{ + return bl_create(false, NULL, logger); } void diff --git a/contrib/blocklist/lib/blocklist.c b/contrib/blocklist/lib/blocklist.c new file mode 100644 index 000000000000..139fc4342626 --- /dev/null +++ b/contrib/blocklist/lib/blocklist.c @@ -0,0 +1,117 @@ +/* $NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); + +#include <stdio.h> +#include <bl.h> + +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> + +int +blocklist_sa(int action, int rfd, const struct sockaddr *sa, socklen_t salen, + const char *msg) +{ + struct blocklist *bl; + int rv; + if ((bl = blocklist_open()) == NULL) + return -1; + rv = blocklist_sa_r(bl, action, rfd, sa, salen, msg); + blocklist_close(bl); + return rv; +} + +int +blocklist_sa_r(struct blocklist *bl, int action, int rfd, + const struct sockaddr *sa, socklen_t slen, const char *msg) +{ + bl_type_t internal_action; + + /* internal values are not the same as user application values */ + switch (action) { + case BLOCKLIST_AUTH_FAIL: + internal_action = BL_ADD; + break; + case BLOCKLIST_AUTH_OK: + internal_action = BL_DELETE; + break; + case BLOCKLIST_ABUSIVE_BEHAVIOR: + internal_action = BL_ABUSE; + break; + case BLOCKLIST_BAD_USER: + internal_action = BL_BADUSER; + break; + default: + internal_action = BL_INVALID; + break; + } + return bl_send(bl, internal_action, rfd, sa, slen, msg); +} + +int +blocklist(int action, int rfd, const char *msg) +{ + return blocklist_sa(action, rfd, NULL, 0, msg); +} + +int +blocklist_r(struct blocklist *bl, int action, int rfd, const char *msg) +{ + return blocklist_sa_r(bl, action, rfd, NULL, 0, msg); +} + +struct blocklist * +blocklist_open(void) { + return bl_create(false, NULL, vsyslog_r); +} + +struct blocklist * +blocklist_open2( + void (*logger)(int, struct syslog_data *, const char *, va_list)) +{ + return bl_create(false, NULL, logger); +} + +void +blocklist_close(struct blocklist *bl) +{ + bl_destroy(bl); +} diff --git a/contrib/blocklist/lib/libblacklist.3 b/contrib/blocklist/lib/libblacklist.3 index 146915c8dc31..5bc093c38f79 100644 --- a/contrib/blocklist/lib/libblacklist.3 +++ b/contrib/blocklist/lib/libblacklist.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: libblacklist.3,v 1.10 2020/03/30 15:47:15 christos Exp $ +.\" $NetBSD: libblocklist.3,v 1.7 2025/02/05 20:14:30 christos Exp $ .\" .\" Copyright (c) 2015 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,11 +27,12 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 30, 2020 +.Dd February 5, 2025 .Dt LIBBLACKLIST 3 .Os .Sh NAME .Nm blacklist_open , +.Nm blacklist_open2 , .Nm blacklist_close , .Nm blacklist_r , .Nm blacklist , @@ -44,6 +45,8 @@ .In blacklist.h .Ft struct blacklist * .Fn blacklist_open "void" +.Ft struct blacklist * +.Fn blacklist_open2 "void (*logger)(int, struct syslog_data *, va_list)" .Ft void .Fn blacklist_close "struct blacklist *cookie" .Ft int @@ -68,6 +71,19 @@ and returns a pointer to it, or .Dv NULL on failure. .Pp +The function +.Fn blacklist_open2 +is similar to +.Fn blacklist_open +but allows a +.Fa logger +to be specified. +If the +.Fa logger +is +.Dv NULL , +then no logging is performed. +.Pp The .Fn blacklist_close function frees all memory and resources used. @@ -89,17 +105,17 @@ argument. The .Ar action parameter can take these values: -.Bl -tag -width ".Va BLACKLIST_ABUSIVE_BEHAVIOR" -.It Va BLACKLIST_AUTH_FAIL +.Bl -tag -width ".Dv BLACKLIST_ABUSIVE_BEHAVIOR" +.It Dv BLACKLIST_AUTH_FAIL There was an unsuccessful authentication attempt. -.It Va BLACKLIST_AUTH_OK +.It Dv BLACKLIST_AUTH_OK A user successfully authenticated. -.It Va BLACKLIST_ABUSIVE_BEHAVIOR +.It Dv BLACKLIST_ABUSIVE_BEHAVIOR The sending daemon has detected abusive behavior from the remote system. The remote address should be blocked as soon as possible. -.It Va BLACKLIST_BAD_USER +.It Dv BLACKLIST_BAD_USER The sending daemon has determined the username presented for authentication is invalid. The @@ -108,7 +124,7 @@ daemon compares the username to a configured list of forbidden usernames and blocks the address immediately if a forbidden username matches. (The -.Ar BLACKLIST_BAD_USER +.Dv BLACKLIST_BAD_USER support is not currently available.) .El .Pp @@ -160,6 +176,11 @@ on success and on failure setting .Dv errno to an appropriate value. +.Sh NOTES +The +.Lb libblacklist +has been renamed to +.Xr libblocklist 3 . .Sh SEE ALSO .Xr blacklistd.conf 5 , .Xr blacklistd 8 diff --git a/contrib/blocklist/lib/libblocklist.3 b/contrib/blocklist/lib/libblocklist.3 new file mode 100644 index 000000000000..fd6eb93eb756 --- /dev/null +++ b/contrib/blocklist/lib/libblocklist.3 @@ -0,0 +1,183 @@ +.\" $NetBSD: libblocklist.3,v 1.7 2025/02/05 20:14:30 christos Exp $ +.\" +.\" Copyright (c) 2015 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 5, 2025 +.Dt LIBBLOCKLIST 3 +.Os +.Sh NAME +.Nm blocklist_open , +.Nm blocklist_open2 , +.Nm blocklist_close , +.Nm blocklist_r , +.Nm blocklist , +.Nm blocklist_sa , +.Nm blocklist_sa_r +.Nd Blocklistd notification library +.Sh LIBRARY +.Lb libblocklist +.Sh SYNOPSIS +.In blocklist.h +.Ft struct blocklist * +.Fn blocklist_open "void" +.Ft struct blocklist * +.Fn blocklist_open2 "void (*logger)(int, struct syslog_data *, va_list)" +.Ft void +.Fn blocklist_close "struct blocklist *cookie" +.Ft int +.Fn blocklist "int action" "int fd" "const char *msg" +.Ft int +.Fn blocklist_r "struct blocklist *cookie" "int action" "int fd" "const char *msg" +.Ft int +.Fn blocklist_sa "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" +.Ft int +.Fn blocklist_sa_r "struct blocklist *cookie" "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" +.Sh DESCRIPTION +These functions can be used by daemons to notify +.Xr blocklistd 8 +about successful and failed remote connections so that blocklistd can +block or release port access to prevent Denial of Service attacks. +.Pp +The function +.Fn blocklist_open +creates the necessary state to communicate with +.Xr blocklistd 8 +and returns a pointer to it, or +.Dv NULL +on failure. +.Pp +The function +.Fn blocklist_open2 +is similar to +.Fn blocklist_open +but allows a +.Fa logger +to be specified. +If the +.Fa logger +is +.Dv NULL , +then no logging is performed. +.Pp +The +.Fn blocklist_close +function frees all memory and resources used. +.Pp +The +.Fn blocklist +function sends a message to +.Xr blocklistd 8 , +with an integer +.Ar action +argument specifying the type of notification, +a file descriptor +.Ar fd +specifying the accepted file descriptor connected to the client, +and an optional message in the +.Ar msg +argument. +.Pp +The +.Ar action +parameter can take these values: +.Bl -tag -width ".Dv BLOCKLIST_ABUSIVE_BEHAVIOR" +.It Dv BLOCKLIST_AUTH_FAIL +There was an unsuccessful authentication attempt. +.It Dv BLOCKLIST_AUTH_OK +A user successfully authenticated. +.It Dv BLOCKLIST_ABUSIVE_BEHAVIOR +The sending daemon has detected abusive behavior +from the remote system. +The remote address should +be blocked as soon as possible. +.It Dv BLOCKLIST_BAD_USER +The sending daemon has determined the username +presented for authentication is invalid. +The +.Xr blocklistd 8 +daemon compares the username to a configured list of forbidden +usernames and +blocks the address immediately if a forbidden username matches. +(The +.Dv BLOCKLIST_BAD_USER +support is not currently available.) +.El +.Pp +The +.Fn blocklist_r +function is more efficient because it keeps the blocklist state around. +.Pp +The +.Fn blocklist_sa +and +.Fn blocklist_sa_r +functions can be used with unconnected sockets, where +.Xr getpeername 2 +will not work, the server will pass the peer name in the message. +.Pp +In all cases the file descriptor passed in the +.Fa fd +argument must be pointing to a valid socket so that +.Xr blocklistd 8 +can establish ownership of the local endpoint +using +.Xr getsockname 2 . +.Pp +By default, +.Xr syslogd 8 +is used for message logging. +The internal +.Fn bl_create +function can be used to create the required internal +state and specify a custom logging function. +.Sh RETURN VALUES +The function +.Fn blocklist_open +returns a cookie on success and +.Dv NULL +on failure setting +.Dv errno +to an appropriate value. +.Pp +The functions +.Fn blocklist , +.Fn blocklist_sa , +and +.Fn blocklist_sa_r +return +.Dv 0 +on success and +.Dv \-1 +on failure setting +.Dv errno +to an appropriate value. +.Sh SEE ALSO +.Xr blocklistd.conf 5 , +.Xr blocklistd 8 +.Sh AUTHORS +.An Christos Zoulas diff --git a/contrib/blocklist/lib/old_bl.c b/contrib/blocklist/lib/old_bl.c new file mode 100644 index 000000000000..ffbbd3f620ac --- /dev/null +++ b/contrib/blocklist/lib/old_bl.c @@ -0,0 +1,554 @@ +/* $NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $"); + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> + +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <signal.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <errno.h> +#include <stdarg.h> +#include <netinet/in.h> +#ifdef _REENTRANT +#include <pthread.h> +#endif + +#if defined(SO_RECVUCRED) +#include <ucred.h> +#endif + +#include "old_bl.h" + +typedef struct { + uint32_t bl_len; + uint32_t bl_version; + uint32_t bl_type; + uint32_t bl_salen; + struct sockaddr_storage bl_ss; + char bl_data[]; +} bl_message_t; + +struct blacklist { +#ifdef _REENTRANT + pthread_mutex_t b_mutex; +# define BL_INIT(b) pthread_mutex_init(&b->b_mutex, NULL) +# define BL_LOCK(b) pthread_mutex_lock(&b->b_mutex) +# define BL_UNLOCK(b) pthread_mutex_unlock(&b->b_mutex) +#else +# define BL_INIT(b) do {} while(/*CONSTCOND*/0) +# define BL_LOCK(b) BL_INIT(b) +# define BL_UNLOCK(b) BL_INIT(b) +#endif + int b_fd; + int b_connected; + struct sockaddr_un b_sun; + struct syslog_data b_syslog_data; + void (*b_fun)(int, struct syslog_data *, const char *, va_list); + bl_info_t b_info; +}; + +#define BL_VERSION 1 + +bool +bl_isconnected(bl_t b) +{ + return b->b_connected == 0; +} + +int +bl_getfd(bl_t b) +{ + return b->b_fd; +} + +static void +bl_reset(bl_t b, bool locked) +{ + int serrno = errno; + if (!locked) + BL_LOCK(b); + close(b->b_fd); + errno = serrno; + b->b_fd = -1; + b->b_connected = -1; + if (!locked) + BL_UNLOCK(b); +} + +static void +bl_log(bl_t b, int level, const char *fmt, ...) +{ + va_list ap; + int serrno = errno; + + if (b->b_fun == NULL) + return; + + va_start(ap, fmt); + (*b->b_fun)(level, &b->b_syslog_data, fmt, ap); + va_end(ap); + errno = serrno; +} + +static int +bl_init(bl_t b, bool srv) +{ + static int one = 1; + /* AF_UNIX address of local logger */ + mode_t om; + int rv, serrno; + struct sockaddr_un *sun = &b->b_sun; + +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK 0 +#endif +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif +#ifndef SOCK_NOSIGPIPE +#define SOCK_NOSIGPIPE 0 +#endif + + BL_LOCK(b); + + if (b->b_fd == -1) { + b->b_fd = socket(PF_LOCAL, + SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NOSIGPIPE, 0); + if (b->b_fd == -1) { + bl_log(b, LOG_ERR, "%s: socket failed (%s)", + __func__, strerror(errno)); + BL_UNLOCK(b); + return -1; + } +#if SOCK_CLOEXEC == 0 + fcntl(b->b_fd, F_SETFD, FD_CLOEXEC); +#endif +#if SOCK_NONBLOCK == 0 + fcntl(b->b_fd, F_SETFL, fcntl(b->b_fd, F_GETFL) | O_NONBLOCK); +#endif +#if SOCK_NOSIGPIPE == 0 +#ifdef SO_NOSIGPIPE + int o = 1; + setsockopt(b->b_fd, SOL_SOCKET, SO_NOSIGPIPE, &o, sizeof(o)); +#else + signal(SIGPIPE, SIG_IGN); +#endif +#endif + } + + if (bl_isconnected(b)) { + BL_UNLOCK(b); + return 0; + } + + /* + * We try to connect anyway even when we are a server to verify + * that no other server is listening to the socket. If we succeed + * to connect and we are a server, someone else owns it. + */ + rv = connect(b->b_fd, (const void *)sun, (socklen_t)sizeof(*sun)); + if (rv == 0) { + if (srv) { + bl_log(b, LOG_ERR, + "%s: another daemon is handling `%s'", + __func__, sun->sun_path); + goto out; + } + } else { + if (!srv) { + /* + * If the daemon is not running, we just try a + * connect, so leave the socket alone until it does + * and only log once. + */ + if (b->b_connected != 1) { + bl_log(b, LOG_DEBUG, + "%s: connect failed for `%s' (%s)", + __func__, sun->sun_path, strerror(errno)); + b->b_connected = 1; + } + BL_UNLOCK(b); + return -1; + } + bl_log(b, LOG_DEBUG, "Connected to blacklist server", __func__); + } + + if (srv) { + (void)unlink(sun->sun_path); + om = umask(0); + rv = bind(b->b_fd, (const void *)sun, (socklen_t)sizeof(*sun)); + serrno = errno; + (void)umask(om); + errno = serrno; + if (rv == -1) { + bl_log(b, LOG_ERR, "%s: bind failed for `%s' (%s)", + __func__, sun->sun_path, strerror(errno)); + goto out; + } + } + + b->b_connected = 0; +#define GOT_FD 1 +#if defined(LOCAL_CREDS) +#define CRED_LEVEL 0 +#define CRED_NAME LOCAL_CREDS +#define CRED_SC_UID(x) (x)->sc_euid +#define CRED_SC_GID(x) (x)->sc_egid +#define CRED_MESSAGE SCM_CREDS +#define CRED_SIZE SOCKCREDSIZE(NGROUPS_MAX) +#define CRED_TYPE struct sockcred +#define GOT_CRED 2 +#elif defined(SO_PASSCRED) +#define CRED_LEVEL SOL_SOCKET +#define CRED_NAME SO_PASSCRED +#define CRED_SC_UID(x) (x)->uid +#define CRED_SC_GID(x) (x)->gid +#define CRED_MESSAGE SCM_CREDENTIALS +#define CRED_SIZE sizeof(struct ucred) +#define CRED_TYPE struct ucred +#define GOT_CRED 2 +#elif defined(SO_RECVUCRED) +#define CRED_LEVEL SOL_SOCKET +#define CRED_NAME SO_RECVUCRED +#define CRED_SC_UID(x) ucred_geteuid(x) +#define CRED_SC_GID(x) ucred_getegid(x) +#define CRED_MESSAGE SCM_UCRED +#define CRED_SIZE ucred_size() +#define CRED_TYPE ucred_t +#define GOT_CRED 2 +#else +#define GOT_CRED 0 +/* + * getpeereid() and LOCAL_PEERCRED don't help here + * because we are not a stream socket! + */ +#define CRED_SIZE 0 +#define CRED_TYPE void * __unused +#endif + +#ifdef CRED_LEVEL + if (setsockopt(b->b_fd, CRED_LEVEL, CRED_NAME, + &one, (socklen_t)sizeof(one)) == -1) { + bl_log(b, LOG_ERR, "%s: setsockopt %s " + "failed (%s)", __func__, __STRING(CRED_NAME), + strerror(errno)); + goto out; + } +#endif + + BL_UNLOCK(b); + return 0; +out: + bl_reset(b, true); + BL_UNLOCK(b); + return -1; +} + +bl_t +bl_create(bool srv, const char *path, + void (*fun)(int, struct syslog_data *, const char *, va_list)) +{ + static struct syslog_data sd = SYSLOG_DATA_INIT; + bl_t b = calloc(1, sizeof(*b)); + if (b == NULL) + return NULL; + b->b_fun = fun; + b->b_syslog_data = sd; + b->b_fd = -1; + b->b_connected = -1; + BL_INIT(b); + + memset(&b->b_sun, 0, sizeof(b->b_sun)); + b->b_sun.sun_family = AF_LOCAL; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + b->b_sun.sun_len = sizeof(b->b_sun); +#endif + strlcpy(b->b_sun.sun_path, + path ? path : _PATH_BLSOCK, sizeof(b->b_sun.sun_path)); + + bl_init(b, srv); + return b; +} + +void +bl_destroy(bl_t b) +{ + bl_reset(b, false); + free(b); +} + +static int +bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, + socklen_t slen, const char *ctx) +{ + uint8_t family; + + memset(ss, 0, sizeof(*ss)); + + switch (slen) { + case 0: + return 0; + case sizeof(struct sockaddr_in): + family = AF_INET; + break; + case sizeof(struct sockaddr_in6): + family = AF_INET6; + break; + default: + bl_log(b, LOG_ERR, "%s: invalid socket len %u (%s)", + __func__, (unsigned)slen, ctx); + errno = EINVAL; + return -1; + } + + memcpy(ss, sa, slen); + + if (ss->ss_family != family) { + bl_log(b, LOG_INFO, + "%s: correcting socket family %d to %d (%s)", + __func__, ss->ss_family, family, ctx); + ss->ss_family = family; + } + +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + if (ss->ss_len != slen) { + bl_log(b, LOG_INFO, + "%s: correcting socket len %u to %u (%s)", + __func__, ss->ss_len, (unsigned)slen, ctx); + ss->ss_len = (uint8_t)slen; + } +#endif + return 0; +} + +int +bl_send(bl_t b, bl_type_t e, int pfd, const struct sockaddr *sa, + socklen_t slen, const char *ctx) +{ + struct msghdr msg; + struct iovec iov; + union { + char ctrl[CMSG_SPACE(sizeof(int))]; + uint32_t fd; + } ua; + struct cmsghdr *cmsg; + union { + bl_message_t bl; + char buf[512]; + } ub; + size_t ctxlen, tried; +#define NTRIES 5 + + ctxlen = strlen(ctx); + if (ctxlen > 128) + ctxlen = 128; + + iov.iov_base = ub.buf; + iov.iov_len = sizeof(bl_message_t) + ctxlen; + ub.bl.bl_len = (uint32_t)iov.iov_len; + ub.bl.bl_version = BL_VERSION; + ub.bl.bl_type = (uint32_t)e; + + if (bl_getsock(b, &ub.bl.bl_ss, sa, slen, ctx) == -1) + return -1; + + + ub.bl.bl_salen = slen; + memcpy(ub.bl.bl_data, ctx, ctxlen); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + + msg.msg_control = ua.ctrl; + msg.msg_controllen = sizeof(ua.ctrl); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + memcpy(CMSG_DATA(cmsg), &pfd, sizeof(pfd)); + + tried = 0; +again: + if (bl_init(b, false) == -1) + return -1; + + if ((sendmsg(b->b_fd, &msg, 0) == -1) && tried++ < NTRIES) { + bl_reset(b, false); + goto again; + } + return tried >= NTRIES ? -1 : 0; +} + +bl_info_t * +bl_recv(bl_t b) +{ + struct msghdr msg; + struct iovec iov; + union { + char ctrl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(CRED_SIZE)]; + uint32_t fd; + } ua; + struct cmsghdr *cmsg; +#if GOT_CRED != 0 + CRED_TYPE *sc; +#endif + union { + bl_message_t bl; + char buf[512]; + } ub; + int got; + ssize_t rlen; + size_t rem; + bl_info_t *bi = &b->b_info; + + got = 0; + memset(bi, 0, sizeof(*bi)); + + iov.iov_base = ub.buf; + iov.iov_len = sizeof(ub); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + + msg.msg_control = ua.ctrl; + msg.msg_controllen = sizeof(ua.ctrl); + + rlen = recvmsg(b->b_fd, &msg, 0); + if (rlen == -1) { + bl_log(b, LOG_ERR, "%s: recvmsg failed (%s)", __func__, + strerror(errno)); + return NULL; + } + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET) { + bl_log(b, LOG_ERR, + "%s: unexpected cmsg_level %d", + __func__, cmsg->cmsg_level); + continue; + } + switch (cmsg->cmsg_type) { + case SCM_RIGHTS: + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { + int *fd = (void *)CMSG_DATA(cmsg); + size_t len = cmsg->cmsg_len / sizeof(int); + bl_log(b, LOG_ERR, + "%s: unexpected cmsg_len %d != %zu", + __func__, cmsg->cmsg_len, + CMSG_LEN(sizeof(int))); + + for (size_t i = 0; i < len; i++) + (void)close(fd[i]); + continue; + } + memcpy(&bi->bi_fd, CMSG_DATA(cmsg), sizeof(bi->bi_fd)); + got |= GOT_FD; + break; +#ifdef CRED_MESSAGE + case CRED_MESSAGE: + sc = (void *)CMSG_DATA(cmsg); + bi->bi_uid = CRED_SC_UID(sc); + bi->bi_gid = CRED_SC_GID(sc); + got |= GOT_CRED; + break; +#endif + default: + bl_log(b, LOG_ERR, + "%s: unexpected cmsg_type %d", + __func__, cmsg->cmsg_type); + continue; + } + + } + + if (got != (GOT_CRED|GOT_FD)) { + bl_log(b, LOG_ERR, "message missing %s %s", +#if GOT_CRED != 0 + (got & GOT_CRED) == 0 ? "cred" : +#endif + "", (got & GOT_FD) == 0 ? "fd" : ""); + return NULL; + } + + rem = (size_t)rlen; + if (rem < sizeof(ub.bl)) { + bl_log(b, LOG_ERR, "message too short %zd", rlen); + return NULL; + } + rem -= sizeof(ub.bl); + + if (ub.bl.bl_version != BL_VERSION) { + bl_log(b, LOG_ERR, "bad version %d", ub.bl.bl_version); + return NULL; + } + + bi->bi_type = ub.bl.bl_type; + bi->bi_slen = ub.bl.bl_salen; + bi->bi_ss = ub.bl.bl_ss; +#ifndef CRED_MESSAGE + bi->bi_uid = -1; + bi->bi_gid = -1; +#endif + if (rem == 0) + bi->bi_msg[0] = '\0'; + else { + rem = MIN(sizeof(bi->bi_msg) - 1, rem); + memcpy(bi->bi_msg, ub.bl.bl_data, rem); + bi->bi_msg[rem] = '\0'; + } + return bi; +} diff --git a/contrib/blocklist/lib/shlib_version b/contrib/blocklist/lib/shlib_version index 97c9f92d6b8f..3d7c908e43d6 100644 --- a/contrib/blocklist/lib/shlib_version +++ b/contrib/blocklist/lib/shlib_version @@ -1,2 +1,2 @@ major=0 -minor=0 +minor=1 diff --git a/contrib/blocklist/libexec/Makefile b/contrib/blocklist/libexec/Makefile index 6537080bf465..619d962c23b2 100644 --- a/contrib/blocklist/libexec/Makefile +++ b/contrib/blocklist/libexec/Makefile @@ -1,6 +1,6 @@ -# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ -SCRIPTS= blacklistd-helper +SCRIPTS= blocklistd-helper SCRIPTSDIR= /libexec .include <bsd.prog.mk> diff --git a/contrib/blocklist/libexec/blacklistd-helper b/contrib/blocklist/libexec/blacklistd-helper deleted file mode 100644 index f92eab8b29bd..000000000000 --- a/contrib/blocklist/libexec/blacklistd-helper +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/sh -#echo "run $@" 1>&2 -#set -x -# $1 command -# $2 rulename -# $3 protocol -# $4 address -# $5 mask -# $6 port -# $7 id - -pf= -if [ -f "/etc/ipfw-blacklist.rc" ]; then - pf="ipfw" - . /etc/ipfw-blacklist.rc - ipfw_offset=${ipfw_offset:-2000} -fi - -if [ -z "$pf" ]; then - for f in npf pf ipf; do - if [ -f "/etc/$f.conf" ]; then - pf="$f" - break - fi - done -fi - -if [ -z "$pf" ]; then - echo "$0: Unsupported packet filter" 1>&2 - exit 1 -fi - -if [ -n "$3" ]; then - proto="proto $3" -fi - -if [ -n "$6" ]; then - port="port $6" -fi - -addr="$4" -mask="$5" -case "$4" in -::ffff:*.*.*.*) - if [ "$5" = 128 ]; then - mask=32 - addr=${4#::ffff:} - fi;; -esac - -case "$1" in -add) - case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -f - -s >/dev/null 2>&1 && echo OK - ;; - ipfw) - # use $ipfw_offset+$port for rule number - rule=$(($ipfw_offset + $6)) - tname="port$6" - /sbin/ipfw table $tname create type addr 2>/dev/null - /sbin/ipfw -q table $tname add "$addr/$mask" - # if rule number $rule does not already exist, create it - /sbin/ipfw show $rule >/dev/null 2>&1 || \ - /sbin/ipfw add $rule drop $3 from \ - table"("$tname")" to any dst-port $6 >/dev/null && \ - echo OK - ;; - npf) - /sbin/npfctl rule "$2" add block in final $proto from \ - "$addr/$mask" to any $port - ;; - pf) - # if the filtering rule does not exist, create it - /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ - grep -q "<port$6>" || \ - echo "block in quick $proto from <port$6> to any $port" | \ - /sbin/pfctl -a "$2/$6" -f - - # insert $ip/$mask into per-protocol/port anchored table - /sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \ - /sbin/pfctl -qk "$addr" && echo OK - ;; - esac - ;; -rem) - case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -r -f - -s >/dev/null 2>&1 && echo OK - ;; - ipfw) - /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ - echo OK - ;; - npf) - /sbin/npfctl rule "$2" rem-id "$7" - ;; - pf) - /sbin/pfctl -qa "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ - echo OK - ;; - esac - ;; -flush) - case "$pf" in - ipf) - /sbin/ipf -Z -I -Fi -s > /dev/null && echo OK - ;; - ipfw) - /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK - ;; - npf) - /sbin/npfctl rule "$2" flush - ;; - pf) - # dynamically determine which anchors exist - for anchor in $(/sbin/pfctl -a "$2" -s Anchors); do - /sbin/pfctl -a $anchor -t "port${anchor##*/}" -T flush - /sbin/pfctl -a $anchor -F rules - done - echo OK - ;; - esac - ;; -*) - echo "$0: Unknown command '$1'" 1>&2 - exit 1 - ;; -esac diff --git a/contrib/blocklist/libexec/blocklistd-helper b/contrib/blocklist/libexec/blocklistd-helper new file mode 100755 index 000000000000..14a192ee35ce --- /dev/null +++ b/contrib/blocklist/libexec/blocklistd-helper @@ -0,0 +1,272 @@ +#!/bin/sh +#echo "run $@" 1>&2 +#set -x +# $1 command +# $2 rulename +# $3 protocol +# $4 address +# $5 mask +# $6 port +# $7 id + +pf= +if [ -f "/etc/ipfw-blocklist.rc" ]; then + pf="ipfw" + . /etc/ipfw-blocklist.rc + ipfw_offset=${ipfw_offset:-2000} +fi + +if [ -z "$pf" ]; then + for f in npf pf ipfilter ipfw; do + if [ -x /etc/rc.d/$f ]; then + if /etc/rc.d/$f status >/dev/null 2>&1; then + pf="$f" + break + fi + elif [ -f "/etc/$f.conf" ]; then + # xxx assume a config file means it can be enabled -- + # and the first one wins! + pf="$f" + break + fi + done +fi + +if [ -z "$pf" -a -x "/sbin/iptables" ]; then + pf="iptables" +fi + +if [ -z "$pf" ]; then + echo "$0: Unsupported packet filter" 1>&2 + exit 1 +fi + +flags= +if [ -n "$3" ]; then + raw_proto="$3" + proto="proto $3" + if [ $3 = "tcp" ]; then + flags="flags S/SAFR" + fi +fi + +if [ -n "$6" ]; then + raw_port="$6" + port="port $6" +fi + +addr="$4" +mask="$5" +case "$4" in +::ffff:*.*.*.*) + if [ "$5" = 128 ]; then + mask=32 + addr=${4#::ffff:} + fi;; +esac + +case "$1" in +add) + case "$pf" in + ipfilter) + # N.B.: If you reload /etc/ipf.conf then you need to stop and + # restart blocklistd (and make sure blocklistd_flags="-r"). + # This should normally already be implemented in + # /etc/rc.d/ipfilter, but if then not add the following lines to + # the end of the ipfilter_reload() function: + # + # if checkyesnox blocklistd; then + # /etc/rc.d/blocklistd restart + # fi + # + # XXX we assume the following rule is present in /etc/ipf.conf: + # (should we check? -- it probably cannot be added dynamically) + # + # block in proto tcp/udp from any to any head blocklistd + # + # where "blocklistd" is the default rulename (i.e. "$2") + # + # This rule can come before any rule that logs connections, + # etc., and should be followed by final rules such as: + # + # # log all as-yet unblocked incoming TCP connection + # # attempts + # log in proto tcp from any to any flags S/SAFR + # # last "pass" match wins for all non-blocked packets + # pass in all + # pass out all + # + # I.e. a "pass" rule which will be the final match and override + # the "block". This way the rules added by blocklistd will + # actually block packets, and prevent logging of them as + # connections, because they include the "quick" flag. + # + # N.b.: $port is not included/used in rules -- abusers are cut + # off completely from all services! + # + # Note RST packets are not returned for blocked SYN packets of + # active attacks, so the port will not appear to be closed. + # This will probably give away the fact that a firewall has been + # triggered to block connections, but it prevents generating + # extra outbound traffic, and it may also slow down the attacker + # somewhat. + # + # Note also that we don't block all packets, just new attempts + # to open connections (see $flags above). This allows us to do + # counterespionage against the attacker (or continue to make use + # of any other services that might be on the same subnet as the + # supposed attacker). However it does not kill any active + # connections -- we rely on the reporting daemon to do its own + # protection and cleanup. + # + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "rem" command below! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -f - >/dev/null 2>&1 && echo OK + ;; + + ipfw) + # use $ipfw_offset+$port for rule number + rule=$(($ipfw_offset + $6)) + tname="port$6" + /sbin/ipfw table $tname create type addr 2>/dev/null + /sbin/ipfw -q table $tname add "$addr/$mask" + # if rule number $rule does not already exist, create it + /sbin/ipfw show $rule >/dev/null 2>&1 || \ + /sbin/ipfw add $rule drop $3 from \ + table"("$tname")" to any dst-port $6 >/dev/null && \ + echo OK + ;; + + iptables) + if ! /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --new-chain "$2" + fi + /sbin/iptables --append INPUT --proto "$raw_proto" \ + --dport "$raw_port" --jump "$2" + /sbin/iptables --append "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" --jump DROP + echo OK + ;; + + npf) + /sbin/npfctl rule "$2" add block in final $proto from \ + "$addr/$mask" to any $port + ;; + + pf) + # if the filtering rule does not exist, create it + /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ + grep -q "<port$6>" || \ + echo "block in quick $proto from <port$6> to any $port" | \ + /sbin/pfctl -a "$2/$6" -f - + # insert $ip/$mask into per-protocol/port anchored table + /sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \ + /sbin/pfctl -qk "$addr" && echo OK + ;; + + esac + ;; +rem) + case "$pf" in + ipfilter) + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "add" command above! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -r -f - >/dev/null 2>&1 && echo OK + ;; + + ipfw) + /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ + echo OK + ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --delete "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" \ + --jump DROP + fi + echo OK + ;; + + npf) + /sbin/npfctl rule "$2" rem-id "$7" + ;; + + pf) + /sbin/pfctl -qa "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ + echo OK + ;; + + esac + ;; +flush) + case "$pf" in + ipfilter) + # + # N.B. WARNING: This is obviously not reentrant! + # + # First we flush all the rules from the inactive set, then we + # reload the ones that do not belong to the group "$2", and + # finally we swap the active and inactive rule sets. + # + /sbin/ipf -I -F a + # + # "ipf -I -F a" also flushes active accounting rules! + # + # Note that accounting rule groups are unique to accounting + # rules and have nothing to do with filter rules, though of + # course theoretically one could use the same group name for + # them too. + # + # In theory anyone using any such accounting rules should have a + # wrapper /etc/rc.conf.d/blocklistd script (and corresponding + # /etc/rc.conf.d/ipfilter script) that will record and + # consolidate the values accumulated by such accounting rules + # before they are flushed, since otherwise their counts will be + # lost forever. + # + /usr/sbin/ipfstat -io | fgrep -v "group $2" | \ + /sbin/ipf -I -f - >/dev/null 2>&1 + # + # This MUST be done last and separately as "-s" is executed + # _while_ the command arguments are being processed! + # + /sbin/ipf -s && echo OK + ;; + + ipfw) + /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK + ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --flush "$2" + fi + echo OK + ;; + + npf) + /sbin/npfctl rule "$2" flush + ;; + + pf) + # dynamically determine which anchors exist + for anchor in $(/sbin/pfctl -a "$2" -s Anchors 2> /dev/null); do + /sbin/pfctl -a "$anchor" -t "port${anchor##*/}" -T flush 2> /dev/null + /sbin/pfctl -a "$anchor" -F rules + done + echo OK + ;; + esac + ;; +*) + echo "$0: Unknown command '$1'" 1>&2 + exit 1 + ;; +esac diff --git a/contrib/blocklist/port/Makefile.am b/contrib/blocklist/port/Makefile.am index 43bf6c94b420..0e6085f9580f 100644 --- a/contrib/blocklist/port/Makefile.am +++ b/contrib/blocklist/port/Makefile.am @@ -1,25 +1,39 @@ # ACLOCAL_AMFLAGS = -I m4 -lib_LTLIBRARIES = libblacklist.la -include_HEADERS = ../include/blacklist.h +lib_LTLIBRARIES = libblocklist.la +include_HEADERS = $(srcdir)/../include/blocklist.h -bin_PROGRAMS = blacklistd blacklistctl srvtest cltest +exampledir = $(datarootdir)/examples +example_DATA = $(srcdir)/../etc/blocklistd.conf $(srcdir)/../etc/npf.conf $(srcdir)/../etc/ipf.conf -VPATH = ../bin:../lib:../test:../include +sbin_PROGRAMS = blocklistd blocklistctl +noinst_PROGRAMS = srvtest cltest +libexec_SCRIPTS = $(srcdir)/../libexec/blocklistd-helper -AM_CPPFLAGS = -I../include -DDOT="." +man5_MANS = $(srcdir)/../bin/blocklistd.conf.5 +man8_MANS = $(srcdir)/../bin/blocklistd.8 $(srcdir)/../bin/blocklistctl.8 + +VPATH = $(srcdir)/../port:$(srcdir)/../bin:$(srcdir)/../lib:$(srcdir)/../test:$(srcdir)/../include + +AM_CPPFLAGS = -I$(srcdir)/../include -DDOT="." +AM_CPPFLAGS += -D_PATH_BLCONF=\"$(sysconfdir)/blocklistd.conf\" +AM_CPPFLAGS += -D_PATH_BLCONTROL=\"$(libexecdir)/blocklistd-helper\" +AM_CPPFLAGS += -D_PATH_BLSOCK=\"$(runstatedir)/blocklistd.sock\" +AM_CPPFLAGS += -D_PATH_BLSTATE=\"$(localstatedir)/db/blocklistd.db\" +AM_CPPFLAGS += -std=c99 -D_POSIX_C_SOURCE=200809L -D__EXTENSIONS__ +AM_CPPFLAGS += -D__BSD_VISIBLE=1 AM_CFLAGS = @WARNINGS@ -libblacklist_la_SOURCES = bl.c blacklist.c -libblacklist_la_LDFLAGS = -no-undefined -version-info 0:0:0 -libblacklist_la_LIBADD = $(LTLIBOBJS) +libblocklist_la_SOURCES = bl.c blocklist.c +libblocklist_la_LDFLAGS = -no-undefined -version-info 0:0:0 +libblocklist_la_LIBADD = $(LTLIBOBJS) SRCS = internal.c support.c run.c conf.c state.c -blacklistd_SOURCES = blacklistd.c ${SRCS} -blacklistd_LDADD = libblacklist.la -blacklistctl_SOURCES = blacklistctl.c ${SRCS} -blacklistctl_LDADD = libblacklist.la +blocklistd_SOURCES = blocklistd.c ${SRCS} +blocklistd_LDADD = libblocklist.la +blocklistctl_SOURCES = blocklistctl.c ${SRCS} +blocklistctl_LDADD = libblocklist.la srvtest_SOURCES = srvtest.c ${SRCS} -srvtest_LDADD = libblacklist.la +srvtest_LDADD = libblocklist.la cltest_SOURCES = cltest.c ${SRCS} -cltest_LDADD = libblacklist.la +cltest_LDADD = libblocklist.la diff --git a/contrib/blocklist/port/_strtoi.h b/contrib/blocklist/port/_strtoi.h index 4b2b4e80f0d8..f50eefd67ff1 100644 --- a/contrib/blocklist/port/_strtoi.h +++ b/contrib/blocklist/port/_strtoi.h @@ -1,4 +1,4 @@ -/* $NetBSD: _strtoi.h,v 1.1 2015/01/22 02:15:59 christos Exp $ */ +/* $NetBSD: _strtoi.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ */ /*- * Copyright (c) 1990, 1993 diff --git a/contrib/blocklist/port/configure.ac b/contrib/blocklist/port/configure.ac index eef8065f060a..99ecf8732c93 100644 --- a/contrib/blocklist/port/configure.ac +++ b/contrib/blocklist/port/configure.ac @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([blacklistd],[0.1],[christos@netbsd.com]) +AC_INIT([blocklistd],[0.1],[christos@netbsd.com]) AM_INIT_AUTOMAKE([subdir-objects foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) @@ -7,9 +7,10 @@ AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AC_SUBST(WARNINGS) +AC_SUBST(LINK_NTOA) dnl Checks for programs. -AC_PROG_CC_STDC +AC_PROG_CC AC_USE_SYSTEM_EXTENSIONS AM_PROG_CC_C_O AC_C_BIGENDIAN @@ -18,18 +19,19 @@ AC_PROG_LN_S LT_INIT([disable-static pic-only]) gl_VISIBILITY dnl Checks for headers -AC_HEADER_STDC AC_HEADER_MAJOR AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(stdint.h fcntl.h stdint.h inttypes.h unistd.h) AC_CHECK_HEADERS(sys/un.h sys/socket.h limits.h) AC_CHECK_HEADERS(arpa/inet.h getopt.h err.h) AC_CHECK_HEADERS(sys/types.h util.h sys/time.h time.h) -AC_CHECK_HEADERS(netatalk/at.h net/if_dl.h db.h db_185.h) +AC_CHECK_HEADERS(netatalk/at.h db.h db_185.h) +AC_CHECK_HEADERS(sys/cdefs.h) AC_CHECK_LIB(rt, clock_gettime) AC_CHECK_LIB(db, __db185_open) AC_CHECK_LIB(util, pidfile) AC_CHECK_LIB(util, sockaddr_snprintf) +AC_SEARCH_LIBS(__xnet_connect, socket) AH_BOTTOM([ #ifndef __NetBSD__ @@ -82,7 +84,7 @@ dnl Checks for functions AC_CHECK_FUNCS(strerror) dnl Provide implementation of some required functions if necessary -AC_REPLACE_FUNCS(strtoi sockaddr_snprintf popenve clock_gettime strlcpy strlcat getprogname fparseln fgetln pidfile) +AC_REPLACE_FUNCS(strtoi sockaddr_snprintf popenve clock_gettime strlcpy strlcat getprogname fparseln fgetln pidfile vsyslog_r) dnl See if we are cross-compiling AM_CONDITIONAL(IS_CROSS_COMPILE, test "$cross_compiling" = yes) diff --git a/contrib/blocklist/port/fgetln.c b/contrib/blocklist/port/fgetln.c index a41a383a6653..006e19f5279f 100644 --- a/contrib/blocklist/port/fgetln.c +++ b/contrib/blocklist/port/fgetln.c @@ -1,4 +1,4 @@ -/* $NetBSD: fgetln.c,v 1.1 2015/01/22 03:48:07 christos Exp $ */ +/* $NetBSD: fgetln.c,v 1.1.1.1 2020/06/15 01:52:54 christos Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. diff --git a/contrib/blocklist/port/fparseln.c b/contrib/blocklist/port/fparseln.c index 5bfae54b9a9b..22850ea9e304 100644 --- a/contrib/blocklist/port/fparseln.c +++ b/contrib/blocklist/port/fparseln.c @@ -1,4 +1,4 @@ -/* $NetBSD: fparseln.c,v 1.1 2015/01/22 03:48:07 christos Exp $ */ +/* $NetBSD: fparseln.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /* * Copyright (c) 1997 Christos Zoulas. All rights reserved. @@ -27,9 +27,11 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: fparseln.c,v 1.1 2015/01/22 03:48:07 christos Exp $"); +__RCSID("$NetBSD: fparseln.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #include <assert.h> diff --git a/contrib/blocklist/port/pidfile.c b/contrib/blocklist/port/pidfile.c index 4deb2349d20a..1dbbf510c4e3 100644 --- a/contrib/blocklist/port/pidfile.c +++ b/contrib/blocklist/port/pidfile.c @@ -1,4 +1,4 @@ -/* $NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $ */ +/* $NetBSD: pidfile.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -32,9 +32,11 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $"); +__RCSID("$NetBSD: pidfile.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #endif #include <sys/param.h> diff --git a/contrib/blocklist/port/popenve.c b/contrib/blocklist/port/popenve.c index 20f6b5b86b68..bdff8cdc1de4 100644 --- a/contrib/blocklist/port/popenve.c +++ b/contrib/blocklist/port/popenve.c @@ -1,4 +1,4 @@ -/* $NetBSD: popenve.c,v 1.2 2015/01/22 03:10:50 christos Exp $ */ +/* $NetBSD: popenve.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /* * Copyright (c) 1988, 1993 @@ -36,12 +36,14 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95"; #else -__RCSID("$NetBSD: popenve.c,v 1.2 2015/01/22 03:10:50 christos Exp $"); +__RCSID("$NetBSD: popenve.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ diff --git a/contrib/blocklist/port/port.h b/contrib/blocklist/port/port.h index f82fb34b40f5..d1a9ac6bd6e5 100644 --- a/contrib/blocklist/port/port.h +++ b/contrib/blocklist/port/port.h @@ -1,6 +1,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include <sys/param.h> #include <stdio.h> #include <inttypes.h> #include <time.h> @@ -15,6 +16,22 @@ #define __dead __attribute__((__noreturn__)) #endif +#ifndef __BEGIN_DECLS +#define __BEGIN_DECLS +#endif + +#ifndef __END_DECLS +#define __END_DECLS +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + #ifndef __RCSID #define __RCSID(a) #endif @@ -27,6 +44,10 @@ #define __arraycount(a) (sizeof(a) / sizeof(a[0])) #endif +#ifndef __STRING +#define __STRING(x) #x +#endif + #ifndef HAVE_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif @@ -78,9 +99,10 @@ int clock_gettime(int, struct timespec *); #define CLOCK_REALTIME 0 #endif -#if !defined(__FreeBSD__) -#define _PATH_BLCONF "conf" -#define _PATH_BLCONTROL "control" -#define _PATH_BLSOCK "blacklistd.sock" -#define _PATH_BLSTATE "blacklistd.db" +#ifndef HAVE_VSYSLOG_R +#define SYSLOG_DATA_INIT { 0 } +struct syslog_data { + int dummy; +}; +void vsyslog_r(int, struct syslog_data *, const char *, va_list); #endif diff --git a/contrib/blocklist/port/sockaddr_snprintf.c b/contrib/blocklist/port/sockaddr_snprintf.c index 558755b6294b..a37eded14a88 100644 --- a/contrib/blocklist/port/sockaddr_snprintf.c +++ b/contrib/blocklist/port/sockaddr_snprintf.c @@ -1,4 +1,4 @@ -/* $NetBSD: sockaddr_snprintf.c,v 1.11 2016/06/01 22:57:51 christos Exp $ */ +/* $NetBSD: sockaddr_snprintf.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -32,9 +32,11 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.11 2016/06/01 22:57:51 christos Exp $"); +__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> diff --git a/contrib/blocklist/port/strlcat.c b/contrib/blocklist/port/strlcat.c index d3c69b5fab78..8cabd654e6b0 100644 --- a/contrib/blocklist/port/strlcat.c +++ b/contrib/blocklist/port/strlcat.c @@ -1,4 +1,4 @@ -/* $NetBSD: strlcat.c,v 1.2 2015/01/22 03:48:07 christos Exp $ */ +/* $NetBSD: strlcat.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */ /* @@ -22,9 +22,12 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif + #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: strlcat.c,v 1.2 2015/01/22 03:48:07 christos Exp $"); +__RCSID("$NetBSD: strlcat.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #ifdef _LIBC diff --git a/contrib/blocklist/port/strlcpy.c b/contrib/blocklist/port/strlcpy.c index 6646e1ce9696..3de72a640c59 100644 --- a/contrib/blocklist/port/strlcpy.c +++ b/contrib/blocklist/port/strlcpy.c @@ -1,4 +1,4 @@ -/* $NetBSD: strlcpy.c,v 1.2 2015/01/22 03:48:07 christos Exp $ */ +/* $NetBSD: strlcpy.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ /* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */ /* @@ -22,9 +22,12 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif + #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: strlcpy.c,v 1.2 2015/01/22 03:48:07 christos Exp $"); +__RCSID("$NetBSD: strlcpy.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #ifdef _LIBC diff --git a/contrib/blocklist/port/strtoi.c b/contrib/blocklist/port/strtoi.c index 5514f1a00a32..b0bed7058cc3 100644 --- a/contrib/blocklist/port/strtoi.c +++ b/contrib/blocklist/port/strtoi.c @@ -1,4 +1,4 @@ -/* $NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $ */ +/* $NetBSD: strtoi.c,v 1.2 2025/02/11 17:48:31 christos Exp $ */ /*- * Copyright (c) 2005 The DragonFly Project. All rights reserved. @@ -33,8 +33,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $"); +#endif +__RCSID("$NetBSD: strtoi.c,v 1.2 2025/02/11 17:48:31 christos Exp $"); #if defined(_KERNEL) #include <sys/param.h> diff --git a/contrib/blocklist/port/vsyslog_r.c b/contrib/blocklist/port/vsyslog_r.c new file mode 100644 index 000000000000..848f31b04453 --- /dev/null +++ b/contrib/blocklist/port/vsyslog_r.c @@ -0,0 +1,13 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <syslog.h> +#include <stdarg.h> + +void +vsyslog_r(int priority, struct syslog_data *sd __unused, const char *fmt, va_list ap) +{ + vsyslog(priority, fmt, ap); +} + diff --git a/contrib/blocklist/test/Makefile b/contrib/blocklist/test/Makefile index a451274def06..d127955acdb7 100644 --- a/contrib/blocklist/test/Makefile +++ b/contrib/blocklist/test/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.3 2015/05/30 22:40:38 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:54 christos Exp $ MKMAN=no diff --git a/contrib/blocklist/test/cltest.c b/contrib/blocklist/test/cltest.c index 6671429fc3c4..dc77a522bad8 100644 --- a/contrib/blocklist/test/cltest.c +++ b/contrib/blocklist/test/cltest.c @@ -1,4 +1,4 @@ -/* $NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 christos Exp $ */ +/* $NetBSD: cltest.c,v 1.2 2025/02/11 17:48:31 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 christos Exp $"); +#endif +__RCSID("$NetBSD: cltest.c,v 1.2 2025/02/11 17:48:31 christos Exp $"); #include <sys/types.h> #include <sys/socket.h> diff --git a/contrib/blocklist/test/srvtest.c b/contrib/blocklist/test/srvtest.c index 03a762ab81f2..4eb9468ed5fd 100644 --- a/contrib/blocklist/test/srvtest.c +++ b/contrib/blocklist/test/srvtest.c @@ -1,4 +1,4 @@ -/* $NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $ */ +/* $NetBSD: srvtest.c,v 1.2 2025/02/11 17:43:16 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $"); +#endif +__RCSID("$NetBSD: srvtest.c,v 1.2 2025/02/11 17:43:16 christos Exp $"); #include <sys/types.h> #include <sys/socket.h> @@ -48,7 +50,7 @@ __RCSID("$NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $"); #include <poll.h> #include <err.h> -#include "blacklist.h" +#include "blocklist.h" #ifdef BLDEBUG #include "bl.h" static void *b; @@ -71,9 +73,9 @@ process_tcp(int afd) buffer[sizeof(buffer) - 1] = '\0'; printf("%s: sending %d %s\n", getprogname(), afd, buffer); #ifdef BLDEBUG - blacklist_r(b, 1, afd, buffer); + blocklist_r(b, 1, afd, buffer); #else - blacklist(1, afd, buffer); + blocklist(1, afd, buffer); #endif exit(0); } @@ -95,7 +97,7 @@ process_udp(int afd) err(1, "recvfrom"); buffer[sizeof(buffer) - 1] = '\0'; printf("%s: sending %d %s\n", getprogname(), afd, buffer); - blacklist_sa(1, afd, (void *)&ss, slen, buffer); + blocklist_sa(1, afd, (void *)&ss, slen, buffer); exit(0); } static int @@ -167,7 +169,11 @@ static __dead void usage(int c) { warnx("Unknown option `%c'", (char)c); - fprintf(stderr, "Usage: %s [-u] [-p <num>]\n", getprogname()); + fprintf(stderr, "Usage: %s [-u] [-p <num>]" +#ifdef BLDEBUG + " [-s <sockpath>]" +#endif + "\n", getprogname()); exit(EXIT_FAILURE); } @@ -182,14 +188,16 @@ main(int argc, char *argv[]) struct pollfd pfd[NUMFD]; int type = SOCK_STREAM, c; in_port_t port = 6161; - - signal(SIGCHLD, SIG_IGN); - #ifdef BLDEBUG - b = bl_create(false, "blsock", vsyslog); + char *sockpath = "blsock"; + const char *optstr = "up:s:"; +#else + const char *optstr = "up:"; #endif - while ((c = getopt(argc, argv, "up:")) != -1) + signal(SIGCHLD, SIG_IGN); + + while ((c = getopt(argc, argv, optstr)) != -1) switch (c) { case 'u': type = SOCK_DGRAM; @@ -197,10 +205,20 @@ main(int argc, char *argv[]) case 'p': port = (in_port_t)atoi(optarg); break; +#ifdef BLDEBUG + case 's': + sockpath = (char *)optarg; + break; +#endif default: usage(c); } +#ifdef BLDEBUG + b = bl_create(false, sockpath, vsyslog_r); +#endif + + pfd[0].fd = cr(AF_INET, type, port); pfd[0].events = POLLIN; #if NUMFD > 1 diff --git a/contrib/kyua/drivers/run_tests.cpp b/contrib/kyua/drivers/run_tests.cpp index d92940005242..3af9a1268815 100644 --- a/contrib/kyua/drivers/run_tests.cpp +++ b/contrib/kyua/drivers/run_tests.cpp @@ -209,7 +209,7 @@ finish_test(scheduler::result_handle_ptr result_handle, hooks.got_result( *test_result_handle->test_program(), test_result_handle->test_case_name(), - test_result_handle->test_result(), + test_result, result_handle->end_time() - result_handle->start_time()); } diff --git a/crypto/krb5/src/build-tools/mit-krb5.pc.in b/crypto/krb5/src/build-tools/mit-krb5.pc.in index fdc557785ad4..dca1654c8c9d 100644 --- a/crypto/krb5/src/build-tools/mit-krb5.pc.in +++ b/crypto/krb5/src/build-tools/mit-krb5.pc.in @@ -12,4 +12,4 @@ Description: An implementation of Kerberos network authentication Version: @KRB5_VERSION@ Cflags: -I${includedir} Libs: -L${libdir} -lkrb5 -lk5crypto @COM_ERR_LIB@ -Libs.private: -lkrb5support +Libs.private: -lkrb5support -lkrb5profile diff --git a/crypto/openssh/auth-pam.c b/crypto/openssh/auth-pam.c index df08dbd99a9d..217fae531afa 100644 --- a/crypto/openssh/auth-pam.c +++ b/crypto/openssh/auth-pam.c @@ -101,7 +101,7 @@ #endif #include "monitor_wrap.h" #include "srclimit.h" -#include "blacklist_client.h" +#include "blocklist_client.h" extern ServerOptions options; extern struct sshbuf *loginmsg; @@ -937,7 +937,7 @@ sshpam_query(void *ctx, char **name, char **info, sshbuf_free(buffer); return (0); } - BLACKLIST_NOTIFY(NULL, BLACKLIST_AUTH_FAIL, + BLOCKLIST_NOTIFY(NULL, BLOCKLIST_AUTH_FAIL, "PAM illegal user"); error("PAM: %s for %s%.100s from %.100s", msg, sshpam_authctxt->valid ? "" : "illegal user ", diff --git a/crypto/openssh/auth.c b/crypto/openssh/auth.c index 0a1c8f71b390..28ee390f4a15 100644 --- a/crypto/openssh/auth.c +++ b/crypto/openssh/auth.c @@ -75,7 +75,7 @@ #include "monitor_wrap.h" #include "ssherr.h" #include "channels.h" -#include "blacklist_client.h" +#include "blocklist_client.h" /* import */ extern ServerOptions options; @@ -289,7 +289,7 @@ auth_log(struct ssh *ssh, int authenticated, int partial, else { authmsg = authenticated ? "Accepted" : "Failed"; if (authenticated) - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_OK, + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_OK, "Authenticated"); } @@ -339,7 +339,7 @@ auth_maxtries_exceeded(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, "Maximum attempts exceeded"); + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Maximum attempts exceeded"); error("maximum authentication attempts exceeded for " "%s%.100s from %.200s port %d ssh2", authctxt->valid ? "" : "invalid user ", @@ -500,7 +500,7 @@ getpwnamallow(struct ssh *ssh, const char *user) aix_restoreauthdb(); #endif if (pw == NULL) { - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, "Invalid user"); + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Invalid user"); logit("Invalid user %.100s from %.100s port %d", user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); #ifdef CUSTOM_FAILED_LOGIN diff --git a/crypto/openssh/blacklist.c b/crypto/openssh/blocklist.c index 33d02607dd98..f3c00016db66 100644 --- a/crypto/openssh/blacklist.c +++ b/crypto/openssh/blocklist.c @@ -46,16 +46,16 @@ #include "log.h" #include "misc.h" #include "servconf.h" -#include <blacklist.h> -#include "blacklist_client.h" +#include <blocklist.h> +#include "blocklist_client.h" -static struct blacklist *blstate = NULL; +static struct blocklist *blstate = NULL; /* import */ extern ServerOptions options; /* internal definition from bl.h */ -struct blacklist *bl_create(bool, char *, void (*)(int, const char *, va_list)); +struct blocklist *bl_create(bool, char *, void (*)(int, const char *, va_list)); /* impedence match vsyslog() to sshd's internal logging levels */ void @@ -80,18 +80,18 @@ im_log(int priority, const char *message, va_list args) } void -blacklist_init(void) +blocklist_init(void) { - if (options.use_blacklist) + if (options.use_blocklist) blstate = bl_create(false, NULL, im_log); } void -blacklist_notify(struct ssh *ssh, int action, const char *msg) +blocklist_notify(struct ssh *ssh, int action, const char *msg) { if (blstate != NULL && ssh_packet_connection_is_on_socket(ssh)) - (void)blacklist_r(blstate, action, + (void)blocklist_r(blstate, action, ssh_packet_get_connection_in(ssh), msg); } diff --git a/crypto/openssh/blacklist_client.h b/crypto/openssh/blocklist_client.h index 601a44461e20..be92245e4690 100644 --- a/crypto/openssh/blacklist_client.h +++ b/crypto/openssh/blocklist_client.h @@ -31,31 +31,31 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BLACKLIST_CLIENT_H -#define BLACKLIST_CLIENT_H +#ifndef BLOCKLIST_CLIENT_H +#define BLOCKLIST_CLIENT_H -#ifndef BLACKLIST_API_ENUM +#ifndef BLOCKLIST_API_ENUM enum { - BLACKLIST_AUTH_OK = 0, - BLACKLIST_AUTH_FAIL, - BLACKLIST_ABUSIVE_BEHAVIOR, - BLACKLIST_BAD_USER + BLOCKLIST_AUTH_OK = 0, + BLOCKLIST_AUTH_FAIL, + BLOCKLIST_ABUSIVE_BEHAVIOR, + BLOCKLIST_BAD_USER }; #endif -#ifdef USE_BLACKLIST -void blacklist_init(void); -void blacklist_notify(struct ssh *, int, const char *); +#ifdef USE_BLOCKLIST +void blocklist_init(void); +void blocklist_notify(struct ssh *, int, const char *); -#define BLACKLIST_INIT() blacklist_init() -#define BLACKLIST_NOTIFY(ssh,x,msg) blacklist_notify(ssh,x,msg) +#define BLOCKLIST_INIT() blocklist_init() +#define BLOCKLIST_NOTIFY(ssh,x,msg) blocklist_notify(ssh,x,msg) #else -#define BLACKLIST_INIT() -#define BLACKLIST_NOTIFY(ssh,x,msg) +#define BLOCKLIST_INIT() +#define BLOCKLIST_NOTIFY(ssh,x,msg) #endif -#endif /* BLACKLIST_CLIENT_H */ +#endif /* BLOCKLIST_CLIENT_H */ diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c index b826ecdb9065..77dccf0d84f1 100644 --- a/crypto/openssh/monitor.c +++ b/crypto/openssh/monitor.c @@ -85,7 +85,7 @@ #include "misc.h" #include "servconf.h" #include "monitor.h" -#include "blacklist_client.h" +#include "blocklist_client.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -355,7 +355,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) } } if (authctxt->failures > options.max_authtries) { - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Too many authentication attempts"); /* Shouldn't happen */ fatal_f("privsep child made too many authentication " @@ -364,12 +364,12 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) } if (!authctxt->valid) { - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Authenticated invalid user"); fatal_f("authenticated invalid user"); } if (strcmp(auth_method, "unknown") == 0) { - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Authentication method name unknown"); fatal_f("authentication method name unknown"); } diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 5ab34973bbcb..07d3bee2fcb9 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -217,7 +217,7 @@ initialize_server_options(ServerOptions *options) options->sshd_session_path = NULL; options->sshd_auth_path = NULL; options->refuse_connection = -1; - options->use_blacklist = -1; + options->use_blocklist = -1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ @@ -506,8 +506,8 @@ fill_default_server_options(ServerOptions *options) options->sshd_auth_path = xstrdup(_PATH_SSHD_AUTH); if (options->refuse_connection == -1) options->refuse_connection = 0; - if (options->use_blacklist == -1) - options->use_blacklist = 0; + if (options->use_blocklist == -1) + options->use_blocklist = 0; assemble_algorithms(options); @@ -591,7 +591,7 @@ typedef enum { sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sSshdSessionPath, sSshdAuthPath, sRefuseConnection, - sUseBlacklist, + sUseBlocklist, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -761,8 +761,8 @@ static struct { { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, { "sshdauthpath", sSshdAuthPath, SSHCFG_GLOBAL }, { "refuseconnection", sRefuseConnection, SSHCFG_ALL }, - { "useblacklist", sUseBlacklist, SSHCFG_GLOBAL }, - { "useblocklist", sUseBlacklist, SSHCFG_GLOBAL }, /* alias */ + { "useblocklist", sUseBlocklist, SSHCFG_GLOBAL }, + { "useblacklist", sUseBlocklist, SSHCFG_GLOBAL }, /* alias */ { NULL, sBadOption, 0 } }; @@ -2742,8 +2742,8 @@ process_server_config_line_depth(ServerOptions *options, char *line, multistate_ptr = multistate_flag; goto parse_multistate; - case sUseBlacklist: - intptr = &options->use_blacklist; + case sUseBlocklist: + intptr = &options->use_blocklist; goto parse_flag; case sDeprecated: @@ -3297,7 +3297,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); dump_cfg_fmtint(sRefuseConnection, o->refuse_connection); - dump_cfg_fmtint(sUseBlacklist, o->use_blacklist); + dump_cfg_fmtint(sUseBlocklist, o->use_blocklist); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); diff --git a/crypto/openssh/servconf.h b/crypto/openssh/servconf.h index ad3974322e83..38b2afeb15bd 100644 --- a/crypto/openssh/servconf.h +++ b/crypto/openssh/servconf.h @@ -253,7 +253,7 @@ typedef struct { int refuse_connection; - int use_blacklist; + int use_blocklist; } ServerOptions; /* Information about the incoming connection as used by Match */ diff --git a/crypto/openssh/sshd-session.c b/crypto/openssh/sshd-session.c index 62c76cc1c8aa..e8299c254567 100644 --- a/crypto/openssh/sshd-session.c +++ b/crypto/openssh/sshd-session.c @@ -108,7 +108,7 @@ #include "sk-api.h" #include "srclimit.h" #include "dh.h" -#include "blacklist_client.h" +#include "blocklist_client.h" /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) @@ -217,7 +217,7 @@ mm_is_monitor(void) static void grace_alarm_handler(int sig) { - BLACKLIST_NOTIFY(the_active_state, BLACKLIST_AUTH_FAIL, + BLOCKLIST_NOTIFY(the_active_state, BLOCKLIST_AUTH_FAIL, "Grace period expired"); /* * Try to kill any processes that we have spawned, E.g. authorized @@ -1203,7 +1203,7 @@ main(int ac, char **av) ssh_signal(SIGCHLD, SIG_DFL); ssh_signal(SIGINT, SIG_DFL); - BLACKLIST_INIT(); + BLOCKLIST_INIT(); /* * Register our connection. This turns encryption off because we do @@ -1282,7 +1282,7 @@ main(int ac, char **av) if ((r = kex_exchange_identification(ssh, -1, options.version_addendum)) != 0) { - BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, "Banner exchange"); + BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Banner exchange"); sshpkt_fatal(ssh, r, "banner exchange"); } @@ -1430,7 +1430,7 @@ cleanup_exit(int i) #endif /* Override default fatal exit value when auth was attempted */ if (i == 255 && auth_attempted) { - BLACKLIST_NOTIFY(the_active_state, BLACKLIST_AUTH_FAIL, + BLOCKLIST_NOTIFY(the_active_state, BLOCKLIST_AUTH_FAIL, "Fatal exit"); _exit(EXIT_AUTH_ATTEMPTED); } diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config index 50a3d228fa58..708be7fe2870 100644 --- a/crypto/openssh/sshd_config +++ b/crypto/openssh/sshd_config @@ -107,7 +107,7 @@ AuthorizedKeysFile .ssh/authorized_keys #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none -#UseBlacklist no +#UseBlocklist no #VersionAddendum FreeBSD-20250801 # no default banner path diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index ff1be7ba6ccf..c637d68f90c6 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -2020,20 +2020,20 @@ The default is to never expire connections for having no open channels. This option may be useful in conjunction with .Cm ChannelTimeout . -.It Cm UseBlacklist +.It Cm UseBlocklist Specifies whether .Xr sshd 8 attempts to send authentication success and failure messages to the -.Xr blacklistd 8 +.Xr blocklistd 8 daemon. The default is .Cm no . -For forward compatibility with an upcoming -.Xr blacklistd -rename, the -.Cm UseBlocklist -alias can be used instead. +For backward compatibility with +.Xr blacklistd 8 , +the +.Cm UseBlacklist +alias can still be used. .It Cm UseDNS Specifies whether .Xr sshd 8 diff --git a/lib/Makefile b/lib/Makefile index d43e4d395f56..75a2355aa452 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -163,6 +163,7 @@ SUBDIR_DEPEND_virtual_oss= libsamplerate SUBDIR.${MK_BEARSSL}+= libbearssl libsecureboot SUBDIR.${MK_BLACKLIST}+=libblacklist +SUBDIR.${MK_BLOCKLIST}+=libblocklist SUBDIR.${MK_BLUETOOTH}+=libbluetooth libsdp SUBDIR.${MK_BSNMP}+= libbsnmp diff --git a/lib/libblacklist/Makefile b/lib/libblacklist/Makefile index bfd9edb9614c..cac023d69bb7 100644 --- a/lib/libblacklist/Makefile +++ b/lib/libblacklist/Makefile @@ -1,6 +1,6 @@ BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist -.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include +.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include ${BLOCKLIST_DIR}/port PACKAGE= blocklist LIB= blacklist @@ -13,9 +13,10 @@ CFLAGS.clang+=-Wno-thread-safety-analysis CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \ -D_REENTRANT -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_GETPROGNAME \ - -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN + -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN \ + -DHAVE_SYS_CDEFS_H -SRCS= bl.c blacklist.c +SRCS= old_bl.c blacklist.c vsyslog_r.c INCS= blacklist.h MAN= libblacklist.3 diff --git a/lib/libblocklist/Makefile b/lib/libblocklist/Makefile new file mode 100644 index 000000000000..127abb23f43e --- /dev/null +++ b/lib/libblocklist/Makefile @@ -0,0 +1,30 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist + +.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include ${BLOCKLIST_DIR}/port + +PACKAGE= blocklist +LIB= blocklist +SHLIB_MAJOR= 0 + +LIBADD+= pthread + +CFLAGS.clang+=-Wno-thread-safety-analysis + +CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \ + -D_REENTRANT -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \ + -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_GETPROGNAME \ + -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN \ + -DHAVE_SYS_CDEFS_H + +SRCS= bl.c blocklist.c vsyslog_r.c +INCS= blocklist.h +MAN= libblocklist.3 + +MLINKS= libblocklist.3 blocklist_open.3 \ + libblocklist.3 blocklist_close.3 \ + libblocklist.3 blocklist.3 \ + libblocklist.3 blocklist_r.3 \ + libblocklist.3 blocklist_sa.3 \ + libblocklist.3 blocklist_sa_r.3 + +.include <bsd.lib.mk> diff --git a/lib/libblocklist/Makefile.depend b/lib/libblocklist/Makefile.depend new file mode 100644 index 000000000000..577dc5747f1e --- /dev/null +++ b/lib/libblocklist/Makefile.depend @@ -0,0 +1,16 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + lib/libthr \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/lib/libbluetooth/Makefile b/lib/libbluetooth/Makefile index a6ac291a0bf8..b935bdf3fc78 100644 --- a/lib/libbluetooth/Makefile +++ b/lib/libbluetooth/Makefile @@ -1,6 +1,8 @@ # $Id: Makefile,v 1.5 2003/07/22 18:38:04 max Exp $ PACKAGE= bluetooth +LIB_PACKAGE= + CONFS= hosts protocols CONFSDIR= /etc/bluetooth CONFSMODE_protocols= 444 diff --git a/lib/libsysdecode/Makefile.depend b/lib/libsysdecode/Makefile.depend index 1c40e21d361d..a9ccf3aa0870 100644 --- a/lib/libsysdecode/Makefile.depend +++ b/lib/libsysdecode/Makefile.depend @@ -38,7 +38,7 @@ DIRDEPS = \ lib/libarchive \ lib/libbe \ lib/libbegemot \ - lib/libblacklist \ + lib/libblocklist \ lib/libblocksruntime \ lib/libbluetooth \ lib/libbsddialog \ diff --git a/lib/msun/src/e_remainder.c b/lib/msun/src/e_remainder.c index a5fb7141d01a..cc6cd320073e 100644 --- a/lib/msun/src/e_remainder.c +++ b/lib/msun/src/e_remainder.c @@ -64,8 +64,8 @@ remainder(double x, double p) if(x>=p_half) x -= p; } } - GET_HIGH_WORD(hx,x); - if ((hx&0x7fffffff)==0) hx = 0; + EXTRACT_WORDS(hx, lx, x); + if (((hx&0x7fffffff)|lx) == 0) hx = 0; SET_HIGH_WORD(x,hx^sx); return x; } diff --git a/lib/virtual_oss/Makefile.inc b/lib/virtual_oss/Makefile.inc index 45c8e0b1fdfc..877465a5c548 100644 --- a/lib/virtual_oss/Makefile.inc +++ b/lib/virtual_oss/Makefile.inc @@ -1,3 +1,5 @@ +PACKAGE= sound + .include "../Makefile.inc" LDFLAGS+= -L${.OBJDIR:H:H}/libsamplerate diff --git a/libexec/Makefile b/libexec/Makefile index e87b48b153a8..180dd10b5d29 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -4,7 +4,7 @@ SUBDIR= ${_atf} \ ${_atrun} \ - ${_blacklistd-helper} \ + ${_blocklistd-helper} \ ${_comsat} \ ${_dma} \ flua \ @@ -37,8 +37,8 @@ SUBDIR= ${_atf} \ _atrun= atrun .endif -.if ${MK_BLACKLIST} != "no" -_blacklistd-helper+= blacklistd-helper +.if ${MK_BLOCKLIST} != "no" +_blocklistd-helper+= blocklistd-helper .endif .if ${MK_BOOTPD} != "no" diff --git a/libexec/blacklistd-helper/Makefile b/libexec/blacklistd-helper/Makefile deleted file mode 100644 index d32b69c278a8..000000000000 --- a/libexec/blacklistd-helper/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist - -PACKAGE= blocklist - -SCRIPTS= ${BLOCKLIST_DIR}/libexec/blacklistd-helper - -.include <bsd.prog.mk> diff --git a/libexec/blocklistd-helper/Makefile b/libexec/blocklistd-helper/Makefile new file mode 100644 index 000000000000..5c72b5155662 --- /dev/null +++ b/libexec/blocklistd-helper/Makefile @@ -0,0 +1,10 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist + +PACKAGE= blocklist + +SCRIPTS= ${BLOCKLIST_DIR}/libexec/blocklistd-helper + +# blacklist +SCRIPTS+= blacklistd-helper + +.include <bsd.prog.mk> diff --git a/libexec/blacklistd-helper/Makefile.depend b/libexec/blocklistd-helper/Makefile.depend index 11aba52f82cf..11aba52f82cf 100644 --- a/libexec/blacklistd-helper/Makefile.depend +++ b/libexec/blocklistd-helper/Makefile.depend diff --git a/libexec/blocklistd-helper/blacklistd-helper b/libexec/blocklistd-helper/blacklistd-helper new file mode 100644 index 000000000000..92f768e86cdf --- /dev/null +++ b/libexec/blocklistd-helper/blacklistd-helper @@ -0,0 +1,293 @@ +#!/bin/sh +#echo "run $@" 1>&2 +#set -x +# $1 command +# $2 rulename +# $3 protocol +# $4 address +# $5 mask +# $6 port +# $7 id + +pf= +if [ -f "/etc/ipfw-blacklist.rc" ]; then + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 + echo "@ WARNING: rename /etc/ipfw-blacklist.rc to @" >&2 + echo "@ /etc/ipfw-blocklist.rc @" >&2 + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 + + pf="ipfw" + . /etc/ipfw-blacklist.rc + ipfw_offset=${ipfw_offset:-2000} +fi + +if [ -z "$pf" ]; then + for f in npf pf ipfilter ipfw; do + if [ -x /etc/rc.d/$f ]; then + if /etc/rc.d/$f status >/dev/null 2>&1; then + pf="$f" + break + fi + elif [ -f "/etc/$f.conf" ]; then + # xxx assume a config file means it can be enabled -- + # and the first one wins! + pf="$f" + break + fi + done +fi + +if [ -z "$pf" -a -x "/sbin/iptables" ]; then + pf="iptables" +fi + +if [ -z "$pf" ]; then + echo "$0: Unsupported packet filter" 1>&2 + exit 1 +fi + +flags= +if [ -n "$3" ]; then + raw_proto="$3" + proto="proto $3" + if [ $3 = "tcp" ]; then + flags="flags S/SAFR" + fi +fi + +if [ -n "$6" ]; then + raw_port="$6" + port="port $6" +fi + +addr="$4" +mask="$5" +case "$4" in +::ffff:*.*.*.*) + if [ "$5" = 128 ]; then + mask=32 + addr=${4#::ffff:} + fi;; +esac + +if [ "$pf" = "pf" ]; then + for anchor in $(/sbin/pfctl -s Anchors 2> /dev/null); do + if [ "$anchor" = "blacklistd" ]; then + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 + echo "@ WARNING: rename the blacklist anchor to blocklist @" >&2 + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 + fi + done +fi + +if [ "$pf" = "ipfilter" ]; then + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 + echo "@ WARNING: blacklist has been renamed to blocklist @" >&2 + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >&2 +fi + +case "$1" in +add) + case "$pf" in + ipfilter) + # N.B.: If you reload /etc/ipf.conf then you need to stop and + # restart blacklistd (and make sure blacklistd_flags="-r"). + # This should normally already be implemented in + # /etc/rc.d/ipfilter, but if then not add the following lines to + # the end of the ipfilter_reload() function: + # + # if checkyesnox blacklistd; then + # /etc/rc.d/blacklistd restart + # fi + # + # XXX we assume the following rule is present in /etc/ipf.conf: + # (should we check? -- it probably cannot be added dynamically) + # + # block in proto tcp/udp from any to any head blacklistd + # + # where "blacklistd" is the default rulename (i.e. "$2") + # + # This rule can come before any rule that logs connections, + # etc., and should be followed by final rules such as: + # + # # log all as-yet unblocked incoming TCP connection + # # attempts + # log in proto tcp from any to any flags S/SAFR + # # last "pass" match wins for all non-blocked packets + # pass in all + # pass out all + # + # I.e. a "pass" rule which will be the final match and override + # the "block". This way the rules added by blacklistd will + # actually block packets, and prevent logging of them as + # connections, because they include the "quick" flag. + # + # N.b.: $port is not included/used in rules -- abusers are cut + # off completely from all services! + # + # Note RST packets are not returned for blocked SYN packets of + # active attacks, so the port will not appear to be closed. + # This will probably give away the fact that a firewall has been + # triggered to block connections, but it prevents generating + # extra outbound traffic, and it may also slow down the attacker + # somewhat. + # + # Note also that we don't block all packets, just new attempts + # to open connections (see $flags above). This allows us to do + # counterespionage against the attacker (or continue to make use + # of any other services that might be on the same subnet as the + # supposed attacker). However it does not kill any active + # connections -- we rely on the reporting daemon to do its own + # protection and cleanup. + # + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "rem" command below! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -f - >/dev/null 2>&1 && echo OK + ;; + + ipfw) + # use $ipfw_offset+$port for rule number + rule=$(($ipfw_offset + $6)) + tname="port$6" + /sbin/ipfw table $tname create type addr 2>/dev/null + /sbin/ipfw -q table $tname add "$addr/$mask" + # if rule number $rule does not already exist, create it + /sbin/ipfw show $rule >/dev/null 2>&1 || \ + /sbin/ipfw add $rule drop $3 from \ + table"("$tname")" to any dst-port $6 >/dev/null && \ + echo OK + ;; + + iptables) + if ! /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --new-chain "$2" + fi + /sbin/iptables --append INPUT --proto "$raw_proto" \ + --dport "$raw_port" --jump "$2" + /sbin/iptables --append "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" --jump DROP + echo OK + ;; + + npf) + /sbin/npfctl rule "$2" add block in final $proto from \ + "$addr/$mask" to any $port + ;; + + pf) + # if the filtering rule does not exist, create it + /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ + grep -q "<port$6>" || \ + echo "block in quick $proto from <port$6> to any $port" | \ + /sbin/pfctl -a "$2/$6" -f - + # insert $ip/$mask into per-protocol/port anchored table + /sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \ + /sbin/pfctl -qk "$addr" && echo OK + ;; + + esac + ;; +rem) + case "$pf" in + ipfilter) + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "add" command above! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -r -f - >/dev/null 2>&1 && echo OK + ;; + + ipfw) + /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ + echo OK + ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --delete "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" \ + --jump DROP + fi + echo OK + ;; + + npf) + /sbin/npfctl rule "$2" rem-id "$7" + ;; + + pf) + /sbin/pfctl -qa "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ + echo OK + ;; + + esac + ;; +flush) + case "$pf" in + ipfilter) + # + # N.B. WARNING: This is obviously not reentrant! + # + # First we flush all the rules from the inactive set, then we + # reload the ones that do not belong to the group "$2", and + # finally we swap the active and inactive rule sets. + # + /sbin/ipf -I -F a + # + # "ipf -I -F a" also flushes active accounting rules! + # + # Note that accounting rule groups are unique to accounting + # rules and have nothing to do with filter rules, though of + # course theoretically one could use the same group name for + # them too. + # + # In theory anyone using any such accounting rules should have a + # wrapper /etc/rc.conf.d/blacklistd script (and corresponding + # /etc/rc.conf.d/ipfilter script) that will record and + # consolidate the values accumulated by such accounting rules + # before they are flushed, since otherwise their counts will be + # lost forever. + # + /usr/sbin/ipfstat -io | fgrep -v "group $2" | \ + /sbin/ipf -I -f - >/dev/null 2>&1 + # + # This MUST be done last and separately as "-s" is executed + # _while_ the command arguments are being processed! + # + /sbin/ipf -s && echo OK + ;; + + ipfw) + /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK + ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --flush "$2" + fi + echo OK + ;; + + npf) + /sbin/npfctl rule "$2" flush + ;; + + pf) + # dynamically determine which anchors exist + for anchor in $(/sbin/pfctl -a "$2" -s Anchors 2> /dev/null); do + /sbin/pfctl -a "$anchor" -t "port${anchor##*/}" -T flush 2> /dev/null + /sbin/pfctl -a "$anchor" -F rules + done + echo OK + ;; + esac + ;; +*) + echo "$0: Unknown command '$1'" 1>&2 + exit 1 + ;; +esac diff --git a/libexec/fingerd/Makefile b/libexec/fingerd/Makefile index 296cb504bab1..e2fe412df8bc 100644 --- a/libexec/fingerd/Makefile +++ b/libexec/fingerd/Makefile @@ -7,10 +7,10 @@ MAN= fingerd.8 WARNS?= 2 WFORMAT=0 -.if ${MK_BLACKLIST_SUPPORT} != "no" -CFLAGS+= -DUSE_BLACKLIST -I${SRCTOP}/contrib/blocklist/include -LIBADD+= blacklist -LDFLAGS+=-L${LIBBLACKLISTDIR} +.if ${MK_BLOCKLIST_SUPPORT} != "no" +CFLAGS+= -DUSE_BLOCKLIST -I${SRCTOP}/contrib/blocklist/include +LIBADD+= blocklist +LDFLAGS+=-L${LIBBLOCKLISTDIR} .endif .include <bsd.prog.mk> diff --git a/libexec/fingerd/Makefile.depend.options b/libexec/fingerd/Makefile.depend.options index 5a94eff626dc..f68343adae89 100644 --- a/libexec/fingerd/Makefile.depend.options +++ b/libexec/fingerd/Makefile.depend.options @@ -1,5 +1,5 @@ # This file is not autogenerated - take care! -DIRDEPS_OPTIONS= BLACKLIST_SUPPORT +DIRDEPS_OPTIONS= BLOCKLIST_SUPPORT .include <dirdeps-options.mk> diff --git a/libexec/fingerd/fingerd.c b/libexec/fingerd/fingerd.c index c30d5e5e0ef5..8b63aa338b0c 100644 --- a/libexec/fingerd/fingerd.c +++ b/libexec/fingerd/fingerd.c @@ -45,8 +45,8 @@ #include <stdlib.h> #include <string.h> #include "pathnames.h" -#ifdef USE_BLACKLIST -#include <blacklist.h> +#ifdef USE_BLOCKLIST +#include <blocklist.h> #endif void logerr(const char *, ...) __printflike(1, 2) __dead2; @@ -144,8 +144,8 @@ main(int argc, char *argv[]) *ap = strtok(lp, " \t\r\n"); if (!*ap) { if (secure && ap == &av[4]) { -#ifdef USE_BLACKLIST - blacklist(1, STDIN_FILENO, "nousername"); +#ifdef USE_BLOCKLIST + blocklist(1, STDIN_FILENO, "nousername"); #endif puts("must provide username\r\n"); exit(1); @@ -153,8 +153,8 @@ main(int argc, char *argv[]) break; } if (secure && strchr(*ap, '@')) { -#ifdef USE_BLACKLIST - blacklist(1, STDIN_FILENO, "noforwarding"); +#ifdef USE_BLOCKLIST + blocklist(1, STDIN_FILENO, "noforwarding"); #endif puts("forwarding service denied\r\n"); exit(1); @@ -194,8 +194,8 @@ main(int argc, char *argv[]) } dup2(STDOUT_FILENO, STDERR_FILENO); -#ifdef USE_BLACKLIST - blacklist(0, STDIN_FILENO, "success"); +#ifdef USE_BLOCKLIST + blocklist(0, STDIN_FILENO, "success"); #endif execv(prog, comp); write(STDERR_FILENO, prog, strlen(prog)); diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index c776a815003c..b7cce777c4f6 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -319,8 +319,10 @@ ctld_enable="NO" # CAM Target Layer / iSCSI target daemon. local_unbound_enable="NO" # Local caching DNS resolver local_unbound_oomprotect="YES" # Don't kill local_unbound when swap space is exhausted. local_unbound_tls="NO" # Use DNS over TLS -blacklistd_enable="NO" # Run blacklistd daemon (YES/NO). -blacklistd_flags="" # Optional flags for blacklistd(8). +blacklistd_enable="NO" # Renamed to blocklistd_enable. +blacklistd_flags="" # Renamed to blocklistd_flags. +blocklistd_enable="NO" # Run blocklistd daemon (YES/NO). +blocklistd_flags="" # Optional flags for blocklistd(8). resolv_enable="YES" # Enable resolv / resolvconf # diff --git a/libexec/rc/rc.d/Makefile b/libexec/rc/rc.d/Makefile index f6d1a34ceb9e..093da31ed787 100644 --- a/libexec/rc/rc.d/Makefile +++ b/libexec/rc/rc.d/Makefile @@ -111,9 +111,10 @@ AUTOFS= automount \ automountd \ autounmountd -CONFGROUPS.${MK_BLACKLIST}+= BLOCKLIST +CONFGROUPS.${MK_BLOCKLIST}+= BLOCKLIST BLOCKLISTPACKAGE= blocklist -BLOCKLIST= blacklistd +BLOCKLIST= blacklistd \ + blocklistd CONFGROUPS.${MK_BLUETOOTH}+= BLUETOOTH BLUETOOTHPACKAGE= bluetooth diff --git a/libexec/rc/rc.d/blacklistd b/libexec/rc/rc.d/blacklistd index 5248b0ea3580..9157e258f43f 100755 --- a/libexec/rc/rc.d/blacklistd +++ b/libexec/rc/rc.d/blacklistd @@ -34,13 +34,21 @@ . /etc/rc.subr name="blacklistd" -desc="System blacklist daemon" +desc="The blacklist daemon has been renamed to blocklist" rcvar="blacklistd_enable" command="/usr/sbin/${name}" required_files="/etc/blacklistd.conf" +start_precmd="blacklistd_prestart" # no svcj options needed : ${blacklistd_svcj_options:=""} +blacklistd_prestart() +{ + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + echo "@ WARNING: blacklistd has been renamed to blocklistd @" + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" +} + load_rc_config $name run_rc_command "$1" diff --git a/libexec/rc/rc.d/blocklistd b/libexec/rc/rc.d/blocklistd new file mode 100644 index 000000000000..24cbae77fd40 --- /dev/null +++ b/libexec/rc/rc.d/blocklistd @@ -0,0 +1,46 @@ +#!/bin/sh +# +# Copyright (c) 2016 The FreeBSD Foundation +# +# This software was developed by Kurt Lidl under sponsorship from the +# FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# + +# PROVIDE: blocklistd +# REQUIRE: netif pf + +. /etc/rc.subr + +name="blocklistd" +desc="System blocklist daemon" +rcvar="blocklistd_enable" +command="/usr/sbin/${name}" +required_files="/etc/blocklistd.conf" + +# no svcj options needed +: ${blocklistd_svcj_options:=""} + +load_rc_config $name +run_rc_command "$1" diff --git a/release/Makefile.mirrors b/release/Makefile.mirrors index ed9420e926ce..924d289d1c44 100644 --- a/release/Makefile.mirrors +++ b/release/Makefile.mirrors @@ -407,7 +407,6 @@ pkgbase-repo-stage: mv pkgbase-repo.tar ${OSRELEASE}-pkgbase-repo.tar cp -p ${RELEASEDIR}/pkgbase/${OSRELEASE}-pkgbase-repo.tar \ ${PKGBASE_DIR}/Latest/${OSRELEASE}-pkgbase-repo.tar -. endfor . for CHECKSUM in ${CHECKSUM_FILES} cd ${RELEASEDIR}/pkgbase && \ ${CHECKSUM:tl} ${OSRELEASE}-pkgbase-repo.tar > CHECKSUM.${CHECKSUM} diff --git a/release/packages/ucl/acpi-all.ucl b/release/packages/ucl/acpi-all.ucl index 9e75822a8a04..9b63b825bd60 100644 --- a/release/packages/ucl/acpi-all.ucl +++ b/release/packages/ucl/acpi-all.ucl @@ -23,7 +23,7 @@ ACPI is a hardware standard allowing the operating system to monitor various hardware devices and system state. For example, ACPI can report whether the system is on AC or battery power. -This packages provides several utilities that can be used to interact with the +This package provides several utilities that can be used to interact with the ACPI implementation in the kernel: * The /etc/rc.d/power_profile service can be used to change system performance diff --git a/release/packages/ucl/audit-all.ucl b/release/packages/ucl/audit-all.ucl index 3324795d8d9c..0ff79f7c6b73 100644 --- a/release/packages/ucl/audit-all.ucl +++ b/release/packages/ucl/audit-all.ucl @@ -39,7 +39,7 @@ The audit facility implements the de facto industry standard BSM API, file formats, and command line interface, first found in the Solaris operating system. -This packages provides the auditing daemon auditd(8) and various utilities +This package provides the auditing daemon auditd(8) and various utilities used to manage the auditing system and work with audit data. EOD diff --git a/release/packages/ucl/blocklist-all.ucl b/release/packages/ucl/blocklist-all.ucl index 92f304ac9151..273df85fc22b 100644 --- a/release/packages/ucl/blocklist-all.ucl +++ b/release/packages/ucl/blocklist-all.ucl @@ -19,12 +19,14 @@ comment = "Network blocklist daemon" desc = <<EOD -The blacklistd(8) daemon monitors failed access attempts from remote network +The blocklistd(8) daemon monitors failed access attempts from remote network locations and automatically blocks the originating network address using the system packet filter. -blacklistd(8) relies on each network daemon to report access attempts, so -only daemons which have had blacklist support added will work. +blocklistd(8) relies on each network daemon to report access attempts, so +only daemons which have had blocklist support added will work. + +The blocklistd(8) daemon was previously named blacklistd(8). EOD annotations { diff --git a/release/packages/ucl/libbegemot-all.ucl b/release/packages/ucl/libbegemot-all.ucl index 812e94f72eaf..5bead26f69f8 100644 --- a/release/packages/ucl/libbegemot-all.ucl +++ b/release/packages/ucl/libbegemot-all.ucl @@ -41,8 +41,8 @@ calls are however clumsy to use and the usage of one of these calls is probably not portable to other systems - not all systems support both calls. The rpoll(3) family of functions is designed to overcome these restrictions. -They support the well known and understood technique of event driven programing -and, in addition to select(2) and poll(2) also support timers. +They support the well known and understood technique of event driven +programming and, in addition to select(2) and poll(2) also support timers. EOD annotations { diff --git a/release/packages/ucl/libbsdstat-all.ucl b/release/packages/ucl/libbsdstat-all.ucl index 144d4200fed9..56efee79a334 100644 --- a/release/packages/ucl/libbsdstat-all.ucl +++ b/release/packages/ucl/libbsdstat-all.ucl @@ -19,7 +19,7 @@ comment = "Periodic statistics library" desc = <<EOD -libbsdstat is a library for managing and display periodically collected +libbsdstat is a library for managing and displaying periodically collected statistics. EOD diff --git a/release/packages/ucl/mandoc-all.ucl b/release/packages/ucl/mandoc-all.ucl index 3948c4ce261e..ebd6a9da59e0 100644 --- a/release/packages/ucl/mandoc-all.ucl +++ b/release/packages/ucl/mandoc-all.ucl @@ -19,7 +19,7 @@ comment = "Online manual page reader" desc = <<EOD -This packages provides man(1), a utility which can format and display system +This package provides man(1), a utility which can format and display system manual pages, along with the related utilities apropos(1) and makewhatis(8), and the mandoc(1) rendering backend. EOD diff --git a/release/packages/ucl/yp-all.ucl b/release/packages/ucl/yp-all.ucl index f361f319b730..fb337394fc4c 100644 --- a/release/packages/ucl/yp-all.ucl +++ b/release/packages/ucl/yp-all.ucl @@ -20,7 +20,7 @@ comment = "Yellow Pages (YP) / Network Information Service (NIS)" desc = <<EOD YP, also called NIS, is a network protocol for sharing name service -information across machines on a network. This packages contain the YP +information across machines on a network. This package contains the YP server, YP management utilities, the YP-LDAP gateway (ypldap), YP client utilities and a sample Makefile for building the YP database. EOD diff --git a/release/tools/ec2-base.conf b/release/tools/ec2-base.conf index b6354db3d9d1..ffe2646240a5 100644 --- a/release/tools/ec2-base.conf +++ b/release/tools/ec2-base.conf @@ -36,5 +36,9 @@ vm_extra_pre_umount() { # Standard FreeBSD network configuration ec2_base_networking + # Add files from packages which weren't recorded in metalog + metalog_add_data ./usr/local/etc/dhclient.conf + metalog_add_data ./usr/local/etc/ssl/cert.pem + return 0 } diff --git a/release/tools/ec2-builder.conf b/release/tools/ec2-builder.conf index a55485fec0cd..3b0344f9eb9a 100644 --- a/release/tools/ec2-builder.conf +++ b/release/tools/ec2-builder.conf @@ -66,5 +66,8 @@ vm_extra_pre_umount() { EOF metalog_add_data ./boot/loader.conf + # Add files from packages which weren't recorded in metalog + metalog_add_data ./usr/local/etc/dhclient.conf + return 0 } diff --git a/release/tools/ec2-small.conf b/release/tools/ec2-small.conf index acaffbbc0c42..6564a59c2cf6 100644 --- a/release/tools/ec2-small.conf +++ b/release/tools/ec2-small.conf @@ -49,5 +49,8 @@ vm_extra_pre_umount() { # Standard FreeBSD network configuration ec2_base_networking + # Add files from packages which weren't recorded in metalog + metalog_add_data ./usr/local/etc/dhclient.conf + return 0 } diff --git a/release/tools/vmimage.subr b/release/tools/vmimage.subr index 15c4dd53e70b..c3c917dcd642 100644 --- a/release/tools/vmimage.subr +++ b/release/tools/vmimage.subr @@ -290,6 +290,11 @@ buildfs() { cat ${DESTDIR}/METALOG.pkg >> ${DESTDIR}/METALOG fi + # Sort METALOG file; makefs produces directories with 000 permissions + # if their contents are seen before the directories themselves. + env -i LC_COLLATE=C sort -u ${DESTDIR}/METALOG > ${DESTDIR}/METALOG.sorted + mv ${DESTDIR}/METALOG.sorted ${DESTDIR}/METALOG + case "${VMFS}" in ufs) cd ${DESTDIR} && ${MAKEFS} ${MAKEFSARGS} -o label=rootfs -o version=2 -o softupdates=1 \ diff --git a/secure/libexec/sshd-auth/Makefile b/secure/libexec/sshd-auth/Makefile index a127b50b407a..0ee49585a023 100644 --- a/secure/libexec/sshd-auth/Makefile +++ b/secure/libexec/sshd-auth/Makefile @@ -31,11 +31,11 @@ CFLAGS+= -DUSE_BSM_AUDIT=1 -DHAVE_GETAUDIT_ADDR=1 LIBADD+= bsm .endif -.if ${MK_BLACKLIST_SUPPORT} != "no" -CFLAGS+= -DUSE_BLACKLIST=1 -I${SRCTOP}/contrib/blocklist/include -SRCS+= blacklist.c -LIBADD+= blacklist -LDFLAGS+=-L${LIBBLACKLISTDIR} +.if ${MK_BLOCKLIST_SUPPORT} != "no" +CFLAGS+= -DUSE_BLOCKLIST=1 -I${SRCTOP}/contrib/blocklist/include +SRCS+= blocklist.c +LIBADD+= blocklist +LDFLAGS+=-L${LIBBLOCKLISTDIR} .endif .if ${MK_KERBEROS_SUPPORT} != "no" diff --git a/secure/libexec/sshd-session/Makefile b/secure/libexec/sshd-session/Makefile index 9e95c94000ff..a7849f2a35f8 100644 --- a/secure/libexec/sshd-session/Makefile +++ b/secure/libexec/sshd-session/Makefile @@ -29,11 +29,11 @@ CFLAGS+= -DUSE_BSM_AUDIT=1 -DHAVE_GETAUDIT_ADDR=1 LIBADD+= bsm .endif -.if ${MK_BLACKLIST_SUPPORT} != "no" -CFLAGS+= -DUSE_BLACKLIST=1 -I${SRCTOP}/contrib/blocklist/include -SRCS+= blacklist.c -LIBADD+= blacklist -LDFLAGS+=-L${LIBBLACKLISTDIR} +.if ${MK_BLOCKLIST_SUPPORT} != "no" +CFLAGS+= -DUSE_BLOCKLIST=1 -I${SRCTOP}/contrib/blocklist/include +SRCS+= blocklist.c +LIBADD+= blocklist +LDFLAGS+=-L${LIBBLOCKLISTDIR} .endif .if ${MK_KERBEROS_SUPPORT} != "no" diff --git a/secure/usr.sbin/sshd/Makefile.depend.options b/secure/usr.sbin/sshd/Makefile.depend.options index 69af5a2e8d79..c8816eb881fb 100644 --- a/secure/usr.sbin/sshd/Makefile.depend.options +++ b/secure/usr.sbin/sshd/Makefile.depend.options @@ -1,5 +1,5 @@ # This file is not autogenerated - take care! -DIRDEPS_OPTIONS= AUDIT BLACKLIST_SUPPORT GSSAPI KERBEROS_SUPPORT TCP_WRAPPERS +DIRDEPS_OPTIONS= AUDIT BLOCKLIST_SUPPORT GSSAPI KERBEROS_SUPPORT TCP_WRAPPERS .include <dirdeps-options.mk> diff --git a/share/man/man5/periodic.conf.5 b/share/man/man5/periodic.conf.5 index a2ed2b09d772..8910895d9b89 100644 --- a/share/man/man5/periodic.conf.5 +++ b/share/man/man5/periodic.conf.5 @@ -981,7 +981,7 @@ since yesterday's check. Space-separated list of additional anchors whose denied packets log entries to show. The main ruleset (i.e., the empty-string anchor) and any -.Xr blacklistd 8 +.Xr blocklistd 8 anchors, if present, are always shown. .It Va security_status_pfdenied_period .Pq Vt str diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index 5c8ae5b83e5f..1bb609336532 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,5 +1,5 @@ .\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman. -.Dd September 25, 2025 +.Dd October 1, 2025 .Dt SRC.CONF 5 .Os .Sh NAME @@ -226,10 +226,15 @@ options provide "full" Relocation Read-Only (RELRO) support. With full RELRO the entire GOT is made read-only after performing relocation at startup, avoiding GOT overwrite attacks. .It Va WITHOUT_BLACKLIST -Set this if you do not want to build -.Xr blacklistd 8 -and -.Xr blacklistctl 8 . +This option has been renamed to +.Va WITHOUT_BLOCKLIST . +When set, it enforces these options: +.Pp +.Bl -item -compact +.It +.Va WITHOUT_BLOCKLIST +.El +.Pp When set, these options are also in effect: .Pp .Bl -inset -compact @@ -237,10 +242,36 @@ When set, these options are also in effect: (unless .Va WITH_BLACKLIST_SUPPORT is set explicitly) +.It Va WITHOUT_BLOCKLIST_SUPPORT +(unless +.Va WITH_BLOCKLIST_SUPPORT +is set explicitly) .El .It Va WITHOUT_BLACKLIST_SUPPORT +This option has been renamed to +.Va WITHOUT_BLOCKLIST_SUPPORT . +When set, it enforces these options: +.Pp +.Bl -item -compact +.It +.Va WITHOUT_BLOCKLIST_SUPPORT +.El +.It Va WITHOUT_BLOCKLIST +Set this if you do not want to build +.Xr blocklistd 8 +and +.Xr blocklistctl 8 . +When set, these options are also in effect: +.Pp +.Bl -inset -compact +.It Va WITHOUT_BLOCKLIST_SUPPORT +(unless +.Va WITH_BLOCKLIST_SUPPORT +is set explicitly) +.El +.It Va WITHOUT_BLOCKLIST_SUPPORT Build some programs without -.Xr libblacklist 3 +.Xr libblocklist 3 support, like .Xr fingerd 8 and diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 3ff4c4e90a1b..2f099e0579b2 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -27,6 +27,7 @@ LIBAVL?= ${LIBDESTDIR}${LIBDIR_BASE}/libavl.a LIBBE?= ${LIBDESTDIR}${LIBDIR_BASE}/libbe.a LIBBEGEMOT?= ${LIBDESTDIR}${LIBDIR_BASE}/libbegemot.a LIBBLACKLIST?= ${LIBDESTDIR}${LIBDIR_BASE}/libblacklist.a +LIBBLOCKLIST?= ${LIBDESTDIR}${LIBDIR_BASE}/libblocklist.a LIBBLOCKSRUNTIME?= ${LIBDESTDIR}${LIBDIR_BASE}/libBlocksRuntime.a LIBBLUETOOTH?= ${LIBDESTDIR}${LIBDIR_BASE}/libbluetooth.a LIBBSDXML?= ${LIBDESTDIR}${LIBDIR_BASE}/libbsdxml.a diff --git a/share/mk/local.dirdeps-options.mk b/share/mk/local.dirdeps-options.mk index 4eef5311375e..5773c4979e56 100644 --- a/share/mk/local.dirdeps-options.mk +++ b/share/mk/local.dirdeps-options.mk @@ -2,6 +2,7 @@ # avoid duplication DIRDEPS.AUDIT.yes= lib/libbsm DIRDEPS.BLACKLIST_SUPPORT.yes+= lib/libblacklist +DIRDEPS.BLOCKLIST_SUPPORT.yes+= lib/libblocklist DIRDEPS.CASPER.yes+= lib/libcasper/libcasper DIRDEPS.GSSAPI.yes+= lib/libgssapi DIRDEPS.JAIL.yes+= lib/libjail diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index 3e108591251a..b2ed63759c19 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -264,8 +264,12 @@ _LIBRARIES+= \ .if ${MK_BLACKLIST} != "no" _LIBRARIES+= \ - blacklist \ + blacklist +.endif +.if ${MK_BLOCKLIST} != "no" +_LIBRARIES+= \ + blocklist .endif .if ${MK_OFED} != "no" @@ -319,6 +323,9 @@ _DP_zstd= pthread .if ${MK_BLACKLIST} != "no" _DP_blacklist+= pthread .endif +.if ${MK_BLOCKLIST} != "no" +_DP_blocklist+= pthread +.endif _DP_crypto= pthread # See comment by _DP_archive above .if ${.MAKE.OS} == "FreeBSD" || !defined(BOOTSTRAPPING) @@ -865,6 +872,7 @@ LIBGTESTDIR= ${_LIB_OBJTOP}/lib/googletest/gtest LIBGTEST_MAINDIR= ${_LIB_OBJTOP}/lib/googletest/gtest_main LIBALIASDIR= ${_LIB_OBJTOP}/lib/libalias/libalias LIBBLACKLISTDIR= ${_LIB_OBJTOP}/lib/libblacklist +LIBBLOCKLISTDIR= ${_LIB_OBJTOP}/lib/libblocklist LIBBLOCKSRUNTIMEDIR= ${_LIB_OBJTOP}/lib/libblocksruntime LIBBSNMPDIR= ${_LIB_OBJTOP}/lib/libbsnmp/libbsnmp LIBCASPERDIR= ${_LIB_OBJTOP}/lib/libcasper/libcasper diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 9bd4e6a1842f..446f78a2acf3 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -66,6 +66,7 @@ __DEFAULT_YES_OPTIONS = \ AUTOFS \ BHYVE \ BLACKLIST \ + BLOCKLIST \ BLUETOOTH \ BOOT \ BOOTPARAMD \ @@ -242,6 +243,7 @@ __LIBC_MALLOC_DEFAULT= jemalloc # .for var in \ BLACKLIST \ + BLOCKLIST \ BZIP2 \ INET \ INET6 \ @@ -391,6 +393,14 @@ MK_SOURCELESS_HOST:= no MK_SOURCELESS_UCODE:= no .endif +.if ${MK_BLACKLIST} == "no" +MK_BLOCKLIST:= no +.endif + +.if ${MK_BLACKLIST_SUPPORT} == "no" +MK_BLOCKLIST_SUPPORT:= no +.endif + .if ${MK_CDDL} == "no" MK_CTF:= no MK_DTRACE:= no diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c index 03116cb0641c..3a8de2b2bfee 100644 --- a/sys/netpfil/ipfw/ip_dn_io.c +++ b/sys/netpfil/ipfw/ip_dn_io.c @@ -43,6 +43,7 @@ #include <sys/priv.h> #include <sys/proc.h> #include <sys/rwlock.h> +#include <sys/sdt.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/sysctl.h> @@ -70,6 +71,9 @@ #endif #include <netpfil/ipfw/dn_sched.h> +SDT_PROVIDER_DEFINE(dummynet); +SDT_PROBE_DEFINE2(dummynet, , , drop, "struct mbuf *", "struct dn_queue *"); + /* * We keep a private variable for the simulation time, but we could * probably use an existing one ("softticks" in sys/kern/kern_timeout.c) @@ -545,6 +549,7 @@ dn_enqueue(struct dn_queue *q, struct mbuf* m, int drop) drop: V_dn_cfg.io_pkt_drop++; + SDT_PROBE2(dummynet, , , drop, m, q); q->ni.drops++; ni->drops++; FREE_PKT(m); @@ -1001,6 +1006,7 @@ done: dropit: V_dn_cfg.io_pkt_drop++; + SDT_PROBE2(dummynet, , , drop, m, q); DN_BH_WUNLOCK(); if (m) FREE_PKT(m); diff --git a/targets/pseudo/userland/Makefile.depend b/targets/pseudo/userland/Makefile.depend index 5f72461ab12e..e21d7dd70eb7 100644 --- a/targets/pseudo/userland/Makefile.depend +++ b/targets/pseudo/userland/Makefile.depend @@ -806,6 +806,12 @@ DIRDEPS+= \ usr.sbin/blacklistd .endif +.if ${MK_BLOCKLIST_SUPPORT} != "no" +DIRDEPS+= \ + usr.sbin/blocklistctl \ + usr.sbin/blocklistd +.endif + .if ${MK_CXGBETOOL} != "no" DIRDEPS+= usr.sbin/cxgbetool .endif diff --git a/targets/pseudo/userland/lib/Makefile.depend b/targets/pseudo/userland/lib/Makefile.depend index 8e1b0282be48..63c7e69719c2 100644 --- a/targets/pseudo/userland/lib/Makefile.depend +++ b/targets/pseudo/userland/lib/Makefile.depend @@ -255,6 +255,10 @@ DIRDEPS+= \ DIRDEPS+= lib/libblacklist .endif +.if ${MK_BLOCKLIST_SUPPORT} != "no" +DIRDEPS+= lib/libblocklist +.endif + .if ${MK_ZFS} != "no" DIRDEPS+= cddl/lib/libzutil .endif diff --git a/targets/pseudo/userland/libexec/Makefile.depend b/targets/pseudo/userland/libexec/Makefile.depend index 4a6d72f914e3..9e5eec3f0c81 100644 --- a/targets/pseudo/userland/libexec/Makefile.depend +++ b/targets/pseudo/userland/libexec/Makefile.depend @@ -38,8 +38,8 @@ DIRDEPS = \ libexec/ypxfr \ -.if ${MK_BLACKLIST_SUPPORT} != "no" -DIRDEPS+= libexec/blacklistd-helper +.if ${MK_BLOCKLIST_SUPPORT} != "no" +DIRDEPS+= libexec/blocklistd-helper .endif .if ${MK_DMAGENT} != "no" diff --git a/tests/sys/netpfil/pf/ether.sh b/tests/sys/netpfil/pf/ether.sh index f0fdce50a7d3..f15dff06f9cd 100644 --- a/tests/sys/netpfil/pf/ether.sh +++ b/tests/sys/netpfil/pf/ether.sh @@ -287,6 +287,7 @@ captive_body() # Run the echo server only on the gw, so we know we've redirectly # correctly if we get an echo message. jexec gw /usr/sbin/inetd -p ${PWD}/echo_inetd.pid $(atf_get_srcdir)/echo_inetd.conf + sleep 1 # Confirm that we're getting redirected atf_check -s exit:0 -o match:"^foo$" -x "echo foo | nc -N 198.51.100.2 7" @@ -305,6 +306,7 @@ captive_body() # Start a server in srv jexec srv /usr/sbin/inetd -p ${PWD}/echo_inetd.pid $(atf_get_srcdir)/echo_inetd.conf + sleep 1 # And now we can talk to that one. atf_check -s exit:0 -o match:"^foo$" -x "echo foo | nc -N 198.51.100.2 7" @@ -364,6 +366,7 @@ captive_long_body() jexec gw /usr/sbin/inetd -p ${PWD}/gw.pid $(atf_get_srcdir)/echo_inetd.conf jexec srv /usr/sbin/inetd -p ${PWD}/srv.pid $(atf_get_srcdir)/daytime_inetd.conf + sleep p1 echo foo | nc -N 198.51.100.2 13 diff --git a/tests/sys/netpfil/pf/nat.sh b/tests/sys/netpfil/pf/nat.sh index e55f46418221..1ef87cee3598 100644 --- a/tests/sys/netpfil/pf/nat.sh +++ b/tests/sys/netpfil/pf/nat.sh @@ -55,6 +55,9 @@ exhaust_body() jexec echo ifconfig ${epair_echo}b 198.51.100.2/24 up jexec echo /usr/sbin/inetd -p ${PWD}/inetd-echo.pid $(atf_get_srcdir)/echo_inetd.conf + # Disable checksum offload on one of the interfaces to ensure pf handles that + jexec nat ifconfig ${epair_nat}a -txcsum + # Enable pf! jexec nat pfctl -e pft_set_rules nat \ @@ -474,6 +477,7 @@ no_addrs_random_cleanup() pft_cleanup } +atf_test_case "nat_pass" "cleanup" nat_pass_head() { atf_set descr 'IPv4 NAT on pass rule' @@ -505,6 +509,7 @@ nat_pass_cleanup() pft_cleanup } +atf_test_case "nat_match" "cleanup" nat_match_head() { atf_set descr 'IPv4 NAT on match rule' @@ -644,6 +649,7 @@ map_e_pass_cleanup() pft_cleanup } +atf_test_case "binat_compat" "cleanup" binat_compat_head() { atf_set descr 'IPv4 BINAT with nat ruleset' @@ -710,6 +716,7 @@ binat_compat_cleanup() kill $(cat ${PWD}/inetd_tester.pid) } +atf_test_case "binat_match" "cleanup" binat_match_head() { atf_set descr 'IPv4 BINAT with nat ruleset' diff --git a/tests/sys/netpfil/pf/rules_counter.sh b/tests/sys/netpfil/pf/rules_counter.sh index 98f96a7adca1..e80a46e9d6c6 100644 --- a/tests/sys/netpfil/pf/rules_counter.sh +++ b/tests/sys/netpfil/pf/rules_counter.sh @@ -153,6 +153,7 @@ atf_test_case "4G" "cleanup" { atf_set descr 'Test keepcounter for values above 32 bits' atf_set require.user root + atf_set timeout 900 } 4G_body() diff --git a/tests/sys/netpfil/pf/syncookie.sh b/tests/sys/netpfil/pf/syncookie.sh index fad90f3b2618..598ac17c67f5 100644 --- a/tests/sys/netpfil/pf/syncookie.sh +++ b/tests/sys/netpfil/pf/syncookie.sh @@ -253,6 +253,9 @@ Creativity, no. __EOF__ nc -l $addr $port >out & + # Give the background nc time to start + sleep 1 + atf_check nc -N $addr $port < in atf_check -o file:in cat out diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 13d7703148d2..7cf742616e63 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -161,7 +161,26 @@ OLD_FILES+=usr/share/man/man8/bhyveload.8.gz OLD_DIRS+=usr/share/examples/bhyve .endif -.if ${MK_BLACKLIST} == no +.if ${MK_BLOCKLIST} == no +OLD_FILES+=etc/blocklistd.conf +OLD_FILES+=etc/rc.d/blocklistd +OLD_FILES+=usr/include/blocklist.h +OLD_FILES+=usr/lib/libblocklist.a +OLD_FILES+=usr/lib/libblocklist_p.a +OLD_FILES+=usr/lib/libblocklist.so +OLD_LIBS+=usr/lib/libblocklist.so.0 +OLD_FILES+=usr/libexec/blocklistd-helper +OLD_FILES+=usr/sbin/blocklistctl +OLD_FILES+=usr/sbin/blocklistd +OLD_FILES+=usr/share/man/man3/blocklist.3.gz +OLD_FILES+=usr/share/man/man3/blocklist_close.3.gz +OLD_FILES+=usr/share/man/man3/blocklist_open.3.gz +OLD_FILES+=usr/share/man/man3/blocklist_r.3.gz +OLD_FILES+=usr/share/man/man3/blocklist_sa.3.gz +OLD_FILES+=usr/share/man/man3/blocklist_sa_r.3.gz +OLD_FILES+=usr/share/man/man5/blocklistd.conf.5.gz +OLD_FILES+=usr/share/man/man8/blocklistctl.8.gz +OLD_FILES+=usr/share/man/man8/blocklistd.8.gz OLD_FILES+=etc/blacklistd.conf OLD_FILES+=etc/rc.d/blacklistd OLD_FILES+=usr/include/blacklist.h diff --git a/tools/build/options/WITHOUT_BLACKLIST b/tools/build/options/WITHOUT_BLACKLIST index c54c83f27553..df9c9a41227f 100644 --- a/tools/build/options/WITHOUT_BLACKLIST +++ b/tools/build/options/WITHOUT_BLACKLIST @@ -1,4 +1,2 @@ -Set this if you do not want to build -.Xr blacklistd 8 -and -.Xr blacklistctl 8 . +This option has been renamed to +.Va WITHOUT_BLOCKLIST . diff --git a/tools/build/options/WITHOUT_BLACKLIST_SUPPORT b/tools/build/options/WITHOUT_BLACKLIST_SUPPORT index ff1c2c43d595..cd484727d636 100644 --- a/tools/build/options/WITHOUT_BLACKLIST_SUPPORT +++ b/tools/build/options/WITHOUT_BLACKLIST_SUPPORT @@ -1,6 +1,2 @@ -Build some programs without -.Xr libblacklist 3 -support, like -.Xr fingerd 8 -and -.Xr sshd 8 . +This option has been renamed to +.Va WITHOUT_BLOCKLIST_SUPPORT . diff --git a/tools/build/options/WITHOUT_BLOCKLIST b/tools/build/options/WITHOUT_BLOCKLIST new file mode 100644 index 000000000000..c456a98c672f --- /dev/null +++ b/tools/build/options/WITHOUT_BLOCKLIST @@ -0,0 +1,4 @@ +Set this if you do not want to build +.Xr blocklistd 8 +and +.Xr blocklistctl 8 . diff --git a/tools/build/options/WITHOUT_BLOCKLIST_SUPPORT b/tools/build/options/WITHOUT_BLOCKLIST_SUPPORT new file mode 100644 index 000000000000..f06ebc6e4263 --- /dev/null +++ b/tools/build/options/WITHOUT_BLOCKLIST_SUPPORT @@ -0,0 +1,6 @@ +Build some programs without +.Xr libblocklist 3 +support, like +.Xr fingerd 8 +and +.Xr sshd 8 . diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 3c5fd0973a43..44679ca290a5 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -121,6 +121,8 @@ SUBDIR.${MK_AUTHPF}+= authpf SUBDIR.${MK_AUTOFS}+= autofs SUBDIR.${MK_BLACKLIST}+= blacklistctl SUBDIR.${MK_BLACKLIST}+= blacklistd +SUBDIR.${MK_BLOCKLIST}+= blocklistctl +SUBDIR.${MK_BLOCKLIST}+= blocklistd SUBDIR.${MK_BLUETOOTH}+= bluetooth SUBDIR.${MK_BOOTPARAMD}+= bootparamd SUBDIR.${MK_BSDINSTALL}+= bsdinstall diff --git a/usr.sbin/blacklistctl/Makefile b/usr.sbin/blacklistctl/Makefile index 7bdff4158bb4..41c5f44b072b 100644 --- a/usr.sbin/blacklistctl/Makefile +++ b/usr.sbin/blacklistctl/Makefile @@ -4,19 +4,20 @@ BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist PACKAGE= blocklist PROG= blacklistctl -SRCS= blacklistctl.c conf.c state.c support.c internal.c \ +SRCS= blacklistctl.c conf.c state.c support.c old_internal.c \ sockaddr_snprintf.c pidfile.c strtoi.c popenve.c MAN= blacklistctl.8 LDFLAGS+=-L${LIBBLACKLISTDIR} -LIBADD+= blacklist util +LIBADD+= blocklist util CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \ + -D_PATH_BLCONF=\"/etc/blacklistd.conf\" \ -D_PATH_BLCONTROL=\"/usr/libexec/blacklistd-helper\" \ -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_FPARSELN \ -DHAVE_GETPROGNAME -DHAVE_STRLCAT -DHAVE_STRLCPY \ - -DHAVE_STRUCT_SOCKADDR_SA_LEN + -DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_SYS_CDEFS_H # CFLAGS+= -D_REENTRANT .include <bsd.prog.mk> diff --git a/usr.sbin/blacklistd/Makefile b/usr.sbin/blacklistd/Makefile index e0a3ddd80881..490b12d46968 100644 --- a/usr.sbin/blacklistd/Makefile +++ b/usr.sbin/blacklistd/Makefile @@ -5,19 +5,20 @@ PACKAGE= blocklist CONFS= blacklistd.conf PROG= blacklistd -SRCS= blacklistd.c conf.c run.c state.c support.c internal.c \ - sockaddr_snprintf.c pidfile.c strtoi.c popenve.c +SRCS= blacklistd.c conf.c run.c state.c support.c old_internal.c \ + sockaddr_snprintf.c pidfile.c strtoi.c popenve.c vsyslog_r.c MAN= blacklistd.8 blacklistd.conf.5 LDFLAGS+=-L${LIBBLACKLISTDIR} -LIBADD+= blacklist util +LIBADD+= blocklist util CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \ + -D_PATH_BLCONF=\"/etc/blacklistd.conf\" \ -D_PATH_BLCONTROL=\"/usr/libexec/blacklistd-helper\" \ -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_FPARSELN \ -DHAVE_GETPROGNAME -DHAVE_STRLCAT -DHAVE_STRLCPY \ - -DHAVE_STRUCT_SOCKADDR_SA_LEN + -DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_SYS_CDEFS_H # CFLAGS+= -D_REENTRANT .include <bsd.prog.mk> diff --git a/usr.sbin/blacklistd/blacklistd.conf b/usr.sbin/blacklistd/blacklistd.conf index b8dee6768cc7..ec995e038574 100644 --- a/usr.sbin/blacklistd/blacklistd.conf +++ b/usr.sbin/blacklistd/blacklistd.conf @@ -1,6 +1,9 @@ -# +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ The file blacklistd.conf has been renamed to blocklistd.conf @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + # Blacklist rule -# adr/mask:port type proto owner name nfail disable +# adr/mask:port type proto owner name nfail duration [local] ssh stream * * * 3 24h ftp stream * * * 3 24h @@ -9,8 +12,9 @@ submission stream * * * 3 24h #6161 stream tcp6 christos * 2 10m * * * * * 3 60 -# adr/mask:port type proto owner name nfail disable +# adr/mask:port type proto owner name nfail duration [remote] #129.168.0.0/16 * * * = * * +#[2001:db8::]/32:ssh * * * = * * #6161 = = = =/24 = = #* stream tcp * = = = diff --git a/usr.sbin/blocklistctl/Makefile b/usr.sbin/blocklistctl/Makefile new file mode 100644 index 000000000000..55891bfb2670 --- /dev/null +++ b/usr.sbin/blocklistctl/Makefile @@ -0,0 +1,22 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist +.PATH: ${BLOCKLIST_DIR}/bin ${BLOCKLIST_DIR}/port + +PACKAGE= blocklist + +PROG= blocklistctl +SRCS= blocklistctl.c conf.c state.c support.c internal.c \ + sockaddr_snprintf.c pidfile.c strtoi.c popenve.c +MAN= blocklistctl.8 + +LDFLAGS+=-L${LIBBLOCKLISTDIR} +LIBADD+= blocklist util + +CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \ + -D_PATH_BLCONTROL=\"/usr/libexec/blocklistd-helper\" \ + -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \ + -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_FPARSELN \ + -DHAVE_GETPROGNAME -DHAVE_STRLCAT -DHAVE_STRLCPY \ + -DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_SYS_CDEFS_H +# CFLAGS+= -D_REENTRANT + +.include <bsd.prog.mk> diff --git a/usr.sbin/blocklistctl/Makefile.depend b/usr.sbin/blocklistctl/Makefile.depend new file mode 100644 index 000000000000..6b74110bfe08 --- /dev/null +++ b/usr.sbin/blocklistctl/Makefile.depend @@ -0,0 +1,18 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/arpa \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libblocklist \ + lib/libc \ + lib/libcompiler_rt \ + lib/libutil \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/blocklistd/Makefile b/usr.sbin/blocklistd/Makefile new file mode 100644 index 000000000000..ccee9637e208 --- /dev/null +++ b/usr.sbin/blocklistd/Makefile @@ -0,0 +1,23 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist +.PATH: ${BLOCKLIST_DIR}/bin ${BLOCKLIST_DIR}/port + +PACKAGE= blocklist + +CONFS= blocklistd.conf +PROG= blocklistd +SRCS= blocklistd.c conf.c run.c state.c support.c internal.c \ + sockaddr_snprintf.c pidfile.c strtoi.c popenve.c vsyslog_r.c +MAN= blocklistd.8 blocklistd.conf.5 + +LDFLAGS+=-L${LIBBLOCKLISTDIR} +LIBADD+= blocklist util + +CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \ + -D_PATH_BLCONTROL=\"/usr/libexec/blocklistd-helper\" \ + -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \ + -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_FPARSELN \ + -DHAVE_GETPROGNAME -DHAVE_STRLCAT -DHAVE_STRLCPY \ + -DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_SYS_CDEFS_H +# CFLAGS+= -D_REENTRANT + +.include <bsd.prog.mk> diff --git a/usr.sbin/blocklistd/Makefile.depend b/usr.sbin/blocklistd/Makefile.depend new file mode 100644 index 000000000000..6b74110bfe08 --- /dev/null +++ b/usr.sbin/blocklistd/Makefile.depend @@ -0,0 +1,18 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/arpa \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libblocklist \ + lib/libc \ + lib/libcompiler_rt \ + lib/libutil \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/blocklistd/blocklistd.conf b/usr.sbin/blocklistd/blocklistd.conf new file mode 100644 index 000000000000..c6c7f7c2fafc --- /dev/null +++ b/usr.sbin/blocklistd/blocklistd.conf @@ -0,0 +1,16 @@ +# Blocklist rule +# adr/mask:port type proto owner name nfail duration +[local] +ssh stream * * * 3 24h +ftp stream * * * 3 24h +smtp stream * * * 3 24h +submission stream * * * 3 24h +#6161 stream tcp6 christos * 2 10m +* * * * * 3 60 + +# adr/mask:port type proto owner name nfail duration +[remote] +#129.168.0.0/16 * * * = * * +#[2001:db8::]/32:ssh * * * = * * +#6161 = = = =/24 = = +#* stream tcp * = = = diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto index 61d52065af2a..8058b1a41dbf 100755 --- a/usr.sbin/bsdinstall/scripts/auto +++ b/usr.sbin/bsdinstall/scripts/auto @@ -209,9 +209,9 @@ if [ ! -f $BSDINSTALL_DISTDIR/MANIFEST ]; then PKGBASE=yes else bsddialog --backtitle "$OSNAME Installer" --title "Select Installation Type" \ - --yes-label "Traditional" --no-label "Packages (Experimental)" --yesno \ + --yes-label "Distribution Sets" --no-label "Packages (Tech Preview)" --yesno \ $PKGBASE_DEFAULT_BUTTON \ - "Would you like to install the base system using traditional distribution sets or packages (experimental)?" 0 0 + "Would you like to install the base system using traditional distribution sets or packages (technology preview)?" 0 0 if [ $? -eq 1 ]; then PKGBASE=yes fi diff --git a/usr.sbin/bsdinstall/scripts/jail b/usr.sbin/bsdinstall/scripts/jail index f2c7ef2b37de..3b1b2ee98fff 100755 --- a/usr.sbin/bsdinstall/scripts/jail +++ b/usr.sbin/bsdinstall/scripts/jail @@ -175,8 +175,8 @@ fi if [ ! "$nonInteractive" == "YES" ]; then bsddialog --backtitle "$OSNAME Installer" --title "Select Installation Type" \ - --yes-label "Traditional" --no-label "Packages (Experimental)" --yesno \ - "Would you like to install the base system using traditional distribution sets or packages (experimental)?" 0 0 + --yes-label "Distribution Sets" --no-label "Packages (Tech Preview)" --yesno \ + "Would you like to install the base system using traditional distribution sets or packages (technology preview)?" 0 0 if [ $? -eq 1 ]; then PKGBASE=yes fi diff --git a/usr.sbin/periodic/etc/security/520.pfdenied b/usr.sbin/periodic/etc/security/520.pfdenied index 9852936257bc..d87dfa0ae64c 100755 --- a/usr.sbin/periodic/etc/security/520.pfdenied +++ b/usr.sbin/periodic/etc/security/520.pfdenied @@ -41,7 +41,7 @@ rc=0 if check_yesno_period security_status_pfdenied_enable then TMP=`mktemp -t security` - for _a in "" $(pfctl -a "blacklistd" -sA 2>/dev/null) ${security_status_pfdenied_additionalanchors} + for _a in "" $(pfctl -a "blacklistd" -sA 2>/dev/null) $(pfctl -a "blocklistd" -sA 2>/dev/null) ${security_status_pfdenied_additionalanchors} do pfctl -a "${_a}" -sr -v -z 2>/dev/null | \ nawk '{if (/^block/) {buf=$0; getline; gsub(" +"," ",$0); if ($5 > 0) print buf$0;} }' >> ${TMP} |