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 = *