————use
strict;
use
Apache2::Connection ();
use
Apache2::RequestRec ();
use
Apache::Test;
=head1 NAME
Mail::SpamAssassin::Spamd::Apache2::AclRFC1413 - check spamd's client ident
=head1 SYNOPSIS
##### in httpd.conf:
# engine; module has been separated in Apache 2.1
LoadModule ident_module modules/mod_ident.so
IdentityCheck on
IdentityTimeout 4
# enable check
PerlLoadModule Mail::SpamAssassin::Spamd::Apache2::Config
SAident on
##### in PerlProcessConnectionHandler:
Mail::SpamAssassin::Spamd::Apache2::AclRFC1413::check_ident($c, "user")
or return Apache2::Const::FORBIDDEN;
# or like this:
my $remote_logname =
Mail::SpamAssassin::Spamd::Apache2::AclRFC1413::get_ident($c)
=head1 DESCRIPTION
Queries remote ident server using mod_ident.so, saves result in
C<$c-E<gt>notes()>.
Returns C<Apache2::Const::FORBIDDEN> on failure.
The C<SAident On> directive actually does this:
PerlPreConnectionHandler Mail::SpamAssassin::Spamd::Apache2::AclRFC1413
=head1 NOTE
Doing ident for non-localhost users is rather pointless. Unless you
know what you're doing, listen only on C<127.0.0.1> and/or C<::1>, if
you want to prevent users from lying about their identity. Or use SSL
with client certificates (refer to C<mod_ssl> documentation for details).
=head1 FUNCTIONS
=cut
sub
handler {
my
(
$c
) =
@_
;
# is there a point in doing ident for remote users?
#$c->remote_ip eq $c->local_ip
# or return Apache2::Const::FORBIDDEN;
my
$r
= Apache2::RequestRec->new(
$c
)
or
die
'Apache2::RequestRec->new($c) failed'
;
my
$remote_user
=
$r
->get_remote_logname;
unless
(
defined
$remote_user
&&
length
$remote_user
) {
warn
'rfc1413 check: failed to obtain info for '
. APACHE24 ?
$c
->client_addr->ip_get() :
$c
->remote_addr->ip_get() .
':'
. APACHE24 ?
$c
->client_addr->port() :
$c
->remote_addr->port() .
"\n"
;
return
Apache2::Const::FORBIDDEN;
}
my
$notes
=
$c
->notes
# APR::Table
or
die
'$c->notes failed'
;
$notes
->{remote_user} =
$remote_user
;
$c
->notes(
$notes
);
return
Apache2::Const::OK;
}
=head2 check_ident($c, $username)
Returns remote username (might be "0"), as returned by the ident server, if it
matches supplied $username; undef otherwise.
=cut
sub
check_ident {
my
(
$c
,
$user
) =
@_
;
my
$remote_user
=
$c
->notes->{remote_user};
die
"rfc1413 check: no query result for user=$user ip="
. APACHE24 ?
$c
->client_addr->ip_get() :
$c
->remote_addr->ip_get()
.
' port='
. APACHE24 ?
$c
->client_addr->port() :
$c
->remote_addr->port()
unless
defined
$remote_user
&&
length
$remote_user
;
return
$remote_user
if
$user
eq
$remote_user
;
warn
"ident mismatch for [$user] from "
. APACHE24 ?
$c
->client_addr->ip_get() :
$c
->remote_addr->ip_get() .
':'
. APACHE24 ?
$c
->client_addr->port() :
$c
->remote_addr->port()
.
"; remote identd returned [$remote_user]\n"
;
0;
}
=head2 get_ident($c)
Returns remote username (might be "0"), as returned by the ident server.
=cut
sub
get_ident {
my
(
$c
) =
@_
;
$c
->notes->{remote_user};
}
=head1 EXPORTS
Nothing.
=head1 BUGS
See E<lt>http://bugzilla.spamassassin.org/E<gt>
=head1 SEE ALSO
C<Mail::SpamAssassin::Spamd::Apache2::Config(3)>
=cut
1;
# vim: ts=8 sw=2 et