You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by be...@apache.org on 2005/08/23 06:34:27 UTC
svn commit: r239342 - in /httpd/mod_smtpd/trunk: mod_dnsbl_lookup/
mod_smtpd_rbl/
Author: berkes
Date: Mon Aug 22 21:34:20 2005
New Revision: 239342
URL: http://svn.apache.org/viewcvs?rev=239342&view=rev
Log:
Adding all RBL/DNSBL stuff, two modules
Added:
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/Makefile.in (with props)
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/README (with props)
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/autogen.sh (with props)
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/configure.ac (with props)
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/dnsbl_lookup.h
httpd/mod_smtpd/trunk/mod_dnsbl_lookup/mod_dnsbl_lookup.c (with props)
httpd/mod_smtpd/trunk/mod_smtpd_rbl/
httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile
httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile.in (with props)
httpd/mod_smtpd/trunk/mod_smtpd_rbl/README
httpd/mod_smtpd/trunk/mod_smtpd_rbl/autogen.sh (with props)
httpd/mod_smtpd/trunk/mod_smtpd_rbl/configure.ac (with props)
httpd/mod_smtpd/trunk/mod_smtpd_rbl/dnsbl_lookup.h
httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd.h (with props)
httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd_rbl.c (with props)
Added: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/Makefile.in
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_dnsbl_lookup/Makefile.in?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_dnsbl_lookup/Makefile.in (added)
+++ httpd/mod_smtpd/trunk/mod_dnsbl_lookup/Makefile.in Mon Aug 22 21:34:20 2005
@@ -0,0 +1,17 @@
+APXS=@APXS_BIN@
+CFLAGS=-Wall
+APXSFLAGS=
+DNSBL_SRC=mod_dnsbl_lookup.c
+
+all: mod_dnsbl_lookup.la
+
+mod_dnsbl_lookup.la: $(DNSBL_SRC)
+ $(APXS) -Wc,"$(CFLAGS)" $(APXSFLAGS) -o mod_dnsbl_lookup.la -c $(DNSBL_SRC)
+
+install: all
+ $(APXS) -i -a -n dnsbl_lookup mod_dnsbl_lookup.la
+
+clean-objs:
+ rm -rf *.lo *.o *.slo *~ *.la .libs
+
+clean: clean-objs
Propchange: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/Makefile.in
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/README
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_dnsbl_lookup/README?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_dnsbl_lookup/README (added)
+++ httpd/mod_smtpd/trunk/mod_dnsbl_lookup/README Mon Aug 22 21:34:20 2005
@@ -0,0 +1,209 @@
+/* Copyright 2005 Jem Berkes
+ * www.sysdesign.ca
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+CONTENTS
+
+1. How to build and install
+2. How to configure
+3. How to use (module code)
+4. Using from mod_smtpd
+
+
+===========================
+1. How to build and install
+===========================
+
+Compile and install (adds module loading directives to httpd.conf)
+apxs -cia mod_dnsbl_lookup.c
+
+Or
+./autogen.sh
+./configure
+make
+make install
+
+
+===========================
+2. How to configure
+===========================
+
+A DNSBL or RHSBL is just a form of efficient database that returns a
+simple code (expressed as an IP address) for a given lookup key. The
+lookup key is either an IPv4 (current implementation) for a DNSBL, or a
+host/sub/domain name in the case of a RHSBL. The return code from the
+database may be an IP address such as 127.0.0.2 or NXDOMAIN, indicating no
+match.
+
+DNSBLs are often used in spam filtering, where the return code 127.0.0.x
+indicates that the lookup key (a relay's IP address) is blacklisted.
+However the meaning of the information returned by a database is on no way
+limited to this. Sometimes the DNSBL server intends positive matches to be
+whitelisted hosts; other times there are a variety of 127.0.0.x codes each
+meaning something different.
+
+For this reason we discourage the use of the term blacklist or RBL (real
+time blacklist) because this is just one use of DNSBLs and RHSBLs.
+
+This mod_dnsbl_lookup aims to provide generic and flexible DNSBL and RHSBL
+use without limiting functionality. Each server has its own policy and
+return codess, so you must configure dnsbl_lookup_query appropriately as
+there is no intrinsic way to know if something is blacklisted,
+whitelisted, or somewhere in between.
+
+Define servers and respones that you consider "positive matches" under one
+or more chains. This allows you to make independent configurations for
+different uses. The chain namespaces are separate for IPv4 DNSBLs and
+RHSBLs under different hash tables (IPv6 DNSBLs are not currently
+supported).
+
+# This might be under a mod_smtpd virtual server config
+<VirtualHost *:25>
+
+# Enable module
+DnsblLookups On
+#
+# Need to get host names for RHSBL lookups to work
+# Note that terminating dot in server names prevents local domain search
+HostNameLookups On
+#
+# The following define positive matches for the chain I call "spammers"
+#
+# Any non-failure result from sbl.spamhaus.org is a positive match
+DnsblZone spammers sbl.spamhaus.org. any
+#
+# The 127.0.0.2 result from cbl.abuseat.org is a positive match
+DnsblZone spammers cbl.abuseat.org. 127.0.0.2
+#
+# Only the specific codes 127.0.0.5,6,9 from dnsbl.sorbs.net are positive
+# The module internally caches queries, only one actual DNS query is made
+DnsblZone spammers dnsbl.sorbs.net. 127.0.0.5
+DnsblZone spammers dnsbl.sorbs.net. 127.0.0.6
+DnsblZone spammers dnsbl.sorbs.net. 127.0.0.9
+#
+# The following define positive matches for the chain I call "whitelist"
+#
+# A zone designed for whitelisting, any mail from Canada is positive
+DnsblZone whitelist ca.countries.nerd.dk. 127.0.0.2
+#
+# A local zone we run, customers or partners of ours are positive
+DnsblZone whitelist customers.dnsbl any
+#
+# A chain for RHSBL lookups (distinct from DNSBL chains)
+#
+RhsblZone spammers rhsbl.ahbl.org. 127.0.0.2
+
+With this configuration, a user could now do a DNSBL_ANYPOSTV_RETFIRST
+query on the "spammers" chain to see if a host is a spammer (returns
+DNSBL_POSITIVE when the first positive response is encountered). The user
+might also want to do a DNSBL_ANYPOSTV_RETFIRST on the "whitelist" chain
+and allow through any host that returns DNSBL_POSITIVE, meaning it is
+whitelisted. If the whitelist override is more stringent, a
+DNSBL_ALLPOSTV_RETEVERY query might be done instead to require that every
+single entry in the "whitelist" chain returns a positive result.
+
+A more lenient admin might instead do a DNSBL_ANYPOSTV_RETEVERY query on
+the "spammers" chain and do post processing after getting DNSBL_POSITIVE.
+The table returned by the lookup (see below) contains detail on every
+positive match, so the admin may want to only block mail from the host if
+there are at least 2 positive zones. The disadvantage of this are many
+extra queries.
+
+
+===========================
+3. How to use (module code)
+===========================
+
+The configuration (above) simplifies the client code down to querying a
+specific chain using a certain query mode. The functions used are:
+
+dnsbl_lookup_ip(const char* chain, int querymode, apr_sockaddr_t* address,
+ apr_pool_t* p, server_rec* s, apr_table_t** zonedata)
+
+dnsbl_lookup_domain(const char* chain, int querymode, const char* domain,
+ apr_pool_t* p, server_rec* s, apr_table_t** zonedata)
+
+With return values:
+DNSBL_POSITIVE - Positive match (zonedata has details, if requested)
+DNSBL_NEGATIVE - Negative
+DNSBL_FAILURE - Generic failure, e.g. DnsblLookups Off or invalid chain
+
+For DNSBLs, you would use dnsbl_lookup_ip() and pass the IP address in the
+apr_sockaddr_t*. For RHSBLs you would use dnsbl_lookup_domain() and pass
+the host or domain name string. A chain name must always be specified.
+
+The allowed querymodes are:
+DNSBL_ANYPOSTV_RETFIRST - Any positive from chain, stop and return first
+DNSBL_ANYPOSTV_RETEVERY - Any positive, check all and return every positive
+DNSBL_ALLPOSTV_RETEVERY - All must check positive, return every positive
+
+If zonedata is NULL then there will be none returned. Otherwise, a new
+table will be created and filled with {zone, result} pairs for each zone
+that comes back positive. The result is an IPv4 string, probably
+127.0.0.x. Note that this zonedata table will only contain entries if
+there is some positive match, i.e., only if the return code was
+DNSBL_POSITIVE.
+
+Here is how another module would load and use the optional function:
+
+
+#include "dnsbl_lookup.h"
+
+...
+
+int (*dnsbl_ip)(const char*, int, apr_sockaddr_t*, apr_pool_t*,
+ server_rec*, apr_table_t**);
+int (*dnsbl_domain)(const char*, int, const char*, apr_pool_t*,
+ server_rec*, apr_table_t**);
+
+dnsbl_ip = APR_RETRIEVE_OPTIONAL_FN(dnsbl_lookup_ip);
+dnsbl_domain = APR_RETRIEVE_OPTIONAL_FN(dnsbl_lookup_domain);
+
+/* Provided they aren't NULL, you can now use these functions */
+
+
+===========================
+4. Using from mod_smtpd
+===========================
+
+The function calls work in isolation, without requiring any prior setup
+before using DNSBLs. The server configuration takes care of all
+DNSBL and RHSBL setup, including domains to query and responses to
+interpret as positive.
+
+The important knowledge link between mod_dnsbl_lookup and its user, say
+mod_smtpd, is the chain name that defines the desired DNSBLs. Instead of
+hard coding a chain name, it makes much more sense to have a module such
+as mod_smtpd load during its configuration some chains to work with.
+
+So mod_smtpd might have configuration directives such as:
+SmtpBlacklistChain blackchain
+SmtpWhitelistChain whitechain
+
+Now mod_smtpd knows which chain to query for blacklisting purposes, and
+which chain to query for whitelisting purposes. The admin may leave either
+chain undefined of course and can easily modify the configuration by
+substituting different chain names (as used by DnsblZone and RhsblZone).
+The pseudo code within mod_smtpd might then be:
+
+Attempt to load optional dnsbl_lookup functions
+If functions are available
+ If dnsbl_lookup_ip("whitechain", client) == DNSBL_POSITIVE
+ return ALLOW_SERVICE // even if blacklisted
+ Else If dnsbl_lookup_ip("blackchain", client) == DNSBL_POSITIVE
+ return DENY_SERVICE
+return ALLOW_SERVICE // default action
+
Propchange: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/README
------------------------------------------------------------------------------
svn:eol-stype = native
Added: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/autogen.sh
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_dnsbl_lookup/autogen.sh?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_dnsbl_lookup/autogen.sh (added)
+++ httpd/mod_smtpd/trunk/mod_dnsbl_lookup/autogen.sh Mon Aug 22 21:34:20 2005
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+autoconf
+rm -rf autom4te.cache
Propchange: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/autogen.sh
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/configure.ac
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_dnsbl_lookup/configure.ac?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_dnsbl_lookup/configure.ac (added)
+++ httpd/mod_smtpd/trunk/mod_dnsbl_lookup/configure.ac Mon Aug 22 21:34:20 2005
@@ -0,0 +1,60 @@
+# Required initializer
+AC_INIT(mod_dnsbl_lookup, 0.91)
+
+AC_DEFUN([CHECK_VERSION],[dnl
+ min_apache_version=ifelse([$1], ,no,$1)
+ AP_BIN=`$APXS_BIN -q BINDIR`
+ AP_SBIN=`$APXS_BIN -q SBINDIR`
+ AP_PROG=`$APXS_BIN -q PROGNAME`
+ if test -e "$AP_BIN/$AP_PROG"; then
+ AP_PATH="$AP_BIN/$AP_PROG"
+ else
+ AP_PATH="$AP_SBIN/$AP_PROG"
+ fi
+ our_apache_version=`$AP_PATH -v | grep -i Apache |
+ sed -e 's/.*Apache\///' | tr -dc [^0-9.]`
+
+ AC_MSG_CHECKING(for Apache version >= $min_apache_version)
+
+ if test "$our_apache_version" \> "$min_apache_version" ||
+ test "$our_apache_version" = "$min_apache_version"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([*** Apache version $min_apache_version not found!])
+ fi
+])
+
+# Define a macro that is used to parse a --with-apxs parameter
+# The macro is named "APACHE_DIR"
+AC_DEFUN([APACHE_DIR],[dnl
+ AC_ARG_WITH(
+ apxs,
+ [ --with-apxs[=PATH_TO_APXS] APXS Location],
+ apxs_prefix="$withval",
+ )
+
+ if test -d $apxs_prefix; then
+ apxs_prefix=`dirname $apxs_prefix`
+
+ test_paths="$apxs_prefix:$apxs_prefix/bin:$apxs_prefix/sbin"
+ test_paths="${test_paths}:${PATH}:/usr/bin:/usr/sbin"
+ test_paths="${test_paths}:/usr/local/bin:/usr/local/sbin:/usr/local/apache2/bin"
+ AC_PATH_PROG(APXS_BIN, apxs, no, [$test_paths])
+ else
+ APXS_BIN="$withval"
+ fi
+
+ if test "$APXS_BIN" = "no"; then
+ AC_MSG_ERROR([*** The apxs binary installed by apache could not be found!])
+ AC_MSG_ERROR([*** Use the --with-apxs option with the full path to apxs])
+ fi
+])
+
+# Now call the APACHE_DIR macro that was just specified
+APACHE_DIR
+
+CHECK_VERSION(2.0)
+
+# Write the Makefile
+AC_OUTPUT(Makefile)
Propchange: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/configure.ac
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/dnsbl_lookup.h
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_dnsbl_lookup/dnsbl_lookup.h?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_dnsbl_lookup/dnsbl_lookup.h (added)
+++ httpd/mod_smtpd/trunk/mod_dnsbl_lookup/dnsbl_lookup.h Mon Aug 22 21:34:20 2005
@@ -0,0 +1,34 @@
+#ifndef MOD_DNSBL_LOOKUP_H
+#define MOD_DNSBL_LOOKUP_H
+
+#include <httpd.h>
+#include <apr_optional.h>
+
+/* Boolean-like result of a dnsbl lookup */
+#define DNSBL_NEGATIVE 0 /* negative */
+#define DNSBL_POSITIVE 1 /* positive match */
+#define DNSBL_FAILURE 2 /* generic failure, not enabled or configured */
+
+/* Types of queries for dnsbl_lookup_ip() and dnsbl_lookup_domain() */
+#define DNSBL_ANYPOSTV_RETFIRST 0 /* Any positive from chain, stop and return first */
+#define DNSBL_ANYPOSTV_RETEVERY 1 /* Any positive, check all and return every positive */
+#define DNSBL_ALLPOSTV_RETEVERY 2 /* All must check positive, return every positive */
+
+#define DNSBL_MATCH_ANY "any"
+
+APR_DECLARE_OPTIONAL_FN(int, dnsbl_lookup_ip,
+ (const char*, int, apr_sockaddr_t*, apr_pool_t*, server_rec*, apr_table_t**) );
+
+APR_DECLARE_OPTIONAL_FN(int, dnsbl_lookup_domain,
+ (const char*, int, const char*, apr_pool_t*, server_rec*, apr_table_t**) );
+
+/*
+ This structure defines a zone in a chain
+ These are stored within hash tables - one table for IPv4 DNSBLs, another for RHSBLs
+*/
+typedef struct {
+ const char* zonedomain;
+ const char* postvresp; /* positive response, (sub)string or DNSBL_MATCH_ANY */
+} zone_entry;
+
+#endif
Added: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/mod_dnsbl_lookup.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_dnsbl_lookup/mod_dnsbl_lookup.c?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_dnsbl_lookup/mod_dnsbl_lookup.c (added)
+++ httpd/mod_smtpd/trunk/mod_dnsbl_lookup/mod_dnsbl_lookup.c Mon Aug 22 21:34:20 2005
@@ -0,0 +1,305 @@
+/* Copyright 2005 Jem Berkes
+ * www.sysdesign.ca
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ap_config.h"
+#include "apr_optional.h"
+#include "apr_hash.h"
+#include "apr_strings.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_connection.h"
+#include "util_filter.h"
+
+#include "dnsbl_lookup.h"
+
+
+/* Link between httpd and dnsbl_lookup module */
+module AP_MODULE_DECLARE_DATA dnsbl_lookup_module;
+
+
+/* Module configuration, on a per-server basis (virtual host container) */
+typedef struct dnsbl_lookup_cfg
+{
+ int lookup_enabled;
+ apr_hash_t* ipv4_dnsbl_chains; /* many chains can be held inside these */
+/* apr_hash_t* ipv6_dnsbl_chains; not supported currently, but easily added */
+ apr_hash_t* rhsbl_chains;
+} dnsbl_lookup_cfg;
+
+
+
+char* dns_lookup_host(const char* hostname, apr_pool_t* p)
+{
+ apr_sockaddr_t* sa;
+ char* dnsresult;
+ if ((apr_sockaddr_info_get(&sa, hostname, APR_INET, 0, 0, p) == APR_SUCCESS) &&
+ (apr_sockaddr_ip_get(&dnsresult, sa) == APR_SUCCESS))
+ return dnsresult;
+ else
+ return NULL;
+}
+
+
+/*
+ Converts IPv4 address to reverse octet notation (NULL on error)
+ TODO: more elegant binary based reversal? that is reliably portable?
+*/
+char* ipreverse(apr_pool_t* p, apr_sockaddr_t* address)
+{
+ char* ipstring;
+ if (apr_sockaddr_ip_get(&ipstring, address) == APR_SUCCESS) {
+ char *token, *tokstate;
+ int n;
+ int octets[4] = {0, 0, 0, 0};
+ token = apr_strtok(ipstring, ".", &tokstate);
+ for (n=0; token && (n<4); n++) {
+ octets[n] = atoi(token);
+ token = apr_strtok(NULL, ".", &tokstate);
+ }
+ return apr_psprintf(p, "%d.%d.%d.%d", octets[3], octets[2], octets[1], octets[0]);
+ }
+ return NULL;
+}
+
+
+/*
+ This function does the work for dnsbl_lookup_ip() and _domain(). They
+ provide us the appropriate chain (IPv4 DNSBL, IPv6 DNSBL, RHSBL) and
+ a text form of the key to lookup. Then the queries always work the same:
+
+ - Go down the servers under the indicated chain of zones
+ - Do a DNS lookup on key.zonedomain
+ - Analyze response and act depending on querymode
+
+ Note that zonedata may be NULL if user doesn't want storage of results.
+ Returns DNSBL_POSITIVE, DNSBL_NEGATIVE, or DNSBL_FAILURE
+*/
+static int dnsbl_lookup(apr_array_header_t* zones, int querymode, const char* key,
+ apr_pool_t* p, apr_table_t* zonedata, dnsbl_lookup_cfg* cfg)
+{
+ int zonenum, numpositive = 0;
+ int numservers = zones->nelts;
+ zone_entry* servers = (zone_entry *)zones->elts;
+
+ if ((querymode!=DNSBL_ANYPOSTV_RETFIRST) && (querymode!=DNSBL_ANYPOSTV_RETEVERY)
+ && (querymode!=DNSBL_ALLPOSTV_RETEVERY))
+ return DNSBL_FAILURE; /* invalid querymode */
+
+ for (zonenum=0; zonenum < numservers; zonenum++) {
+ const char* resultaddr =
+ dns_lookup_host(apr_pstrcat(p, key, ".", servers[zonenum].zonedomain, NULL), p);
+ if (resultaddr) {
+ /* we got some result from the DNS query, not NXDOMAIN. should we consider 'positive'? */
+ const char* postvresp = servers[zonenum].postvresp; /* check positive match criteria */
+ if ((apr_strnatcasecmp(postvresp, DNSBL_MATCH_ANY) == 0) ||
+ (strncmp(resultaddr, postvresp, strlen(postvresp)) == 0)) {
+ numpositive++;
+ if (zonedata)
+ apr_table_add(zonedata, servers[zonenum].zonedomain, resultaddr);
+ if (querymode == DNSBL_ANYPOSTV_RETFIRST)
+ return DNSBL_POSITIVE; /* found one positive, returning single */
+ }
+ }
+ }
+ /* all servers were queried */
+ if (numpositive == numservers)
+ return DNSBL_POSITIVE;
+ else if ((querymode == DNSBL_ANYPOSTV_RETEVERY) && (numpositive > 0))
+ return DNSBL_POSITIVE;
+ else
+ return DNSBL_NEGATIVE;
+}
+
+
+/*
+
+Do DNSBL lookups for an IP address
+
+chain The chain name from the configuration to query
+
+querymode
+DNSBL_ANYPOSTV_RETFIRST - Any positive from chain, stop and return first
+DNSBL_ANYPOSTV_RETEVERY - Any positive, check all and return every positive
+DNSBL_ALLPOSTV_RETEVERY - All must check positive, return every positive
+
+address The address to look up. Only IPv4 is currently supported.
+
+p Pool to use for storage
+
+s Server record whose module configuration to use
+
+zonedata (output)
+If zonedata is NULL then there will be none returned. Otherwise, a new table
+will be created and filled with {zone, result} pairs for each zone that
+comes back positive. The result is an IPv4 string, probably 127.0.0.x. Note
+that this zonedata table will only contain entries if there is some positive
+match, i.e., only if the return code was DNSBL_POSITIVE.
+
+Returns:
+DNSBL_POSITIVE - Positive match (zonedata has details, if requested)
+DNSBL_NEGATIVE - Negative
+DNSBL_FAILURE - Generic failure, e.g. DnsblLookups Off or invalid chain
+
+*/
+static int dnsbl_lookup_ip(const char* chain, int querymode, apr_sockaddr_t* address,
+ apr_pool_t* p, server_rec* s, apr_table_t** zonedata)
+{
+ dnsbl_lookup_cfg* cfg;
+ apr_table_t* zones = NULL; /* might not return zonedata */
+ apr_array_header_t* zonechain;
+ char* lookupkey;
+
+ cfg = ap_get_module_config(s->module_config, &dnsbl_lookup_module);
+ if (!(cfg->lookup_enabled))
+ return DNSBL_FAILURE; /* DNSBL lookups are not enabled */
+ if (!address)
+ return DNSBL_FAILURE; /* null address given */
+ /*
+ Require IPv4. TODO: add IPv6 support
+ That would involve apr_hash_get from ipv6_dnsbl_chains and
+ preparing an appropriate lookupkey, string form of IPv6
+ */
+ if (address->ipaddr_len > 16)
+ return DNSBL_FAILURE;
+ lookupkey = ipreverse(p, address);
+ if (!lookupkey)
+ return DNSBL_FAILURE; /* unable to prepare lookup string from address */
+ zonechain = (apr_array_header_t *)apr_hash_get(cfg->ipv4_dnsbl_chains, chain, APR_HASH_KEY_STRING);
+ if (!zonechain)
+ return DNSBL_FAILURE; /* no such chain */
+ if (zonedata) {
+ *zonedata = apr_table_make(p, 1);
+ zones = *zonedata;
+ }
+ /* pass work to main lookup function */
+ return dnsbl_lookup(zonechain, querymode, lookupkey, p, zones, cfg);
+}
+
+
+/*
+ Similar to dnsbl_lookup_ip() except _domain is used for RHSBLs to query some
+ host or domain name. Return codes the same - passes through to dnsbl_lookup()
+*/
+static int dnsbl_lookup_domain(const char* chain, int querymode, const char* domain,
+ apr_pool_t* p, server_rec* s, apr_table_t** zonedata)
+{
+ dnsbl_lookup_cfg* cfg;
+ apr_table_t* zones = NULL; /* might not return zonedata */
+ apr_array_header_t* zonechain;
+
+ cfg = ap_get_module_config(s->module_config, &dnsbl_lookup_module);
+ if (!(cfg->lookup_enabled))
+ return DNSBL_FAILURE; /* DNSBL lookups are not enabled */
+ if (!domain)
+ return DNSBL_FAILURE; /* null domain given */
+
+ zonechain = (apr_array_header_t *)apr_hash_get(cfg->rhsbl_chains, chain, APR_HASH_KEY_STRING);
+ if (!zonechain)
+ return DNSBL_FAILURE; /* no such chain */
+ if (zonedata) {
+ *zonedata = apr_table_make(p, 1);
+ zones = *zonedata;
+ }
+ /* pass work to main lookup function */
+ return dnsbl_lookup(zonechain, querymode, domain, p, zones, cfg);
+}
+
+
+/*
+ Called by Apache to create per-server configuration (virtual host)
+ Returns pointer to module-specific structure
+*/
+static void* dnsbl_lookup_create_server_config(apr_pool_t* p, server_rec* s)
+{
+ dnsbl_lookup_cfg* cfg = apr_pcalloc(p, sizeof(dnsbl_lookup_cfg));
+ cfg->lookup_enabled = 0; /* disabled by default */
+ cfg->ipv4_dnsbl_chains = apr_hash_make(p);
+ cfg->rhsbl_chains = apr_hash_make(p);
+ return cfg;
+}
+
+
+static const char* enable_dnsbl_lookups(cmd_parms* cmd, void* dummy, int arg)
+{
+ dnsbl_lookup_cfg* cfg = ap_get_module_config(cmd->server->module_config, &dnsbl_lookup_module);
+ if (cfg)
+ cfg->lookup_enabled = arg;
+ return NULL;
+}
+
+/*
+ Helper function to add DNSBL and RHSBL zones into chains.
+ Hash tables store the chain names under each chain namespace
+ The hash table entries are arrays of zone_entry structs
+*/
+static const char* add_into_chains(apr_pool_t* p, apr_hash_t* chainspace,
+ const char* chain, const char* domain, const char* postvresp)
+{
+ apr_array_header_t* zonechain;
+ zone_entry* newentry;
+
+ zonechain = (apr_array_header_t *)apr_hash_get(chainspace, chain, APR_HASH_KEY_STRING);
+ if (!zonechain) { /* this chain does not exist yet */
+ zonechain = apr_array_make(p, 1, sizeof(zone_entry));
+ apr_hash_set(chainspace, chain, APR_HASH_KEY_STRING, zonechain);
+ }
+ newentry = (zone_entry *) apr_array_push(zonechain);
+ newentry->zonedomain = domain;
+ newentry->postvresp = postvresp;
+ return NULL;
+}
+
+
+static const char* set_ipv4_dnsbl(cmd_parms* cmd, void* dummy, const char* chain,
+ const char* domain, const char* postvresp)
+{
+ dnsbl_lookup_cfg* cfg = ap_get_module_config(cmd->server->module_config, &dnsbl_lookup_module);
+ return add_into_chains(cmd->pool, cfg->ipv4_dnsbl_chains, chain, domain, postvresp);
+}
+
+
+static const char* set_rhsbl(cmd_parms* cmd, void* dummy, const char* chain,
+ const char* domain, const char* postvresp)
+{
+ dnsbl_lookup_cfg* cfg = ap_get_module_config(cmd->server->module_config, &dnsbl_lookup_module);
+ return add_into_chains(cmd->pool, cfg->rhsbl_chains, chain, domain, postvresp);
+}
+
+static void dnsbl_lookup_register_hooks(apr_pool_t *p)
+{
+ APR_REGISTER_OPTIONAL_FN(dnsbl_lookup_ip); /* Register our utility function (optional function) */
+ APR_REGISTER_OPTIONAL_FN(dnsbl_lookup_domain);
+}
+
+
+static const command_rec dnsbl_lookup_cmds[] = {
+ AP_INIT_FLAG("DnsblLookups", enable_dnsbl_lookups, NULL, RSRC_CONF, "Enable DNSBL and RHSBL lookups"),
+ AP_INIT_TAKE3("DnsblZone", set_ipv4_dnsbl, NULL, RSRC_CONF, "Define an IPv4 DNSBL zone in a chain"),
+ AP_INIT_TAKE3("RhsblZone", set_rhsbl, NULL, RSRC_CONF, "Define a RHSBL zone in a chain"),
+ { NULL }
+};
+
+
+module AP_MODULE_DECLARE_DATA dnsbl_lookup_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL,
+ NULL,
+ dnsbl_lookup_create_server_config,
+ NULL,
+ dnsbl_lookup_cmds,
+ dnsbl_lookup_register_hooks
+};
Propchange: httpd/mod_smtpd/trunk/mod_dnsbl_lookup/mod_dnsbl_lookup.c
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile Mon Aug 22 21:34:20 2005
@@ -0,0 +1,17 @@
+APXS=/usr/sbin/apxs
+CFLAGS=-Wall
+APXSFLAGS=
+RBL_SRC=mod_smtpd_rbl.c
+
+all: mod_smtpd_rbl.la
+
+mod_smtpd_rbl.la: $(RBL_SRC)
+ $(APXS) -Wc,"$(CFLAGS)" $(APXSFLAGS) -o mod_smtpd_rbl.la -c $(RBL_SRC)
+
+install: all
+ $(APXS) -i -a -n smtpd_rbl mod_smtpd_rbl.la
+
+clean-objs:
+ rm -rf *.lo *.o *.slo *~ *.la .libs
+
+clean: clean-objs
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile.in
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile.in?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile.in (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile.in Mon Aug 22 21:34:20 2005
@@ -0,0 +1,17 @@
+APXS=@APXS_BIN@
+CFLAGS=-Wall
+APXSFLAGS=
+RBL_SRC=mod_smtpd_rbl.c
+
+all: mod_smtpd_rbl.la
+
+mod_smtpd_rbl.la: $(RBL_SRC)
+ $(APXS) -Wc,"$(CFLAGS)" $(APXSFLAGS) -o mod_smtpd_rbl.la -c $(RBL_SRC)
+
+install: all
+ $(APXS) -i -a -n smtpd_rbl mod_smtpd_rbl.la
+
+clean-objs:
+ rm -rf *.lo *.o *.slo *~ *.la .libs
+
+clean: clean-objs
Propchange: httpd/mod_smtpd/trunk/mod_smtpd_rbl/Makefile.in
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/README
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/README?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/README (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/README Mon Aug 22 21:34:20 2005
@@ -0,0 +1,30 @@
+mod_smtpd_rbl brings "RBL" (DNSBL/RHSBL) support to mod_dnsbl
+-> requires mod_smtpd
+-> requires mod_dnsbl_lookup
+
+The only directives introduced by mod_smtpd_rbl are
+SmtpWhitelist - Set SMTP whitelist chain name
+SmtpBlacklist - Set SMTP blacklist chain name
+
+The main configuration is handled by mod_dnsbl_lookup, see README for a complete
+description of how to configure multiple chains for DNSBL and RHSBL lookups.
+
+Here is a sample configuration:
+
+# Enable mod_smtpd
+SmtpProtocol On
+
+# Define whitelist and blacklist chains for mod_smtpd_rbl
+SmtpWhitelist mywhitelist
+SmtpBlacklist myblacklist
+
+# Enable mod_dnsbl_lookup
+DnsblLookups On
+
+# The zones and chains for mod_dnsbl_lookup
+
+RhsblZone myblacklist rhsbl.ahbl.org. 127.0.0.2
+RhsblZone myblacklist abuse.rfc-ignorant.org. 127.0.0.4
+
+DnsblZone myblacklist sbl.spamhaus.org. any
+DnsblZone myblacklist cbl.abuseat.org. any
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/autogen.sh
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/autogen.sh?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/autogen.sh (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/autogen.sh Mon Aug 22 21:34:20 2005
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+autoconf
+rm -rf autom4te.cache
Propchange: httpd/mod_smtpd/trunk/mod_smtpd_rbl/autogen.sh
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/configure.ac
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/configure.ac?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/configure.ac (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/configure.ac Mon Aug 22 21:34:20 2005
@@ -0,0 +1,60 @@
+# Required initializer
+AC_INIT(mod_smtpd_rbl, 0.90)
+
+AC_DEFUN([CHECK_VERSION],[dnl
+ min_apache_version=ifelse([$1], ,no,$1)
+ AP_BIN=`$APXS_BIN -q BINDIR`
+ AP_SBIN=`$APXS_BIN -q SBINDIR`
+ AP_PROG=`$APXS_BIN -q PROGNAME`
+ if test -e "$AP_BIN/$AP_PROG"; then
+ AP_PATH="$AP_BIN/$AP_PROG"
+ else
+ AP_PATH="$AP_SBIN/$AP_PROG"
+ fi
+ our_apache_version=`$AP_PATH -v | grep -i Apache |
+ sed -e 's/.*Apache\///' | tr -dc [^0-9.]`
+
+ AC_MSG_CHECKING(for Apache version >= $min_apache_version)
+
+ if test "$our_apache_version" \> "$min_apache_version" ||
+ test "$our_apache_version" = "$min_apache_version"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([*** Apache version $min_apache_version not found!])
+ fi
+])
+
+# Define a macro that is used to parse a --with-apxs parameter
+# The macro is named "APACHE_DIR"
+AC_DEFUN([APACHE_DIR],[dnl
+ AC_ARG_WITH(
+ apxs,
+ [ --with-apxs[=PATH_TO_APXS] APXS Location],
+ apxs_prefix="$withval",
+ )
+
+ if test -d $apxs_prefix; then
+ apxs_prefix=`dirname $apxs_prefix`
+
+ test_paths="$apxs_prefix:$apxs_prefix/bin:$apxs_prefix/sbin"
+ test_paths="${test_paths}:${PATH}:/usr/bin:/usr/sbin"
+ test_paths="${test_paths}:/usr/local/bin:/usr/local/sbin:/usr/local/apache2/bin"
+ AC_PATH_PROG(APXS_BIN, apxs, no, [$test_paths])
+ else
+ APXS_BIN="$withval"
+ fi
+
+ if test "$APXS_BIN" = "no"; then
+ AC_MSG_ERROR([*** The apxs binary installed by apache could not be found!])
+ AC_MSG_ERROR([*** Use the --with-apxs option with the full path to apxs])
+ fi
+])
+
+# Now call the APACHE_DIR macro that was just specified
+APACHE_DIR
+
+CHECK_VERSION(2.0)
+
+# Write the Makefile
+AC_OUTPUT(Makefile)
Propchange: httpd/mod_smtpd/trunk/mod_smtpd_rbl/configure.ac
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/dnsbl_lookup.h
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/dnsbl_lookup.h?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/dnsbl_lookup.h (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/dnsbl_lookup.h Mon Aug 22 21:34:20 2005
@@ -0,0 +1,34 @@
+#ifndef MOD_DNSBL_LOOKUP_H
+#define MOD_DNSBL_LOOKUP_H
+
+#include <httpd.h>
+#include <apr_optional.h>
+
+/* Boolean-like result of a dnsbl lookup */
+#define DNSBL_NEGATIVE 0 /* negative */
+#define DNSBL_POSITIVE 1 /* positive match */
+#define DNSBL_FAILURE 2 /* generic failure, not enabled or configured */
+
+/* Types of queries for dnsbl_lookup_ip() and dnsbl_lookup_domain() */
+#define DNSBL_ANYPOSTV_RETFIRST 0 /* Any positive from chain, stop and return first */
+#define DNSBL_ANYPOSTV_RETEVERY 1 /* Any positive, check all and return every positive */
+#define DNSBL_ALLPOSTV_RETEVERY 2 /* All must check positive, return every positive */
+
+#define DNSBL_MATCH_ANY "any"
+
+APR_DECLARE_OPTIONAL_FN(int, dnsbl_lookup_ip,
+ (const char*, int, apr_sockaddr_t*, apr_pool_t*, server_rec*, apr_table_t**) );
+
+APR_DECLARE_OPTIONAL_FN(int, dnsbl_lookup_domain,
+ (const char*, int, const char*, apr_pool_t*, server_rec*, apr_table_t**) );
+
+/*
+ This structure defines a zone in a chain
+ These are stored within hash tables - one table for IPv4 DNSBLs, another for RHSBLs
+*/
+typedef struct {
+ const char* zonedomain;
+ const char* postvresp; /* positive response, (sub)string or DNSBL_MATCH_ANY */
+} zone_entry;
+
+#endif
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd.h
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd.h?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd.h (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd.h Mon Aug 22 21:34:20 2005
@@ -0,0 +1,165 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MOD_SMTPD_H
+#define _MOD_SMTPD_H
+
+#include "apr_pools.h"
+#include "apr_hash.h"
+#include "apr_file_io.h"
+#include "httpd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Current version of the Plugin interface */
+#define SMTPD_PLUGIN_VERSION 20050414
+
+#if !defined(WIN32)
+#define SMTPD_DECLARE(type) type
+#define SMTPD_DECLARE_NONSTD(type) type
+#define SMTPD_DECLARE_DATA
+#elif defined(SMTPD_DECLARE_STATIC)
+#define SMTPD_DECLARE(type) type __stdcall
+#define SMTPD_DECLARE_NONSTD(type) type
+#define SMTPD_DECLARE_DATA
+#elif defined(SMTPD_DECLARE_EXPORT)
+#define SMTPD_DECLARE(type) __declspec(dllexport) type __stdcall
+#define SMTPD_DECLARE_NONSTD(type) __declspec(dllexport) type
+#define SMTPD_DECLARE_DATA __declspec(dllexport)
+#else
+#define SMTPD_DECLARE(type) __declspec(dllimport) type __stdcall
+#define SMTPD_DECLARE_NONSTD(type) __declspec(dllimport) type
+#define SMTPD_DECLARE_DATA __declspec(dllimport)
+#endif
+
+ typedef enum {
+ SMTPD_DECLINED,
+ SMTPD_DENY,
+ SMTPD_DENYSOFT,
+ SMTPD_DENY_DISCONNECT,
+ SMTPD_DENYSOFT_DISCONNECT,
+ SMTPD_DONE,
+ SMTPD_DONE_DISCONNECT,
+ SMTPD_OK
+ } smtpd_retcode;
+
+ typedef enum {
+ SMTPD_STATE_GOT_NOTHING,
+ SMTPD_STATE_GOT_HELO,
+ SMTPD_STATE_GOT_MAIL,
+ SMTPD_STATE_GOT_RCPT
+ } smtpd_trans_state;
+
+ typedef enum {
+ SMTPD_PROTOCOL_SMTP,
+ SMTPD_PROTOCOL_ESMTP
+ } smtpd_protocol_type;
+
+ typedef struct smtpd_return_data {
+ apr_pool_t *p;
+ /* list of messages
+ null terminated */
+ char **msgs;
+ } smtpd_return_data;
+
+ typedef struct smtpd_trans_rec {
+ apr_pool_t *p;
+
+ /* where are we in the current transaction */
+ smtpd_trans_state state_vector;
+
+ /* is this esmtp or smtp */
+ /* by default smtp */
+ smtpd_protocol_type extended;
+
+ /* hostname we were helo'd with */
+ char *helo;
+
+ /* string of who this mail is from */
+ char *mail_from;
+
+ /* recipient list */
+ apr_array_header_t *rcpt_to;
+
+ /* spooled data file pointer */
+ apr_file_t *tfp;
+ } smtpd_trans_rec;
+
+ typedef struct smtpd_conn_rec {
+ apr_pool_t *p;
+ conn_rec *c;
+ server_rec *s;
+
+ /* extensions registered with this connection */
+ apr_array_header_t *extensions;
+
+ /* current transaction */
+ smtpd_trans_rec *transaction;
+
+ /* bb in */
+ apr_bucket_brigade *bb_in;
+
+ /* bb out */
+ apr_bucket_brigade *bb_out;
+ } smtpd_conn_rec;
+
+ /* public */
+ SMTPD_DECLARE_NONSTD(void)
+ smtpd_register_extension(smtpd_conn_rec *scr, const char *line);
+
+ SMTPD_DECLARE_NONSTD(void)
+ smtpd_reset_transaction(smtpd_conn_rec *scr);
+
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode,
+ unrecognized_command,
+ (smtpd_conn_rec *scr, smtpd_return_data *in,
+ char *command, char *data));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, connect,
+ (smtpd_conn_rec *scr, smtpd_return_data *in));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, reset_transaction,
+ (smtpd_conn_rec *scr));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, helo,
+ (smtpd_conn_rec *scr, smtpd_return_data *in,
+ char *str));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, ehlo,
+ (smtpd_conn_rec *scr, smtpd_return_data *in,
+ char *str));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, mail,
+ (smtpd_conn_rec *scr, smtpd_return_data *in,
+ char *str));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, rcpt,
+ (smtpd_conn_rec *scr, smtpd_return_data *in,
+ char *str));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, vrfy,
+ (smtpd_conn_rec *scr, smtpd_return_data *in,
+ char *str));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, quit,
+ (smtpd_conn_rec *scr, smtpd_return_data *in));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, data,
+ (smtpd_conn_rec *scr, smtpd_return_data *in));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, data_post,
+ (smtpd_conn_rec *scr, smtpd_return_data *in));
+ APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, queue,
+ (smtpd_conn_rec *scr, smtpd_return_data *in));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_MOD_SMTPD_H */
Propchange: httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd.h
------------------------------------------------------------------------------
svn:executable = *
Added: httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd_rbl.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd_rbl.c?rev=239342&view=auto
==============================================================================
--- httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd_rbl.c (added)
+++ httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd_rbl.c Mon Aug 22 21:34:20 2005
@@ -0,0 +1,162 @@
+/* Copyright 2005 Jem Berkes
+ * www.sysdesign.ca
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ap_config.h"
+#include "apr_optional.h"
+#include "apr_strings.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_connection.h"
+#include "util_filter.h"
+#include <string.h>
+
+#include "mod_smtpd.h"
+#include "dnsbl_lookup.h"
+
+
+module AP_MODULE_DECLARE_DATA smtpd_rbl_module;
+
+
+typedef struct smtpd_rbl_config
+{
+ const char* whitelist_chain;
+ const char* blacklist_chain;
+} smtpd_rbl_config;
+
+
+static void *smtpd_rbl_create_server_config(apr_pool_t * p, server_rec * s)
+{
+ smtpd_rbl_config *cfg = apr_pcalloc(p, sizeof(smtpd_rbl_config));
+ /* the pointers to chain names will be null unless configured */
+ return cfg;
+}
+
+
+/*
+ When mod_smtpd gets MAIL FROM it will invoke this callback,
+ (smtpd_run_mail) and we will do a RHSBL check on the envelope
+ sender's domain portion to see whether mail should be denied.
+
+ If there is a whitelist match, it will override a blacklist.
+*/
+smtpd_retcode check_envelope(smtpd_conn_rec *scr, smtpd_return_data *in, char *str)
+{
+ char *pos, *querystr;
+ smtpd_rbl_config* cfg = ap_get_module_config(scr->s->module_config, &smtpd_rbl_module);
+ int (* dnsbl_domain)(const char*, int, const char*, apr_pool_t*,
+ server_rec*, apr_table_t**);
+
+ pos = strchr(str, '@'); /* find domain in MAIL FROM: <hi...@address> */
+ if (pos) {
+ querystr = apr_pstrdup(scr->p, pos+1);
+ for (pos=querystr; *pos && (*pos != '>') && (*pos != ' '); pos++)
+ ;
+ *pos = '\0'; /* querystr now has just domain */
+ }
+ else
+ return SMTPD_OK;
+
+ dnsbl_domain = APR_RETRIEVE_OPTIONAL_FN(dnsbl_lookup_domain);
+ if (dnsbl_domain && cfg) {
+ if (cfg->whitelist_chain && (dnsbl_domain(cfg->whitelist_chain, DNSBL_ANYPOSTV_RETFIRST,
+ querystr, scr->p, scr->s, NULL)==DNSBL_POSITIVE))
+ return SMTPD_OK; /* envelope domain was whitelisted */
+ if (cfg->blacklist_chain && (dnsbl_domain(cfg->blacklist_chain, DNSBL_ANYPOSTV_RETFIRST,
+ querystr, scr->p, scr->s, NULL)==DNSBL_POSITIVE)) {
+ /* prepare description of why access is denied */
+ in->msgs = apr_pcalloc(scr->p, 2*sizeof(char*));
+ in->msgs[0] = apr_psprintf(scr->p, "Envelope domain %s not permitted", querystr);
+ in->msgs[1] = NULL;
+ return SMTPD_DENY;
+ }
+ }
+ /* default action */
+ return SMTPD_OK;
+}
+
+
+/*
+ When mod_smtpd gets a connection it will invoke this callback,
+ (smtpd_run_connect) and we will do a DNSBL check on the peer IP
+ to see whether mail should be denied.
+
+ If there is a whitelist match, it will override a blacklist.
+*/
+smtpd_retcode check_address(smtpd_conn_rec *scr, smtpd_return_data *in)
+{
+ smtpd_rbl_config* cfg = ap_get_module_config(scr->s->module_config, &smtpd_rbl_module);
+ int (*dnsbl_ip)(const char*, int, apr_sockaddr_t*, apr_pool_t*,
+ server_rec*, apr_table_t**);
+
+ dnsbl_ip = APR_RETRIEVE_OPTIONAL_FN(dnsbl_lookup_ip);
+ if (dnsbl_ip && cfg) {
+ if (cfg->whitelist_chain && (dnsbl_ip(cfg->whitelist_chain, DNSBL_ANYPOSTV_RETFIRST,
+ scr->c->remote_addr, scr->p, scr->s, NULL)==DNSBL_POSITIVE))
+ return SMTPD_OK; /* connecting IP was whitelisted */
+ if (cfg->blacklist_chain && (dnsbl_ip(cfg->blacklist_chain, DNSBL_ANYPOSTV_RETFIRST,
+ scr->c->remote_addr, scr->p, scr->s, NULL)==DNSBL_POSITIVE)) {
+ in->msgs = apr_pcalloc(scr->p, 2*sizeof(char*));
+ in->msgs[0] = apr_psprintf(scr->p, "Client IP %s not permitted", scr->c->remote_ip);
+ in->msgs[1] = NULL;
+ return SMTPD_DENY;
+ }
+ }
+ /* default action */
+ return SMTPD_OK;
+}
+
+
+/*
+ Use hooks from mod_smtpd
+*/
+static void smtpd_rbl_register_hooks(apr_pool_t * p)
+{
+ APR_OPTIONAL_HOOK(smtpd, mail, check_envelope, NULL, NULL, APR_HOOK_FIRST);
+ APR_OPTIONAL_HOOK(smtpd, connect, check_address, NULL, NULL, APR_HOOK_FIRST);
+}
+
+
+static const char* set_whitelist(cmd_parms* cmd, void* dummy, const char* arg)
+{
+ smtpd_rbl_config* cfg = ap_get_module_config(cmd->server->module_config, &smtpd_rbl_module);
+ cfg->whitelist_chain = arg;
+ return NULL;
+}
+
+static const char* set_blacklist(cmd_parms* cmd, void* dummy, const char* arg)
+{
+ smtpd_rbl_config* cfg = ap_get_module_config(cmd->server->module_config, &smtpd_rbl_module);
+ cfg->blacklist_chain = arg;
+ return NULL;
+}
+
+
+static const command_rec smtpd_rbl_cmds[] = {
+ AP_INIT_TAKE1("SmtpWhitelist", set_whitelist, NULL, RSRC_CONF, "Set SMTP whitelist chain name"),
+ AP_INIT_TAKE1("SmtpBlacklist", set_blacklist, NULL, RSRC_CONF, "Set SMTP blacklist chain name"),
+ {NULL}
+};
+
+
+module AP_MODULE_DECLARE_DATA smtpd_rbl_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL,
+ NULL,
+ smtpd_rbl_create_server_config,
+ NULL,
+ smtpd_rbl_cmds,
+ smtpd_rbl_register_hooks
+};
Propchange: httpd/mod_smtpd/trunk/mod_smtpd_rbl/mod_smtpd_rbl.c
------------------------------------------------------------------------------
svn:executable = *