Reviewed by: rpaulo

Approved by:	rpaulo
Obtained from:	NetBSD external/bsd/blacklist @ 20160409
Relnotes:		YES
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D5912
This commit is contained in:
Kurt Lidl 2016-06-01 21:48:22 +00:00
commit df0cfa3b86
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/NetBSD/blacklist/dist/; revision=301169
svn path=/vendor/NetBSD/blacklist/20160409/; revision=301170; tag=vendor/NetBSD/blacklist/20160409
58 changed files with 7239 additions and 0 deletions

5
Makefile Normal file
View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.2 2015/01/22 17:49:41 christos Exp $
SUBDIR = lib .WAIT include bin etc libexec
.include <bsd.subdir.mk>

10
Makefile.inc Normal file
View File

@ -0,0 +1,10 @@
# $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

103
README Normal file
View File

@ -0,0 +1,103 @@
# $NetBSD: README,v 1.7 2015/01/26 00:34:50 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"
...
}
Enjoy,
christos

21
TODO Normal file
View File

@ -0,0 +1,21 @@
# $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?
<bge0/4>? 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

15
bin/Makefile Normal file
View File

@ -0,0 +1,15 @@
# $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 <bsd.prog.mk>

81
bin/blacklistctl.8 Normal file
View File

@ -0,0 +1,81 @@
.\" $NetBSD: blacklistctl.8,v 1.7 2015/04/30 06:20:43 riz 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 April 29, 2015
.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
appeared in
.Nx 7 .
.Sh AUTHORS
.An Christos Zoulas

151
bin/blacklistctl.c Normal file
View File

@ -0,0 +1,151 @@
/* $NetBSD: blacklistctl.c,v 1.20 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 <sys/cdefs.h>
__RCSID("$NetBSD: blacklistctl.c,v 1.20 2016/04/04 15:52:56 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);
}
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;
case 'D':
dbname = optarg;
break;
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];
if (!all) {
if (blocked) {
if (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/%d:%d\t", wide, wide, buf, c.c_lmask, c.c_port);
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/%d\t%-s\n", dbi.id, dbi.count, c.c_nfail, buf);
}
state_close(db);
return EXIT_SUCCESS;
}

222
bin/blacklistd.8 Normal file
View File

@ -0,0 +1,222 @@
.\" $NetBSD: blacklistd.8,v 1.15 2016/03/11 17:16:40 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 June 4, 2015
.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 a 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
appeared in
.Nx 7 .
.Sh AUTHORS
.An Christos Zoulas

537
bin/blacklistd.c Normal file
View File

@ -0,0 +1,537 @@
/* $NetBSD: blacklistd.c,v 1.34 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 <sys/cdefs.h>
__RCSID("$NetBSD: blacklistd.c,v 1.34 2016/04/04 15:52:56 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: db state info 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.last = 0;
break;
default:
(*lfun)(LOG_ERR, "unknown message %d", bi->bi_type);
}
if (state_put(state, &c, &dbi) == -1)
goto out;
out:
close(bi->bi_fd);
}
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("rem", &c, dbi.id, 0);
(void)run_change("add", &c, dbi.id, sizeof(dbi.id));
}
}
int
main(int argc, char *argv[])
{
int c, tout, flags, flush, restore;
const char *spath, *blsock;
setprogname(argv[0]);
spath = NULL;
blsock = _PATH_BLSOCK;
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':
blsock = 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();
flags |= O_TRUNC;
}
if (restore)
rules_restore();
struct pollfd *pfd = NULL;
bl_t *bl = NULL;
size_t nfd = 0;
size_t maxfd = 0;
if (spath == NULL)
addfd(&pfd, &bl, &nfd, &maxfd, blsock);
else {
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);
}
state = state_open(dbfile, flags, 0600);
if (state == NULL)
state = state_open(dbfile, flags | O_CREAT, 0600);
if (state == NULL)
return 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);
}
switch (poll(pfd, (nfds_t)nfd, tout)) {
case -1:
if (errno == EINTR)
continue;
(*lfun)(LOG_ERR, "poll (%m)");
return EXIT_FAILURE;
case 0:
state_sync(state);
break;
default:
for (size_t i = 0; i < nfd; i++)
if (pfd[i].revents & POLLIN)
process(bl[i]);
}
if (t % 100 == 0)
state_sync(state);
if (t % 10000 == 0)
update_interfaces();
update();
}
state_close(state);
return 0;
}

222
bin/blacklistd.conf.5 Normal file
View File

@ -0,0 +1,222 @@
.\" $NetBSD: blacklistd.conf.5,v 1.3 2015/04/30 06:20:43 riz 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 April 29, 2015
.Dt BLACKLISTD.CONF 5
.Os
.Sh NAME
.Nm blacklistd.conf
.Nd configuration file format for blacklistd
.Sh DESCRIPTION
The
.Nm
files contains configuration lines for
.Xr blacklistd 8 .
It contains one entry per line, and is similar to
.Xr inetd.conf 5 .
There must be an entry for each field of the configuration file, with
entries for each field separated by a tab or a space.
Comments are denoted by a
.Dq #
at the beginning of a line.
.Pp
There are two kinds of configuration lines,
.Va local
and
.Va remote .
By default, configuration lines are
.Va local ,
i.e. the address specified refers to the addresses on the local machine.
To switch to between
.Va local
and
.Va remote
configuration lines you can specify the stanzas:
.Dq [local]
and
.Dq [remote] .
.Pp
On
.Va local
and
.Va remote
lines
.Dq *
means use the default, or wildcard match.
In addition, for
.Va remote
lines
.Dq =
means use the values from the matched
.Va local
configuration line.
.Pp
The first four fields,
.Va location ,
.Va type ,
.Va proto ,
and
.Va owner
are used to match the
.Va local
or
.Va remote
addresses, whereas the last 3 fields
.Va name ,
.Va nfail ,
and
.Va disable
are used to modify the filtering action.
.Pp
The first field denotes the
.Va location
as an address, mask, and port.
The syntax for the
.Va location
is:
.Bd -literal -offset indent
[<address>|<interface>][/<mask>][:<port>]
.Ed
.Pp
The
.Dv address
can be an IPv4 address in numeric format, an IPv6 address
in numeric format and enclosed by square brackets, or an interface name.
Mask modifiers are not allowed on interfaces because interfaces
have multiple address 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 prococol :
.Dv tcp ,
.Dv udp ,
.Dv tcp6 ,
.Dv udp6 ,
or numeric.
The fourth file 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 are controlling 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, so one can block whole
subnets for a single rule violation.
.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 one by one, from the most specific to the least specific.
If a match is found, then the
.Va remote
rules are applied, and if a match is found 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, or the rule that the packet filter uses, the number of failed attempts,
or the blocked duration.
.Sh FILES
.Bl -tag -width /etc/blacklistd.conf -compact
.It Pa /etc/blacklistd.conf
Configuration file.
.El
.Sh EXAMPLES
.Bd -literal -offset
# 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
appeared in
.Nx 7 .
.Sh AUTHORS
.An Christos Zoulas

1142
bin/conf.c Normal file

File diff suppressed because it is too large Load Diff

65
bin/conf.h Normal file
View File

@ -0,0 +1,65 @@
/* $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 <sys/socket.h>
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 */

48
bin/internal.c Normal file
View File

@ -0,0 +1,48 @@
/* $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 <sys/cdefs.h>
__RCSID("$NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $");
#include <stdio.h>
#include <syslog.h>
#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;

57
bin/internal.h Normal file
View File

@ -0,0 +1,57 @@
/* $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 */

156
bin/run.c Normal file
View File

@ -0,0 +1,156 @@
/* $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 <sys/cdefs.h>
__RCSID("$NetBSD: run.c,v 1.14 2016/04/04 15:52:56 christos Exp $");
#include <stdio.h>
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#include <stdarg.h>
#include <limits.h>
#include <stdlib.h>
#include <inttypes.h>
#include <syslog.h>
#include <string.h>
#include <netinet/in.h>
#include <net/if.h>
#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;
va_list ap;
FILE *fp;
char buf[10240], *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) {
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;
}
if (fgets(buf, sizeof(buf), fp) != NULL)
res = strdup(buf);
else
res = NULL;
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;
}

41
bin/run.h Normal file
View File

@ -0,0 +1,41 @@
/* $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 */

233
bin/state.c Normal file
View File

@ -0,0 +1,233 @@
/* $NetBSD: state.c,v 1.18 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 <sys/cdefs.h>
__RCSID("$NetBSD: state.c,v 1.18 2016/04/04 15:52:56 christos Exp $");
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>
#include <netinet/in.h>
#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)
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);
}

62
bin/state.h Normal file
View File

@ -0,0 +1,62 @@
/* $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 <db_185.h>
#elif HAVE_DB_H
#include <db.h>
#else
#error "no db.h"
#endif
#include <time.h>
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 */

157
bin/support.c Normal file
View File

@ -0,0 +1,157 @@
/* $NetBSD: support.c,v 1.8 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 <sys/cdefs.h>
__RCSID("$NetBSD: support.c,v 1.8 2016/04/04 15:52:56 christos Exp $");
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <stdlib.h>
#include <inttypes.h>
#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 % 60;
t /= 24;
d = t % 24;
t /= 356;
y = t;
z = 0;
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;
}

44
bin/support.h Normal file
View File

@ -0,0 +1,44 @@
/* $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 */

91
diff/ftpd.diff Normal file
View File

@ -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 <stdio.h>
+#include <blacklist.h>
+
+#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 <security/pam_appl.h>
#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);

216
diff/named.diff Normal file
View File

@ -0,0 +1,216 @@
--- /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 <config.h>
+
+#include <isc/platform.h>
+#include <isc/util.h>
+#include <named/types.h>
+#include <named/client.h>
+
+#include <blacklist.h>
+
+#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 <bsd.prog.mk>
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 <named/server.h>
#include <named/update.h>
+#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 <libxml/xmlversion.h>
#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 <named/sortlist.h>
#include <named/xfrout.h>
+#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 <named/server.h>
#include <named/update.h>
+#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 <named/server.h>
#include <named/xfrout.h>
+#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];

124
diff/proftpd.diff Normal file
View File

@ -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_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 <blacklist.h>
+#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
+}

231
diff/ssh.diff Normal file
View File

@ -0,0 +1,231 @@
--- /dev/null 2015-01-22 23:10:33.000000000 -0500
+++ dist/pfilter.c 2015-01-22 23:46:03.000000000 -0500
@@ -0,0 +1,28 @@
+#include "namespace.h"
+#include "includes.h"
+#include "ssh.h"
+#include "packet.h"
+#include "log.h"
+#include "pfilter.h"
+#include <blacklist.h>
+
+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");
+}
--- /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}
Index: dist/auth.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth.c,v
retrieving revision 1.10
diff -u -u -r1.10 auth.c
--- dist/auth.c 19 Oct 2014 16:30:58 -0000 1.10
+++ dist/auth.c 22 Jan 2015 21:39:22 -0000
@@ -62,6 +62,7 @@
#include "monitor_wrap.h"
#include "krl.h"
#include "compat.h"
+#include "pfilter.h"
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
@@ -362,6 +363,8 @@
compat20 ? "ssh2" : "ssh1",
authctxt->info != NULL ? ": " : "",
authctxt->info != NULL ? authctxt->info : "");
+ if (!authctxt->postponed)
+ pfilter_notify(!authenticated);
free(authctxt->info);
authctxt->info = NULL;
}
Index: dist/sshd.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/sshd.c,v
retrieving revision 1.15
diff -u -u -r1.15 sshd.c
--- dist/sshd.c 28 Oct 2014 21:36:16 -0000 1.15
+++ dist/sshd.c 22 Jan 2015 21:39:22 -0000
@@ -109,6 +109,7 @@
#include "roaming.h"
#include "ssh-sandbox.h"
#include "version.h"
+#include "pfilter.h"
#ifdef LIBWRAP
#include <tcpd.h>
@@ -364,6 +365,7 @@
killpg(0, SIGTERM);
}
+ pfilter_notify(1);
/* Log error and exit. */
sigdie("Timeout before authentication for %s", get_remote_ipaddr());
}
@@ -1160,6 +1162,7 @@
for (i = 0; i < options.max_startups; i++)
startup_pipes[i] = -1;
+ pfilter_init();
/*
* Stay listening for connections until the system crashes or
* the daemon is killed with a signal.
Index: auth1.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth1.c,v
retrieving revision 1.9
diff -u -u -r1.9 auth1.c
--- auth1.c 19 Oct 2014 16:30:58 -0000 1.9
+++ auth1.c 14 Feb 2015 15:40:51 -0000
@@ -41,6 +41,7 @@
#endif
#include "monitor_wrap.h"
#include "buffer.h"
+#include "pfilter.h"
/* import */
extern ServerOptions options;
@@ -445,6 +446,7 @@
else {
debug("do_authentication: invalid user %s", user);
authctxt->pw = fakepw();
+ pfilter_notify(1);
}
/* Configuration may have changed as a result of Match */
Index: auth2.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth2.c,v
retrieving revision 1.9
diff -u -u -r1.9 auth2.c
--- auth2.c 19 Oct 2014 16:30:58 -0000 1.9
+++ auth2.c 14 Feb 2015 15:40:51 -0000
@@ -52,6 +52,7 @@
#include "pathnames.h"
#include "buffer.h"
#include "canohost.h"
+#include "pfilter.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -256,6 +257,7 @@
} else {
logit("input_userauth_request: invalid user %s", user);
authctxt->pw = fakepw();
+ pfilter_notify(1);
}
#ifdef USE_PAM
if (options.use_pam)
Index: sshd.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/sshd.c,v
retrieving revision 1.16
diff -u -r1.16 sshd.c
--- sshd.c 25 Jan 2015 15:52:44 -0000 1.16
+++ sshd.c 14 Feb 2015 09:55:06 -0000
@@ -628,6 +628,8 @@
explicit_bzero(pw->pw_passwd, strlen(pw->pw_passwd));
endpwent();
+ pfilter_init();
+
/* Change our root directory */
if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
Index: auth-pam.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth-pam.c,v
retrieving revision 1.7
diff -u -u -r1.7 auth-pam.c
--- auth-pam.c 3 Jul 2015 00:59:59 -0000 1.7
+++ auth-pam.c 23 Jan 2016 00:01:16 -0000
@@ -114,6 +114,7 @@
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
+#include "pfilter.h"
extern ServerOptions options;
extern Buffer loginmsg;
@@ -809,6 +810,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,
Index: auth.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth.c,v
retrieving revision 1.15
diff -u -u -r1.15 auth.c
--- auth.c 21 Aug 2015 08:20:59 -0000 1.15
+++ auth.c 23 Jan 2016 00:01:16 -0000
@@ -656,6 +656,7 @@
pw = getpwnam(user);
if (pw == NULL) {
+ pfilter_notify(1);
logit("Invalid user %.100s from %.100s",
user, get_remote_ipaddr());
return (NULL);
Index: auth1.c
===================================================================
RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth1.c,v
retrieving revision 1.12
diff -u -u -r1.12 auth1.c
--- auth1.c 3 Jul 2015 00:59:59 -0000 1.12
+++ auth1.c 23 Jan 2016 00:01:16 -0000
@@ -376,6 +376,7 @@
char *msg;
size_t len;
+ pfilter_notify(1);
error("Access denied for user %s by PAM account "
"configuration", authctxt->user);
len = buffer_len(&loginmsg);

10
etc/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $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 <bsd.files.mk>
.include <bsd.subdir.mk>

14
etc/blacklistd.conf Normal file
View File

@ -0,0 +1,14 @@
# 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 * = = =

15
etc/npf.conf Normal file
View File

@ -0,0 +1,15 @@
# 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
}

6
etc/rc.d/Makefile Normal file
View File

@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $
SCRIPTS=blacklistd
SCRIPTSDIR=/etc/rc.d
.include <bsd.prog.mk>

57
etc/rc.d/blacklistd Normal file
View File

@ -0,0 +1,57 @@
#!/bin/sh
#
# $NetBSD: blacklistd,v 1.1 2015/01/22 17:49:41 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="blsock"
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"

10
include/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $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 <bsd.prog.mk>

76
include/bl.h Normal file
View File

@ -0,0 +1,76 @@
/* $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 <stdbool.h>
#include <stdarg.h>
#include <sys/param.h>
#include <sys/socket.h>
#include "blacklist.h"
typedef enum {
BL_INVALID,
BL_ADD,
BL_DELETE
} bl_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 */

46
include/blacklist.h Normal file
View File

@ -0,0 +1,46 @@
/* $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 <sys/socket.h>
__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
#endif /* _BLACKLIST_H */

19
lib/Makefile Normal file
View File

@ -0,0 +1,19 @@
# $NetBSD: Makefile,v 1.6 2016/01/05 13:07:46 christos Exp $
.include <bsd.own.mk>
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 <bsd.lib.mk>

524
lib/bl.c Normal file
View File

@ -0,0 +1,524 @@
/* $NetBSD: bl.c,v 1.27 2015/12/30 16:42:48 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 <sys/cdefs.h>
__RCSID("$NetBSD: bl.c,v 1.27 2015/12/30 16:42:48 christos Exp $");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <signal.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <stdarg.h>
#include <netinet/in.h>
#ifdef _REENTRANT
#include <pthread.h>
#endif
#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 (%m)",
__func__);
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' (%m)",
__func__, sun->sun_path);
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' (%m)",
__func__, sun->sun_path);
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 (%m)", __func__, __STRING(CRED_NAME));
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 (%m)", __func__);
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;
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 (%m)", __func__);
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;
}
if ((size_t)rlen <= sizeof(ub.bl)) {
bl_log(b->b_fun, LOG_ERR, "message too short %zd", rlen);
return NULL;
}
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
strlcpy(bi->bi_msg, ub.bl.bl_data, MIN(sizeof(bi->bi_msg),
((size_t)rlen - sizeof(ub.bl) + 1)));
return bi;
}

88
lib/blacklist.c Normal file
View File

@ -0,0 +1,88 @@
/* $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 <sys/cdefs.h>
__RCSID("$NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $");
#include <stdio.h>
#include <bl.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
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)
{
return bl_send(bl, action ? BL_ADD : BL_DELETE, 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);
}

125
lib/libblacklist.3 Normal file
View File

@ -0,0 +1,125 @@
.\" $NetBSD: libblacklist.3,v 1.3 2015/01/25 23:09:28 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 22, 2015
.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 a 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
.Ar action
argument specifying
.Dv 1
for a failed connection or
.Dv 0
for a successful connection,
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
.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
All functions log errors to
.Xr syslogd 8 .
.Sh RETURN VALUES
The function
.Fn bl_open
returns a cookie on success and
.Dv NULL
on failure setting errno to an appropriate value.
.Pp
The
.Fn bl_send
function returns
.Dv 0
on success and
.Dv -1
on failure setting errno to an appropriate value.
.Sh SEE ALSO
.Xr blacklistd.conf 5 ,
.Xr blacklistd 8
.Sh AUTHORS
.An Christos Zoulas

2
lib/shlib_version Normal file
View File

@ -0,0 +1,2 @@
major=0
minor=0

6
libexec/Makefile Normal file
View File

@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $
SCRIPTS= blacklistd-helper
SCRIPTSDIR= /libexec
.include <bsd.prog.mk>

82
libexec/blacklistd-helper Normal file
View File

@ -0,0 +1,82 @@
#!/bin/sh
#echo "run $@" 1>&2
#set -x
# $1 command
# $2 rulename
# $3 protocol
# $4 address
# $5 mask
# $6 port
# $7 id
pf=
for f in npf pf; do
if [ -f "/etc/$f.conf" ]; then
pf="$f"
break
fi
done
if [ -z "$pf" ]; then
echo "$0: Unsupported packet filter" 1>&2
exit 1
fi
if [ -n "$3" ]; then
proto="proto $3"
fi
if [ -n "$6" ]; then
port="port $6"
fi
addr="$4"
mask="$5"
case "$4" in
::ffff:*.*.*.*)
if [ "$5" = 128 ]; then
mask=32
addr=${4#::ffff:}
fi;;
esac
case "$1" in
add)
case "$pf" in
npf)
/sbin/npfctl rule "$2" add block in final $proto from \
"$addr/$mask" to any $port
;;
pf)
# insert $ip/$mask into per-protocol anchored table
/sbin/pfctl -a "$2" -t "port$6" -T add "$addr/$mask"
echo "block in quick $proto from <port$6> to any $port" | \
/sbin/pfctl -a "$2" -f -
;;
esac
;;
rem)
case "$pf" in
npf)
/sbin/npfctl rule "$2" rem-id "$7"
;;
pf)
/sbin/pfctl -a "$2" -t "port$6" -T delete "$addr/$mask"
;;
esac
;;
flush)
case "$pf" in
npf)
/sbin/npfctl rule "$2" flush
;;
pf)
/sbin/pfctl -a "$2" -t "port$6" -T flush
;;
esac
;;
*)
echo "$0: Unknown command '$1'" 1>&2
exit 1
;;
esac

25
port/Makefile.am Normal file
View File

@ -0,0 +1,25 @@
#
ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libblacklist.la
include_HEADERS = blacklist.h
bin_PROGRAMS = blacklistd blacklistctl srvtest cltest
VPATH = ../bin:../lib:../test
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

93
port/_strtoi.h Normal file
View File

@ -0,0 +1,93 @@
/* $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;
}

17
port/clock_gettime.c Normal file
View File

@ -0,0 +1,17 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <time.h>
#include <sys/time.h>
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;
}

3
port/config.h Normal file
View File

@ -0,0 +1,3 @@
#if defined(__FreeBSD__)
#include "port.h"
#endif

91
port/configure.ac Normal file
View File

@ -0,0 +1,91 @@
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 <sys/socket.h>])
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

106
port/fgetln.c Normal file
View File

@ -0,0 +1,106 @@
/* $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 <stdlib.h>
#ifndef HAVE_NBTOOL_CONFIG_H
/* These headers are required, but included from nbtool_config.h */
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#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

236
port/fparseln.c Normal file
View File

@ -0,0 +1,236 @@
/* $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 <sys/cdefs.h>
#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 <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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 */

24
port/getprogname.c Normal file
View File

@ -0,0 +1,24 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
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;
}

1
port/m4/.cvsignore Normal file
View File

@ -0,0 +1 @@
*.m4

183
port/pidfile.c Normal file
View File

@ -0,0 +1,183 @@
/* $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 <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $");
#endif
#include <sys/param.h>
#include <paths.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#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);
}

274
port/popenve.c Normal file
View File

@ -0,0 +1,274 @@
/* $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 <sys/cdefs.h>
#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 <sys/param.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <assert.h>
#include <errno.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#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)
return cur;
serrno = errno;
(void)close(pdes[0]);
(void)close(pdes[1]);
errno = serrno;
return NULL;
}
static void
pdes_child(int *pdes, const char *type)
{
struct pid *old;
/* 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
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]);
}
}
}
static void
pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type)
{
FILE *iop;
/* Parent; assume fdopen can't fail. */
if (*type == 'r') {
iop = fdopen(pdes[0], type);
#ifdef _REENTRANT
cur->fd = pdes[0];
#endif
(void)close(pdes[1]);
} else {
iop = fdopen(pdes[1], type);
#ifdef _REENTRANT
cur->fd = pdes[1];
#endif
(void)close(pdes[0]);
}
/* Link into list of file descriptors. */
cur->fp = iop;
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 = vfork()) {
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;
}

86
port/port.h Normal file
View File

@ -0,0 +1,86 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <sys/stat.h>
#include <netdb.h>
#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

383
port/sockaddr_snprintf.c Normal file
View File

@ -0,0 +1,383 @@
/* $NetBSD: sockaddr_snprintf.c,v 1.10 2016/04/05 12:28:57 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 <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.10 2016/04/05 12:28:57 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#ifdef __linux__
#undef HAVE_NETATALK_AT_H
#endif
#ifdef HAVE_NETATALK_AT_H
#include <netatalk/at.h>
#endif
#ifdef HAVE_NET_IF_DL_H
#include <net/if_dl.h>
#endif
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#include <netdb.h>
#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, ':')) != 0) {
*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);
}

96
port/strlcat.c Normal file
View File

@ -0,0 +1,96 @@
/* $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 <Todd.Miller@courtesan.com>
*
* 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 <sys/cdefs.h>
#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 <sys/types.h>
#include <assert.h>
#include <string.h>
#ifdef _LIBC
# ifdef __weak_alias
__weak_alias(strlcat, _strlcat)
# endif
#endif
#else
#include <lib/libkern/libkern.h>
#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

78
port/strlcpy.c Normal file
View File

@ -0,0 +1,78 @@
/* $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 <Todd.Miller@courtesan.com>
*
* 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 <sys/cdefs.h>
#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 <sys/types.h>
#include <assert.h>
#include <string.h>
#ifdef _LIBC
# ifdef __weak_alias
__weak_alias(strlcpy, _strlcpy)
# endif
#endif
#else
#include <lib/libkern/libkern.h>
#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

61
port/strtoi.c Normal file
View File

@ -0,0 +1,61 @@
/* $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 <sys/cdefs.h>
__RCSID("$NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $");
#if defined(_KERNEL)
#include <sys/param.h>
#include <sys/types.h>
#include <lib/libkern/libkern.h>
#elif defined(_STANDALONE)
#include <sys/param.h>
#include <sys/types.h>
#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>
#else
#include <stddef.h>
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#endif
#define _FUNCNAME strtoi
#define __TYPE intmax_t
#define __WRAPPED strtoimax
#if !HAVE_STRTOI
#include "_strtoi.h"
#endif

12
test/Makefile Normal file
View File

@ -0,0 +1,12 @@
# $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 <bsd.prog.mk>

136
test/cltest.c Normal file
View File

@ -0,0 +1,136 @@
/* $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 <sys/cdefs.h>
__RCSID("$NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 christos Exp $");
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
static __dead void
usage(int c)
{
warnx("Unknown option `%c'", (char)c);
fprintf(stderr, "Usage: %s [-u] [-a <addr>] [-m <msg>] [-p <port>]\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;
}

220
test/srvtest.c Normal file
View File

@ -0,0 +1,220 @@
/* $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 <sys/cdefs.h>
__RCSID("$NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $");
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <poll.h>
#include <err.h>
#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 <num>]\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);
}
}
}