[svn:qpsmtpd] rev 432 - in trunk: . plugins/auth

[email protected] 10 Jun 2005 12:11:27 -0000
Newsgroups perl.cvs.qpsmtpd
Message-ID <[email protected]>
Author: jpeacock
Date: Fri Jun 10 05:11:26 2005
New Revision: 432

Added:
   trunk/plugins/auth/auth_cvm_unix_local
Modified:
   trunk/   (props changed)
Log:
 A new auth plugin by Gordon Rowell <[email protected]> 
 Interfaces with Bruce Guenther's Credential Validation Module (CVM)

 *   plugins/auth/auth_cvm_unix_local
     Only DENY if the credentials were accepted but incorrect (bad password?)


Added: trunk/plugins/auth/auth_cvm_unix_local
==============================================================================
--- (empty file)
+++ trunk/plugins/auth/auth_cvm_unix_local	Fri Jun 10 05:11:26 2005
@@ -0,0 +1,109 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+auth_cvm_unix_local - SMTP AUTH LOGIN module using 
+Bruce Guenther's Credential Validation Module (CVM) 
+    http://untroubled.org/cvm/
+
+=head1 SYNOPSIS
+
+In config/plugins:
+
+  auth/auth_cvm_unix_local \
+	cvm_socket /var/lib/cvm/cvm-unix-local.socket	\
+	enable_smtp no \
+	enable_ssmtp yes
+
+=head1 BUGS
+
+- Should probably handle auth-cram-md5 as well. However, this requires
+access to the plain text password. We could store a separate database
+of passwords purely for SMTP AUTH, for example as an optional 
+SMTPAuthPassword property of an account in the esmith::AccountsDB;
+
+=head1 DESCRIPTION
+
+This plugin implements an authentication plugin using Bruce Guenther's
+Credential Validation Module (http://untroubled.org/cvm).
+
+=head1 AUTHOR
+
+Copyright 2005 Gordon Rowell <[email protected]>
+
+This software is free software and may be distributed or modified
+under the same terms as Perl itself.
+
+=head1 VERSION
+
+Version $Id: auth_cvm_unix_local,v 1.1 2005/06/09 22:50:06 gordonr Exp gordonr $
+
+=cut
+
+use Socket;
+use constant SMTP_PORT => getservbyname("smtp", "tcp") || 25;
+use constant SSMTP_PORT => getservbyname("ssmtp", "tcp") || 465;
+
+sub register 
+{
+    my ( $self, $qp, %arg ) = @_;
+
+    unless ($arg{cvm_socket})
+    {
+        $self->log(LOGERROR, "authcvm - requires cvm_socket argument");
+        return 0;
+    }
+
+    $self->{_enable_smtp} = $arg{enable_smtp} || 'no';
+    $self->{_enable_ssmtp} = $arg{enable_ssmtp} || 'yes';
+
+    my $port = $ENV{PORT} || SMTP_PORT;
+
+    return 0 if ($port == SMTP_PORT and $self->{_enable_smtp} ne 'yes');
+    return 0 if ($port == SSMTP_PORT and $self->{_enable_ssmtp} ne 'yes');
+
+    if ($arg{cvm_socket} =~ /^([\w\/.-]+)$/)
+    {
+        $self->{_cvm_socket} = $1;
+    }
+
+    unless (-S $self->{_cvm_socket})
+    {
+	$self->log(LOGERROR, "authcvm - cvm_socket missing or not usable");
+	return 0;
+    }
+
+    $self->register_hook("auth-plain", "authcvm_plain");
+    $self->register_hook("auth-login", "authcvm_plain");
+#    $self->register_hook("auth-cram-md5", "authcvm_hash");
+}
+
+sub authcvm_plain
+{
+    my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) =
+      @_;
+
+    $self->log(LOGINFO, "authcvm/$method authentication attempt for: $user");
+
+    socket(SOCK, PF_UNIX, SOCK_STREAM, 0) 
+        or return (DENY, "authcvm/$method");
+
+    connect(SOCK, sockaddr_un($self->{_cvm_socket}))
+        or return (DENY, "authcvm/$method");
+
+    my $o = select(SOCK); $| = 1; select($o);
+
+    my ($u, $host) = split(/\@/, $user);
+    $host ||= "localhost";
+
+    print SOCK "\001$u\000$host\000$passClear\000\000";
+
+    shutdown SOCK, 1;
+
+    my $ret = <SOCK>;
+    my ($s) = unpack ("C", $ret);
+    return (
+	($s ? $s == 100 ? DENY : DECLINED
+	    : OK), 
+	"authcvm/$method");
+}