aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgilles <gilles@poolp.org>2016-07-06 17:19:20 +0200
committergilles <gilles@poolp.org>2016-07-06 17:19:20 +0200
commitda8bc3dc23bc6350ee05ef7744c4c42386aab836 (patch)
treed245f1084fbe74a78fd043699cedf28e9188338d
parentdisable entering sub directories for experimental filters (diff)
downloadOpenSMTPD-extras-da8bc3dc23bc6350ee05ef7744c4c42386aab836.tar.xz
OpenSMTPD-extras-da8bc3dc23bc6350ee05ef7744c4c42386aab836.zip
remove all experimental filters from -extras
-rw-r--r--extras/filters/filter-clamav/Makefile.am10
-rw-r--r--extras/filters/filter-clamav/filter-clamav.895
-rw-r--r--extras/filters/filter-clamav/filter_clamav.c301
-rw-r--r--extras/filters/filter-dkim-signer/Makefile.am9
-rw-r--r--extras/filters/filter-dkim-signer/filter-dkim-signer.8108
-rw-r--r--extras/filters/filter-dkim-signer/filter_dkim_signer.c333
-rw-r--r--extras/filters/filter-dnsbl/Makefile.am14
-rw-r--r--extras/filters/filter-dnsbl/filter-dnsbl.8103
-rw-r--r--extras/filters/filter-dnsbl/filter_dnsbl.c187
-rw-r--r--extras/filters/filter-lua/Makefile.am11
-rw-r--r--extras/filters/filter-lua/filter_lua.c480
-rw-r--r--extras/filters/filter-pause/Makefile.am10
-rw-r--r--extras/filters/filter-pause/filter-pause.890
-rw-r--r--extras/filters/filter-pause/filter_pause.c89
-rw-r--r--extras/filters/filter-perl/Makefile.am11
-rw-r--r--extras/filters/filter-perl/filter_perl.c305
-rw-r--r--extras/filters/filter-python/Makefile.am11
-rw-r--r--extras/filters/filter-python/filter_python.c539
-rw-r--r--extras/filters/filter-regex/Makefile.am18
-rw-r--r--extras/filters/filter-regex/filter-regex.8.in90
-rw-r--r--extras/filters/filter-regex/filter-regex.conf26
-rw-r--r--extras/filters/filter-regex/filter-regex.conf.5.in126
-rw-r--r--extras/filters/filter-regex/filter_regex.c302
-rw-r--r--extras/filters/filter-rspamd/Makefile.am13
-rw-r--r--extras/filters/filter-rspamd/filter_rspamd.c213
-rw-r--r--extras/filters/filter-rspamd/fixme.c68
-rw-r--r--extras/filters/filter-rspamd/json.c1011
-rw-r--r--extras/filters/filter-rspamd/json.h283
-rw-r--r--extras/filters/filter-rspamd/rspamd.c409
-rw-r--r--extras/filters/filter-rspamd/rspamd.h85
-rw-r--r--extras/filters/filter-spamassassin/Makefile.am10
-rw-r--r--extras/filters/filter-spamassassin/filter-spamassassin.8130
-rw-r--r--extras/filters/filter-spamassassin/filter_spamassassin.c368
33 files changed, 0 insertions, 5858 deletions
diff --git a/extras/filters/filter-clamav/Makefile.am b/extras/filters/filter-clamav/Makefile.am
deleted file mode 100644
index 4d05005..0000000
--- a/extras/filters/filter-clamav/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-clamav
-
-filter_clamav_SOURCES = $(SRCS)
-filter_clamav_SOURCES += filter_clamav.c
-
-man_MANS = filter-clamav.8
diff --git a/extras/filters/filter-clamav/filter-clamav.8 b/extras/filters/filter-clamav/filter-clamav.8
deleted file mode 100644
index aae4abd..0000000
--- a/extras/filters/filter-clamav/filter-clamav.8
+++ /dev/null
@@ -1,95 +0,0 @@
-.\"
-.\" Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 16 2016 $
-.Dt FILTER-CLAMAV 8
-.Os
-.Sh NAME
-.Nm filter-clamav
-.Nd smtpd filter for Clam AntiVirus clamd
-.Sh SYNOPSIS
-.Nm
-.Op Fl Cdv
-.Op Fl c Ar path
-.Op Fl h Ar host
-.Op Fl p Ar port
-.Sh DESCRIPTION
-.Nm
-is a filter for
-.Xr smtpd 8
-which can be used to filter mails based on the decision from Clam AntiVirus's
-.Xr clamd 8
-daemon.
-Mails are piped to the daemon, which scans the mail for viruses.
-.Pp
-The options are as follows:
-.Bl -tag -width "-h host"
-.It Fl d
-Debug mode, if this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl h Ar host
-Set the ClamAV
-.Ar host
-to be used.
-.Pp
-The default
-.Ar host
-is 127.0.0.1.
-.It Fl p Ar port
-Set the
-.Ar port
-ClamAV is listening on.
-.Pp
-The default
-.Ar port
-is 3310.
-.It Fl v
-Produce more verbose output.
-.El
-.Pp
-.Nm
-runs by default in a chroot.
-.Pp
-The debug and verbose options given with the
-.Xr smtpd 8
-invocation are intially passed to
-.Nm .
-.Pp
-Mails which contain a virus are rejected with a SMTP 554 reply.
-Non-virus mails are accepted.
-.\"Accepted messages are marked with a
-.\".Dq X-Filter-ClamAV
-.\"header.
-.Sh CLAM ANTIVIRUS CONFIGURATION
-By default
-.Nm
-expects Clam AntiVirus'
-.Xr clamd 8
-to listen on 127.0.0.1 port 3310 for incoming requests.
-This requires to uncomment the TCPAddr and TCPSocket option in the default
-configuration of the daemon.
-.Sh SEE ALSO
-.Xr filter_api 3 ,
-.Xr smtpd.conf 5 ,
-.Xr clamd 8 ,
-.Xr smtpd 8
-.Sh HISTORY
-The first version of
-.Nm
-was written in 2015.
-.Sh AUTHORS
-.An Joerg Jung Aq Mt jung@openbsd.org
diff --git a/extras/filters/filter-clamav/filter_clamav.c b/extras/filters/filter-clamav/filter_clamav.c
deleted file mode 100644
index 7f505d2..0000000
--- a/extras/filters/filter-clamav/filter_clamav.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <arpa/inet.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-#define CLAMAV_HOST "127.0.0.1"
-#define CLAMAV_PORT "3310"
-
-struct clamav {
- uint64_t id;
- struct iobuf iobuf;
- struct io io;
- int r;
- enum { CL_DATA, CL_EOM, CL_STA } s;
-};
-
-static struct sockaddr_storage clamav_ss;
-
-static void
-clamav_clear(struct clamav *cl)
-{
- if (cl == NULL)
- return;
- io_clear(&cl->io);
- iobuf_clear(&cl->iobuf);
- free(cl);
-}
-
-static int
-clamav_result(struct clamav *cl)
-{
- if (cl->r == INT_MIN) {
- log_warnx("warn: result: failed");
- return -1;
- }
- if (cl->r) {
- log_warnx("warn: session %016"PRIx64": result: REJECT virus", cl->id);
- return filter_api_reject_code(cl->id, FILTER_CLOSE, 554, "5.7.1 Virus found");
- }
- return filter_api_accept(cl->id);
-}
-
-#define CLAMAV_EXPAND(tok) #tok
-#define CLAMAV_QUOTE(tok) CLAMAV_EXPAND(tok)
-
-static int
-clamav_status(struct clamav *cl, const char *l) {
- char s[BUFSIZ + 1];
-
- if (sscanf(l, "stream: %"CLAMAV_QUOTE(BUFSIZ)"s", s) != 1) {
- (errno ? log_warn : log_warnx)("warn: result: sscanf");
- return -1;
- }
- log_info("info: result: %s", l);
- cl->r = (strcmp(s, "OK") != 0);
- return 0;
-}
-
-static int
-clamav_response(struct clamav *cl, const char *l)
-{
- switch (cl->s) {
- case CL_STA:
- if (clamav_status(cl, l) == -1)
- return -1;
- break;
- default:
- fatalx("response: bad state");
- }
- return 0;
-}
-
-static void
-clamav_io(struct io *io, int evt)
-{
- struct clamav *cl = io->arg;
- char *l;
-
- switch (evt) {
- case IO_CONNECTED:
- io_set_write(io);
- break;
- case IO_LOWAT:
- if (cl->s == CL_EOM) {
- cl->s++;
- io_set_read(io);
- }
- break;
- case IO_DATAIN:
- while ((l = iobuf_getline(&cl->iobuf, NULL))) {
- if (iobuf_len(&cl->iobuf) >= LINE_MAX) {
- log_warnx("warn: io: iobuf_getline");
- goto fail;
- }
- if (clamav_response(cl, l) == -1)
- goto fail;
- }
- iobuf_normalize(&cl->iobuf);
- break;
- case IO_DISCONNECTED:
- if (cl->s == CL_STA) {
- if (iobuf_len(&cl->iobuf)) {
- log_warnx("warn: io: incomplete");
- goto fail;
- }
- if (clamav_result(cl) == -1)
- goto fail;
- io_clear(io);
- break;
- } /* FALLTHROUGH */
- case IO_TIMEOUT:
- case IO_ERROR:
- log_warnx("warn: io: %s %s", io_strevent(evt), cl->io.error);
- goto fail;
- default:
- fatalx("io: bad event");
- }
- return;
-fail:
- if (cl->s > CL_DATA)
- filter_api_reject_code(cl->id, FILTER_FAIL, 451, "4.7.1 Virus filter failed");
- filter_api_set_udata(cl->id, NULL);
- clamav_clear(cl);
-}
-
-static void
-clamav_init(struct clamav *cl, uint64_t id)
-{
- iobuf_xinit(&cl->iobuf, LINE_MAX, LINE_MAX, "init");
- io_init(&cl->io, -1, cl, clamav_io, &cl->iobuf);
- cl->id = id;
- cl->r = INT_MIN;
-}
-
-static int
-clamav_on_data(uint64_t id)
-{
- struct clamav *cl;
-
- clamav_init((cl = xcalloc(1, sizeof(struct clamav), "on_data")), id);
- if (io_connect(&cl->io, (struct sockaddr *)&clamav_ss, NULL) == -1) {
- log_warnx("warn: on_data: io_connect %s", cl->io.error);
- clamav_clear(cl);
- return filter_api_accept(id);
- }
- iobuf_xfqueue(&cl->iobuf, "on_data", "nINSTREAM\n");
- filter_api_set_udata(id, cl);
- return filter_api_accept(id);
-}
-
-static void
-clamav_on_dataline(uint64_t id, const char *l)
-{
- struct clamav *cl;
- uint32_t n = htonl(strlen(l) + 1);
-
- filter_api_writeln(id, l);
- if ((cl = filter_api_get_udata(id)) == NULL)
- return;
- if (iobuf_queue(&cl->iobuf, &n, sizeof(uint32_t)) != (int)sizeof(uint32_t))
- fatalx("on_dataline: iobuf_queue");
- iobuf_xfqueue(&cl->iobuf, "on_dataline", "%s\n", l);
- io_reload(&cl->io);
-}
-
-static int
-clamav_on_eom(uint64_t id, size_t size)
-{
- struct clamav *cl;
- uint32_t n = htonl(0);
-
- if ((cl = filter_api_get_udata(id)) == NULL)
- return filter_api_accept(id);
- if (iobuf_queue(&cl->iobuf, &n, sizeof(uint32_t)) != (int)sizeof(uint32_t))
- fatalx("on_eom: iobuf_queue");
- io_reload(&cl->io);
- cl->s++;
- return 1; /* defer accept or reject */
-}
-
-static void
-clamav_on_tx_commit(uint64_t id)
-{
- clamav_clear(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-static void
-clamav_on_tx_rollback(uint64_t id)
-{
- clamav_clear(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-
-static void
-clamav_resolve(const char *h, const char *p)
-{
- struct addrinfo hints, *addresses, *ai;
- int fd, r;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if ((r = getaddrinfo(h, p, &hints, &addresses)))
- fatalx("resolve: getaddrinfo %s", gai_strerror(r));
- for (ai = addresses; ai; ai = ai->ai_next) {
- if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1)
- continue;
- if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
- close(fd);
- continue;
- }
- write(fd, "nPING\n", 6);
- close(fd);
- memmove(&clamav_ss, ai->ai_addr, ai->ai_addrlen);
- break;
- }
- freeaddrinfo(addresses);
- if (!ai)
- fatalx("resolve: failed");
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- char *h = CLAMAV_HOST, *p = CLAMAV_PORT;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "dh:p:v")) != -1) {
- switch (ch) {
- case 'd':
- d = 1;
- break;
- case 'h':
- h = optarg;
- break;
- case 'p':
- p = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (h)
- h = strip(h);
- if (p)
- p = strip(p);
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
- clamav_resolve(h, p);
-
- filter_api_on_data(clamav_on_data);
- filter_api_on_dataline(clamav_on_dataline);
- filter_api_on_eom(clamav_on_eom);
- filter_api_on_tx_commit(clamav_on_tx_commit);
- filter_api_on_tx_rollback(clamav_on_tx_rollback);
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-dkim-signer/Makefile.am b/extras/filters/filter-dkim-signer/Makefile.am
deleted file mode 100644
index e24ba41..0000000
--- a/extras/filters/filter-dkim-signer/Makefile.am
+++ /dev/null
@@ -1,9 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-
-pkglibexec_PROGRAMS = filter-dkim-signer
-
-filter_dkim_signer_SOURCES = $(SRCS)
-filter_dkim_signer_SOURCES += filter_dkim_signer.c
-
-man_MANS = filter-dkim-signer.8
diff --git a/extras/filters/filter-dkim-signer/filter-dkim-signer.8 b/extras/filters/filter-dkim-signer/filter-dkim-signer.8
deleted file mode 100644
index 5b7dc42..0000000
--- a/extras/filters/filter-dkim-signer/filter-dkim-signer.8
+++ /dev/null
@@ -1,108 +0,0 @@
-.\"
-.\" Copyright (c) 2015 Bernard Spil <brnrd@FreeBSD.org>
-.\" Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 18 2016 $
-.Dt FILTER-DKIM-SIGNER 8
-.Os
-.Sh NAME
-.Nm filter-dkim-signer
-.Nd smtpd filter to add DKIM signatures
-.Sh SYNOPSIS
-.Nm
-.Op Fl Cdv
-.Op Fl c Ar path
-.Op Fl D Ar domain
-.Op Fl p Ar private-key
-.Op Fl s Ar selector
-.Sh DESCRIPTION
-.Nm
-is a filter for
-.Xr smtpd 8
-which can be used to add rsa-sha256 DKIM signatures to
-SMTP headers
-.Pp
-The options are as follows:
-.Bl -tag -width "-p private-key"
-.It Fl C
-No
-.Xr chroot 2
-mode, if this option is specified,
-.Nm
-will not run in a chroot.
-.It Fl c Ar path
-Set the chroot
-.Ar path .
-.Pp
-The default
-.Ar path
-is
-.Pa /var/empty
-(compile option).
-.It Fl D Ar domain
-Set the DKIM
-.Ar domain
-to be added.
-.Pp
-The default
-.Ar domain
-is retrieved with gethostname().
-.It Fl d
-Debug mode, if this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl p Ar private-key
-The file-name that contains the RSA
-.Ar private-key
-to be used for signing
-.Pp
-The default
-.Ar private-key
-is /etc/ssl/private/rsa.private
-.It Fl s Ar selector
-Set the DKIM
-.Ar selector
-.Pp
-The default
-.Ar selector
-is "default"
-.It Fl v
-Produce more verbose output.
-.El
-.Pp
-.Nm
-runs by default in a chroot.
-.Pp
-The debug and verbose options given with the
-.Xr smtpd 8
-invocation are intially passed to
-.Nm .
-.Pp
-With
-.Nm
-enabled, an rsa-sha256 DKIM signature header is added to mails passing
-through the filter.
-.Sh SEE ALSO
-.Xr chroot 2 ,
-.Xr filter_api 3 ,
-.Xr smtpd.conf 5 ,
-.Xr smtpd 8
-.Sh HISTORY
-The first version of
-.Nm
-was written in 2014.
-.Sh AUTHORS
-.An Sunil Nimmagadda
diff --git a/extras/filters/filter-dkim-signer/filter_dkim_signer.c b/extras/filters/filter-dkim-signer/filter_dkim_signer.c
deleted file mode 100644
index 2707ad4..0000000
--- a/extras/filters/filter-dkim-signer/filter_dkim_signer.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (c) 2014 Sunil Nimmagadda <sunil@nimmagadda.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openssl/pem.h>
-#include <openssl/rand.h>
-#include <openssl/rsa.h>
-#include <openssl/sha.h>
-
-#include <smtpd-api.h>
-
-#define DKIM_SIGNER_CRLF "\r\n"
-#define DKIM_SIGNER_CRLF_LEN 2
-#define DKIM_SIGNER_PRIVATE_KEY "/etc/ssl/private/rsa.private"
-#define DKIM_SIGNER_TEMPLATE "DKIM-Signature: v=1; a=rsa-sha256; " \
- "c=simple/simple; d=%s; " \
- "h=%s; " \
- "s=%s; " \
- "bh=%s; " \
- "b="
-
-struct entry {
- SIMPLEQ_ENTRY(entry) entries;
- char *line;
-};
-
-struct dkim_signer {
- SIMPLEQ_HEAD(, entry) lines;
- SHA256_CTX hdr_ctx;
- SHA256_CTX body_ctx;
- char b64_rsa_sig[BUFSIZ];
- char b64_body_hash[BUFSIZ];
- char hdrs_list[BUFSIZ];
- char hdr_hash[SHA256_DIGEST_LENGTH];
- char body_hash[SHA256_DIGEST_LENGTH];
- SHA256_CTX *ctx;
- size_t nlines;
- size_t emptylines;
-};
-
-static RSA *dkim_signer_rsa;
-static const char *dkim_signer_domain, *dkim_signer_selector = "default";
-
-static int
-dkim_signer_add_hdr_line(struct dkim_signer *s, const char *line)
-{
- const char *want_hdrs[] = {
- "from:", "to:", "subject:", "date:", "message-id:"
- };
- size_t i;
-
- for (i = 0; i < nitems(want_hdrs); i++) {
- if (strncasecmp(want_hdrs[i], line, strlen(want_hdrs[i])))
- continue;
-
- if (strlcat(s->hdrs_list, want_hdrs[i],
- sizeof(s->hdrs_list)) >= sizeof(s->hdrs_list))
- fatalx("headers list overflow");
- else
- return 1;
- }
-
- return 0;
-}
-
-static void
-dkim_signer_clear(struct dkim_signer *s)
-{
- struct entry *n;
-
- if (s == NULL)
- return;
- while (!SIMPLEQ_EMPTY(&s->lines)) {
- n = SIMPLEQ_FIRST(&s->lines);
- SIMPLEQ_REMOVE_HEAD(&s->lines, entries);
- free(n->line);
- free(n);
- }
- free(s);
-}
-
-static int
-dkim_signer_on_data(uint64_t id)
-{
- struct dkim_signer *s = xmalloc(sizeof *s, "dkim_signer: on_data");
-
- SIMPLEQ_INIT(&s->lines);
- SHA256_Init(&s->hdr_ctx);
- SHA256_Init(&s->body_ctx);
- s->ctx = &s->hdr_ctx;
- s->nlines = 0;
- s->emptylines = 0;
- s->hdrs_list[0] = '\0';
-
- filter_api_set_udata(id, s);
- return filter_api_accept(id);
-}
-
-static void
-dkim_signer_on_dataline(uint64_t id, const char *line)
-{
- struct dkim_signer *s;
- struct entry *n;
-
- if ((s = filter_api_get_udata(id)) == NULL)
- return;
- n = xmalloc(sizeof *n, "dkim_signer: on_dataline");
- n->line = xstrdup(line, "dkim_signer: on_dataline");
- SIMPLEQ_INSERT_TAIL(&s->lines, n, entries);
-
- /* first emptyline seperates headers and body */
- if (s->ctx == &s->hdr_ctx && strlen(line) == 0) {
- s->ctx = &s->body_ctx;
- return;
- }
-
- if (s->ctx == &s->hdr_ctx) {
- if (dkim_signer_add_hdr_line(s, line) == 0)
- return; /* skip unwanted headers */
- } else {
- s->nlines += 1;
- /*
- * treat trailing two or more emptylines at end of
- * message as a single emptyline
- */
- if (strlen(line) == 0) {
- s->emptylines += 1;
- return;
- } else {
- while (s->emptylines--)
- SHA256_Update(s->ctx, DKIM_SIGNER_CRLF, DKIM_SIGNER_CRLF_LEN);
-
- s->emptylines = 0;
- }
- }
-
- SHA256_Update(s->ctx, line, strlen(line));
- /* explicitly terminate with a CRLF */
- SHA256_Update(s->ctx, DKIM_SIGNER_CRLF, DKIM_SIGNER_CRLF_LEN);
-}
-
-static int
-dkim_signer_on_eom(uint64_t id, size_t size)
-{
- struct dkim_signer *s;
- struct entry *n;
- char *dkim_header = NULL, *dkim_sig = NULL, *rsa_sig = NULL;
- int dkim_sig_len, rsa_sig_len, r = 0;
-
- if ((s = filter_api_get_udata(id)) == NULL) {
- log_warnx("warn: on_eom: get_udata failed");
- goto done;
- }
- /* empty body should be treated as a single CRLF */
- if (s->nlines == 0)
- SHA256_Update(&s->body_ctx, DKIM_SIGNER_CRLF, DKIM_SIGNER_CRLF_LEN);
-
- SHA256_Final(s->body_hash, &s->body_ctx);
- if (base64_encode(s->body_hash, sizeof(s->body_hash),
- s->b64_body_hash, sizeof(s->b64_body_hash)) == -1) {
- log_warnx("warn: on_eom: __b64_ntop failed");
- goto done;
- }
-
- /* trim trailing colon in the hdrs_list */
- s->hdrs_list[strlen(s->hdrs_list) - 1] = '\0';
-
- if ((dkim_sig_len = asprintf(&dkim_sig, DKIM_SIGNER_TEMPLATE,
- dkim_signer_domain, s->hdrs_list, dkim_signer_selector,
- s->b64_body_hash)) == -1) {
- log_warn("warn: on_eom: asprintf failed");
- goto done;
- }
-
- SHA256_Update(&s->hdr_ctx, dkim_sig, dkim_sig_len);
- SHA256_Final(s->hdr_hash, &s->hdr_ctx);
-
- rsa_sig = xmalloc(RSA_size(dkim_signer_rsa), "dkim_signer: on_eom");
- if (RSA_sign(NID_sha256, s->hdr_hash, sizeof(s->hdr_hash),
- rsa_sig, &rsa_sig_len, dkim_signer_rsa) == 0)
- fatalx("dkim_signer: on_eom: RSA_sign");
-
- if (base64_encode(rsa_sig, rsa_sig_len, s->b64_rsa_sig,
- sizeof(s->b64_rsa_sig)) == -1) {
- log_warnx("warn: on_eom: __b64_ntop failed");
- goto done;
- }
-
- if (asprintf(&dkim_header, "%s%s", dkim_sig, s->b64_rsa_sig) == -1) {
- log_warn("warn: on_eom: asprintf failed");
- goto done;
- }
-
- /* prepend dkim header to the mail */
- filter_api_writeln(id, dkim_header);
-
- /* write out message */
- SIMPLEQ_FOREACH(n, &s->lines, entries)
- filter_api_writeln(id, n->line);
- r = 1;
-done:
- free(dkim_header);
- free(dkim_sig);
- free(rsa_sig);
- return r ? filter_api_accept(id) : filter_api_reject(id, FILTER_FAIL);
-}
-
-static void
-dkim_signer_on_tx_commit(uint64_t id)
-{
- dkim_signer_clear(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-static void
-dkim_signer_on_tx_rollback(uint64_t id)
-{
- dkim_signer_clear(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, C = 0, d = 0, v = 0;
- const char *p = DKIM_SIGNER_PRIVATE_KEY;
- char *c = NULL, *D = NULL, *s = NULL;
- FILE *fp;
- static char hostname[SMTPD_MAXHOSTNAMELEN];
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "Cc:D:dp:s:v")) != -1) {
- switch (ch) {
- case 'C':
- C = 1;
- break;
- case 'c':
- c = optarg;
- break;
- case 'D':
- D = optarg;
- break;
- case 'd':
- d = 1;
- break;
- case 'p':
- p = optarg;
- break;
- case 's':
- s = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (c)
- c = strip(c);
- if (D)
- dkim_signer_domain = strip(D);
- if (s)
- dkim_signer_selector = strip(s);
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
- OpenSSL_add_all_algorithms();
- OpenSSL_add_all_ciphers();
- OpenSSL_add_all_digests();
- if (dkim_signer_domain == NULL) {
- if (gethostname(hostname, sizeof(hostname)) == -1)
- fatal("gethostname");
- dkim_signer_domain = hostname;
- }
- if ((fp = fopen(p, "r")) == NULL)
- fatal("fopen %s", p);
- if ((dkim_signer_rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL)
- fatalx("PEM_read_RSAPrivateKey");
-
- filter_api_on_data(dkim_signer_on_data);
- filter_api_on_dataline(dkim_signer_on_dataline);
- filter_api_on_eom(dkim_signer_on_eom);
- filter_api_on_tx_commit(dkim_signer_on_tx_commit);
- filter_api_on_tx_rollback(dkim_signer_on_tx_rollback);
- if (c)
- filter_api_set_chroot(c);
- if (C)
- filter_api_no_chroot();
-
- /* XXX */
- /*
- * OpenSSL will not be able to seed PRNG after chroot which will
- * lead to runtime failures if we don't seed PRNG pre-chroot. We
- * shouldn't have to do that, LibreSSL does not suffer from this
- * shortcoming but luckily provides RAND_status() as a no-op for
- * ABI compat...
- */
- RAND_status();
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-dnsbl/Makefile.am b/extras/filters/filter-dnsbl/Makefile.am
deleted file mode 100644
index 1db4695..0000000
--- a/extras/filters/filter-dnsbl/Makefile.am
+++ /dev/null
@@ -1,14 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-dnsbl
-
-filter_dnsbl_SOURCES = $(SRCS)
-filter_dnsbl_SOURCES += filter_dnsbl.c
-
-man_MANS = filter-dnsbl.8
-
-if !NO_LIBASR
-LDADD += -lasr
-endif
diff --git a/extras/filters/filter-dnsbl/filter-dnsbl.8 b/extras/filters/filter-dnsbl/filter-dnsbl.8
deleted file mode 100644
index 254a5db..0000000
--- a/extras/filters/filter-dnsbl/filter-dnsbl.8
+++ /dev/null
@@ -1,103 +0,0 @@
-.\"
-.\" Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 16 2016 $
-.Dt FILTER-DNSBL 8
-.Os
-.Sh NAME
-.Nm filter-dnsbl
-.Nd smtpd filter for DNSBL checks
-.Sh SYNOPSIS
-.Nm
-.Op Fl Cdv
-.Op Fl c Ar path
-.Op Fl h Ar host
-.Op Fl w Ar host
-.Sh DESCRIPTION
-.Nm
-is a filter for
-.Xr smtpd 8
-which can be used to check new connections against a
-DNS-based Blackhole List (DNSBL) and optional a DNS-based Whitelist (DNSWL).
-.Pp
-The options are as follows:
-.Bl -tag -width "-c path"
-.It Fl C
-No
-.Xr chroot 2
-mode, if this option is specified,
-.Nm
-will not run in a chroot.
-.It Fl c Ar path
-Set the chroot
-.Ar path .
-.Pp
-The default
-.Ar path
-is
-.Pa /var/empty
-(compile option).
-.It Fl d
-Debug mode, if this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl h Ar host
-Set the DNSBL
-.Ar host
-to be queried.
-.Pp
-The default
-.Ar host
-is dnsbl.sorbs.net.
-.It Fl v
-Produce more verbose output.
-.It Fl w Ar host
-Set the DNSWL
-.Ar host
-to be queried.
-.Pp
-The default is to not query a DNSWL
-.Ar host .
-.El
-.Pp
-.Nm
-runs by default in a chroot.
-In order to make DNS queries working, a valid
-.Pa resolv.conf
-is required within the chroot.
-.Pp
-The debug and verbose options given with the
-.Xr smtpd 8
-invocation are intially passed to
-.Nm .
-.Pp
-The remote IP address of new connections is used in a DNS query against the
-DNSBL and optional DNSWL.
-If the remote address is listed in the DNSBL, the connection is rejected,
-otherwise accepted.
-If the optional DNSWL host is given, it is queried first and if the remote
-address is listed the connection is accepted (without checking the DNSBL).
-.Sh SEE ALSO
-.Xr chroot 2 ,
-.Xr filter_api 3 ,
-.Xr smtpd.conf 5 ,
-.Xr smtpd 8
-.Sh HISTORY
-The first version of
-.Nm
-was written in 2013.
-.Sh AUTHORS
-.An Eric Faurot Aq Mt eric@openbsd.org
diff --git a/extras/filters/filter-dnsbl/filter_dnsbl.c b/extras/filters/filter-dnsbl/filter_dnsbl.c
deleted file mode 100644
index 6835538..0000000
--- a/extras/filters/filter-dnsbl/filter_dnsbl.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
- * Copyright (c) 2016 Joerg Jung <jung@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <asr.h>
-
-#include <smtpd-api.h>
-
-struct dnsbl {
- uint64_t id;
- struct asr_query *aq_bl, *aq_wl;
-};
-
-static const char *dnsbl_host = "dnsbl.sorbs.net", *dnswl_host;
-
-static void
-dnsbl_event_black(struct asr_result *ar, void *p)
-{
- struct dnsbl *dl = p;
-
- if (ar->ar_addrinfo)
- freeaddrinfo(ar->ar_addrinfo);
- if (ar->ar_gai_errno == EAI_NODATA || ar->ar_gai_errno == EAI_NONAME) {
- log_info("info: event_black: ACCEPT address");
- filter_api_accept(dl->id);
- } else if (ar->ar_gai_errno) {
- log_warnx("warn: session %016"PRIx64": event_black: getaddrinfo '%s'", dl->id, gai_strerror(ar->ar_gai_errno));
- filter_api_reject_code(dl->id, FILTER_FAIL, 451, "4.7.1 DNSBL filter failed");
- } else {
- log_warnx("warn: session %016"PRIx64": event_black: REJECT address", dl->id);
- filter_api_reject_code(dl->id, FILTER_CLOSE, 554, "5.7.1 Address in DNSBL");
- }
- free(dl);
-}
-
-static void
-dnsbl_event_white(struct asr_result *ar, void *p)
-{
- struct dnsbl *dl = p;
-
- if (ar->ar_addrinfo)
- freeaddrinfo(ar->ar_addrinfo);
- if (ar->ar_gai_errno == EAI_NODATA || ar->ar_gai_errno == EAI_NONAME) {
- log_debug("debug: event_white: address not in DNSWL");
- event_asr_run(dl->aq_bl, dnsbl_event_black, dl);
- } else if (ar->ar_gai_errno) {
- log_warnx("warn: session %016"PRIx64": event_white: getaddrinfo '%s'", dl->id, gai_strerror(ar->ar_gai_errno));
- filter_api_reject_code(dl->id, FILTER_FAIL, 451, "4.7.1 DNSBL filter failed");
- asr_abort(dl->aq_bl);
- free(dl);
- } else {
- log_info("info: event_white: ACCEPT address");
- filter_api_accept(dl->id);
- asr_abort(dl->aq_bl);
- free(dl);
- }
-}
-
-static struct asr_query *
-dnsbl_query(in_addr_t ia, const char *h)
-{
- struct asr_query *aq;
- struct addrinfo hints;
- char buf[512];
-
- ia = ntohl(ia);
- if (snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%s.",
- ia & 0xff, (ia >> 8) & 0xff, (ia >> 16) & 0xff, (ia >> 24) & 0xff, h) >= sizeof(buf)) {
- log_warnx("warn: query: host name too long: %s", buf);
- return NULL;
- }
- log_debug("debug: query: checking %s", buf);
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- if (!(aq = getaddrinfo_async(buf, NULL, &hints, NULL))) {
- log_warn("warn: query: getaddrinfo_async");
- return NULL;
- }
- return aq;
-}
-
-static int
-dnsbl_on_connect(uint64_t id, struct filter_connect *conn)
-{
- struct dnsbl *dl;
- in_addr_t ia;
-
- if (conn->remote.ss_family != AF_INET)
- return filter_api_accept(id);
- ia = ((const struct sockaddr_in *)&conn->remote)->sin_addr.s_addr;
- dl = xcalloc(1, sizeof(struct dnsbl), "on_connect");
- dl->id = id;
- if (!(dl->aq_bl = dnsbl_query(ia, dnsbl_host)) || (dnswl_host &&
- !(dl->aq_wl = dnsbl_query(ia, dnswl_host)))) {
- free(dl);
- return filter_api_reject_code(id, FILTER_FAIL, 451, "4.7.1 DNSBL filter failed");
- }
- dnswl_host ? event_asr_run(dl->aq_wl, dnsbl_event_white, dl) :
- event_asr_run(dl->aq_bl, dnsbl_event_black, dl);
- return 1;
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, C = 0, d = 0, v = 0;
- char *c = NULL, *h = NULL, *w = NULL;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "Cc:dh:vw:")) != -1) {
- switch (ch) {
- case 'C':
- C = 1;
- break;
- case 'c':
- c = optarg;
- break;
- case 'd':
- d = 1;
- break;
- case 'h':
- h = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- case 'w':
- w = optarg;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (c)
- c = strip(c);
- if (h)
- dnsbl_host = strip(h);
- if (w)
- dnswl_host = strip(w);
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
-
- filter_api_on_connect(dnsbl_on_connect);
- if (c)
- filter_api_set_chroot(c); /* getaddrinfo requires resolv.conf */
- if (C)
- filter_api_no_chroot();
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-lua/Makefile.am b/extras/filters/filter-lua/Makefile.am
deleted file mode 100644
index 58f8a7d..0000000
--- a/extras/filters/filter-lua/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-lua
-
-filter_lua_SOURCES = $(SRCS)
-filter_lua_SOURCES += filter_lua.c
-
-CFLAGS += ${LUA_CPPFLAGS}
-LDFLAGS += ${LUA_LDFLAGS}
diff --git a/extras/filters/filter-lua/filter_lua.c b/extras/filters/filter-lua/filter_lua.c
deleted file mode 100644
index c2c8781..0000000
--- a/extras/filters/filter-lua/filter_lua.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
- * Copyright (c) 2014 Emmanuel Vadot <manu@bocal.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
-#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501
-#define luaL_Reg luaL_reg
-void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
- luaL_checkstack(L, nup+1, "too many upvalues");
- for (; l->name != NULL; l++) { /* fill the table with given functions */
- int i;
- lua_pushstring(L, l->name);
- for (i = 0; i < nup; i++) /* copy upvalues to the top */
- lua_pushvalue(L, -(nup + 1));
- lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
- lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
- }
- lua_pop(L, nup); /* remove upvalues */
-}
-#define luaL_newlib(L, l) \
- (lua_newtable((L)),luaL_setfuncs((L), (l), 0))
-#endif
-
-#include <smtpd-api.h>
-
-#define ID_STR_SZ 20
-
-lua_State *L;
-
-static int
-l_filter_accept(lua_State *L)
-{
- uint64_t id;
- const char *s_hex_id;
-
- if (lua_gettop(L) != 1)
- return 0;
-
- s_hex_id = luaL_checklstring(L, 1, NULL);
- id = strtoumax(s_hex_id, NULL, 16);
- filter_api_accept(id);
- return 0;
-}
-
-static int
-l_filter_reject(lua_State *L)
-{
- uint64_t id;
- const char *s_hex_id;
- uint32_t action;
-
- if (lua_gettop(L) != 2)
- return 0;
-
- s_hex_id = luaL_checklstring(L, 1, NULL);
- id = strtoumax(s_hex_id, NULL, 16);
- action = luaL_checkinteger(L, 2);
- switch (action) {
- case FILTER_FAIL:
- case FILTER_CLOSE:
- filter_api_reject(id, action);
- break;
- }
-
- return 0;
-}
-
-static int
-l_filter_reject_code(lua_State *L)
-{
- uint64_t id;
- const char *s_hex_id;
- uint32_t action;
- uint32_t code;
- const char *line;
-
- if (lua_gettop(L) != 4)
- return 0;
-
- s_hex_id = luaL_checklstring(L, 1, NULL);
- id = strtoumax(s_hex_id, NULL, 16);
- action = luaL_checkinteger(L, 2);
- code = luaL_checkinteger(L, 3);
- line = luaL_checklstring(L, 4, NULL);
-
- switch (action) {
- case FILTER_FAIL:
- case FILTER_CLOSE:
- filter_api_reject_code(id, action, code, line);
- break;
- }
-
- return 0;
-}
-
-static int
-l_filter_writeln(lua_State *L)
-{
- uint64_t id;
- const char *s_hex_id;
- const char *line;
-
- if (lua_gettop(L) != 2)
- return 0;
-
- s_hex_id = luaL_checklstring(L, 1, NULL);
- id = strtoumax(s_hex_id, NULL, 16);
- line = luaL_checklstring(L, 2, NULL);
-
- filter_api_writeln(id, line);
-
- return 0;
-}
-
-static const luaL_Reg l_filter [] = {
- {"accept", l_filter_accept},
- {"reject", l_filter_reject},
- {"reject_code", l_filter_reject_code},
- {"writeln", l_filter_writeln},
- {NULL, NULL}
-};
-
-static int
-on_connect(uint64_t id, struct filter_connect *conn)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
-
- lua_getglobal(L, "on_connect");
- lua_pushstring(L, s_id);
- lua_pushstring(L,
- filter_api_sockaddr_to_text((struct sockaddr *)&conn->local));
- lua_pushstring(L,
- filter_api_sockaddr_to_text((struct sockaddr *)&conn->remote));
- lua_pushstring(L, conn->hostname);
-
- if (lua_pcall(L, 4, 0, 0)) {
- log_warnx("warn: on_connect: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_helo(uint64_t id, const char *helo)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_helo");
- lua_pushstring(L, s_id);
- lua_pushstring(L, helo);
-
- if (lua_pcall(L, 2, 0, 0)) {
- log_warnx("warn: on_helo: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_mail(uint64_t id, struct mailaddr *mail)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_mail");
- lua_pushstring(L, s_id);
- lua_pushstring(L, filter_api_mailaddr_to_text(mail));
-
- if (lua_pcall(L, 2, 0, 0)) {
- log_warnx("warn: on_mail: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_rcpt(uint64_t id, struct mailaddr *rcpt)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_rcpt");
- lua_pushstring(L, s_id);
- lua_pushstring(L, filter_api_mailaddr_to_text(rcpt));
-
- if (lua_pcall(L, 2, 0, 0)) {
- log_warnx("warn: on_rcpt: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_data(uint64_t id)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_data");
- lua_pushstring(L, s_id);
-
- if (lua_pcall(L, 1, 0, 0)) {
- log_warnx("warn: on_data: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-
- return 1;
-}
-
-static void
-on_dataline(uint64_t id, const char *line)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_dataline");
- lua_pushstring(L, s_id);
- lua_pushstring(L, line);
-
- if (lua_pcall(L, 2, 0, 0)) {
- log_warnx("warn: on_dataline: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-}
-
-static int
-on_eom(uint64_t id, size_t size)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_eom");
- lua_pushstring(L, s_id);
-
- if (lua_pcall(L, 1, 0, 0)) {
- log_warnx("warn: on_eom: %s", lua_tostring(L, -1));
- exit(1);
- }
-
- return 1;
-}
-
-static void
-on_tx_begin(uint64_t id)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_tx_begin");
- lua_pushstring(L, s_id);
-
- if (lua_pcall(L, 1, 0, 0)) {
- log_warnx("warn: on_tx_begin: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-}
-
-static void
-on_tx_commit(uint64_t id)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_tx_commit");
- lua_pushstring(L, s_id);
-
- if (lua_pcall(L, 1, 0, 0)) {
- log_warnx("warn: on_tx_commit: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-}
-
-static void
-on_tx_rollback(uint64_t id)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_tx_rollback");
- lua_pushstring(L, s_id);
-
- if (lua_pcall(L, 1, 0, 0)) {
- log_warnx("warn: on_tx_rollback: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-}
-
-static void
-on_disconnect(uint64_t id)
-{
- char s_id[ID_STR_SZ];
-
- (void)snprintf(s_id, sizeof(s_id), "%016"PRIx64"", id);
- lua_getglobal(L, "on_disconnect");
- lua_pushstring(L, s_id);
-
- if (lua_pcall(L, 1, 0, 0)) {
- log_warnx("warn: on_disconnect: %s",
- lua_tostring(L, -1));
- exit(1);
- }
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- char *c = NULL, *path;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "c:dv")) != -1) {
- switch (ch) {
- case 'c':
- c = optarg;
- break;
- case 'd':
- d = 1;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
- if (argc == 0)
- errx(1, "missing path");
-
- if (c)
- c = strip(c);
- path = argv[0];
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
-
- if ((L = luaL_newstate()) == NULL) {
- log_warnx("warn: can't create lua state");
- return 1;
- }
- luaL_openlibs(L);
- luaL_newlib(L, l_filter);
-#if 0
- luaL_newmetatable(L, "filter");
- lua_setmetatable(L, -2);
-
- lua_pushnumber(L, FILTER_OK);
- lua_setfield(L, -2, "FILTER_OK");
- lua_pushnumber(L, FILTER_FAIL);
- lua_setfield(L, -2, "FILTER_FAIL");
- lua_pushnumber(L, FILTER_CLOSE);
- lua_setfield(L, -2, "FILTER_CLOSE");
-#endif
- lua_setglobal(L, "filter");
-
- if (luaL_dofile(L, path) != 0) {
- log_warnx("warn: error loading script: %s", path);
- return 1;
- }
-
- lua_getglobal(L, "on_connect");
- if (lua_isfunction(L, -1)) {
- log_debug("debug: on_connect is present");
- filter_api_on_connect(on_connect);
- }
-
- lua_getglobal(L, "on_helo");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_helo is present");
- filter_api_on_helo(on_helo);
- }
-
- lua_getglobal(L, "on_mail");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_mail is present");
- filter_api_on_mail(on_mail);
- }
-
- lua_getglobal(L, "on_rcpt");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_rcpt is present");
- filter_api_on_rcpt(on_rcpt);
- }
-
- lua_getglobal(L, "on_data");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_data is present");
- filter_api_on_data(on_data);
- }
-
- lua_getglobal(L, "on_dataline");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_dataline is present");
- filter_api_on_dataline(on_dataline);
- }
-
- lua_getglobal(L, "on_eom");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_eom is present");
- filter_api_on_eom(on_eom);
- }
-
- lua_getglobal(L, "on_tx_begin");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_tx_begin is present");
- filter_api_on_tx_begin(on_tx_begin);
- }
-
- lua_getglobal(L, "on_tx_commit");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_tx_commit is present");
- filter_api_on_tx_commit(on_tx_commit);
- }
-
- lua_getglobal(L, "on_tx_rollback");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_tx_rollback is present");
- filter_api_on_tx_rollback(on_tx_rollback);
- }
-
- lua_getglobal(L, "on_disconnect");
- if (lua_isfunction(L, 1)) {
- log_debug("debug: on_disconnect is present");
- filter_api_on_disconnect(on_disconnect);
- }
-
- filter_api_no_chroot();
- if (c)
- filter_api_set_chroot(c);
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-pause/Makefile.am b/extras/filters/filter-pause/Makefile.am
deleted file mode 100644
index 21a226f..0000000
--- a/extras/filters/filter-pause/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-pause
-
-filter_pause_SOURCES = $(SRCS)
-filter_pause_SOURCES += filter_pause.c
-
-man_MANS = filter-pause.8
diff --git a/extras/filters/filter-pause/filter-pause.8 b/extras/filters/filter-pause/filter-pause.8
deleted file mode 100644
index 341ed2b..0000000
--- a/extras/filters/filter-pause/filter-pause.8
+++ /dev/null
@@ -1,90 +0,0 @@
-.\"
-.\" Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 16 2016 $
-.Dt FILTER-PAUSE 8
-.Os
-.Sh NAME
-.Nm filter-pause
-.Nd smtpd filter to pause on new connections
-.Sh SYNOPSIS
-.Nm
-.Op Fl dv
-.Op Fl s Ar seconds
-.Sh DESCRIPTION
-.Nm
-is a filter for
-.Xr smtpd 8
-which can be used to pause on new connections before emitting the standard
-initial SMTP greeting.
-This is useful to avoid the so called
-.Dq slamming
-technique used by some senders of spam mails.
-.Pp
-The options are as follows:
-.Bl -tag -width "-s seconds"
-.It Fl d
-Debug mode, if this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl s Ar seconds
-Set the number of
-.Ar seconds
-to pause before sending the initial greeting.
-The accepted values are within the range of 1s and 300s.
-.Pp
-The default
-.Ar seconds
-value is 5s.
-.It Fl v
-Produce more verbose output.
-.El
-.Pp
-.Nm
-runs by default in a chroot.
-.Pp
-The debug and verbose options given with the
-.Xr smtpd 8
-invocation are intially passed to
-.Nm .
-.Pp
-With
-.Nm
-enabled,
-.Xr smtpd 8
-simply waits the specified amount of
-.Ar seconds
-on each new connection.
-If the remote server starts sending SMTP commands before the greeting, the
-connection is rejected.
-Otherwise, the connection is accepted and normally processed.
-.Sh SEE ALSO
-.Xr filter_api 3 ,
-.Xr smtpd.conf 5 ,
-.Xr smtpd 8
-.Sh STANDARDS
-.Rs
-.%A J. Klensin
-.%D October 2008
-.%R RFC 5321
-.%T Simple Mail Transfer Protocol
-.Re
-.Sh HISTORY
-The first version of
-.Nm
-was written in 2015.
-.Sh AUTHORS
-.An Joerg Jung Aq Mt jung@openbsd.org
diff --git a/extras/filters/filter-pause/filter_pause.c b/extras/filters/filter-pause/filter_pause.c
deleted file mode 100644
index 4a0613a..0000000
--- a/extras/filters/filter-pause/filter_pause.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-static unsigned short pause_seconds = 5;
-
-static void
-pause_timer(uint64_t id, void *p)
-{
- filter_api_accept(id);
-}
-
-static int
-pause_on_connect(uint64_t id, struct filter_connect *conn)
-{
- log_debug("debug: on_connect: sleeping %u", pause_seconds);
- filter_api_timer(id, pause_seconds * 1000, pause_timer, NULL);
- return 1;
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- const char *errstr, *s = NULL;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "ds:v")) != -1) {
- switch (ch) {
- case 'd':
- d = 1;
- break;
- case 's':
- s = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (s) { /* RFC 5321 4.5.3.2 Initial 220 Message: 5 Minutes */
- pause_seconds = strtonum(s, 1, 300, &errstr);
- if (errstr)
- fatalx("seconds option is %s: %s", errstr, s);
- }
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
-
- filter_api_on_connect(pause_on_connect);
- filter_api_loop();
-
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-perl/Makefile.am b/extras/filters/filter-perl/Makefile.am
deleted file mode 100644
index cd3d861..0000000
--- a/extras/filters/filter-perl/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-perl
-
-filter_perl_SOURCES = $(SRCS)
-filter_perl_SOURCES += filter_perl.c
-
-CFLAGS += ${PERL_CPPFLAGS}
-LDFLAGS += ${PERL_LDFLAGS}
diff --git a/extras/filters/filter-perl/filter_perl.c b/extras/filters/filter-perl/filter_perl.c
deleted file mode 100644
index e58d004..0000000
--- a/extras/filters/filter-perl/filter_perl.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2014 Gilles Chehade <gilles@poolp.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <EXTERN.h>
-#include <XSUB.h>
-#include <perl.h>
-
-#include <smtpd-api.h>
-
-static PerlInterpreter *my_perl; /* fix build */
-static PerlInterpreter *pi;
-static CV *pl_on_connect;
-static CV *pl_on_helo;
-static CV *pl_on_mail;
-static CV *pl_on_rcpt;
-static CV *pl_on_data;
-static CV *pl_on_eom;
-static CV *pl_on_tx_begin;
-static CV *pl_on_tx_commit;
-static CV *pl_on_tx_rollback;
-static CV *pl_on_dataline;
-static CV *pl_on_disconnect;
-
-EXTERN_C void xs_init(pTHX);
-EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
-
-EXTERN_C void
-xs_init(pTHX)
-{
- static const char file[] = __FILE__;
- dXSUB_SYS;
- PERL_UNUSED_CONTEXT;
-
- /* DynaLoader is a special case */
- newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
-}
-
-XS(XS_filter_accept);
-XS(XS_filter_reject);
-XS(XS_filter_reject_code);
-XS(XS_filter_writeln);
-
-XS(XS_filter_accept)
-{
- dXSARGS;
- uint64_t id;
- int ret;
-
- id = SvUV(ST(0));
- ret = filter_api_accept(id);
- XPUSHs(sv_2mortal(newSViv(ret)));
- XSRETURN(1);
-}
-
-XS(XS_filter_reject)
-{
- dXSARGS;
- uint64_t id;
- int ret;
-
- id = SvUV(ST(0));
- ret = filter_api_reject(id, FILTER_CLOSE);
- XPUSHs(sv_2mortal(newSViv(ret)));
- XSRETURN(1);
-}
-
-XS(XS_filter_reject_code)
-{
- dXSARGS;
- XSRETURN(1);
-}
-
-XS(XS_filter_writeln)
-{
- dXSARGS;
- uint64_t id;
- const char *line;
-
- id = SvUV(ST(0));
- line = SvPVX(ST(1));
- filter_api_writeln(id, line);
- XSRETURN(1);
-}
-
-void
-call_sub_sv(SV *plsub, const char *format, ...)
-{
- va_list ap;
- dSP;
-
- va_start(ap, format);
-
- ENTER;
- SAVETMPS;
-
- PUSHMARK(SP);
- while (*format) {
- switch (*format++) {
- case 's':
- XPUSHs(sv_2mortal(newSVpv(va_arg(ap, char *), 0)));
- break;
- case 'i':
- XPUSHs(sv_2mortal(newSVuv(va_arg(ap, uint64_t))));
- break;
- }
- }
- PUTBACK;
-
- perl_call_sv(plsub, G_DISCARD);
-
- FREETMPS;
- LEAVE;
-
- va_end(ap);
-}
-
-static int
-on_connect(uint64_t id, struct filter_connect *conn)
-{
- char local[SMTPD_MAXHOSTNAMELEN];
- char remote[SMTPD_MAXHOSTNAMELEN];
-
- (void)snprintf(local, sizeof local, "%s",
- filter_api_sockaddr_to_text((struct sockaddr *)&conn->local));
- (void)snprintf(remote, sizeof remote, "%s",
- filter_api_sockaddr_to_text((struct sockaddr *)&conn->remote));
-
- call_sub_sv((SV *)pl_on_connect, "%i%s%s%s", id, local, remote, conn->hostname);
-}
-
-static int
-on_helo(uint64_t id, const char *helo)
-{
- call_sub_sv((SV *)pl_on_helo, "%i%s", id, helo);
-}
-
-static int
-on_mail(uint64_t id, struct mailaddr *mail)
-{
- const char *mailaddr;
-
- mailaddr = filter_api_mailaddr_to_text(mail);
- call_sub_sv((SV *)pl_on_mail, "%i%s", id, mailaddr);
-}
-
-static int
-on_rcpt(uint64_t id, struct mailaddr *rcpt)
-{
- const char *mailaddr;
-
- mailaddr = filter_api_mailaddr_to_text(rcpt);
- call_sub_sv((SV *)pl_on_rcpt, "%i%s", id, mailaddr);
-}
-
-static int
-on_data(uint64_t id)
-{
- call_sub_sv((SV *)pl_on_data, "%i", id);
-}
-
-static int
-on_eom(uint64_t id, size_t size)
-{
- call_sub_sv((SV *)pl_on_eom, "%i", id);
-}
-
-static void
-on_tx_begin(uint64_t id)
-{
- call_sub_sv((SV *)pl_on_tx_begin, "%i", id);
- return;
-}
-
-static void
-on_tx_commit(uint64_t id)
-{
- call_sub_sv((SV *)pl_on_tx_commit, "%i", id);
- return;
-}
-
-static void
-on_tx_rollback(uint64_t id)
-{
- call_sub_sv((SV *)pl_on_tx_rollback, "%i", id);
- return;
-}
-
-static void
-on_disconnect(uint64_t id)
-{
- call_sub_sv((SV *)pl_on_disconnect, "%i", id);
- return;
-}
-
-static void
-on_dataline(uint64_t id, const char *line)
-{
- call_sub_sv((SV *)pl_on_dataline, "%i%s", id, line);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- char *c = NULL, *fake_argv[3] = { "-e", NULL, NULL };
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "c:dv")) != -1) {
- switch (ch) {
- case 'c':
- c = optarg;
- break;
- case 'd':
- d = 1;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
- if (argc == 0)
- errx(1, "missing path");
-
- if (c)
- c = strip(c);
- fake_argv[1] = argv[0];
-
- log_init(d);
- log_verbose(v);
-
- pi = perl_alloc();
- perl_construct(pi);
- perl_parse(pi, xs_init, 2, fake_argv, NULL);
-
- newXS("smtpd::filter_api_accept", XS_filter_accept, __FILE__);
- newXS("smtpd::filter_api_reject", XS_filter_reject, __FILE__);
- newXS("smtpd::filter_api_writeln", XS_filter_writeln, __FILE__);
-
- log_debug("debug: starting...");
-
- if ((pl_on_connect = perl_get_cv("on_connect", FALSE)))
- filter_api_on_connect(on_connect);
- if ((pl_on_helo = perl_get_cv("on_helo", FALSE)))
- filter_api_on_helo(on_helo);
- if ((pl_on_mail = perl_get_cv("on_mail", FALSE)))
- filter_api_on_mail(on_mail);
- if ((pl_on_rcpt = perl_get_cv("on_rcpt", FALSE)))
- filter_api_on_rcpt(on_rcpt);
- if ((pl_on_data = perl_get_cv("on_data", FALSE)))
- filter_api_on_data(on_data);
- if ((pl_on_eom = perl_get_cv("on_eom", FALSE)))
- filter_api_on_eom(on_eom);
- if ((pl_on_tx_begin = perl_get_cv("on_tx_begin", FALSE)))
- filter_api_on_tx_begin(on_tx_begin);
- if ((pl_on_tx_commit = perl_get_cv("on_tx_commit", FALSE)))
- filter_api_on_tx_commit(on_tx_commit);
- if ((pl_on_tx_rollback = perl_get_cv("on_tx_rollback", FALSE)))
- filter_api_on_rollback(on_tx_rollback);
- if ((pl_on_dataline = perl_get_cv("on_dataline", FALSE)))
- filter_api_on_dataline(on_dataline);
- if ((pl_on_disconnect = perl_get_cv("on_disconnect", FALSE)))
- filter_api_on_disconnect(on_disconnect);
-
- filter_api_no_chroot();
- if (c)
- filter_api_set_chroot(c);
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- perl_destruct(pi);
- perl_free(pi);
-
- return 1;
-}
diff --git a/extras/filters/filter-python/Makefile.am b/extras/filters/filter-python/Makefile.am
deleted file mode 100644
index 8a7329a..0000000
--- a/extras/filters/filter-python/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-python
-
-filter_python_SOURCES = $(SRCS)
-filter_python_SOURCES += filter_python.c
-
-CFLAGS += ${PYTHON_CPPFLAGS}
-LDFLAGS += ${PYTHON_LDFLAGS}
diff --git a/extras/filters/filter-python/filter_python.c b/extras/filters/filter-python/filter_python.c
deleted file mode 100644
index 33c1f4b..0000000
--- a/extras/filters/filter-python/filter_python.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Copyright (c) 2014 Gilles Chehade <gilles@poolp.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <unistd.h>
-
-/* _GNU_SOURCE is not properly protected in Python.h ... */
-#undef _GNU_SOURCE
-#include <Python.h>
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <smtpd-api.h>
-
-static PyObject *py_on_connect;
-static PyObject *py_on_helo;
-static PyObject *py_on_mail;
-static PyObject *py_on_rcpt;
-static PyObject *py_on_data;
-static PyObject *py_on_eom;
-static PyObject *py_on_dataline;
-
-static PyObject *py_on_tx_begin;
-static PyObject *py_on_tx_commit;
-static PyObject *py_on_tx_rollback;
-static PyObject *py_on_disconnect;
-
-
-static PyObject *
-py_filter_accept(PyObject *self, PyObject *args)
-{
- uint64_t id;
-
- if (!PyArg_ParseTuple(args, "K", &id))
- return NULL;
- filter_api_accept(id);
- Py_RETURN_TRUE;
-}
-
-static PyObject *
-py_filter_reject(PyObject *self, PyObject *args)
-{
- uint64_t id;
- uint32_t action;
-
- if (!PyArg_ParseTuple(args, "Ki", &id, &action))
- return NULL;
-
- switch (action) {
- case FILTER_FAIL:
- case FILTER_CLOSE:
- filter_api_reject(id, action);
- Py_RETURN_TRUE;
- break;
- }
- Py_RETURN_FALSE;
-}
-
-static PyObject *
-py_filter_reject_code(PyObject *self, PyObject *args)
-{
- uint64_t id;
- uint32_t action;
- uint32_t code;
- const char *line;
-
- if (!PyArg_ParseTuple(args, "Kiis", &id, &action, &code, &line))
- return NULL;
-
- switch (action) {
- case FILTER_FAIL:
- case FILTER_CLOSE:
- filter_api_reject_code(id, action, code, line);
- Py_RETURN_TRUE;
- break;
- }
- Py_RETURN_FALSE;
-}
-
-static PyObject *
-py_filter_writeln(PyObject *self, PyObject *args)
-{
- uint64_t id;
- const char *line;
-
- if (!PyArg_ParseTuple(args, "Ks", &id, &line))
- return NULL;
- filter_api_writeln(id, line);
- Py_RETURN_TRUE;
-}
-
-static PyMethodDef py_methods[] = {
- { "accept", py_filter_accept, METH_VARARGS, "accept" },
- { "reject", py_filter_reject, METH_VARARGS, "reject" },
- { "reject_code", py_filter_reject_code, METH_VARARGS, "reject_code" },
- { "writeln", py_filter_writeln, METH_VARARGS, "writeln" },
- { NULL, NULL, 0, NULL }
-};
-
-
-static int
-on_connect(uint64_t id, struct filter_connect *conn)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
- PyObject *py_local;
- PyObject *py_remote;
- PyObject *py_hostname;
-
- py_args = PyTuple_New(4);
- py_id = PyLong_FromUnsignedLongLong(id);
- py_local = PyString_FromString(filter_api_sockaddr_to_text((struct sockaddr *)&conn->local));
- py_remote = PyString_FromString(filter_api_sockaddr_to_text((struct sockaddr *)&conn->remote));
- py_hostname = PyString_FromString(conn->hostname);
-
- PyTuple_SetItem(py_args, 0, py_id);
- PyTuple_SetItem(py_args, 1, py_local);
- PyTuple_SetItem(py_args, 2, py_remote);
- PyTuple_SetItem(py_args, 3, py_hostname);
-
- py_ret = PyObject_CallObject(py_on_connect, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_connect: handler failed");
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_helo(uint64_t id, const char *helo)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
- PyObject *py_helo;
-
- py_args = PyTuple_New(2);
- py_id = PyLong_FromUnsignedLongLong(id);
- py_helo = PyString_FromString(helo);
-
- PyTuple_SetItem(py_args, 0, py_id);
- PyTuple_SetItem(py_args, 1, py_helo);
-
- py_ret = PyObject_CallObject(py_on_helo, py_args);
- Py_DECREF(py_args);
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_helo: handler failed");
- exit(1);
- }
- return 1;
-}
-
-static int
-on_mail(uint64_t id, struct mailaddr *mail)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
- PyObject *py_sender;
-
- py_args = PyTuple_New(2);
- py_id = PyLong_FromUnsignedLongLong(id);
- py_sender = PyString_FromString(filter_api_mailaddr_to_text(mail));
-
- PyTuple_SetItem(py_args, 0, py_id);
- PyTuple_SetItem(py_args, 1, py_sender);
-
- py_ret = PyObject_CallObject(py_on_mail, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_mail: handler failed");
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_rcpt(uint64_t id, struct mailaddr *rcpt)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
- PyObject *py_rcpt;
-
- py_args = PyTuple_New(2);
- py_id = PyLong_FromUnsignedLongLong(id);
- py_rcpt = PyString_FromString(filter_api_mailaddr_to_text(rcpt));
-
- PyTuple_SetItem(py_args, 0, py_id);
- PyTuple_SetItem(py_args, 1, py_rcpt);
-
- py_ret = PyObject_CallObject(py_on_rcpt, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_rcpt: handler failed");
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_data(uint64_t id)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
-
- py_args = PyTuple_New(1);
- py_id = PyLong_FromUnsignedLongLong(id);
- PyTuple_SetItem(py_args, 0, py_id);
- py_ret = PyObject_CallObject(py_on_data, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_data: handler failed");
- exit(1);
- }
-
- return 1;
-}
-
-static int
-on_eom(uint64_t id, size_t sz)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
- PyObject *py_sz;
-
- py_args = PyTuple_New(2);
- py_id = PyLong_FromUnsignedLongLong(id);
- py_sz = PyLong_FromSize_t(sz);
- PyTuple_SetItem(py_args, 0, py_id);
- PyTuple_SetItem(py_args, 1, py_sz);
- py_ret = PyObject_CallObject(py_on_eom, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_eom: handler failed");
- exit(1);
- }
-
- return 1;
-}
-
-static void
-on_tx_begin(uint64_t id)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
-
- py_args = PyTuple_New(1);
- py_id = PyLong_FromUnsignedLongLong(id);
- PyTuple_SetItem(py_args, 0, py_id);
- py_ret = PyObject_CallObject(py_on_tx_begin, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_tx_begin: handler failed");
- exit(1);
- }
-}
-
-static void
-on_tx_commit(uint64_t id)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
-
- py_args = PyTuple_New(1);
- py_id = PyLong_FromUnsignedLongLong(id);
- PyTuple_SetItem(py_args, 0, py_id);
- py_ret = PyObject_CallObject(py_on_tx_commit, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_tx_commit: handler failed");
- exit(1);
- }
-}
-
-static void
-on_tx_rollback(uint64_t id)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
-
- py_args = PyTuple_New(1);
- py_id = PyLong_FromUnsignedLongLong(id);
- PyTuple_SetItem(py_args, 0, py_id);
- py_ret = PyObject_CallObject(py_on_tx_rollback, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_tx_rollback: handler failed");
- exit(1);
- }
-}
-
-static void
-on_disconnect(uint64_t id)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
-
- py_args = PyTuple_New(1);
- py_id = PyLong_FromUnsignedLongLong(id);
- PyTuple_SetItem(py_args, 0, py_id);
- py_ret = PyObject_CallObject(py_on_disconnect, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_disconnect: handler failed");
- exit(1);
- }
-}
-
-static void
-on_dataline(uint64_t id, const char *line)
-{
- PyObject *py_args;
- PyObject *py_ret;
- PyObject *py_id;
- PyObject *py_line;
-
- py_args = PyTuple_New(2);
- py_id = PyLong_FromUnsignedLongLong(id);
- py_line = PyString_FromString(line);
-
- PyTuple_SetItem(py_args, 0, py_id);
- PyTuple_SetItem(py_args, 1, py_line);
-
- py_ret = PyObject_CallObject(py_on_dataline, py_args);
- Py_DECREF(py_args);
-
- if (py_ret == NULL) {
- PyErr_Print();
- log_warnx("warn: on_dataline: handler failed");
- exit(1);
- }
-}
-
-static char *
-loadfile(const char * path)
-{
- FILE *f;
- off_t oz;
- size_t sz;
- char *buf;
-
- if ((f = fopen(path, "r")) == NULL)
- err(1, "fopen");
-
- if (fseek(f, 0, SEEK_END) == -1)
- err(1, "fseek");
-
- oz = ftello(f);
-
- if (fseek(f, 0, SEEK_SET) == -1)
- err(1, "fseek");
-
- if (oz >= SIZE_MAX)
- errx(1, "too big");
-
- sz = oz;
-
- buf = xmalloc(sz + 1, "loadfile");
-
- if (fread(buf, 1, sz, f) != sz)
- err(1, "fread");
-
- buf[sz] = '\0';
-
- fclose(f);
-
- return buf;
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- char *c = NULL, *path, *buf;
- PyObject *self, *code, *module;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "c:dv")) != -1) {
- switch (ch) {
- case 'c':
- c = optarg;
- break;
- case 'd':
- d = 1;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
- if (argc == 0)
- errx(1, "missing path");
-
- if (c)
- c = strip(c);
- path = argv[0];
-
- log_init(d);
- log_verbose(v);
-
- Py_Initialize();
- self = Py_InitModule("filter", py_methods);
- PyModule_AddIntConstant(self, "FILTER_OK", FILTER_OK);
- PyModule_AddIntConstant(self, "FILTER_FAIL", FILTER_FAIL);
- PyModule_AddIntConstant(self, "FILTER_CLOSE", FILTER_CLOSE);
-
- buf = loadfile(path);
- code = Py_CompileString(buf, path, Py_file_input);
- free(buf);
-
- if (code == NULL) {
- PyErr_Print();
- log_warnx("warn: failed to compile %s", path);
- return 1;
- }
-
- module = PyImport_ExecCodeModuleEx("myfilter", code, path);
-
- if (module == NULL) {
- PyErr_Print();
- log_warnx("warn: failed to install module %s", path);
- return 1;
- }
-
- log_debug("debug: starting...");
-
- py_on_connect = PyObject_GetAttrString(module, "on_connect");
- if (py_on_connect && PyCallable_Check(py_on_connect))
- filter_api_on_connect(on_connect);
-
- py_on_helo = PyObject_GetAttrString(module, "on_helo");
- if (py_on_helo && PyCallable_Check(py_on_helo))
- filter_api_on_helo(on_helo);
-
- py_on_mail = PyObject_GetAttrString(module, "on_mail");
- if (py_on_mail && PyCallable_Check(py_on_mail))
- filter_api_on_mail(on_mail);
-
- py_on_rcpt = PyObject_GetAttrString(module, "on_rcpt");
- if (py_on_rcpt && PyCallable_Check(py_on_rcpt))
- filter_api_on_rcpt(on_rcpt);
-
- py_on_data = PyObject_GetAttrString(module, "on_data");
- if (py_on_data && PyCallable_Check(py_on_data))
- filter_api_on_data(on_data);
-
- py_on_eom = PyObject_GetAttrString(module, "on_eom");
- if (py_on_eom && PyCallable_Check(py_on_eom))
- filter_api_on_eom(on_eom);
-
- py_on_tx_begin = PyObject_GetAttrString(module, "on_tx_begin");
- if (py_on_tx_begin && PyCallable_Check(py_on_tx_begin))
- filter_api_on_tx_begin(on_tx_begin);
-
- py_on_tx_commit = PyObject_GetAttrString(module, "on_tx_commit");
- if (py_on_tx_commit && PyCallable_Check(py_on_tx_commit))
- filter_api_on_tx_commit(on_tx_commit);
-
- py_on_tx_rollback = PyObject_GetAttrString(module, "on_tx_rollback");
- if (py_on_tx_rollback && PyCallable_Check(py_on_tx_rollback))
- filter_api_on_tx_rollback(on_tx_rollback);
-
- py_on_dataline = PyObject_GetAttrString(module, "on_dataline");
- if (py_on_dataline && PyCallable_Check(py_on_dataline))
- filter_api_on_dataline(on_dataline);
-
- py_on_disconnect = PyObject_GetAttrString(module, "on_disconnect");
- if (py_on_disconnect && PyCallable_Check(py_on_disconnect))
- filter_api_on_disconnect(on_disconnect);
-
- filter_api_no_chroot();
- if (c)
- filter_api_set_chroot(c);
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- Py_Finalize();
-
- return 1;
-}
diff --git a/extras/filters/filter-regex/Makefile.am b/extras/filters/filter-regex/Makefile.am
deleted file mode 100644
index 1ed4e7e..0000000
--- a/extras/filters/filter-regex/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-regex
-
-filter_regex_SOURCES = $(SRCS)
-filter_regex_SOURCES += filter_regex.c
-
-man_MANS = filter-regex.8 filter-regex.conf.5
-
-filter-regex.8: filter-regex.8.in
- $(SED) -e 's|[@]SYSCONFDIR@|$(sysconfdir)|g' < filter-regex.8.in > "$@"
-filter-regex.conf.5: filter-regex.conf.5.in
- $(SED) -e 's|[@]SYSCONFDIR@|$(sysconfdir)|g' < filter-regex.conf.5.in > "$@"
-
-clean-local:
- rm -f filter-regex.8 filter-regex.conf.5
diff --git a/extras/filters/filter-regex/filter-regex.8.in b/extras/filters/filter-regex/filter-regex.8.in
deleted file mode 100644
index 33ffad3..0000000
--- a/extras/filters/filter-regex/filter-regex.8.in
+++ /dev/null
@@ -1,90 +0,0 @@
-.\"
-.\" Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 16 2016 $
-.Dt FILTER-REGEX 8
-.Os
-.Sh NAME
-.Nm filter-regex
-.Nd smtpd filter for regular expression filtering
-.Sh SYNOPSIS
-.Nm
-.Op Fl dv
-.Op Fl l Ar limit
-.Op Ar file
-.Sh DESCRIPTION
-.Nm
-is a filter for
-.Xr smtpd 8
-which can be used to filter mails using regular expressions matching SMTP
-session parameters.
-.Pp
-The options are as follows:
-.Bl -tag -width "-l limit"
-.It Fl d
-Debug mode, if this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl l Ar limit
-Set the number of bytes
-.Ar limit
-after which the regular expression processing is stopped and the mail is
-accepted.
-The accepted values are within the range of 1 and SIZE_MAX.
-.Pp
-The default
-.Ar limit
-value is 0 (unlimited).
-.It Fl v
-Produce more verbose output.
-.El
-.Pp
-.Nm
-runs by default in a chroot.
-.Pp
-The debug and verbose options given with the
-.Xr smtpd 8
-invocation are intially passed to
-.Nm .
-.Pp
-Depending if one of the regular expressions matches mails are either accepted
-or rejected with a SMTP 554 reply.
-Non-matching mails are always accepted.
-.Sh FILES
-.Bl -tag -width "@SYSCONFDIR@/filter-regex.conf" -compact
-.It Pa @SYSCONFDIR@/filter-regex.conf
-Default
-.Nm
-configuration file.
-.El
-.Sh SEE ALSO
-.Xr filter_api 3 ,
-.Xr regex 3 ,
-.Xr filter-regex.conf 5 ,
-.Xr smtpd.conf 5 ,
-.Xr re_format 7 ,
-.Xr smtpd 8
-.Sh HISTORY
-The first version of
-.Nm
-was written in 2015.
-.Sh AUTHORS
-.An -nosplit
-.Nm
-was intially written by
-.An Armin Wolfermann Aq Mt armin@wolfermann.org
-and further improved by
-.An Joerg Jung Aq Mt jung@openbsd.org .
diff --git a/extras/filters/filter-regex/filter-regex.conf b/extras/filters/filter-regex/filter-regex.conf
deleted file mode 100644
index c449d73..0000000
--- a/extras/filters/filter-regex/filter-regex.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-# opensmptd-extras filter-regex configuration
-
-# reject a host
-#connect ^host\.example\.com$
-
-# allow a specific hosts while rejecting the rest of the domain
-#connect ! ^allow\.example\.net$
-#connect ^.*\.example\.net$
-
-# reject helo with leading or trailing dot, and without dots (non-FQDN)
-# skipping address literals
-#helo ! ^\[
-#helo ^\.
-#helo \.$
-#helo ^[^\.]*$
-
-# reject some senders
-#mail ^.*@example\.com$
-#mail ^.*@example\.net$
-
-# reject some recipients
-#rcpt ^.*@example\.org$
-
-# reject some content
-#dataline ^Content-Type: application/x-msdownload; name="[a-z]*\.[a-z]*"
-#dataline (Viagra|Cialis)
diff --git a/extras/filters/filter-regex/filter-regex.conf.5.in b/extras/filters/filter-regex/filter-regex.conf.5.in
deleted file mode 100644
index fabd928..0000000
--- a/extras/filters/filter-regex/filter-regex.conf.5.in
+++ /dev/null
@@ -1,126 +0,0 @@
-.\"
-.\" Copyright (c) 2015 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 15 2015 $
-.Dt FILTER-REGEX.CONF 5
-.Os
-.Sh NAME
-.Nm filter-regex.conf
-.Nd filter-regex configuration file
-.Sh DESCRIPTION
-.Nm
-is the configuration file for
-.Xr filter-regex 8 .
-.Pp
-The file consists of rules that, when matched, cause
-.Xr filter-regex 8
-to reject mails.
-.Pp
-Comments can be put anywhere in the file using a hash mark
-.Pq Sq # ,
-and extend to the end of the current line.
-Emtpy lines and lines starting with
-.Sq #
-are ignored, as well as leading whitespaces.
-.Pp
-The syntax of
-.Nm
-is described below.
-.Bl -tag -width Ds
-.It Xo
-.Ic connect
-.Op Ic \&!
-.Pf < Ar hostname Ns >
-.Xc
-Reject the connection if the connection sender's
-.Ar hostname
-matches the specified regular expressions.
-.It Xo
-.Ic helo
-.Op Ic \&!
-.Pf < Ar name Ns >
-.Xc
-Reject the connection if the sender supplied HELO
-.Ar name
-matches the specified regular expression.
-.It Xo
-.Ic mail
-.Op Ic \&!
-.Pf < Ar address Ns >
-.Xc
-Reject the mail if the sender supplied MAIL FROM
-.Ar address
-matches the specified regular expression.
-.It Xo
-.Ic rcpt
-.Op Ic \&!
-.Pf < Ar address Ns >
-.Xc
-Reject the mail if the sender supplied RCPT TO
-.Ar address
-matches the specified regular expression.
-.It Xo
-.Ic dataline
-.Op Ic \&!
-.Pf < Ar line Ns >
-.Xc
-Reject the mail if a data (header or body)
-.Ar line
-matches the specified regular expression.
-.El
-.Sh REGULAR EXPRESSIONS
-The regular expressions used in the configuration rules do not need further
-escaping.
-.Pp
-The optional
-.Sq \&!
-character in front of the regular expression (separated by a whitespace)
-reverses the matching result and causes the rule, when matched, to be accepted.
-This is considered a negotiation and break operation, thus allows exceptions to
-the actual rejection rules.
-.Pp
-All subsequent argument characters up to the end of the line are taken
-literally as the regular expression.
-.Pp
-See
-.Xr re_format 7
-for a detailed description of basic and extended regular expressions.
-.Sh EXAMPLES
-The default filter-regex.conf file which ships with OpenSMTPD-extras contains
-commented examples.
-.Sh FILES
-.Bl -tag -width "@SYSCONFDIR@/filter-regex.conf" -compact
-.It Pa @SYSCONFDIR@/filter-regex.conf
-Default
-.Xr filter-regex 8
-configuration file.
-.El
-.Sh SEE ALSO
-.Xr filter_api 3 ,
-.Xr regex 3 ,
-.Xr smtpd.conf 5 ,
-.Xr re_format 7 ,
-.Xr filter-regex 8 ,
-.Xr smtpd 8
-.Sh HISTORY
-The first version of
-.Xr filter-regex 8
-was written in 2015.
-.Sh AUTHORS
-.Xr filter-regex 8
-was intially written by
-.An Armin Wolfermann Aq Mt armin@wolfermann.org
-and further improved by
-.An Joerg Jung Aq Mt jung@openbsd.org .
diff --git a/extras/filters/filter-regex/filter_regex.c b/extras/filters/filter-regex/filter_regex.c
deleted file mode 100644
index 02fd36e..0000000
--- a/extras/filters/filter-regex/filter_regex.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (c) 2015, Armin Wolfermann <armin@wolfermann.org>
- * Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <ctype.h>
-#include <regex.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-#define REGEX_CONF SMTPD_CONFDIR "/filter-regex.conf"
-
-struct regex {
- SIMPLEQ_ENTRY(regex) el;
- char *s, n;
- regex_t p;
-};
-
-static SIMPLEQ_HEAD(regex_q, regex)
- regex_connect = SIMPLEQ_HEAD_INITIALIZER(regex_connect),
- regex_helo = SIMPLEQ_HEAD_INITIALIZER(regex_helo),
- regex_mail = SIMPLEQ_HEAD_INITIALIZER(regex_mail),
- regex_rcpt = SIMPLEQ_HEAD_INITIALIZER(regex_rcpt),
- regex_dataline = SIMPLEQ_HEAD_INITIALIZER(regex_dataline);
-static struct { const char *s; struct regex_q *rq; } regex_s[] = {
- { "connect", &regex_connect }, { "helo", &regex_helo },
- { "mail", &regex_mail }, { "rcpt", &regex_rcpt },
- { "dataline", &regex_dataline }, { NULL, NULL } };
-static size_t regex_limit;
-
-static int
-regex_parse(char *l, size_t no)
-{
- struct regex_q *rq = NULL;
- struct regex *re;
- char *k, buf[BUFSIZ];
- int i, r;
-
- l = strip(l);
- if ((k = strsep(&l, " \t")) == NULL || strlen(k) == 0 || *k == '#')
- return 0; /* skip empty or commented line */
- for (i = 0; regex_s[i].s != NULL && rq == NULL; i++)
- if (strcmp(k, regex_s[i].s) == 0)
- rq = regex_s[i].rq;
- if (rq == NULL) {
- log_warnx("warn: parse: unknown keyword %s line %lu", k, no);
- return -1;
- }
- if (strlen((l = strip(l))) == 0 || *l == '#') {
- log_warnx("warn: parse: missing value line %lu", no);
- return -1;
- }
- re = xcalloc(1, sizeof(struct regex), "parse");
- re->s = xstrdup(l, "parse");
- if ((re->n = (l[0] == '!' && isspace((unsigned char)l[1]))))
- l = strip(++l);
- if ((r = regcomp(&re->p, l, REG_EXTENDED|REG_NOSUB)) != 0) {
- regerror(r, &re->p, buf, sizeof(buf));
- log_warnx("warn: parse: regcomp %s line %lu", buf, no);
- free(re->s);
- free(re);
- return -1;
- }
- SIMPLEQ_INSERT_TAIL(rq, re, el);
- log_debug("debug: parse: %s %s line %lu", k, re->s, no);
- return 0;
-}
-
-static int
-regex_load(const char *c)
-{
- FILE *f;
- char *l = NULL;
- size_t sz = 0, no = 0;
- ssize_t len;
-
- if ((f = fopen(c, "r")) == NULL) {
- log_warn("warn: load: fopen %s", c);
- return -1;
- }
- while ((len = getline(&l, &sz, f)) != -1) {
- if (l[len - 1] == '\n')
- l[len - 1] = '\0';
- if (regex_parse(l, ++no) == -1) {
- free(l);
- fclose(f);
- return -1;
- }
- }
- if (ferror(f)) {
- log_warn("warn: load: getline");
- free(l);
- fclose(f);
- return -1;
- }
- free(l);
- fclose(f);
- return 0;
-}
-
-static int
-regex_match(struct regex_q *rq, const char *s)
-{
- struct regex *re;
- char buf[BUFSIZ];
- int r;
-
- SIMPLEQ_FOREACH(re, rq, el) {
- if ((r = regexec(&re->p, s, 0, NULL, 0)) != 0) {
- if (r != REG_NOMATCH) {
- regerror(r, &re->p, buf, sizeof(buf));
- log_warnx("warn: match: regexec %s", buf);
- }
- continue;
- }
- log_info("info: match: %s to %s", re->s, s);
- return (re->n == 0);
- }
- return 0;
-}
-
-static void
-regex_clear(void)
-{
- struct regex *re;
- int i;
-
- for (i = 0; regex_s[i].rq != NULL; i++) {
- while((re = SIMPLEQ_FIRST(regex_s[i].rq)) != NULL) {
- SIMPLEQ_REMOVE_HEAD(regex_s[i].rq, el);
- regfree(&re->p);
- free(re->s);
- free(re);
- }
- }
-}
-
-static int
-regex_on_connect(uint64_t id, struct filter_connect *c)
-{
- if (regex_match(&regex_connect, c->hostname)) {
- log_warnx("warn: session %016"PRIx64": on_connect: REJECT connect hostname", id);
- return filter_api_reject_code(id, FILTER_FAIL, 554, "5.7.1 Hostname rejected");
- }
- return filter_api_accept(id);
-}
-
-static int
-regex_on_helo(uint64_t id, const char *h)
-{
- if (regex_match(&regex_helo, h)) {
- log_warnx("warn: session %016"PRIx64": on_helo: REJECT helo hostname", id);
- return filter_api_reject_code(id, FILTER_FAIL, 554, "5.7.1 Helo rejected");
- }
- return filter_api_accept(id);
-}
-
-static int
-regex_on_mail(uint64_t id, struct mailaddr *m)
-{
- if (regex_match(&regex_mail, filter_api_mailaddr_to_text(m))) {
- log_warnx("warn: session %016"PRIx64": on_mail: REJECT mail from", id);
- return filter_api_reject_code(id, FILTER_FAIL, 554, "5.7.1 Sender rejected");
- }
- return filter_api_accept(id);
-}
-
-static int
-regex_on_rcpt(uint64_t id, struct mailaddr *r)
-{
- if (regex_match(&regex_rcpt, filter_api_mailaddr_to_text(r))) {
- log_warnx("warn: session %016"PRIx64": on_rcpt: REJECT rcpt to", id);
- return filter_api_reject_code(id, FILTER_FAIL, 554, "5.7.1 Recipient rejected");
- }
- return filter_api_accept(id);
-}
-
-static void
-regex_on_dataline(uint64_t id, const char *l)
-{
- struct { int m; size_t l; } *u;
-
- filter_api_writeln(id, l);
- if ((u = filter_api_get_udata(id)) == NULL) {
- u = xcalloc(1, sizeof(*u), "on_dataline");
- filter_api_set_udata(id, u);
- }
- u->l += strlen(l);
- if (u->m || (regex_limit && u->l >= regex_limit))
- return;
- u->m = regex_match(&regex_dataline, l);
-}
-
-static int
-regex_on_eom(uint64_t id, size_t size)
-{
- int *m;
-
- if ((m = filter_api_get_udata(id)) == NULL)
- return filter_api_accept(id);
- if (*m) {
- log_warnx("warn: session %016"PRIx64": on_eom: REJECT dataline", id);
- return filter_api_reject_code(id, FILTER_CLOSE, 554, "5.7.1 Message content rejected");
- }
- return filter_api_accept(id);
-}
-
-static void
-regex_on_tx_commit(uint64_t id)
-{
- free(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-static void
-regex_on_tx_rollback(uint64_t id)
-{
- free(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- const char *errstr, *l = NULL;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "dl:v")) != -1) {
- switch (ch) {
- case 'd':
- d = 1;
- break;
- case 'l':
- l = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
- if (argc > 1)
- fatalx("bogus argument(s)");
-
- if (l) {
- regex_limit = strtonum(l, 1, UINT_MAX, &errstr); /* todo: SIZE_MAX here? */
- if (errstr)
- fatalx("limit option is %s: %s", errstr, l);
- }
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
- if (regex_load((argc == 1) ? argv[0] : REGEX_CONF) == -1)
- fatalx("configuration failed");
-
- filter_api_on_connect(regex_on_connect);
- filter_api_on_helo(regex_on_helo);
- filter_api_on_mail(regex_on_mail);
- filter_api_on_rcpt(regex_on_rcpt);
- filter_api_on_dataline(regex_on_dataline);
- filter_api_on_eom(regex_on_eom);
- filter_api_on_tx_commit(regex_on_tx_commit);
- filter_api_on_tx_rollback(regex_on_tx_rollback);
-
- filter_api_loop();
- regex_clear();
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-rspamd/Makefile.am b/extras/filters/filter-rspamd/Makefile.am
deleted file mode 100644
index a01d3b6..0000000
--- a/extras/filters/filter-rspamd/Makefile.am
+++ /dev/null
@@ -1,13 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-rspamd
-
-filter_rspamd_SOURCES = $(SRCS)
-filter_rspamd_SOURCES += filter_rspamd.c
-filter_rspamd_SOURCES += rspamd.c
-filter_rspamd_SOURCES += json.c
-filter_rspamd_SOURCES += fixme.c
-
-LDFLAGS += -lm
diff --git a/extras/filters/filter-rspamd/filter_rspamd.c b/extras/filters/filter-rspamd/filter_rspamd.c
deleted file mode 100644
index f4c3bbd..0000000
--- a/extras/filters/filter-rspamd/filter_rspamd.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2016 Gilles Chehade <gilles@poolp.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-#include "rspamd.h"
-
-
-static int
-on_connect(uint64_t id, struct filter_connect *conn)
-{
- struct session *rs = filter_api_session(id);
- const char *ip;
-
- ip = filter_api_sockaddr_to_text((struct sockaddr *)&conn->local);
- if (! session_set_ip(rs, ip ? ip : "127.0.0.1"))
- return filter_api_reject_code(id, FILTER_FAIL, 421,
- "temporary failure");
-
- if (! session_set_hostname(rs, conn->hostname))
- return filter_api_reject_code(id, FILTER_FAIL, 421,
- "temporary failure");
-
- return filter_api_accept(id);
-}
-
-static int
-on_helo(uint64_t id, const char *helo)
-{
- struct session *rs = filter_api_session(id);
-
- if (! session_set_helo(rs, helo))
- return filter_api_reject_code(id, FILTER_FAIL, 421,
- "temporary failure");
-
- return filter_api_accept(id);
-}
-
-static int
-on_mail(uint64_t id, struct mailaddr *mail)
-{
- struct transaction *tx = filter_api_transaction(id);
- const char *address;
-
- address = filter_api_mailaddr_to_text(mail);
- if (! transaction_set_from(tx, address))
- return filter_api_reject_code(id, FILTER_FAIL, 421,
- "temporary failure");
-
- return filter_api_accept(id);
-}
-
-static int
-on_rcpt(uint64_t id, struct mailaddr *rcpt)
-{
- struct transaction *tx = filter_api_transaction(id);
- const char *address;
-
- address = filter_api_mailaddr_to_text(rcpt);
- if (! transaction_add_rcpt(tx, address))
- return filter_api_reject_code(id, FILTER_FAIL, 421,
- "temporary failure");
-
- return filter_api_accept(id);
-}
-
-static int
-on_data(uint64_t id)
-{
- struct transaction *tx = filter_api_transaction(id);
-
- if (! rspamd_connect(tx))
- return filter_api_reject_code(id, FILTER_FAIL, 421,
- "temporary failure");
-
- /* accept/reject is called from rspamd.c */
- return 1;
-}
-
-static void
-on_dataline(uint64_t id, const char *line)
-{
- struct transaction *tx = filter_api_transaction(id);
-
- rspamd_send_chunk(tx, line);
-}
-
-static int
-on_eom(uint64_t id, size_t size)
-{
- struct transaction *tx = filter_api_transaction(id);
-
- rspamd_send_chunk(tx, NULL);
-
- /* accept/reject is called from rspamd.c */
- return 1;
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, C = 0, d = 0, v = 0;
- const char *l = NULL;
- char *c = NULL, *h = RSPAMD_HOST, *p = RSPAMD_PORT, *s = NULL;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "dh:l:p:s:v")) != -1) {
- switch (ch) {
- case 'C':
- C = 1;
- break;
- case 'c':
- c = optarg;
- break;
- case 'd':
- d = 1;
- break;
- case 'h':
- h = optarg;
- break;
- case 'l':
- l = optarg;
- break;
- case 'p':
- p = optarg;
- break;
- case 's':
- s = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (c)
- c = strip(c);
- if (h)
- h = strip(h);
- if (p)
- p = strip(p);
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
-
- rspamd_resolve(h, p);
-
- filter_api_on_connect(on_connect);
- filter_api_on_helo(on_helo);
- filter_api_on_mail(on_mail);
- filter_api_on_rcpt(on_rcpt);
- filter_api_on_data(on_data);
- filter_api_on_dataline(on_dataline);
- filter_api_on_eom(on_eom);
-
- filter_api_session_allocator(session_allocator);
- filter_api_session_destructor(session_destructor);
-
- filter_api_transaction_allocator(transaction_allocator);
- filter_api_transaction_destructor(transaction_destructor);
-
- filter_api_data_buffered();
-
- /*
- if (c)
- filter_api_set_chroot(c);
- if (C)
- filter_api_no_chroot();
- */
- filter_api_no_chroot();
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- return 1;
-}
diff --git a/extras/filters/filter-rspamd/fixme.c b/extras/filters/filter-rspamd/fixme.c
deleted file mode 100644
index 74c5a55..0000000
--- a/extras/filters/filter-rspamd/fixme.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2016 Gilles Chehade <gilles@poolp.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-#include "rspamd.h"
-
-struct sockaddr_storage ss;
-
-
-/* XXX
- * this needs to be handled differently, but lets focus on the filter for now
- */
-void
-rspamd_resolve(const char *h, const char *p)
-{
- struct addrinfo hints, *addresses, *ai;
- int fd, r;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if ((r = getaddrinfo(h, p, &hints, &addresses)))
- fatalx("resolve: getaddrinfo %s", gai_strerror(r));
- for (ai = addresses; ai; ai = ai->ai_next) {
- if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1)
- continue;
- if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
- close(fd);
- continue;
- }
- close(fd);
- memmove(&ss, ai->ai_addr, ai->ai_addrlen);
- break;
- }
- freeaddrinfo(addresses);
- if (!ai)
- fatalx("resolve: failed");
-}
diff --git a/extras/filters/filter-rspamd/json.c b/extras/filters/filter-rspamd/json.c
deleted file mode 100644
index ea975e8..0000000
--- a/extras/filters/filter-rspamd/json.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
- *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
- * https://github.com/udp/json-parser
- *
- * 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.
- */
-
-#include "json.h"
-
-#ifdef _MSC_VER
- #ifndef _CRT_SECURE_NO_WARNINGS
- #define _CRT_SECURE_NO_WARNINGS
- #endif
-#endif
-
-const struct _json_value json_value_none;
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-
-typedef unsigned int json_uchar;
-
-static unsigned char hex_value (json_char c)
-{
- if (isdigit(c))
- return c - '0';
-
- switch (c) {
- case 'a': case 'A': return 0x0A;
- case 'b': case 'B': return 0x0B;
- case 'c': case 'C': return 0x0C;
- case 'd': case 'D': return 0x0D;
- case 'e': case 'E': return 0x0E;
- case 'f': case 'F': return 0x0F;
- default: return 0xFF;
- }
-}
-
-typedef struct
-{
- unsigned long used_memory;
-
- unsigned int uint_max;
- unsigned long ulong_max;
-
- json_settings settings;
- int first_pass;
-
- const json_char * ptr;
- unsigned int cur_line, cur_col;
-
-} json_state;
-
-static void * default_alloc (size_t size, int zero, void * user_data)
-{
- return zero ? calloc (1, size) : malloc (size);
-}
-
-static void default_free (void * ptr, void * user_data)
-{
- free (ptr);
-}
-
-static void * json_alloc (json_state * state, unsigned long size, int zero)
-{
- if ((state->ulong_max - state->used_memory) < size)
- return 0;
-
- if (state->settings.max_memory
- && (state->used_memory += size) > state->settings.max_memory)
- {
- return 0;
- }
-
- return state->settings.mem_alloc (size, zero, state->settings.user_data);
-}
-
-static int new_value (json_state * state,
- json_value ** top, json_value ** root, json_value ** alloc,
- json_type type)
-{
- json_value * value;
- int values_size;
-
- if (!state->first_pass)
- {
- value = *top = *alloc;
- *alloc = (*alloc)->_reserved.next_alloc;
-
- if (!*root)
- *root = value;
-
- switch (value->type)
- {
- case json_array:
-
- if (value->u.array.length == 0)
- break;
-
- if (! (value->u.array.values = (json_value **) json_alloc
- (state, value->u.array.length * sizeof (json_value *), 0)) )
- {
- return 0;
- }
-
- value->u.array.length = 0;
- break;
-
- case json_object:
-
- if (value->u.object.length == 0)
- break;
-
- values_size = sizeof (*value->u.object.values) * value->u.object.length;
-
- if (! (value->u.object.values = (json_object_entry *) json_alloc
- (state, values_size + ((unsigned long) value->u.object.values), 0)) )
- {
- return 0;
- }
-
- value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
-
- value->u.object.length = 0;
- break;
-
- case json_string:
-
- if (! (value->u.string.ptr = (json_char *) json_alloc
- (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
- {
- return 0;
- }
-
- value->u.string.length = 0;
- break;
-
- default:
- break;
- };
-
- return 1;
- }
-
- if (! (value = (json_value *) json_alloc
- (state, sizeof (json_value) + state->settings.value_extra, 1)))
- {
- return 0;
- }
-
- if (!*root)
- *root = value;
-
- value->type = type;
- value->parent = *top;
-
- #ifdef JSON_TRACK_SOURCE
- value->line = state->cur_line;
- value->col = state->cur_col;
- #endif
-
- if (*alloc)
- (*alloc)->_reserved.next_alloc = value;
-
- *alloc = *top = value;
-
- return 1;
-}
-
-#define whitespace \
- case '\n': ++ state.cur_line; state.cur_col = 0; \
- case ' ': case '\t': case '\r'
-
-#define string_add(b) \
- do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
-
-#define line_and_col \
- state.cur_line, state.cur_col
-
-static const long
- flag_next = 1 << 0,
- flag_reproc = 1 << 1,
- flag_need_comma = 1 << 2,
- flag_seek_value = 1 << 3,
- flag_escaped = 1 << 4,
- flag_string = 1 << 5,
- flag_need_colon = 1 << 6,
- flag_done = 1 << 7,
- flag_num_negative = 1 << 8,
- flag_num_zero = 1 << 9,
- flag_num_e = 1 << 10,
- flag_num_e_got_sign = 1 << 11,
- flag_num_e_negative = 1 << 12,
- flag_line_comment = 1 << 13,
- flag_block_comment = 1 << 14;
-
-json_value * json_parse_ex (json_settings * settings,
- const json_char * json,
- size_t length,
- char * error_buf)
-{
- json_char error [json_error_max];
- const json_char * end;
- json_value * top, * root, * alloc = 0;
- json_state state = { 0 };
- long flags;
- long num_digits = 0, num_e = 0;
- json_int_t num_fraction = 0;
-
- /* Skip UTF-8 BOM
- */
- if (length >= 3 && ((unsigned char) json [0]) == 0xEF
- && ((unsigned char) json [1]) == 0xBB
- && ((unsigned char) json [2]) == 0xBF)
- {
- json += 3;
- length -= 3;
- }
-
- error[0] = '\0';
- end = (json + length);
-
- memcpy (&state.settings, settings, sizeof (json_settings));
-
- if (!state.settings.mem_alloc)
- state.settings.mem_alloc = default_alloc;
-
- if (!state.settings.mem_free)
- state.settings.mem_free = default_free;
-
- memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
- memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
-
- state.uint_max -= 8; /* limit of how much can be added before next check */
- state.ulong_max -= 8;
-
- for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
- {
- json_uchar uchar;
- unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
- json_char * string = 0;
- unsigned int string_length = 0;
-
- top = root = 0;
- flags = flag_seek_value;
-
- state.cur_line = 1;
-
- for (state.ptr = json ;; ++ state.ptr)
- {
- json_char b = (state.ptr == end ? 0 : *state.ptr);
-
- if (flags & flag_string)
- {
- if (!b)
- { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
- goto e_failed;
- }
-
- if (string_length > state.uint_max)
- goto e_overflow;
-
- if (flags & flag_escaped)
- {
- flags &= ~ flag_escaped;
-
- switch (b)
- {
- case 'b': string_add ('\b'); break;
- case 'f': string_add ('\f'); break;
- case 'n': string_add ('\n'); break;
- case 'r': string_add ('\r'); break;
- case 't': string_add ('\t'); break;
- case 'u':
-
- if (end - state.ptr < 4 ||
- (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
- {
- sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
- goto e_failed;
- }
-
- uc_b1 = (uc_b1 << 4) | uc_b2;
- uc_b2 = (uc_b3 << 4) | uc_b4;
- uchar = (uc_b1 << 8) | uc_b2;
-
- if ((uchar & 0xF800) == 0xD800) {
- json_uchar uchar2;
-
- if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
- (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
- {
- sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
- goto e_failed;
- }
-
- uc_b1 = (uc_b1 << 4) | uc_b2;
- uc_b2 = (uc_b3 << 4) | uc_b4;
- uchar2 = (uc_b1 << 8) | uc_b2;
-
- uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
- }
-
- if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
- {
- string_add ((json_char) uchar);
- break;
- }
-
- if (uchar <= 0x7FF)
- {
- if (state.first_pass)
- string_length += 2;
- else
- { string [string_length ++] = 0xC0 | (uchar >> 6);
- string [string_length ++] = 0x80 | (uchar & 0x3F);
- }
-
- break;
- }
-
- if (uchar <= 0xFFFF) {
- if (state.first_pass)
- string_length += 3;
- else
- { string [string_length ++] = 0xE0 | (uchar >> 12);
- string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
- string [string_length ++] = 0x80 | (uchar & 0x3F);
- }
-
- break;
- }
-
- if (state.first_pass)
- string_length += 4;
- else
- { string [string_length ++] = 0xF0 | (uchar >> 18);
- string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
- string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
- string [string_length ++] = 0x80 | (uchar & 0x3F);
- }
-
- break;
-
- default:
- string_add (b);
- };
-
- continue;
- }
-
- if (b == '\\')
- {
- flags |= flag_escaped;
- continue;
- }
-
- if (b == '"')
- {
- if (!state.first_pass)
- string [string_length] = 0;
-
- flags &= ~ flag_string;
- string = 0;
-
- switch (top->type)
- {
- case json_string:
-
- top->u.string.length = string_length;
- flags |= flag_next;
-
- break;
-
- case json_object:
-
- if (state.first_pass)
- (*(json_char **) &top->u.object.values) += string_length + 1;
- else
- {
- top->u.object.values [top->u.object.length].name
- = (json_char *) top->_reserved.object_mem;
-
- top->u.object.values [top->u.object.length].name_length
- = string_length;
-
- (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
- }
-
- flags |= flag_seek_value | flag_need_colon;
- continue;
-
- default:
- break;
- };
- }
- else
- {
- string_add (b);
- continue;
- }
- }
-
- if (state.settings.settings & json_enable_comments)
- {
- if (flags & (flag_line_comment | flag_block_comment))
- {
- if (flags & flag_line_comment)
- {
- if (b == '\r' || b == '\n' || !b)
- {
- flags &= ~ flag_line_comment;
- -- state.ptr; /* so null can be reproc'd */
- }
-
- continue;
- }
-
- if (flags & flag_block_comment)
- {
- if (!b)
- { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
- goto e_failed;
- }
-
- if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
- {
- flags &= ~ flag_block_comment;
- ++ state.ptr; /* skip closing sequence */
- }
-
- continue;
- }
- }
- else if (b == '/')
- {
- if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
- { sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
- goto e_failed;
- }
-
- if (++ state.ptr == end)
- { sprintf (error, "%d:%d: EOF unexpected", line_and_col);
- goto e_failed;
- }
-
- switch (b = *state.ptr)
- {
- case '/':
- flags |= flag_line_comment;
- continue;
-
- case '*':
- flags |= flag_block_comment;
- continue;
-
- default:
- sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
- goto e_failed;
- };
- }
- }
-
- if (flags & flag_done)
- {
- if (!b)
- break;
-
- switch (b)
- {
- whitespace:
- continue;
-
- default:
-
- sprintf (error, "%d:%d: Trailing garbage: `%c`",
- state.cur_line, state.cur_col, b);
-
- goto e_failed;
- };
- }
-
- if (flags & flag_seek_value)
- {
- switch (b)
- {
- whitespace:
- continue;
-
- case ']':
-
- if (top && top->type == json_array)
- flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
- else
- { sprintf (error, "%d:%d: Unexpected ]", line_and_col);
- goto e_failed;
- }
-
- break;
-
- default:
-
- if (flags & flag_need_comma)
- {
- if (b == ',')
- { flags &= ~ flag_need_comma;
- continue;
- }
- else
- {
- sprintf (error, "%d:%d: Expected , before %c",
- state.cur_line, state.cur_col, b);
-
- goto e_failed;
- }
- }
-
- if (flags & flag_need_colon)
- {
- if (b == ':')
- { flags &= ~ flag_need_colon;
- continue;
- }
- else
- {
- sprintf (error, "%d:%d: Expected : before %c",
- state.cur_line, state.cur_col, b);
-
- goto e_failed;
- }
- }
-
- flags &= ~ flag_seek_value;
-
- switch (b)
- {
- case '{':
-
- if (!new_value (&state, &top, &root, &alloc, json_object))
- goto e_alloc_failure;
-
- continue;
-
- case '[':
-
- if (!new_value (&state, &top, &root, &alloc, json_array))
- goto e_alloc_failure;
-
- flags |= flag_seek_value;
- continue;
-
- case '"':
-
- if (!new_value (&state, &top, &root, &alloc, json_string))
- goto e_alloc_failure;
-
- flags |= flag_string;
-
- string = top->u.string.ptr;
- string_length = 0;
-
- continue;
-
- case 't':
-
- if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
- *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
- {
- goto e_unknown_value;
- }
-
- if (!new_value (&state, &top, &root, &alloc, json_boolean))
- goto e_alloc_failure;
-
- top->u.boolean = 1;
-
- flags |= flag_next;
- break;
-
- case 'f':
-
- if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
- *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
- *(++ state.ptr) != 'e')
- {
- goto e_unknown_value;
- }
-
- if (!new_value (&state, &top, &root, &alloc, json_boolean))
- goto e_alloc_failure;
-
- flags |= flag_next;
- break;
-
- case 'n':
-
- if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
- *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
- {
- goto e_unknown_value;
- }
-
- if (!new_value (&state, &top, &root, &alloc, json_null))
- goto e_alloc_failure;
-
- flags |= flag_next;
- break;
-
- default:
-
- if (isdigit (b) || b == '-')
- {
- if (!new_value (&state, &top, &root, &alloc, json_integer))
- goto e_alloc_failure;
-
- if (!state.first_pass)
- {
- while (isdigit (b) || b == '+' || b == '-'
- || b == 'e' || b == 'E' || b == '.')
- {
- if ( (++ state.ptr) == end)
- {
- b = 0;
- break;
- }
-
- b = *state.ptr;
- }
-
- flags |= flag_next | flag_reproc;
- break;
- }
-
- flags &= ~ (flag_num_negative | flag_num_e |
- flag_num_e_got_sign | flag_num_e_negative |
- flag_num_zero);
-
- num_digits = 0;
- num_fraction = 0;
- num_e = 0;
-
- if (b != '-')
- {
- flags |= flag_reproc;
- break;
- }
-
- flags |= flag_num_negative;
- continue;
- }
- else
- { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
- goto e_failed;
- }
- };
- };
- }
- else
- {
- switch (top->type)
- {
- case json_object:
-
- switch (b)
- {
- whitespace:
- continue;
-
- case '"':
-
- if (flags & flag_need_comma)
- { sprintf (error, "%d:%d: Expected , before \"", line_and_col);
- goto e_failed;
- }
-
- flags |= flag_string;
-
- string = (json_char *) top->_reserved.object_mem;
- string_length = 0;
-
- break;
-
- case '}':
-
- flags = (flags & ~ flag_need_comma) | flag_next;
- break;
-
- case ',':
-
- if (flags & flag_need_comma)
- {
- flags &= ~ flag_need_comma;
- break;
- }
-
- default:
- sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
- goto e_failed;
- };
-
- break;
-
- case json_integer:
- case json_double:
-
- if (isdigit (b))
- {
- ++ num_digits;
-
- if (top->type == json_integer || flags & flag_num_e)
- {
- if (! (flags & flag_num_e))
- {
- if (flags & flag_num_zero)
- { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
- goto e_failed;
- }
-
- if (num_digits == 1 && b == '0')
- flags |= flag_num_zero;
- }
- else
- {
- flags |= flag_num_e_got_sign;
- num_e = (num_e * 10) + (b - '0');
- continue;
- }
-
- top->u.integer = (top->u.integer * 10) + (b - '0');
- continue;
- }
-
- num_fraction = (num_fraction * 10) + (b - '0');
- continue;
- }
-
- if (b == '+' || b == '-')
- {
- if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
- {
- flags |= flag_num_e_got_sign;
-
- if (b == '-')
- flags |= flag_num_e_negative;
-
- continue;
- }
- }
- else if (b == '.' && top->type == json_integer)
- {
- if (!num_digits)
- { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
- goto e_failed;
- }
-
- top->type = json_double;
- top->u.dbl = (double) top->u.integer;
-
- num_digits = 0;
- continue;
- }
-
- if (! (flags & flag_num_e))
- {
- if (top->type == json_double)
- {
- if (!num_digits)
- { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
- goto e_failed;
- }
-
- top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));
- }
-
- if (b == 'e' || b == 'E')
- {
- flags |= flag_num_e;
-
- if (top->type == json_integer)
- {
- top->type = json_double;
- top->u.dbl = (double) top->u.integer;
- }
-
- num_digits = 0;
- flags &= ~ flag_num_zero;
-
- continue;
- }
- }
- else
- {
- if (!num_digits)
- { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
- goto e_failed;
- }
-
- top->u.dbl *= pow (10.0, (double)
- (flags & flag_num_e_negative ? - num_e : num_e));
- }
-
- if (flags & flag_num_negative)
- {
- if (top->type == json_integer)
- top->u.integer = - top->u.integer;
- else
- top->u.dbl = - top->u.dbl;
- }
-
- flags |= flag_next | flag_reproc;
- break;
-
- default:
- break;
- };
- }
-
- if (flags & flag_reproc)
- {
- flags &= ~ flag_reproc;
- -- state.ptr;
- }
-
- if (flags & flag_next)
- {
- flags = (flags & ~ flag_next) | flag_need_comma;
-
- if (!top->parent)
- {
- /* root value done */
-
- flags |= flag_done;
- continue;
- }
-
- if (top->parent->type == json_array)
- flags |= flag_seek_value;
-
- if (!state.first_pass)
- {
- json_value * parent = top->parent;
-
- switch (parent->type)
- {
- case json_object:
-
- parent->u.object.values
- [parent->u.object.length].value = top;
-
- break;
-
- case json_array:
-
- parent->u.array.values
- [parent->u.array.length] = top;
-
- break;
-
- default:
- break;
- };
- }
-
- if ( (++ top->parent->u.array.length) > state.uint_max)
- goto e_overflow;
-
- top = top->parent;
-
- continue;
- }
- }
-
- alloc = root;
- }
-
- return root;
-
-e_unknown_value:
-
- sprintf (error, "%d:%d: Unknown value", line_and_col);
- goto e_failed;
-
-e_alloc_failure:
-
- strlcpy (error, "Memory allocation failure", sizeof error);
- goto e_failed;
-
-e_overflow:
-
- sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
- goto e_failed;
-
-e_failed:
-
- if (error_buf)
- {
- if (*error)
- strcpy (error_buf, error);
- else
- strcpy (error_buf, "Unknown error");
- }
-
- if (state.first_pass)
- alloc = root;
-
- while (alloc)
- {
- top = alloc->_reserved.next_alloc;
- state.settings.mem_free (alloc, state.settings.user_data);
- alloc = top;
- }
-
- if (!state.first_pass)
- json_value_free_ex (&state.settings, root);
-
- return 0;
-}
-
-json_value * json_parse (const json_char * json, size_t length)
-{
- json_settings settings = { 0 };
- return json_parse_ex (&settings, json, length, 0);
-}
-
-void json_value_free_ex (json_settings * settings, json_value * value)
-{
- json_value * cur_value;
-
- if (!value)
- return;
-
- value->parent = 0;
-
- while (value)
- {
- switch (value->type)
- {
- case json_array:
-
- if (!value->u.array.length)
- {
- settings->mem_free (value->u.array.values, settings->user_data);
- break;
- }
-
- value = value->u.array.values [-- value->u.array.length];
- continue;
-
- case json_object:
-
- if (!value->u.object.length)
- {
- settings->mem_free (value->u.object.values, settings->user_data);
- break;
- }
-
- value = value->u.object.values [-- value->u.object.length].value;
- continue;
-
- case json_string:
-
- settings->mem_free (value->u.string.ptr, settings->user_data);
- break;
-
- default:
- break;
- };
-
- cur_value = value;
- value = value->parent;
- settings->mem_free (cur_value, settings->user_data);
- }
-}
-
-void json_value_free (json_value * value)
-{
- json_settings settings = { 0 };
- settings.mem_free = default_free;
- json_value_free_ex (&settings, value);
-}
-
diff --git a/extras/filters/filter-rspamd/json.h b/extras/filters/filter-rspamd/json.h
deleted file mode 100644
index f6549ec..0000000
--- a/extras/filters/filter-rspamd/json.h
+++ /dev/null
@@ -1,283 +0,0 @@
-
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
- *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
- * https://github.com/udp/json-parser
- *
- * 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.
- */
-
-#ifndef _JSON_H
-#define _JSON_H
-
-#ifndef json_char
- #define json_char char
-#endif
-
-#ifndef json_int_t
- #ifndef _MSC_VER
- #include <inttypes.h>
- #define json_int_t int64_t
- #else
- #define json_int_t __int64
- #endif
-#endif
-
-#include <stdlib.h>
-
-#ifdef __cplusplus
-
- #include <string.h>
-
- extern "C"
- {
-
-#endif
-
-typedef struct
-{
- unsigned long max_memory;
- int settings;
-
- /* Custom allocator support (leave null to use malloc/free)
- */
-
- void * (* mem_alloc) (size_t, int zero, void * user_data);
- void (* mem_free) (void *, void * user_data);
-
- void * user_data; /* will be passed to mem_alloc and mem_free */
-
- size_t value_extra; /* how much extra space to allocate for values? */
-
-} json_settings;
-
-#define json_enable_comments 0x01
-
-typedef enum
-{
- json_none,
- json_object,
- json_array,
- json_integer,
- json_double,
- json_string,
- json_boolean,
- json_null
-
-} json_type;
-
-extern const struct _json_value json_value_none;
-
-typedef struct _json_object_entry
-{
- json_char * name;
- unsigned int name_length;
-
- struct _json_value * value;
-
-} json_object_entry;
-
-typedef struct _json_value
-{
- struct _json_value * parent;
-
- json_type type;
-
- union
- {
- int boolean;
- json_int_t integer;
- double dbl;
-
- struct
- {
- unsigned int length;
- json_char * ptr; /* null terminated */
-
- } string;
-
- struct
- {
- unsigned int length;
-
- json_object_entry * values;
-
- #if defined(__cplusplus) && __cplusplus >= 201103L
- decltype(values) begin () const
- { return values;
- }
- decltype(values) end () const
- { return values + length;
- }
- #endif
-
- } object;
-
- struct
- {
- unsigned int length;
- struct _json_value ** values;
-
- #if defined(__cplusplus) && __cplusplus >= 201103L
- decltype(values) begin () const
- { return values;
- }
- decltype(values) end () const
- { return values + length;
- }
- #endif
-
- } array;
-
- } u;
-
- union
- {
- struct _json_value * next_alloc;
- void * object_mem;
-
- } _reserved;
-
- #ifdef JSON_TRACK_SOURCE
-
- /* Location of the value in the source JSON
- */
- unsigned int line, col;
-
- #endif
-
-
- /* Some C++ operator sugar */
-
- #ifdef __cplusplus
-
- public:
-
- inline _json_value ()
- { memset (this, 0, sizeof (_json_value));
- }
-
- inline const struct _json_value &operator [] (int index) const
- {
- if (type != json_array || index < 0
- || ((unsigned int) index) >= u.array.length)
- {
- return json_value_none;
- }
-
- return *u.array.values [index];
- }
-
- inline const struct _json_value &operator [] (const char * index) const
- {
- if (type != json_object)
- return json_value_none;
-
- for (unsigned int i = 0; i < u.object.length; ++ i)
- if (!strcmp (u.object.values [i].name, index))
- return *u.object.values [i].value;
-
- return json_value_none;
- }
-
- inline operator const char * () const
- {
- switch (type)
- {
- case json_string:
- return u.string.ptr;
-
- default:
- return "";
- };
- }
-
- inline operator json_int_t () const
- {
- switch (type)
- {
- case json_integer:
- return u.integer;
-
- case json_double:
- return (json_int_t) u.dbl;
-
- default:
- return 0;
- };
- }
-
- inline operator bool () const
- {
- if (type != json_boolean)
- return false;
-
- return u.boolean != 0;
- }
-
- inline operator double () const
- {
- switch (type)
- {
- case json_integer:
- return (double) u.integer;
-
- case json_double:
- return u.dbl;
-
- default:
- return 0;
- };
- }
-
- #endif
-
-} json_value;
-
-json_value * json_parse (const json_char * json,
- size_t length);
-
-#define json_error_max 128
-json_value * json_parse_ex (json_settings * settings,
- const json_char * json,
- size_t length,
- char * error);
-
-void json_value_free (json_value *);
-
-
-/* Not usually necessary, unless you used a custom mem_alloc and now want to
- * use a custom mem_free.
- */
-void json_value_free_ex (json_settings * settings,
- json_value *);
-
-
-#ifdef __cplusplus
- } /* extern "C" */
-#endif
-
-#endif
-
-
diff --git a/extras/filters/filter-rspamd/rspamd.c b/extras/filters/filter-rspamd/rspamd.c
deleted file mode 100644
index 76cbbbe..0000000
--- a/extras/filters/filter-rspamd/rspamd.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (c) 2016 Gilles Chehade <gilles@poolp.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-#include "rspamd.h"
-#include "json.h"
-
-extern struct sockaddr_storage ss;
-
-void *
-session_allocator(uint64_t id)
-{
- return xcalloc(1, sizeof (struct session), "on_connect");
-}
-
-void
-session_destructor(void *ctx)
-{
- struct session *rs = ctx;
-
- free(rs->ip);
- free(rs->hostname);
- free(rs->helo);
- free(rs);
-}
-
-void *
-transaction_allocator(uint64_t id)
-{
- struct transaction *tx;
-
- tx = xcalloc(1, sizeof *tx, "transaction_allocator");
- tx->id = id;
-
- iobuf_xinit(&tx->iobuf, LINE_MAX, LINE_MAX, "on_eom");
- io_init(&tx->io, -1, tx, rspamd_io, &tx->iobuf);
-
- dict_init(&tx->rcpts);
-
- return tx;
-}
-
-void
-transaction_destructor(void *ctx)
-{
- struct transaction *tx = ctx;
- void *data;
-
- iobuf_clear(&tx->iobuf);
- io_clear(&tx->io);
-
- if (tx->from)
- free(tx->from);
- if (tx->rspamd.body)
- free(tx->rspamd.body);
- if (tx->rspamd.subject)
- free(tx->rspamd.subject);
-
- tx->eom = 0;
- tx->from = NULL;
- tx->rspamd.body = NULL;
- tx->rspamd.subject = NULL;
-
- while (dict_poproot(&tx->rcpts, &data))
- ;
-
- free(tx);
-}
-
-
-int
-session_set_helo(struct session *s, const char *helo)
-{
- return ((s->helo = strdup(helo)) != NULL);
-}
-
-int
-session_set_ip(struct session *s, const char *ip)
-{
- return ((s->ip = strdup(ip)) != NULL);
-}
-
-int
-session_set_hostname(struct session *s, const char *hostname)
-{
- return ((s->hostname = strdup(hostname)) != NULL);
-}
-
-int
-transaction_set_from(struct transaction *t, const char *from)
-{
- return ((t->from = strdup(from)) != NULL);
-}
-
-int
-transaction_add_rcpt(struct transaction *t, const char *rcpt)
-{
- /* XXX - not the best data structure */
- dict_set(&t->rcpts, rcpt, NULL);
- return 1;
-}
-
-
-int
-rspamd_connect(struct transaction *tx)
-{
- return (io_connect(&tx->io, (struct sockaddr *)&ss, NULL) != -1);
-}
-
-void
-rspamd_disconnect(struct transaction *tx)
-{
- iobuf_clear(&tx->iobuf);
- io_clear(&tx->io);
-}
-
-void
-rspamd_connected(struct transaction *tx)
-{
- /* answer to DATA phase */
- filter_api_accept(tx->id);
-}
-
-void
-rspamd_error(struct transaction *tx)
-{
- filter_api_reject_code(tx->id, FILTER_FAIL, 421, "temporary failure");
-}
-
-void
-rspamd_send_query(struct transaction *tx)
-{
- struct session *rs = filter_api_session(tx->id);
- void *iter;
- const char *key;
-
- iobuf_xfqueue(&tx->iobuf, "io",
- "POST /check HTTP/1.0\r\n"
- "Transfer-Encoding: chunked\r\n"
- "Pass: all\r\n"
- "IP: %s\r\n"
- "Helo: %s\r\n"
- "Hostname: %s\r\n"
- "From: %s\r\n",
- rs->ip,
- rs->helo,
- rs->hostname,
- tx->from);
-
- iter = NULL;
- while (dict_iter(&tx->rcpts, &iter, &key, NULL))
- iobuf_xfqueue(&tx->iobuf, "io", "Rcpt: %s\r\n", key);
- iobuf_xfqueue(&tx->iobuf, "io", "\r\n");
- io_reload(&tx->io);
-}
-
-void
-rspamd_send_chunk(struct transaction *tx, const char *line)
-{
- if (line)
- iobuf_xfqueue(&tx->iobuf, "io", "%x\r\n%s\r\n\r\n",
- strlen(line)+2, line);
- else {
- iobuf_xfqueue(&tx->iobuf, "io", "0\r\n\r\n");
- tx->eom = 1;
- }
-
- io_reload(&tx->io);
-}
-
-void
-rspamd_read_response(struct transaction *tx)
-{
- char *line;
-
- while ((line = iobuf_getline(&tx->iobuf, NULL)))
- if (strlen(line) == 0)
- tx->rspamd.eoh = 1;
-
- if (tx->rspamd.eoh)
- if (iobuf_len(&tx->iobuf) != 0) {
- tx->rspamd.body = xmemdup(iobuf_data(&tx->iobuf),
- iobuf_len(&tx->iobuf) + 1, "rspamd_read_response");
- tx->rspamd.body[iobuf_len(&tx->iobuf)] = 0;
- }
-
- iobuf_normalize(&tx->iobuf);
-}
-
-/* XXX this can certainly be cleaned up */
-int
-rspamd_parse_response(struct transaction *tx)
-{
- json_value *jv = NULL;
- json_value *def = NULL;
- char *name;
- json_value *val;
- size_t i;
-
- if (tx->rspamd.body == NULL)
- goto fail;
-
- jv = json_parse(tx->rspamd.body, strlen(tx->rspamd.body));
- if (jv == NULL || jv->type != json_object)
- goto fail;
-
- for (i = 0; i < jv->u.object.length; ++i)
- if (strcmp(jv->u.object.values[i].name, "default") == 0) {
- def = jv->u.object.values[i].value;
- break;
- }
- if (def == NULL)
- goto fail;
-
- for (i = 0; i < def->u.object.length; ++i) {
- name = def->u.object.values[i].name;
-
- if (strcmp(name, "is_spam") == 0) {
- val = def->u.object.values[i].value;
- if (val->type != json_boolean)
- goto fail;
- tx->rspamd.is_spam = val->u.boolean;
- }
- else if (strcmp(name, "is_skipped") == 0) {
- val = def->u.object.values[i].value;
- if (val->type != json_boolean)
- goto fail;
- tx->rspamd.is_skipped = val->u.boolean;
- }
- else if (strcmp(name, "score") == 0) {
- val = def->u.object.values[i].value;
- if (val->type != json_double)
- goto fail;
- tx->rspamd.score = val->u.dbl;
- }
- else if (strcmp(name, "required_score") == 0) {
- val = def->u.object.values[i].value;
- if (val->type != json_double)
- goto fail;
- tx->rspamd.required_score = val->u.dbl;
- }
- else if (strcmp(name, "action") == 0) {
- val = def->u.object.values[i].value;
- if (val->type != json_string)
- goto fail;
- if (strncmp(val->u.string.ptr, "no action",
- val->u.string.length) == 0)
- tx->rspamd.action = NO_ACTION;
- else if (strncmp(val->u.string.ptr, "greylist",
- val->u.string.length) == 0)
- tx->rspamd.action = GREYLIST;
- else if (strncmp(val->u.string.ptr, "add header",
- val->u.string.length) == 0)
- tx->rspamd.action = ADD_HEADER;
- else if (strncmp(val->u.string.ptr, "rewrite subject",
- val->u.string.length) == 0)
- tx->rspamd.action = REWRITE_SUBJECT;
- else if (strncmp(val->u.string.ptr, "soft reject",
- val->u.string.length) == 0)
- tx->rspamd.action = SOFT_REJECT;
- else if (strncmp(val->u.string.ptr, "reject",
- val->u.string.length) == 0)
- tx->rspamd.action = REJECT;
- }
- else if (strcmp(name, "subject") == 0) {
- val = def->u.object.values[i].value;
- if (val->type != json_string)
- goto fail;
- tx->rspamd.subject = xmemdup(val->u.string.ptr,
- val->u.string.length, "rspamd_parse_result");
- }
- }
-
- json_value_free(jv);
- return 1;
-
-fail:
- if (jv)
- json_value_free(jv);
- return 0;
-}
-
-void
-rspamd_spam_headers(struct transaction *tx)
-{
- filter_api_header_add(tx->id, "X-Spam-Flag", "%s",
- tx->rspamd.is_spam ? "Yes" : "No");
- filter_api_header_add(tx->id, "X-Spam-Score", "%.2f",
- tx->rspamd.score);
-}
-
-int
-rspamd_proceed(struct transaction *tx)
-{
- if (! rspamd_parse_response(tx))
- return 0;
-
- switch (tx->rspamd.action) {
- case NO_ACTION:
- return 1;
-
- case SOFT_REJECT:
- filter_api_reject_code(tx->id, FILTER_FAIL, 421,
- "message content rejected");
- return 0;
-
- case GREYLIST:
- /* XXX - don't greylist until filter is finished */
- /*
- filter_api_reject_code(tx->id, FILTER_FAIL, 421,
- "greylisted");
- return 0;
- */
- return 1;
-
- case REJECT:
- filter_api_reject_code(tx->id, FILTER_FAIL, 550,
- "message content rejected");
- return 0;
-
- case ADD_HEADER:
- /* insert header */
- rspamd_spam_headers(tx);
- return 1;
-
- case REWRITE_SUBJECT:
- /* rewrite subject */
- return 1;
- }
-
- filter_api_reject_code(tx->id, FILTER_FAIL, 550,
- "server internal error");
- return 0;
-}
-
-
-void
-rspamd_io(struct io *io, int evt)
-{
- struct transaction *tx = io->arg;
-
- switch (evt) {
- case IO_CONNECTED:
- rspamd_connected(tx);
- rspamd_send_query(tx);
- io_set_write(io);
- return;
-
- case IO_LOWAT:
- /* we've hit EOM and no more data, toggle to read */
- if (tx->eom)
- io_set_read(io);
- return;
-
- case IO_DATAIN:
- rspamd_read_response(tx);
- return;
-
- case IO_DISCONNECTED:
- rspamd_disconnect(tx);
-
- /* we're done with rspamd, if there was a local error
- * during transaction, reject now, else move forward.
- */
- if (! rspamd_proceed(tx))
- goto fail;
-
- filter_api_data_buffered_stream(tx->id);
- return;
-
- case IO_TIMEOUT:
- case IO_ERROR:
- default:
- break;
- }
-
-fail:
- rspamd_error(tx);
- return;
-}
diff --git a/extras/filters/filter-rspamd/rspamd.h b/extras/filters/filter-rspamd/rspamd.h
deleted file mode 100644
index 02774db..0000000
--- a/extras/filters/filter-rspamd/rspamd.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2016 Gilles Chehade <gilles@poolp.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#define RSPAMD_HOST "127.0.0.1"
-#define RSPAMD_PORT "11333"
-
-struct session {
- char *ip;
- char *hostname;
- char *helo;
-};
-
-struct transaction {
- uint64_t id;
-
- struct iobuf iobuf;
- struct io io;
-
- char *from;
- int eom;
- struct dict rcpts;
-
- struct rspamd_response {
- int eoh;
- char *body;
-
- int is_spam;
- int is_skipped;
- double score;
- double required_score;
- enum {
- NO_ACTION,
- GREYLIST,
- ADD_HEADER,
- REWRITE_SUBJECT,
- SOFT_REJECT,
- REJECT
- } action;
- char *subject;
- } rspamd;
-
- char *line;
-};
-
-void *session_allocator(uint64_t);
-void session_destructor(void *);
-int session_set_helo(struct session *, const char *);
-int session_set_ip(struct session *, const char *);
-int session_set_hostname(struct session *, const char *);
-
-void *transaction_allocator(uint64_t);
-void transaction_destructor(void *);
-int transaction_set_from(struct transaction *, const char *);
-int transaction_add_rcpt(struct transaction *, const char *);
-
-int rspamd_connect(struct transaction *);
-void rspamd_connected(struct transaction *);
-void rspamd_send_query(struct transaction *);
-void rspamd_send_chunk(struct transaction *, const char *);
-void rspamd_read_response(struct transaction *);
-int rspamd_parse_response(struct transaction *);
-void rspamd_error(struct transaction *);
-
-void rspamd_io(struct io *, int);
-
-
-
-
-
-
diff --git a/extras/filters/filter-spamassassin/Makefile.am b/extras/filters/filter-spamassassin/Makefile.am
deleted file mode 100644
index 7a456de..0000000
--- a/extras/filters/filter-spamassassin/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-include $(top_srcdir)/mk/paths.mk
-include $(top_srcdir)/mk/filter.mk
-include $(top_srcdir)/mk/experimental.mk
-
-pkglibexec_PROGRAMS = filter-spamassassin
-
-filter_spamassassin_SOURCES = $(SRCS)
-filter_spamassassin_SOURCES += filter_spamassassin.c
-
-man_MANS = filter-spamassassin.8
diff --git a/extras/filters/filter-spamassassin/filter-spamassassin.8 b/extras/filters/filter-spamassassin/filter-spamassassin.8
deleted file mode 100644
index 9ebff45..0000000
--- a/extras/filters/filter-spamassassin/filter-spamassassin.8
+++ /dev/null
@@ -1,130 +0,0 @@
-.\"
-.\" Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 16 2016 $
-.Dt FILTER-SPAMASSASSIN 8
-.Os
-.Sh NAME
-.Nm filter-spamassassin
-.Nd smtpd filter for SpamAssassin spamd
-.Sh SYNOPSIS
-.Nm
-.Op Fl dv
-.Op Fl h Ar host
-.Op Fl l Ar limit
-.Op Fl p Ar port
-.Op Fl s Ar strategy
-.Sh DESCRIPTION
-.Nm
-is a filter for
-.Xr smtpd 8
-which can be used to filter mails based on decisions from SpamAssassin's
-.Xr spamd 1
-daemon.
-Mails are piped to the daemon, which decides whether a mail is spam or not,
-according to its own configuration.
-.Pp
-The options are as follows:
-.Bl -tag -width "-s strategy"
-.It Fl d
-Debug mode, if this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl h Ar host
-Set the
-.Ar host
-that runs SpamAssassin's
-.Xr spamd 1 .
-.Pp
-The default
-.Ar host
-value is 127.0.0.1.
-.It Fl l Ar limit
-Set the number of bytes
-.Ar limit
-passed to
-.Xr spamd 1
-after which the scanning is stopped and the mail is accepted.
-The accepted values are within the range of 1 and SIZE_MAX.
-.Pp
-The default
-.Ar limit
-value is 0 (unlimited).
-.It Fl p Ar port
-Set the
-.Ar port
-that SpamAssassin's
-.Xr spamd 1
-listens on.
-.Pp
-The default
-.Ar port
-value is 783.
-.It Fl s Ar strategy
-Set the
-.Ar strategy
-of
-.Nm
-to either accept or reject spam mails.
-The accepted values are:
-.Pp
-.Bl -tag -width "accept" -compact
-.It accept
-Spam mails are accepted.
-.It reject
-Spam mails are rejected.
-.El
-.Pp
-The default
-.Ar strategy
-value is accept.
-.It Fl v
-Produce more verbose output.
-.El
-.Pp
-.Nm
-runs by default in a chroot.
-.Pp
-The debug and verbose options given with the
-.Xr smtpd 8
-invocation are intially passed to
-.Nm .
-.Pp
-Depending on the chosen
-.Ar strategy
-spam mails are either accepted or rejected with a SMTP 554 reply.
-Non-spam mails are always accepted.
-.\"Accepted messages are marked with a
-.\".Dq X-Filter-SpamAssassin
-.\"header.
-.Sh SPAMASSASSIN CONFIGURATION
-The default
-.Nm
-configuration expects SpamAssassin's
-.Xr spamd 1
-to listen on 127.0.0.1 port 783 for incoming requests.
-This matches to the default configuration of the daemon.
-.Sh SEE ALSO
-.Xr spamd 1 ,
-.Xr filter_api 3 ,
-.Xr smtpd.conf 5 ,
-.Xr smtpd 8
-.Sh HISTORY
-The first version of
-.Nm
-was written in 2015.
-.Sh AUTHORS
-.An Joerg Jung Aq Mt jung@openbsd.org
diff --git a/extras/filters/filter-spamassassin/filter_spamassassin.c b/extras/filters/filter-spamassassin/filter_spamassassin.c
deleted file mode 100644
index 264aa20..0000000
--- a/extras/filters/filter-spamassassin/filter_spamassassin.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (c) 2015, 2016 Joerg Jung <jung@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <limits.h>
-#include <unistd.h>
-
-#include <smtpd-api.h>
-
-#define SPAMASSASSIN_HOST "127.0.0.1"
-#define SPAMASSASSIN_PORT "783"
-
-struct spamassassin {
- uint64_t id;
- struct iobuf iobuf;
- struct io io;
- size_t l;
- int r;
- enum { SA_DATA, SA_EOM, SA_STA, SA_HDR, SA_MSG } s;
-};
-
-static struct sockaddr_storage spamassassin_ss;
-static size_t spamassassin_limit;
-static enum { SPAMASSASSIN_ACCEPT, SPAMASSASSIN_REJECT } spamassassin_strategy;
-
-static void
-spamassassin_clear(struct spamassassin *sa)
-{
- if (sa == NULL)
- return;
- io_clear(&sa->io);
- iobuf_clear(&sa->iobuf);
- free(sa);
-}
-
-static int
-spamassassin_result(struct spamassassin *sa)
-{
- if (sa->r == INT_MIN) {
- log_warnx("warn: result: failed");
- return -1;
- }
- if (sa->r) {
- if (spamassassin_strategy == SPAMASSASSIN_ACCEPT) {
- log_warnx("warn: session %016"PRIx64": result: ACCEPT spam", sa->id);
- filter_api_accept(sa->id);
- }
- if (spamassassin_strategy == SPAMASSASSIN_REJECT) {
- log_warnx("warn: session %016"PRIx64": result: REJECT spam", sa->id);
- filter_api_reject_code(sa->id, FILTER_CLOSE, 554, "5.7.1 Message considered spam");
- }
- }
- return filter_api_accept(sa->id);
-}
-
-#define SPAMASSASSIN_EXPAND(tok) #tok
-#define SPAMASSASSIN_QUOTE(tok) SPAMASSASSIN_EXPAND(tok)
-#define SPAMASSASSIN_EX_MAX 16 /* longest spamd response e.g. strlen("EX_UNAVAILABLE") */
-
-static int
-spamassassin_status(struct spamassassin *sa, const char *l)
-{
- char s[SPAMASSASSIN_EX_MAX + 1];
- int r;
-
- if (sscanf(l, "SPAMD/%*d.%*d %d %"SPAMASSASSIN_QUOTE(SPAMASSASSIN_EX_MAX)"s", &r, s) != 2) {
- (errno ? log_warn : log_warnx)("warn: status: sscanf");
- return -1;
- }
- if (r != 0 || strcmp(s, "EX_OK") != 0) {
- log_warnx("warn: status: r=%d, s=%s", r, s);
- return -1;
- }
- return sa->s++;
-}
-
-static int
-spamassassin_header(struct spamassassin *sa, const char *l)
-{
- char s[SPAMASSASSIN_EX_MAX + 1];
-
- if (strlen(l) == 0)
- return sa->s++; /* end of spamd response headers */
- if (strncmp(l, "Spam: ", 6) == 0) {
- if (sscanf(l, "Spam: %"SPAMASSASSIN_QUOTE(SPAMASSASSIN_EX_MAX)"s ; %*f / %*f", s) != 1) {
- (errno ? log_warn : log_warnx)("warn: result: sscanf");
- return -1;
- }
- log_info("info: result: %s", l);
- sa->r = (strcmp(s, "True") == 0);
- }
- return 0;
-}
-
-static int
-spamassassin_response(struct spamassassin *sa, const char *l)
-{
- switch (sa->s) {
- case SA_STA:
- if (spamassassin_status(sa, l) == -1)
- return -1;
- break;
- case SA_HDR:
- if (spamassassin_header(sa, l) == -1)
- return -1;
- break;
- case SA_MSG:
- filter_api_writeln(sa->id, l);
- break;
- default:
- fatalx("response: bad state");
- }
- return 0;
-}
-
-static void
-spamassassin_io(struct io *io, int evt)
-{
- struct spamassassin *sa = io->arg;
- char *l;
-
- switch (evt) {
- case IO_CONNECTED:
- io_set_write(io);
- break;
- case IO_LOWAT:
- if (sa->s == SA_EOM) {
- if (shutdown(sa->io.sock, SHUT_WR) == -1) {
- log_warn("warn: io: shutdown");
- goto fail;
- }
- sa->s++;
- io_set_read(io);
- }
- break;
- case IO_DATAIN:
- while ((l = iobuf_getline(&sa->iobuf, NULL))) {
- if (iobuf_len(&sa->iobuf) >= LINE_MAX) {
- log_warnx("warn: io: iobuf_getline");
- goto fail;
- }
- if (spamassassin_response(sa, l) == -1)
- goto fail;
- }
- iobuf_normalize(&sa->iobuf);
- break;
- case IO_DISCONNECTED:
- if (sa->s == SA_MSG) {
- if (iobuf_len(&sa->iobuf)) {
- log_warnx("warn: io: incomplete");
- goto fail;
- }
- if (spamassassin_result(sa) == -1)
- goto fail;
- io_clear(io);
- break;
- } /* FALLTHROUGH */
- case IO_TIMEOUT:
- case IO_ERROR:
- log_warnx("warn: io: %s %s", io_strevent(evt), sa->io.error);
- goto fail;
- default:
- fatalx("io: bad event");
- }
- return;
-fail:
- if (sa->s > SA_DATA)
- filter_api_reject_code(sa->id, FILTER_FAIL, 451, "4.7.1 Spam filter failed");
- filter_api_set_udata(sa->id, NULL);
- spamassassin_clear(sa);
-}
-
-static void
-spamassassin_init(struct spamassassin *sa, uint64_t id)
-{
- iobuf_xinit(&sa->iobuf, LINE_MAX, LINE_MAX, "init");
- io_init(&sa->io, -1, sa, spamassassin_io, &sa->iobuf);
- sa->id = id;
- sa->r = INT_MIN;
-}
-
-static int
-spamassassin_on_data(uint64_t id)
-{
- struct spamassassin *sa;
-
- spamassassin_init((sa = xcalloc(1, sizeof(struct spamassassin), "on_data")), id);
- if (io_connect(&sa->io, (struct sockaddr *)&spamassassin_ss, NULL) == -1) {
- log_warnx("warn: on_data: io_connect %s", sa->io.error);
- spamassassin_clear(sa);
- return filter_api_accept(id);
- }
- iobuf_xfqueue(&sa->iobuf, "on_data", "PROCESS SPAMC/1.5\r\n\r\n"); /* spamd.raw source: content length header is optional */
- filter_api_set_udata(id, sa);
- return filter_api_accept(id);
-}
-
-static void
-spamassassin_on_dataline(uint64_t id, const char *l)
-{
- struct spamassassin *sa;
-
- if ((sa = filter_api_get_udata(id)) == NULL) {
- filter_api_writeln(id, l);
- return;
- }
- sa->l += strlen(l);
- if (spamassassin_limit && sa->l >= spamassassin_limit) {
- log_info("info: on_dataline: limit reached");
- log_warnx("warn: on_dataline: limit option not implemented");
- }
- iobuf_xfqueue(&sa->iobuf, "on_dataline", "%s\n", l);
- io_reload(&sa->io);
-}
-
-static int
-spamassassin_on_eom(uint64_t id, size_t size)
-{
- struct spamassassin *sa;
-
- if ((sa = filter_api_get_udata(id)) == NULL)
- return filter_api_accept(id);
- sa->s++;
- if (iobuf_queued(&sa->iobuf) == 0)
- spamassassin_io(&sa->io, IO_LOWAT);
- return 1; /* defer accept or reject */
-}
-
-static void
-spamassassin_on_tx_commit(uint64_t id)
-{
- spamassassin_clear(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-static void
-spamassassin_on_tx_rollback(uint64_t id)
-{
- spamassassin_clear(filter_api_get_udata(id));
- filter_api_set_udata(id, NULL);
-}
-
-static void
-spamassassin_resolve(const char *h, const char *p)
-{
- struct addrinfo hints, *addresses, *ai;
- int fd, r;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if ((r = getaddrinfo(h, p, &hints, &addresses)))
- fatalx("resolve: getaddrinfo %s", gai_strerror(r));
- for (ai = addresses; ai; ai = ai->ai_next) {
- if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1)
- continue;
- if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
- close(fd);
- continue;
- }
- write(fd, "PING SPAMC/1.5\r\n\r\n", 18); /* avoid warning in log */
- close(fd);
- memmove(&spamassassin_ss, ai->ai_addr, ai->ai_addrlen);
- break;
- }
- freeaddrinfo(addresses);
- if (!ai)
- fatalx("resolve: failed");
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, d = 0, v = 0;
- const char *errstr, *l = NULL;
- char *h = SPAMASSASSIN_HOST, *p = SPAMASSASSIN_PORT, *s = NULL;
-
- log_init(1);
-
- while ((ch = getopt(argc, argv, "dh:l:p:s:v")) != -1) {
- switch (ch) {
- case 'd':
- d = 1;
- break;
- case 'h':
- h = optarg;
- break;
- case 'l':
- l = optarg;
- break;
- case 'p':
- p = optarg;
- break;
- case 's':
- s = optarg;
- break;
- case 'v':
- v |= TRACE_DEBUG;
- break;
- default:
- log_warnx("warn: bad option");
- return 1;
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (h)
- h = strip(h);
- if (p)
- p = strip(p);
- if (l) {
- spamassassin_limit = strtonum(l, 1, UINT_MAX, &errstr); /* todo: SIZE_MAX here? */
- if (errstr)
- fatalx("limit option is %s: %s", errstr, l);
- }
- if (s) {
- s = strip(s);
- if (strncmp(s, "accept", 6) == 0)
- spamassassin_strategy = SPAMASSASSIN_ACCEPT;
- else if (strncmp(s, "reject", 6) == 0)
- spamassassin_strategy = SPAMASSASSIN_REJECT;
- else
- fatalx("bad strategy");
- }
-
- log_init(d);
- log_verbose(v);
-
- log_debug("debug: starting...");
- spamassassin_resolve(h, p);
-
- filter_api_on_data(spamassassin_on_data);
- filter_api_on_dataline(spamassassin_on_dataline);
- filter_api_on_eom(spamassassin_on_eom);
- filter_api_on_tx_commit(spamassassin_on_tx_commit);
- filter_api_on_tx_rollback(spamassassin_on_tx_rollback);
-
- filter_api_loop();
- log_debug("debug: exiting");
-
- return 1;
-}