2012-04-29 10:35:59 +02:00
|
|
|
#!perl -w
|
2005-06-10 14:11:26 +02:00
|
|
|
|
|
|
|
=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 <gordonr@gormand.com.au>
|
|
|
|
|
r4215@g5: ask | 2006-01-24 23:11:01 -0800
From: gordonr@gormand.com.au
Subject: Re: Submitting plugins (was Re: New plugin: denybounce)
Date: January 24, 2006 9:02:35 PM PST
To: ask@develooper.com
Cc: gavin@openfusion.com.au, qpsmtpd@perl.org
Message-Id: <43D7066B.3050106@gormand.com.au>
Ask Bjørn Hansen wrote:
On Jan 24, 2006, at 1:08 PM, Gordon Rowell wrote:
- License statement - either as per qpsmtpd or as per Perl or similar open license
No, it really should be MIT licensed ("as per qpsmtpd") to go in the distribution.
There are a few exceptions (only your plugins at a cursory glance), but those are mistakes. :-)
I don't have an issue with my qpsmtpd plugins being changed to state:
=head1 AUTHOR
Copyright 2005 Gordon Rowell <gordonr@gormand.com.au>
This software is free software and may be distributed under the same
terms as qpsmtpd itself.
Though as a distro maintainer, we do have a sizeable issue with license proliferation. It really is a bit of a nightmare when two licenses are almost, but not completely, the same.
Thanks,
Gordon
r4216@g5: ask | 2006-01-24 23:12:21 -0800
merge license fix from trunk
git-svn-id: https://svn.perl.org/qpsmtpd/trunk@603 958fd67b-6ff1-0310-b445-bb7760255be9
2006-01-25 08:12:34 +01:00
|
|
|
This software is free software and may be distributed under the same
|
|
|
|
terms as qpsmtpd itself.
|
2005-06-10 14:11:26 +02:00
|
|
|
|
|
|
|
=head1 VERSION
|
|
|
|
|
|
|
|
Version $Id: auth_cvm_unix_local,v 1.1 2005/06/09 22:50:06 gordonr Exp gordonr $
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use Qpsmtpd::Constants;
|
|
|
|
|
2005-06-10 14:11:26 +02:00
|
|
|
use Socket;
|
|
|
|
use constant SMTP_PORT => getservbyname("smtp", "tcp") || 25;
|
|
|
|
use constant SSMTP_PORT => getservbyname("ssmtp", "tcp") || 465;
|
|
|
|
|
2012-04-08 02:11:16 +02:00
|
|
|
sub register {
|
2005-06-10 14:11:26 +02:00
|
|
|
my ( $self, $qp, %arg ) = @_;
|
|
|
|
|
2012-05-04 22:04:28 +02:00
|
|
|
unless ($arg{cvm_socket}) {
|
2012-05-07 09:36:01 +02:00
|
|
|
$self->log(LOGERROR, "skip: requires cvm_socket argument");
|
2005-06-10 14:11:26 +02:00
|
|
|
return 0;
|
2012-05-07 09:36:01 +02:00
|
|
|
};
|
2005-06-10 14:11:26 +02:00
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
$self->{_args} = { %arg };
|
2005-06-10 14:11:26 +02:00
|
|
|
$self->{_enable_smtp} = $arg{enable_smtp} || 'no';
|
|
|
|
$self->{_enable_ssmtp} = $arg{enable_ssmtp} || 'yes';
|
|
|
|
|
|
|
|
my $port = $ENV{PORT} || SMTP_PORT;
|
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
return 0 if ($port == SMTP_PORT && $arg{enable_smtp} ne 'yes');
|
|
|
|
return 0 if ($port == SSMTP_PORT && $arg{enable_ssmtp} ne 'yes');
|
2005-06-10 14:11:26 +02:00
|
|
|
|
2012-05-04 22:04:28 +02:00
|
|
|
if ($arg{cvm_socket} =~ /^([\w\/.-]+)$/) {
|
2005-06-10 14:11:26 +02:00
|
|
|
$self->{_cvm_socket} = $1;
|
|
|
|
}
|
|
|
|
|
2012-05-04 22:04:28 +02:00
|
|
|
unless (-S $self->{_cvm_socket}) {
|
2012-05-07 09:36:01 +02:00
|
|
|
$self->log(LOGERROR, "skip: cvm_socket missing or not usable");
|
2012-05-04 22:04:28 +02:00
|
|
|
return 0;
|
2005-06-10 14:11:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$self->register_hook("auth-plain", "authcvm_plain");
|
|
|
|
$self->register_hook("auth-login", "authcvm_plain");
|
|
|
|
# $self->register_hook("auth-cram-md5", "authcvm_hash");
|
|
|
|
}
|
|
|
|
|
2012-04-08 02:11:16 +02:00
|
|
|
sub authcvm_plain {
|
2005-06-10 14:11:26 +02:00
|
|
|
my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket ) =
|
|
|
|
@_;
|
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or do {
|
|
|
|
$self->log(LOGERROR, "skip: socket creation attempt for: $user");
|
|
|
|
return (DENY, "authcvm");
|
|
|
|
};
|
2005-06-10 14:11:26 +02:00
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
# DENY, really? Should this plugin return a DENY when it cannot connect
|
|
|
|
# to the cvs socket? I'd expect such a failure to return DECLINED, so
|
|
|
|
# any other auth plugins could take a stab at authenticating the user
|
2005-06-10 14:11:26 +02:00
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
connect(SOCK, sockaddr_un($self->{_cvm_socket})) or do {
|
|
|
|
$self->log(LOGERROR, "skip: socket connection attempt for: $user");
|
|
|
|
return (DENY, "authcvm");
|
|
|
|
};
|
2005-06-10 14:11:26 +02:00
|
|
|
|
|
|
|
my $o = select(SOCK); $| = 1; select($o);
|
|
|
|
|
|
|
|
my ($u, $host) = split(/\@/, $user);
|
|
|
|
$host ||= "localhost";
|
|
|
|
|
|
|
|
print SOCK "\001$u\000$host\000$passClear\000\000";
|
|
|
|
|
2012-05-07 09:36:01 +02:00
|
|
|
shutdown SOCK, 1; # tell remote we're finished
|
2005-06-10 14:11:26 +02:00
|
|
|
|
|
|
|
my $ret = <SOCK>;
|
|
|
|
my ($s) = unpack ("C", $ret);
|
2012-05-07 09:36:01 +02:00
|
|
|
|
|
|
|
if ( ! defined $s ) {
|
|
|
|
$self->log(LOGERROR, "skip: no response from cvm for $user");
|
|
|
|
return (DECLINED);
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( $s == 0 ) {
|
|
|
|
$self->log(LOGINFO, "pass: authentication for: $user");
|
|
|
|
return (OK, "auth success for $user");
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( $s == 100 ) {
|
|
|
|
$self->log(LOGINFO, "fail: authentication failure for: $user");
|
|
|
|
return (DENY, 'auth failure (100)');
|
|
|
|
};
|
|
|
|
|
|
|
|
$self->log(LOGERROR, "skip: unknown response from cvm for $user");
|
|
|
|
return (DECLINED, "unknown result code ($s)");
|
2005-06-10 14:11:26 +02:00
|
|
|
}
|