svn commit: r362196 - in vendor: NetBSD/blacklist blocklist blocklist/dist/bin blocklist/dist/etc blocklist/dist/etc/rc.d blocklist/dist/include blocklist/dist/lib blocklist/dist/libexec
Ed Maste
emaste at FreeBSD.org
Mon Jun 15 13:17:23 UTC 2020
Author: emaste
Date: Mon Jun 15 13:17:22 2020
New Revision: 362196
URL: https://svnweb.freebsd.org/changeset/base/362196
Log:
Following upstream, rename blacklist to blocklist
Also move up one level from vendor/NetBSD/blacklist to vendor/blocklist,
as this is now has a standalone home at
https://github.com/zoulasc/blocklist
I also renamed the individual files under dist/ so that the subsequent
update from upstream will drop in.
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Added:
vendor/blocklist/
- copied from r362195, vendor/NetBSD/blacklist/
vendor/blocklist/dist/bin/blocklistctl.8
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistctl.8
vendor/blocklist/dist/bin/blocklistctl.c
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistctl.c
vendor/blocklist/dist/bin/blocklistd.8
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.8
vendor/blocklist/dist/bin/blocklistd.c
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.c
vendor/blocklist/dist/bin/blocklistd.conf.5
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.conf.5
vendor/blocklist/dist/etc/blocklistd.conf
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/etc/blacklistd.conf
vendor/blocklist/dist/etc/rc.d/blocklistd
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/etc/rc.d/blacklistd
vendor/blocklist/dist/include/blocklist.h
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/include/blacklist.h
vendor/blocklist/dist/lib/blocklist.c
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/lib/blacklist.c
vendor/blocklist/dist/lib/libblocklist.3
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/lib/libblacklist.3
vendor/blocklist/dist/libexec/blocklistd-helper
- copied unchanged from r362194, vendor/NetBSD/blacklist/dist/libexec/blacklistd-helper
Deleted:
vendor/NetBSD/blacklist/
vendor/blocklist/dist/bin/blacklistctl.8
vendor/blocklist/dist/bin/blacklistctl.c
vendor/blocklist/dist/bin/blacklistd.8
vendor/blocklist/dist/bin/blacklistd.c
vendor/blocklist/dist/bin/blacklistd.conf.5
vendor/blocklist/dist/etc/blacklistd.conf
vendor/blocklist/dist/etc/rc.d/blacklistd
vendor/blocklist/dist/include/blacklist.h
vendor/blocklist/dist/lib/blacklist.c
vendor/blocklist/dist/lib/libblacklist.3
vendor/blocklist/dist/libexec/blacklistd-helper
Copied: vendor/blocklist/dist/bin/blocklistctl.8 (from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistctl.8)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/blocklist/dist/bin/blocklistctl.8 Mon Jun 15 13:17:22 2020 (r362196, copy of r362194, vendor/NetBSD/blacklist/dist/bin/blacklistctl.8)
@@ -0,0 +1,86 @@
+.\" $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
Copied: vendor/blocklist/dist/bin/blocklistctl.c (from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistctl.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/blocklist/dist/bin/blocklistctl.c Mon Jun 15 13:17:22 2020 (r362196, copy of r362194, vendor/NetBSD/blacklist/dist/bin/blacklistctl.c)
@@ -0,0 +1,168 @@
+/* $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 <sys/cdefs.h>
+__RCSID("$NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $");
+
+#include <stdio.h>
+#include <time.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <fcntl.h>
+#include <string.h>
+#include <syslog.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "conf.h"
+#include "state.h"
+#include "internal.h"
+#include "support.h"
+
+static __dead void
+usage(int c)
+{
+ if (c == 0)
+ warnx("Missing/unknown command");
+ else
+ 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;
+}
Copied: vendor/blocklist/dist/bin/blocklistd.8 (from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.8)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/blocklist/dist/bin/blocklistd.8 Mon Jun 15 13:17:22 2020 (r362196, copy of r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.8)
@@ -0,0 +1,227 @@
+.\" $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 June 7, 2016
+.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 <rulename> <proto> <address> <mask> <port>
+.Ed
+.Pp
+and should invoke a packet filter command to block the connection
+specified by the arguments.
+The
+.Ar rulename
+argument can be set from the command line (default
+.Dv 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 <rulename> <proto> <address> <mask> <port> <id>
+.Ed
+.Pp
+where
+.Ar id
+is the number returned from the
+.Dq add
+action.
+.Pp
+.Nm
+maintains a database of known connections in
+.Ar dbfile .
+On startup it reads entries from that file, and updates its internal state.
+.Pp
+.Nm
+checks the list of active entries every
+.Ar timeout
+seconds (default
+.Dv 15 )
+and removes entries and block rules using the control program as necessary.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl C Ar controlprog
+Use
+.Ar controlprog
+to communicate with the packet filter, usually
+.Pa /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/run/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 <rulename>
+.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 don't 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 FILES
+.Bl -tag -width /libexec/blacklistd-helper -compact
+.It Pa /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 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
Copied: vendor/blocklist/dist/bin/blocklistd.c (from r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/blocklist/dist/bin/blocklistd.c Mon Jun 15 13:17:22 2020 (r362196, copy of r362194, vendor/NetBSD/blacklist/dist/bin/blacklistd.c)
@@ -0,0 +1,568 @@
+/* $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 <sys/cdefs.h>
+__RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <inttypes.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+
+#include "bl.h"
+#include "internal.h"
+#include "conf.h"
+#include "run.h"
+#include "state.h"
+#include "support.h"
+
+static const char *configfile = _PATH_BLCONF;
+static DB *state;
+static const char *dbfile = _PATH_BLSTATE;
+static sig_atomic_t readconf;
+static sig_atomic_t done;
+static int vflag;
+
+static void
+sigusr1(int n __unused)
+{
+ debug++;
+}
+
+static void
+sigusr2(int n __unused)
+{
+ debug--;
+}
+
+static void
+sighup(int n __unused)
+{
+ readconf++;
+}
+
+static void
+sigdone(int n __unused)
+{
+ done++;
+}
+
+static __dead void
+usage(int c)
+{
+ if (c)
+ warnx("Unknown option `%c'", (char)c);
+ fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] "
+ "[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] "
+ "[-s <sockpath>] [-t <timeout>]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static int
+getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl)
+{
+ *rsl = sizeof(*rss);
+ memset(rss, 0, *rsl);
+
+ if (getpeername(bi->bi_fd, (void *)rss, rsl) != -1)
+ return 0;
+
+ if (errno != ENOTCONN) {
+ (*lfun)(LOG_ERR, "getpeername failed (%m)");
+ return -1;
+ }
+
+ if (bi->bi_slen == 0) {
+ (*lfun)(LOG_ERR, "unconnected socket with no peer in message");
+ return -1;
+ }
+
+ switch (bi->bi_ss.ss_family) {
+ case AF_INET:
+ *rsl = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ *rsl = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ (*lfun)(LOG_ERR, "bad client passed socket family %u",
+ (unsigned)bi->bi_ss.ss_family);
+ return -1;
+ }
+
+ if (*rsl != bi->bi_slen) {
+ (*lfun)(LOG_ERR, "bad client passed socket length %u != %u",
+ (unsigned)*rsl, (unsigned)bi->bi_slen);
+ return -1;
+ }
+
+ memcpy(rss, &bi->bi_ss, *rsl);
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (*rsl != rss->ss_len) {
+ (*lfun)(LOG_ERR,
+ "bad client passed socket internal length %u != %u",
+ (unsigned)*rsl, (unsigned)rss->ss_len);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static void
+process(bl_t bl)
+{
+ struct sockaddr_storage rss;
+ socklen_t rsl;
+ char rbuf[BUFSIZ];
+ bl_info_t *bi;
+ struct conf c;
+ struct dbinfo dbi;
+ struct timespec ts;
+
+ 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_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;
+ 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);
+ syslog(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 = realloc(*blp, sizeof(**blp) * *maxfd);
+ if (*blp == NULL)
+ err(EXIT_FAILURE, "malloc");
+ *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd);
+ if (*pfdp == NULL)
+ err(EXIT_FAILURE, "malloc");
+ }
+
+ (*pfdp)[*nfd].fd = bl_getfd(bl);
+ (*pfdp)[*nfd].events = POLLIN;
+ (*blp)[*nfd] = bl;
+ *nfd += 1;
+}
+
+static void
+uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c)
+{
+ struct conf **list = *listp;
+
+ if (c->c_name[0] == '\0')
+ return;
+ for (size_t i = 0; i < *nlist; i++) {
+ if (strcmp(list[i]->c_name, c->c_name) == 0)
+ return;
+ }
+ if (*nlist == *mlist) {
+ *mlist += 10;
+ void *p = realloc(*listp, *mlist * sizeof(*list));
+ if (p == NULL)
+ err(EXIT_FAILURE, "Can't allocate for rule list");
+ list = *listp = p;
+ }
+ list[(*nlist)++] = c;
+}
+
+static void
+rules_flush(void)
+{
+ struct conf **list;
+ size_t nlist, mlist;
+
+ list = NULL;
+ mlist = nlist = 0;
+ for (size_t i = 0; i < rconf.cs_n; i++)
+ uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]);
+ for (size_t i = 0; i < lconf.cs_n; i++)
+ uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]);
+
+ for (size_t i = 0; i < nlist; i++)
+ run_flush(list[i]);
+ free(list);
+}
+
+static void
+rules_restore(void)
+{
+ 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 = realloc(blsock,
+ sizeof(*blsock) * maxblsock);
+ if (p == NULL)
+ err(EXIT_FAILURE,
+ "Can't allocate memory for %zu sockets",
+ maxblsock);
+ blsock = p;
+ }
+ blsock[nblsock++] = optarg;
+ break;
+ case 't':
+ tout = atoi(optarg) * 1000;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage(c);
+ }
+ }
+
+ argc -= optind;
+ if (argc)
+ usage(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");
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list