Altered SASL method to include the mechanism in log entries.

removed auth method from return calls in all auth plugins. The caller knows the mechanism already. In the code, the difference looks like this:

before:
        or return (DENY, "authcvm/$method");
after:
        or return (DENY, "authcvm");

Added debug level log entries in auth_vpopmaild

Conflicts:

	plugins/auth/auth_vpopmail_sql
This commit is contained in:
Matt Simerson 2012-05-04 16:04:28 -04:00 committed by Robert
parent 77ff89d6ca
commit a6e664ce83
7 changed files with 68 additions and 61 deletions

View File

@ -211,7 +211,7 @@ vpopmail.
=item auth_vpopmaild =item auth_vpopmaild
If you aren't sure which one to use, then use auth_vpopmaild. It If you aren't sure which one to use, then use auth_vpopmaild. It
has full support for all 3 authentication methods (PLAIN,LOGIN,CRAM-MD5), supports the PLAIN and LOGIN authentication methods,
doesn't require the qpsmtpd process to run with special permissions, and doesn't require the qpsmtpd process to run with special permissions, and
can authenticate against vpopmail running on another host. It does require can authenticate against vpopmail running on another host. It does require
the vpopmaild server to be running. the vpopmaild server to be running.
@ -228,7 +228,7 @@ CRAM-MD5 patch has been added to the developers repo:
=item auth_vpopmail_sql =item auth_vpopmail_sql
If you are using the MySQL backend for vpopmail, then this module can be If you are using the MySQL backend for vpopmail, then this module can be
used for smtp-auth. It has support for all three auth methods. However, it used for smtp-auth. It supports LOGIN, PLAIN, and CRAM-MD5. However, it
does not work with some vpopmail features such as alias domains, service does not work with some vpopmail features such as alias domains, service
restrictions, nor does it update vpopmail's last_auth information. restrictions, nor does it update vpopmail's last_auth information.

View File

@ -51,8 +51,8 @@ sub SASL {
} }
if ( $rc == OK ) { if ( $rc == OK ) {
$msg = "Authentication successful for $user" . $msg = uc($mechanism) . " authentication successful for $user" .
( defined $msg ? " - " . $msg : "" ); ( $msg ? " - $msg" : '');
$session->respond( 235, $msg ); $session->respond( 235, $msg );
$session->connection->relay_client(1); $session->connection->relay_client(1);
$session->log( LOGDEBUG, $msg ); # already logged by $session->respond $session->log( LOGDEBUG, $msg ); # already logged by $session->respond
@ -64,8 +64,8 @@ sub SASL {
return OK; return OK;
} }
else { else {
$msg = "Authentication failed for $user" . $msg = uc($mechanism) . " authentication failed for $user" .
( defined $msg ? " - " . $msg : "" ); ( $msg ? " - $msg" : '');
$session->respond( 535, $msg ); $session->respond( 535, $msg );
$session->log( LOGDEBUG, $msg ); # already logged by $session->respond $session->log( LOGDEBUG, $msg ); # already logged by $session->respond
return DENY; return DENY;

View File

@ -142,7 +142,7 @@ sub get_sudo {
my $sudo = `which sudo` || '/usr/local/bin/sudo'; my $sudo = `which sudo` || '/usr/local/bin/sudo';
return '' if !-x $sudo; return '' if !-x $sudo;
$sudo .= ' -C4'; # prevent sudo from clobber file descriptor 3 $sudo .= ' -C4'; # prevent sudo from clobbering file descriptor 3
return "$sudo -u vpopmail" if $binary =~ /vchkpw/; return "$sudo -u vpopmail" if $binary =~ /vchkpw/;
return $sudo; return $sudo;

View File

@ -47,8 +47,7 @@ use constant SSMTP_PORT => getservbyname("ssmtp", "tcp") || 465;
sub register { sub register {
my ( $self, $qp, %arg ) = @_; my ( $self, $qp, %arg ) = @_;
unless ($arg{cvm_socket}) unless ($arg{cvm_socket}) {
{
$self->log(LOGERROR, "authcvm - requires cvm_socket argument"); $self->log(LOGERROR, "authcvm - requires cvm_socket argument");
return 0; return 0;
} }
@ -61,13 +60,11 @@ sub register {
return 0 if ($port == SMTP_PORT and $self->{_enable_smtp} ne 'yes'); return 0 if ($port == SMTP_PORT and $self->{_enable_smtp} ne 'yes');
return 0 if ($port == SSMTP_PORT and $self->{_enable_ssmtp} ne 'yes'); return 0 if ($port == SSMTP_PORT and $self->{_enable_ssmtp} ne 'yes');
if ($arg{cvm_socket} =~ /^([\w\/.-]+)$/) if ($arg{cvm_socket} =~ /^([\w\/.-]+)$/) {
{
$self->{_cvm_socket} = $1; $self->{_cvm_socket} = $1;
} }
unless (-S $self->{_cvm_socket}) unless (-S $self->{_cvm_socket}) {
{
$self->log(LOGERROR, "authcvm - cvm_socket missing or not usable"); $self->log(LOGERROR, "authcvm - cvm_socket missing or not usable");
return 0; return 0;
} }
@ -81,13 +78,12 @@ sub authcvm_plain {
my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) = my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) =
@_; @_;
$self->log(LOGINFO, "authcvm/$method authentication attempt for: $user"); $self->log(LOGINFO, "authcvm authentication attempt for: $user");
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or return (DENY, "authcvm");
or return (DENY, "authcvm/$method");
connect(SOCK, sockaddr_un($self->{_cvm_socket})) connect(SOCK, sockaddr_un($self->{_cvm_socket}))
or return (DENY, "authcvm/$method"); or return (DENY, "authcvm");
my $o = select(SOCK); $| = 1; select($o); my $o = select(SOCK); $| = 1; select($o);
@ -100,8 +96,5 @@ sub authcvm_plain {
my $ret = <SOCK>; my $ret = <SOCK>;
my ($s) = unpack ("C", $ret); my ($s) = unpack ("C", $ret);
return ( return ( ($s ? $s == 100 ? DENY : DECLINED : OK), 'authcvm');
($s ? $s == 100 ? DENY : DECLINED
: OK),
"authcvm/$method");
} }

View File

@ -1,5 +1,4 @@
#!perl -w #!perl -w
use strict;
=head1 NAME =head1 NAME
@ -41,9 +40,13 @@ Please see the LICENSE file included with qpsmtpd for details.
=cut =cut
use strict; use strict;
use warnings;
use Qpsmtpd::Constants; use Qpsmtpd::Constants;
use Digest::HMAC_MD5 qw(hmac_md5_hex);
use vpopmail;
sub register { sub register {
my ($self, $qp) = @_; my ($self, $qp) = @_;
@ -53,16 +56,13 @@ sub register {
} }
sub auth_vpopmail { sub auth_vpopmail {
use vpopmail;
use Digest::HMAC_MD5 qw(hmac_md5_hex);
my ($self, $transaction, $method, $user, $passClear, $passHash, $ticket) = my ($self, $transaction, $method, $user, $passClear, $passHash, $ticket) =
@_; @_;
my ($pw_name, $pw_domain) = split "@", lc($user); my ($pw_name, $pw_domain) = split "@", lc($user);
$self->log(LOGINFO, "Authenticating against vpopmail: $user"); $self->log(LOGINFO, "Authenticating against vpopmail: $user");
return (DECLINED, "authvpopmail/$method - plugin not configured correctly") return (DECLINED, "auth_vpopmail - plugin not configured correctly")
if !test_vpopmail(); if !test_vpopmail();
my $pw = vauth_getpw($pw_name, $pw_domain); my $pw = vauth_getpw($pw_name, $pw_domain);
@ -71,25 +71,25 @@ sub auth_vpopmail {
# make sure the user exists # make sure the user exists
if (!$pw || (!$pw_clear_passwd && !$pw_passwd)) { if (!$pw || (!$pw_clear_passwd && !$pw_passwd)) {
return (DENY, "authvpopmail/$method - invalid user"); return (DENY, "auth_vpopmail - invalid user");
# change DENY to DECLINED to support multiple auth plugins # change DENY to DECLINED to support multiple auth plugins
} }
return (OK, "authvpopmail/$method") return (OK, "auth_vpopmail")
if $pw_passwd eq crypt($passClear, $pw_passwd); if $pw_passwd eq crypt($passClear, $pw_passwd);
# simplest case: clear text passwords # simplest case: clear text passwords
if (defined $passClear && defined $pw_clear_passwd) { if (defined $passClear && defined $pw_clear_passwd) {
return (DENY, "authvpopmail/$method - incorrect password") return (DENY, "auth_vpopmail - incorrect password")
if $passClear ne $pw_clear_passwd; if $passClear ne $pw_clear_passwd;
return (OK, "authvpopmail/$method"); return (OK, "auth_vpopmail");
} }
if ($method =~ /CRAM-MD5/i) { if ($method =~ /CRAM-MD5/i) {
# clear_passwd isn't defined so we cannot support CRAM-MD5 # clear_passwd isn't defined so we cannot support CRAM-MD5
return (DECLINED, "authvpopmail/$method") if !defined $pw_clear_passwd; return (DECLINED, "auth_vpopmail") if !defined $pw_clear_passwd;
if (defined $passHash if (defined $passHash
and $passHash eq hmac_md5_hex($ticket, $pw_clear_passwd)) and $passHash eq hmac_md5_hex($ticket, $pw_clear_passwd))
@ -97,11 +97,11 @@ sub auth_vpopmail {
} }
} }
return (OK, "authvpopmail/$method") return (OK, "auth_vpopmail")
if (defined $passHash if (defined $passHash
&& $passHash eq hmac_md5_hex($ticket, $pw_clear_passwd)); && $passHash eq hmac_md5_hex($ticket, $pw_clear_passwd));
return (DENY, "authvpopmail/$method - unknown error"); return (DENY, "auth_vpopmail - unknown error");
} }
sub test_vpopmail { sub test_vpopmail {

View File

@ -63,21 +63,21 @@ Please see the LICENSE file included with qpsmtpd for details.
=cut =cut
use DBI;
use Qpsmtpd::Constants;
use Digest::HMAC_MD5 qw(hmac_md5_hex);
sub register { sub register {
my ( $self, $qp ) = @_; my ( $self, $qp ) = @_;
$self->register_hook("auth-plain", "auth_vmysql" ); $self->register_hook('auth-plain', 'auth_vmysql');
$self->register_hook("auth-login", "auth_vmysql" ); $self->register_hook('auth-login', 'auth_vmysql');
$self->register_hook("auth-cram-md5", "auth_vmysql"); $self->register_hook('auth-cram-md5', 'auth_vmysql');
} }
sub auth_vmysql { sub auth_vmysql {
my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) = @_; my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) = @_;
use DBI;
use Qpsmtpd::Constants;
use Digest::HMAC_MD5 qw(hmac_md5_hex);
# $DB::single = 1; # $DB::single = 1;
my $dsn = $self->qp->config("vpopmail_mysql_dsn") || "dbi:mysql:dbname=vpopmail;host=127.0.0.1"; my $dsn = $self->qp->config("vpopmail_mysql_dsn") || "dbi:mysql:dbname=vpopmail;host=127.0.0.1";
@ -94,8 +94,7 @@ sub auth_vmysql {
return DECLINED if ! defined $pw_domain; return DECLINED if ! defined $pw_domain;
$self->log(LOGINFO, $self->log(LOGDEBUG, "auth_vpopmail_sql: $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 *
@ -123,7 +122,7 @@ 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, "auth_vmysql/$method" ); return ( DECLINED, "auth_vmysql" );
} }
# at this point we can assume the user name matched # at this point we can assume the user name matched
@ -139,10 +138,10 @@ SQL
) )
{ {
return ( OK, "auth_vmysql/$method" ); return ( OK, "auth_vmysql" );
} }
else { else {
return ( DENY, "auth_vmysql/$method - wrong password" ); return ( DENY, "auth_vmysql - wrong password" );
} }
} }

View File

@ -2,9 +2,11 @@
use strict; use strict;
use warnings; use warnings;
use Qpsmtpd::Constants;
use IO::Socket; use IO::Socket;
use version; use version;
my $VERSION = qv('1.0.1'); my $VERSION = qv('1.0.2');
sub register { sub register {
my ($self, $qp, %args) = @_; my ($self, $qp, %args) = @_;
@ -14,13 +16,16 @@ sub register {
$self->register_hook('auth-plain', 'auth_vpopmaild'); $self->register_hook('auth-plain', 'auth_vpopmaild');
$self->register_hook('auth-login', 'auth_vpopmaild'); $self->register_hook('auth-login', 'auth_vpopmaild');
$self->register_hook('auth-cram-md5', 'auth_vpopmaild'); #$self->register_hook('auth-cram-md5', 'auth_vpopmaild'); # not supported
} }
sub auth_vpopmaild { sub auth_vpopmaild {
my ($self, $transaction, $method, $user, $passClear, $passHash, $ticket) = @_; my ($self, $transaction, $method, $user, $passClear, $passHash, $ticket) = @_;
use Qpsmtpd::Constants; if ( ! $passClear ) {
$self->log(LOGINFO, "vpopmaild does not support cram-md5");
return DECLINED;
}
# create socket # create socket
my $vpopmaild_socket = my $vpopmaild_socket =
@ -31,28 +36,38 @@ sub auth_vpopmaild {
Type => SOCK_STREAM Type => SOCK_STREAM
) or return DECLINED; ) or return DECLINED;
#$self->log(LOGINFO, "Attempting $method auth via vpopmaild"); $self->log(LOGDEBUG, "attempting $method");
# Get server greeting (+OK) # Get server greeting (+OK)
my $connect_response = <$vpopmaild_socket>; my $connect_response = <$vpopmaild_socket>;
if ( $connect_response !~ /^\+OK/ ) { if ( ! $connect_response ) {
$self->log(LOGINFO, "Failed to receive vpopmaild connection response: $connect_response"); $self->log(LOGERROR, "no connection response");
close($vpopmaild_socket); close($vpopmaild_socket);
return DECLINED; return DECLINED;
}; };
# send login details if ( $connect_response !~ /^\+OK/ ) {
print $vpopmaild_socket "login $user $passClear\n\r"; $self->log(LOGERROR, "bad connection response: $connect_response");
close($vpopmaild_socket);
# get response from server return DECLINED;
my $login_response = <$vpopmaild_socket>; };
print $vpopmaild_socket "login $user $passClear\n\r"; # send login details
my $login_response = <$vpopmaild_socket>; # get response from server
close($vpopmaild_socket); close($vpopmaild_socket);
# check for successful login (single line (+OK) or multiline (+OK+)) if ( ! $login_response ) {
return (OK, 'auth_vpopmaild') if $login_response =~ /^\+OK/; $self->log(LOGERROR, "no login response");
return DECLINED;
};
$self->log(LOGINFO, "Failed vpopmaild authentication response: $login_response"); # check for successful login (single line (+OK) or multiline (+OK+))
if ( $login_response =~ /^\+OK/ ) {
$self->log(LOGDEBUG, "auth success");
return (OK, 'auth_vpopmaild');
};
$self->log(LOGNOTICE, "failed authentication response: $login_response");
return DECLINED; return DECLINED;
} }