From e3c1423c58bf146705e080460f0d5db7eaf86a9c Mon Sep 17 00:00:00 2001 From: Lucas Holt Date: Tue, 22 Sep 2026 13:58:20 -0400 Subject: [PATCH 1/4] Import blocklist 2026-04-09 (46419aa) Upstream hash 46419aa7eea2cebc0cbc74c7b3aba8592cddc5bb. Obtained from: https://github.com/zoulasc/blocklist AI-Assisted-by: Claude Fable 5.1 Signed-off-by: Lucas Holt --- Makefile | 5 + Makefile.inc | 11 + README | 113 +++ TODO | 64 ++ bin/Makefile | 15 + bin/blocklistctl.8 | 134 ++++ bin/blocklistctl.c | 170 ++++ bin/blocklistd.8 | 301 +++++++ bin/blocklistd.c | 594 ++++++++++++++ bin/blocklistd.conf.5 | 237 ++++++ bin/conf.c | 1360 ++++++++++++++++++++++++++++++++ bin/conf.h | 66 ++ bin/internal.c | 50 ++ bin/internal.h | 57 ++ bin/run.c | 160 ++++ bin/run.h | 41 + bin/state.c | 237 ++++++ bin/state.h | 62 ++ bin/support.c | 163 ++++ bin/support.h | 45 ++ diff/ftpd.diff | 91 +++ diff/named.diff | 161 ++++ diff/postfix.diff | 98 +++ diff/proftpd.diff | 124 +++ diff/ssh.diff | 150 ++++ etc/Makefile | 10 + etc/blocklistd.conf | 15 + etc/ipf.conf | 45 ++ etc/npf.conf | 15 + etc/rc.d/Makefile | 6 + etc/rc.d/blocklistd | 57 ++ include/Makefile | 10 + include/bl.h | 79 ++ include/blocklist.h | 65 ++ lib/Makefile | 19 + lib/bl.c | 554 +++++++++++++ lib/blocklist.c | 117 +++ lib/libblocklist.3 | 177 +++++ lib/shlib_version | 2 + libexec/Makefile | 6 + libexec/blocklistd-helper | 272 +++++++ port/Makefile.am | 39 + port/_strtoi.h | 93 +++ port/clock_gettime.c | 17 + port/configure.ac | 93 +++ port/debian/blocklist.manpages | 4 + port/debian/changelog | 6 + port/debian/compat | 1 + port/debian/control | 21 + port/debian/copyright | 38 + port/debian/install | 1 + port/debian/rules | 15 + port/debian/source/format | 1 + port/fgetln.c | 106 +++ port/fparseln.c | 238 ++++++ port/getprogname.c | 24 + port/m4/.cvsignore | 1 + port/pidfile.c | 185 +++++ port/popenve.c | 279 +++++++ port/port.h | 108 +++ port/sockaddr_snprintf.c | 385 +++++++++ port/strlcat.c | 99 +++ port/strlcpy.c | 81 ++ port/strtoi.c | 63 ++ port/vsyslog_r.c | 13 + test/Makefile | 12 + test/cltest.c | 138 ++++ test/srvtest.c | 238 ++++++ 68 files changed, 8257 insertions(+) create mode 100644 Makefile create mode 100644 Makefile.inc create mode 100644 README create mode 100644 TODO create mode 100644 bin/Makefile create mode 100644 bin/blocklistctl.8 create mode 100644 bin/blocklistctl.c create mode 100644 bin/blocklistd.8 create mode 100644 bin/blocklistd.c create mode 100644 bin/blocklistd.conf.5 create mode 100644 bin/conf.c create mode 100644 bin/conf.h create mode 100644 bin/internal.c create mode 100644 bin/internal.h create mode 100644 bin/run.c create mode 100644 bin/run.h create mode 100644 bin/state.c create mode 100644 bin/state.h create mode 100644 bin/support.c create mode 100644 bin/support.h create mode 100644 diff/ftpd.diff create mode 100644 diff/named.diff create mode 100644 diff/postfix.diff create mode 100644 diff/proftpd.diff create mode 100644 diff/ssh.diff create mode 100644 etc/Makefile create mode 100644 etc/blocklistd.conf create mode 100644 etc/ipf.conf create mode 100644 etc/npf.conf create mode 100644 etc/rc.d/Makefile create mode 100644 etc/rc.d/blocklistd create mode 100644 include/Makefile create mode 100644 include/bl.h create mode 100644 include/blocklist.h create mode 100644 lib/Makefile create mode 100644 lib/bl.c create mode 100644 lib/blocklist.c create mode 100644 lib/libblocklist.3 create mode 100644 lib/shlib_version create mode 100644 libexec/Makefile create mode 100755 libexec/blocklistd-helper create mode 100644 port/Makefile.am create mode 100644 port/_strtoi.h create mode 100644 port/clock_gettime.c create mode 100644 port/configure.ac create mode 100644 port/debian/blocklist.manpages create mode 100644 port/debian/changelog create mode 100644 port/debian/compat create mode 100644 port/debian/control create mode 100644 port/debian/copyright create mode 100644 port/debian/install create mode 100755 port/debian/rules create mode 100644 port/debian/source/format create mode 100644 port/fgetln.c create mode 100644 port/fparseln.c create mode 100644 port/getprogname.c create mode 100644 port/m4/.cvsignore create mode 100644 port/pidfile.c create mode 100644 port/popenve.c create mode 100644 port/port.h create mode 100644 port/sockaddr_snprintf.c create mode 100644 port/strlcat.c create mode 100644 port/strlcpy.c create mode 100644 port/strtoi.c create mode 100644 port/vsyslog_r.c create mode 100644 test/Makefile create mode 100644 test/cltest.c create mode 100644 test/srvtest.c diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..899746d0143 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:52 christos Exp $ + +SUBDIR = lib .WAIT include bin etc libexec + +.include diff --git a/Makefile.inc b/Makefile.inc new file mode 100644 index 00000000000..b22d4a80124 --- /dev/null +++ b/Makefile.inc @@ -0,0 +1,11 @@ +# $NetBSD: Makefile.inc,v 1.3 2025/02/11 17:48:30 christos Exp $ + +WARNS=6 +.if !defined(LIB) +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/README b/README new file mode 100644 index 00000000000..4b34138e01e --- /dev/null +++ b/README @@ -0,0 +1,113 @@ +# $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/blocklistd-helper +(this is currently designed for npf) and the configuration file +(inspired from inetd.conf) is in etc/blocklistd.conf. + +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 +blocklistd=YES in /etc/rc.conf, start it up, and you are all set. + +There is also a startup file in etc/rc.d/blocklistd + +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] + - ftpd: diff/ftpd.diff [tcp] + +These patches have been applied to NetBSD-current. + +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: + + blocklist(action, acceptedfd, message); + +Where: + 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 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. + message -> an optional string that is used in debugging logs. + +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 blocklistd via: + + blocklist_sa(action, acceptedfd, sockaddr, sockaddr_len, message); + +The configuration file contains entries of the form: + +# 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 +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 +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, +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. + +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, +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 blocklistd as follows: + +ext_if=bge0 +int_if=sk0 + +group "external" on $ext_if { + ... + ruleset "blocklistd-ext" + ruleset "blocklistd" + ... +} + +group "internal" on $int_if { + ... + ruleset "blocklistd-int" + ... +} + +You can use 'blocklistctl dump -a' to list all the current entries +in the database; the ones that have nfail / where urrent +>= 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 list'. The number of current entries can exceed +the total. This happens because entering packet filter rules is +asynchronous; there could be other connection before the rule +becomes activated. + +Enjoy, + +christos diff --git a/TODO b/TODO new file mode 100644 index 00000000000..d67111bd513 --- /dev/null +++ b/TODO @@ -0,0 +1,64 @@ +# $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? +- add functionality to the control program. Should it change the database + directly, or talk to the daemon to have it do it? +- perhaps handle interfaces too instead of addresses for dynamic ip? + ? What to do with multiple addresses? +- perhaps rate limit against DoS +- perhaps instead of scanning the list have a sparse map by port? +- do we want to use libnpf directly for efficiency? +- add more daemons ftpd? +- do we care about the db state becoming too large? +- instead of a yes = bump one, no = return to 0 interface, do we want + to have something more flexible like? + +n + -n + block + unblock +- 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/bin/Makefile b/bin/Makefile new file mode 100644 index 00000000000..1856e2524f3 --- /dev/null +++ b/bin/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:52 christos Exp $ + +BINDIR=/sbin + +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 +DPADD+=${LIBUTIL} + +.include diff --git a/bin/blocklistctl.8 b/bin/blocklistctl.8 new file mode 100644 index 00000000000..d241f284447 --- /dev/null +++ b/bin/blocklistctl.8 @@ -0,0 +1,134 @@ +.\" $NetBSD: blocklistctl.8,v 1.6 2025/10/26 13:49:22 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 October 25, 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 +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 rulename +The packet filter rule name associated with the database entry, +usually +.Dv blocklistd . +.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 create 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/bin/blocklistctl.c b/bin/blocklistctl.c new file mode 100644 index 00000000000..b43d8b8aaab --- /dev/null +++ b/bin/blocklistctl.c @@ -0,0 +1,170 @@ +/* $NetBSD: blocklistctl.c,v 1.5 2025/10/25 16:56:10 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 +#endif +__RCSID("$NetBSD: blocklistctl.c,v 1.5 2025/10/25 16:56:10 christos Exp $"); + +#include +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#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("rulename\t%*.*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\t%*.*s/%s:%s\t", c.c_name, 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/bin/blocklistd.8 b/bin/blocklistd.8 new file mode 100644 index 00000000000..38bf2217536 --- /dev/null +++ b/bin/blocklistd.8 @@ -0,0 +1,301 @@ +.\" $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
+.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
+.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 /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 +.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 /libexec/blocklistd-helper -compact +.It Pa /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 npfctl 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/bin/blocklistd.c b/bin/blocklistd.c new file mode 100644 index 00000000000..231d6477835 --- /dev/null +++ b/bin/blocklistd.c @@ -0,0 +1,594 @@ +/* $NetBSD: blocklistd.c,v 1.15 2026/02/07 14:32:04 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 +#endif +__RCSID("$NetBSD: blocklistd.c,v 1.15 2026/02/07 14:32:04 christos Exp $"); + +#include +#include +#include + +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ] [-R ] " + "[-P ] [-C ] [-D ] " + "[-s ] [-t ]\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 two less than the configured limit. + * Fall through to the normal BL_ADD and BL_BADUSER processing, + * which will increment the failure count to the threshold, and + * block the abusive address. + */ + if (c.c_nfail != -1) + dbi.count = c.c_nfail - 2; + /*FALLTHROUGH*/ + case BL_ADD: + dbi.count++; /* will become += 2 */ + /*FALLTHROUGH*/ + case BL_BADUSER: + 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; + 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); + } + if (state_del(state, &c) == 0) + 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 = reallocarray(*blp, *maxfd, sizeof(**blp)); + if (*blp == NULL) + err(EXIT_FAILURE, "malloc"); + *pfdp = reallocarray(*pfdp, *maxfd, sizeof(**pfdp)); + 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 = reallocarray(*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 = reallocarray(blsock, maxblsock, + sizeof(*blsock)); + 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); + else { + if (restore) { + if (!flush) + rules_flush(); + rules_restore(); + } + } + if (state == NULL) + exit(EXIT_FAILURE); + + 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)"); + exit(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); + exit(EXIT_SUCCESS); +} diff --git a/bin/blocklistd.conf.5 b/bin/blocklistd.conf.5 new file mode 100644 index 00000000000..cff8b33302e --- /dev/null +++ b/bin/blocklistd.conf.5 @@ -0,0 +1,237 @@ +.\" $NetBSD: blocklistd.conf.5,v 1.9 2026/01/13 21:38:18 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 January 13, 2026 +.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 + [
|[/]:] +.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/bin/conf.c b/bin/conf.c new file mode 100644 index 00000000000..3c6fadb5fa4 --- /dev/null +++ b/bin/conf.c @@ -0,0 +1,1360 @@ +/* $NetBSD: conf.c,v 1.10 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 +#endif +__RCSID("$NetBSD: conf.c,v 1.10 2025/02/11 17:48:30 christos Exp $"); + +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bl.h" +#include "internal.h" +#include "support.h" +#include "conf.h" + + +struct sockaddr_if { + uint8_t sif_len; + sa_family_t sif_family; + in_port_t sif_port; + char sif_name[16]; +}; + +#define SIF_NAME(a) \ + ((const struct sockaddr_if *)(const void *)(a))->sif_name + +static int conf_is_interface(const char *); + +#define FSTAR -1 +#define FEQUAL -2 + +static void +advance(char **p) +{ + char *ep = *p; + while (*ep && !isspace((unsigned char)*ep)) + ep++; + while (*ep && isspace((unsigned char)*ep)) + *ep++ = '\0'; + *p = ep; +} + +static int +conf_getnum(const char *f, size_t l, bool local, void *rp, const char *name, + const char *p) +{ + int e; + intmax_t im; + int *r = rp; + + if (strcmp(p, "*") == 0) { + *r = FSTAR; + return 0; + } + if (strcmp(p, "=") == 0) { + if (local) + goto out; + *r = FEQUAL; + return 0; + } + + im = strtoi(p, NULL, 0, 0, INT_MAX, &e); + if (e == 0) { + *r = (int)im; + return 0; + } + + if (f == NULL) + return -1; + (*lfun)(LOG_ERR, "%s: %s, %zu: Bad number for %s [%s]", __func__, f, l, + name, p); + return -1; +out: + (*lfun)(LOG_ERR, "%s: %s, %zu: `=' for %s not allowed in local config", + __func__, f, l, name); + return -1; + +} + +static int +conf_getnfail(const char *f, size_t l, bool local, struct conf *c, + const char *p) +{ + return conf_getnum(f, l, local, &c->c_nfail, "nfail", p); +} + +static int +conf_getsecs(const char *f, size_t l, bool local, struct conf *c, const char *p) +{ + int e; + char *ep; + intmax_t tot, im; + + tot = 0; + if (strcmp(p, "*") == 0) { + c->c_duration = FSTAR; + return 0; + } + if (strcmp(p, "=") == 0) { + if (local) + goto out; + c->c_duration = FEQUAL; + return 0; + } +again: + im = strtoi(p, &ep, 0, 0, INT_MAX, &e); + + if (e == ENOTSUP) { + switch (*ep) { + case 'd': + im *= 24; + /*FALLTHROUGH*/ + case 'h': + im *= 60; + /*FALLTHROUGH*/ + case 'm': + im *= 60; + /*FALLTHROUGH*/ + case 's': + e = 0; + tot += im; + if (ep[1] != '\0') { + p = ep + 2; + goto again; + } + break; + } + } else + tot = im; + + if (e == 0) { + c->c_duration = (int)tot; + return 0; + } + + if (f == NULL) + return -1; + (*lfun)(LOG_ERR, "%s: %s, %zu: Bad number [%s]", __func__, f, l, p); + return -1; +out: + (*lfun)(LOG_ERR, "%s: %s, %zu: `=' duration not allowed in local" + " config", __func__, f, l); + return -1; + +} + +static int +conf_getport(const char *f, size_t l, bool local, void *r, const char *p) +{ + struct servent *sv; + + // XXX: Pass in the proto instead + if ((sv = getservbyname(p, "tcp")) != NULL) { + *(int *)r = ntohs(sv->s_port); + return 0; + } + if ((sv = getservbyname(p, "udp")) != NULL) { + *(int *)r = ntohs(sv->s_port); + return 0; + } + + return conf_getnum(f, l, local, r, "service", p); +} + +static int +conf_getmask(const char *f, size_t l, bool local, const char **p, int *mask) +{ + char *d; + const char *s = *p; + + if ((d = strchr(s, ':')) != NULL) { + *d++ = '\0'; + *p = d; + } + if ((d = strchr(s, '/')) == NULL) { + *mask = FSTAR; + return 0; + } + + *d++ = '\0'; + return conf_getnum(f, l, local, mask, "mask", d); +} + +static int +conf_gethostport(const char *f, size_t l, bool local, struct conf *c, + const char *p) +{ + char *d; // XXX: Ok to write to string. + in_port_t *port = NULL; + const char *pstr; + + if (strcmp(p, "*") == 0) { + c->c_port = FSTAR; + c->c_lmask = FSTAR; + return 0; + } + + if ((d = strchr(p, ']')) != NULL) { + *d++ = '\0'; + pstr = d; + p++; + } else + pstr = p; + + if (conf_getmask(f, l, local, &pstr, &c->c_lmask) == -1) + goto out; + + if (d) { + struct sockaddr_in6 *sin6 = (void *)&c->c_ss; + if (debug) + (*lfun)(LOG_DEBUG, "%s: host6 %s", __func__, p); + if (strcmp(p, "*") != 0) { + if (inet_pton(AF_INET6, p, &sin6->sin6_addr) != 1) + goto out; + sin6->sin6_family = AF_INET6; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin6->sin6_len = sizeof(*sin6); +#endif + port = &sin6->sin6_port; + } + if (!*pstr) + pstr = "*"; + } else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) { + if (pstr == p) + pstr = "*"; + struct sockaddr_in *sin = (void *)&c->c_ss; + struct sockaddr_if *sif = (void *)&c->c_ss; + if (debug) + (*lfun)(LOG_DEBUG, "%s: host4 %s", __func__, p); + if (strcmp(p, "*") != 0) { + if (conf_is_interface(p)) { + if (!local) + goto out2; + if (debug) + (*lfun)(LOG_DEBUG, "%s: interface %s", + __func__, p); + if (c->c_lmask != FSTAR) + goto out1; + sif->sif_family = AF_MAX; + strlcpy(sif->sif_name, p, + sizeof(sif->sif_name)); +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sif->sif_len = sizeof(*sif); +#endif + port = &sif->sif_port; + } else if (inet_pton(AF_INET, p, &sin->sin_addr) != -1) + { + sin->sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin->sin_len = sizeof(*sin); +#endif + port = &sin->sin_port; + } else + goto out; + } + } + + if (conf_getport(f, l, local, &c->c_port, pstr) == -1) + return -1; + + if (port && c->c_port != FSTAR && c->c_port != FEQUAL) + *port = htons((in_port_t)c->c_port); + return 0; +out: + (*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 " + "interface [%s]", __func__, f, l, c->c_lmask, p); + return -1; +out2: + (*lfun)(LOG_ERR, "%s: %s, %zu: Interface spec does not make sense " + "with remote config [%s]", __func__, f, l, p); + return -1; +} + +static int +conf_getproto(const char *f, size_t l, bool local __unused, struct conf *c, + const char *p) +{ + if (strcmp(p, "stream") == 0) { + c->c_proto = IPPROTO_TCP; + return 0; + } + if (strcmp(p, "dgram") == 0) { + c->c_proto = IPPROTO_UDP; + return 0; + } + return conf_getnum(f, l, local, &c->c_proto, "protocol", p); +} + +static int +conf_getfamily(const char *f, size_t l, bool local __unused, struct conf *c, + const char *p) +{ + if (strncmp(p, "tcp", 3) == 0 || strncmp(p, "udp", 3) == 0) { + c->c_family = p[3] == '6' ? AF_INET6 : AF_INET; + return 0; + } + return conf_getnum(f, l, local, &c->c_family, "family", p); +} + +static int +conf_getuid(const char *f, size_t l, bool local __unused, struct conf *c, + const char *p) +{ + struct passwd *pw; + + if ((pw = getpwnam(p)) != NULL) { + c->c_uid = (int)pw->pw_uid; + return 0; + } + + return conf_getnum(f, l, local, &c->c_uid, "user", p); +} + + +static int +conf_getname(const char *f, size_t l, bool local, struct conf *c, + const char *p) +{ + if (conf_getmask(f, l, local, &p, &c->c_rmask) == -1) + return -1; + + if (strcmp(p, "*") == 0) { + strlcpy(c->c_name, rulename, CONFNAMESZ); + return 0; + } + + if (strcmp(p, "=") == 0) { + if (local) + goto out; + c->c_name[0] = '\0'; + return 0; + } + + snprintf(c->c_name, CONFNAMESZ, "%s%s", *p == '-' ? rulename : "", p); + return 0; +out: + (*lfun)(LOG_ERR, "%s: %s, %zu: `=' name not allowed in local" + " config", __func__, f, l); + return -1; +} + +static int +getvalue(const char *f, size_t l, bool local, void *r, char **p, + int (*fun)(const char *, size_t, bool, struct conf *, const char *)) +{ + char *ep = *p; + + advance(p); + return (*fun)(f, l, local, r, ep); +} + + +static int +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++; + + memset(c, 0, sizeof(*c)); + e = getvalue(f, l, local, c, &p, conf_gethostport); + if (e) return -1; + e = getvalue(f, l, local, c, &p, conf_getproto); + if (e) return -1; + e = getvalue(f, l, local, c, &p, conf_getfamily); + if (e) return -1; + e = getvalue(f, l, local, c, &p, conf_getuid); + if (e) return -1; + e = getvalue(f, l, local, c, &p, conf_getname); + if (e) return -1; + e = getvalue(f, l, local, c, &p, conf_getnfail); + if (e) return -1; + e = getvalue(f, l, local, c, &p, conf_getsecs); + if (e) return -1; + + return 0; +} + +static int +conf_sort(const void *v1, const void *v2) +{ + const struct conf *c1 = v1; + const struct conf *c2 = v2; + +#define CMP(a, b, f) \ + if ((a)->f > (b)->f) return -1; \ + else if ((a)->f < (b)->f) return 1 + + CMP(c1, c2, c_ss.ss_family); + CMP(c1, c2, c_lmask); + CMP(c1, c2, c_port); + CMP(c1, c2, c_proto); + CMP(c1, c2, c_family); + CMP(c1, c2, c_rmask); + CMP(c1, c2, c_uid); +#undef CMP + return 0; +} + +static int +conf_is_interface(const char *name) +{ + const struct ifaddrs *ifa; + + for (ifa = ifas; ifa; ifa = ifa->ifa_next) + if (strcmp(ifa->ifa_name, name) == 0) + return 1; + return 0; +} + +#define MASK(m) ((uint32_t)~((1 << (32 - (m))) - 1)) + +static int +conf_amask_eq(const void *v1, const void *v2, size_t len, int mask) +{ + const uint32_t *a1 = v1; + const uint32_t *a2 = v2; + uint32_t m; + int omask = mask; + + switch (mask) { + case FSTAR: + if (memcmp(v1, v2, len) == 0) + return 1; + goto out; + case FEQUAL: + (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__, + mask); + abort(); + default: + break; + } + + for (size_t i = 0; i < (len >> 2); i++) { + if (mask > 32) { + m = htonl((uint32_t)~0); + mask -= 32; + } else if (mask) { + m = htonl(MASK(mask)); + mask = 0; + } else + return 1; + if ((a1[i] & m) != (a2[i] & m)) + goto out; + } + return 1; +out: + if (debug > 1) { + char b1[256], b2[256]; + blhexdump(b1, sizeof(b1), "a1", v1, len); + blhexdump(b2, sizeof(b2), "a2", v2, len); + (*lfun)(LOG_DEBUG, "%s: %s != %s [0x%x]", __func__, + b1, b2, omask); + } + return 0; +} + +/* + * Apply the mask to the given address + */ +static void +conf_apply_mask(void *v, size_t len, int mask) +{ + uint32_t *a = v; + uint32_t m; + + switch (mask) { + case FSTAR: + return; + case FEQUAL: + (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__, + mask); + abort(); + default: + break; + } + len >>= 2; + + for (size_t i = 0; i < len; i++) { + if (mask > 32) { + m = htonl((uint32_t)~0); + mask -= 32; + } else if (mask) { + m = htonl(MASK(mask)); + mask = 0; + } else + m = 0; + a[i] &= m; + } +} + +/* + * apply the mask and the port to the address given + */ +static void +conf_addr_set(struct conf *c, const struct sockaddr_storage *ss) +{ + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + in_port_t *port; + void *addr; + size_t alen; + + c->c_lmask = c->c_rmask; + c->c_ss = *ss; + + if (c->c_ss.ss_family != c->c_family) { + (*lfun)(LOG_CRIT, "%s: Internal error: mismatched family " + "%u != %u", __func__, c->c_ss.ss_family, c->c_family); + abort(); + } + + switch (c->c_ss.ss_family) { + case AF_INET: + sin = (void *)&c->c_ss; + port = &sin->sin_port; + addr = &sin->sin_addr; + alen = sizeof(sin->sin_addr); + break; + case AF_INET6: + sin6 = (void *)&c->c_ss; + port = &sin6->sin6_port; + addr = &sin6->sin6_addr; + alen = sizeof(sin6->sin6_addr); + break; + default: + (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u", + __func__, c->c_ss.ss_family); + abort(); + } + + *port = htons((in_port_t)c->c_port); + conf_apply_mask(addr, alen, c->c_lmask); + if (c->c_lmask == FSTAR) + c->c_lmask = (int)(alen * 8); + if (debug) { + char buf[128]; + sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&c->c_ss); + (*lfun)(LOG_DEBUG, "Applied address %s", buf); + } +} + +/* + * Compared two addresses for equality applying the mask + */ +static int +conf_inet_eq(const void *v1, const void *v2, int mask) +{ + const struct sockaddr *sa1 = v1; + const struct sockaddr *sa2 = v2; + size_t size; + + if (sa1->sa_family != sa2->sa_family) + return 0; + + switch (sa1->sa_family) { + case AF_INET: { + const struct sockaddr_in *s1 = v1; + const struct sockaddr_in *s2 = v2; + size = sizeof(s1->sin_addr); + v1 = &s1->sin_addr; + v2 = &s2->sin_addr; + break; + } + + case AF_INET6: { + const struct sockaddr_in6 *s1 = v1; + const struct sockaddr_in6 *s2 = v2; + size = sizeof(s1->sin6_addr); + v1 = &s1->sin6_addr; + v2 = &s2->sin6_addr; + break; + } + + default: + (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u", + __func__, sa1->sa_family); + abort(); + } + + return conf_amask_eq(v1, v2, size, mask); +} + +static int +conf_addr_in_interface(const struct sockaddr_storage *s1, + const struct sockaddr_storage *s2, int mask) +{ + const char *name = SIF_NAME(s2); + const struct ifaddrs *ifa; + + for (ifa = ifas; ifa; ifa = ifa->ifa_next) { + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + + if (strcmp(ifa->ifa_name, name) != 0) + continue; + + if (s1->ss_family != ifa->ifa_addr->sa_family) + continue; + + bool eq; + switch (s1->ss_family) { + case AF_INET: + case AF_INET6: + eq = conf_inet_eq(ifa->ifa_addr, s1, mask); + break; + default: + (*lfun)(LOG_ERR, "Bad family %u", s1->ss_family); + continue; + } + if (eq) + return 1; + } + return 0; +} + +static int +conf_addr_eq(const struct sockaddr_storage *s1, + const struct sockaddr_storage *s2, int mask) +{ + switch (s2->ss_family) { + case 0: + return 1; + case AF_MAX: + return conf_addr_in_interface(s1, s2, mask); + case AF_INET: + case AF_INET6: + return conf_inet_eq(s1, s2, mask); + default: + (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u", + __func__, s1->ss_family); + abort(); + } +} + +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; + +#define CMP(a, b, f) \ + if ((a)->f != (b)->f && (b)->f != FSTAR && (b)->f != FEQUAL) { \ + if (debug > 1) \ + (*lfun)(LOG_DEBUG, "%s: %s fail %d != %d", __func__, \ + __STRING(f), (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 const char * +conf_num(char *b, size_t l, int n) +{ + switch (n) { + case FSTAR: + return "*"; + case FEQUAL: + return "="; + default: + snprintf(b, l, "%d", n); + return b; + } +} + +static const char * +fmtname(const char *n) { + size_t l = strlen(rulename); + if (l == 0) + return "*"; + if (strncmp(n, rulename, l) == 0) { + if (n[l] != '\0') + return n + l; + else + return "*"; + } else if (!*n) + return "="; + else + return n; +} + +static void +fmtport(char *b, size_t l, int port) +{ + char buf[128]; + + if (port == FSTAR) + return; + + if (b[0] == '\0' || strcmp(b, "*") == 0) + snprintf(b, l, "%d", port); + else { + snprintf(buf, sizeof(buf), ":%d", port); + strlcat(b, buf, l); + } +} + +static const char * +fmtmask(char *b, size_t l, int fam, int mask) +{ + char buf[128]; + + switch (mask) { + case FSTAR: + return ""; + case FEQUAL: + if (strcmp(b, "=") == 0) + return ""; + else { + strlcat(b, "/=", l); + return b; + } + default: + break; + } + + switch (fam) { + case AF_INET: + if (mask == 32) + return ""; + break; + case AF_INET6: + if (mask == 128) + return ""; + break; + default: + break; + } + + snprintf(buf, sizeof(buf), "/%d", mask); + strlcat(b, buf, l); + return b; +} + +static const char * +conf_namemask(char *b, size_t l, const struct conf *c) +{ + strlcpy(b, fmtname(c->c_name), l); + fmtmask(b, l, c->c_family, c->c_rmask); + return b; +} + +const char * +conf_print(char *buf, size_t len, const char *pref, const char *delim, + const struct conf *c) +{ + char ha[128], hb[32], b[5][64]; + int sp; + +#define N(n, v) conf_num(b[n], sizeof(b[n]), (v)) + + switch (c->c_ss.ss_family) { + case 0: + snprintf(ha, sizeof(ha), "*"); + break; + case AF_MAX: + snprintf(ha, sizeof(ha), "%s", SIF_NAME(&c->c_ss)); + break; + default: + sockaddr_snprintf(ha, sizeof(ha), "%a", (const void *)&c->c_ss); + break; + } + + fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask); + fmtport(ha, sizeof(ha), c->c_port); + + sp = *delim == '\t' ? 20 : -1; + hb[0] = '\0'; + if (*delim) + snprintf(buf, len, "%s%*.*s%s%s%s" "%s%s%s%s" + "%s%s" "%s%s%s", + pref, sp, sp, ha, delim, N(0, c->c_proto), delim, + N(1, c->c_family), delim, N(2, c->c_uid), delim, + conf_namemask(hb, sizeof(hb), c), delim, + N(3, c->c_nfail), delim, N(4, c->c_duration)); + else + snprintf(buf, len, "%starget:%s, proto:%s, family:%s, " + "uid:%s, name:%s, nfail:%s, duration:%s", pref, + ha, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid), + conf_namemask(hb, sizeof(hb), c), + N(3, c->c_nfail), N(4, c->c_duration)); + return buf; +} + +/* + * Apply the local config match to the result + */ +static void +conf_apply(struct conf *c, const struct conf *sc) +{ + char buf[BUFSIZ]; + + if (debug) { + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "merge:\t", "", sc)); + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "to:\t", "", c)); + } + memcpy(c->c_name, sc->c_name, CONFNAMESZ); + c->c_uid = sc->c_uid; + c->c_rmask = sc->c_rmask; + c->c_nfail = sc->c_nfail; + c->c_duration = sc->c_duration; + + if (debug) + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "result:\t", "", c)); +} + +/* + * Merge a remote configuration to the result + */ +static void +conf_merge(struct conf *c, const struct conf *sc) +{ + char buf[BUFSIZ]; + + if (debug) { + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "merge:\t", "", sc)); + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "to:\t", "", c)); + } + + if (sc->c_name[0]) + memcpy(c->c_name, sc->c_name, CONFNAMESZ); + if (sc->c_uid != FEQUAL) + c->c_uid = sc->c_uid; + if (sc->c_rmask != FEQUAL) + c->c_lmask = c->c_rmask = sc->c_rmask; + if (sc->c_nfail != FEQUAL) + c->c_nfail = sc->c_nfail; + if (sc->c_duration != FEQUAL) + c->c_duration = sc->c_duration; + if (debug) + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "result:\t", "", c)); +} + +static void +confset_init(struct confset *cs) +{ + cs->cs_c = NULL; + cs->cs_n = 0; + cs->cs_m = 0; +} + +static int +confset_grow(struct confset *cs) +{ + void *tc; + + cs->cs_m += 10; + tc = realloc(cs->cs_c, cs->cs_m * sizeof(*cs->cs_c)); + if (tc == NULL) { + (*lfun)(LOG_ERR, "%s: Can't grow confset (%m)", __func__); + return -1; + } + cs->cs_c = tc; + return 0; +} + +static struct conf * +confset_get(struct confset *cs) +{ + return &cs->cs_c[cs->cs_n]; +} + +static bool +confset_full(const struct confset *cs) +{ + return cs->cs_n == cs->cs_m; +} + +static void +confset_sort(struct confset *cs) +{ + qsort(cs->cs_c, cs->cs_n, sizeof(*cs->cs_c), conf_sort); +} + +static void +confset_add(struct confset *cs) +{ + cs->cs_n++; +} + +static void +confset_free(struct confset *cs) +{ + free(cs->cs_c); + confset_init(cs); +} + +static void +confset_merge(struct confset *dc, struct confset *sc) +{ + 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 +confset_list(const struct confset *cs, const char *msg, const char *where) +{ + char buf[BUFSIZ]; + + (*lfun)(LOG_DEBUG, "[%s]", msg); + (*lfun)(LOG_DEBUG, "%20.20s\ttype\tproto\towner\tname\tnfail\tduration", + where); + for (size_t i = 0; i < cs->cs_n; i++) + (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), "", "\t", + &cs->cs_c[i])); +} + +/* + * Match a configuration against the given list and apply the function + * to it, returning the matched entry number. + */ +static size_t +confset_match(const struct confset *cs, struct conf *c, + void (*fun)(struct conf *, const struct conf *)) +{ + char buf[BUFSIZ]; + size_t i; + + for (i = 0; i < cs->cs_n; i++) { + if (debug) + (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), + "check:\t", "", &cs->cs_c[i])); + if (conf_match(c, &cs->cs_c[i])) { + if (debug) + (*lfun)(LOG_DEBUG, "%s", + conf_print(buf, sizeof(buf), + "found:\t", "", &cs->cs_c[i])); + (*fun)(c, &cs->cs_c[i]); + break; + } + } + return i; +} + +#ifdef AF_ROUTE +static int +conf_route_perm(int fd) { +#if defined(RTM_IFANNOUNCE) && defined(RT_ROUNDUP) + /* + * Send a routing message that is not supported to check for access + * We expect EOPNOTSUPP for having access, since we are sending a + * request the system does not understand and EACCES if we don't have + * access. + */ + static struct sockaddr_in sin = { +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + .sin_len = sizeof(sin), +#endif + .sin_family = AF_INET, + }; + char buf[4096]; + struct rt_msghdr *rtm = (void *)buf; + char *cp = (char *)(rtm + 1); + size_t l; + +#define NEXTADDR(s) \ + l = RT_ROUNDUP(sizeof(*s)); memmove(cp, s, l); cp += l; + memset(buf, 0, sizeof(buf)); + rtm->rtm_type = RTM_IFANNOUNCE; + rtm->rtm_flags = 0; + rtm->rtm_addrs = RTA_DST|RTA_GATEWAY; + rtm->rtm_version = RTM_VERSION; + rtm->rtm_seq = 666; + NEXTADDR(&sin); + NEXTADDR(&sin); + rtm->rtm_msglen = (u_short)((char *)cp - (char *)rtm); + if (write(fd, rtm, rtm->rtm_msglen) != -1) { + (*lfun)(LOG_ERR, "Writing to routing socket succeeded!"); + return 0; + } + switch (errno) { + case EACCES: + return 0; + case EOPNOTSUPP: + return 1; + default: + (*lfun)(LOG_ERR, + "Unexpected error writing to routing socket (%m)"); + return 0; + } +#else + return 0; +#endif +} +#endif + +static int +conf_handle_inet(int fd, const void *lss, struct conf *cr) +{ + char buf[BUFSIZ]; + int proto; + socklen_t slen = sizeof(proto); + + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) { + (*lfun)(LOG_ERR, "getsockopt failed (%m)"); + return -1; + } + + if (debug) { + sockaddr_snprintf(buf, sizeof(buf), "%a:%p", lss); + (*lfun)(LOG_DEBUG, "listening socket: %s", buf); + } + + switch (proto) { + case SOCK_STREAM: + cr->c_proto = IPPROTO_TCP; + break; + case SOCK_DGRAM: + cr->c_proto = IPPROTO_UDP; + break; + default: + (*lfun)(LOG_ERR, "unsupported protocol %d", proto); + return -1; + } + return 0; +} + +const struct conf * +conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss, + struct conf *cr) +{ + socklen_t slen; + struct sockaddr_storage lss; + size_t i; + char buf[BUFSIZ]; + + memset(cr, 0, sizeof(*cr)); + slen = sizeof(lss); + memset(&lss, 0, slen); + if (getsockname(fd, (void *)&lss, &slen) == -1) { + (*lfun)(LOG_ERR, "getsockname failed (%m)"); + return NULL; + } + + switch (lss.ss_family) { + case AF_INET: + cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port); + if (conf_handle_inet(fd, &lss, cr) == -1) + return NULL; + break; + case AF_INET6: + cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port); + if (conf_handle_inet(fd, &lss, cr) == -1) + return NULL; + break; +#ifdef AF_ROUTE + case AF_ROUTE: + if (!conf_route_perm(fd)) { + (*lfun)(LOG_ERR, + "permission denied to routing socket (%m)"); + return NULL; + } + cr->c_proto = FSTAR; + cr->c_port = FSTAR; + memcpy(&lss, rss, sizeof(lss)); + break; +#endif + default: + (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family); + return NULL; + } + + cr->c_ss = lss; + cr->c_lmask = FSTAR; + cr->c_uid = (int)uid; + cr->c_family = lss.ss_family; + cr->c_name[0] = '\0'; + cr->c_rmask = FSTAR; + cr->c_nfail = FSTAR; + cr->c_duration = FSTAR; + + if (debug) + (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), + "look:\t", "", cr)); + + /* match the local config */ + i = confset_match(&lconf, cr, conf_apply); + if (i == lconf.cs_n) { + if (debug) + (*lfun)(LOG_DEBUG, "not found"); + return NULL; + } + + conf_addr_set(cr, rss); + /* match the remote config */ + confset_match(&rconf, cr, conf_merge); + /* to apply the mask */ + conf_addr_set(cr, &cr->c_ss); + + return cr; +} + +static void +conf_parsefile(FILE *fp, const char *config_file) +{ + char *line; + size_t lineno, len; + struct confset lc, rc, *cs; + + lineno = 0; + + confset_init(&rc); + confset_init(&lc); + cs = &lc; + for (; (line = fparseln(fp, &len, &lineno, NULL, 0)) != NULL; + free(line)) + { + if (!*line) + continue; + if (strcmp(line, "[local]") == 0) { + cs = &lc; + continue; + } + if (strcmp(line, "[remote]") == 0) { + cs = &rc; + continue; + } + + if (confset_full(cs)) { + if (confset_grow(cs) == -1) { + confset_free(&lc); + confset_free(&rc); + free(line); + return; + } + } + if (conf_parseline(config_file, lineno, line, confset_get(cs), + cs == &lc) == -1) + continue; + confset_add(cs); + } + + 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_sort(&lconf); + confset_sort(&rconf); + + if (debug) { + confset_list(&lconf, "local", "target"); + confset_list(&rconf, "remote", "source"); + } +} diff --git a/bin/conf.h b/bin/conf.h new file mode 100644 index 00000000000..8e4cd3a41fa --- /dev/null +++ b/bin/conf.h @@ -0,0 +1,66 @@ +/* $NetBSD: conf.h,v 1.2 2025/02/05 20:09:33 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 _CONF_H +#define _CONF_H + +#include + +struct conf { + size_t c_lineno; + struct sockaddr_storage c_ss; + int c_lmask; + int c_port; + int c_proto; + int c_family; + int c_uid; + int c_nfail; + char c_name[128]; + int c_rmask; + int c_duration; +}; + +struct confset { + struct conf *cs_c; + size_t cs_n; + size_t cs_m; +}; + +#define CONFNAMESZ sizeof(((struct conf *)0)->c_name) + +__BEGIN_DECLS +const char *conf_print(char *, size_t, const char *, const char *, + const struct conf *); +void conf_parse(const char *); +const struct conf *conf_find(int, uid_t, const struct sockaddr_storage *, + struct conf *); +__END_DECLS + +#endif /* _CONF_H */ diff --git a/bin/internal.c b/bin/internal.c new file mode 100644 index 00000000000..625de55928d --- /dev/null +++ b/bin/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 +#endif +__RCSID("$NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); + +#include +#include +#include "conf.h" +#include "internal.h" + +int debug; +const char *rulename = "blocklistd"; +const char *controlprog = _PATH_BLCONTROL; +struct confset lconf, rconf; +struct ifaddrs *ifas; +void (*lfun)(int, const char *, ...) = syslog; diff --git a/bin/internal.h b/bin/internal.h new file mode 100644 index 00000000000..b88e1330221 --- /dev/null +++ b/bin/internal.h @@ -0,0 +1,57 @@ +/* $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 _INTERNAL_H +#define _INTERNAL_H + +#ifndef _PATH_BLCONF +#define _PATH_BLCONF "/etc/blocklistd.conf" +#endif +#ifndef _PATH_BLCONTROL +#define _PATH_BLCONTROL "/libexec/blocklistd-helper" +#endif +#ifndef _PATH_BLSTATE +#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 /* _INTERNAL_H */ diff --git a/bin/run.c b/bin/run.c new file mode 100644 index 00000000000..90071291811 --- /dev/null +++ b/bin/run.c @@ -0,0 +1,160 @@ +/* $NetBSD: run.c,v 1.4 2026/02/07 14:29:09 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 +#endif +__RCSID("$NetBSD: run.c,v 1.4 2026/02/07 14:29:09 christos Exp $"); + +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "run.h" +#include "conf.h" +#include "internal.h" +#include "support.h" + +extern char **environ; + +static char * +run(const char *cmd, const char *name, ...) +{ + const char *argv[20]; + size_t i, len; + va_list ap; + FILE *fp; + char *line, *res; + + argv[0] = "control"; + argv[1] = cmd; + argv[2] = name; + va_start(ap, name); + for (i = 3; i < __arraycount(argv) && + (argv[i] = va_arg(ap, char *)) != NULL; i++) + continue; + va_end(ap); + + if (debug) { + char buf[2048]; + size_t z; + int r; + + r = snprintf(buf, sizeof(buf), "run %s [", controlprog); + if (r == -1 || (z = (size_t)r) >= sizeof(buf)) + z = sizeof(buf); + for (i = 0; argv[i]; i++) { + r = snprintf(buf + z, sizeof(buf) - z, "%s%s", + argv[i], argv[i + 1] ? " " : ""); + if (r == -1 || (z += (size_t)r) >= sizeof(buf)) + z = sizeof(buf); + } + (*lfun)(LOG_DEBUG, "%s]", buf); + } + + fp = popenve(controlprog, __UNCONST(argv), environ, "r"); + if (fp == NULL) { + (*lfun)(LOG_ERR, "popen %s failed (%m)", controlprog); + return NULL; + } + line = res = NULL; + len = 0; + if (getline(&line, &len, fp) >= 0) + res = line; + pclose(fp); + if (debug) + (*lfun)(LOG_DEBUG, "%s returns %s", cmd, res); + return res; +} + +void +run_flush(const struct conf *c) +{ + free(run("flush", c->c_name, NULL)); +} + +int +run_change(const char *how, const struct conf *c, char *id, size_t len) +{ + const char *prname; + char poname[64], adname[128], maskname[32], *rv; + size_t off; + + switch (c->c_proto) { + case -1: + prname = ""; + break; + case IPPROTO_TCP: + prname = "tcp"; + break; + case IPPROTO_UDP: + prname = "udp"; + break; + default: + (*lfun)(LOG_ERR, "%s: bad protocol %d (line %zu)", __func__, + c->c_proto, c->c_lineno); + return -1; + } + + if (c->c_port != -1) + snprintf(poname, sizeof(poname), "%d", c->c_port); + else + poname[0] = '\0'; + + snprintf(maskname, sizeof(maskname), "%d", c->c_lmask); + sockaddr_snprintf(adname, sizeof(adname), "%a", (const void *)&c->c_ss); + + rv = run(how, c->c_name, prname, adname, maskname, poname, id, NULL); + if (rv == NULL) + return -1; + if (len != 0) { + rv[strcspn(rv, "\n")] = '\0'; + off = strncmp(rv, "OK ", 3) == 0 ? 3 : 0; + strlcpy(id, rv + off, len); + } + free(rv); + return 0; +} diff --git a/bin/run.h b/bin/run.h new file mode 100644 index 00000000000..da21906e0db --- /dev/null +++ b/bin/run.h @@ -0,0 +1,41 @@ +/* $NetBSD: run.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 _RUN_H +#define _RUN_H + +__BEGIN_DECLS +struct conf; +void run_flush(const struct conf *); +struct sockaddr_storage; +int run_change(const char *, const struct conf *, char *, size_t); +__END_DECLS + +#endif /* _RUN_H */ diff --git a/bin/state.c b/bin/state.c new file mode 100644 index 00000000000..bb93904f348 --- /dev/null +++ b/bin/state.c @@ -0,0 +1,237 @@ +/* $NetBSD: state.c,v 1.3 2025/10/25 18:43:51 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 +#endif +__RCSID("$NetBSD: state.c,v 1.3 2025/10/25 18:43:51 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bl.h" +#include "internal.h" +#include "conf.h" +#include "support.h" +#include "state.h" + +static HASHINFO openinfo = { + 4096, /* bsize */ + 32, /* ffactor */ + 256, /* nelem */ + 8 * 1024 * 1024,/* cachesize */ + NULL, /* hash() */ + 0 /* lorder */ +}; + +int +state_close(DB *db) +{ + if (db == NULL) + return -1; + if ((*db->close)(db) == -1) { + (*lfun)(LOG_ERR, "%s: can't close db (%m)", __func__); + return -1; + } + return 0; +} + +DB * +state_open(const char *dbname, int flags, mode_t perm) +{ + DB *db; + +#ifdef __APPLE__ + flags &= O_CREAT|O_EXCL|O_EXLOCK|O_NONBLOCK|O_RDONLY| + O_RDWR|O_SHLOCK|O_TRUNC; +#endif + db = dbopen(dbname, flags, perm, DB_HASH, &openinfo); + if (db == NULL) { + if (errno == ENOENT && (flags & O_CREAT) == 0) + return NULL; + (*lfun)(LOG_ERR, "%s: can't open `%s' (%m)", __func__, dbname); + } + return db; +} + +static int +state_sizecheck(const DBT *t) +{ + if (sizeof(struct conf) == t->size) + return 0; + (*lfun)(LOG_ERR, "Key size mismatch %zu != %zu", sizeof(struct conf), + t->size); + return -1; +} + +static void +dumpkey(const struct conf *k) +{ + char buf[10240]; + blhexdump(buf, sizeof(buf), __func__, k, sizeof(*k)); + (*lfun)(LOG_DEBUG, "%s", buf); + (*lfun)(LOG_DEBUG, "%s: %s", __func__, + conf_print(buf, sizeof(buf), "", "", k)); + +} + +int +state_del(DB *db, const struct conf *c) +{ + int rv; + DBT k; + + if (db == NULL) + return -1; + + k.data = __UNCONST(c); + k.size = sizeof(*c); + + switch (rv = (*db->del)(db, &k, 0)) { + case 0: + case 1: + if (debug > 1) { + (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); + (*db->sync)(db, 0); + } + return rv; + default: + (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); + return -1; + } +} + +int +state_get(DB *db, const struct conf *c, struct dbinfo *dbi) +{ + int rv; + DBT k, v; + + if (db == NULL) + return -1; + + k.data = __UNCONST(c); + k.size = sizeof(*c); + + switch (rv = (*db->get)(db, &k, &v, 0)) { + case 0: + case 1: + if (rv) + memset(dbi, 0, sizeof(*dbi)); + else + memcpy(dbi, v.data, sizeof(*dbi)); + if (debug > 1) + (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); + return 0; + default: + (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); + return -1; + } +} + +int +state_put(DB *db, const struct conf *c, const struct dbinfo *dbi) +{ + int rv; + DBT k, v; + + if (db == NULL) + return -1; + + k.data = __UNCONST(c); + k.size = sizeof(*c); + v.data = __UNCONST(dbi); + v.size = sizeof(*dbi); + + switch (rv = (*db->put)(db, &k, &v, 0)) { + case 0: + if (debug > 1) { + (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); + (*db->sync)(db, 0); + } + return 0; + case 1: + errno = EEXIST; + /*FALLTHROUGH*/ + default: + (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); + return -1; + } +} + +int +state_iterate(DB *db, struct conf *c, struct dbinfo *dbi, unsigned int first) +{ + int rv; + DBT k, v; + + if (db == NULL) { + (*lfun)(LOG_ERR, "%s: called with no database file", __func__); + return -1; + } + + first = first ? R_FIRST : R_NEXT; + + switch (rv = (*db->seq)(db, &k, &v, first)) { + case 0: + if (state_sizecheck(&k) == -1) + return -1; + memcpy(c, k.data, sizeof(*c)); + if (debug > 2) + dumpkey(c); + memcpy(dbi, v.data, sizeof(*dbi)); + if (debug > 1) + (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); + return 1; + case 1: + if (debug > 1) + (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); + return 0; + default: + (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); + return -1; + } +} + +int +state_sync(DB *db) +{ + return (*db->sync)(db, 0); +} diff --git a/bin/state.h b/bin/state.h new file mode 100644 index 00000000000..48f63a41ef3 --- /dev/null +++ b/bin/state.h @@ -0,0 +1,62 @@ +/* $NetBSD: state.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 _STATE_H +#define _STATE_H + +#ifdef HAVE_DB_185_H +#include +#elif HAVE_DB_H +#include +#else +#error "no db.h" +#endif +#include + +struct dbinfo { + int count; + time_t last; + char id[64]; +}; + +__BEGIN_DECLS +struct sockaddr_storage; +struct conf; + +DB *state_open(const char *, int, mode_t); +int state_close(DB *); +int state_get(DB *, const struct conf *, struct dbinfo *); +int state_put(DB *, const struct conf *, const struct dbinfo *); +int state_del(DB *, const struct conf *); +int state_iterate(DB *, struct conf *, struct dbinfo *, unsigned int); +int state_sync(DB *); +__END_DECLS + +#endif /* _STATE_H */ diff --git a/bin/support.c b/bin/support.c new file mode 100644 index 00000000000..66d6ccce7db --- /dev/null +++ b/bin/support.c @@ -0,0 +1,163 @@ +/* $NetBSD: support.c,v 1.4 2026/02/07 14:29:58 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 +#endif +__RCSID("$NetBSD: support.c,v 1.4 2026/02/07 14:29:58 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include "support.h" + +static __attribute__((__format_arg__(3))) const char * +expandm(char *buf, size_t len, const char *fmt) +{ + char *p; + size_t r; + + if ((p = strstr(fmt, "%m")) == NULL) + return fmt; + + r = (size_t)(p - fmt); + if (r >= len) + return fmt; + + strlcpy(buf, fmt, r + 1); + strlcat(buf, strerror(errno), len); + strlcat(buf, fmt + r + 2, len); + + return buf; +} + +void +vdlog(int level __unused, struct syslog_data *sd __unused, + const char *fmt, va_list ap) +{ + char buf[BUFSIZ]; + +// fprintf(stderr, "%s: ", getprogname()); + vfprintf(stderr, expandm(buf, sizeof(buf), fmt), ap); + fprintf(stderr, "\n"); +} + +void +dlog(int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vdlog(level, NULL, fmt, ap); + va_end(ap); +} + +const char * +fmttime(char *b, size_t l, time_t t) +{ + struct tm tm; + if (localtime_r(&t, &tm) == NULL) + snprintf(b, l, "*%jd*", (intmax_t)t); + else + strftime(b, l, "%Y/%m/%d %H:%M:%S", &tm); + return b; +} + +const char * +fmtydhms(char *b, size_t l, time_t t) +{ + time_t s, m, h, d, y; + int z; + size_t o; + + s = t % 60; + t /= 60; + + m = t % 60; + t /= 60; + + h = t % 24; + t /= 24; + + d = t % 365; + t /= 365; + + y = t; + + o = 0; +#define APPEND(a) \ + if (a) { \ + z = snprintf(b + o, l - o, "%jd%s", (intmax_t)a, __STRING(a)); \ + if (z == -1) \ + return b; \ + o += (size_t)z; \ + if (o >= l) \ + return b; \ + } + APPEND(y) + APPEND(d) + APPEND(h) + APPEND(m) + APPEND(s) + return b; +} + +ssize_t +blhexdump(char *buf, size_t len, const char *str, const void *b, size_t l) +{ + size_t z, cz; + int r; + const unsigned char *p = b; + const unsigned char *e = p + l; + + r = snprintf(buf, len, "%s: ", str); + if (r == -1) + return -1; + if ((cz = z = (size_t)r) >= len) + cz = len; + + while (p < e) { + r = snprintf(buf + cz, len - cz, "%.2x", *p++); + if (r == -1) + return -1; + if ((cz = (z += (size_t)r)) >= len) + cz = len; + } + return (ssize_t)z; +} diff --git a/bin/support.h b/bin/support.h new file mode 100644 index 00000000000..bb865cb8fe6 --- /dev/null +++ b/bin/support.h @@ -0,0 +1,45 @@ +/* $NetBSD: support.h,v 1.2 2024/08/02 17:11:55 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 _SUPPORT_H +#define _SUPPORT_H + +__BEGIN_DECLS +const char *fmttime(char *, size_t, time_t); +const char *fmtydhms(char *, size_t, time_t); +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); +__END_DECLS + +#endif /* _SUPPORT_H */ diff --git a/diff/ftpd.diff b/diff/ftpd.diff new file mode 100644 index 00000000000..37b43dae229 --- /dev/null +++ b/diff/ftpd.diff @@ -0,0 +1,91 @@ +--- /dev/null 2015-01-23 17:30:40.000000000 -0500 ++++ pfilter.c 2015-01-23 17:12:02.000000000 -0500 +@@ -0,0 +1,24 @@ ++#include ++#include ++ ++#include "pfilter.h" ++ ++static struct blocklist *blstate; ++ ++void ++pfilter_open(void) ++{ ++ if (blstate == NULL) ++ blstate = blocklist_open(); ++} ++ ++void ++pfilter_notify(int what, const char *msg) ++{ ++ pfilter_open(); ++ ++ if (blstate == NULL) ++ return; ++ ++ 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 +@@ -0,0 +1,2 @@ ++void pfilter_open(void); ++void pfilter_notify(int, const char *); +Index: Makefile +=================================================================== +RCS file: /cvsroot/src/libexec/ftpd/Makefile,v +retrieving revision 1.63 +diff -u -p -u -r1.63 Makefile +--- Makefile 14 Aug 2011 11:46:28 -0000 1.63 ++++ Makefile 23 Jan 2015 22:32:20 -0000 +@@ -11,6 +11,10 @@ LDADD+= -lcrypt -lutil + MAN= ftpd.conf.5 ftpusers.5 ftpd.8 + MLINKS= ftpusers.5 ftpchroot.5 + ++SRCS+= pfilter.c ++LDADD+= -lblocklist ++DPADD+= ${LIBBLOCKLIST} ++ + .if defined(NO_INTERNAL_LS) + CPPFLAGS+=-DNO_INTERNAL_LS + .else +Index: ftpd.c +=================================================================== +RCS file: /cvsroot/src/libexec/ftpd/ftpd.c,v +retrieving revision 1.200 +diff -u -p -u -r1.200 ftpd.c +--- ftpd.c 31 Jul 2013 19:50:47 -0000 1.200 ++++ ftpd.c 23 Jan 2015 22:32:20 -0000 +@@ -165,6 +165,8 @@ __RCSID("$NetBSD: ftpd.c,v 1.200 2013/07 + #include + #endif + ++#include "pfilter.h" ++ + #define GLOBAL + #include "extern.h" + #include "pathnames.h" +@@ -471,6 +473,8 @@ main(int argc, char *argv[]) + if (EMPTYSTR(confdir)) + confdir = _DEFAULT_CONFDIR; + ++ pfilter_open(); ++ + if (dowtmp) { + #ifdef SUPPORT_UTMPX + ftpd_initwtmpx(); +@@ -1401,6 +1405,7 @@ do_pass(int pass_checked, int pass_rval, + if (rval) { + reply(530, "%s", rval == 2 ? "Password expired." : + "Login incorrect."); ++ pfilter_notify(1, rval == 2 ? "exppass" : "badpass"); + if (logging) { + syslog(LOG_NOTICE, + "FTP LOGIN FAILED FROM %s", remoteloghost); +@@ -1444,6 +1449,7 @@ do_pass(int pass_checked, int pass_rval, + *remote_ip = 0; + remote_ip[sizeof(remote_ip) - 1] = 0; + if (!auth_hostok(lc, remotehost, remote_ip)) { ++ pfilter_notify(1, "bannedhost"); + syslog(LOG_INFO|LOG_AUTH, + "FTP LOGIN FAILED (HOST) as %s: permission denied.", + pw->pw_name); diff --git a/diff/named.diff b/diff/named.diff new file mode 100644 index 00000000000..75ebc74bde7 --- /dev/null +++ b/diff/named.diff @@ -0,0 +1,161 @@ +Index: bin/named/Makefile +=================================================================== +RCS file: /cvsroot/src/external/mpl/bind/bin/named/Makefile,v +retrieving revision 1.6 +diff -u -p -u -r1.6 Makefile +--- bin/named/Makefile 21 Feb 2024 22:50:56 -0000 1.6 ++++ bin/named/Makefile 9 Apr 2026 15:53:58 -0000 +@@ -47,5 +47,7 @@ CLEANFILES+= xsl.c + + main.o: ${VERSIONFILE} + ++LDADD+=-lblocklist ++DPADD+=${LIBBLOCKLIST} + + .include +Index: dist/bin/named/main.c +=================================================================== +RCS file: /cvsroot/src/external/mpl/bind/dist/bin/named/main.c,v +retrieving revision 1.22 +diff -u -p -u -r1.22 main.c +--- dist/bin/named/main.c 8 Apr 2026 00:15:44 -0000 1.22 ++++ dist/bin/named/main.c 9 Apr 2026 15:53:59 -0000 +@@ -54,6 +54,8 @@ + + #include + ++#include "ns/pfilter.h" ++ + #ifdef HAVE_GPERFTOOLS_PROFILER + #include + #endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ +@@ -1554,6 +1556,9 @@ main(int argc, char *argv[]) { + + parse_command_line(argc, argv); + ++ // Should we have a command line flag? ++ pfilter_enable(); ++ + #ifdef ENABLE_AFL + if (named_g_fuzz_type != isc_fuzz_none) { + named_fuzz_setup(); +Index: dist/lib/ns/client.c +=================================================================== +RCS file: /cvsroot/src/external/mpl/bind/dist/lib/ns/client.c,v +retrieving revision 1.27 +diff -u -p -u -r1.27 client.c +--- dist/lib/ns/client.c 8 Apr 2026 00:16:16 -0000 1.27 ++++ dist/lib/ns/client.c 9 Apr 2026 15:54:00 -0000 +@@ -66,6 +66,8 @@ + #include + #include + ++#include "pfilter.h" ++ + /*** + *** Client + ***/ +@@ -2703,6 +2705,7 @@ ns_client_checkacl(ns_client_t *client, + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, log_level, "%s denied", + opname); ++ pfilter_notify(result, client, opname); + } + return result; + } +Index: dist/lib/ns/xfrout.c +=================================================================== +RCS file: /cvsroot/src/external/mpl/bind/dist/lib/ns/xfrout.c,v +retrieving revision 1.16 +diff -u -p -u -r1.16 xfrout.c +--- dist/lib/ns/xfrout.c 29 Jan 2026 18:37:56 -0000 1.16 ++++ dist/lib/ns/xfrout.c 9 Apr 2026 15:54:00 -0000 +@@ -48,6 +48,8 @@ + #include + #include + ++#include "pfilter.h" ++ + /*! \file + * \brief + * Outgoing AXFR and IXFR. +@@ -826,6 +828,7 @@ ns_xfr_start(ns_client_t *client, dns_rd + ISC_LOG_ERROR, + "zone transfer '%s/%s' denied", + _buf1, _buf2); ++ pfilter_notify(result, client, "zonexfr"); + goto cleanup; + } + if (result != ISC_R_SUCCESS) { +Index: include/ns/pfilter.h +=================================================================== +RCS file: /cvsroot/src/external/mpl/bind/include/ns/pfilter.h,v +retrieving revision 1.1 +diff -u -p -u -r1.1 pfilter.h +--- include/ns/pfilter.h 26 Jan 2025 16:30:19 -0000 1.1 ++++ include/ns/pfilter.h 9 Apr 2026 15:54:00 -0000 +@@ -1,2 +1,3 @@ + void pfilter_enable(void); +-void pfilter_notify(isc_result_t, ns_client_t *, const char *); ++struct ns_client; ++void pfilter_notify(isc_result_t, struct ns_client *, const char *); +Index: include/ns/pfilter.h +=================================================================== +RCS file: include/ns/pfilter.h +diff -N include/ns/pfilter.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ include/ns/pfilter.h 9 Apr 2026 15:54:52 -0000 1.2 +@@ -0,0 +1,3 @@ ++void pfilter_enable(void); ++struct ns_client; ++void pfilter_notify(isc_result_t, struct ns_client *, const char *); +Index: lib/libns/pfilter.c +=================================================================== +RCS file: lib/libns/pfilter.c +diff -N lib/libns/pfilter.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ lib/libns/pfilter.c 26 Jan 2025 16:30:19 -0000 1.1 +@@ -0,0 +1,43 @@ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++static struct blocklist *blstate; ++static int blenable; ++ ++void ++pfilter_enable(void) { ++ blenable = 1; ++} ++ ++#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) ++ ++void ++pfilter_notify(isc_result_t res, ns_client_t *client, const char *msg) ++{ ++ int fd; ++ ++ if (!blenable) ++ return; ++ ++ if (blstate == NULL) ++ blstate = blocklist_open(); ++ ++ if (blstate == NULL) ++ return; ++ ++ if (!TCP_CLIENT(client) && !client->peeraddr_valid) ++ return; ++ ++ if ((fd = isc_nmhandle_getfd(client->handle)) == -1) ++ return; ++ ++ blocklist_sa_r(blstate, ++ res != ISC_R_SUCCESS, fd, ++ &client->peeraddr.type.sa, client->peeraddr.length, msg); ++} diff --git a/diff/postfix.diff b/diff/postfix.diff new file mode 100644 index 00000000000..6f14389515c --- /dev/null +++ b/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 /* for NULL */ ++#include ++ ++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 + #include + ++#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/diff/proftpd.diff b/diff/proftpd.diff new file mode 100644 index 00000000000..e8d2cc5e9e0 --- /dev/null +++ b/diff/proftpd.diff @@ -0,0 +1,124 @@ +--- 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_BLOCKLIST ++LIBS+=-lblocklist ++OBJS+= pfilter.o ++BUILD_OBJS+= src/pfilter.o +--- /dev/null 2016-01-22 17:30:55.000000000 -0500 ++++ include/pfilter.h 2016-01-22 16:18:33.000000000 -0500 +@@ -0,0 +1,3 @@ ++ ++void pfilter_notify(int); ++void pfilter_init(void); +--- modules/mod_auth.c.orig 2015-05-27 20:25:54.000000000 -0400 ++++ modules/mod_auth.c 2016-01-22 16:21:06.000000000 -0500 +@@ -30,6 +30,7 @@ + + #include "conf.h" + #include "privs.h" ++#include "pfilter.h" + + extern pid_t mpid; + +@@ -84,6 +85,8 @@ + _("Login timeout (%d %s): closing control connection"), TimeoutLogin, + TimeoutLogin != 1 ? "seconds" : "second"); + ++ pfilter_notify(1); ++ + /* It's possible that any listeners of this event might terminate the + * session process themselves (e.g. mod_ban). So write out that the + * TimeoutLogin has been exceeded to the log here, in addition to the +@@ -913,6 +916,7 @@ + pr_memscrub(pass, strlen(pass)); + } + ++ pfilter_notify(1); + pr_log_auth(PR_LOG_NOTICE, "SECURITY VIOLATION: Root login attempted"); + return 0; + } +@@ -1726,6 +1730,7 @@ + return 1; + + auth_failure: ++ pfilter_notify(1); + if (pass) + pr_memscrub(pass, strlen(pass)); + session.user = session.group = NULL; +--- src/main.c.orig 2016-01-22 17:36:43.000000000 -0500 ++++ src/main.c 2016-01-22 17:37:58.000000000 -0500 +@@ -49,6 +49,7 @@ + #endif + + #include "privs.h" ++#include "pfilter.h" + + int (*cmd_auth_chk)(cmd_rec *); + void (*cmd_handler)(server_rec *, conn_t *); +@@ -1050,6 +1051,7 @@ + pid_t pid; + sigset_t sig_set; + ++ pfilter_init(); + if (!nofork) { + + /* A race condition exists on heavily loaded servers where the parent +@@ -1169,7 +1171,8 @@ + + /* Reseed pseudo-randoms */ + srand((unsigned int) (time(NULL) * getpid())); +- ++#else ++ pfilter_init(); + #endif /* PR_DEVEL_NO_FORK */ + + /* Child is running here */ +--- /dev/null 2016-01-22 17:30:55.000000000 -0500 ++++ src/pfilter.c 2016-01-22 16:37:55.000000000 -0500 +@@ -0,0 +1,41 @@ ++#include "pfilter.h" ++#include "conf.h" ++#include "privs.h" ++#ifdef HAVE_BLOCKLIST ++#include ++#endif ++ ++static struct blocklist *blstate; ++ ++void ++pfilter_init(void) ++{ ++#ifdef HAVE_BLOCKLIST ++ if (blstate == NULL) ++ blstate = blocklist_open(); ++#endif ++} ++ ++void ++pfilter_notify(int a) ++{ ++#ifdef HAVE_BLOCKLIST ++ conn_t *c = session.c; ++ int fd; ++ ++ if (c == NULL) ++ return; ++ if (c->rfd != -1) ++ fd = c->rfd; ++ else if (c->wfd != -1) ++ fd = c->wfd; ++ else ++ return; ++ ++ if (blstate == NULL) ++ pfilter_init(); ++ if (blstate == NULL) ++ return; ++ (void)blocklist_r(blstate, a, fd, "proftpd"); ++#endif ++} diff --git a/diff/ssh.diff b/diff/ssh.diff new file mode 100644 index 00000000000..17300bb5dc8 --- /dev/null +++ b/diff/ssh.diff @@ -0,0 +1,150 @@ +--- /dev/null 2015-01-22 23:10:33.000000000 -0500 ++++ dist/pfilter.c 2015-01-22 23:46:03.000000000 -0500 +@@ -0,0 +1,32 @@ ++#include "namespace.h" ++#include "includes.h" ++#include "ssh.h" ++#include "packet.h" ++#include "log.h" ++#include "pfilter.h" ++#include ++ ++static struct blocklist *blstate; ++ ++void ++pfilter_init(void) ++{ ++ blstate = blocklist_open(); ++} ++ ++void ++pfilter_notify(int a) ++{ ++ int fd; ++ if (blstate == NULL) ++ pfilter_init(); ++ if (blstate == NULL) ++ return; ++ // XXX: 3? ++ fd = packet_connection_is_on_socket() ? packet_get_connection_in() : 3; ++ (void)blocklist_r(blstate, a, fd, "ssh"); ++ if (a == 0) { ++ blocklist_close(blstate); ++ blstate = NULL; ++ } ++} +--- /dev/null 2015-01-20 21:14:44.000000000 -0500 ++++ dist/pfilter.h 2015-01-20 20:16:20.000000000 -0500 +@@ -0,0 +1,3 @@ ++ ++void pfilter_notify(int); ++void pfilter_init(void); +Index: bin/sshd/Makefile +=================================================================== +RCS file: /cvsroot/src/crypto/external/bsd/openssh/bin/sshd/Makefile,v +retrieving revision 1.10 +diff -u -u -r1.10 Makefile +--- bin/sshd/Makefile 19 Oct 2014 16:30:58 -0000 1.10 ++++ bin/sshd/Makefile 22 Jan 2015 21:39:21 -0000 +@@ -15,7 +15,7 @@ + auth2-none.c auth2-passwd.c auth2-pubkey.c \ + monitor_mm.c monitor.c monitor_wrap.c \ + kexdhs.c kexgexs.c kexecdhs.c sftp-server.c sftp-common.c \ +- roaming_common.c roaming_serv.c sandbox-rlimit.c ++ roaming_common.c roaming_serv.c sandbox-rlimit.c pfilter.c + + COPTS.auth-options.c= -Wno-pointer-sign + COPTS.ldapauth.c= -Wno-format-nonliteral # XXX: should fix +@@ -68,3 +68,6 @@ + + LDADD+= -lwrap + DPADD+= ${LIBWRAP} ++ ++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 +@@ -103,6 +103,7 @@ + #include "ssh-gss.h" + #endif + #include "monitor_wrap.h" ++#include "pfilter.h" + + extern ServerOptions options; + extern Buffer loginmsg; +@@ -526,6 +527,7 @@ + ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, &buffer); + else + ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer); ++ pfilter_notify(1); + buffer_free(&buffer); + pthread_exit(NULL); + +@@ -804,6 +806,7 @@ + free(msg); + return (0); + } ++ pfilter_notify(1); + error("PAM: %s for %s%.100s from %.100s", msg, + sshpam_authctxt->valid ? "" : "illegal user ", + sshpam_authctxt->user, +diff -ru openssh-7.7p1/auth2.c dist/auth2.c +--- openssh-7.7p1/auth2.c 2018-04-02 01:38:28.000000000 -0400 ++++ dist/auth2.c 2018-05-23 11:57:31.022197317 -0400 +@@ -51,6 +51,7 @@ + #include "dispatch.h" + #include "pathnames.h" + #include "buffer.h" ++#include "pfilter.h" + + #ifdef GSSAPI + #include "ssh-gss.h" +@@ -242,6 +243,7 @@ + } else { + /* Invalid user, fake password information */ + authctxt->pw = fakepw(); ++ pfilter_notify(1); + #ifdef SSH_AUDIT_EVENTS + PRIVSEP(audit_event(SSH_INVALID_USER)); + #endif +Only in dist: pfilter.c +Only in dist: pfilter.h +diff -ru openssh-7.7p1/sshd.c dist/sshd.c +--- openssh-7.7p1/sshd.c 2018-04-02 01:38:28.000000000 -0400 ++++ dist/sshd.c 2018-05-23 11:59:39.573197347 -0400 +@@ -122,6 +122,7 @@ + #include "auth-options.h" + #include "version.h" + #include "ssherr.h" ++#include "pfilter.h" + + /* Re-exec fds */ + #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) +@@ -346,6 +347,7 @@ + static void + grace_alarm_handler(int sig) + { ++ pfilter_notify(1); + if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0) + kill(pmonitor->m_pid, SIGALRM); + +@@ -1835,6 +1837,8 @@ + if (test_flag) + exit(0); + ++ pfilter_init(); ++ + /* + * Clear out any supplemental groups we may have inherited. This + * prevents inadvertent creation of files with bad modes (in the +@@ -2280,6 +2284,9 @@ + { + struct ssh *ssh = active_state; /* XXX */ + ++ if (i == 255) ++ pfilter_notify(1); ++ + if (the_authctxt) { + do_cleanup(ssh, the_authctxt); + if (use_privsep && privsep_is_preauth && diff --git a/etc/Makefile b/etc/Makefile new file mode 100644 index 00000000000..f4f2dc79f85 --- /dev/null +++ b/etc/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.2 2025/02/05 20:24:26 christos Exp $ + +SUBDIR= rc.d + +FILESDIR= /usr/share/examples/blocklist +FILESMODE= 644 +FILES= blocklistd.conf ipf.conf npf.conf + +.include +.include diff --git a/etc/blocklistd.conf b/etc/blocklistd.conf new file mode 100644 index 00000000000..49eb99a4107 --- /dev/null +++ b/etc/blocklistd.conf @@ -0,0 +1,15 @@ +# Blocklist rule +# adr/mask:port type proto owner name nfail duration +[local] +ssh stream * * * 3 6h +ftp stream * * * 3 6h +domain * * named * 3 12h +#6161 stream tcp6 christos * 2 10m +* * * * * 3 60 + +# adr/mask:port type proto owner name nfail duration +[remote] +#192.168.0.0/16 * * * = * * +#[2001:db8::]/32:ssh * * * = * * +#6161 = = = =/24 = = +#* stream tcp * = = = diff --git a/etc/ipf.conf b/etc/ipf.conf new file mode 100644 index 00000000000..f6bec74238d --- /dev/null +++ b/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/etc/npf.conf b/etc/npf.conf new file mode 100644 index 00000000000..b1c33f2738f --- /dev/null +++ b/etc/npf.conf @@ -0,0 +1,15 @@ +# Transparent firewall example for blocklistd + +$ext_if = "bnx0" + +set bpf.jit on; +alg "icmp" + +group "external" on $ext_if { + ruleset "blocklistd" + pass final all +} + +group default { + pass final all +} diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile new file mode 100644 index 00000000000..9e214984f7c --- /dev/null +++ b/etc/rc.d/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ + +SCRIPTS=blocklistd +SCRIPTSDIR=/etc/rc.d + +.include diff --git a/etc/rc.d/blocklistd b/etc/rc.d/blocklistd new file mode 100644 index 00000000000..89871ebda4a --- /dev/null +++ b/etc/rc.d/blocklistd @@ -0,0 +1,57 @@ +#!/bin/sh +# +# $NetBSD: blocklistd,v 1.2 2021/03/07 00:46:39 christos Exp $ +# + +# PROVIDE: blocklistd +# REQUIRE: npf pf ipfilter +# BEFORE: SERVERS + +$_rc_subr_loaded . /etc/rc.subr + +name="blocklistd" +rcvar=$name +command="/sbin/${name}" +pidfile="/var/run/${name}.pid" +required_files="/etc/${name}.conf" +start_precmd="${name}_precmd" +extra_commands="reload" + +_sockfile="/var/run/${name}.sockets" +_sockname="blocklistd.sock" + +blocklistd_precmd() +{ + # 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 + # blocklistd socket to list of sockets to watch. + # + for _lr in $(rcorder -k chrootdir /etc/rc.d/*); do + ( + _l=${_lr##*/} + load_rc_config ${_l} + eval _ldir=\$${_l}_chrootdir + if checkyesno $_l && [ -n "$_ldir" ]; then + echo "${_ldir}/var/run/${_sockname}" >> $_sockfile + fi + ) + done + + # If other sockets have been provided, change run_rc_command()'s + # internal copy of $blocklistd_flags to force use of specific + # blocklistd sockets. + # + if [ -s $_sockfile ]; then + echo "/var/run/${_sockname}" >> $_sockfile + rc_flags="-P $_sockfile $rc_flags" + fi + + return 0 +} + +load_rc_config $name +run_rc_command "$1" diff --git a/include/Makefile b/include/Makefile new file mode 100644 index 00000000000..b7ce1eca278 --- /dev/null +++ b/include/Makefile @@ -0,0 +1,10 @@ +# $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= blocklist.h +INCSDIR= /usr/include + +.include diff --git a/include/bl.h b/include/bl.h new file mode 100644 index 00000000000..c7ed517d7a6 --- /dev/null +++ b/include/bl.h @@ -0,0 +1,79 @@ +/* $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 _BL_H +#define _BL_H + +#include +#include +#include +#include +#include "blocklist.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 + +#ifndef _PATH_BLSOCK +#define _PATH_BLSOCK "/var/run/blocklistd.sock" +#endif + +__BEGIN_DECLS + +typedef struct blocklist *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 /* _BL_H */ diff --git a/include/blocklist.h b/include/blocklist.h new file mode 100644 index 00000000000..f09e5139079 --- /dev/null +++ b/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 +#include + +#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/lib/Makefile b/lib/Makefile new file mode 100644 index 00000000000..147f311c478 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,19 @@ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ + +.include + +USE_SHLIBDIR= yes + +CPPFLAGS+=-D_REENTRANT +#LIBDPLIBS+=pthread ${NETBSDSRCDIR}/lib/libpthread +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 diff --git a/lib/bl.c b/lib/bl.c new file mode 100644 index 00000000000..80396ed12b2 --- /dev/null +++ b/lib/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 +#endif +__RCSID("$NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _REENTRANT +#include +#endif + +#if defined(SO_RECVUCRED) +#include +#endif + +#include "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 blocklist { +#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 blocklist 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/lib/blocklist.c b/lib/blocklist.c new file mode 100644 index 00000000000..139fc434262 --- /dev/null +++ b/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 +#endif +__RCSID("$NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); + +#include +#include + +#include +#include +#include +#include +#include + +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/lib/libblocklist.3 b/lib/libblocklist.3 new file mode 100644 index 00000000000..7a016625a04 --- /dev/null +++ b/lib/libblocklist.3 @@ -0,0 +1,177 @@ +.\" $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 Va BLOCKLIST_BAD_USER +The sending daemon has determined the username presented for +authentication is invalid. +This is considered as one failure count. +.It Va BLOCKLIST_AUTH_FAIL +There was an unsuccessful authentication attempt. +This is considered as two failure counts together. +.It Va BLOCKLIST_ABUSIVE_BEHAVIOR +The sending daemon has detected abusive behavior from the remote system. +This is considered as a total immediate failure. +The remote address will be blocked as soon as possible. +.It Va BLOCKLIST_AUTH_OK +A valid user successfully authenticated. +Any entry for the remote address will be removed as soon as possible. +.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/lib/shlib_version b/lib/shlib_version new file mode 100644 index 00000000000..3d7c908e43d --- /dev/null +++ b/lib/shlib_version @@ -0,0 +1,2 @@ +major=0 +minor=1 diff --git a/libexec/Makefile b/libexec/Makefile new file mode 100644 index 00000000000..619d962c23b --- /dev/null +++ b/libexec/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ + +SCRIPTS= blocklistd-helper +SCRIPTSDIR= /libexec + +.include diff --git a/libexec/blocklistd-helper b/libexec/blocklistd-helper new file mode 100755 index 00000000000..f27cde4ed4e --- /dev/null +++ b/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 "" || \ + echo "block in quick $proto from 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 + /sbin/pfctl -a "$anchor" -F rules + done + echo OK + ;; + esac + ;; +*) + echo "$0: Unknown command '$1'" 1>&2 + exit 1 + ;; +esac diff --git a/port/Makefile.am b/port/Makefile.am new file mode 100644 index 00000000000..0e6085f9580 --- /dev/null +++ b/port/Makefile.am @@ -0,0 +1,39 @@ +# +ACLOCAL_AMFLAGS = -I m4 +lib_LTLIBRARIES = libblocklist.la +include_HEADERS = $(srcdir)/../include/blocklist.h + +exampledir = $(datarootdir)/examples +example_DATA = $(srcdir)/../etc/blocklistd.conf $(srcdir)/../etc/npf.conf $(srcdir)/../etc/ipf.conf + +sbin_PROGRAMS = blocklistd blocklistctl +noinst_PROGRAMS = srvtest cltest +libexec_SCRIPTS = $(srcdir)/../libexec/blocklistd-helper + +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@ + +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 +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 = libblocklist.la +cltest_SOURCES = cltest.c ${SRCS} +cltest_LDADD = libblocklist.la diff --git a/port/_strtoi.h b/port/_strtoi.h new file mode 100644 index 00000000000..f50eefd67ff --- /dev/null +++ b/port/_strtoi.h @@ -0,0 +1,93 @@ +/* $NetBSD: _strtoi.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * Original version ID: + * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp + * + * Created by Kamil Rytarowski, based on ID: + * NetBSD: src/common/lib/libc/stdlib/_strtoul.h,v 1.7 2013/05/17 12:55:56 joerg Exp + */ + +/* + * function template for strtoi and strtou + * + * parameters: + * _FUNCNAME : function name + * __TYPE : return and range limits type + * __WRAPPED : wrapped function, strtoimax or strtoumax + */ + +__TYPE +_FUNCNAME(const char * __restrict nptr, char ** __restrict endptr, int base, + __TYPE lo, __TYPE hi, int * rstatus) +{ + int serrno; + __TYPE im; + char *ep; + int rep; + + /* endptr may be NULL */ + + if (endptr == NULL) + endptr = &ep; + + if (rstatus == NULL) + rstatus = &rep; + + serrno = errno; + errno = 0; + + im = __WRAPPED(nptr, endptr, base); + + *rstatus = errno; + errno = serrno; + + if (*rstatus == 0) { + /* No digits were found */ + if (nptr == *endptr) + *rstatus = ECANCELED; + /* There are further characters after number */ + else if (**endptr != '\0') + *rstatus = ENOTSUP; + } + + if (im < lo) { + if (*rstatus == 0) + *rstatus = ERANGE; + return lo; + } + if (im > hi) { + if (*rstatus == 0) + *rstatus = ERANGE; + return hi; + } + + return im; +} diff --git a/port/clock_gettime.c b/port/clock_gettime.c new file mode 100644 index 00000000000..284bd817690 --- /dev/null +++ b/port/clock_gettime.c @@ -0,0 +1,17 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +int +clock_gettime(int clock __unused, struct timespec *ts) +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) == -1) + return -1; + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec * 1000; + return 0; +} diff --git a/port/configure.ac b/port/configure.ac new file mode 100644 index 00000000000..99ecf8732c9 --- /dev/null +++ b/port/configure.ac @@ -0,0 +1,93 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT([blocklistd],[0.1],[christos@netbsd.com]) +AM_INIT_AUTOMAKE([subdir-objects foreign]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +AC_SUBST(WARNINGS) +AC_SUBST(LINK_NTOA) + +dnl Checks for programs. +AC_PROG_CC +AC_USE_SYSTEM_EXTENSIONS +AM_PROG_CC_C_O +AC_C_BIGENDIAN +AC_PROG_INSTALL +AC_PROG_LN_S +LT_INIT([disable-static pic-only]) +gl_VISIBILITY +dnl Checks for headers +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 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__ +#include "port.h" +#endif +]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_SYS_LARGEFILE +AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [#include ]) + +AC_TYPE_PID_T +AC_TYPE_UINT8_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_INT32_T +AC_TYPE_UINT64_T +AC_TYPE_INT64_T +AC_TYPE_INTPTR_T +AC_TYPE_UINTPTR_T + +AC_MSG_CHECKING(for gcc compiler warnings) +AC_ARG_ENABLE(warnings, +[ --disable-warnings disable compiler warnings], +[if test "${enableval}" = no -o "$GCC" = no; then + AC_MSG_RESULT(no) + WARNINGS= +else + AC_MSG_RESULT(yes) + WARNINGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ + -Wmissing-declarations -Wredundant-decls -Wnested-externs \ + -Wsign-compare -Wreturn-type -Wswitch -Wshadow \ + -Wcast-qual -Wwrite-strings -Wextra -Wunused-parameter -Wformat=2" +fi], [ +if test "$GCC" = yes; then + AC_MSG_RESULT(yes) + WARNINGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ + -Wmissing-declarations -Wredundant-decls -Wnested-externs \ + -Wsign-compare -Wreturn-type -Wswitch -Wshadow \ + -Wcast-qual -Wwrite-strings -Wextra -Wunused-parameter -Wformat=2" +else + WARNINGS= + AC_MSG_RESULT(no) +fi]) + +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 vsyslog_r) + +dnl See if we are cross-compiling +AM_CONDITIONAL(IS_CROSS_COMPILE, test "$cross_compiling" = yes) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/port/debian/blocklist.manpages b/port/debian/blocklist.manpages new file mode 100644 index 00000000000..29bf2aa3eda --- /dev/null +++ b/port/debian/blocklist.manpages @@ -0,0 +1,4 @@ +bin/blocklistctl.8 +bin/blocklistd.8 +bin/blocklistd.conf.5 +lib/libblocklist.3 diff --git a/port/debian/changelog b/port/debian/changelog new file mode 100644 index 00000000000..cd69e1d13e0 --- /dev/null +++ b/port/debian/changelog @@ -0,0 +1,6 @@ +blocklist (1.7+nmu1) unstable; urgency=low + + * nmu; import from https://github.com/zoulasc/blocklist + * + + -- Two Sigma Base Platform Engineering Tue, 30 Jun 2020 14:40:28 +0000 diff --git a/port/debian/compat b/port/debian/compat new file mode 100644 index 00000000000..f599e28b8ab --- /dev/null +++ b/port/debian/compat @@ -0,0 +1 @@ +10 diff --git a/port/debian/control b/port/debian/control new file mode 100644 index 00000000000..cec0c4ef1a3 --- /dev/null +++ b/port/debian/control @@ -0,0 +1,21 @@ +Source: blocklist +Section: net +Priority: optional +Maintainer: Christos Zoulas +Standards-Version: 4.4.1 +Build-Depends: debhelper (>= 10~), + dh-exec, + dpkg-dev (>= 1.16.1~), + libdb-dev, + quilt + +Package: blocklist +Architecture: any +Homepage: https://github.com/zoulasc/blocklist +Depends: ${misc:Depends}, + ${shlibs:Depends}, + libdb5.3 +Description: 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. diff --git a/port/debian/copyright b/port/debian/copyright new file mode 100644 index 00000000000..1eb03776041 --- /dev/null +++ b/port/debian/copyright @@ -0,0 +1,38 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: blocklist +Upstream-Contact: christos@zoulas.com +Source: https://github.com/zoulasc/blocklist +Comment: + 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. + +Files: * +Copyright: 2020 Christos Zoulas +License: NetBSD + * 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. diff --git a/port/debian/install b/port/debian/install new file mode 100644 index 00000000000..6c5e1ac7126 --- /dev/null +++ b/port/debian/install @@ -0,0 +1 @@ +libexec/blocklistd-helper usr/libexec diff --git a/port/debian/rules b/port/debian/rules new file mode 100755 index 00000000000..80c2d9c5a82 --- /dev/null +++ b/port/debian/rules @@ -0,0 +1,15 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +# export DH_VERBOSE=1 + +# This has to be exported to make some magic below work. +export DH_OPTIONS + +%: + dh $@ --sourcedirectory=port --with quilt + +# https://lintian.debian.org/tags/non-empty-dependency_libs-in-la-file.html +override_dh_auto_install: + dh_auto_install + sed -i "/dependency_libs/ s/'.*'/''/" `find . -name '*.la'` diff --git a/port/debian/source/format b/port/debian/source/format new file mode 100644 index 00000000000..89ae9db8f88 --- /dev/null +++ b/port/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/port/fgetln.c b/port/fgetln.c new file mode 100644 index 00000000000..006e19f5279 --- /dev/null +++ b/port/fgetln.c @@ -0,0 +1,106 @@ +/* $NetBSD: fgetln.c,v 1.1.1.1 2020/06/15 01:52:54 christos Exp $ */ + +/*- + * Copyright (c) 1998 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 + +#if !HAVE_FGETLN +#include +#ifndef HAVE_NBTOOL_CONFIG_H +/* These headers are required, but included from nbtool_config.h */ +#include +#include +#include +#include +#endif + +char * +fgetln(FILE *fp, size_t *len) +{ + static char *buf = NULL; + static size_t bufsiz = 0; + char *ptr; + + + if (buf == NULL) { + bufsiz = BUFSIZ; + if ((buf = malloc(bufsiz)) == NULL) + return NULL; + } + + if (fgets(buf, bufsiz, fp) == NULL) + return NULL; + + *len = 0; + while ((ptr = strchr(&buf[*len], '\n')) == NULL) { + size_t nbufsiz = bufsiz + BUFSIZ; + char *nbuf = realloc(buf, nbufsiz); + + if (nbuf == NULL) { + int oerrno = errno; + free(buf); + errno = oerrno; + buf = NULL; + return NULL; + } else + buf = nbuf; + + if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) { + buf[bufsiz] = '\0'; + *len = strlen(buf); + return buf; + } + + *len = bufsiz; + bufsiz = nbufsiz; + } + + *len = (ptr - buf) + 1; + return buf; +} + +#endif + +#ifdef TEST +int +main(int argc, char *argv[]) +{ + char *p; + size_t len; + + while ((p = fgetln(stdin, &len)) != NULL) { + (void)printf("%zu %s", len, p); + free(p); + } + return 0; +} +#endif diff --git a/port/fparseln.c b/port/fparseln.c new file mode 100644 index 00000000000..22850ea9e30 --- /dev/null +++ b/port/fparseln.c @@ -0,0 +1,238 @@ +/* $NetBSD: fparseln.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ + +/* + * Copyright (c) 1997 Christos Zoulas. All rights reserved. + * + * 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 ``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 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 +#endif +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: fparseln.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include + +#if ! HAVE_FPARSELN || BROKEN_FPARSELN + +#define FLOCKFILE(fp) +#define FUNLOCKFILE(fp) + +#if defined(_REENTRANT) && !HAVE_NBTOOL_CONFIG_H +#define __fgetln(f, l) __fgetstr(f, l, '\n') +#else +#define __fgetln(f, l) fgetln(f, l) +#endif + +static int isescaped(const char *, const char *, int); + +/* isescaped(): + * Return true if the character in *p that belongs to a string + * that starts in *sp, is escaped by the escape character esc. + */ +static int +isescaped(const char *sp, const char *p, int esc) +{ + const char *cp; + size_t ne; + + /* No escape character */ + if (esc == '\0') + return 0; + + /* Count the number of escape characters that precede ours */ + for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++) + continue; + + /* Return true if odd number of escape characters */ + return (ne & 1) != 0; +} + + +/* fparseln(): + * Read a line from a file parsing continuations ending in \ + * and eliminating trailing newlines, or comments starting with + * the comment char. + */ +char * +fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags) +{ + static const char dstr[3] = { '\\', '\\', '#' }; + + size_t s, len; + char *buf; + char *ptr, *cp; + int cnt; + char esc, con, nl, com; + + len = 0; + buf = NULL; + cnt = 1; + + if (str == NULL) + str = dstr; + + esc = str[0]; + con = str[1]; + com = str[2]; + /* + * XXX: it would be cool to be able to specify the newline character, + * but unfortunately, fgetln does not let us + */ + nl = '\n'; + + FLOCKFILE(fp); + + while (cnt) { + cnt = 0; + + if (lineno) + (*lineno)++; + + if ((ptr = __fgetln(fp, &s)) == NULL) + break; + + if (s && com) { /* Check and eliminate comments */ + for (cp = ptr; cp < ptr + s; cp++) + if (*cp == com && !isescaped(ptr, cp, esc)) { + s = cp - ptr; + cnt = s == 0 && buf == NULL; + break; + } + } + + if (s && nl) { /* Check and eliminate newlines */ + cp = &ptr[s - 1]; + + if (*cp == nl) + s--; /* forget newline */ + } + + if (s && con) { /* Check and eliminate continuations */ + cp = &ptr[s - 1]; + + if (*cp == con && !isescaped(ptr, cp, esc)) { + s--; /* forget continuation char */ + cnt = 1; + } + } + + if (s == 0) { + /* + * nothing to add, skip realloc except in case + * we need a minimal buf to return an empty line + */ + if (cnt || buf != NULL) + continue; + } + + if ((cp = realloc(buf, len + s + 1)) == NULL) { + FUNLOCKFILE(fp); + free(buf); + return NULL; + } + buf = cp; + + (void) memcpy(buf + len, ptr, s); + len += s; + buf[len] = '\0'; + } + + FUNLOCKFILE(fp); + + if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL && + strchr(buf, esc) != NULL) { + ptr = cp = buf; + while (cp[0] != '\0') { + int skipesc; + + while (cp[0] != '\0' && cp[0] != esc) + *ptr++ = *cp++; + if (cp[0] == '\0' || cp[1] == '\0') + break; + + skipesc = 0; + if (cp[1] == com) + skipesc += (flags & FPARSELN_UNESCCOMM); + if (cp[1] == con) + skipesc += (flags & FPARSELN_UNESCCONT); + if (cp[1] == esc) + skipesc += (flags & FPARSELN_UNESCESC); + if (cp[1] != com && cp[1] != con && cp[1] != esc) + skipesc = (flags & FPARSELN_UNESCREST); + + if (skipesc) + cp++; + else + *ptr++ = *cp++; + *ptr++ = *cp++; + } + *ptr = '\0'; + len = strlen(buf); + } + + if (size) + *size = len; + return buf; +} + +#ifdef TEST + +int main(int, char **); + +int +main(int argc, char **argv) +{ + char *ptr; + size_t size, line; + + line = 0; + while ((ptr = fparseln(stdin, &size, &line, NULL, + FPARSELN_UNESCALL)) != NULL) + printf("line %d (%d) |%s|\n", line, size, ptr); + return 0; +} + +/* + +# This is a test +line 1 +line 2 \ +line 3 # Comment +line 4 \# Not comment \\\\ + +# And a comment \ +line 5 \\\ +line 6 + +*/ + +#endif /* TEST */ +#endif /* ! HAVE_FPARSELN || BROKEN_FPARSELN */ diff --git a/port/getprogname.c b/port/getprogname.c new file mode 100644 index 00000000000..983d6740c88 --- /dev/null +++ b/port/getprogname.c @@ -0,0 +1,24 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +extern char *__progname; + +const char * +getprogname(void) +{ + return __progname; +} + +void +setprogname(char *p) +{ + char *q; + if (p == NULL) + return; + if ((q = strrchr(p, '/')) != NULL) + __progname = ++q; + else + __progname = p; +} diff --git a/port/m4/.cvsignore b/port/m4/.cvsignore new file mode 100644 index 00000000000..0f4126cd671 --- /dev/null +++ b/port/m4/.cvsignore @@ -0,0 +1 @@ +*.m4 diff --git a/port/pidfile.c b/port/pidfile.c new file mode 100644 index 00000000000..1dbbf510c4e --- /dev/null +++ b/port/pidfile.c @@ -0,0 +1,185 @@ +/* $NetBSD: pidfile.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe, Matthias Scheler and Julio Merino. + * + * 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 +#endif +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: pidfile.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); +#endif + +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif + +static pid_t pidfile_pid; +static char *pidfile_path; + +/* Deletes an existent pidfile iff it was created by this process. */ +static void +pidfile_cleanup(void) +{ + + if ((pidfile_path != NULL) && (pidfile_pid == getpid())) + (void) unlink(pidfile_path); +} + +/* Registers an atexit(3) handler to delete the pidfile we have generated. + * We only register the handler when we create a pidfile, so we can assume + * that the pidfile exists. + * + * Returns 0 on success or -1 if the handler could not be registered. */ +static int +register_atexit_handler(void) +{ + static bool done = false; + + if (!done) { + if (atexit(pidfile_cleanup) < 0) + return -1; + done = true; + } + + return 0; +} + +/* Given a new pidfile name in 'path', deletes any previously-created pidfile + * if the previous file differs to the new one. + * + * If a previous file is deleted, returns 1, which means that a new pidfile + * must be created. Otherwise, this returns 0, which means that the existing + * file does not need to be touched. */ +static int +cleanup_old_pidfile(const char* path) +{ + if (pidfile_path != NULL) { + if (strcmp(pidfile_path, path) != 0) { + pidfile_cleanup(); + + free(pidfile_path); + pidfile_path = NULL; + + return 1; + } else + return 0; + } else + return 1; +} + +/* Constructs a name for a pidfile in the default location (/var/run). If + * 'basename' is NULL, uses the name of the current program for the name of + * the pidfile. + * + * Returns a pointer to a dynamically-allocatd string containing the absolute + * path to the pidfile; NULL on failure. */ +static char * +generate_varrun_path(const char *bname) +{ + char *path; + + if (bname == NULL) + bname = getprogname(); + + /* _PATH_VARRUN includes trailing / */ + if (asprintf(&path, "%s%s.pid", _PATH_VARRUN, bname) == -1) + return NULL; + return path; +} + +/* Creates a pidfile with the provided name. The new pidfile is "registered" + * in the global variables pidfile_path and pidfile_pid so that any further + * call to pidfile(3) can check if we are recreating the same file or a new + * one. + * + * Returns 0 on success or -1 if there is any error. */ +static int +create_pidfile(const char* path) +{ + FILE *f; + + if (register_atexit_handler() == -1) + return -1; + + if (cleanup_old_pidfile(path) == 0) + return 0; + + pidfile_path = strdup(path); + if (pidfile_path == NULL) + return -1; + + if ((f = fopen(path, "w")) == NULL) { + free(pidfile_path); + pidfile_path = NULL; + return -1; + } + + pidfile_pid = getpid(); + + (void) fprintf(f, "%d\n", pidfile_pid); + (void) fclose(f); + + return 0; +} + +int +pidfile(const char *path) +{ + + if (path == NULL || strchr(path, '/') == NULL) { + char *default_path; + + if ((default_path = generate_varrun_path(path)) == NULL) + return -1; + + if (create_pidfile(default_path) == -1) { + free(default_path); + return -1; + } + + free(default_path); + return 0; + } else + return create_pidfile(path); +} diff --git a/port/popenve.c b/port/popenve.c new file mode 100644 index 00000000000..30aac98a7f6 --- /dev/null +++ b/port/popenve.c @@ -0,0 +1,279 @@ +/* $NetBSD: popenve.c,v 1.3 2026/02/07 14:26:07 christos Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software written by Ken Arnold and + * published in UNIX Review, Vol. 6, No. 8. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 +#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.3 2026/02/07 14:26:07 christos Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __weak_alias +__weak_alias(popen,_popen) +__weak_alias(pclose,_pclose) +#endif + +static struct pid { + struct pid *next; + FILE *fp; +#ifdef _REENTRANT + int fd; +#endif + pid_t pid; +} *pidlist; + +#ifdef _REENTRANT +static rwlock_t pidlist_lock = RWLOCK_INITIALIZER; +#endif + +static struct pid * +pdes_get(int *pdes, const char **type) +{ + struct pid *cur; + int flags = strchr(*type, 'e') ? O_CLOEXEC : 0; + int serrno; + + if (strchr(*type, '+')) { +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + int stype = flags ? (SOCK_STREAM | SOCK_CLOEXEC) : SOCK_STREAM; + *type = "r+"; + if (socketpair(AF_LOCAL, stype, 0, pdes) < 0) + return NULL; +#if SOCK_CLOEXEC == 0 + fcntl(pdes[0], F_SETFD, FD_CLOEXEC); + fcntl(pdes[1], F_SETFD, FD_CLOEXEC); +#endif + } else { + *type = strrchr(*type, 'r') ? "r" : "w"; +#if SOCK_CLOEXEC != 0 + if (pipe2(pdes, flags) == -1) + return NULL; +#else + if (pipe(pdes) == -1) + return NULL; + fcntl(pdes[0], F_SETFL, fcntl(pdes[0], F_GETFL) | flags); + fcntl(pdes[1], F_SETFL, fcntl(pdes[1], F_GETFL) | flags); +#endif + } + + if ((cur = malloc(sizeof(*cur))) != NULL) { + if (**type == 'r') { + cur->fp = fdopen(pdes[0], *type); +#ifdef _REENTRANT + cur->fd = pdes[0]; +#endif + } else { + cur->fp = fdopen(pdes[1], *type); +#ifdef _REENTRANT + cur->fd = pdes[1]; +#endif + } + if (cur->fp != NULL) + return cur; + } + serrno = errno; + (void)close(pdes[0]); + (void)close(pdes[1]); + free(cur); + errno = serrno; + return NULL; +} + +static void +pdes_child(int *pdes, const char *type) +{ + struct pid *old; + + if (type[0] == 'r') { + (void)close(pdes[0]); + if (pdes[1] != STDOUT_FILENO) { + (void)dup2(pdes[1], STDOUT_FILENO); + (void)close(pdes[1]); + } + if (type[1] == '+') + (void)dup2(STDOUT_FILENO, STDIN_FILENO); + } else { + (void)close(pdes[1]); + if (pdes[0] != STDIN_FILENO) { + (void)dup2(pdes[0], STDIN_FILENO); + (void)close(pdes[0]); + } + } + + /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams + from previous popen() calls that remain open in the + parent process are closed in the new child process. */ + for (old = pidlist; old; old = old->next) { +#ifdef _REENTRANT + (void)close(old->fd); /* don't allow a flush */ +#else + (void)close(fileno(old->fp)); /* don't allow a flush */ +#endif + } +} + +static void +pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type) +{ + /* Parent */ + if (*type == 'r') + (void)close(pdes[1]); + else + (void)close(pdes[0]); + + /* Link into list of file descriptors. */ + cur->pid = pid; + cur->next = pidlist; + pidlist = cur; +} + +static void +pdes_error(int *pdes, struct pid *cur) +{ + free(cur); + (void)close(pdes[0]); + (void)close(pdes[1]); +} + +FILE * +popenve(const char *cmd, char *const *argv, char *const *envp, const char *type) +{ + struct pid *cur; + int pdes[2], serrno; + pid_t pid; + + if ((cur = pdes_get(pdes, &type)) == NULL) + return NULL; + +#ifdef _REENTRANT + (void)rwlock_rdlock(&pidlist_lock); +#endif + switch (pid = fork()) { + case -1: /* Error. */ + serrno = errno; +#ifdef _REENTRANT + (void)rwlock_unlock(&pidlist_lock); +#endif + pdes_error(pdes, cur); + errno = serrno; + return NULL; + /* NOTREACHED */ + case 0: /* Child. */ + pdes_child(pdes, type); + execve(cmd, argv, envp); + _exit(127); + /* NOTREACHED */ + } + + pdes_parent(pdes, cur, pid, type); + +#ifdef _REENTRANT + (void)rwlock_unlock(&pidlist_lock); +#endif + + return cur->fp; +} + +/* + * pclose -- + * Pclose returns -1 if stream is not associated with a `popened' command, + * if already `pclosed', or waitpid returns an error. + */ +int +pcloseve(FILE *iop) +{ + struct pid *cur, *last; + int pstat; + pid_t pid; + +#ifdef _REENTRANT + rwlock_wrlock(&pidlist_lock); +#endif + + /* Find the appropriate file pointer. */ + for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) + if (cur->fp == iop) + break; + if (cur == NULL) { +#ifdef _REENTRANT + (void)rwlock_unlock(&pidlist_lock); +#endif + errno = ESRCH; + return -1; + } + + (void)fclose(iop); + + /* Remove the entry from the linked list. */ + if (last == NULL) + pidlist = cur->next; + else + last->next = cur->next; + +#ifdef _REENTRANT + (void)rwlock_unlock(&pidlist_lock); +#endif + + do { + pid = waitpid(cur->pid, &pstat, 0); + } while (pid == -1 && errno == EINTR); + + free(cur); + + return pid == -1 ? -1 : pstat; +} diff --git a/port/port.h b/port/port.h new file mode 100644 index 00000000000..d1a9ac6bd6e --- /dev/null +++ b/port/port.h @@ -0,0 +1,108 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include + +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +#ifndef __dead +#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 + +#ifndef __UNCONST +#define __UNCONST(a) ((void *)(intptr_t)(a)) +#endif + +#ifndef __arraycount +#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 + +#ifndef HAVE_STRLCAT +size_t strlcat(char *, const char *, size_t); +#endif + +#ifndef HAVE_POPENVE +FILE *popenve(const char *, char *const *, char *const *, const char *); +int pcloseve(FILE *); +#define pclose(a) pcloseve(a); +#endif + +#ifndef HAVE_SOCKADDR_SNPRINTF +struct sockaddr; +int sockaddr_snprintf(char *, size_t, const char *, const struct sockaddr *); +#endif + +#ifndef HAVE_STRTOI +intmax_t strtoi(const char *, char **, int, intmax_t, intmax_t, int *); +#endif + +#ifndef HAVE_GETPROGNAME +const char *getprogname(void); +void setprogname(char *); +#endif + +#ifndef HAVE_PIDFILE +int pidfile(const char *); +#endif + +#ifndef HAVE_FPARSELN +#define FPARSELN_UNESCALL 0xf +#define FPARSELN_UNESCCOMM 0x1 +#define FPARSELN_UNESCCONT 0x2 +#define FPARSELN_UNESCESC 0x4 +#define FPARSELN_UNESCREST 0x8 +char *fparseln(FILE *, size_t *, size_t *, const char delim[3], int); +#endif + +#ifndef HAVE_FGETLN +char *fgetln(FILE *, size_t *); +#endif + +#ifndef HAVE_CLOCK_GETTIME +struct timespec; +int clock_gettime(int, struct timespec *); +#define CLOCK_REALTIME 0 +#endif + +#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/port/sockaddr_snprintf.c b/port/sockaddr_snprintf.c new file mode 100644 index 00000000000..a37eded14a8 --- /dev/null +++ b/port/sockaddr_snprintf.c @@ -0,0 +1,385 @@ +/* $NetBSD: sockaddr_snprintf.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ + +/*- + * Copyright (c) 2004 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 +#endif +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include + +#include +#ifdef __linux__ +#undef HAVE_NETATALK_AT_H +#endif +#ifdef HAVE_NETATALK_AT_H +#include +#endif +#ifdef HAVE_NET_IF_DL_H +#include +#endif + +#include +#include +#include +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include + +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN +#define SLEN(a) (a)->a ## _len +#else +static socklen_t +socklen(u_int af) +{ + switch (af) { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + case AF_LOCAL: + return sizeof(struct sockaddr_un); +#ifdef HAVE_NET_IF_DL_H + case AF_LINK: + return sizeof(struct sockaddr_dl); +#endif +#ifdef HAVE_NETATALK_AT_H + case AF_APPLETALK: + return sizeof(struct sockaddr_at); +#endif + default: + return sizeof(struct sockaddr_storage); + } +} + +#define SLEN(a) socklen((a)->a ## _family) +#endif + +#ifdef HAVE_NETATALK_AT_H +static int +debug_at(char *str, size_t len, const struct sockaddr_at *sat) +{ + return snprintf(str, len, "sat_len=%u, sat_family=%u, sat_port=%u, " + "sat_addr.s_net=%u, sat_addr.s_node=%u, " + "sat_range.r_netrange.nr_phase=%u, " + "sat_range.r_netrange.nr_firstnet=%u, " + "sat_range.r_netrange.nr_lastnet=%u", + SLEN(sat), sat->sat_family, sat->sat_port, + sat->sat_addr.s_net, sat->sat_addr.s_node, + sat->sat_range.r_netrange.nr_phase, + sat->sat_range.r_netrange.nr_firstnet, + sat->sat_range.r_netrange.nr_lastnet); +} +#endif + +static int +debug_in(char *str, size_t len, const struct sockaddr_in *sin) +{ + return snprintf(str, len, "sin_len=%u, sin_family=%u, sin_port=%u, " + "sin_addr.s_addr=%08x", + SLEN(sin), sin->sin_family, sin->sin_port, + sin->sin_addr.s_addr); +} + +static int +debug_in6(char *str, size_t len, const struct sockaddr_in6 *sin6) +{ + const uint8_t *s = sin6->sin6_addr.s6_addr; + + return snprintf(str, len, "sin6_len=%u, sin6_family=%u, sin6_port=%u, " + "sin6_flowinfo=%u, " + "sin6_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x:%02x:%02x, sin6_scope_id=%u", + SLEN(sin6), sin6->sin6_family, sin6->sin6_port, + sin6->sin6_flowinfo, s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5], + s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb], s[0xc], s[0xd], + s[0xe], s[0xf], sin6->sin6_scope_id); +} + +static int +debug_un(char *str, size_t len, const struct sockaddr_un *sun) +{ + return snprintf(str, len, "sun_len=%u, sun_family=%u, sun_path=%*s", + SLEN(sun), sun->sun_family, (int)sizeof(sun->sun_path), + sun->sun_path); +} + +#ifdef HAVE_NET_IF_DL_H +static int +debug_dl(char *str, size_t len, const struct sockaddr_dl *sdl) +{ + const uint8_t *s = (const void *)sdl->sdl_data; + + return snprintf(str, len, "sdl_len=%u, sdl_family=%u, sdl_index=%u, " + "sdl_type=%u, sdl_nlen=%u, sdl_alen=%u, sdl_slen=%u, sdl_data=" + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + SLEN(sdl), sdl->sdl_family, sdl->sdl_index, + sdl->sdl_type, sdl->sdl_nlen, sdl->sdl_alen, sdl->sdl_slen, + s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5], + s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb]); +} +#endif + +int +sockaddr_snprintf(char * const sbuf, const size_t len, const char * const fmt, + const struct sockaddr * const sa) +{ + const void *a = NULL; + char abuf[1024], nbuf[1024], *addr = NULL; + + char Abuf[1024], pbuf[32], *name = NULL, *port = NULL; + char *ebuf = &sbuf[len - 1], *buf = sbuf; + const char *ptr, *s; + int p = -1; +#ifdef HAVE_NETATALK_AT_H + const struct sockaddr_at *sat = NULL; +#endif + const struct sockaddr_in *sin4 = NULL; + const struct sockaddr_in6 *sin6 = NULL; + const struct sockaddr_un *sun = NULL; +#ifdef HAVE_NET_IF_DL_H + const struct sockaddr_dl *sdl = NULL; + char *w = NULL; +#endif + int na = 1; + +#define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \ + while (/*CONSTCOND*/0) +#define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \ + while (/*CONSTCOND*/0) +#define ADDNA() do { if (na) ADDS("N/A"); } \ + while (/*CONSTCOND*/0) + + switch (sa->sa_family) { + case AF_UNSPEC: + goto done; +#ifdef HAVE_NETATALK_AT_H + case AF_APPLETALK: + sat = ((const struct sockaddr_at *)(const void *)sa); + p = ntohs(sat->sat_port); + (void)snprintf(addr = abuf, sizeof(abuf), "%u.%u", + ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); + (void)snprintf(port = pbuf, sizeof(pbuf), "%d", p); + break; +#endif + case AF_LOCAL: + sun = ((const struct sockaddr_un *)(const void *)sa); + (void)strlcpy(addr = abuf, sun->sun_path, sizeof(abuf)); + break; + case AF_INET: + sin4 = ((const struct sockaddr_in *)(const void *)sa); + p = ntohs(sin4->sin_port); + a = &sin4->sin_addr; + break; + case AF_INET6: + sin6 = ((const struct sockaddr_in6 *)(const void *)sa); + p = ntohs(sin6->sin6_port); + a = &sin6->sin6_addr; + break; +#ifdef HAVE_NET_IF_DL_H + case AF_LINK: + sdl = ((const struct sockaddr_dl *)(const void *)sa); + (void)strlcpy(addr = abuf, link_ntoa(sdl), sizeof(abuf)); + if ((w = strchr(addr, ':')) != NULL) { + *w++ = '\0'; + addr = w; + } + break; +#endif + default: + errno = EAFNOSUPPORT; + return -1; + } + + if (addr == abuf) + name = addr; + + if (a && getnameinfo(sa, (socklen_t)SLEN(sa), addr = abuf, + (unsigned int)sizeof(abuf), NULL, 0, + NI_NUMERICHOST|NI_NUMERICSERV) != 0) + return -1; + + for (ptr = fmt; *ptr; ptr++) { + if (*ptr != '%') { + ADDC(*ptr); + continue; + } + next_char: + switch (*++ptr) { + case '?': + na = 0; + goto next_char; + case 'a': + ADDS(addr); + break; + case 'p': + if (p != -1) { + (void)snprintf(nbuf, sizeof(nbuf), "%d", p); + ADDS(nbuf); + } else + ADDNA(); + break; + case 'f': + (void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family); + ADDS(nbuf); + break; + case 'l': + (void)snprintf(nbuf, sizeof(nbuf), "%d", SLEN(sa)); + ADDS(nbuf); + break; + case 'A': + if (name) + ADDS(name); + else if (!a) + ADDNA(); + else { + getnameinfo(sa, (socklen_t)SLEN(sa), + name = Abuf, + (unsigned int)sizeof(nbuf), NULL, 0, 0); + ADDS(name); + } + break; + case 'P': + if (port) + ADDS(port); + else if (p == -1) + ADDNA(); + else { + getnameinfo(sa, (socklen_t)SLEN(sa), NULL, 0, + port = pbuf, + (unsigned int)sizeof(pbuf), 0); + ADDS(port); + } + break; + case 'I': +#ifdef HAVE_NET_IF_DL_H + if (sdl && addr != abuf) { + ADDS(abuf); + } else +#endif + { + ADDNA(); + } + break; + case 'F': + if (sin6) { + (void)snprintf(nbuf, sizeof(nbuf), "%d", + sin6->sin6_flowinfo); + ADDS(nbuf); + break; + } else { + ADDNA(); + } + break; + case 'S': + if (sin6) { + (void)snprintf(nbuf, sizeof(nbuf), "%d", + sin6->sin6_scope_id); + ADDS(nbuf); + break; + } else { + ADDNA(); + } + break; + case 'R': +#ifdef HAVE_NETATALK_AT_H + if (sat) { + const struct netrange *n = + &sat->sat_range.r_netrange; + (void)snprintf(nbuf, sizeof(nbuf), + "%d:[%d,%d]", n->nr_phase , n->nr_firstnet, + n->nr_lastnet); + ADDS(nbuf); + } else +#endif + { + ADDNA(); + } + break; + case 'D': + switch (sa->sa_family) { +#ifdef HAVE_NETATALK_AT_H + case AF_APPLETALK: + debug_at(nbuf, sizeof(nbuf), sat); + break; +#endif + case AF_LOCAL: + debug_un(nbuf, sizeof(nbuf), sun); + break; + case AF_INET: + debug_in(nbuf, sizeof(nbuf), sin4); + break; + case AF_INET6: + debug_in6(nbuf, sizeof(nbuf), sin6); + break; +#ifdef HAVE_NET_IF_DL_H + case AF_LINK: + debug_dl(nbuf, sizeof(nbuf), sdl); + break; +#endif + default: + abort(); + } + ADDS(nbuf); + break; + default: + ADDC('%'); + if (na == 0) + ADDC('?'); + if (*ptr == '\0') + goto done; + /*FALLTHROUGH*/ + case '%': + ADDC(*ptr); + break; + } + na = 1; + } +done: + if (buf < ebuf) + *buf = '\0'; + else if (len != 0) + sbuf[len - 1] = '\0'; + return (int)(buf - sbuf); +} diff --git a/port/strlcat.c b/port/strlcat.c new file mode 100644 index 00000000000..8cabd654e6b --- /dev/null +++ b/port/strlcat.c @@ -0,0 +1,99 @@ +/* $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 $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(_KERNEL) && !defined(_STANDALONE) +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include +#endif + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: strlcat.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#ifdef _LIBC +#include "namespace.h" +#endif +#include +#include +#include + +#ifdef _LIBC +# ifdef __weak_alias +__weak_alias(strlcat, _strlcat) +# endif +#endif + +#else +#include +#endif /* !_KERNEL && !_STANDALONE */ + +#if !HAVE_STRLCAT +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ +#if 1 + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +#else + + /* + * Find length of string in dst (maxing out at siz). + */ + size_t dlen = strnlen(dst, siz); + + /* + * Copy src into any remaining space in dst (truncating if needed). + * Note strlcpy(dst, src, 0) returns strlen(src). + */ + return dlen + strlcpy(dst + dlen, src, siz - dlen); +#endif +} +#endif diff --git a/port/strlcpy.c b/port/strlcpy.c new file mode 100644 index 00000000000..3de72a640c5 --- /dev/null +++ b/port/strlcpy.c @@ -0,0 +1,81 @@ +/* $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 $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(_KERNEL) && !defined(_STANDALONE) +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include +#endif + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: strlcpy.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#ifdef _LIBC +#include "namespace.h" +#endif +#include +#include +#include + +#ifdef _LIBC +# ifdef __weak_alias +__weak_alias(strlcpy, _strlcpy) +# endif +#endif +#else +#include +#endif /* !_KERNEL && !_STANDALONE */ + + +#if !HAVE_STRLCPY +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif diff --git a/port/strtoi.c b/port/strtoi.c new file mode 100644 index 00000000000..b0bed7058cc --- /dev/null +++ b/port/strtoi.c @@ -0,0 +1,63 @@ +/* $NetBSD: strtoi.c,v 1.2 2025/02/11 17:48:31 christos Exp $ */ + +/*- + * Copyright (c) 2005 The DragonFly Project. All rights reserved. + * Copyright (c) 2003 Citrus Project, + * All rights reserved. + * + * 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. + * + * Created by Kamil Rytarowski, based on ID: + * NetBSD: src/common/lib/libc/stdlib/strtoul.c,v 1.3 2008/08/20 19:58:34 oster Exp + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: strtoi.c,v 1.2 2025/02/11 17:48:31 christos Exp $"); + +#if defined(_KERNEL) +#include +#include +#include +#elif defined(_STANDALONE) +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#define _FUNCNAME strtoi +#define __TYPE intmax_t +#define __WRAPPED strtoimax + +#if !HAVE_STRTOI +#include "_strtoi.h" +#endif diff --git a/port/vsyslog_r.c b/port/vsyslog_r.c new file mode 100644 index 00000000000..848f31b0445 --- /dev/null +++ b/port/vsyslog_r.c @@ -0,0 +1,13 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +void +vsyslog_r(int priority, struct syslog_data *sd __unused, const char *fmt, va_list ap) +{ + vsyslog(priority, fmt, ap); +} + diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 00000000000..d127955acdb --- /dev/null +++ b/test/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:54 christos Exp $ + +MKMAN=no + +PROGS=srvtest cltest +SRCS.srvtest = srvtest.c +SRCS.cltest = cltest.c +CPPFLAGS+=-DBLDEBUG +LDADD+=-lutil +DPADD+=${LIBUTIL} + +.include diff --git a/test/cltest.c b/test/cltest.c new file mode 100644 index 00000000000..dc77a522bad --- /dev/null +++ b/test/cltest.c @@ -0,0 +1,138 @@ +/* $NetBSD: cltest.c,v 1.2 2025/02/11 17:48:31 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 +#endif +__RCSID("$NetBSD: cltest.c,v 1.2 2025/02/11 17:48:31 christos Exp $"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef HAVE_UTIL_H +#include +#endif + +static __dead void +usage(int c) +{ + warnx("Unknown option `%c'", (char)c); + fprintf(stderr, "Usage: %s [-u] [-a ] [-m ] [-p ]\n", + getprogname()); + exit(EXIT_FAILURE); +} + +static void +getaddr(const char *a, in_port_t p, struct sockaddr_storage *ss, + socklen_t *slen) +{ + int c; + + memset(ss, 0, sizeof(*ss)); + p = htons(p); + + if (strchr(a, ':')) { + struct sockaddr_in6 *s6 = (void *)ss; + c = inet_pton(AF_INET6, a, &s6->sin6_addr); + s6->sin6_family = AF_INET6; + *slen = sizeof(*s6); + s6->sin6_port = p; + } else { + struct sockaddr_in *s = (void *)ss; + c = inet_pton(AF_INET, a, &s->sin_addr); + s->sin_family = AF_INET; + *slen = sizeof(*s); + s->sin_port = p; + } +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + ss->ss_len = (uint8_t)*slen; +#endif + if (c == -1) + err(EXIT_FAILURE, "Invalid address `%s'", a); +} + +int +main(int argc, char *argv[]) +{ + int sfd; + int c; + struct sockaddr_storage ss; + const char *msg = "hello"; + const char *addr = "127.0.0.1"; + int type = SOCK_STREAM; + in_port_t port = 6161; + socklen_t slen; + char buf[128]; + + while ((c = getopt(argc, argv, "a:m:p:u")) != -1) { + switch (c) { + case 'a': + addr = optarg; + break; + case 'm': + msg = optarg; + break; + case 'p': + port = (in_port_t)atoi(optarg); + break; + case 'u': + type = SOCK_DGRAM; + break; + default: + usage(c); + } + } + + getaddr(addr, port, &ss, &slen); + + if ((sfd = socket(AF_INET, type, 0)) == -1) + err(EXIT_FAILURE, "socket"); + + sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (const void *)&ss); + printf("connecting to: %s\n", buf); + if (connect(sfd, (const void *)&ss, slen) == -1) + err(EXIT_FAILURE, "connect"); + + size_t len = strlen(msg) + 1; + if (write(sfd, msg, len) != (ssize_t)len) + err(EXIT_FAILURE, "write"); + return 0; +} diff --git a/test/srvtest.c b/test/srvtest.c new file mode 100644 index 00000000000..4eb9468ed5f --- /dev/null +++ b/test/srvtest.c @@ -0,0 +1,238 @@ +/* $NetBSD: srvtest.c,v 1.2 2025/02/11 17:43:16 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 +#endif +__RCSID("$NetBSD: srvtest.c,v 1.2 2025/02/11 17:43:16 christos Exp $"); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blocklist.h" +#ifdef BLDEBUG +#include "bl.h" +static void *b; +#endif + +#ifndef INFTIM +#define INFTIM -1 +#endif + +static void +process_tcp(int afd) +{ + ssize_t n; + char buffer[256]; + + memset(buffer, 0, sizeof(buffer)); + + if ((n = read(afd, buffer, sizeof(buffer))) == -1) + err(1, "read"); + buffer[sizeof(buffer) - 1] = '\0'; + printf("%s: sending %d %s\n", getprogname(), afd, buffer); +#ifdef BLDEBUG + blocklist_r(b, 1, afd, buffer); +#else + blocklist(1, afd, buffer); +#endif + exit(0); +} + +static void +process_udp(int afd) +{ + ssize_t n; + char buffer[256]; + struct sockaddr_storage ss; + socklen_t slen; + + memset(buffer, 0, sizeof(buffer)); + + slen = (socklen_t)sizeof(ss); + memset(&ss, 0, sizeof(ss)); + if ((n = recvfrom(afd, buffer, sizeof(buffer), 0, (void *)&ss, + &slen)) == -1) + err(1, "recvfrom"); + buffer[sizeof(buffer) - 1] = '\0'; + printf("%s: sending %d %s\n", getprogname(), afd, buffer); + blocklist_sa(1, afd, (void *)&ss, slen, buffer); + exit(0); +} +static int +cr(int af, int type, in_port_t p) +{ + int sfd; + struct sockaddr_storage ss; + socklen_t slen; + sfd = socket(af == AF_INET ? PF_INET : PF_INET6, type, 0); + if (sfd == -1) + err(1, "socket"); + + p = htons(p); + memset(&ss, 0, sizeof(ss)); + if (af == AF_INET) { + struct sockaddr_in *s = (void *)&ss; + s->sin_family = AF_INET; + slen = sizeof(*s); + s->sin_port = p; + } else { + struct sockaddr_in6 *s6 = (void *)&ss; + s6->sin6_family = AF_INET6; + slen = sizeof(*s6); + s6->sin6_port = p; + } +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + ss.ss_len = (uint8_t)slen; +#endif + + if (bind(sfd, (const void *)&ss, slen) == -1) + err(1, "bind"); + + if (type != SOCK_DGRAM) + if (listen(sfd, 5) == -1) + err(1, "listen"); + return sfd; +} + +static void +handle(int type, int sfd) +{ + struct sockaddr_storage ss; + socklen_t alen = sizeof(ss); + int afd; + + if (type != SOCK_DGRAM) { + if ((afd = accept(sfd, (void *)&ss, &alen)) == -1) + err(1, "accept"); + } else + afd = sfd; + + /* Create child process */ + switch (fork()) { + case -1: + err(1, "fork"); + case 0: + if (type == SOCK_DGRAM) + process_udp(afd); + else + process_tcp(afd); + break; + default: + close(afd); + break; + } +} + +static __dead void +usage(int c) +{ + warnx("Unknown option `%c'", (char)c); + fprintf(stderr, "Usage: %s [-u] [-p ]" +#ifdef BLDEBUG + " [-s ]" +#endif + "\n", getprogname()); + exit(EXIT_FAILURE); +} + +int +main(int argc, char *argv[]) +{ +#ifdef __linux__ +#define NUMFD 1 +#else +#define NUMFD 2 +#endif + struct pollfd pfd[NUMFD]; + int type = SOCK_STREAM, c; + in_port_t port = 6161; +#ifdef BLDEBUG + char *sockpath = "blsock"; + const char *optstr = "up:s:"; +#else + const char *optstr = "up:"; +#endif + + signal(SIGCHLD, SIG_IGN); + + while ((c = getopt(argc, argv, optstr)) != -1) + switch (c) { + case 'u': + type = SOCK_DGRAM; + break; + 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 + pfd[1].fd = cr(AF_INET6, type, port); + pfd[1].events = POLLIN; +#endif + + for (;;) { + if (poll(pfd, __arraycount(pfd), INFTIM) == -1) + err(1, "poll"); + for (size_t i = 0; i < __arraycount(pfd); i++) { + if ((pfd[i].revents & POLLIN) == 0) + continue; + handle(type, pfd[i].fd); + } + } +} From a54c7d52432b4abe1f67fc5f6781803cdfb125f2 Mon Sep 17 00:00:00 2001 From: Lucas Holt Date: Tue, 22 Sep 2026 13:58:36 -0400 Subject: [PATCH 2/4] Remove contrib/blacklist Upstream renamed the project to blocklist; the replacement is imported at contrib/blocklist in the next commit. AI-Assisted-by: Claude Fable 5.1 Signed-off-by: Lucas Holt --- contrib/blacklist/Makefile | 5 - contrib/blacklist/Makefile.inc | 10 - contrib/blacklist/README | 113 -- contrib/blacklist/TODO | 21 - contrib/blacklist/bin/Makefile | 15 - contrib/blacklist/bin/blacklistctl.8 | 86 -- contrib/blacklist/bin/blacklistctl.c | 168 --- contrib/blacklist/bin/blacklistd.8 | 248 ---- contrib/blacklist/bin/blacklistd.c | 582 ---------- contrib/blacklist/bin/blacklistd.conf.5 | 229 ---- contrib/blacklist/bin/conf.c | 1145 ------------------- contrib/blacklist/bin/conf.h | 65 -- contrib/blacklist/bin/internal.c | 48 - contrib/blacklist/bin/internal.h | 57 - contrib/blacklist/bin/run.c | 157 --- contrib/blacklist/bin/run.h | 41 - contrib/blacklist/bin/state.c | 235 ---- contrib/blacklist/bin/state.h | 62 - contrib/blacklist/bin/support.c | 160 --- contrib/blacklist/bin/support.h | 44 - contrib/blacklist/diff/ftpd.diff | 91 -- contrib/blacklist/diff/named.diff | 216 ---- contrib/blacklist/diff/proftpd.diff | 124 -- contrib/blacklist/diff/ssh.diff | 150 --- contrib/blacklist/etc/Makefile | 10 - contrib/blacklist/etc/blacklistd.conf | 14 - contrib/blacklist/etc/npf.conf | 15 - contrib/blacklist/etc/rc.d/Makefile | 6 - contrib/blacklist/etc/rc.d/blacklistd | 57 - contrib/blacklist/include/Makefile | 10 - contrib/blacklist/include/bl.h | 78 -- contrib/blacklist/include/blacklist.h | 55 - contrib/blacklist/lib/Makefile | 19 - contrib/blacklist/lib/bl.c | 533 --------- contrib/blacklist/lib/blacklist.c | 108 -- contrib/blacklist/lib/libblacklist.3 | 157 --- contrib/blacklist/lib/shlib_version | 2 - contrib/blacklist/libexec/Makefile | 6 - contrib/blacklist/libexec/blacklistd-helper | 272 ----- contrib/blacklist/port/Makefile.am | 25 - contrib/blacklist/port/_strtoi.h | 93 -- contrib/blacklist/port/clock_gettime.c | 17 - contrib/blacklist/port/config.h | 3 - contrib/blacklist/port/configure.ac | 91 -- contrib/blacklist/port/fgetln.c | 106 -- contrib/blacklist/port/fparseln.c | 236 ---- contrib/blacklist/port/getprogname.c | 24 - contrib/blacklist/port/m4/.cvsignore | 1 - contrib/blacklist/port/pidfile.c | 183 --- contrib/blacklist/port/popenve.c | 277 ----- contrib/blacklist/port/port.h | 86 -- contrib/blacklist/port/sockaddr_snprintf.c | 383 ------- contrib/blacklist/port/strlcat.c | 96 -- contrib/blacklist/port/strlcpy.c | 78 -- contrib/blacklist/port/strtoi.c | 61 - contrib/blacklist/test/Makefile | 12 - contrib/blacklist/test/cltest.c | 136 --- contrib/blacklist/test/srvtest.c | 220 ---- 58 files changed, 7542 deletions(-) delete mode 100644 contrib/blacklist/Makefile delete mode 100644 contrib/blacklist/Makefile.inc delete mode 100644 contrib/blacklist/README delete mode 100644 contrib/blacklist/TODO delete mode 100644 contrib/blacklist/bin/Makefile delete mode 100644 contrib/blacklist/bin/blacklistctl.8 delete mode 100644 contrib/blacklist/bin/blacklistctl.c delete mode 100644 contrib/blacklist/bin/blacklistd.8 delete mode 100644 contrib/blacklist/bin/blacklistd.c delete mode 100644 contrib/blacklist/bin/blacklistd.conf.5 delete mode 100644 contrib/blacklist/bin/conf.c delete mode 100644 contrib/blacklist/bin/conf.h delete mode 100644 contrib/blacklist/bin/internal.c delete mode 100644 contrib/blacklist/bin/internal.h delete mode 100644 contrib/blacklist/bin/run.c delete mode 100644 contrib/blacklist/bin/run.h delete mode 100644 contrib/blacklist/bin/state.c delete mode 100644 contrib/blacklist/bin/state.h delete mode 100644 contrib/blacklist/bin/support.c delete mode 100644 contrib/blacklist/bin/support.h delete mode 100644 contrib/blacklist/diff/ftpd.diff delete mode 100644 contrib/blacklist/diff/named.diff delete mode 100644 contrib/blacklist/diff/proftpd.diff delete mode 100644 contrib/blacklist/diff/ssh.diff delete mode 100644 contrib/blacklist/etc/Makefile delete mode 100644 contrib/blacklist/etc/blacklistd.conf delete mode 100644 contrib/blacklist/etc/npf.conf delete mode 100644 contrib/blacklist/etc/rc.d/Makefile delete mode 100644 contrib/blacklist/etc/rc.d/blacklistd delete mode 100644 contrib/blacklist/include/Makefile delete mode 100644 contrib/blacklist/include/bl.h delete mode 100644 contrib/blacklist/include/blacklist.h delete mode 100644 contrib/blacklist/lib/Makefile delete mode 100644 contrib/blacklist/lib/bl.c delete mode 100644 contrib/blacklist/lib/blacklist.c delete mode 100644 contrib/blacklist/lib/libblacklist.3 delete mode 100644 contrib/blacklist/lib/shlib_version delete mode 100644 contrib/blacklist/libexec/Makefile delete mode 100644 contrib/blacklist/libexec/blacklistd-helper delete mode 100644 contrib/blacklist/port/Makefile.am delete mode 100644 contrib/blacklist/port/_strtoi.h delete mode 100644 contrib/blacklist/port/clock_gettime.c delete mode 100644 contrib/blacklist/port/config.h delete mode 100644 contrib/blacklist/port/configure.ac delete mode 100644 contrib/blacklist/port/fgetln.c delete mode 100644 contrib/blacklist/port/fparseln.c delete mode 100644 contrib/blacklist/port/getprogname.c delete mode 100644 contrib/blacklist/port/m4/.cvsignore delete mode 100644 contrib/blacklist/port/pidfile.c delete mode 100644 contrib/blacklist/port/popenve.c delete mode 100644 contrib/blacklist/port/port.h delete mode 100644 contrib/blacklist/port/sockaddr_snprintf.c delete mode 100644 contrib/blacklist/port/strlcat.c delete mode 100644 contrib/blacklist/port/strlcpy.c delete mode 100644 contrib/blacklist/port/strtoi.c delete mode 100644 contrib/blacklist/test/Makefile delete mode 100644 contrib/blacklist/test/cltest.c delete mode 100644 contrib/blacklist/test/srvtest.c diff --git a/contrib/blacklist/Makefile b/contrib/blacklist/Makefile deleted file mode 100644 index da4411d0ca7..00000000000 --- a/contrib/blacklist/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# $NetBSD: Makefile,v 1.2 2015/01/22 17:49:41 christos Exp $ - -SUBDIR = lib .WAIT include bin etc libexec - -.include diff --git a/contrib/blacklist/Makefile.inc b/contrib/blacklist/Makefile.inc deleted file mode 100644 index 85c82783cd3..00000000000 --- a/contrib/blacklist/Makefile.inc +++ /dev/null @@ -1,10 +0,0 @@ -# $NetBSD: Makefile.inc,v 1.3 2015/01/23 03:57:22 christos Exp $ - -WARNS=6 -.if !defined(LIB) -LDADD+= -lblacklist -DPADD+= ${LIBBLACKLIST} -.endif -CPPFLAGS+= -I${.CURDIR}/../include -CPPFLAGS+=-DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_UTIL_H -DHAVE_DB_H - diff --git a/contrib/blacklist/README b/contrib/blacklist/README deleted file mode 100644 index 7da3317a77f..00000000000 --- a/contrib/blacklist/README +++ /dev/null @@ -1,113 +0,0 @@ -# $NetBSD: README,v 1.8 2017/04/13 17:59:34 christos 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 -(this is currently designed for npf) and the configuration file -(inspired from inetd.conf) is in etc/blacklistd.conf. - -On NetBSD you can find an example npf.conf and blacklistd.conf in -/usr/share/examples/blacklistd; 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. - -There is also a startup file in etc/rc.d/blacklistd - -Patches to various daemons to add blacklisting capabilitiers are in the -"diff" directory: - - OpenSSH: diff/ssh.diff [tcp socket example] - - Bind: diff/named.diff [both tcp and udp] - - ftpd: diff/ftpd.diff [tcp] - -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 -is handled by the library. In the simplest form the only thing the -daemon needs to do is to call: - - blacklist(action, acceptedfd, message); - -Where: - action = 0 -> successful login clear blacklist 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 - if the program has access to the listening - socket is done by virtue that the port - number is retrieved from the kernel. - message -> an optional string that is used in debugging logs. - -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: - - blacklist_sa(action, acceptedfd, sockaddr, sockaddr_len, message); - -The configuration file contains entries of the form: - -# Blacklist 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 -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 -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, -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 -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, -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: - -ext_if=bge0 -int_if=sk0 - -group "external" on $ext_if { - ... - ruleset "blacklistd-ext" - ruleset "blacklistd" - ... -} - -group "internal" on $int_if { - ... - ruleset "blacklistd-int" - ... -} - -You can use 'blacklistctl dump -a' to list all the current entries -in the database; the ones that have nfail / where urrent ->= otal, should have an id assosiated 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 list'. The number of current entries can exceed -the total. This happens because entering packet filter rules is -asynchronous; there could be other connection before the rule -becomes activated. - -Enjoy, - -christos diff --git a/contrib/blacklist/TODO b/contrib/blacklist/TODO deleted file mode 100644 index 9925020d54b..00000000000 --- a/contrib/blacklist/TODO +++ /dev/null @@ -1,21 +0,0 @@ -# $NetBSD: TODO,v 1.7 2015/01/23 21:34:01 christos Exp $ - -- don't poll periodically, find the next timeout -- use the socket also for commands? Or separate socket? -- add functionality to the control program. Should it change the database - directly, or talk to the daemon to have it do it? -- perhaps handle interfaces too instead of addresses for dynamic ip? - ? What to do with multiple addresses? -- perhaps rate limit against DoS -- perhaps instead of scanning the list have a sparse map by port? -- do we want to use libnpf directly for efficiency? -- add more daemons ftpd? -- do we care about the db state becoming too large? -- instead of a yes = bump one, no = return to 0 interface, do we want - to have something more flexible like? - +n - -n - block - unblock -- do we need an api in blacklistctl to perform maintenance -- fix the blacklistctl output to be more user friendly diff --git a/contrib/blacklist/bin/Makefile b/contrib/blacklist/bin/Makefile deleted file mode 100644 index 280c72fd3af..00000000000 --- a/contrib/blacklist/bin/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# $NetBSD: Makefile,v 1.11 2015/01/27 19:40:36 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 -DBG=-g - -LDADD+=-lutil -DPADD+=${LIBUTIL} - -.include diff --git a/contrib/blacklist/bin/blacklistctl.8 b/contrib/blacklist/bin/blacklistctl.8 deleted file mode 100644 index 7c652111774..00000000000 --- a/contrib/blacklist/bin/blacklistctl.8 +++ /dev/null @@ -1,86 +0,0 @@ -.\" $NetBSD: blacklistctl.8,v 1.9 2016/06/08 12:48:37 wiz 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 June 7, 2016 -.Dt BLACKLISTCTL 8 -.Os -.Sh NAME -.Nm blacklistctl -.Nd display and change the state of blacklistd -.Sh SYNOPSIS -.Nm -.Cm dump -.Op Fl abdnrw -.Sh DESCRIPTION -.Nm -is a program used to display the state of -.Xr blacklistd 8 -.Pp -The following options are available: -.Bl -tag -width indent -.It Fl a -Show all database entries, by default it shows only the embryonic ones. -.It Fl b -Show only the blocked entries. -.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 -.Sh SEE ALSO -.Xr blacklistd 8 -.Sh NOTES -Sometimes the reported number of failed attempts can exceed the number -of attempts that -.Xr blacklistd 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 blacklistd 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/blacklist/bin/blacklistctl.c b/contrib/blacklist/bin/blacklistctl.c deleted file mode 100644 index aebbf72acc5..00000000000 --- a/contrib/blacklist/bin/blacklistctl.c +++ /dev/null @@ -1,168 +0,0 @@ -/* $NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 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 - -#include -__RCSID("$NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $"); - -#include -#include -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#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 - warnx("Unknown option `%c'", (char)c); - fprintf(stderr, "Usage: %s dump [-abdnrw]\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); - break; - } - - 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/blacklist/bin/blacklistd.8 b/contrib/blacklist/bin/blacklistd.8 deleted file mode 100644 index ec7f8b429d9..00000000000 --- a/contrib/blacklist/bin/blacklistd.8 +++ /dev/null @@ -1,248 +0,0 @@ -.\" $NetBSD: blacklistd.8,v 1.18 2016/07/30 06:09:29 dholland 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 October 5, 2018 -.Dt BLACKLISTD 8 -.Os -.Sh NAME -.Nm blacklistd -.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 sockspath -or if that is not specified to -.Pa /var/run/blacklistd.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 -.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 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
-.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 blacklistd ) . -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 remove -Then the same control script is invoked as: -.Bd -literal -offset indent -control remove
-.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, usually -.Pa /usr/libexec/blacklistd-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, usually -.Pa /etc/blacklistd.conf . -.It Fl D Ar dbfile -The Berkeley DB file where -.Nm -stores its state, usually -.Pa /var/db/blacklistd.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 -.Ed -.It Fl P Ar sockspathsfile -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 blacklistd . -.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 HUP -Receipt of this signal causes -.Nm -to re-read the configuration file. -.It INT, TERM & QUIT -These signals tell -.Nm -to exit in an orderly fashion. -.It USR1 -This signal tells -.Nm -to increase the internal debugging level by 1. -.It USR2 -This signal tells -.Nm -to decrease the internal debugging level by 1. -.El -.Sh FILES -.Bl -tag -width /usr/libexec/blacklistd-helper -compact -.It Pa /usr/libexec/blacklistd-helper -Shell script invoked to interface with the packet filter. -.It Pa /etc/blacklistd.conf -Configuration file. -.It Pa /var/db/blacklistd.db -Database of current connection entries. -.It Pa /var/run/blacklistd.sock -Socket to receive connection notifications. -.El -.Sh SEE ALSO -.Xr blacklistd.conf 5 , -.Xr blacklistctl 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/blacklist/bin/blacklistd.c b/contrib/blacklist/bin/blacklistd.c deleted file mode 100644 index ebfcc6e840b..00000000000 --- a/contrib/blacklist/bin/blacklistd.c +++ /dev/null @@ -1,582 +0,0 @@ -/* $NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 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 -#include -__RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $"); - -#include -#include -#include - -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 ] [-R ] " - "[-P ] [-C ] [-D ] " - "[-s ] [-t ]\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; - - 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) { - 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, - 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 (dbi.id[0]) { - /* - * We should not be getting this since the rule - * should have blocked the address. A possible - * explanation is that someone removed that rule, - * and another would be that we got another attempt - * before we added the rule. In anycase, we remove - * and re-add the rule because we don't want to add - * it twice, because then we'd lose track of it. - */ - (*lfun)(LOG_DEBUG, "rule exists %s", dbi.id); - (void)run_change("rem", &c, dbi.id, 0); - dbi.id[0] = '\0'; - } - if (c.c_nfail != -1 && dbi.count >= c.c_nfail) { - 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); - if (bl == NULL || !bl_isconnected(bl)) - exit(EXIT_FAILURE); - if (*nfd >= *maxfd) { - *maxfd += 10; - *blp = reallocarray(*blp, *maxfd, sizeof(**blp)); - if (*blp == NULL) - err(EXIT_FAILURE, "malloc"); - *pfdp = reallocarray(*pfdp, *maxfd, sizeof(**pfdp)); - 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 = reallocarray(*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) -{ - struct conf c; - struct dbinfo dbi; - unsigned int f; - - for (f = 1; state_iterate(state, &c, &dbi, f) == 1; f = 0) { - if (dbi.id[0] == '\0') - continue; - (void)run_change("add", &c, dbi.id, sizeof(dbi.id)); - } -} - -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 = reallocarray(blsock, maxblsock, - sizeof(*blsock)); - 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(0); - - 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); - else { - if (restore) { - if (!flush) - rules_flush(); - rules_restore(); - } - } - if (state == NULL) - exit(EXIT_FAILURE); - - 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)"); - exit(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); - exit(EXIT_SUCCESS); -} diff --git a/contrib/blacklist/bin/blacklistd.conf.5 b/contrib/blacklist/bin/blacklistd.conf.5 deleted file mode 100644 index d79da702c85..00000000000 --- a/contrib/blacklist/bin/blacklistd.conf.5 +++ /dev/null @@ -1,229 +0,0 @@ -.\" $NetBSD: blacklistd.conf.5,v 1.7 2017/06/07 13:50:57 wiz 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 13, 2026 -.Dt BLACKLISTD.CONF 5 -.Os -.Sh NAME -.Nm blacklistd.conf -.Nd configuration file format for blacklistd -.Sh DESCRIPTION -The -.Nm -file contains configuration entries for -.Xr blacklistd 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 - [
|[/]:] -.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 -.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 disable -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 -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 -.Va remote -rules are applied. -The -.Va name , -.Va nfail , -and -.Va disable -fields can be altered by the -.Va remote -rule that matched. -.Pp -The -.Va remote -rules can be used for whitelisting specific addresses, changing the mask -size, the rule that the packet filter uses, the number of failed attempts, -or the block duration. -.Sh FILES -.Bl -tag -width /etc/blacklistd.conf -compact -.It Pa /etc/blacklistd.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 * * * * * * -# For addresses coming from 8.8.0.0/16 block class C 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 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/blacklist/bin/conf.c b/contrib/blacklist/bin/conf.c deleted file mode 100644 index 5fc614d794b..00000000000 --- a/contrib/blacklist/bin/conf.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* $NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 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 - -#include -__RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $"); - -#include -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bl.h" -#include "internal.h" -#include "support.h" -#include "conf.h" - - -struct sockaddr_if { - uint8_t sif_len; - sa_family_t sif_family; - in_port_t sif_port; - char sif_name[16]; -}; - -#define SIF_NAME(a) \ - ((const struct sockaddr_if *)(const void *)(a))->sif_name - -static int conf_is_interface(const char *); - -#define FSTAR -1 -#define FEQUAL -2 - -static void -advance(char **p) -{ - char *ep = *p; - while (*ep && !isspace((unsigned char)*ep)) - ep++; - while (*ep && isspace((unsigned char)*ep)) - *ep++ = '\0'; - *p = ep; -} - -static int -conf_getnum(const char *f, size_t l, bool local, void *rp, const char *name, - const char *p) -{ - int e; - intmax_t im; - int *r = rp; - - if (strcmp(p, "*") == 0) { - *r = FSTAR; - return 0; - } - if (strcmp(p, "=") == 0) { - if (local) - goto out; - *r = FEQUAL; - return 0; - } - - im = strtoi(p, NULL, 0, 0, INT_MAX, &e); - if (e == 0) { - *r = (int)im; - return 0; - } - - if (f == NULL) - return -1; - (*lfun)(LOG_ERR, "%s: %s, %zu: Bad number for %s [%s]", __func__, f, l, - name, p); - return -1; -out: - (*lfun)(LOG_ERR, "%s: %s, %zu: `=' for %s not allowed in local config", - __func__, f, l, name); - return -1; - -} - -static int -conf_getnfail(const char *f, size_t l, bool local, struct conf *c, - const char *p) -{ - return conf_getnum(f, l, local, &c->c_nfail, "nfail", p); -} - -static int -conf_getsecs(const char *f, size_t l, bool local, struct conf *c, const char *p) -{ - int e; - char *ep; - intmax_t tot, im; - - tot = 0; - if (strcmp(p, "*") == 0) { - c->c_duration = FSTAR; - return 0; - } - if (strcmp(p, "=") == 0) { - if (local) - goto out; - c->c_duration = FEQUAL; - return 0; - } -again: - im = strtoi(p, &ep, 0, 0, INT_MAX, &e); - - if (e == ENOTSUP) { - switch (*ep) { - case 'd': - im *= 24; - /*FALLTHROUGH*/ - case 'h': - im *= 60; - /*FALLTHROUGH*/ - case 'm': - im *= 60; - /*FALLTHROUGH*/ - case 's': - e = 0; - tot += im; - if (ep[1] != '\0') { - p = ep + 2; - goto again; - } - break; - } - } else - tot = im; - - if (e == 0) { - c->c_duration = (int)tot; - return 0; - } - - if (f == NULL) - return -1; - (*lfun)(LOG_ERR, "%s: %s, %zu: Bad number [%s]", __func__, f, l, p); - return -1; -out: - (*lfun)(LOG_ERR, "%s: %s, %zu: `=' duration not allowed in local" - " config", __func__, f, l); - return -1; - -} - -static int -conf_getport(const char *f, size_t l, bool local, void *r, const char *p) -{ - struct servent *sv; - - // XXX: Pass in the proto instead - if ((sv = getservbyname(p, "tcp")) != NULL) { - *(int *)r = ntohs(sv->s_port); - return 0; - } - if ((sv = getservbyname(p, "udp")) != NULL) { - *(int *)r = ntohs(sv->s_port); - return 0; - } - - return conf_getnum(f, l, local, r, "service", p); -} - -static int -conf_getmask(const char *f, size_t l, bool local, const char **p, int *mask) -{ - char *d; - const char *s = *p; - - if ((d = strchr(s, ':')) != NULL) { - *d++ = '\0'; - *p = d; - } - if ((d = strchr(s, '/')) == NULL) { - *mask = FSTAR; - return 0; - } - - *d++ = '\0'; - return conf_getnum(f, l, local, mask, "mask", d); -} - -static int -conf_gethostport(const char *f, size_t l, bool local, struct conf *c, - const char *p) -{ - char *d; // XXX: Ok to write to string. - in_port_t *port = NULL; - const char *pstr; - - if (strcmp(p, "*") == 0) { - c->c_port = FSTAR; - c->c_lmask = FSTAR; - return 0; - } - - if ((d = strchr(p, ']')) != NULL) { - *d++ = '\0'; - pstr = d; - p++; - } else - pstr = p; - - if (conf_getmask(f, l, local, &pstr, &c->c_lmask) == -1) - goto out; - - if (d) { - struct sockaddr_in6 *sin6 = (void *)&c->c_ss; - if (debug) - (*lfun)(LOG_DEBUG, "%s: host6 %s", __func__, p); - if (strcmp(p, "*") != 0) { - if (inet_pton(AF_INET6, p, &sin6->sin6_addr) == -1) - goto out; - sin6->sin6_family = AF_INET6; -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - sin6->sin6_len = sizeof(*sin6); -#endif - port = &sin6->sin6_port; - } - } else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) { - if (pstr == p) - pstr = "*"; - struct sockaddr_in *sin = (void *)&c->c_ss; - struct sockaddr_if *sif = (void *)&c->c_ss; - if (debug) - (*lfun)(LOG_DEBUG, "%s: host4 %s", __func__, p); - if (strcmp(p, "*") != 0) { - if (conf_is_interface(p)) { - if (!local) - goto out2; - if (debug) - (*lfun)(LOG_DEBUG, "%s: interface %s", - __func__, p); - if (c->c_lmask != FSTAR) - goto out1; - sif->sif_family = AF_MAX; - strlcpy(sif->sif_name, p, - sizeof(sif->sif_name)); -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - sif->sif_len = sizeof(*sif); -#endif - port = &sif->sif_port; - } else if (inet_pton(AF_INET, p, &sin->sin_addr) != -1) - { - sin->sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - sin->sin_len = sizeof(*sin); -#endif - port = &sin->sin_port; - } else - goto out; - } - } - - if (conf_getport(f, l, local, &c->c_port, pstr) == -1) - return -1; - - if (port && c->c_port != FSTAR && c->c_port != FEQUAL) - *port = htons((in_port_t)c->c_port); - return 0; -out: - (*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, pstr); - return -1; -out1: - (*lfun)(LOG_ERR, "%s: %s, %zu: Can't specify mask %d with " - "interface [%s]", __func__, f, l, c->c_lmask, p); - return -1; -out2: - (*lfun)(LOG_ERR, "%s: %s, %zu: Interface spec does not make sense " - "with remote config [%s]", __func__, f, l, p); - return -1; -} - -static int -conf_getproto(const char *f, size_t l, bool local __unused, struct conf *c, - const char *p) -{ - if (strcmp(p, "stream") == 0) { - c->c_proto = IPPROTO_TCP; - return 0; - } - if (strcmp(p, "dgram") == 0) { - c->c_proto = IPPROTO_UDP; - return 0; - } - return conf_getnum(f, l, local, &c->c_proto, "protocol", p); -} - -static int -conf_getfamily(const char *f, size_t l, bool local __unused, struct conf *c, - const char *p) -{ - if (strncmp(p, "tcp", 3) == 0 || strncmp(p, "udp", 3) == 0) { - c->c_family = p[3] == '6' ? AF_INET6 : AF_INET; - return 0; - } - return conf_getnum(f, l, local, &c->c_family, "family", p); -} - -static int -conf_getuid(const char *f, size_t l, bool local __unused, struct conf *c, - const char *p) -{ - struct passwd *pw; - - if ((pw = getpwnam(p)) != NULL) { - c->c_uid = (int)pw->pw_uid; - return 0; - } - - return conf_getnum(f, l, local, &c->c_uid, "user", p); -} - - -static int -conf_getname(const char *f, size_t l, bool local, struct conf *c, - const char *p) -{ - if (conf_getmask(f, l, local, &p, &c->c_rmask) == -1) - return -1; - - if (strcmp(p, "*") == 0) { - strlcpy(c->c_name, rulename, CONFNAMESZ); - return 0; - } - if (strcmp(p, "=") == 0) { - if (local) - goto out; - c->c_name[0] = '\0'; - return 0; - } - - snprintf(c->c_name, CONFNAMESZ, "%s%s", *p == '-' ? rulename : "", p); - return 0; -out: - (*lfun)(LOG_ERR, "%s: %s, %zu: `=' name not allowed in local" - " config", __func__, f, l); - return -1; -} - -static int -getvalue(const char *f, size_t l, bool local, void *r, char **p, - int (*fun)(const char *, size_t, bool, struct conf *, const char *)) -{ - char *ep = *p; - - advance(p); - return (*fun)(f, l, local, r, ep); -} - - -static int -conf_parseline(const char *f, size_t l, char *p, struct conf *c, bool local) -{ - int e; - - while (*p && isspace((unsigned char)*p)) - p++; - - memset(c, 0, sizeof(*c)); - e = getvalue(f, l, local, c, &p, conf_gethostport); - if (e) return -1; - e = getvalue(f, l, local, c, &p, conf_getproto); - if (e) return -1; - e = getvalue(f, l, local, c, &p, conf_getfamily); - if (e) return -1; - e = getvalue(f, l, local, c, &p, conf_getuid); - if (e) return -1; - e = getvalue(f, l, local, c, &p, conf_getname); - if (e) return -1; - e = getvalue(f, l, local, c, &p, conf_getnfail); - if (e) return -1; - e = getvalue(f, l, local, c, &p, conf_getsecs); - if (e) return -1; - - return 0; -} - -static int -conf_sort(const void *v1, const void *v2) -{ - const struct conf *c1 = v1; - const struct conf *c2 = v2; - -#define CMP(a, b, f) \ - if ((a)->f > (b)->f) return -1; \ - else if ((a)->f < (b)->f) return 1 - - CMP(c1, c2, c_ss.ss_family); - CMP(c1, c2, c_lmask); - CMP(c1, c2, c_port); - CMP(c1, c2, c_proto); - CMP(c1, c2, c_family); - CMP(c1, c2, c_rmask); - CMP(c1, c2, c_uid); -#undef CMP - return 0; -} - -static int -conf_is_interface(const char *name) -{ - const struct ifaddrs *ifa; - - for (ifa = ifas; ifa; ifa = ifa->ifa_next) - if (strcmp(ifa->ifa_name, name) == 0) - return 1; - return 0; -} - -#define MASK(m) ((uint32_t)~((1 << (32 - (m))) - 1)) - -static int -conf_amask_eq(const void *v1, const void *v2, size_t len, int mask) -{ - const uint32_t *a1 = v1; - const uint32_t *a2 = v2; - uint32_t m; - int omask = mask; - - len >>= 2; - switch (mask) { - case FSTAR: - if (memcmp(v1, v2, len) == 0) - return 1; - goto out; - case FEQUAL: - - (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__, - mask); - abort(); - default: - break; - } - - for (size_t i = 0; i < len; i++) { - if (mask > 32) { - m = htonl((uint32_t)~0); - mask -= 32; - } else if (mask) { - m = htonl(MASK(mask)); - mask = 0; - } else - return 1; - if ((a1[i] & m) != (a2[i] & m)) - goto out; - } - return 1; -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__, - b1, b2, omask); - } - return 0; -} - -/* - * Apply the mask to the given address - */ -static void -conf_apply_mask(void *v, size_t len, int mask) -{ - uint32_t *a = v; - uint32_t m; - - switch (mask) { - case FSTAR: - return; - case FEQUAL: - (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__, - mask); - abort(); - default: - break; - } - len >>= 2; - - for (size_t i = 0; i < len; i++) { - if (mask > 32) { - m = htonl((uint32_t)~0); - mask -= 32; - } else if (mask) { - m = htonl(MASK(mask)); - mask = 0; - } else - m = 0; - a[i] &= m; - } -} - -/* - * apply the mask and the port to the address given - */ -static void -conf_addr_set(struct conf *c, const struct sockaddr_storage *ss) -{ - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - in_port_t *port; - void *addr; - size_t alen; - - c->c_lmask = c->c_rmask; - c->c_ss = *ss; - - if (c->c_ss.ss_family != c->c_family) { - (*lfun)(LOG_CRIT, "%s: Internal error: mismatched family " - "%u != %u", __func__, c->c_ss.ss_family, c->c_family); - abort(); - } - - switch (c->c_ss.ss_family) { - case AF_INET: - sin = (void *)&c->c_ss; - port = &sin->sin_port; - addr = &sin->sin_addr; - alen = sizeof(sin->sin_addr); - break; - case AF_INET6: - sin6 = (void *)&c->c_ss; - port = &sin6->sin6_port; - addr = &sin6->sin6_addr; - alen = sizeof(sin6->sin6_addr); - break; - default: - (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u", - __func__, c->c_ss.ss_family); - abort(); - } - - *port = htons((in_port_t)c->c_port); - conf_apply_mask(addr, alen, c->c_lmask); - if (c->c_lmask == FSTAR) - c->c_lmask = (int)(alen * 8); - if (debug) { - char buf[128]; - sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&c->c_ss); - (*lfun)(LOG_DEBUG, "Applied address %s", buf); - } -} - -/* - * Compared two addresses for equality applying the mask - */ -static int -conf_inet_eq(const void *v1, const void *v2, int mask) -{ - const struct sockaddr *sa1 = v1; - const struct sockaddr *sa2 = v2; - size_t size; - - if (sa1->sa_family != sa2->sa_family) - return 0; - - switch (sa1->sa_family) { - case AF_INET: { - const struct sockaddr_in *s1 = v1; - const struct sockaddr_in *s2 = v2; - size = sizeof(s1->sin_addr); - v1 = &s1->sin_addr; - v2 = &s2->sin_addr; - break; - } - - case AF_INET6: { - const struct sockaddr_in6 *s1 = v1; - const struct sockaddr_in6 *s2 = v2; - size = sizeof(s1->sin6_addr); - v1 = &s1->sin6_addr; - v2 = &s2->sin6_addr; - break; - } - - default: - (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u", - __func__, sa1->sa_family); - abort(); - } - - return conf_amask_eq(v1, v2, size, mask); -} - -static int -conf_addr_in_interface(const struct sockaddr_storage *s1, - const struct sockaddr_storage *s2, int mask) -{ - const char *name = SIF_NAME(s2); - const struct ifaddrs *ifa; - - for (ifa = ifas; ifa; ifa = ifa->ifa_next) { - if ((ifa->ifa_flags & IFF_UP) == 0) - continue; - - if (strcmp(ifa->ifa_name, name) != 0) - continue; - - if (s1->ss_family != ifa->ifa_addr->sa_family) - continue; - - bool eq; - switch (s1->ss_family) { - case AF_INET: - case AF_INET6: - eq = conf_inet_eq(ifa->ifa_addr, s1, mask); - break; - default: - (*lfun)(LOG_ERR, "Bad family %u", s1->ss_family); - continue; - } - if (eq) - return 1; - } - return 0; -} - -static int -conf_addr_eq(const struct sockaddr_storage *s1, - const struct sockaddr_storage *s2, int mask) -{ - switch (s2->ss_family) { - case 0: - return 1; - case AF_MAX: - return conf_addr_in_interface(s1, s2, mask); - case AF_INET: - case AF_INET6: - return conf_inet_eq(s1, s2, mask); - default: - (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u", - __func__, s1->ss_family); - abort(); - } -} - -static int -conf_eq(const struct conf *c1, const struct conf *c2) -{ - - if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, c2->c_lmask)) - return 0; - -#define CMP(a, b, f) \ - if ((a)->f != (b)->f && (b)->f != FSTAR && (b)->f != FEQUAL) { \ - if (debug > 1) \ - (*lfun)(LOG_DEBUG, "%s: %s fail %d != %d", __func__, \ - __STRING(f), (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 const char * -conf_num(char *b, size_t l, int n) -{ - switch (n) { - case FSTAR: - return "*"; - case FEQUAL: - return "="; - default: - snprintf(b, l, "%d", n); - return b; - } -} - -static const char * -fmtname(const char *n) { - size_t l = strlen(rulename); - if (l == 0) - return "*"; - if (strncmp(n, rulename, l) == 0) { - if (n[l] != '\0') - return n + l; - else - return "*"; - } else if (!*n) - return "="; - else - return n; -} - -static void -fmtport(char *b, size_t l, int port) -{ - char buf[128]; - - if (port == FSTAR) - return; - - if (b[0] == '\0' || strcmp(b, "*") == 0) - snprintf(b, l, "%d", port); - else { - snprintf(buf, sizeof(buf), ":%d", port); - strlcat(b, buf, l); - } -} - -static const char * -fmtmask(char *b, size_t l, int fam, int mask) -{ - char buf[128]; - - switch (mask) { - case FSTAR: - return ""; - case FEQUAL: - if (strcmp(b, "=") == 0) - return ""; - else { - strlcat(b, "/=", l); - return b; - } - default: - break; - } - - switch (fam) { - case AF_INET: - if (mask == 32) - return ""; - break; - case AF_INET6: - if (mask == 128) - return ""; - break; - default: - break; - } - - snprintf(buf, sizeof(buf), "/%d", mask); - strlcat(b, buf, l); - return b; -} - -static const char * -conf_namemask(char *b, size_t l, const struct conf *c) -{ - strlcpy(b, fmtname(c->c_name), l); - fmtmask(b, l, c->c_family, c->c_rmask); - return b; -} - -const char * -conf_print(char *buf, size_t len, const char *pref, const char *delim, - const struct conf *c) -{ - char ha[128], hb[32], b[5][64]; - int sp; - -#define N(n, v) conf_num(b[n], sizeof(b[n]), (v)) - - switch (c->c_ss.ss_family) { - case 0: - snprintf(ha, sizeof(ha), "*"); - break; - case AF_MAX: - snprintf(ha, sizeof(ha), "%s", SIF_NAME(&c->c_ss)); - break; - default: - sockaddr_snprintf(ha, sizeof(ha), "%a", (const void *)&c->c_ss); - break; - } - - fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask); - fmtport(ha, sizeof(ha), c->c_port); - - sp = *delim == '\t' ? 20 : -1; - hb[0] = '\0'; - if (*delim) - snprintf(buf, len, "%s%*.*s%s%s%s" "%s%s%s%s" - "%s%s" "%s%s%s", - pref, sp, sp, ha, delim, N(0, c->c_proto), delim, - N(1, c->c_family), delim, N(2, c->c_uid), delim, - conf_namemask(hb, sizeof(hb), c), delim, - N(3, c->c_nfail), delim, N(4, c->c_duration)); - else - snprintf(buf, len, "%starget:%s, proto:%s, family:%s, " - "uid:%s, name:%s, nfail:%s, duration:%s", pref, - ha, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid), - conf_namemask(hb, sizeof(hb), c), - N(3, c->c_nfail), N(4, c->c_duration)); - return buf; -} - -/* - * Apply the local config match to the result - */ -static void -conf_apply(struct conf *c, const struct conf *sc) -{ - char buf[BUFSIZ]; - - if (debug) { - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "merge:\t", "", sc)); - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "to:\t", "", c)); - } - memcpy(c->c_name, sc->c_name, CONFNAMESZ); - c->c_uid = sc->c_uid; - c->c_rmask = sc->c_rmask; - c->c_nfail = sc->c_nfail; - c->c_duration = sc->c_duration; - - if (debug) - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "result:\t", "", c)); -} - -/* - * Merge a remote configuration to the result - */ -static void -conf_merge(struct conf *c, const struct conf *sc) -{ - char buf[BUFSIZ]; - - if (debug) { - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "merge:\t", "", sc)); - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "to:\t", "", c)); - } - - if (sc->c_name[0]) - memcpy(c->c_name, sc->c_name, CONFNAMESZ); - if (sc->c_uid != FEQUAL) - c->c_uid = sc->c_uid; - if (sc->c_rmask != FEQUAL) - c->c_lmask = c->c_rmask = sc->c_rmask; - if (sc->c_nfail != FEQUAL) - c->c_nfail = sc->c_nfail; - if (sc->c_duration != FEQUAL) - c->c_duration = sc->c_duration; - if (debug) - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "result:\t", "", c)); -} - -static void -confset_init(struct confset *cs) -{ - cs->cs_c = NULL; - cs->cs_n = 0; - cs->cs_m = 0; -} - -static int -confset_grow(struct confset *cs) -{ - void *tc; - - cs->cs_m += 10; - tc = realloc(cs->cs_c, cs->cs_m * sizeof(*cs->cs_c)); - if (tc == NULL) { - (*lfun)(LOG_ERR, "%s: Can't grow confset (%m)", __func__); - return -1; - } - cs->cs_c = tc; - return 0; -} - -static struct conf * -confset_get(struct confset *cs) -{ - return &cs->cs_c[cs->cs_n]; -} - -static bool -confset_full(const struct confset *cs) -{ - return cs->cs_n == cs->cs_m; -} - -static void -confset_sort(struct confset *cs) -{ - qsort(cs->cs_c, cs->cs_n, sizeof(*cs->cs_c), conf_sort); -} - -static void -confset_add(struct confset *cs) -{ - cs->cs_n++; -} - -static void -confset_free(struct confset *cs) -{ - free(cs->cs_c); - confset_init(cs); -} - -static void -confset_replace(struct confset *dc, struct confset *sc) -{ - struct confset tc; - tc = *dc; - *dc = *sc; - confset_init(sc); - confset_free(&tc); -} - -static void -confset_list(const struct confset *cs, const char *msg, const char *where) -{ - char buf[BUFSIZ]; - - (*lfun)(LOG_DEBUG, "[%s]", msg); - (*lfun)(LOG_DEBUG, "%20.20s\ttype\tproto\towner\tname\tnfail\tduration", - where); - for (size_t i = 0; i < cs->cs_n; i++) - (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), "", "\t", - &cs->cs_c[i])); -} - -/* - * Match a configuration against the given list and apply the function - * to it, returning the matched entry number. - */ -static size_t -confset_match(const struct confset *cs, struct conf *c, - void (*fun)(struct conf *, const struct conf *)) -{ - char buf[BUFSIZ]; - size_t i; - - for (i = 0; i < cs->cs_n; i++) { - 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 (debug) - (*lfun)(LOG_DEBUG, "%s", - conf_print(buf, sizeof(buf), - "found:\t", "", &cs->cs_c[i])); - (*fun)(c, &cs->cs_c[i]); - break; - } - } - return i; -} - -const struct conf * -conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss, - struct conf *cr) -{ - int proto; - socklen_t slen; - struct sockaddr_storage lss; - size_t i; - char buf[BUFSIZ]; - - memset(cr, 0, sizeof(*cr)); - slen = sizeof(lss); - memset(&lss, 0, slen); - if (getsockname(fd, (void *)&lss, &slen) == -1) { - (*lfun)(LOG_ERR, "getsockname failed (%m)"); - return NULL; - } - - slen = sizeof(proto); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) { - (*lfun)(LOG_ERR, "getsockopt failed (%m)"); - return NULL; - } - - if (debug) { - sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&lss); - (*lfun)(LOG_DEBUG, "listening socket: %s", buf); - } - - switch (proto) { - case SOCK_STREAM: - cr->c_proto = IPPROTO_TCP; - break; - case SOCK_DGRAM: - cr->c_proto = IPPROTO_UDP; - break; - default: - (*lfun)(LOG_ERR, "unsupported protocol %d", proto); - return NULL; - } - - switch (lss.ss_family) { - case AF_INET: - cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port); - break; - case AF_INET6: - cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port); - break; - default: - (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family); - return NULL; - } - - cr->c_ss = lss; - cr->c_lmask = FSTAR; - cr->c_uid = (int)uid; - cr->c_family = lss.ss_family; - cr->c_name[0] = '\0'; - cr->c_rmask = FSTAR; - cr->c_nfail = FSTAR; - cr->c_duration = FSTAR; - - if (debug) - (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), - "look:\t", "", cr)); - - /* match the local config */ - i = confset_match(&lconf, cr, conf_apply); - if (i == lconf.cs_n) { - if (debug) - (*lfun)(LOG_DEBUG, "not found"); - return NULL; - } - - conf_addr_set(cr, rss); - /* match the remote config */ - confset_match(&rconf, cr, conf_merge); - /* to apply the mask */ - conf_addr_set(cr, &cr->c_ss); - - return cr; -} - - -void -conf_parse(const char *f) -{ - 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; - - confset_init(&rc); - confset_init(&lc); - cs = &lc; - for (; (line = fparseln(fp, &len, &lineno, NULL, 0)) != NULL; - free(line)) - { - if (!*line) - continue; - if (strcmp(line, "[local]") == 0) { - cs = &lc; - continue; - } - if (strcmp(line, "[remote]") == 0) { - cs = &rc; - continue; - } - - if (confset_full(cs)) { - 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), - cs == &lc) == -1) - continue; - confset_add(cs); - } - - fclose(fp); - confset_sort(&lc); - confset_sort(&rc); - - confset_replace(&rconf, &rc); - confset_replace(&lconf, &lc); - - if (debug) { - confset_list(&lconf, "local", "target"); - confset_list(&rconf, "remote", "source"); - } -} diff --git a/contrib/blacklist/bin/conf.h b/contrib/blacklist/bin/conf.h deleted file mode 100644 index 03f1942e3e3..00000000000 --- a/contrib/blacklist/bin/conf.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $NetBSD: conf.h,v 1.6 2015/01/27 19:40:36 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 _CONF_H -#define _CONF_H - -#include - -struct conf { - struct sockaddr_storage c_ss; - int c_lmask; - int c_port; - int c_proto; - int c_family; - int c_uid; - int c_nfail; - char c_name[128]; - int c_rmask; - int c_duration; -}; - -struct confset { - struct conf *cs_c; - size_t cs_n; - size_t cs_m; -}; - -#define CONFNAMESZ sizeof(((struct conf *)0)->c_name) - -__BEGIN_DECLS -const char *conf_print(char *, size_t, const char *, const char *, - const struct conf *); -void conf_parse(const char *); -const struct conf *conf_find(int, uid_t, const struct sockaddr_storage *, - struct conf *); -__END_DECLS - -#endif /* _CONF_H */ diff --git a/contrib/blacklist/bin/internal.c b/contrib/blacklist/bin/internal.c deleted file mode 100644 index 5c039e4dc5d..00000000000 --- a/contrib/blacklist/bin/internal.c +++ /dev/null @@ -1,48 +0,0 @@ -/* $NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 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 - -#include -__RCSID("$NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $"); - -#include -#include -#include "conf.h" -#include "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/blacklist/bin/internal.h b/contrib/blacklist/bin/internal.h deleted file mode 100644 index 5a40e49fbbd..00000000000 --- a/contrib/blacklist/bin/internal.h +++ /dev/null @@ -1,57 +0,0 @@ -/* $NetBSD: internal.h,v 1.14 2016/04/04 15:52:56 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 _INTERNAL_H -#define _INTERNAL_H - -#ifndef _PATH_BLCONF -#define _PATH_BLCONF "/etc/blacklistd.conf" -#endif -#ifndef _PATH_BLCONTROL -#define _PATH_BLCONTROL "/libexec/blacklistd-helper" -#endif -#ifndef _PATH_BLSTATE -#define _PATH_BLSTATE "/var/db/blacklistd.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 /* _INTERNAL_H */ diff --git a/contrib/blacklist/bin/run.c b/contrib/blacklist/bin/run.c deleted file mode 100644 index e11f8b28e2e..00000000000 --- a/contrib/blacklist/bin/run.c +++ /dev/null @@ -1,157 +0,0 @@ -/* $NetBSD: run.c,v 1.14 2016/04/04 15:52:56 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 - -#include -__RCSID("$NetBSD: run.c,v 1.14 2016/04/04 15:52:56 christos Exp $"); - -#include -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#include "run.h" -#include "conf.h" -#include "internal.h" -#include "support.h" - -extern char **environ; - -static char * -run(const char *cmd, const char *name, ...) -{ - const char *argv[20]; - size_t i, len; - va_list ap; - FILE *fp; - char *line, *res; - - argv[0] = "control"; - argv[1] = cmd; - argv[2] = name; - va_start(ap, name); - for (i = 3; i < __arraycount(argv) && - (argv[i] = va_arg(ap, char *)) != NULL; i++) - continue; - va_end(ap); - - if (debug) { - char buf[2048]; - size_t z; - int r; - - r = snprintf(buf, sizeof(buf), "run %s [", controlprog); - if (r == -1 || (z = (size_t)r) >= sizeof(buf)) - z = sizeof(buf); - for (i = 0; argv[i]; i++) { - r = snprintf(buf + z, sizeof(buf) - z, "%s%s", - argv[i], argv[i + 1] ? " " : ""); - if (r == -1 || (z += (size_t)r) >= sizeof(buf)) - z = sizeof(buf); - } - (*lfun)(LOG_DEBUG, "%s]", buf); - } - - fp = popenve(controlprog, __UNCONST(argv), environ, "r"); - if (fp == NULL) { - (*lfun)(LOG_ERR, "popen %s failed (%m)", controlprog); - return NULL; - } - line = res = NULL; - len = 0; - if (getline(&line, &len, fp) >= 0) - res = line; - pclose(fp); - if (debug) - (*lfun)(LOG_DEBUG, "%s returns %s", cmd, res); - return res; -} - -void -run_flush(const struct conf *c) -{ - free(run("flush", c->c_name, NULL)); -} - -int -run_change(const char *how, const struct conf *c, char *id, size_t len) -{ - const char *prname; - char poname[64], adname[128], maskname[32], *rv; - size_t off; - - switch (c->c_proto) { - case -1: - prname = ""; - break; - case IPPROTO_TCP: - prname = "tcp"; - break; - case IPPROTO_UDP: - prname = "udp"; - break; - default: - (*lfun)(LOG_ERR, "%s: bad protocol %d", __func__, c->c_proto); - return -1; - } - - if (c->c_port != -1) - snprintf(poname, sizeof(poname), "%d", c->c_port); - else - poname[0] = '\0'; - - snprintf(maskname, sizeof(maskname), "%d", c->c_lmask); - sockaddr_snprintf(adname, sizeof(adname), "%a", (const void *)&c->c_ss); - - rv = run(how, c->c_name, prname, adname, maskname, poname, id, NULL); - if (rv == NULL) - return -1; - if (len != 0) { - rv[strcspn(rv, "\n")] = '\0'; - off = strncmp(rv, "OK ", 3) == 0 ? 3 : 0; - strlcpy(id, rv + off, len); - } - free(rv); - return 0; -} diff --git a/contrib/blacklist/bin/run.h b/contrib/blacklist/bin/run.h deleted file mode 100644 index bafc3e55469..00000000000 --- a/contrib/blacklist/bin/run.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $NetBSD: run.h,v 1.5 2015/01/27 19:40:37 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 _RUN_H -#define _RUN_H - -__BEGIN_DECLS -struct conf; -void run_flush(const struct conf *); -struct sockaddr_storage; -int run_change(const char *, const struct conf *, char *, size_t); -__END_DECLS - -#endif /* _RUN_H */ diff --git a/contrib/blacklist/bin/state.c b/contrib/blacklist/bin/state.c deleted file mode 100644 index f2622c82c25..00000000000 --- a/contrib/blacklist/bin/state.c +++ /dev/null @@ -1,235 +0,0 @@ -/* $NetBSD: state.c,v 1.19 2016/09/26 19:43:43 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 - -#include -__RCSID("$NetBSD: state.c,v 1.19 2016/09/26 19:43:43 christos Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bl.h" -#include "internal.h" -#include "conf.h" -#include "support.h" -#include "state.h" - -static HASHINFO openinfo = { - 4096, /* bsize */ - 32, /* ffactor */ - 256, /* nelem */ - 8 * 1024 * 1024,/* cachesize */ - NULL, /* hash() */ - 0 /* lorder */ -}; - -int -state_close(DB *db) -{ - if (db == NULL) - return -1; - if ((*db->close)(db) == -1) { - (*lfun)(LOG_ERR, "%s: can't close db (%m)", __func__); - return -1; - } - return 0; -} - -DB * -state_open(const char *dbname, int flags, mode_t perm) -{ - DB *db; - -#ifdef __APPLE__ - flags &= O_CREAT|O_EXCL|O_EXLOCK|O_NONBLOCK|O_RDONLY| - O_RDWR|O_SHLOCK|O_TRUNC; -#endif - db = dbopen(dbname, flags, perm, DB_HASH, &openinfo); - if (db == NULL) { - if (errno == ENOENT && (flags & O_CREAT) == 0) - return NULL; - (*lfun)(LOG_ERR, "%s: can't open `%s' (%m)", __func__, dbname); - } - return db; -} - -static int -state_sizecheck(const DBT *t) -{ - if (sizeof(struct conf) == t->size) - return 0; - (*lfun)(LOG_ERR, "Key size mismatch %zu != %zu", sizeof(struct conf), - t->size); - return -1; -} - -static void -dumpkey(const struct conf *k) -{ - char buf[10240]; - blhexdump(buf, sizeof(buf), __func__, k, sizeof(*k)); - (*lfun)(LOG_DEBUG, "%s", buf); - (*lfun)(LOG_DEBUG, "%s: %s", __func__, - conf_print(buf, sizeof(buf), "", "", k)); - -} - -int -state_del(DB *db, const struct conf *c) -{ - int rv; - DBT k; - - if (db == NULL) - return -1; - - k.data = __UNCONST(c); - k.size = sizeof(*c); - - switch (rv = (*db->del)(db, &k, 0)) { - case 0: - case 1: - if (debug > 1) { - (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); - (*db->sync)(db, 0); - } - return 0; - default: - (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); - return -1; - } -} - -int -state_get(DB *db, const struct conf *c, struct dbinfo *dbi) -{ - int rv; - DBT k, v; - - if (db == NULL) - return -1; - - k.data = __UNCONST(c); - k.size = sizeof(*c); - - switch (rv = (*db->get)(db, &k, &v, 0)) { - case 0: - case 1: - if (rv) - memset(dbi, 0, sizeof(*dbi)); - else - memcpy(dbi, v.data, sizeof(*dbi)); - if (debug > 1) - (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); - return 0; - default: - (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); - return -1; - } -} - -int -state_put(DB *db, const struct conf *c, const struct dbinfo *dbi) -{ - int rv; - DBT k, v; - - if (db == NULL) - return -1; - - k.data = __UNCONST(c); - k.size = sizeof(*c); - v.data = __UNCONST(dbi); - v.size = sizeof(*dbi); - - switch (rv = (*db->put)(db, &k, &v, 0)) { - case 0: - if (debug > 1) { - (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); - (*db->sync)(db, 0); - } - return 0; - case 1: - errno = EEXIST; - /*FALLTHROUGH*/ - default: - (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); - return -1; - } -} - -int -state_iterate(DB *db, struct conf *c, struct dbinfo *dbi, unsigned int first) -{ - int rv; - DBT k, v; - - if (db == NULL) { - (*lfun)(LOG_ERR, "%s: called with no database file", __func__); - return -1; - } - - first = first ? R_FIRST : R_NEXT; - - switch (rv = (*db->seq)(db, &k, &v, first)) { - case 0: - if (state_sizecheck(&k) == -1) - return -1; - memcpy(c, k.data, sizeof(*c)); - if (debug > 2) - dumpkey(c); - memcpy(dbi, v.data, sizeof(*dbi)); - if (debug > 1) - (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); - return 1; - case 1: - if (debug > 1) - (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv); - return 0; - default: - (*lfun)(LOG_ERR, "%s: failed (%m)", __func__); - return -1; - } -} - -int -state_sync(DB *db) -{ - return (*db->sync)(db, 0); -} diff --git a/contrib/blacklist/bin/state.h b/contrib/blacklist/bin/state.h deleted file mode 100644 index 2e9257006e8..00000000000 --- a/contrib/blacklist/bin/state.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $NetBSD: state.h,v 1.5 2015/01/27 19:40:37 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 _STATE_H -#define _STATE_H - -#ifdef HAVE_DB_185_H -#include -#elif HAVE_DB_H -#include -#else -#error "no db.h" -#endif -#include - -struct dbinfo { - int count; - time_t last; - char id[64]; -}; - -__BEGIN_DECLS -struct sockaddr_storage; -struct conf; - -DB *state_open(const char *, int, mode_t); -int state_close(DB *); -int state_get(DB *, const struct conf *, struct dbinfo *); -int state_put(DB *, const struct conf *, const struct dbinfo *); -int state_del(DB *, const struct conf *); -int state_iterate(DB *, struct conf *, struct dbinfo *, unsigned int); -int state_sync(DB *); -__END_DECLS - -#endif /* _STATE_H */ diff --git a/contrib/blacklist/bin/support.c b/contrib/blacklist/bin/support.c deleted file mode 100644 index 3e14fcbdc68..00000000000 --- a/contrib/blacklist/bin/support.c +++ /dev/null @@ -1,160 +0,0 @@ -/* $NetBSD: support.c,v 1.9 2018/09/18 22:12:19 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 - -#include -__RCSID("$NetBSD: support.c,v 1.9 2018/09/18 22:12:19 christos Exp $"); - -#include -#include -#include -#include -#include -#include -#include - -#include "support.h" - -static __attribute__((__format_arg__(3))) const char * -expandm(char *buf, size_t len, const char *fmt) -{ - char *p; - size_t r; - - if ((p = strstr(fmt, "%m")) == NULL) - return fmt; - - r = (size_t)(p - fmt); - if (r >= len) - return fmt; - - strlcpy(buf, fmt, r + 1); - strlcat(buf, strerror(errno), len); - strlcat(buf, fmt + r + 2, len); - - return buf; -} - -void -vdlog(int level __unused, const char *fmt, va_list ap) -{ - char buf[BUFSIZ]; - -// fprintf(stderr, "%s: ", getprogname()); - vfprintf(stderr, expandm(buf, sizeof(buf), fmt), ap); - fprintf(stderr, "\n"); -} - -void -dlog(int level, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vdlog(level, fmt, ap); - va_end(ap); -} - -const char * -fmttime(char *b, size_t l, time_t t) -{ - struct tm tm; - if (localtime_r(&t, &tm) == NULL) - snprintf(b, l, "*%jd*", (intmax_t)t); - else - strftime(b, l, "%Y/%m/%d %H:%M:%S", &tm); - return b; -} - -const char * -fmtydhms(char *b, size_t l, time_t t) -{ - time_t s, m, h, d, y; - int z; - size_t o; - - s = t % 60; - t /= 60; - - m = t % 60; - t /= 60; - - h = t % 24; - t /= 24; - - d = t % 365; - t /= 365; - - y = t; - - o = 0; -#define APPEND(a) \ - if (a) { \ - z = snprintf(b + o, l - o, "%jd%s", (intmax_t)a, __STRING(a)); \ - if (z == -1) \ - return b; \ - o += (size_t)z; \ - if (o >= l) \ - return b; \ - } - APPEND(y) - APPEND(d) - APPEND(h) - APPEND(m) - APPEND(s) - return b; -} - -ssize_t -blhexdump(char *buf, size_t len, const char *str, const void *b, size_t l) -{ - size_t z, cz; - int r; - const unsigned char *p = b; - const unsigned char *e = p + l; - - r = snprintf(buf, len, "%s: ", str); - if (r == -1) - return -1; - if ((cz = z = (size_t)r) >= len) - cz = len; - - while (p < e) { - r = snprintf(buf + cz, len - cz, "%.2x", *p++); - if (r == -1) - return -1; - if ((cz = (z += (size_t)r)) >= len) - cz = len; - } - return (ssize_t)z; -} diff --git a/contrib/blacklist/bin/support.h b/contrib/blacklist/bin/support.h deleted file mode 100644 index 899649ce831..00000000000 --- a/contrib/blacklist/bin/support.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $NetBSD: support.h,v 1.7 2016/04/04 15:52:56 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 _SUPPORT_H -#define _SUPPORT_H - -__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))); -void dlog(int, const char *, ...) - __attribute__((__format__(__printf__, 2, 3))); -ssize_t blhexdump(char *, size_t, const char *, const void *, size_t); -__END_DECLS - -#endif /* _SUPPORT_H */ diff --git a/contrib/blacklist/diff/ftpd.diff b/contrib/blacklist/diff/ftpd.diff deleted file mode 100644 index d28577f3ef5..00000000000 --- a/contrib/blacklist/diff/ftpd.diff +++ /dev/null @@ -1,91 +0,0 @@ ---- /dev/null 2015-01-23 17:30:40.000000000 -0500 -+++ pfilter.c 2015-01-23 17:12:02.000000000 -0500 -@@ -0,0 +1,24 @@ -+#include -+#include -+ -+#include "pfilter.h" -+ -+static struct blacklist *blstate; -+ -+void -+pfilter_open(void) -+{ -+ if (blstate == NULL) -+ blstate = blacklist_open(); -+} -+ -+void -+pfilter_notify(int what, const char *msg) -+{ -+ pfilter_open(); -+ -+ if (blstate == NULL) -+ return; -+ -+ blacklist_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 -@@ -0,0 +1,2 @@ -+void pfilter_open(void); -+void pfilter_notify(int, const char *); -Index: Makefile -=================================================================== -RCS file: /cvsroot/src/libexec/ftpd/Makefile,v -retrieving revision 1.63 -diff -u -p -u -r1.63 Makefile ---- Makefile 14 Aug 2011 11:46:28 -0000 1.63 -+++ Makefile 23 Jan 2015 22:32:20 -0000 -@@ -11,6 +11,10 @@ LDADD+= -lcrypt -lutil - MAN= ftpd.conf.5 ftpusers.5 ftpd.8 - MLINKS= ftpusers.5 ftpchroot.5 - -+SRCS+= pfilter.c -+LDADD+= -lblacklist -+DPADD+= ${LIBBLACKLIST} -+ - .if defined(NO_INTERNAL_LS) - CPPFLAGS+=-DNO_INTERNAL_LS - .else -Index: ftpd.c -=================================================================== -RCS file: /cvsroot/src/libexec/ftpd/ftpd.c,v -retrieving revision 1.200 -diff -u -p -u -r1.200 ftpd.c ---- ftpd.c 31 Jul 2013 19:50:47 -0000 1.200 -+++ ftpd.c 23 Jan 2015 22:32:20 -0000 -@@ -165,6 +165,8 @@ __RCSID("$NetBSD: ftpd.c,v 1.200 2013/07 - #include - #endif - -+#include "pfilter.h" -+ - #define GLOBAL - #include "extern.h" - #include "pathnames.h" -@@ -471,6 +473,8 @@ main(int argc, char *argv[]) - if (EMPTYSTR(confdir)) - confdir = _DEFAULT_CONFDIR; - -+ pfilter_open(); -+ - if (dowtmp) { - #ifdef SUPPORT_UTMPX - ftpd_initwtmpx(); -@@ -1401,6 +1405,7 @@ do_pass(int pass_checked, int pass_rval, - if (rval) { - reply(530, "%s", rval == 2 ? "Password expired." : - "Login incorrect."); -+ pfilter_notify(1, rval == 2 ? "exppass" : "badpass"); - if (logging) { - syslog(LOG_NOTICE, - "FTP LOGIN FAILED FROM %s", remoteloghost); -@@ -1444,6 +1449,7 @@ do_pass(int pass_checked, int pass_rval, - *remote_ip = 0; - remote_ip[sizeof(remote_ip) - 1] = 0; - if (!auth_hostok(lc, remotehost, remote_ip)) { -+ pfilter_notify(1, "bannedhost"); - syslog(LOG_INFO|LOG_AUTH, - "FTP LOGIN FAILED (HOST) as %s: permission denied.", - pw->pw_name); diff --git a/contrib/blacklist/diff/named.diff b/contrib/blacklist/diff/named.diff deleted file mode 100644 index fcd97ba7ec1..00000000000 --- a/contrib/blacklist/diff/named.diff +++ /dev/null @@ -1,216 +0,0 @@ ---- /dev/null 2015-01-22 01:48:00.000000000 -0500 -+++ dist/bin/named/pfilter.c 2015-01-22 01:35:16.000000000 -0500 -@@ -0,0 +1,42 @@ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "pfilter.h" -+ -+static struct blacklist *blstate; -+ -+void -+pfilter_open(void) -+{ -+ if (blstate == NULL) -+ blstate = blacklist_open(); -+} -+ -+#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) -+ -+void -+pfilter_notify(isc_result_t res, ns_client_t *client, const char *msg) -+{ -+ isc_socket_t *socket; -+ -+ pfilter_open(); -+ -+ if (TCP_CLIENT(client)) -+ socket = client->tcpsocket; -+ else { -+ socket = client->udpsocket; -+ if (!client->peeraddr_valid) -+ return; -+ } -+ if (socket == NULL) -+ return; -+ blacklist_sa_r(blstate, -+ res != ISC_R_SUCCESS, isc_socket_getfd(socket), -+ &client->peeraddr.type.sa, client->peeraddr.length, msg); -+} ---- /dev/null 2015-01-22 01:48:00.000000000 -0500 -+++ dist/bin/named/pfilter.h 2015-01-22 01:16:56.000000000 -0500 -@@ -0,0 +1,2 @@ -+void pfilter_open(void); -+void pfilter_notify(isc_result_t, ns_client_t *, const char *); -Index: bin/named/Makefile -=================================================================== -RCS file: /cvsroot/src/external/bsd/bind/bin/named/Makefile,v -retrieving revision 1.8 -diff -u -u -r1.8 Makefile ---- bin/named/Makefile 31 Dec 2013 20:23:12 -0000 1.8 -+++ bin/named/Makefile 23 Jan 2015 21:37:09 -0000 -@@ -33,7 +33,9 @@ - lwaddr.c lwdclient.c lwderror.c \ - lwdgabn.c lwdgnba.c lwdgrbn.c lwdnoop.c lwresd.c lwsearch.c \ - main.c notify.c query.c server.c sortlist.c statschannel.c \ -- tkeyconf.c tsigconf.c \ -+ pfilter.c tkeyconf.c tsigconf.c \ - update.c xfrout.c zoneconf.c ${SRCS_UNIX} - -+LDADD+=-lblacklist -+DPADD+=${LIBBLACKLIST} - .include -Index: dist/bin/named/client.c -=================================================================== -RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/client.c,v -retrieving revision 1.11 -diff -u -u -r1.11 client.c ---- dist/bin/named/client.c 10 Dec 2014 04:37:51 -0000 1.11 -+++ dist/bin/named/client.c 23 Jan 2015 21:37:09 -0000 -@@ -65,6 +65,8 @@ - #include - #include - -+#include "pfilter.h" -+ - /*** - *** Client - ***/ -@@ -3101,6 +3103,7 @@ - result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL, - acl, default_allow); - -+ pfilter_notify(result, client, opname); - if (result == ISC_R_SUCCESS) - ns_client_log(client, DNS_LOGCATEGORY_SECURITY, - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), -Index: dist/bin/named/main.c -=================================================================== -RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/main.c,v -retrieving revision 1.15 -diff -u -u -r1.15 main.c ---- dist/bin/named/main.c 10 Dec 2014 04:37:51 -0000 1.15 -+++ dist/bin/named/main.c 23 Jan 2015 21:37:09 -0000 -@@ -83,6 +83,9 @@ - #ifdef HAVE_LIBXML2 - #include - #endif -+ -+#include "pfilter.h" -+ - /* - * Include header files for database drivers here. - */ -@@ -1206,6 +1209,8 @@ - - parse_command_line(argc, argv); - -+ pfilter_open(); -+ - /* - * Warn about common configuration error. - */ -Index: dist/bin/named/query.c -=================================================================== -RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/query.c,v -retrieving revision 1.17 -diff -u -u -r1.17 query.c ---- dist/bin/named/query.c 10 Dec 2014 04:37:52 -0000 1.17 -+++ dist/bin/named/query.c 23 Jan 2015 21:37:09 -0000 -@@ -65,6 +65,8 @@ - #include - #include - -+#include "pfilter.h" -+ - #if 0 - /* - * It has been recommended that DNS64 be changed to return excluded -@@ -762,6 +764,8 @@ - } - - result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); -+ if (result != ISC_R_SUCCESS) -+ pfilter_notify(result, client, "validatezonedb"); - if ((options & DNS_GETDB_NOLOG) == 0) { - char msg[NS_CLIENT_ACLMSGSIZE("query")]; - if (result == ISC_R_SUCCESS) { -@@ -1026,6 +1030,8 @@ - result = ns_client_checkaclsilent(client, NULL, - client->view->cacheacl, - ISC_TRUE); -+ if (result == ISC_R_SUCCESS) -+ pfilter_notify(result, client, "cachedb"); - if (result == ISC_R_SUCCESS) { - /* - * We were allowed by the "allow-query-cache" ACL. -Index: dist/bin/named/update.c -=================================================================== -RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/update.c,v -retrieving revision 1.9 -diff -u -u -r1.9 update.c ---- dist/bin/named/update.c 10 Dec 2014 04:37:52 -0000 1.9 -+++ dist/bin/named/update.c 23 Jan 2015 21:37:09 -0000 -@@ -59,6 +59,8 @@ - #include - #include - -+#include "pfilter.h" -+ - /*! \file - * \brief - * This module implements dynamic update as in RFC2136. -@@ -307,6 +309,7 @@ - - result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); - if (result != ISC_R_SUCCESS) { -+ pfilter_notify(result, client, "queryacl"); - dns_name_format(zonename, namebuf, sizeof(namebuf)); - dns_rdataclass_format(client->view->rdclass, classbuf, - sizeof(classbuf)); -@@ -324,6 +327,7 @@ - sizeof(classbuf)); - - result = DNS_R_REFUSED; -+ pfilter_notify(result, client, "updateacl"); - ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, - NS_LOGMODULE_UPDATE, ISC_LOG_INFO, - "update '%s/%s' denied", namebuf, classbuf); -@@ -362,6 +366,7 @@ - msg = "disabled"; - } else { - result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE); -+ pfilter_notify(result, client, "updateacl"); - if (result == ISC_R_SUCCESS) { - level = ISC_LOG_DEBUG(3); - msg = "approved"; -Index: dist/bin/named/xfrout.c -=================================================================== -RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/xfrout.c,v -retrieving revision 1.7 -diff -u -u -r1.7 xfrout.c ---- dist/bin/named/xfrout.c 10 Dec 2014 04:37:52 -0000 1.7 -+++ dist/bin/named/xfrout.c 23 Jan 2015 21:37:09 -0000 -@@ -54,6 +54,8 @@ - #include - #include - -+#include "pfilter.h" -+ - /*! \file - * \brief - * Outgoing AXFR and IXFR. -@@ -822,6 +824,7 @@ - &client->peeraddr, - &db); - -+ pfilter_notify(result, client, "zonexfr"); - if (result == ISC_R_NOPERM) { - char _buf1[DNS_NAME_FORMATSIZE]; - char _buf2[DNS_RDATACLASS_FORMATSIZE]; diff --git a/contrib/blacklist/diff/proftpd.diff b/contrib/blacklist/diff/proftpd.diff deleted file mode 100644 index 455b7cd60c6..00000000000 --- a/contrib/blacklist/diff/proftpd.diff +++ /dev/null @@ -1,124 +0,0 @@ ---- 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 -+OBJS+= pfilter.o -+BUILD_OBJS+= src/pfilter.o ---- /dev/null 2016-01-22 17:30:55.000000000 -0500 -+++ include/pfilter.h 2016-01-22 16:18:33.000000000 -0500 -@@ -0,0 +1,3 @@ -+ -+void pfilter_notify(int); -+void pfilter_init(void); ---- modules/mod_auth.c.orig 2015-05-27 20:25:54.000000000 -0400 -+++ modules/mod_auth.c 2016-01-22 16:21:06.000000000 -0500 -@@ -30,6 +30,7 @@ - - #include "conf.h" - #include "privs.h" -+#include "pfilter.h" - - extern pid_t mpid; - -@@ -84,6 +85,8 @@ - _("Login timeout (%d %s): closing control connection"), TimeoutLogin, - TimeoutLogin != 1 ? "seconds" : "second"); - -+ pfilter_notify(1); -+ - /* It's possible that any listeners of this event might terminate the - * session process themselves (e.g. mod_ban). So write out that the - * TimeoutLogin has been exceeded to the log here, in addition to the -@@ -913,6 +916,7 @@ - pr_memscrub(pass, strlen(pass)); - } - -+ pfilter_notify(1); - pr_log_auth(PR_LOG_NOTICE, "SECURITY VIOLATION: Root login attempted"); - return 0; - } -@@ -1726,6 +1730,7 @@ - return 1; - - auth_failure: -+ pfilter_notify(1); - if (pass) - pr_memscrub(pass, strlen(pass)); - session.user = session.group = NULL; ---- src/main.c.orig 2016-01-22 17:36:43.000000000 -0500 -+++ src/main.c 2016-01-22 17:37:58.000000000 -0500 -@@ -49,6 +49,7 @@ - #endif - - #include "privs.h" -+#include "pfilter.h" - - int (*cmd_auth_chk)(cmd_rec *); - void (*cmd_handler)(server_rec *, conn_t *); -@@ -1050,6 +1051,7 @@ - pid_t pid; - sigset_t sig_set; - -+ pfilter_init(); - if (!nofork) { - - /* A race condition exists on heavily loaded servers where the parent -@@ -1169,7 +1171,8 @@ - - /* Reseed pseudo-randoms */ - srand((unsigned int) (time(NULL) * getpid())); -- -+#else -+ pfilter_init(); - #endif /* PR_DEVEL_NO_FORK */ - - /* Child is running here */ ---- /dev/null 2016-01-22 17:30:55.000000000 -0500 -+++ src/pfilter.c 2016-01-22 16:37:55.000000000 -0500 -@@ -0,0 +1,41 @@ -+#include "pfilter.h" -+#include "conf.h" -+#include "privs.h" -+#ifdef HAVE_BLACKLIST -+#include -+#endif -+ -+static struct blacklist *blstate; -+ -+void -+pfilter_init(void) -+{ -+#ifdef HAVE_BLACKLIST -+ if (blstate == NULL) -+ blstate = blacklist_open(); -+#endif -+} -+ -+void -+pfilter_notify(int a) -+{ -+#ifdef HAVE_BLACKLIST -+ conn_t *c = session.c; -+ int fd; -+ -+ if (c == NULL) -+ return; -+ if (c->rfd != -1) -+ fd = c->rfd; -+ else if (c->wfd != -1) -+ fd = c->wfd; -+ else -+ return; -+ -+ if (blstate == NULL) -+ pfilter_init(); -+ if (blstate == NULL) -+ return; -+ (void)blacklist_r(blstate, a, fd, "proftpd"); -+#endif -+} diff --git a/contrib/blacklist/diff/ssh.diff b/contrib/blacklist/diff/ssh.diff deleted file mode 100644 index 9427fc8ddb3..00000000000 --- a/contrib/blacklist/diff/ssh.diff +++ /dev/null @@ -1,150 +0,0 @@ ---- /dev/null 2015-01-22 23:10:33.000000000 -0500 -+++ dist/pfilter.c 2015-01-22 23:46:03.000000000 -0500 -@@ -0,0 +1,32 @@ -+#include "namespace.h" -+#include "includes.h" -+#include "ssh.h" -+#include "packet.h" -+#include "log.h" -+#include "pfilter.h" -+#include -+ -+static struct blacklist *blstate; -+ -+void -+pfilter_init(void) -+{ -+ blstate = blacklist_open(); -+} -+ -+void -+pfilter_notify(int a) -+{ -+ int fd; -+ if (blstate == NULL) -+ pfilter_init(); -+ if (blstate == NULL) -+ return; -+ // XXX: 3? -+ fd = packet_connection_is_on_socket() ? packet_get_connection_in() : 3; -+ (void)blacklist_r(blstate, a, fd, "ssh"); -+ if (a == 0) { -+ blacklist_close(blstate); -+ blstate = NULL; -+ } -+} ---- /dev/null 2015-01-20 21:14:44.000000000 -0500 -+++ dist/pfilter.h 2015-01-20 20:16:20.000000000 -0500 -@@ -0,0 +1,3 @@ -+ -+void pfilter_notify(int); -+void pfilter_init(void); -Index: bin/sshd/Makefile -=================================================================== -RCS file: /cvsroot/src/crypto/external/bsd/openssh/bin/sshd/Makefile,v -retrieving revision 1.10 -diff -u -u -r1.10 Makefile ---- bin/sshd/Makefile 19 Oct 2014 16:30:58 -0000 1.10 -+++ bin/sshd/Makefile 22 Jan 2015 21:39:21 -0000 -@@ -15,7 +15,7 @@ - auth2-none.c auth2-passwd.c auth2-pubkey.c \ - monitor_mm.c monitor.c monitor_wrap.c \ - kexdhs.c kexgexs.c kexecdhs.c sftp-server.c sftp-common.c \ -- roaming_common.c roaming_serv.c sandbox-rlimit.c -+ roaming_common.c roaming_serv.c sandbox-rlimit.c pfilter.c - - COPTS.auth-options.c= -Wno-pointer-sign - COPTS.ldapauth.c= -Wno-format-nonliteral # XXX: should fix -@@ -68,3 +68,6 @@ - - LDADD+= -lwrap - DPADD+= ${LIBWRAP} -+ -+LDADD+= -lblacklist -+DPADD+= ${LIBBLACKLIST} -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 -@@ -103,6 +103,7 @@ - #include "ssh-gss.h" - #endif - #include "monitor_wrap.h" -+#include "pfilter.h" - - extern ServerOptions options; - extern Buffer loginmsg; -@@ -526,6 +527,7 @@ - ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, &buffer); - else - ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer); -+ pfilter_notify(1); - buffer_free(&buffer); - pthread_exit(NULL); - -@@ -804,6 +806,7 @@ - free(msg); - return (0); - } -+ pfilter_notify(1); - error("PAM: %s for %s%.100s from %.100s", msg, - sshpam_authctxt->valid ? "" : "illegal user ", - sshpam_authctxt->user, -diff -ru openssh-7.7p1/auth2.c dist/auth2.c ---- openssh-7.7p1/auth2.c 2018-04-02 01:38:28.000000000 -0400 -+++ dist/auth2.c 2018-05-23 11:57:31.022197317 -0400 -@@ -51,6 +51,7 @@ - #include "dispatch.h" - #include "pathnames.h" - #include "buffer.h" -+#include "pfilter.h" - - #ifdef GSSAPI - #include "ssh-gss.h" -@@ -242,6 +243,7 @@ - } else { - /* Invalid user, fake password information */ - authctxt->pw = fakepw(); -+ pfilter_notify(1); - #ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_INVALID_USER)); - #endif -Only in dist: pfilter.c -Only in dist: pfilter.h -diff -ru openssh-7.7p1/sshd.c dist/sshd.c ---- openssh-7.7p1/sshd.c 2018-04-02 01:38:28.000000000 -0400 -+++ dist/sshd.c 2018-05-23 11:59:39.573197347 -0400 -@@ -122,6 +122,7 @@ - #include "auth-options.h" - #include "version.h" - #include "ssherr.h" -+#include "pfilter.h" - - /* Re-exec fds */ - #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) -@@ -346,6 +347,7 @@ - static void - grace_alarm_handler(int sig) - { -+ pfilter_notify(1); - if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0) - kill(pmonitor->m_pid, SIGALRM); - -@@ -1835,6 +1837,8 @@ - if (test_flag) - exit(0); - -+ pfilter_init(); -+ - /* - * Clear out any supplemental groups we may have inherited. This - * prevents inadvertent creation of files with bad modes (in the -@@ -2280,6 +2284,9 @@ - { - struct ssh *ssh = active_state; /* XXX */ - -+ if (i == 255) -+ pfilter_notify(1); -+ - if (the_authctxt) { - do_cleanup(ssh, the_authctxt); - if (use_privsep && privsep_is_preauth && diff --git a/contrib/blacklist/etc/Makefile b/contrib/blacklist/etc/Makefile deleted file mode 100644 index 669528ddca8..00000000000 --- a/contrib/blacklist/etc/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $NetBSD: Makefile,v 1.3 2015/01/26 00:18:40 christos Exp $ - -SUBDIR=rc.d - -FILESDIR= /usr/share/examples/blacklist -FILESMODE= 644 -FILES= blacklistd.conf npf.conf - -.include -.include diff --git a/contrib/blacklist/etc/blacklistd.conf b/contrib/blacklist/etc/blacklistd.conf deleted file mode 100644 index f061b004ad3..00000000000 --- a/contrib/blacklist/etc/blacklistd.conf +++ /dev/null @@ -1,14 +0,0 @@ -# Blacklist rule -# adr/mask:port type proto owner name nfail disable -[local] -ssh stream * * * 3 6h -ftp stream * * * 3 6h -domain * * named * 3 12h -#6161 stream tcp6 christos * 2 10m -* * * * * 3 60 - -# adr/mask:port type proto owner name nfail disable -[remote] -#129.168.0.0/16 * * * = * * -#6161 = = = =/24 = = -#* stream tcp * = = = diff --git a/contrib/blacklist/etc/npf.conf b/contrib/blacklist/etc/npf.conf deleted file mode 100644 index 42d56044ad6..00000000000 --- a/contrib/blacklist/etc/npf.conf +++ /dev/null @@ -1,15 +0,0 @@ -# Transparent firewall example for blacklistd - -$ext_if = "bnx0" - -set bpf.jit on; -alg "icmp" - -group "external" on $ext_if { - ruleset "blacklistd" - pass final all -} - -group default { - pass final all -} diff --git a/contrib/blacklist/etc/rc.d/Makefile b/contrib/blacklist/etc/rc.d/Makefile deleted file mode 100644 index e863d0853a0..00000000000 --- a/contrib/blacklist/etc/rc.d/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $ - -SCRIPTS=blacklistd -SCRIPTSDIR=/etc/rc.d - -.include diff --git a/contrib/blacklist/etc/rc.d/blacklistd b/contrib/blacklist/etc/rc.d/blacklistd deleted file mode 100644 index 278a6742e63..00000000000 --- a/contrib/blacklist/etc/rc.d/blacklistd +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -# -# $NetBSD: blacklistd,v 1.2 2016/10/17 22:47:16 christos Exp $ -# - -# PROVIDE: blacklistd -# REQUIRE: npf -# BEFORE: SERVERS - -$_rc_subr_loaded . /etc/rc.subr - -name="blacklistd" -rcvar=$name -command="/sbin/${name}" -pidfile="/var/run/${name}.pid" -required_files="/etc/${name}.conf" -start_precmd="${name}_precmd" -extra_commands="reload" - -_sockfile="/var/run/${name}.sockets" -_sockname="blacklistd.sock" - -blacklistd_precmd() -{ - # Create default list of blacklistd 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. - # - for _lr in $(rcorder -k chrootdir /etc/rc.d/*); do - ( - _l=${_lr##*/} - load_rc_config ${_l} - eval _ldir=\$${_l}_chrootdir - if checkyesno $_l && [ -n "$_ldir" ]; then - echo "${_ldir}/var/run/${_sockname}" >> $_sockfile - fi - ) - done - - # If other sockets have been provided, change run_rc_command()'s - # internal copy of $blacklistd_flags to force use of specific - # blacklistd sockets. - # - if [ -s $_sockfile ]; then - echo "/var/run/${_sockname}" >> $_sockfile - rc_flags="-P $_sockfile $rc_flags" - fi - - return 0 -} - -load_rc_config $name -run_rc_command "$1" diff --git a/contrib/blacklist/include/Makefile b/contrib/blacklist/include/Makefile deleted file mode 100644 index 6854907be25..00000000000 --- a/contrib/blacklist/include/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2015/01/21 16:16:00 christos Exp $ - -# Doing a make includes builds /usr/include - -NOOBJ= # defined - -INCS= blacklist.h -INCSDIR= /usr/include - -.include diff --git a/contrib/blacklist/include/bl.h b/contrib/blacklist/include/bl.h deleted file mode 100644 index 8f366de912f..00000000000 --- a/contrib/blacklist/include/bl.h +++ /dev/null @@ -1,78 +0,0 @@ -/* $NetBSD: bl.h,v 1.13 2016/03/11 17:16:40 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 _BL_H -#define _BL_H - -#include -#include -#include -#include -#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 - -#ifndef _PATH_BLSOCK -#define _PATH_BLSOCK "/var/run/blacklistd.sock" -#endif - -__BEGIN_DECLS - -typedef struct blacklist *bl_t; - -bl_t bl_create(bool, const char *, void (*)(int, 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 /* _BL_H */ diff --git a/contrib/blacklist/include/blacklist.h b/contrib/blacklist/include/blacklist.h deleted file mode 100644 index 2f5c8ba0986..00000000000 --- a/contrib/blacklist/include/blacklist.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $NetBSD: blacklist.h,v 1.3 2015/01/23 18:48:56 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 _BLACKLIST_H -#define _BLACKLIST_H - -#include - -__BEGIN_DECLS -struct blacklist *blacklist_open(void); -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 - -/* action values for user applications */ -#define BLACKLIST_API_ENUM 1 -enum { - BLACKLIST_AUTH_OK = 0, - BLACKLIST_AUTH_FAIL, - BLACKLIST_ABUSIVE_BEHAVIOR, - BLACKLIST_BAD_USER -}; - -#endif /* _BLACKLIST_H */ diff --git a/contrib/blacklist/lib/Makefile b/contrib/blacklist/lib/Makefile deleted file mode 100644 index 4f1ab7717a9..00000000000 --- a/contrib/blacklist/lib/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# $NetBSD: Makefile,v 1.7 2019/03/08 20:40:05 christos Exp $ - -.include - -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 - -.include diff --git a/contrib/blacklist/lib/bl.c b/contrib/blacklist/lib/bl.c deleted file mode 100644 index a3aa4ef1f9f..00000000000 --- a/contrib/blacklist/lib/bl.c +++ /dev/null @@ -1,533 +0,0 @@ -/* $NetBSD: bl.c,v 1.28 2016/07/29 17:13:09 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 - -#include -__RCSID("$NetBSD: bl.c,v 1.28 2016/07/29 17:13:09 christos Exp $"); - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef _REENTRANT -#include -#endif - -#include "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; - void (*b_fun)(int, 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(void (*fun)(int, const char *, va_list), int level, - const char *fmt, ...) -{ - va_list ap; - int serrno = errno; - - va_start(ap, fmt); - (*fun)(level, 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->b_fun, 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->b_fun, 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->b_fun, 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->b_fun, 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->b_fun, 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 sc_euid -#define CRED_SC_GID 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 uid -#define CRED_SC_GID gid -#define CRED_MESSAGE SCM_CREDENTIALS -#define CRED_SIZE sizeof(struct ucred) -#define CRED_TYPE struct ucred -#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->b_fun, 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, const char *, va_list)) -{ - bl_t b = calloc(1, sizeof(*b)); - if (b == NULL) - goto out; - b->b_fun = fun == NULL ? vsyslog : fun; - 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; -out: - free(b); - bl_log(fun, LOG_ERR, "%s: malloc failed (%s)", __func__, - strerror(errno)); - return NULL; -} - -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->b_fun, 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->b_fun, 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->b_fun, 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; - CRED_TYPE sc; - } ua; - struct cmsghdr *cmsg; - CRED_TYPE *sc; - 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) + 100; - - rlen = recvmsg(b->b_fd, &msg, 0); - if (rlen == -1) { - bl_log(b->b_fun, 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, - "%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))) { - bl_log(b->b_fun, LOG_ERR, - "%s: unexpected cmsg_len %d != %zu", - __func__, cmsg->cmsg_len, - CMSG_LEN(2 * sizeof(int))); - 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 = sc->CRED_SC_UID; - bi->bi_gid = sc->CRED_SC_GID; - got |= GOT_CRED; - break; -#endif - default: - bl_log(b->b_fun, LOG_ERR, - "%s: unexpected cmsg_type %d", - __func__, cmsg->cmsg_type); - continue; - } - - } - - if (got != (GOT_CRED|GOT_FD)) { - bl_log(b->b_fun, 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->b_fun, 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); - 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 - 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); - return bi; -} diff --git a/contrib/blacklist/lib/blacklist.c b/contrib/blacklist/lib/blacklist.c deleted file mode 100644 index ba376c3daf0..00000000000 --- a/contrib/blacklist/lib/blacklist.c +++ /dev/null @@ -1,108 +0,0 @@ -/* $NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 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 - -#include -__RCSID("$NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $"); - -#include -#include - -#include -#include -#include -#include -#include - -int -blacklist_sa(int action, int rfd, const struct sockaddr *sa, socklen_t salen, - const char *msg) -{ - struct blacklist *bl; - int rv; - if ((bl = blacklist_open()) == NULL) - return -1; - rv = blacklist_sa_r(bl, action, rfd, sa, salen, msg); - blacklist_close(bl); - return rv; -} - -int -blacklist_sa_r(struct blacklist *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 BLACKLIST_AUTH_FAIL: - internal_action = BL_ADD; - break; - case BLACKLIST_AUTH_OK: - internal_action = BL_DELETE; - break; - case BLACKLIST_ABUSIVE_BEHAVIOR: - internal_action = BL_ABUSE; - break; - case BLACKLIST_BAD_USER: - internal_action = BL_BADUSER; - break; - default: - internal_action = BL_INVALID; - break; - } - return bl_send(bl, internal_action, rfd, sa, slen, msg); -} - -int -blacklist(int action, int rfd, const char *msg) -{ - return blacklist_sa(action, rfd, NULL, 0, msg); -} - -int -blacklist_r(struct blacklist *bl, int action, int rfd, const char *msg) -{ - return blacklist_sa_r(bl, action, rfd, NULL, 0, msg); -} - -struct blacklist * -blacklist_open(void) { - return bl_create(false, NULL, vsyslog); -} - -void -blacklist_close(struct blacklist *bl) -{ - bl_destroy(bl); -} diff --git a/contrib/blacklist/lib/libblacklist.3 b/contrib/blacklist/lib/libblacklist.3 deleted file mode 100644 index aaf809469e6..00000000000 --- a/contrib/blacklist/lib/libblacklist.3 +++ /dev/null @@ -1,157 +0,0 @@ -.\" $NetBSD: libblacklist.3,v 1.8 2017/10/22 10:31:57 abhinav 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 May 5, 2017 -.Dt LIBBLACKLIST 3 -.Os -.Sh NAME -.Nm blacklist_open , -.Nm blacklist_close , -.Nm blacklist_r , -.Nm blacklist , -.Nm blacklist_sa , -.Nm blacklist_sa_r -.Nd Blacklistd notification library -.Sh LIBRARY -.Lb libblacklist -.Sh SYNOPSIS -.In blacklist.h -.Ft struct blacklist * -.Fn blacklist_open "void" -.Ft void -.Fn blacklist_close "struct blacklist *cookie" -.Ft int -.Fn blacklist "int action" "int fd" "const char *msg" -.Ft int -.Fn blacklist_r "struct blacklist *cookie" "int action" "int fd" "const char *msg" -.Ft int -.Fn blacklist_sa "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" -.Ft int -.Fn blacklist_sa_r "struct blacklist *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 blacklistd 8 -about successful and failed remote connections so that blacklistd can -block or release port access to prevent Denial of Service attacks. -.Pp -The function -.Fn blacklist_open -creates the necessary state to communicate with -.Xr blacklistd 8 -and returns a pointer to it, or -.Dv NULL -on failure. -.Pp -The -.Fn blacklist_close -function frees all memory and resources used. -.Pp -The -.Fn blacklist -function sends a message to -.Xr blacklistd 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 ".Va BLACKLIST_ABUSIVE_BEHAVIOR" -.It Va BLACKLIST_AUTH_FAIL -There was an unsuccessful authentication attempt. -.It Va BLACKLIST_AUTH_OK -A user successfully authenticated. -.It Va 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 -The sending daemon has determined the username -presented for authentication is invalid. The -.Xr blacklistd 8 -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 -support is not currently available.) -.El -.Pp -The -.Fn blacklist_r -function is more efficient because it keeps the blacklist state around. -.Pp -The -.Fn blacklist_sa -and -.Fn blacklist_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 -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 blacklist_open -returns a cookie on success and -.Dv NULL -on failure setting -.Dv errno -to an appropriate value. -.Pp -The functions -.Fn blacklist , -.Fn blacklist_sa , -and -.Fn blacklist_sa_r -return -.Dv 0 -on success and -.Dv \-1 -on failure setting -.Dv errno -to an appropriate value. -.Sh SEE ALSO -.Xr blacklistd.conf 5 , -.Xr blacklistd 8 -.Sh AUTHORS -.An Christos Zoulas diff --git a/contrib/blacklist/lib/shlib_version b/contrib/blacklist/lib/shlib_version deleted file mode 100644 index 97c9f92d6b8..00000000000 --- a/contrib/blacklist/lib/shlib_version +++ /dev/null @@ -1,2 +0,0 @@ -major=0 -minor=0 diff --git a/contrib/blacklist/libexec/Makefile b/contrib/blacklist/libexec/Makefile deleted file mode 100644 index 6537080bf46..00000000000 --- a/contrib/blacklist/libexec/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $ - -SCRIPTS= blacklistd-helper -SCRIPTSDIR= /libexec - -.include diff --git a/contrib/blacklist/libexec/blacklistd-helper b/contrib/blacklist/libexec/blacklistd-helper deleted file mode 100644 index fa53c8c8493..00000000000 --- a/contrib/blacklist/libexec/blacklistd-helper +++ /dev/null @@ -1,272 +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 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 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 "" || \ - echo "block in quick $proto from 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 - /sbin/pfctl -a "$anchor" -F rules - done - echo OK - ;; - esac - ;; -*) - echo "$0: Unknown command '$1'" 1>&2 - exit 1 - ;; -esac diff --git a/contrib/blacklist/port/Makefile.am b/contrib/blacklist/port/Makefile.am deleted file mode 100644 index 43bf6c94b42..00000000000 --- a/contrib/blacklist/port/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -# -ACLOCAL_AMFLAGS = -I m4 -lib_LTLIBRARIES = libblacklist.la -include_HEADERS = ../include/blacklist.h - -bin_PROGRAMS = blacklistd blacklistctl srvtest cltest - -VPATH = ../bin:../lib:../test:../include - -AM_CPPFLAGS = -I../include -DDOT="." -AM_CFLAGS = @WARNINGS@ - -libblacklist_la_SOURCES = bl.c blacklist.c -libblacklist_la_LDFLAGS = -no-undefined -version-info 0:0:0 -libblacklist_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 -srvtest_SOURCES = srvtest.c ${SRCS} -srvtest_LDADD = libblacklist.la -cltest_SOURCES = cltest.c ${SRCS} -cltest_LDADD = libblacklist.la diff --git a/contrib/blacklist/port/_strtoi.h b/contrib/blacklist/port/_strtoi.h deleted file mode 100644 index 4b2b4e80f0d..00000000000 --- a/contrib/blacklist/port/_strtoi.h +++ /dev/null @@ -1,93 +0,0 @@ -/* $NetBSD: _strtoi.h,v 1.1 2015/01/22 02:15:59 christos Exp $ */ - -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * 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. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * Original version ID: - * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp - * - * Created by Kamil Rytarowski, based on ID: - * NetBSD: src/common/lib/libc/stdlib/_strtoul.h,v 1.7 2013/05/17 12:55:56 joerg Exp - */ - -/* - * function template for strtoi and strtou - * - * parameters: - * _FUNCNAME : function name - * __TYPE : return and range limits type - * __WRAPPED : wrapped function, strtoimax or strtoumax - */ - -__TYPE -_FUNCNAME(const char * __restrict nptr, char ** __restrict endptr, int base, - __TYPE lo, __TYPE hi, int * rstatus) -{ - int serrno; - __TYPE im; - char *ep; - int rep; - - /* endptr may be NULL */ - - if (endptr == NULL) - endptr = &ep; - - if (rstatus == NULL) - rstatus = &rep; - - serrno = errno; - errno = 0; - - im = __WRAPPED(nptr, endptr, base); - - *rstatus = errno; - errno = serrno; - - if (*rstatus == 0) { - /* No digits were found */ - if (nptr == *endptr) - *rstatus = ECANCELED; - /* There are further characters after number */ - else if (**endptr != '\0') - *rstatus = ENOTSUP; - } - - if (im < lo) { - if (*rstatus == 0) - *rstatus = ERANGE; - return lo; - } - if (im > hi) { - if (*rstatus == 0) - *rstatus = ERANGE; - return hi; - } - - return im; -} diff --git a/contrib/blacklist/port/clock_gettime.c b/contrib/blacklist/port/clock_gettime.c deleted file mode 100644 index 284bd817690..00000000000 --- a/contrib/blacklist/port/clock_gettime.c +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -int -clock_gettime(int clock __unused, struct timespec *ts) -{ - struct timeval tv; - if (gettimeofday(&tv, NULL) == -1) - return -1; - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; - return 0; -} diff --git a/contrib/blacklist/port/config.h b/contrib/blacklist/port/config.h deleted file mode 100644 index 27f32636de0..00000000000 --- a/contrib/blacklist/port/config.h +++ /dev/null @@ -1,3 +0,0 @@ -#if defined(__FreeBSD__) -#include "port.h" -#endif diff --git a/contrib/blacklist/port/configure.ac b/contrib/blacklist/port/configure.ac deleted file mode 100644 index eef8065f060..00000000000 --- a/contrib/blacklist/port/configure.ac +++ /dev/null @@ -1,91 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -AC_INIT([blacklistd],[0.1],[christos@netbsd.com]) -AM_INIT_AUTOMAKE([subdir-objects foreign]) -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_MACRO_DIR([m4]) - -AC_SUBST(WARNINGS) - -dnl Checks for programs. -AC_PROG_CC_STDC -AC_USE_SYSTEM_EXTENSIONS -AM_PROG_CC_C_O -AC_C_BIGENDIAN -AC_PROG_INSTALL -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_LIB(rt, clock_gettime) -AC_CHECK_LIB(db, __db185_open) -AC_CHECK_LIB(util, pidfile) -AC_CHECK_LIB(util, sockaddr_snprintf) - -AH_BOTTOM([ -#ifndef __NetBSD__ -#include "port.h" -#endif -]) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_OFF_T -AC_TYPE_SIZE_T -AC_SYS_LARGEFILE -AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [#include ]) - -AC_TYPE_PID_T -AC_TYPE_UINT8_T -AC_TYPE_UINT16_T -AC_TYPE_UINT32_T -AC_TYPE_INT32_T -AC_TYPE_UINT64_T -AC_TYPE_INT64_T -AC_TYPE_INTPTR_T -AC_TYPE_UINTPTR_T - -AC_MSG_CHECKING(for gcc compiler warnings) -AC_ARG_ENABLE(warnings, -[ --disable-warnings disable compiler warnings], -[if test "${enableval}" = no -o "$GCC" = no; then - AC_MSG_RESULT(no) - WARNINGS= -else - AC_MSG_RESULT(yes) - WARNINGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ - -Wmissing-declarations -Wredundant-decls -Wnested-externs \ - -Wsign-compare -Wreturn-type -Wswitch -Wshadow \ - -Wcast-qual -Wwrite-strings -Wextra -Wunused-parameter -Wformat=2" -fi], [ -if test "$GCC" = yes; then - AC_MSG_RESULT(yes) - WARNINGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ - -Wmissing-declarations -Wredundant-decls -Wnested-externs \ - -Wsign-compare -Wreturn-type -Wswitch -Wshadow \ - -Wcast-qual -Wwrite-strings -Wextra -Wunused-parameter -Wformat=2" -else - WARNINGS= - AC_MSG_RESULT(no) -fi]) - -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) - -dnl See if we are cross-compiling -AM_CONDITIONAL(IS_CROSS_COMPILE, test "$cross_compiling" = yes) - -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/contrib/blacklist/port/fgetln.c b/contrib/blacklist/port/fgetln.c deleted file mode 100644 index a41a383a665..00000000000 --- a/contrib/blacklist/port/fgetln.c +++ /dev/null @@ -1,106 +0,0 @@ -/* $NetBSD: fgetln.c,v 1.1 2015/01/22 03:48:07 christos Exp $ */ - -/*- - * Copyright (c) 1998 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 - -#if !HAVE_FGETLN -#include -#ifndef HAVE_NBTOOL_CONFIG_H -/* These headers are required, but included from nbtool_config.h */ -#include -#include -#include -#include -#endif - -char * -fgetln(FILE *fp, size_t *len) -{ - static char *buf = NULL; - static size_t bufsiz = 0; - char *ptr; - - - if (buf == NULL) { - bufsiz = BUFSIZ; - if ((buf = malloc(bufsiz)) == NULL) - return NULL; - } - - if (fgets(buf, bufsiz, fp) == NULL) - return NULL; - - *len = 0; - while ((ptr = strchr(&buf[*len], '\n')) == NULL) { - size_t nbufsiz = bufsiz + BUFSIZ; - char *nbuf = realloc(buf, nbufsiz); - - if (nbuf == NULL) { - int oerrno = errno; - free(buf); - errno = oerrno; - buf = NULL; - return NULL; - } else - buf = nbuf; - - if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) { - buf[bufsiz] = '\0'; - *len = strlen(buf); - return buf; - } - - *len = bufsiz; - bufsiz = nbufsiz; - } - - *len = (ptr - buf) + 1; - return buf; -} - -#endif - -#ifdef TEST -int -main(int argc, char *argv[]) -{ - char *p; - size_t len; - - while ((p = fgetln(stdin, &len)) != NULL) { - (void)printf("%zu %s", len, p); - free(p); - } - return 0; -} -#endif diff --git a/contrib/blacklist/port/fparseln.c b/contrib/blacklist/port/fparseln.c deleted file mode 100644 index 5bfae54b9a9..00000000000 --- a/contrib/blacklist/port/fparseln.c +++ /dev/null @@ -1,236 +0,0 @@ -/* $NetBSD: fparseln.c,v 1.1 2015/01/22 03:48:07 christos Exp $ */ - -/* - * Copyright (c) 1997 Christos Zoulas. All rights reserved. - * - * 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 ``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 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 - -#include -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: fparseln.c,v 1.1 2015/01/22 03:48:07 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include - -#if ! HAVE_FPARSELN || BROKEN_FPARSELN - -#define FLOCKFILE(fp) -#define FUNLOCKFILE(fp) - -#if defined(_REENTRANT) && !HAVE_NBTOOL_CONFIG_H -#define __fgetln(f, l) __fgetstr(f, l, '\n') -#else -#define __fgetln(f, l) fgetln(f, l) -#endif - -static int isescaped(const char *, const char *, int); - -/* isescaped(): - * Return true if the character in *p that belongs to a string - * that starts in *sp, is escaped by the escape character esc. - */ -static int -isescaped(const char *sp, const char *p, int esc) -{ - const char *cp; - size_t ne; - - /* No escape character */ - if (esc == '\0') - return 0; - - /* Count the number of escape characters that precede ours */ - for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++) - continue; - - /* Return true if odd number of escape characters */ - return (ne & 1) != 0; -} - - -/* fparseln(): - * Read a line from a file parsing continuations ending in \ - * and eliminating trailing newlines, or comments starting with - * the comment char. - */ -char * -fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags) -{ - static const char dstr[3] = { '\\', '\\', '#' }; - - size_t s, len; - char *buf; - char *ptr, *cp; - int cnt; - char esc, con, nl, com; - - len = 0; - buf = NULL; - cnt = 1; - - if (str == NULL) - str = dstr; - - esc = str[0]; - con = str[1]; - com = str[2]; - /* - * XXX: it would be cool to be able to specify the newline character, - * but unfortunately, fgetln does not let us - */ - nl = '\n'; - - FLOCKFILE(fp); - - while (cnt) { - cnt = 0; - - if (lineno) - (*lineno)++; - - if ((ptr = __fgetln(fp, &s)) == NULL) - break; - - if (s && com) { /* Check and eliminate comments */ - for (cp = ptr; cp < ptr + s; cp++) - if (*cp == com && !isescaped(ptr, cp, esc)) { - s = cp - ptr; - cnt = s == 0 && buf == NULL; - break; - } - } - - if (s && nl) { /* Check and eliminate newlines */ - cp = &ptr[s - 1]; - - if (*cp == nl) - s--; /* forget newline */ - } - - if (s && con) { /* Check and eliminate continuations */ - cp = &ptr[s - 1]; - - if (*cp == con && !isescaped(ptr, cp, esc)) { - s--; /* forget continuation char */ - cnt = 1; - } - } - - if (s == 0) { - /* - * nothing to add, skip realloc except in case - * we need a minimal buf to return an empty line - */ - if (cnt || buf != NULL) - continue; - } - - if ((cp = realloc(buf, len + s + 1)) == NULL) { - FUNLOCKFILE(fp); - free(buf); - return NULL; - } - buf = cp; - - (void) memcpy(buf + len, ptr, s); - len += s; - buf[len] = '\0'; - } - - FUNLOCKFILE(fp); - - if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL && - strchr(buf, esc) != NULL) { - ptr = cp = buf; - while (cp[0] != '\0') { - int skipesc; - - while (cp[0] != '\0' && cp[0] != esc) - *ptr++ = *cp++; - if (cp[0] == '\0' || cp[1] == '\0') - break; - - skipesc = 0; - if (cp[1] == com) - skipesc += (flags & FPARSELN_UNESCCOMM); - if (cp[1] == con) - skipesc += (flags & FPARSELN_UNESCCONT); - if (cp[1] == esc) - skipesc += (flags & FPARSELN_UNESCESC); - if (cp[1] != com && cp[1] != con && cp[1] != esc) - skipesc = (flags & FPARSELN_UNESCREST); - - if (skipesc) - cp++; - else - *ptr++ = *cp++; - *ptr++ = *cp++; - } - *ptr = '\0'; - len = strlen(buf); - } - - if (size) - *size = len; - return buf; -} - -#ifdef TEST - -int main(int, char **); - -int -main(int argc, char **argv) -{ - char *ptr; - size_t size, line; - - line = 0; - while ((ptr = fparseln(stdin, &size, &line, NULL, - FPARSELN_UNESCALL)) != NULL) - printf("line %d (%d) |%s|\n", line, size, ptr); - return 0; -} - -/* - -# This is a test -line 1 -line 2 \ -line 3 # Comment -line 4 \# Not comment \\\\ - -# And a comment \ -line 5 \\\ -line 6 - -*/ - -#endif /* TEST */ -#endif /* ! HAVE_FPARSELN || BROKEN_FPARSELN */ diff --git a/contrib/blacklist/port/getprogname.c b/contrib/blacklist/port/getprogname.c deleted file mode 100644 index 983d6740c88..00000000000 --- a/contrib/blacklist/port/getprogname.c +++ /dev/null @@ -1,24 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include - -extern char *__progname; - -const char * -getprogname(void) -{ - return __progname; -} - -void -setprogname(char *p) -{ - char *q; - if (p == NULL) - return; - if ((q = strrchr(p, '/')) != NULL) - __progname = ++q; - else - __progname = p; -} diff --git a/contrib/blacklist/port/m4/.cvsignore b/contrib/blacklist/port/m4/.cvsignore deleted file mode 100644 index 0f4126cd671..00000000000 --- a/contrib/blacklist/port/m4/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.m4 diff --git a/contrib/blacklist/port/pidfile.c b/contrib/blacklist/port/pidfile.c deleted file mode 100644 index 4deb2349d20..00000000000 --- a/contrib/blacklist/port/pidfile.c +++ /dev/null @@ -1,183 +0,0 @@ -/* $NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $ */ - -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe, Matthias Scheler and Julio Merino. - * - * 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 - -#include -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $"); -#endif - -#include - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif - -static pid_t pidfile_pid; -static char *pidfile_path; - -/* Deletes an existent pidfile iff it was created by this process. */ -static void -pidfile_cleanup(void) -{ - - if ((pidfile_path != NULL) && (pidfile_pid == getpid())) - (void) unlink(pidfile_path); -} - -/* Registers an atexit(3) handler to delete the pidfile we have generated. - * We only register the handler when we create a pidfile, so we can assume - * that the pidfile exists. - * - * Returns 0 on success or -1 if the handler could not be registered. */ -static int -register_atexit_handler(void) -{ - static bool done = false; - - if (!done) { - if (atexit(pidfile_cleanup) < 0) - return -1; - done = true; - } - - return 0; -} - -/* Given a new pidfile name in 'path', deletes any previously-created pidfile - * if the previous file differs to the new one. - * - * If a previous file is deleted, returns 1, which means that a new pidfile - * must be created. Otherwise, this returns 0, which means that the existing - * file does not need to be touched. */ -static int -cleanup_old_pidfile(const char* path) -{ - if (pidfile_path != NULL) { - if (strcmp(pidfile_path, path) != 0) { - pidfile_cleanup(); - - free(pidfile_path); - pidfile_path = NULL; - - return 1; - } else - return 0; - } else - return 1; -} - -/* Constructs a name for a pidfile in the default location (/var/run). If - * 'basename' is NULL, uses the name of the current program for the name of - * the pidfile. - * - * Returns a pointer to a dynamically-allocatd string containing the absolute - * path to the pidfile; NULL on failure. */ -static char * -generate_varrun_path(const char *bname) -{ - char *path; - - if (bname == NULL) - bname = getprogname(); - - /* _PATH_VARRUN includes trailing / */ - if (asprintf(&path, "%s%s.pid", _PATH_VARRUN, bname) == -1) - return NULL; - return path; -} - -/* Creates a pidfile with the provided name. The new pidfile is "registered" - * in the global variables pidfile_path and pidfile_pid so that any further - * call to pidfile(3) can check if we are recreating the same file or a new - * one. - * - * Returns 0 on success or -1 if there is any error. */ -static int -create_pidfile(const char* path) -{ - FILE *f; - - if (register_atexit_handler() == -1) - return -1; - - if (cleanup_old_pidfile(path) == 0) - return 0; - - pidfile_path = strdup(path); - if (pidfile_path == NULL) - return -1; - - if ((f = fopen(path, "w")) == NULL) { - free(pidfile_path); - pidfile_path = NULL; - return -1; - } - - pidfile_pid = getpid(); - - (void) fprintf(f, "%d\n", pidfile_pid); - (void) fclose(f); - - return 0; -} - -int -pidfile(const char *path) -{ - - if (path == NULL || strchr(path, '/') == NULL) { - char *default_path; - - if ((default_path = generate_varrun_path(path)) == NULL) - return -1; - - if (create_pidfile(default_path) == -1) { - free(default_path); - return -1; - } - - free(default_path); - return 0; - } else - return create_pidfile(path); -} diff --git a/contrib/blacklist/port/popenve.c b/contrib/blacklist/port/popenve.c deleted file mode 100644 index df57cde9d51..00000000000 --- a/contrib/blacklist/port/popenve.c +++ /dev/null @@ -1,277 +0,0 @@ -/* $NetBSD: popenve.c,v 1.2 2015/01/22 03:10:50 christos Exp $ */ - -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software written by Ken Arnold and - * published in UNIX Review, Vol. 6, No. 8. - * - * 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. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 - -#include -#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 $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __weak_alias -__weak_alias(popen,_popen) -__weak_alias(pclose,_pclose) -#endif - -static struct pid { - struct pid *next; - FILE *fp; -#ifdef _REENTRANT - int fd; -#endif - pid_t pid; -} *pidlist; - -#ifdef _REENTRANT -static rwlock_t pidlist_lock = RWLOCK_INITIALIZER; -#endif - -static struct pid * -pdes_get(int *pdes, const char **type) -{ - struct pid *cur; - int flags = strchr(*type, 'e') ? O_CLOEXEC : 0; - int serrno; - - if (strchr(*type, '+')) { -#ifndef SOCK_CLOEXEC -#define SOCK_CLOEXEC 0 -#endif - int stype = flags ? (SOCK_STREAM | SOCK_CLOEXEC) : SOCK_STREAM; - *type = "r+"; - if (socketpair(AF_LOCAL, stype, 0, pdes) < 0) - return NULL; -#if SOCK_CLOEXEC == 0 - fcntl(pdes[0], F_SETFD, FD_CLOEXEC); - fcntl(pdes[1], F_SETFD, FD_CLOEXEC); -#endif - } else { - *type = strrchr(*type, 'r') ? "r" : "w"; -#if SOCK_CLOEXEC != 0 - if (pipe2(pdes, flags) == -1) - return NULL; -#else - if (pipe(pdes) == -1) - return NULL; - fcntl(pdes[0], F_SETFL, fcntl(pdes[0], F_GETFL) | flags); - fcntl(pdes[1], F_SETFL, fcntl(pdes[1], F_GETFL) | flags); -#endif - } - - if ((cur = malloc(sizeof(*cur))) != NULL) { - if (**type == 'r') { - cur->fp = fdopen(pdes[0], *type); -#ifdef _REENTRANT - cur->fd = pdes[0]; -#endif - } else { - cur->fp = fdopen(pdes[1], *type); -#ifdef _REENTRANT - cur->fd = pdes[1]; -#endif - } - if (cur->fp != NULL) - return cur; - } - serrno = errno; - (void)close(pdes[0]); - (void)close(pdes[1]); - free(cur); - errno = serrno; - return NULL; -} - -static void -pdes_child(int *pdes, const char *type) -{ - struct pid *old; - - if (type[0] == 'r') { - (void)close(pdes[0]); - if (pdes[1] != STDOUT_FILENO) { - (void)dup2(pdes[1], STDOUT_FILENO); - (void)close(pdes[1]); - } - if (type[1] == '+') - (void)dup2(STDOUT_FILENO, STDIN_FILENO); - } else { - (void)close(pdes[1]); - if (pdes[0] != STDIN_FILENO) { - (void)dup2(pdes[0], STDIN_FILENO); - (void)close(pdes[0]); - } - } - - /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams - from previous popen() calls that remain open in the - parent process are closed in the new child process. */ - for (old = pidlist; old; old = old->next) { -#ifdef _REENTRANT - (void)close(old->fd); /* don't allow a flush */ -#else - (void)close(fileno(old->fp)); /* don't allow a flush */ -#endif - } -} - -static void -pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type) -{ - /* Parent */ - if (*type == 'r') - (void)close(pdes[1]); - else - (void)close(pdes[0]); - - /* Link into list of file descriptors. */ - cur->pid = pid; - cur->next = pidlist; - pidlist = cur; -} - -static void -pdes_error(int *pdes, struct pid *cur) -{ - free(cur); - (void)close(pdes[0]); - (void)close(pdes[1]); -} - -FILE * -popenve(const char *cmd, char *const *argv, char *const *envp, const char *type) -{ - struct pid *cur; - int pdes[2], serrno; - pid_t pid; - - if ((cur = pdes_get(pdes, &type)) == NULL) - return NULL; - -#ifdef _REENTRANT - (void)rwlock_rdlock(&pidlist_lock); -#endif - switch (pid = fork()) { - case -1: /* Error. */ - serrno = errno; -#ifdef _REENTRANT - (void)rwlock_unlock(&pidlist_lock); -#endif - pdes_error(pdes, cur); - errno = serrno; - return NULL; - /* NOTREACHED */ - case 0: /* Child. */ - pdes_child(pdes, type); - execve(cmd, argv, envp); - _exit(127); - /* NOTREACHED */ - } - - pdes_parent(pdes, cur, pid, type); - -#ifdef _REENTRANT - (void)rwlock_unlock(&pidlist_lock); -#endif - - return cur->fp; -} - -/* - * pclose -- - * Pclose returns -1 if stream is not associated with a `popened' command, - * if already `pclosed', or waitpid returns an error. - */ -int -pcloseve(FILE *iop) -{ - struct pid *cur, *last; - int pstat; - pid_t pid; - -#ifdef _REENTRANT - rwlock_wrlock(&pidlist_lock); -#endif - - /* Find the appropriate file pointer. */ - for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) - if (cur->fp == iop) - break; - if (cur == NULL) { -#ifdef _REENTRANT - (void)rwlock_unlock(&pidlist_lock); -#endif - errno = ESRCH; - return -1; - } - - (void)fclose(iop); - - /* Remove the entry from the linked list. */ - if (last == NULL) - pidlist = cur->next; - else - last->next = cur->next; - -#ifdef _REENTRANT - (void)rwlock_unlock(&pidlist_lock); -#endif - - do { - pid = waitpid(cur->pid, &pstat, 0); - } while (pid == -1 && errno == EINTR); - - free(cur); - - return pid == -1 ? -1 : pstat; -} diff --git a/contrib/blacklist/port/port.h b/contrib/blacklist/port/port.h deleted file mode 100644 index f82fb34b40f..00000000000 --- a/contrib/blacklist/port/port.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include -#include -#include -#include -#include - -#ifndef __unused -#define __unused __attribute__((__unused__)) -#endif - -#ifndef __dead -#define __dead __attribute__((__noreturn__)) -#endif - -#ifndef __RCSID -#define __RCSID(a) -#endif - -#ifndef __UNCONST -#define __UNCONST(a) ((void *)(intptr_t)(a)) -#endif - -#ifndef __arraycount -#define __arraycount(a) (sizeof(a) / sizeof(a[0])) -#endif - -#ifndef HAVE_STRLCPY -size_t strlcpy(char *, const char *, size_t); -#endif - -#ifndef HAVE_STRLCAT -size_t strlcat(char *, const char *, size_t); -#endif - -#ifndef HAVE_POPENVE -FILE *popenve(const char *, char *const *, char *const *, const char *); -int pcloseve(FILE *); -#define pclose(a) pcloseve(a); -#endif - -#ifndef HAVE_SOCKADDR_SNPRINTF -struct sockaddr; -int sockaddr_snprintf(char *, size_t, const char *, const struct sockaddr *); -#endif - -#ifndef HAVE_STRTOI -intmax_t strtoi(const char *, char **, int, intmax_t, intmax_t, int *); -#endif - -#ifndef HAVE_GETPROGNAME -const char *getprogname(void); -void setprogname(char *); -#endif - -#ifndef HAVE_PIDFILE -int pidfile(const char *); -#endif - -#ifndef HAVE_FPARSELN -#define FPARSELN_UNESCALL 0xf -#define FPARSELN_UNESCCOMM 0x1 -#define FPARSELN_UNESCCONT 0x2 -#define FPARSELN_UNESCESC 0x4 -#define FPARSELN_UNESCREST 0x8 -char *fparseln(FILE *, size_t *, size_t *, const char delim[3], int); -#endif - -#ifndef HAVE_FGETLN -char *fgetln(FILE *, size_t *); -#endif - -#ifndef HAVE_CLOCK_GETTIME -struct timespec; -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" -#endif diff --git a/contrib/blacklist/port/sockaddr_snprintf.c b/contrib/blacklist/port/sockaddr_snprintf.c deleted file mode 100644 index 558755b6294..00000000000 --- a/contrib/blacklist/port/sockaddr_snprintf.c +++ /dev/null @@ -1,383 +0,0 @@ -/* $NetBSD: sockaddr_snprintf.c,v 1.11 2016/06/01 22:57:51 christos Exp $ */ - -/*- - * Copyright (c) 2004 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 - -#include -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.11 2016/06/01 22:57:51 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include - -#include -#ifdef __linux__ -#undef HAVE_NETATALK_AT_H -#endif -#ifdef HAVE_NETATALK_AT_H -#include -#endif -#ifdef HAVE_NET_IF_DL_H -#include -#endif - -#include -#include -#include -#include -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include - -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN -#define SLEN(a) (a)->a ## _len -#else -static socklen_t -socklen(u_int af) -{ - switch (af) { - case AF_INET: - return sizeof(struct sockaddr_in); - case AF_INET6: - return sizeof(struct sockaddr_in6); - case AF_LOCAL: - return sizeof(struct sockaddr_un); -#ifdef HAVE_NET_IF_DL_H - case AF_LINK: - return sizeof(struct sockaddr_dl); -#endif -#ifdef HAVE_NETATALK_AT_H - case AF_APPLETALK: - return sizeof(struct sockaddr_at); -#endif - default: - return sizeof(struct sockaddr_storage); - } -} - -#define SLEN(a) socklen((a)->a ## _family) -#endif - -#ifdef HAVE_NETATALK_AT_H -static int -debug_at(char *str, size_t len, const struct sockaddr_at *sat) -{ - return snprintf(str, len, "sat_len=%u, sat_family=%u, sat_port=%u, " - "sat_addr.s_net=%u, sat_addr.s_node=%u, " - "sat_range.r_netrange.nr_phase=%u, " - "sat_range.r_netrange.nr_firstnet=%u, " - "sat_range.r_netrange.nr_lastnet=%u", - SLEN(sat), sat->sat_family, sat->sat_port, - sat->sat_addr.s_net, sat->sat_addr.s_node, - sat->sat_range.r_netrange.nr_phase, - sat->sat_range.r_netrange.nr_firstnet, - sat->sat_range.r_netrange.nr_lastnet); -} -#endif - -static int -debug_in(char *str, size_t len, const struct sockaddr_in *sin) -{ - return snprintf(str, len, "sin_len=%u, sin_family=%u, sin_port=%u, " - "sin_addr.s_addr=%08x", - SLEN(sin), sin->sin_family, sin->sin_port, - sin->sin_addr.s_addr); -} - -static int -debug_in6(char *str, size_t len, const struct sockaddr_in6 *sin6) -{ - const uint8_t *s = sin6->sin6_addr.s6_addr; - - return snprintf(str, len, "sin6_len=%u, sin6_family=%u, sin6_port=%u, " - "sin6_flowinfo=%u, " - "sin6_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" - "%02x:%02x:%02x:%02x:%02x:%02x, sin6_scope_id=%u", - SLEN(sin6), sin6->sin6_family, sin6->sin6_port, - sin6->sin6_flowinfo, s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5], - s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb], s[0xc], s[0xd], - s[0xe], s[0xf], sin6->sin6_scope_id); -} - -static int -debug_un(char *str, size_t len, const struct sockaddr_un *sun) -{ - return snprintf(str, len, "sun_len=%u, sun_family=%u, sun_path=%*s", - SLEN(sun), sun->sun_family, (int)sizeof(sun->sun_path), - sun->sun_path); -} - -#ifdef HAVE_NET_IF_DL_H -static int -debug_dl(char *str, size_t len, const struct sockaddr_dl *sdl) -{ - const uint8_t *s = (const void *)sdl->sdl_data; - - return snprintf(str, len, "sdl_len=%u, sdl_family=%u, sdl_index=%u, " - "sdl_type=%u, sdl_nlen=%u, sdl_alen=%u, sdl_slen=%u, sdl_data=" - "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - SLEN(sdl), sdl->sdl_family, sdl->sdl_index, - sdl->sdl_type, sdl->sdl_nlen, sdl->sdl_alen, sdl->sdl_slen, - s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5], - s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb]); -} -#endif - -int -sockaddr_snprintf(char * const sbuf, const size_t len, const char * const fmt, - const struct sockaddr * const sa) -{ - const void *a = NULL; - char abuf[1024], nbuf[1024], *addr = NULL; - - char Abuf[1024], pbuf[32], *name = NULL, *port = NULL; - char *ebuf = &sbuf[len - 1], *buf = sbuf; - const char *ptr, *s; - int p = -1; -#ifdef HAVE_NETATALK_AT_H - const struct sockaddr_at *sat = NULL; -#endif - const struct sockaddr_in *sin4 = NULL; - const struct sockaddr_in6 *sin6 = NULL; - const struct sockaddr_un *sun = NULL; -#ifdef HAVE_NET_IF_DL_H - const struct sockaddr_dl *sdl = NULL; - char *w = NULL; -#endif - int na = 1; - -#define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \ - while (/*CONSTCOND*/0) -#define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \ - while (/*CONSTCOND*/0) -#define ADDNA() do { if (na) ADDS("N/A"); } \ - while (/*CONSTCOND*/0) - - switch (sa->sa_family) { - case AF_UNSPEC: - goto done; -#ifdef HAVE_NETATALK_AT_H - case AF_APPLETALK: - sat = ((const struct sockaddr_at *)(const void *)sa); - p = ntohs(sat->sat_port); - (void)snprintf(addr = abuf, sizeof(abuf), "%u.%u", - ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); - (void)snprintf(port = pbuf, sizeof(pbuf), "%d", p); - break; -#endif - case AF_LOCAL: - sun = ((const struct sockaddr_un *)(const void *)sa); - (void)strlcpy(addr = abuf, sun->sun_path, sizeof(abuf)); - break; - case AF_INET: - sin4 = ((const struct sockaddr_in *)(const void *)sa); - p = ntohs(sin4->sin_port); - a = &sin4->sin_addr; - break; - case AF_INET6: - sin6 = ((const struct sockaddr_in6 *)(const void *)sa); - p = ntohs(sin6->sin6_port); - a = &sin6->sin6_addr; - break; -#ifdef HAVE_NET_IF_DL_H - case AF_LINK: - sdl = ((const struct sockaddr_dl *)(const void *)sa); - (void)strlcpy(addr = abuf, link_ntoa(sdl), sizeof(abuf)); - if ((w = strchr(addr, ':')) != NULL) { - *w++ = '\0'; - addr = w; - } - break; -#endif - default: - errno = EAFNOSUPPORT; - return -1; - } - - if (addr == abuf) - name = addr; - - if (a && getnameinfo(sa, (socklen_t)SLEN(sa), addr = abuf, - (unsigned int)sizeof(abuf), NULL, 0, - NI_NUMERICHOST|NI_NUMERICSERV) != 0) - return -1; - - for (ptr = fmt; *ptr; ptr++) { - if (*ptr != '%') { - ADDC(*ptr); - continue; - } - next_char: - switch (*++ptr) { - case '?': - na = 0; - goto next_char; - case 'a': - ADDS(addr); - break; - case 'p': - if (p != -1) { - (void)snprintf(nbuf, sizeof(nbuf), "%d", p); - ADDS(nbuf); - } else - ADDNA(); - break; - case 'f': - (void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family); - ADDS(nbuf); - break; - case 'l': - (void)snprintf(nbuf, sizeof(nbuf), "%d", SLEN(sa)); - ADDS(nbuf); - break; - case 'A': - if (name) - ADDS(name); - else if (!a) - ADDNA(); - else { - getnameinfo(sa, (socklen_t)SLEN(sa), - name = Abuf, - (unsigned int)sizeof(nbuf), NULL, 0, 0); - ADDS(name); - } - break; - case 'P': - if (port) - ADDS(port); - else if (p == -1) - ADDNA(); - else { - getnameinfo(sa, (socklen_t)SLEN(sa), NULL, 0, - port = pbuf, - (unsigned int)sizeof(pbuf), 0); - ADDS(port); - } - break; - case 'I': -#ifdef HAVE_NET_IF_DL_H - if (sdl && addr != abuf) { - ADDS(abuf); - } else -#endif - { - ADDNA(); - } - break; - case 'F': - if (sin6) { - (void)snprintf(nbuf, sizeof(nbuf), "%d", - sin6->sin6_flowinfo); - ADDS(nbuf); - break; - } else { - ADDNA(); - } - break; - case 'S': - if (sin6) { - (void)snprintf(nbuf, sizeof(nbuf), "%d", - sin6->sin6_scope_id); - ADDS(nbuf); - break; - } else { - ADDNA(); - } - break; - case 'R': -#ifdef HAVE_NETATALK_AT_H - if (sat) { - const struct netrange *n = - &sat->sat_range.r_netrange; - (void)snprintf(nbuf, sizeof(nbuf), - "%d:[%d,%d]", n->nr_phase , n->nr_firstnet, - n->nr_lastnet); - ADDS(nbuf); - } else -#endif - { - ADDNA(); - } - break; - case 'D': - switch (sa->sa_family) { -#ifdef HAVE_NETATALK_AT_H - case AF_APPLETALK: - debug_at(nbuf, sizeof(nbuf), sat); - break; -#endif - case AF_LOCAL: - debug_un(nbuf, sizeof(nbuf), sun); - break; - case AF_INET: - debug_in(nbuf, sizeof(nbuf), sin4); - break; - case AF_INET6: - debug_in6(nbuf, sizeof(nbuf), sin6); - break; -#ifdef HAVE_NET_IF_DL_H - case AF_LINK: - debug_dl(nbuf, sizeof(nbuf), sdl); - break; -#endif - default: - abort(); - } - ADDS(nbuf); - break; - default: - ADDC('%'); - if (na == 0) - ADDC('?'); - if (*ptr == '\0') - goto done; - /*FALLTHROUGH*/ - case '%': - ADDC(*ptr); - break; - } - na = 1; - } -done: - if (buf < ebuf) - *buf = '\0'; - else if (len != 0) - sbuf[len - 1] = '\0'; - return (int)(buf - sbuf); -} diff --git a/contrib/blacklist/port/strlcat.c b/contrib/blacklist/port/strlcat.c deleted file mode 100644 index d3c69b5fab7..00000000000 --- a/contrib/blacklist/port/strlcat.c +++ /dev/null @@ -1,96 +0,0 @@ -/* $NetBSD: strlcat.c,v 1.2 2015/01/22 03:48:07 christos Exp $ */ -/* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE - * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#if !defined(_KERNEL) && !defined(_STANDALONE) -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: strlcat.c,v 1.2 2015/01/22 03:48:07 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#ifdef _LIBC -#include "namespace.h" -#endif -#include -#include -#include - -#ifdef _LIBC -# ifdef __weak_alias -__weak_alias(strlcat, _strlcat) -# endif -#endif - -#else -#include -#endif /* !_KERNEL && !_STANDALONE */ - -#if !HAVE_STRLCAT -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t siz) -{ -#if 1 - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -#else - - /* - * Find length of string in dst (maxing out at siz). - */ - size_t dlen = strnlen(dst, siz); - - /* - * Copy src into any remaining space in dst (truncating if needed). - * Note strlcpy(dst, src, 0) returns strlen(src). - */ - return dlen + strlcpy(dst + dlen, src, siz - dlen); -#endif -} -#endif diff --git a/contrib/blacklist/port/strlcpy.c b/contrib/blacklist/port/strlcpy.c deleted file mode 100644 index 6646e1ce969..00000000000 --- a/contrib/blacklist/port/strlcpy.c +++ /dev/null @@ -1,78 +0,0 @@ -/* $NetBSD: strlcpy.c,v 1.2 2015/01/22 03:48:07 christos Exp $ */ -/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE - * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#if !defined(_KERNEL) && !defined(_STANDALONE) -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: strlcpy.c,v 1.2 2015/01/22 03:48:07 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#ifdef _LIBC -#include "namespace.h" -#endif -#include -#include -#include - -#ifdef _LIBC -# ifdef __weak_alias -__weak_alias(strlcpy, _strlcpy) -# endif -#endif -#else -#include -#endif /* !_KERNEL && !_STANDALONE */ - - -#if !HAVE_STRLCPY -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} -#endif diff --git a/contrib/blacklist/port/strtoi.c b/contrib/blacklist/port/strtoi.c deleted file mode 100644 index 5514f1a00a3..00000000000 --- a/contrib/blacklist/port/strtoi.c +++ /dev/null @@ -1,61 +0,0 @@ -/* $NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $ */ - -/*- - * Copyright (c) 2005 The DragonFly Project. All rights reserved. - * Copyright (c) 2003 Citrus Project, - * All rights reserved. - * - * 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. - * - * Created by Kamil Rytarowski, based on ID: - * NetBSD: src/common/lib/libc/stdlib/strtoul.c,v 1.3 2008/08/20 19:58:34 oster Exp - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -__RCSID("$NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $"); - -#if defined(_KERNEL) -#include -#include -#include -#elif defined(_STANDALONE) -#include -#include -#include -#include -#else -#include -#include -#include -#include -#endif - -#define _FUNCNAME strtoi -#define __TYPE intmax_t -#define __WRAPPED strtoimax - -#if !HAVE_STRTOI -#include "_strtoi.h" -#endif diff --git a/contrib/blacklist/test/Makefile b/contrib/blacklist/test/Makefile deleted file mode 100644 index a451274def0..00000000000 --- a/contrib/blacklist/test/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $NetBSD: Makefile,v 1.3 2015/05/30 22:40:38 christos Exp $ - -MKMAN=no - -PROGS=srvtest cltest -SRCS.srvtest = srvtest.c -SRCS.cltest = cltest.c -CPPFLAGS+=-DBLDEBUG -LDADD+=-lutil -DPADD+=${LIBUTIL} - -.include diff --git a/contrib/blacklist/test/cltest.c b/contrib/blacklist/test/cltest.c deleted file mode 100644 index 6671429fc3c..00000000000 --- a/contrib/blacklist/test/cltest.c +++ /dev/null @@ -1,136 +0,0 @@ -/* $NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 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 - -#include -__RCSID("$NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 christos Exp $"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#ifdef HAVE_UTIL_H -#include -#endif - -static __dead void -usage(int c) -{ - warnx("Unknown option `%c'", (char)c); - fprintf(stderr, "Usage: %s [-u] [-a ] [-m ] [-p ]\n", - getprogname()); - exit(EXIT_FAILURE); -} - -static void -getaddr(const char *a, in_port_t p, struct sockaddr_storage *ss, - socklen_t *slen) -{ - int c; - - memset(ss, 0, sizeof(*ss)); - p = htons(p); - - if (strchr(a, ':')) { - struct sockaddr_in6 *s6 = (void *)ss; - c = inet_pton(AF_INET6, a, &s6->sin6_addr); - s6->sin6_family = AF_INET6; - *slen = sizeof(*s6); - s6->sin6_port = p; - } else { - struct sockaddr_in *s = (void *)ss; - c = inet_pton(AF_INET, a, &s->sin_addr); - s->sin_family = AF_INET; - *slen = sizeof(*s); - s->sin_port = p; - } -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - ss->ss_len = (uint8_t)*slen; -#endif - if (c == -1) - err(EXIT_FAILURE, "Invalid address `%s'", a); -} - -int -main(int argc, char *argv[]) -{ - int sfd; - int c; - struct sockaddr_storage ss; - const char *msg = "hello"; - const char *addr = "127.0.0.1"; - int type = SOCK_STREAM; - in_port_t port = 6161; - socklen_t slen; - char buf[128]; - - while ((c = getopt(argc, argv, "a:m:p:u")) != -1) { - switch (c) { - case 'a': - addr = optarg; - break; - case 'm': - msg = optarg; - break; - case 'p': - port = (in_port_t)atoi(optarg); - break; - case 'u': - type = SOCK_DGRAM; - break; - default: - usage(c); - } - } - - getaddr(addr, port, &ss, &slen); - - if ((sfd = socket(AF_INET, type, 0)) == -1) - err(EXIT_FAILURE, "socket"); - - sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (const void *)&ss); - printf("connecting to: %s\n", buf); - if (connect(sfd, (const void *)&ss, slen) == -1) - err(EXIT_FAILURE, "connect"); - - size_t len = strlen(msg) + 1; - if (write(sfd, msg, len) != (ssize_t)len) - err(EXIT_FAILURE, "write"); - return 0; -} diff --git a/contrib/blacklist/test/srvtest.c b/contrib/blacklist/test/srvtest.c deleted file mode 100644 index 03a762ab81f..00000000000 --- a/contrib/blacklist/test/srvtest.c +++ /dev/null @@ -1,220 +0,0 @@ -/* $NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 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 - -#include -__RCSID("$NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $"); - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "blacklist.h" -#ifdef BLDEBUG -#include "bl.h" -static void *b; -#endif - -#ifndef INFTIM -#define INFTIM -1 -#endif - -static void -process_tcp(int afd) -{ - ssize_t n; - char buffer[256]; - - memset(buffer, 0, sizeof(buffer)); - - if ((n = read(afd, buffer, sizeof(buffer))) == -1) - err(1, "read"); - buffer[sizeof(buffer) - 1] = '\0'; - printf("%s: sending %d %s\n", getprogname(), afd, buffer); -#ifdef BLDEBUG - blacklist_r(b, 1, afd, buffer); -#else - blacklist(1, afd, buffer); -#endif - exit(0); -} - -static void -process_udp(int afd) -{ - ssize_t n; - char buffer[256]; - struct sockaddr_storage ss; - socklen_t slen; - - memset(buffer, 0, sizeof(buffer)); - - slen = (socklen_t)sizeof(ss); - memset(&ss, 0, sizeof(ss)); - if ((n = recvfrom(afd, buffer, sizeof(buffer), 0, (void *)&ss, - &slen)) == -1) - 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); - exit(0); -} -static int -cr(int af, int type, in_port_t p) -{ - int sfd; - struct sockaddr_storage ss; - socklen_t slen; - sfd = socket(af == AF_INET ? PF_INET : PF_INET6, type, 0); - if (sfd == -1) - err(1, "socket"); - - p = htons(p); - memset(&ss, 0, sizeof(ss)); - if (af == AF_INET) { - struct sockaddr_in *s = (void *)&ss; - s->sin_family = AF_INET; - slen = sizeof(*s); - s->sin_port = p; - } else { - struct sockaddr_in6 *s6 = (void *)&ss; - s6->sin6_family = AF_INET6; - slen = sizeof(*s6); - s6->sin6_port = p; - } -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - ss.ss_len = (uint8_t)slen; -#endif - - if (bind(sfd, (const void *)&ss, slen) == -1) - err(1, "bind"); - - if (type != SOCK_DGRAM) - if (listen(sfd, 5) == -1) - err(1, "listen"); - return sfd; -} - -static void -handle(int type, int sfd) -{ - struct sockaddr_storage ss; - socklen_t alen = sizeof(ss); - int afd; - - if (type != SOCK_DGRAM) { - if ((afd = accept(sfd, (void *)&ss, &alen)) == -1) - err(1, "accept"); - } else - afd = sfd; - - /* Create child process */ - switch (fork()) { - case -1: - err(1, "fork"); - case 0: - if (type == SOCK_DGRAM) - process_udp(afd); - else - process_tcp(afd); - break; - default: - close(afd); - break; - } -} - -static __dead void -usage(int c) -{ - warnx("Unknown option `%c'", (char)c); - fprintf(stderr, "Usage: %s [-u] [-p ]\n", getprogname()); - exit(EXIT_FAILURE); -} - -int -main(int argc, char *argv[]) -{ -#ifdef __linux__ -#define NUMFD 1 -#else -#define NUMFD 2 -#endif - 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); -#endif - - while ((c = getopt(argc, argv, "up:")) != -1) - switch (c) { - case 'u': - type = SOCK_DGRAM; - break; - case 'p': - port = (in_port_t)atoi(optarg); - break; - default: - usage(c); - } - - pfd[0].fd = cr(AF_INET, type, port); - pfd[0].events = POLLIN; -#if NUMFD > 1 - pfd[1].fd = cr(AF_INET6, type, port); - pfd[1].events = POLLIN; -#endif - - for (;;) { - if (poll(pfd, __arraycount(pfd), INFTIM) == -1) - err(1, "poll"); - for (size_t i = 0; i < __arraycount(pfd); i++) { - if ((pfd[i].revents & POLLIN) == 0) - continue; - handle(type, pfd[i].fd); - } - } -} From 36fd9af0bbb504998261225cf3b26f36055bbf7f Mon Sep 17 00:00:00 2001 From: Lucas Holt Date: Tue, 22 Sep 2026 13:59:38 -0400 Subject: [PATCH 3/4] contrib/blocklist: local adaptations and compatibility sources Apply the MidnightBSD changes (drop the Debian port, /usr/libexec paths, SA_SIZE instead of RT_ROUNDUP, packet filter man page cross-references) and record them in midnightbsd-changes.sh. Add the compatibility sources for the old blacklist names from FreeBSD so lib/libblacklist, blacklistd and blacklistctl can keep being built during the transition. Describe the import procedure in MIDNIGHTBSD-upgrade. AI-Assisted-by: Claude Fable 5.1 Signed-off-by: Lucas Holt --- contrib/blocklist/MIDNIGHTBSD-upgrade | 34 + contrib/blocklist/bin/blacklistctl.c | 170 +++++ contrib/blocklist/bin/blacklistd.c | 594 ++++++++++++++++++ contrib/blocklist/bin/blocklistd.8 | 10 +- contrib/blocklist/bin/conf.c | 4 +- contrib/blocklist/bin/internal.h | 2 +- .../debian/copyright => bin/old_internal.c} | 34 +- contrib/blocklist/bin/old_internal.h | 58 ++ contrib/blocklist/include/blacklist.h | 65 ++ contrib/blocklist/include/old_bl.h | 80 +++ contrib/blocklist/lib/blacklist.c | 117 ++++ contrib/blocklist/lib/old_bl.c | 554 ++++++++++++++++ contrib/blocklist/midnightbsd-changes.sh | 20 + .../blocklist/port/debian/blocklist.manpages | 4 - contrib/blocklist/port/debian/changelog | 6 - contrib/blocklist/port/debian/compat | 1 - contrib/blocklist/port/debian/control | 21 - contrib/blocklist/port/debian/install | 1 - contrib/blocklist/port/debian/rules | 15 - contrib/blocklist/port/debian/source/format | 1 - 20 files changed, 1724 insertions(+), 67 deletions(-) create mode 100644 contrib/blocklist/MIDNIGHTBSD-upgrade create mode 100644 contrib/blocklist/bin/blacklistctl.c create mode 100644 contrib/blocklist/bin/blacklistd.c rename contrib/blocklist/{port/debian/copyright => bin/old_internal.c} (73%) create mode 100644 contrib/blocklist/bin/old_internal.h create mode 100644 contrib/blocklist/include/blacklist.h create mode 100644 contrib/blocklist/include/old_bl.h create mode 100644 contrib/blocklist/lib/blacklist.c create mode 100644 contrib/blocklist/lib/old_bl.c create mode 100644 contrib/blocklist/midnightbsd-changes.sh delete mode 100644 contrib/blocklist/port/debian/blocklist.manpages delete mode 100644 contrib/blocklist/port/debian/changelog delete mode 100644 contrib/blocklist/port/debian/compat delete mode 100644 contrib/blocklist/port/debian/control delete mode 100644 contrib/blocklist/port/debian/install delete mode 100755 contrib/blocklist/port/debian/rules delete mode 100644 contrib/blocklist/port/debian/source/format diff --git a/contrib/blocklist/MIDNIGHTBSD-upgrade b/contrib/blocklist/MIDNIGHTBSD-upgrade new file mode 100644 index 00000000000..37472b54bc2 --- /dev/null +++ b/contrib/blocklist/MIDNIGHTBSD-upgrade @@ -0,0 +1,34 @@ +blocklist (formerly blacklist) from https://github.com/zoulasc/blocklist + +Vendor branch: vendor/blocklist, tagged vendor/blocklist/YYYYMMDD after +the upstream commit date. Upstream has no releases; import HEAD. + +To import a new snapshot: + + 1) git clone https://github.com/zoulasc/blocklist.git and note the + commit hash and date. + 2) In this repository: + git fetch HEAD + c=$(git commit-tree FETCH_HEAD^{tree} -p vendor/blocklist \ + -m "Import blocklist YYYY-MM-DD (shorthash)") + git branch -f vendor/blocklist $c + git tag vendor/blocklist/YYYYMMDD $c + 3) On master: + git merge -X subtree=contrib/blocklist vendor/blocklist + 4) Re-run sh midnightbsd-changes.sh in contrib/blocklist and check + that nothing else changed with + git diff vendor/blocklist HEAD:contrib/blocklist + 5) If source files were added or removed, update lib/libblocklist, + usr.sbin/blocklistd and usr.sbin/blocklistctl. + 6) Build world and test sshd(8) and fingerd(8) integration. + +Files that are not upstream: + + bin/blacklistctl.c bin/blacklistd.c bin/old_internal.[ch] + include/blacklist.h include/old_bl.h lib/blacklist.c lib/old_bl.c + Compatibility sources for the old blacklist names, taken from + FreeBSD. They build lib/libblacklist, usr.sbin/blacklistd and + usr.sbin/blacklistctl so existing configurations keep working + with a warning. + midnightbsd-changes.sh MIDNIGHTBSD-upgrade + This file and the change script. diff --git a/contrib/blocklist/bin/blacklistctl.c b/contrib/blocklist/bin/blacklistctl.c new file mode 100644 index 00000000000..6298a08b10b --- /dev/null +++ b/contrib/blocklist/bin/blacklistctl.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 +#endif +__RCSID("$NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); + +#include +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "conf.h" +#include "state.h" +#include "old_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/blacklistd.c b/contrib/blocklist/bin/blacklistd.c new file mode 100644 index 00000000000..01eb662c83f --- /dev/null +++ b/contrib/blocklist/bin/blacklistd.c @@ -0,0 +1,594 @@ +/* $NetBSD: blocklistd.c,v 1.15 2026/02/07 14:32:04 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 +#endif +__RCSID("$NetBSD: blocklistd.c,v 1.15 2026/02/07 14:32:04 christos Exp $"); + +#include +#include +#include + +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "old_bl.h" +#include "old_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 ] [-R ] " + "[-P ] [-C ] [-D ] " + "[-s ] [-t ]\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 threshold, 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); + } + if (state_del(state, &c) == 0) + 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 = reallocarray(*blp, *maxfd, sizeof(**blp)); + if (*blp == NULL) + err(EXIT_FAILURE, "malloc"); + *pfdp = reallocarray(*pfdp, *maxfd, sizeof(**pfdp)); + 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 = reallocarray(*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 = reallocarray(blsock, maxblsock, + sizeof(*blsock)); + 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); + else { + if (restore) { + if (!flush) + rules_flush(); + rules_restore(); + } + } + if (state == NULL) + exit(EXIT_FAILURE); + + 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)"); + exit(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); + exit(EXIT_SUCCESS); +} diff --git a/contrib/blocklist/bin/blocklistd.8 b/contrib/blocklist/bin/blocklistd.8 index 38bf2217536..e0b9fb482cb 100644 --- a/contrib/blocklist/bin/blocklistd.8 +++ b/contrib/blocklist/bin/blocklistd.8 @@ -166,7 +166,7 @@ The following options are available: Use .Ar controlprog to communicate with the packet filter, instead of the default, which is -.Pa /libexec/blocklistd-helper . +.Pa /usr/libexec/blocklistd-helper . The following arguments are passed to the control program: .Bl -tag -width protocol .It action @@ -273,8 +273,8 @@ This signal tells to decrease the internal debugging level by 1. .El .Sh FILES -.Bl -tag -width /libexec/blocklistd-helper -compact -.It Pa /libexec/blocklistd-helper +.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. @@ -286,7 +286,9 @@ Socket to receive connection notifications. .Sh SEE ALSO .Xr blocklistd.conf 5 , .Xr blocklistctl 8 , -.Xr npfctl 8 , +.Xr ipf 8 , +.Xr ipfw 8 , +.Xr pfctl 8 , .Xr syslogd 8 .Sh HISTORY .Nm diff --git a/contrib/blocklist/bin/conf.c b/contrib/blocklist/bin/conf.c index 3c6fadb5fa4..f469e28235c 100644 --- a/contrib/blocklist/bin/conf.c +++ b/contrib/blocklist/bin/conf.c @@ -1070,7 +1070,7 @@ confset_match(const struct confset *cs, struct conf *c, #ifdef AF_ROUTE static int conf_route_perm(int fd) { -#if defined(RTM_IFANNOUNCE) && defined(RT_ROUNDUP) +#if defined(RTM_IFANNOUNCE) && defined(SA_SIZE) /* * Send a routing message that is not supported to check for access * We expect EOPNOTSUPP for having access, since we are sending a @@ -1089,7 +1089,7 @@ conf_route_perm(int fd) { size_t l; #define NEXTADDR(s) \ - l = RT_ROUNDUP(sizeof(*s)); memmove(cp, s, l); cp += l; + l = SA_SIZE(sizeof(*s)); memmove(cp, s, l); cp += l; memset(buf, 0, sizeof(buf)); rtm->rtm_type = RTM_IFANNOUNCE; rtm->rtm_flags = 0; diff --git a/contrib/blocklist/bin/internal.h b/contrib/blocklist/bin/internal.h index b88e1330221..553320e7afd 100644 --- a/contrib/blocklist/bin/internal.h +++ b/contrib/blocklist/bin/internal.h @@ -35,7 +35,7 @@ #define _PATH_BLCONF "/etc/blocklistd.conf" #endif #ifndef _PATH_BLCONTROL -#define _PATH_BLCONTROL "/libexec/blocklistd-helper" +#define _PATH_BLCONTROL "/usr/libexec/blocklistd-helper" #endif #ifndef _PATH_BLSTATE #define _PATH_BLSTATE "/var/db/blocklistd.db" diff --git a/contrib/blocklist/port/debian/copyright b/contrib/blocklist/bin/old_internal.c similarity index 73% rename from contrib/blocklist/port/debian/copyright rename to contrib/blocklist/bin/old_internal.c index 1eb03776041..79093cc8b8a 100644 --- a/contrib/blocklist/port/debian/copyright +++ b/contrib/blocklist/bin/old_internal.c @@ -1,15 +1,6 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: blocklist -Upstream-Contact: christos@zoulas.com -Source: https://github.com/zoulasc/blocklist -Comment: - 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. +/* $NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $ */ -Files: * -Copyright: 2020 Christos Zoulas -License: NetBSD +/*- * Copyright (c) 2015 The NetBSD Foundation, Inc. * All rights reserved. * @@ -36,3 +27,24 @@ License: NetBSD * 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 +#endif +__RCSID("$NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $"); + +#include +#include +#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 00000000000..becee563e81 --- /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/include/blacklist.h b/contrib/blocklist/include/blacklist.h new file mode 100644 index 00000000000..f97cf34c4bc --- /dev/null +++ b/contrib/blocklist/include/blacklist.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 _BLACKLIST_H +#define _BLACKLIST_H + +#include +#include + +#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 *); + +#if defined(__cplusplus) +} +#endif + +/* action values for user applications */ +#define BLACKLIST_API_ENUM 1 +enum { + BLACKLIST_AUTH_OK = 0, + BLACKLIST_AUTH_FAIL, + BLACKLIST_ABUSIVE_BEHAVIOR, + BLACKLIST_BAD_USER +}; + +#endif /* _BLACKLIST_H */ diff --git a/contrib/blocklist/include/old_bl.h b/contrib/blocklist/include/old_bl.h new file mode 100644 index 00000000000..1ab64a4d9b6 --- /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 +#include +#include +#include +#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/blacklist.c b/contrib/blocklist/lib/blacklist.c new file mode 100644 index 00000000000..12e5f83e09a --- /dev/null +++ b/contrib/blocklist/lib/blacklist.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 +#endif +__RCSID("$NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); + +#include +#include + +#include +#include +#include +#include +#include + +int +blacklist_sa(int action, int rfd, const struct sockaddr *sa, socklen_t salen, + const char *msg) +{ + struct blacklist *bl; + int rv; + if ((bl = blacklist_open()) == NULL) + return -1; + rv = blacklist_sa_r(bl, action, rfd, sa, salen, msg); + blacklist_close(bl); + return rv; +} + +int +blacklist_sa_r(struct blacklist *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 BLACKLIST_AUTH_FAIL: + internal_action = BL_ADD; + break; + case BLACKLIST_AUTH_OK: + internal_action = BL_DELETE; + break; + case BLACKLIST_ABUSIVE_BEHAVIOR: + internal_action = BL_ABUSE; + break; + case BLACKLIST_BAD_USER: + internal_action = BL_BADUSER; + break; + default: + internal_action = BL_INVALID; + break; + } + return bl_send(bl, internal_action, rfd, sa, slen, msg); +} + +int +blacklist(int action, int rfd, const char *msg) +{ + return blacklist_sa(action, rfd, NULL, 0, msg); +} + +int +blacklist_r(struct blacklist *bl, int action, int rfd, const char *msg) +{ + return blacklist_sa_r(bl, action, rfd, NULL, 0, msg); +} + +struct blacklist * +blacklist_open(void) { + 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 +blacklist_close(struct blacklist *bl) +{ + bl_destroy(bl); +} diff --git a/contrib/blocklist/lib/old_bl.c b/contrib/blocklist/lib/old_bl.c new file mode 100644 index 00000000000..ffbbd3f620a --- /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 +#endif +__RCSID("$NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _REENTRANT +#include +#endif + +#if defined(SO_RECVUCRED) +#include +#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/midnightbsd-changes.sh b/contrib/blocklist/midnightbsd-changes.sh new file mode 100644 index 00000000000..3ac589cd4cb --- /dev/null +++ b/contrib/blocklist/midnightbsd-changes.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# +# MidnightBSD-specific changes from upstream, applied after a vendor +# merge. Derived from FreeBSD's freebsd-changes.sh. +# + +# Remove Debian port +rm -fr port/debian + +# /libexec -> /usr/libexec +sed -i '' -e 's| /libexec| /usr/libexec|g' bin/blocklistd.8 +sed -i '' -e 's|"/libexec|"/usr/libexec|g' bin/internal.h + +# NetBSD: RT_ROUNDUP -> MidnightBSD: SA_SIZE (from net/route.h) +sed -i '' -e 's/RT_ROUNDUP/SA_SIZE/g' bin/conf.c + +# npfctl(8) -> ipf(8), ipfw(8), pfctl(8) +sed -i '' -e 's/npfctl 8 ,/ipf 8 ,\ +.Xr ipfw 8 ,\ +.Xr pfctl 8 ,/g' bin/blocklistd.8 diff --git a/contrib/blocklist/port/debian/blocklist.manpages b/contrib/blocklist/port/debian/blocklist.manpages deleted file mode 100644 index 29bf2aa3eda..00000000000 --- a/contrib/blocklist/port/debian/blocklist.manpages +++ /dev/null @@ -1,4 +0,0 @@ -bin/blocklistctl.8 -bin/blocklistd.8 -bin/blocklistd.conf.5 -lib/libblocklist.3 diff --git a/contrib/blocklist/port/debian/changelog b/contrib/blocklist/port/debian/changelog deleted file mode 100644 index cd69e1d13e0..00000000000 --- a/contrib/blocklist/port/debian/changelog +++ /dev/null @@ -1,6 +0,0 @@ -blocklist (1.7+nmu1) unstable; urgency=low - - * nmu; import from https://github.com/zoulasc/blocklist - * - - -- Two Sigma Base Platform Engineering Tue, 30 Jun 2020 14:40:28 +0000 diff --git a/contrib/blocklist/port/debian/compat b/contrib/blocklist/port/debian/compat deleted file mode 100644 index f599e28b8ab..00000000000 --- a/contrib/blocklist/port/debian/compat +++ /dev/null @@ -1 +0,0 @@ -10 diff --git a/contrib/blocklist/port/debian/control b/contrib/blocklist/port/debian/control deleted file mode 100644 index cec0c4ef1a3..00000000000 --- a/contrib/blocklist/port/debian/control +++ /dev/null @@ -1,21 +0,0 @@ -Source: blocklist -Section: net -Priority: optional -Maintainer: Christos Zoulas -Standards-Version: 4.4.1 -Build-Depends: debhelper (>= 10~), - dh-exec, - dpkg-dev (>= 1.16.1~), - libdb-dev, - quilt - -Package: blocklist -Architecture: any -Homepage: https://github.com/zoulasc/blocklist -Depends: ${misc:Depends}, - ${shlibs:Depends}, - libdb5.3 -Description: 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. diff --git a/contrib/blocklist/port/debian/install b/contrib/blocklist/port/debian/install deleted file mode 100644 index 6c5e1ac7126..00000000000 --- a/contrib/blocklist/port/debian/install +++ /dev/null @@ -1 +0,0 @@ -libexec/blocklistd-helper usr/libexec diff --git a/contrib/blocklist/port/debian/rules b/contrib/blocklist/port/debian/rules deleted file mode 100755 index 80c2d9c5a82..00000000000 --- a/contrib/blocklist/port/debian/rules +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/make -f - -# Uncomment this to turn on verbose mode. -# export DH_VERBOSE=1 - -# This has to be exported to make some magic below work. -export DH_OPTIONS - -%: - dh $@ --sourcedirectory=port --with quilt - -# https://lintian.debian.org/tags/non-empty-dependency_libs-in-la-file.html -override_dh_auto_install: - dh_auto_install - sed -i "/dependency_libs/ s/'.*'/''/" `find . -name '*.la'` diff --git a/contrib/blocklist/port/debian/source/format b/contrib/blocklist/port/debian/source/format deleted file mode 100644 index 89ae9db8f88..00000000000 --- a/contrib/blocklist/port/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) From 23358a9e82df423b559cf1fe6b1c3de9941e5a3c Mon Sep 17 00:00:00 2001 From: Lucas Holt Date: Tue, 22 Sep 2026 14:06:15 -0400 Subject: [PATCH 4/4] Rename blacklist to blocklist, following upstream Build the library, daemon and control program from contrib/blocklist under their new names: libblocklist(3), blocklistd(8) and blocklistctl(8), with /etc/blocklistd.conf, the blocklistd rc script, blocklistd_enable and blocklistd_flags in rc.conf, and the blocklistd-helper script. The build knobs are MK_BLOCKLIST and MK_BLOCKLIST_SUPPORT. Consumers move to the new API: sshd (UseBlocklist, with UseBlacklist kept as an alias), ftpd and fingerd now include blocklist.h and call blocklist_*(), and their client glue is renamed from blacklist.c to blocklist.c. The old names remain available during the transition, as FreeBSD did in commit 7238317403b9: libblacklist, blacklistd, blacklistctl and blacklistd-helper are built from the compatibility sources in contrib/blocklist, the blacklistd rc script still starts the old daemon but prints a warning, and WITHOUT_BLACKLIST and WITHOUT_BLACKLIST_SUPPORT are wired to the blocklist options. The periodic pf security check looks at both anchor names. Note the rename in UPDATING. Obtained from: FreeBSD 7238317403b95a8e35cf0bc7cd66fbd78ecbe521 AI-Assisted-by: Claude Fable 5.1 Signed-off-by: Lucas Holt --- UPDATING | 16 + contrib/blocklist/MIDNIGHTBSD-upgrade | 4 + contrib/blocklist/bin/blacklistctl.8 | 135 ++++++++ contrib/blocklist/bin/blacklistd.8 | 308 ++++++++++++++++++ contrib/blocklist/bin/blacklistd.conf.5 | 242 ++++++++++++++ contrib/blocklist/lib/libblacklist.3 | 188 +++++++++++ contrib/blocklist/port/config.h | 3 + crypto/openssh/auth-pam.c | 4 +- crypto/openssh/auth.c | 8 +- crypto/openssh/{blacklist.c => blocklist.c} | 16 +- ...{blacklist_client.h => blocklist_client.h} | 30 +- crypto/openssh/monitor.c | 8 +- crypto/openssh/servconf.c | 18 +- crypto/openssh/servconf.h | 2 +- crypto/openssh/sshd-session.c | 6 +- crypto/openssh/sshd_config | 2 +- crypto/openssh/sshd_config.5 | 14 +- lib/Makefile | 1 + lib/libblacklist/Makefile | 12 +- lib/libblocklist/Makefile | 29 ++ lib/libblocklist/Makefile.depend | 16 + lib/libsysdecode/Makefile.depend | 2 +- libexec/Makefile | 6 +- libexec/blacklistd-helper/Makefile | 6 - libexec/blocklistd-helper/Makefile | 8 + .../Makefile.depend | 0 libexec/blocklistd-helper/blacklistd-helper | 293 +++++++++++++++++ libexec/fingerd/Makefile | 8 +- libexec/fingerd/Makefile.depend.options | 2 +- libexec/fingerd/fingerd.c | 16 +- libexec/ftpd/Makefile | 10 +- libexec/ftpd/Makefile.depend.options | 2 +- libexec/ftpd/{blacklist.c => blocklist.c} | 18 +- ...{blacklist_client.h => blocklist_client.h} | 26 +- libexec/ftpd/ftpd.8 | 4 +- libexec/ftpd/ftpd.c | 20 +- libexec/rc/rc.conf | 6 +- libexec/rc/rc.d/Makefile | 5 + libexec/rc/rc.d/blacklistd | 12 +- libexec/rc/rc.d/blocklistd | 43 +++ secure/libexec/sshd-auth/Makefile | 10 +- secure/libexec/sshd-session/Makefile | 10 +- secure/usr.sbin/sshd/Makefile.depend.options | 2 +- share/man/man5/src.conf.5 | 43 ++- share/mk/bsd.libnames.mk | 1 + share/mk/local.dirdeps-options.mk | 1 + share/mk/src.libnames.mk | 11 +- share/mk/src.opts.mk | 22 ++ targets/pseudo/userland/Makefile.depend | 6 + targets/pseudo/userland/lib/Makefile.depend | 4 + .../pseudo/userland/libexec/Makefile.depend | 4 +- tools/build/mk/OptionalObsoleteFiles.inc | 21 +- tools/build/options/WITHOUT_BLACKLIST | 6 +- tools/build/options/WITHOUT_BLACKLIST_SUPPORT | 9 +- tools/build/options/WITHOUT_BLOCKLIST | 4 + tools/build/options/WITHOUT_BLOCKLIST_SUPPORT | 7 + usr.sbin/Makefile | 2 + usr.sbin/blacklistctl/Makefile | 14 +- usr.sbin/blacklistctl/Makefile.depend | 2 +- usr.sbin/blacklistd/Makefile | 16 +- usr.sbin/blacklistd/Makefile.depend | 2 +- usr.sbin/blocklistctl/Makefile | 20 ++ usr.sbin/blocklistctl/Makefile.depend | 20 ++ usr.sbin/blocklistd/Makefile | 21 ++ usr.sbin/blocklistd/Makefile.depend | 20 ++ usr.sbin/blocklistd/blocklistd.conf | 16 + usr.sbin/periodic/etc/security/520.pfdenied | 2 +- 67 files changed, 1667 insertions(+), 178 deletions(-) create mode 100644 contrib/blocklist/bin/blacklistctl.8 create mode 100644 contrib/blocklist/bin/blacklistd.8 create mode 100644 contrib/blocklist/bin/blacklistd.conf.5 create mode 100644 contrib/blocklist/lib/libblacklist.3 create mode 100644 contrib/blocklist/port/config.h rename crypto/openssh/{blacklist.c => blocklist.c} (89%) rename crypto/openssh/{blacklist_client.h => blocklist_client.h} (77%) create mode 100644 lib/libblocklist/Makefile create mode 100644 lib/libblocklist/Makefile.depend delete mode 100644 libexec/blacklistd-helper/Makefile create mode 100644 libexec/blocklistd-helper/Makefile rename libexec/{blacklistd-helper => blocklistd-helper}/Makefile.depend (100%) create mode 100644 libexec/blocklistd-helper/blacklistd-helper rename libexec/ftpd/{blacklist.c => blocklist.c} (84%) rename libexec/ftpd/{blacklist_client.h => blocklist_client.h} (78%) create mode 100755 libexec/rc/rc.d/blocklistd create mode 100644 tools/build/options/WITHOUT_BLOCKLIST create mode 100644 tools/build/options/WITHOUT_BLOCKLIST_SUPPORT create mode 100644 usr.sbin/blocklistctl/Makefile create mode 100644 usr.sbin/blocklistctl/Makefile.depend create mode 100644 usr.sbin/blocklistd/Makefile create mode 100644 usr.sbin/blocklistd/Makefile.depend create mode 100644 usr.sbin/blocklistd/blocklistd.conf diff --git a/UPDATING b/UPDATING index 4c4e8033a6d..277e70c7bd6 100644 --- a/UPDATING +++ b/UPDATING @@ -1,5 +1,21 @@ Updating Information for MidnightBSD users. +20260922: + blacklistd has been renamed to blocklistd, following upstream. + The library is now libblocklist(3) with blocklist_*() functions, + the daemon and control program are blocklistd(8) and + blocklistctl(8), the configuration file is /etc/blocklistd.conf, + the rc.conf knobs are blocklistd_enable and blocklistd_flags, and + the sshd_config option is UseBlocklist. The build options are + WITH[OUT]_BLOCKLIST and WITH[OUT]_BLOCKLIST_SUPPORT. + + The old names keep working for now: libblacklist, blacklistd, + blacklistctl, /etc/blacklistd.conf, the blacklistd rc script and + the old build options are all still provided, but they warn on + use and will be removed in a future release. Move your + configuration to the new names. Note that the last column of the + configuration file, formerly "disable", is now "duration". + 20260922: tcsh 6.24.16 (from 6.21.00). Adds $'...' strings with \x, \u, \U and \c escapes, the :Q modifier, $?<, jobs -Z, CLICOLOR_FORCE and diff --git a/contrib/blocklist/MIDNIGHTBSD-upgrade b/contrib/blocklist/MIDNIGHTBSD-upgrade index 37472b54bc2..8fe004fdc91 100644 --- a/contrib/blocklist/MIDNIGHTBSD-upgrade +++ b/contrib/blocklist/MIDNIGHTBSD-upgrade @@ -26,9 +26,13 @@ Files that are not upstream: bin/blacklistctl.c bin/blacklistd.c bin/old_internal.[ch] include/blacklist.h include/old_bl.h lib/blacklist.c lib/old_bl.c + bin/blacklistctl.8 bin/blacklistd.8 bin/blacklistd.conf.5 lib/libblacklist.3 Compatibility sources for the old blacklist names, taken from FreeBSD. They build lib/libblacklist, usr.sbin/blacklistd and usr.sbin/blacklistctl so existing configurations keep working with a warning. + port/config.h + Wrapper that pulls in port/port.h; upstream generates this with + autoconf. midnightbsd-changes.sh MIDNIGHTBSD-upgrade This file and the change script. diff --git a/contrib/blocklist/bin/blacklistctl.8 b/contrib/blocklist/bin/blacklistctl.8 new file mode 100644 index 00000000000..08f1d1b9e5a --- /dev/null +++ b/contrib/blocklist/bin/blacklistctl.8 @@ -0,0 +1,135 @@ +.\" $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 BLACKLISTCTL 8 +.Os +.Sh NAME +.Nm blacklistctl +.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 and change the state of the +.Xr blacklistd 8 +database. +The following sub-commands are supported: +.Ss dump +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 blacklistd +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 create 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 +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 blacklistd 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/blacklistd.8 b/contrib/blocklist/bin/blacklistd.8 new file mode 100644 index 00000000000..9ca886e9c4d --- /dev/null +++ b/contrib/blocklist/bin/blacklistd.8 @@ -0,0 +1,308 @@ +.\" $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 BLACKLISTD 8 +.Os +.Sh NAME +.Nm blacklistd +.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 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 +file descriptor associated with the connection the client wants to blacklist +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
+.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 blacklistd ) . +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
+.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/blacklistd-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/blacklistd.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 +.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 blacklistd . +.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/blacklistd-helper -compact +.It Pa /usr/libexec/blacklistd-helper +Shell script invoked to interface with the packet filter. +.It Pa /etc/blacklistd.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 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 +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas diff --git a/contrib/blocklist/bin/blacklistd.conf.5 b/contrib/blocklist/bin/blacklistd.conf.5 new file mode 100644 index 00000000000..d4ca6785d5b --- /dev/null +++ b/contrib/blocklist/bin/blacklistd.conf.5 @@ -0,0 +1,242 @@ +.\" $NetBSD: blocklistd.conf.5,v 1.9 2026/01/13 21:38:18 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 January 13, 2026 +.Dt BLACKLISTD.CONF 5 +.Os +.Sh NAME +.Nm blacklistd.conf +.Nd configuration file format for blacklistd +.Sh DESCRIPTION +The +.Nm +file contains configuration entries for +.Xr blacklistd 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 + [
|[/]:] +.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/blacklistd.conf -compact +.It Pa /etc/blacklistd.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 blacklistctl 8 , +.Xr blacklistd 8 +.Sh NOTES +The +.Nm +file has been renamed to +.Xr blocklistd.conf 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/lib/libblacklist.3 b/contrib/blocklist/lib/libblacklist.3 new file mode 100644 index 00000000000..5bc093c38f7 --- /dev/null +++ b/contrib/blocklist/lib/libblacklist.3 @@ -0,0 +1,188 @@ +.\" $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 LIBBLACKLIST 3 +.Os +.Sh NAME +.Nm blacklist_open , +.Nm blacklist_open2 , +.Nm blacklist_close , +.Nm blacklist_r , +.Nm blacklist , +.Nm blacklist_sa , +.Nm blacklist_sa_r +.Nd Blacklistd notification library +.Sh LIBRARY +.Lb libblacklist +.Sh SYNOPSIS +.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 +.Fn blacklist "int action" "int fd" "const char *msg" +.Ft int +.Fn blacklist_r "struct blacklist *cookie" "int action" "int fd" "const char *msg" +.Ft int +.Fn blacklist_sa "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" +.Ft int +.Fn blacklist_sa_r "struct blacklist *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 blacklistd 8 +about successful and failed remote connections so that blacklistd can +block or release port access to prevent Denial of Service attacks. +.Pp +The function +.Fn blacklist_open +creates the necessary state to communicate with +.Xr blacklistd 8 +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. +.Pp +The +.Fn blacklist +function sends a message to +.Xr blacklistd 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 BLACKLIST_ABUSIVE_BEHAVIOR" +.It Dv BLACKLIST_AUTH_FAIL +There was an unsuccessful authentication attempt. +.It Dv BLACKLIST_AUTH_OK +A user successfully authenticated. +.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 Dv BLACKLIST_BAD_USER +The sending daemon has determined the username +presented for authentication is invalid. +The +.Xr blacklistd 8 +daemon compares the username to a configured list of forbidden +usernames and +blocks the address immediately if a forbidden username matches. +(The +.Dv BLACKLIST_BAD_USER +support is not currently available.) +.El +.Pp +The +.Fn blacklist_r +function is more efficient because it keeps the blacklist state around. +.Pp +The +.Fn blacklist_sa +and +.Fn blacklist_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 blacklistd 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 blacklist_open +returns a cookie on success and +.Dv NULL +on failure setting +.Dv errno +to an appropriate value. +.Pp +The functions +.Fn blacklist , +.Fn blacklist_sa , +and +.Fn blacklist_sa_r +return +.Dv 0 +on success and +.Dv \-1 +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 +.Sh AUTHORS +.An Christos Zoulas diff --git a/contrib/blocklist/port/config.h b/contrib/blocklist/port/config.h new file mode 100644 index 00000000000..27f32636de0 --- /dev/null +++ b/contrib/blocklist/port/config.h @@ -0,0 +1,3 @@ +#if defined(__FreeBSD__) +#include "port.h" +#endif diff --git a/crypto/openssh/auth-pam.c b/crypto/openssh/auth-pam.c index 09efa0c6c6c..b7c7e940f2d 100644 --- a/crypto/openssh/auth-pam.c +++ b/crypto/openssh/auth-pam.c @@ -100,7 +100,7 @@ #endif #include "monitor_wrap.h" #include "srclimit.h" -#include "blacklist_client.h" +#include "blocklist_client.h" extern ServerOptions options; extern struct sshbuf *loginmsg; @@ -917,7 +917,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 0f77a3a7288..da1a674126d 100644 --- a/crypto/openssh/auth.c +++ b/crypto/openssh/auth.c @@ -73,7 +73,7 @@ #include "monitor_wrap.h" #include "ssherr.h" #include "channels.h" -#include "blacklist_client.h" +#include "blocklist_client.h" /* import */ extern ServerOptions options; @@ -287,7 +287,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"); } @@ -337,7 +337,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 ", @@ -498,7 +498,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 similarity index 89% rename from crypto/openssh/blacklist.c rename to crypto/openssh/blocklist.c index 33d02607dd9..f3c00016db6 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 -#include "blacklist_client.h" +#include +#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 similarity index 77% rename from crypto/openssh/blacklist_client.h rename to crypto/openssh/blocklist_client.h index 601a44461e2..be92245e469 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 1feab4ec89e..5994a7fc76d 100644 --- a/crypto/openssh/monitor.c +++ b/crypto/openssh/monitor.c @@ -75,7 +75,7 @@ #include "misc.h" #include "servconf.h" #include "monitor.h" -#include "blacklist_client.h" +#include "blocklist_client.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -350,7 +350,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 " @@ -359,12 +359,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 63b50ea3d9b..b3df3ffe634 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -215,7 +215,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. */ @@ -504,8 +504,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); @@ -590,7 +590,7 @@ typedef enum { sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sSshdSessionPath, sSshdAuthPath, sRefuseConnection, - sUseBlacklist, + sUseBlocklist, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -762,8 +762,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 } }; @@ -2779,8 +2779,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: @@ -3337,7 +3337,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 6830c31bde9..9f3db6e3b0a 100644 --- a/crypto/openssh/servconf.h +++ b/crypto/openssh/servconf.h @@ -256,7 +256,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 8366c5ba33d..a0dacc119c3 100644 --- a/crypto/openssh/sshd-session.c +++ b/crypto/openssh/sshd-session.c @@ -90,7 +90,7 @@ #include "ssh-gss.h" #endif #include "auth-options.h" -#include "blacklist_client.h" +#include "blocklist_client.h" #include "dh.h" #include "monitor_wrap.h" #include "sk-api.h" @@ -1155,7 +1155,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 @@ -1374,7 +1374,7 @@ cleanup_exit(int i) #endif /* Override default fatal exit value when auth was attempted */ if (i == 255 && monitor_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 04f77c66151..12919f75fc3 100644 --- a/crypto/openssh/sshd_config +++ b/crypto/openssh/sshd_config @@ -105,7 +105,7 @@ AuthorizedKeysFile .ssh/authorized_keys #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none -#UseBlacklist no +#UseBlocklist no #VersionAddendum MidnightBSD-20250324 # no default banner path diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index ac225aa91fb..c0e63f7bc3f 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -2052,20 +2052,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 239d6231615..20d45bdb491 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -164,6 +164,7 @@ SUBDIR_DEPEND_flua= libjail SUBDIR.${MK_ATM}+= libngatm 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 e8d25ac7f1b..f031ed01a77 100644 --- a/lib/libblacklist/Makefile +++ b/lib/libblacklist/Makefile @@ -1,7 +1,6 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist -BLACKLIST_DIR=${SRCTOP}/contrib/blacklist - -.PATH: ${BLACKLIST_DIR}/lib ${BLACKLIST_DIR}/include +.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include ${BLOCKLIST_DIR}/port LIB= blacklist SHLIB_MAJOR= 0 @@ -10,12 +9,13 @@ LIBADD+= pthread CFLAGS.clang+=-Wno-thread-safety-analysis -CFLAGS+=-I${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \ +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 00000000000..783b620aecc --- /dev/null +++ b/lib/libblocklist/Makefile @@ -0,0 +1,29 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist + +.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include ${BLOCKLIST_DIR}/port + +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 diff --git a/lib/libblocklist/Makefile.depend b/lib/libblocklist/Makefile.depend new file mode 100644 index 00000000000..577dc5747f1 --- /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 + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/lib/libsysdecode/Makefile.depend b/lib/libsysdecode/Makefile.depend index 93728767d4f..71e0b9b7095 100644 --- a/lib/libsysdecode/Makefile.depend +++ b/lib/libsysdecode/Makefile.depend @@ -33,7 +33,7 @@ DIRDEPS = \ lib/libalias/libalias \ lib/libarchive \ lib/libbegemot \ - lib/libblacklist \ + lib/libblocklist \ lib/libblocksruntime \ lib/libbluetooth \ lib/libbsdstat \ diff --git a/libexec/Makefile b/libexec/Makefile index 20d4883ec50..a0838cda22a 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -4,7 +4,7 @@ SUBDIR= ${_atf} \ ${_atrun} \ - ${_blacklistd-helper} \ + ${_blocklistd-helper} \ ${_comsat} \ ${_dma} \ flua \ @@ -48,8 +48,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 a22ba37fc76..00000000000 --- a/libexec/blacklistd-helper/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BLACKLIST_DIR=${SRCTOP}/contrib/blacklist - -SCRIPTS= ${BLACKLIST_DIR}/libexec/blacklistd-helper - -.include diff --git a/libexec/blocklistd-helper/Makefile b/libexec/blocklistd-helper/Makefile new file mode 100644 index 00000000000..25630ac8484 --- /dev/null +++ b/libexec/blocklistd-helper/Makefile @@ -0,0 +1,8 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist + +SCRIPTS= ${BLOCKLIST_DIR}/libexec/blocklistd-helper + +# Compatibility with the old blacklist name +SCRIPTS+= blacklistd-helper + +.include diff --git a/libexec/blacklistd-helper/Makefile.depend b/libexec/blocklistd-helper/Makefile.depend similarity index 100% rename from libexec/blacklistd-helper/Makefile.depend rename to libexec/blocklistd-helper/Makefile.depend diff --git a/libexec/blocklistd-helper/blacklistd-helper b/libexec/blocklistd-helper/blacklistd-helper new file mode 100644 index 00000000000..4195f070e8e --- /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 "" || \ + echo "block in quick $proto from 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 + /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 f0f797ad02d..a702706856c 100644 --- a/libexec/fingerd/Makefile +++ b/libexec/fingerd/Makefile @@ -9,10 +9,10 @@ MAN= fingerd.8 WARNS?= 2 WFORMAT=0 -.if ${MK_BLACKLIST_SUPPORT} != "no" -CFLAGS+= -DUSE_BLACKLIST -I${SRCTOP}/contrib/blacklist/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 diff --git a/libexec/fingerd/Makefile.depend.options b/libexec/fingerd/Makefile.depend.options index 5a94eff626d..f68343adae8 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 diff --git a/libexec/fingerd/fingerd.c b/libexec/fingerd/fingerd.c index dd51064a00a..e8376605e87 100644 --- a/libexec/fingerd/fingerd.c +++ b/libexec/fingerd/fingerd.c @@ -57,8 +57,8 @@ static char sccsid[] = "@(#)fingerd.c 8.1 (Berkeley) 6/4/93"; #include #include #include "pathnames.h" -#ifdef USE_BLACKLIST -#include +#ifdef USE_BLOCKLIST +#include #endif void logerr(const char *, ...) __printflike(1, 2) __dead2; @@ -156,8 +156,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); @@ -165,8 +165,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); @@ -206,8 +206,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/ftpd/Makefile b/libexec/ftpd/Makefile index bc35f995acf..40aedb0d98c 100644 --- a/libexec/ftpd/Makefile +++ b/libexec/ftpd/Makefile @@ -25,11 +25,11 @@ SRCS+= ls.c cmp.c print.c util.c CFLAGS+=-Dmain=ls_main -I${SRCTOP}/bin/ls LIBADD+= m -.if ${MK_BLACKLIST_SUPPORT} != "no" -CFLAGS+= -DUSE_BLACKLIST -I${SRCTOP}/contrib/blacklist/include -SRCS+= blacklist.c -LIBADD+= blacklist -LDFLAGS+=-L${LIBBLACKLISTDIR} +.if ${MK_BLOCKLIST_SUPPORT} != "no" +CFLAGS+= -DUSE_BLOCKLIST -I${SRCTOP}/contrib/blocklist/include +SRCS+= blocklist.c +LIBADD+= blocklist +LDFLAGS+=-L${LIBBLOCKLISTDIR} .endif .if ${MK_INET6_SUPPORT} != "no" diff --git a/libexec/ftpd/Makefile.depend.options b/libexec/ftpd/Makefile.depend.options index 5f186bb031f..f5b76378ab2 100644 --- a/libexec/ftpd/Makefile.depend.options +++ b/libexec/ftpd/Makefile.depend.options @@ -1,5 +1,5 @@ # This file is not autogenerated - take care! -DIRDEPS_OPTIONS= BLACKLIST_SUPPORT PAM_SUPPORT +DIRDEPS_OPTIONS= BLOCKLIST_SUPPORT PAM_SUPPORT .include diff --git a/libexec/ftpd/blacklist.c b/libexec/ftpd/blocklist.c similarity index 84% rename from libexec/ftpd/blacklist.c rename to libexec/ftpd/blocklist.c index 0a45f936907..159e76f021a 100644 --- a/libexec/ftpd/blacklist.c +++ b/libexec/ftpd/blocklist.c @@ -31,25 +31,25 @@ #include #include -#include -#include "blacklist_client.h" +#include +#include "blocklist_client.h" -static struct blacklist *blstate; -extern int use_blacklist; +static struct blocklist *blstate; +extern int use_blocklist; void -blacklist_init(void) +blocklist_init(void) { - if (use_blacklist) - blstate = blacklist_open(); + if (use_blocklist) + blstate = blocklist_open(); } void -blacklist_notify(int action, int fd, const char *msg) +blocklist_notify(int action, int fd, const char *msg) { if (blstate == NULL) return; - (void)blacklist_r(blstate, action, fd, msg); + (void)blocklist_r(blstate, action, fd, msg); } diff --git a/libexec/ftpd/blacklist_client.h b/libexec/ftpd/blocklist_client.h similarity index 78% rename from libexec/ftpd/blacklist_client.h rename to libexec/ftpd/blocklist_client.h index 0b6805dc218..9cca5674a71 100644 --- a/libexec/ftpd/blacklist_client.h +++ b/libexec/ftpd/blocklist_client.h @@ -26,28 +26,28 @@ * 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 + BLOCKLIST_AUTH_OK = 0, + BLOCKLIST_AUTH_FAIL }; #endif -#ifdef USE_BLACKLIST -void blacklist_init(void); -void blacklist_notify(int, int, const char *); +#ifdef USE_BLOCKLIST +void blocklist_init(void); +void blocklist_notify(int, int, const char *); -#define BLACKLIST_INIT() blacklist_init() -#define BLACKLIST_NOTIFY(x, y, z) blacklist_notify(x, y, z) +#define BLOCKLIST_INIT() blocklist_init() +#define BLOCKLIST_NOTIFY(x, y, z) blocklist_notify(x, y, z) #else -#define BLACKLIST_INIT() -#define BLACKLIST_NOTIFY(x, y, z) +#define BLOCKLIST_INIT() +#define BLOCKLIST_NOTIFY(x, y, z) #endif -#endif /* BLACKLIST_CLIENT_H */ +#endif /* BLOCKLIST_CLIENT_H */ diff --git a/libexec/ftpd/ftpd.8 b/libexec/ftpd/ftpd.8 index a6bf60af460..ec8937f6027 100644 --- a/libexec/ftpd/ftpd.8 +++ b/libexec/ftpd/ftpd.8 @@ -108,9 +108,9 @@ is specified, accept connections only on the specified With this option set, .Nm sends authentication success and failure messages to the -.Xr blacklistd 8 +.Xr blocklistd 8 daemon. If this option is not specified, no communcation with the -.Xr blacklistd 8 +.Xr blocklistd 8 daemon is attempted. .It Fl D With this option set, diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index d031d8815fd..2191ba66629 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -93,7 +93,7 @@ static char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94"; #include #endif -#include "blacklist_client.h" +#include "blocklist_client.h" #include "pathnames.h" #include "extern.h" @@ -141,7 +141,7 @@ int noretr = 0; /* RETR command is disabled. */ int noguestretr = 0; /* RETR command is disabled for anon users. */ int noguestmkd = 0; /* MKD command is disabled for anon users. */ int noguestmod = 1; /* anon users may not modify existing files. */ -int use_blacklist = 0; +int use_blocklist = 0; off_t file_size; off_t byte_count; @@ -312,10 +312,10 @@ main(int argc, char *argv[], char **envp) break; case 'B': -#ifdef USE_BLACKLIST - use_blacklist = 1; +#ifdef USE_BLOCKLIST + use_blocklist = 1; #else - syslog(LOG_WARNING, "not compiled with USE_BLACKLIST support"); + syslog(LOG_WARNING, "not compiled with USE_BLOCKLIST support"); #endif break; @@ -640,7 +640,7 @@ main(int argc, char *argv[], char **envp) reply(220, "%s FTP server (%s) ready.", hostname, version); else reply(220, "FTP server ready."); - BLACKLIST_INIT(); + BLOCKLIST_INIT(); for (;;) (void) yyparse(); /* NOTREACHED */ @@ -1052,7 +1052,7 @@ user(char *name) (checkuser(_PATH_FTPUSERS, name, 1, NULL, &ecode) || (ecode != 0 && ecode != ENOENT))) { reply(530, "User %s access denied.", name); - BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, STDIN_FILENO, "Access denied"); + BLOCKLIST_NOTIFY(BLOCKLIST_AUTH_FAIL, STDIN_FILENO, "Access denied"); if (logging) syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s", @@ -1417,7 +1417,7 @@ pass(char *passwd) */ if (rval) { reply(530, "Login incorrect."); - BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, STDIN_FILENO, "Login incorrect"); + BLOCKLIST_NOTIFY(BLOCKLIST_AUTH_FAIL, STDIN_FILENO, "Login incorrect"); if (logging) { syslog(LOG_NOTICE, "FTP LOGIN FAILED FROM %s", @@ -1435,7 +1435,7 @@ pass(char *passwd) } return; } else { - BLACKLIST_NOTIFY(BLACKLIST_AUTH_OK, STDIN_FILENO, "Login successful"); + BLOCKLIST_NOTIFY(BLOCKLIST_AUTH_OK, STDIN_FILENO, "Login successful"); } } login_attempts = 0; /* this time successful */ @@ -1455,7 +1455,7 @@ pass(char *passwd) *remote_ip = 0; remote_ip[sizeof(remote_ip) - 1] = 0; if (!auth_hostok(lc, remotehost, remote_ip)) { - BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, STDIN_FILENO, "Permission denied"); + BLOCKLIST_NOTIFY(BLOCKLIST_AUTH_FAIL, STDIN_FILENO, "Permission denied"); syslog(LOG_INFO|LOG_AUTH, "FTP LOGIN FAILED (HOST) as %s: permission denied.", pw->pw_name); diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index 9c176e46180..d800f36c6ab 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -324,8 +324,10 @@ hastd_flags="" # Optional flags to hastd. ctld_enable="NO" # CAM Target Layer / iSCSI target daemon. local_unbound_enable="NO" # Local caching resolver 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). mdnsd_enable="NO" # Run mdnsd, multicast DNS (or NO). mdnsresponder_enable="NO" # Run mdnsresponder (or NO). resolv_enable="YES" # Enable resolv / resolvconf diff --git a/libexec/rc/rc.d/Makefile b/libexec/rc/rc.d/Makefile index 695613a07f8..30abdde52b5 100644 --- a/libexec/rc/rc.d/Makefile +++ b/libexec/rc/rc.d/Makefile @@ -16,6 +16,7 @@ CONFS= DAEMON \ archdep \ bgfsck \ ${_blacklistd} \ + ${_blocklistd} \ bridge \ cfumass \ cleanvar \ @@ -183,6 +184,10 @@ CONFS+= autounmountd _blacklistd+= blacklistd .endif +.if ${MK_BLOCKLIST} != "no" +_blocklistd+= blocklistd +.endif + .if ${MK_BLUETOOTH} != "no" CONFGROUPS+= BLUETOOTH BLUETOOTH+= bluetooth \ diff --git a/libexec/rc/rc.d/blacklistd b/libexec/rc/rc.d/blacklistd index 44a97ad4b3b..e7c26716b20 100755 --- a/libexec/rc/rc.d/blacklistd +++ b/libexec/rc/rc.d/blacklistd @@ -29,15 +29,23 @@ # # PROVIDE: blacklistd -# REQUIRE: netif pf +# REQUIRE: netif ipfilter ipfw pf . /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" + +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 100755 index 00000000000..19451e10ff5 --- /dev/null +++ b/libexec/rc/rc.d/blocklistd @@ -0,0 +1,43 @@ +#!/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 ipfilter ipfw pf + +. /etc/rc.subr + +name="blocklistd" +desc="System blocklist daemon" +rcvar="blocklistd_enable" +command="/usr/sbin/${name}" +required_files="/etc/blocklistd.conf" + +load_rc_config $name +run_rc_command "$1" diff --git a/secure/libexec/sshd-auth/Makefile b/secure/libexec/sshd-auth/Makefile index fbac25ac2a9..46667fac52e 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/blacklist/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_GSSAPI} != "no" && ${MK_KERBEROS_SUPPORT} != "no" diff --git a/secure/libexec/sshd-session/Makefile b/secure/libexec/sshd-session/Makefile index 71594326a4b..4fc165be9f2 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/blacklist/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_GSSAPI} != "no" && ${MK_KERBEROS_SUPPORT} != "no" diff --git a/secure/usr.sbin/sshd/Makefile.depend.options b/secure/usr.sbin/sshd/Makefile.depend.options index 69af5a2e8d7..c8816eb881f 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 diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index f91344b57ce..36515401894 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,6 +1,6 @@ .\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman. .\" $FreeBSD$ -.Dd September 4, 2026 +.Dd September 22, 2026 .Dt SRC.CONF 5 .Os .Sh NAME @@ -200,10 +200,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 @@ -211,10 +216,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 , .Xr ftpd 8 , diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 88c766b8fdd..fdae820e419 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -26,6 +26,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 5f414adf36a..6e0fee74737 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 201146c106d..333738d9a2e 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -235,8 +235,11 @@ _LIBRARIES= \ .if ${MK_BLACKLIST} != "no" _LIBRARIES+= \ - blacklist \ - + blacklist +.endif +.if ${MK_BLOCKLIST} != "no" +_LIBRARIES+= \ + blocklist .endif .if ${MK_OFED} != "no" @@ -285,6 +288,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} == "MidnightBSD" || !defined(BOOTSTRAPPING) @@ -734,6 +740,7 @@ LIBGTESTDIR= ${OBJTOP}/lib/googletest/gtest LIBGTEST_MAINDIR= ${OBJTOP}/lib/googletest/gtest_main LIBALIASDIR= ${OBJTOP}/lib/libalias/libalias LIBBLACKLISTDIR= ${OBJTOP}/lib/libblacklist +LIBBLOCKLISTDIR= ${OBJTOP}/lib/libblocklist LIBBLOCKSRUNTIMEDIR= ${OBJTOP}/lib/libblocksruntime LIBMPORTDIR= ${OBJTOP}/lib/libmport LIBMSEARCHDIR= ${OBJTOP}/lib/libmsearch diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 8c6605043b3..1e762286cd3 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -61,6 +61,7 @@ __DEFAULT_YES_OPTIONS = \ AUTOFS \ BHYVE \ BLACKLIST \ + BLOCKLIST \ BLUETOOTH \ BOOT \ BOOTPARAMD \ @@ -231,6 +232,7 @@ __DEFAULT_DEPENDENT_OPTIONS= \ # .for var in \ BLACKLIST \ + BLOCKLIST \ BZIP2 \ INET \ INET6 \ @@ -487,6 +489,26 @@ MK_${vv:H}:= ${MK_${vv:T}} .endif .endfor +# +# The blacklist knobs are kept as aliases for the blocklist ones +# during the rename transition. +# +.if ${MK_BLACKLIST} == "no" +MK_BLOCKLIST:= no +.endif + +.if ${MK_BLACKLIST_SUPPORT} == "no" +MK_BLOCKLIST_SUPPORT:= no +.endif + +.if ${MK_BLOCKLIST} == "no" +MK_BLACKLIST:= no +.endif + +.if ${MK_BLOCKLIST_SUPPORT} == "no" +MK_BLACKLIST_SUPPORT:= no +.endif + # # Set defaults for the MK_*_SUPPORT variables. # diff --git a/targets/pseudo/userland/Makefile.depend b/targets/pseudo/userland/Makefile.depend index 7c50bec8267..9add8cd4aa9 100644 --- a/targets/pseudo/userland/Makefile.depend +++ b/targets/pseudo/userland/Makefile.depend @@ -831,6 +831,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 dc1dd7ba1b2..b9e9e2ae41c 100644 --- a/targets/pseudo/userland/lib/Makefile.depend +++ b/targets/pseudo/userland/lib/Makefile.depend @@ -254,4 +254,8 @@ DIRDEPS+= \ DIRDEPS+= lib/libblacklist .endif +.if ${MK_BLOCKLIST_SUPPORT} != "no" +DIRDEPS+= lib/libblocklist +.endif + .include diff --git a/targets/pseudo/userland/libexec/Makefile.depend b/targets/pseudo/userland/libexec/Makefile.depend index af5e6f262aa..402d4307b5e 100644 --- a/targets/pseudo/userland/libexec/Makefile.depend +++ b/targets/pseudo/userland/libexec/Makefile.depend @@ -55,8 +55,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/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index c1aa20b19c6..4fcb5c4e714 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -196,7 +196,26 @@ OLD_FILES+=usr/share/man/man1/ld.1.gz .endif .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 c54c83f2755..df9c9a41227 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 2bf22ea42ab..cd484727d63 100644 --- a/tools/build/options/WITHOUT_BLACKLIST_SUPPORT +++ b/tools/build/options/WITHOUT_BLACKLIST_SUPPORT @@ -1,7 +1,2 @@ -Build some programs without -.Xr libblacklist 3 -support, like -.Xr fingerd 8 , -.Xr ftpd 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 00000000000..c456a98c672 --- /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 00000000000..e29d3454180 --- /dev/null +++ b/tools/build/options/WITHOUT_BLOCKLIST_SUPPORT @@ -0,0 +1,7 @@ +Build some programs without +.Xr libblocklist 3 +support, like +.Xr fingerd 8 , +.Xr ftpd 8 , +and +.Xr sshd 8 . diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 80c88e4576e..030d6f6dd1b 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -123,6 +123,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 effba676115..0fa0f9990e1 100644 --- a/usr.sbin/blacklistctl/Makefile +++ b/usr.sbin/blacklistctl/Makefile @@ -1,21 +1,21 @@ - -BLACKLIST_DIR=${SRCTOP}/contrib/blacklist -.PATH: ${BLACKLIST_DIR}/bin ${BLACKLIST_DIR}/port +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist +.PATH: ${BLOCKLIST_DIR}/bin ${BLOCKLIST_DIR}/port 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${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \ +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 diff --git a/usr.sbin/blacklistctl/Makefile.depend b/usr.sbin/blacklistctl/Makefile.depend index 022282c2ed3..88f44bab57d 100644 --- a/usr.sbin/blacklistctl/Makefile.depend +++ b/usr.sbin/blacklistctl/Makefile.depend @@ -6,7 +6,7 @@ DIRDEPS = \ include/arpa \ include/xlocale \ lib/${CSU_DIR} \ - lib/libblacklist \ + lib/libblocklist \ lib/libc \ lib/libcompiler_rt \ lib/libthr \ diff --git a/usr.sbin/blacklistd/Makefile b/usr.sbin/blacklistd/Makefile index a33ea1d285b..08105d99e5e 100644 --- a/usr.sbin/blacklistd/Makefile +++ b/usr.sbin/blacklistd/Makefile @@ -1,22 +1,22 @@ - -BLACKLIST_DIR=${SRCTOP}/contrib/blacklist -.PATH: ${BLACKLIST_DIR}/bin ${BLACKLIST_DIR}/port +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist +.PATH: ${BLOCKLIST_DIR}/bin ${BLOCKLIST_DIR}/port 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${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \ +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 diff --git a/usr.sbin/blacklistd/Makefile.depend b/usr.sbin/blacklistd/Makefile.depend index 022282c2ed3..88f44bab57d 100644 --- a/usr.sbin/blacklistd/Makefile.depend +++ b/usr.sbin/blacklistd/Makefile.depend @@ -6,7 +6,7 @@ DIRDEPS = \ include/arpa \ include/xlocale \ lib/${CSU_DIR} \ - lib/libblacklist \ + lib/libblocklist \ lib/libc \ lib/libcompiler_rt \ lib/libthr \ diff --git a/usr.sbin/blocklistctl/Makefile b/usr.sbin/blocklistctl/Makefile new file mode 100644 index 00000000000..71e724faa5c --- /dev/null +++ b/usr.sbin/blocklistctl/Makefile @@ -0,0 +1,20 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist +.PATH: ${BLOCKLIST_DIR}/bin ${BLOCKLIST_DIR}/port + +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 diff --git a/usr.sbin/blocklistctl/Makefile.depend b/usr.sbin/blocklistctl/Makefile.depend new file mode 100644 index 00000000000..88f44bab57d --- /dev/null +++ b/usr.sbin/blocklistctl/Makefile.depend @@ -0,0 +1,20 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + include \ + include/arpa \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libblocklist \ + lib/libc \ + lib/libcompiler_rt \ + lib/libthr \ + lib/libutil \ + + +.include + +.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 00000000000..118a2a1e5f0 --- /dev/null +++ b/usr.sbin/blocklistd/Makefile @@ -0,0 +1,21 @@ +BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist +.PATH: ${BLOCKLIST_DIR}/bin ${BLOCKLIST_DIR}/port + +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 diff --git a/usr.sbin/blocklistd/Makefile.depend b/usr.sbin/blocklistd/Makefile.depend new file mode 100644 index 00000000000..88f44bab57d --- /dev/null +++ b/usr.sbin/blocklistd/Makefile.depend @@ -0,0 +1,20 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + include \ + include/arpa \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libblocklist \ + lib/libc \ + lib/libcompiler_rt \ + lib/libthr \ + lib/libutil \ + + +.include + +.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 00000000000..72f114290d9 --- /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 * * * = * * +#6161 = = = =/24 = = +#* stream tcp * = = = diff --git a/usr.sbin/periodic/etc/security/520.pfdenied b/usr.sbin/periodic/etc/security/520.pfdenied index 13ed37b368d..1ee03eb4be3 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) + for _a in "" $(pfctl -a "blacklistd" -sA 2>/dev/null) $(pfctl -a "blocklistd" -sA 2>/dev/null) 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}