[PATCH 02/11] added logging and tests to auth_checkpassword

[email protected] (Matt Simerson)
Newsgroups perl.qpsmtpd
Message-ID <[email protected]>
---
 plugins/auth/auth_checkpassword        |   69 +++++++++++++++++++++++++-------
 t/plugin_tests/auth/auth_checkpassword |   44 ++++++++++++++++++++
 2 files changed, 99 insertions(+), 14 deletions(-)
 create mode 100644 t/plugin_tests/auth/auth_checkpassword

diff --git a/plugins/auth/auth_checkpassword b/plugins/auth/auth_checkpassword
index e6baa3b..520d608 100644
--- a/plugins/auth/auth_checkpassword
+++ b/plugins/auth/auth_checkpassword
@@ -14,7 +14,12 @@ or with sudo.
 
 =head1 CONFIGURATION
 
-Configure the path to your checkpassword binary:
+Configure the path to your checkpassword binary. You can configure this in
+config/plugins by defining the checkpw and true arguments as follows:
+
+ auth/auth_checkpassword checkpw /usr/local/vpopmail/bin/vchkpw true /usr/bin/true
+
+or by editing the config file config/smtpauth-checkpassword:
 
  echo "/usr/local/vpopmail/bin/vchkpw /usr/bin/true" > ~qpsmtpd/config/smtpauth-checkpassword
 
@@ -101,50 +106,86 @@ Please see the LICENSE file included with qpsmtpd for details.
 =cut
 
 sub register {
-    my ($self, $qp) = @_;
+    my ($self, $qp, %args ) = @_;
+
+    my ($checkpw, $true) = $self->get_checkpw( \%args );
+    return DECLINED if ! $checkpw || ! $true;
 
-    $self->register_hook("auth-plain", "auth_checkpassword");
-    $self->register_hook("auth-login", "auth_checkpassword");
+    $self->connection->notes('auth_checkpassword_bin', $checkpw);
+    $self->connection->notes('auth_checkpassword_true', $true);
+
+    $self->register_hook('auth-plain', 'auth_checkpassword');
+    $self->register_hook('auth-login', 'auth_checkpassword');
 }
 
 sub auth_checkpassword {
     my ($self, $transaction, $method, $user, $passClear, $passHash, $ticket) =
       @_;
 
-    my $command = $self->qp->config("smtpauth-checkpassword")
-      or return (DECLINED);
-    my ($binary, $params) = $command =~ /^(\S+)(.*)$/;
+    my $binary = $self->connection->notes('auth_checkpassword_bin');
+    my $true = $self->connection->notes('auth_checkpassword_true');
 
-    return (DECLINED) if (!-x $binary);
     my $sudo = get_sudo($binary);
 
-    open(CPW, "|$sudo $binary $params 3<&0");
+    $self->log(LOGDEBUG, "auth_checkpassword: $sudo $binary $true 3<&0");
+    open(CPW, "|$sudo $binary $true 3<&0");
     printf(CPW "%s\0%s\0Y123456\0", $user, $passClear);
     close(CPW);
 
     my $status = $?;
 
-    return (DECLINED) if ($status != 0);
+    if ($status != 0) {
+        $self->log(LOGNOTICE, "authentication failed ($status)");
+        return (DECLINED);
+    };
 
     $self->connection->notes('authuser', $user);
     return (OK, "auth_checkpassword");
 }
 
+sub get_checkpw {
+    my ($self, $args) = @_;
+
+    my ($checkpw) = $args->{checkpw} =~ /^(.*)$/ if $args->{checkpw}; # untaint
+    my ($true)    = $args->{true} =~ /^(.*)$/ if $args->{true};       # untaint
+
+    return ( $checkpw, $true )
+        if ( $checkpw && $true && -x $checkpw && -x $true );
+
+    my $missing_config = "disabled due to invalid configuration. See 'perldoc plugins/auth/auth_checkpassword' for how to configure.";
+
+    if ( ! $self->qp->config('smtpauth-checkpassword') ) {
+        $self->log(LOGERROR, $missing_config );
+        return;
+    };
+
+    $self->log(LOGNOTICE, "reading config from smtpauth-checkpassword");
+    my $config = $self->qp->config("smtpauth-checkpassword");
+    ($checkpw, $true) = $config =~ /^(\S+)\s+(\S+)\s*$/;
+
+    if ( ! $checkpw || ! $true || ! -x $checkpw || ! -x $true ) {
+        $self->log(LOGERROR, $missing_config );
+        return;
+    };
+    return ($checkpw, $true);
+};
+
 sub get_sudo {
     my $binary = shift;
 
     return '' if $> == 0;                            # running as root
-    return '' if $> == 89 && $binary =~ /vchkpw/;    # running as vpopmail
+    return '' if $> == 89 && $binary =~ /vchkpw$/;   # running as vpopmail
 
     my $mode = (stat($binary))[2];
     $mode = sprintf "%lo", $mode & 07777;
     return '' if $mode eq '4711';                    # $binary is setuid
 
     my $sudo = `which sudo` || '/usr/local/bin/sudo';
-    return '' if !-x $sudo;
+    return '' if ! -x $sudo;
+
     $sudo .= ' -C4';    # prevent sudo from clobbering file descriptor 3
 
-    return "$sudo -u vpopmail" if $binary =~ /vchkpw/;
-    return $sudo;
+    return $sudo if $binary !~ /vchkpw$/;
+    return "$sudo -u vpopmail";
 }
 
diff --git a/t/plugin_tests/auth/auth_checkpassword b/t/plugin_tests/auth/auth_checkpassword
new file mode 100644
index 0000000..c51fa2d
--- /dev/null
+++ b/t/plugin_tests/auth/auth_checkpassword
@@ -0,0 +1,44 @@
+#!perl -w
+
+warn "loaded auth_checkpassword\n";
+
+sub register_tests {
+    my $self = shift;
+
+    my ($vpopdir) = (getpwnam('vpopmail'))[7];
+
+    if ( ! $vpopdir ) {
+        warn "skipping tests, vpopmail not installed\n";
+        return;
+    };
+
+    if ( ! -d "$vpopdir/domains/example.com" ) {
+        warn "skipping tests, no example users set up.\n";
+        return;
+    };
+
+    $self->register_test("test_auth_checkpassword", 3);
+}
+
+my @u_list = qw ( good bad none );
+my %u_data = (
+	      good => [ '[email protected]', OK, 'Good Strong Passphrase' ],
+	      bad  => [ '[email protected]', DENY, 'not_bad_pass' ],
+	      none => [ '[email protected]', DECLINED, '' ],
+	      );
+
+sub test_auth_checkpassword {
+    my $self = shift;
+    my ($tran, $ret, $note, $u, $r, $p, $a );
+    $tran = $self->qp->transaction;
+    for $u ( @u_list ) {
+        ( $a,$r,$p ) = @{$u_data{$u}};
+        ($ret, $note) = $self->auth_checkpassword($tran,'LOGIN',$a,$p);
+        defined $note or $note='No-Message';
+        is ($ret, $r, $note);
+
+        ($ret, $note) = $self->auth_checkpassword($tran,'PLAIN',$a,$p);
+        defined $note or $note='No-Message';
+        is ($ret, $r, $note);
+    }
+}
-- 
1.7.9.6
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.