#!/usr/bin/perl -w
#
# oraclevmail:
# tpop3d auth-perl script to authenticate users against an Oracle database.
#
# The relevant tpop3d.conf lines are--
#
# auth-perl-enable: yes
# auth-perl-start: do '/etc/tpop3d/tpop3d.pl'
# auth-perl-finish: auth_finish()
# auth-perl-pass: auth
#
# The database schema in use should be fairly self-evident, and is similar to
# that used by vmail-sql.
#
# (The #! line is for testing on the command line.)
#
# Copyright (c) 2001 Paul Makepeace (realprogrammers.com).
# All rights reserved.
#
# $Id: oraclevmail,v 1.2 2001/07/22 00:32:04 chris Exp $
#
use strict;
use Data::Dumper;
use DBI;
use Digest::MD5;
warn scalar(localtime), ": Perl started...\n";
my @DSN = qw(dbi:Oracle:vmail postmaster postmaster);
my $dbh = DBI->connect(@DSN)
or die "Unable to connect to DSN '@DSN': ", DBI->errstr, "\n";
# These keys are named based on the authentication method
# passwd into auth() below by auth_perl.c
my %sql = (
PASS => <<SQL,
SELECT d.path, p.password_hash, p.mbox_name, p.mbox_driver,
d.unix_user
FROM popbox p, domain d
WHERE p.local_part = ?
AND p.domain_name = ?
AND d.domain_name = p.domain_name
SQL
APOP => <<SQL,
SELECT d.path, p.password_hash, p.mbox_name, p.mbox_driver,
d.unix_user
FROM popbox p, domain d
WHERE p.local_part = ?
AND p.domain_name = ?
AND p.domain_name = d.domain_name
SQL
);
# Prepare the SQL statements above for execution later.
my %sth;
foreach my $auth_type (keys %sql) {
$sth{$auth_type} = $dbh->prepare($sql{$auth_type})
or die "Unable to prepare SQL '$sql{$auth_type}': ",
DBI->errstr, "\n";
}
### END of start-up code
# auth($)
# Called by tpop3d with a hashref containing keys:
# { method => (PASS, APOP), user => 'user@domain.example', pass =>
# 'letmein' }
# Returns hashref with { result => YES, ... } for a successful
# authentication
# match or { result => NO }
sub auth {
my $packet = shift;
my ($local_part, $domain) = $packet->{user} =~ /(.*?)\@(.*)/;
my $passwd = $packet->{pass};
warn Dumper([$packet]), "\n";
my $sth = $sth{$packet->{method}};
$sth ->execute($local_part, $domain)
or die "Couldn't execute $sql{$packet}: ", DBI->errstr,
"\n";
my ($path, $password_hash, $mbox_name, $mbox_driver, $unix_user) = $sth->fetchrow_array;
if (Digest::MD5::md5_hex($passwd) eq $password_hash) {
$packet = {
result => 'YES',
uid => (getpwnam($unix_user))[2],
gid => (getgrnam($unix_user))[2],
mailbox => "$path/$mbox_name",
mboxtype=> $mbox_driver,
domain => $domain,
}
} else {
$packet = { result => 'NO' };
};
warn Dumper([$packet]), "\n";
$packet;
}
# auth_finish():
# Clean up statement handles and then disconnect
sub auth_finish {
$_->finish for values %sth;
$dbh->disconnect();
}
syntax highlighted by Code2HTML, v. 0.9.1