updates to auth_vpopmail_sql module

updates to auth_vpopmail_sql module
 - moved vpopmail database parameters into config files
 - added LIMITATIONS section to POD, noting no support for alias domains
 - renamed sub from authsql (too generic) to auth_vmysql

Signed-off-by: Robert <rspier@pobox.com>
This commit is contained in:
Matt Simerson 2010-05-10 19:13:15 -04:00 committed by Robert
parent fbbf43ad15
commit 0ae24edc55

View File

@ -15,18 +15,34 @@ to compare the crypted password.
=head1 CONFIGURATION =head1 CONFIGURATION
Decide which authentication methods you are willing to support and uncomment echo "dbi:mysql:dbname=vpopmail;host=127.0.0.1" > config/vpopmail_mysql_dsn
echo "vpopmailuser" > config/vpopmail_mysql_user
echo "vpoppasswd" > config/vpopmail_mysql_pass
This can be a read-only database user since the plugin does not update the
last accessed time (yet, see below).
This module supports PLAIN, LOGIN, and CRAM-MD5 authentication methods. You
can disable undesired methods by editing this module and uncommenting
the lines in the register() sub. See the POD for Qspmtpd::Auth for more the lines in the register() sub. See the POD for Qspmtpd::Auth for more
details on the ramifications of supporting various authentication methods. details on the ramifications of supporting various authentication methods.
Then, change the database information at the top of the authsql() sub so that
the module can access the database. This can be a read-only account since
the plugin does not update the last accessed time (yet, see below).
The remote user must login with a fully qualified e-mail address (i.e. both The remote user must login with a fully qualified e-mail address (i.e. both
account name and domain), even if they don't normally need to. This is account name and domain), even if they don't normally need to. This is
because the vpopmail table has a unique index on pw_name/pw_domain, and this because the vpopmail table has a unique index on pw_name/pw_domain, and this
module requires that only a single record be returned from the database. module requires that only a single record be returned from the database.
=head1 LIMITATIONS
This authentication modules does not recognize domain aliases. So, if you have
the domain example.com, with domain aliases for example.org and example.net,
smtp-auth will only work for $user@example.com. If you have domain aliases,
consider using the auth_checkpassword plugin.
The checkpassword plugin only supports plain and login authentications, where
this plugin also supports CRAM-MD5. I use both modules together. I use this one
for CRAM-MD5 and the checkpassword plugin for plain and login.
=head1 FUTURE DIRECTION =head1 FUTURE DIRECTION
The default MySQL configuration for vpopmail includes a table to log access, The default MySQL configuration for vpopmail includes a table to log access,
@ -50,41 +66,38 @@ Please see the LICENSE file included with qpsmtpd for details.
sub register { sub register {
my ( $self, $qp ) = @_; my ( $self, $qp ) = @_;
$self->register_hook("auth-plain", "authsql" ); $self->register_hook("auth-plain", "auth_vmysql" );
$self->register_hook("auth-login", "authsql" ); $self->register_hook("auth-login", "auth_vmysql" );
$self->register_hook("auth-cram-md5", "authsql"); $self->register_hook("auth-cram-md5", "auth_vmysql");
} }
sub authsql { sub auth_vmysql {
my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) = @_;
use DBI; use DBI;
use Qpsmtpd::Constants; use Qpsmtpd::Constants;
use Digest::HMAC_MD5 qw(hmac_md5_hex); use Digest::HMAC_MD5 qw(hmac_md5_hex);
# $DB::single = 1; # $DB::single = 1;
my $connect = "dbi:mysql:dbname=vpopmail"; my $dsn = $self->qp->config("vpopmail_mysql_dsn") || "dbi:mysql:dbname=vpopmail;host=127.0.0.1";
my $dbuser = "vpopmailuser"; my $dbuser = $self->qp->config("vpopmail_mysql_user") || "vpopmailuser";
my $dbpasswd = "vpoppasswd"; my $dbpass = $self->qp->config("vpopmail_mysql_pass") || "vpoppasswd";
my $dbh = DBI->connect( $connect, $dbuser, $dbpasswd ); my $dbh = DBI->connect( $dsn, $dbuser, $dbpass );
$dbh->{ShowErrorStatement} = 1; $dbh->{ShowErrorStatement} = 1;
my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) = my ( $pw_name, $pw_domain ) = split '@', lc($user);
@_;
my ( $pw_name, $pw_domain ) = split "@", lc($user);
unless ( defined $pw_domain ) { return DECLINED if ! defined $pw_domain;
return DECLINED;
}
$self->log(LOGINFO, $self->log(LOGINFO,
"Authentication to vpopmail via mysql: $pw_name\@$pw_domain"); "Authentication to vpopmail via mysql: $pw_name\@$pw_domain");
my $sth = $dbh->prepare(<<SQL); my $sth = $dbh->prepare(<<SQL);
select * SELECT *
from vpopmail FROM vpopmail
where pw_name = ? and pw_domain = ? WHERE pw_name = ? AND pw_domain = ?
SQL SQL
$sth->execute( $pw_name, $pw_domain ); $sth->execute( $pw_name, $pw_domain );
@ -96,8 +109,8 @@ SQL
# if vpopmail was not built with '--enable-clear-passwd=y' # if vpopmail was not built with '--enable-clear-passwd=y'
# then pw_clear_passwd may not even exist # then pw_clear_passwd may not even exist
my $pw_clear_passwd = exists $passwd_hash->{'pw_clear_passwd'} my $pw_clear_passwd = exists $passwd_hash->{'pw_clear_passwd'}
? $passwd_hash->{'pw_clear_passwd'} ? $passwd_hash->{'pw_clear_passwd'}
: undef; : undef;
my $pw_passwd = $passwd_hash->{'pw_passwd'}; # this is always present my $pw_passwd = $passwd_hash->{'pw_passwd'}; # this is always present
@ -107,26 +120,26 @@ SQL
# user doesn't exist in this domain # user doesn't exist in this domain
( not defined $pw_passwd ) ( not defined $pw_passwd )
) { ) {
return ( DECLINED, "authsql/$method" ); return ( DECLINED, "auth_vmysql/$method" );
} }
# at this point we can assume the user name matched # at this point we can assume the user name matched
if ( if (
( defined $passClear and ( defined $passClear and
( (
($pw_clear_passwd eq $passClear) ($pw_clear_passwd eq $passClear)
or ($pw_passwd eq crypt( $passClear, $pw_passwd ) ) or ($pw_passwd eq crypt( $passClear, $pw_passwd ) )
) )
) )
or ( defined $passHash or ( defined $passHash
and $passHash eq hmac_md5_hex( $ticket, $pw_clear_passwd ) ) and $passHash eq hmac_md5_hex( $ticket, $pw_clear_passwd ) )
) )
{ {
return ( OK, "authsql/$method" ); return ( OK, "auth_vmysql/$method" );
} }
else { else {
return ( DENY, "authsql/$method - wrong password" ); return ( DENY, "auth_vmysql/$method - wrong password" );
} }
} }