Re: [exim] Dovecot style Authentication Policy Server for Ex…

Top Page
Delete this message
Reply to this message
Author: Mike Tubby
Date:  
To: exim-users
Old-Topics: Re: [exim] Dovecot style Authentication Policy Server for Exim?
Subject: Re: [exim] Dovecot style Authentication Policy Server for Exim? ** SOLUTION **
Heiko et al,

Inspired by Heiko's suggestion I have brewed up the following which
appears to work.

I now have:

    Exim authentication -> Perl -> HTTP -> Nginx -> PHP ->
MySQL/MariaDB backend

and it works a treat.


*Authenticators in Exim*

In Exim we have a PLAIN and a LOGIN authenticator that calls a Perl
subroutine exim_auth() - like this:

auth_plain:
        driver = plaintext
        public_name = PLAIN
        server_condition =
${perl{exim_auth}{$auth2}{$auth3}{$sender_host_address}}
        server_prompts = :
        server_set_id = $auth2

auth_login:
        driver = plaintext
        public_name = LOGIN
        server_condition =
${perl{exim_auth}{$auth1}{$auth2}{$sender_host_address}}
        server_prompts = Username:: : Password::
        server_set_id = $auth1


*Exim Perl authenticator shim*

In /etc/exim/exim.conf I have:

#
# Perl authenticator
#
perl_startup = do '/srv/auth_policy_server/perl/exim_auth.pl'
perl_at_start = true
perl_taintmode = true

and the code:

#!/usr/bin/perl
#
# exim_auth.pl -- A PERL shim between Exim authenticator and Web
Services authentication policy server.
#
# ABSTRACT
#
# Exim authenticator via PERL.  Called with three arguments from Exim:
#
#       1. Username
#       2. Password
#       3. Remote IP address
#
#
use strict;
use warnings;
use LWP::UserAgent ();

sub exim_auth {
    my $email = $_[0];
    my $password = $_[1];
    my $remote = $_[2];

    # new instance of LWP user agent
    my $ua = LWP::UserAgent->new(
        agent => 'EximAuth/0.01',
        timeout => 3
    );

    # create form data
    my %form;
    $form{'email'} = $email;
    $form{'password'} = $password;
    $form{'remote'} = $remote;

    # post the form data
    my $response = $ua->post('http://localhost/exim.php', \%form);

    # get response and map to success/fail
    return ($response->code() eq '204') ? 1 : 0;
}

which basically takes the three arguments, drops them into a form and
uses method POST to dispatch the request to Nginx on the same host.

Nginx returns:

    204: No content (auth success)
    403: Forbidden (auth failure)
    400: Bad request (all other errors)

which is reflected back into the server_condition as true/false.


*LEMP backend*

A PHP/Nginx/MySQL backend receives the form, does the authentication and
GeoIP policy stuff, logs the transaction and outcome and returns the
HTTP response code.


Mike


On 17/03/2020 08:18, Heiko Schlittermann via Exim-users wrote:
> Mike Tubby via Exim-users <exim-users@???> (Di 17 Mär 2020 01:51:55 CET):
>> All,
>>
>> Dovecot IMAP/POP3 server has a built-in Authentication Policy sub-system
>> whereby it can make a web-services call to to an Authentication Policy
>> Server:
>>
>> 1.     command: on connect, before authentication
>> 2.     command: on connect, after authentication
>> 3.     report: on final outcome of policy + authentication
>>
>> It would be "really good"(tm) if Exim could implement a similar
>> concept/service/API as it would allow me to leverage GEOIP against possible
>> attackers of some (protected) services and report back in to a common
>> database of failed connections for (a) GEOIP policy or (b) username/password
> Maybe I'm missing the point, but something *like* this comes into my
> mind immediatly: (at least as POC it should be ok)
>
>      PLAIN:
>          driver = plaintext
>          server_condition = ${perl{do_auth}{$auth1}{$auth2}{$sender_host_address}}

>
> And provide a Perl subrouting do_auth, that does the actual
> authentication.
>
> But then, of course, you've to implement the actual auth in the perl
> function.
>
> Maybe even that would work, but I'm not sure if we're flexible enough
> with the ACL
>
> begin acl
>
>      acl_auth:
>          require = <pre-auth>
>          require = <auth>
>          require = <report>
>          accept

>
> begin authenticators
>
>      PLAIN:
>          driver = plaintext
>          server_condition = acl_auth

>
>      Best regards from Dresden/Germany
>      Viele Grüße aus Dresden
>      Heiko Schlittermann
> --
>   SCHLITTERMANN.de ---------------------------- internet & unix support -
>   Heiko Schlittermann, Dipl.-Ing. (TU) - {fon,fax}: +49.351.802998{1,3} -
>   gnupg encrypted messages are welcome --------------- key ID: F69376CE -

>