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 <[email protected]> (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 -
--
## List details at https://lists.exim.org/mailman/listinfo/exim-users
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/