The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

autowhitelist_captcha Version 1.0 by Marc Sebastian Pelzer http://search.cpan.org/~mpelzer/

DESCRIPTION

This plug-in is a whitelist which automatically maintains itself based on well known and widely used CAPTCHA authenication.

When you activate this plug-in, it starts to maintain a file called "config/autowhitelist_captcha.whitelist" which contains a list of all sender email addresses that are allowed to send mail. If one sends an email with a sender address that is unknown to this list, this plug-in will send an email to the senders email (or reply-to email) which contains a CAPTCHA image and some explanatory text. The user needs to send a replay to this email containing the solved CAPTCHA which will be detected and handled by this plug-in then. If the CAPTCHA is OK, the senders email will be added to the whitelist and he will be able to send email without and disturbance from this moment on. If the CAPTCHA is not OK, a new email with a fresh generated CAPTCHA is being send for a maximum of 5 times until we get a good response or the user gives up. If the user FAIL to solve the CAPTCHA within 5 tries, he will be added to the file "config/autowhitelist_captcha.blacklist" which is the blacklist equivalent. If you want to give a user new 5 tries, simply remove his email from the blacklist.

So, all in all three files are auto-generated and maintained by this plugin:

 config/autowhitelist_captcha.whitelist         Contains all whitelisted email addresses
 config/autowhitelist_captcha.blacklist         Contians all emails that finaly fail to solve the captcha
 config/autowhitelist_captcha.pending           Contains all emails with CAPTCHA solving in pending

The pending database is a DBM file because its way more easy to handle the stuff that I want to keep in a hash instead of a flat file. If you want to take a look into the file or if you want to manipulate its content, use a small Perl script like this:

--- 8< ----------------------------------------------------------------------------------------- #!/usr/bin/perl

use DB_File::Lock;

tie(%db, 'DB_File::Lock', 'autowhitelist_captcha.pending', O_RDWR|O_CREAT, 0600, $DB_HASH, 'write') || die "error: $!";

foreach $email (keys %db) {

        ($md5, $counter) = ($db($email} =~ m!^([^\:]+)\:(\d+)!);

        print "email = '$email', md5 = '$md5', failure counter = '$counter'\n";
}

untie(%db);

--- 8< -----------------------------------------------------------------------------------------

Generated CAPTCHAS are valid for one day by default. After that time, they expire in the database that is maintained by the Authen::Captcha Perl module. If you want to change the expiry, just seek for the line containing 'expire => 3600' and change the number in seconds.

By default, CAPTCHA images are generated to the /tmp directory. Make sure, that your qpsmtpd user can read and write to this directory. If you want to change the location, seek for the lines

data_folder => '/tmp', output_folder => '/tmp',

and change them to the folder you like. The images will be deleted when the user solved or fail to solve the CAPTCHA or when they have expired.

REQUIREMENTS

This plug-in needs the following Perl modules installed from CPAN:

Authen::Captcha DB_File::Lock GD Digest::MD5 (standard perl module) MIME::Base64 (standard perl module) Net::SMTP (standard perl module)

If you dont have them, get them via "perl -MCPAN -e shell".

IMPORTANT: as of version 1.023 the Perl module Authen::Captcha is not taint-safe. This means that it barfs when being called with 'perl -T' - that is what qpsmtpd does. In order to make it taint safe, apply this patch to your Authen/Captcha.pm file (mine is living in /usr/local/share/perl/5.8.8/Authen/):

Source: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=409731

--- 8< -----------------------------------------------------------------------------------------

--- Authen/Captcha.pm-orig 2007-02-05 11:25:13.000000000 +1100 +++ Authen/Captcha.pm 2007-02-05 11:26:22.000000000 +1100 @@ -232,7 +232,11 @@ foreach my $line (@data) { $line =~ s/\n//; - my ($data_time,$data_code) = split(/::/,$line); + + # + # Extract untainted time and code + # + my ($data_time,$data_code) = $line =~ m/(^\d+)::([[:xdigit:]]{32})$/;

                my $png_file = File::Spec->catfile($self->output_folder(),$data_code . ".png");
                if ($data_code eq $crypt)
@@ -351,7 +355,12 @@
        foreach my $line (@data) 
        {
                $line =~ s/\n//;
-               my ($data_time,$data_code) = split(/::/,$line);
+
+               #
+               # Extract untainted time and code
+               #
+               my ($data_time,$data_code) = $line =~ m/(^\d+)::([[:xdigit:]]{32})$/;
+
                if ( (($current_time - $data_time) > ($self->expire())) ||
                     ($data_code  eq $md5) )
                {       # remove expired captcha, or a dup

--- 8< -----------------------------------------------------------------------------------------

You may also have a look at the Captcha/images/ directory and replace the PNG images with better readable ones.

Also, if you run another qpsmtpd plug-in that check if the recipient exists, like "check_rcptto_exists", you should add a line like:

if ($recipient->user =~ m!^autowhitelist_captcha_!) { return DECLINED; } # allow all autowhitelist mails to pass

into it's method hook_rcpt() in order to allow response emails to the CAPTCHA mails. The reply email address will be like this:

autowhitelist_captcha_a8ffe2e890f22fa971bb@yourdomain.com

This is a 'fake' email address that contains the original md5-sum and will be catched and processed by this plug-in! Make sure, that this emails can pass through your other plug-ins that run before this one.

INSTALLATION

I tried to make the configuration of this plug-in as simple as possible. Nevertheless, some parameters are needed in order to make it work on your system. But please, dont give up - it's worth it :)

Please copy the plug-in into the qpsmtpd's plug-in directory:

plugins/autowhitelist_captcha

and edit the file

config/plugins

Add the plug-in's name somewhere in the upper section of the file.

Here is an example config file entry:

autowhitelist_captcha active

This plug-in can be called with one parameter 'active'. If this parameter is not set, we run in a 'dry-mode'. This means, that we accept all incoming mails and just write to the logfile what would happen if... This way you can run this plug-in without any damage and see if it works for you or not wihtout any email getting rejected. Just do a

tail -f /var/log/qpsmtpd*.log | grep autowhitelist

and see whats going on. When you'r sure that everything is good, then add the optional 'active' parameter and run your autowhitelist full featured.

CONFIGURATION

A configuration file is needed in order to run this plg-in. Create a file called

config/autowhitelist_captcha

which looks like this:

--- 8< ----------------------------------------------------------------------------------------- # config for autowhitelist_captcha #

 # one or more whitelist=/path/to/whitelist
 #
 whitelist=config/relayclients
 whitelist=/usr/local/exim/local.networks

 # email templates for initial and failure CAPTCHA emails
 #
 template=config/autowhitelist_captcha.first-email.template
 failure_template=config/autowhitelist_captcha.failure.template
 success_template=config/autowhitelist_captcha.success.template

 # local mailserver for ougoing CAPTCHA emails
 #
 mailhost=localhost:2525

 # whitelisting only for the following maildomains:
 #
 whitelist_domain=test1.com
 whitelist_domain=test2.org

 # whitelisting only for the following emails:
 #
 whitelist_email=test@test.net
 whitelist_email=user@mydomain.com

--- 8< -----------------------------------------------------------------------------------------

As you can see, parameters are passed over as key=value pairs. The following keys's are possible:

whitelist=/path/to/your/own/whitelist

        Path + Filename to your own (dynamicly generated) whitelist which contains one email or IP or hostname per line.
        Can be used multiple times to point to different whitelist-files! It's highly recommended to point to your
        (dynamicly generated) list of RELAY IP and/or hostnames. Otherwise also all emails that should be routet to
        the outside world (outgoing emails) will be handled through this module! So, if you have a list of RELAY IP's,
        add something like:
        
        whitelist=config/relayclients
        
        which looks like this:
        
        # this is config/relayclients
        #
        127.0.0.1
        192.168.1.*
        192.168.55.1
        192.168.55.99
        *.mydomain.de
        mydomain.*
        [...]

mailhost=localhost:2525

        This is the IP/hostname and tcp port of your local mailer that handles outgoing mails. We need this
        information in order to send emails which contains the CAPTCHA. Mails are sent using the Perl module
        Net::SMTP. Please costumize outgoing mail code if you have a special mail environment that does not
        fit the default. Seek the line 'Net::SMTP->new' and you see the code that send the CAPTCHA email.

firstmail_template=config/autowhitelist_captcha.first-email.template

        This line points to the path+filename of the email template that is used to send the CAPTCHA email.
        Please modify it to fit your needs and preferred language. Make sure, that two variables are still
        inside the template:
        
        {autowhitelist_captcha:imageBASE64}             The base64 encoded CAPTCHA image (PNG)
        
        {autowhitelist_captcha:rctp_email}              The recipient email address that the sender tried to send an
                                                                                        email to. This is mostly your email address or one of your
                                                                                        mail users.

        This template is being sent to the sender when he send you an email for the first time. So it's important
        that the text explains exactly whats going on and what the he should do to succeed with the CAPTCHA. You
        should explain what a CAPTCHA is for users who doesnt know it and you should also explain, that the
        CAPTCHA characters and numbers should be entered inside the [        ] brackets within the reply to the
        email - otherwise we cant extract the CAPTCHA response from the reply email.

failure_template=config/autowhitelist_captcha.failure.template

        This is almost the same as 'template' - a path and filename to an email template. This one gets send
        if a user send a wrong response to a CAPTCHA. So this means that we can use this template to explain
        a bit more what a CAPTCHA is and why he should reply to it. Also we can tell the user that his former
        answer wa wrong.
        
        The difference to 'template' is, that only one variable is available this time:
        
        {autowhitelist_captcha:imageBASE64}     The base64 encoded CAPTCHA image (PNG)

success_template=config/autowhitelist_captcha.success.template

        This template will be send to the user when he successfully solved the Captcha. It should explain, that
        he is now able to communicate with the recipient with ever need to solve a Captcha again. He should
        also be reminded to send his initial e-mail again, which has been blocked by this plug-in.

whitelist_domain=mydomain.com

        This line defines one or more domains that you want to autowhitelist. Every domain that you define will
        be affected by this plug-in. If you want to autowhitelist all of your domains, simply write:

        whitelist_domain=*

whitelist_email=test@test.net

        This is almost the same as whitelist_domain but instead for single emails. You can specify one or more
        emails that should be handled by this plug-in by adding one or multiple lines of whitelist_email.

CHANGELOG

Version 1.0 Thu Dec 6 2007 Initial release Marc Sebastian Pelzer

TODO

- Provide a set of better Authen::Captcha images with this package