package Apache::AuthLDAP;
use strict;
use Apache::Constants ':common';
use Net::LDAPapi;
$Apache::AuthLDAP::VERSION = '0.21';
sub handler
{
my $r = shift;
my ($res, $sent_pwd) = $r->get_basic_auth_pw;
return $res if $res;
my $name = $r->connection->user;
my $basedn = $r->dir_config('BaseDN') || "";
my $ldapserver = $r->dir_config('LDAPServer') || "localhost";
my $ldapport = $r->dir_config('LDAPPort') || 389;
my $uidattr = $r->dir_config('UIDAttr') || "uid";
if ($sent_pwd eq "")
{
$r->note_basic_auth_failure;
$r->log_reason("user $name: no password supplied",$r->uri);
return AUTH_REQUIRED;
}
my $ld = new Net::LDAPapi($ldapserver,$ldapport);
if ($ld <= 0)
{
$r->note_basic_auth_failure;
$r->log_reason("user $name: LDAP Connection Failed",$r->uri);
return AUTH_REQUIRED;
}
if ($ld->bind_s != LDAP_SUCCESS)
{
$r->note_basic_auth_failure;
$r->log_reason("user $name: LDAP Initial Bind Failed",$r->uri);
return AUTH_REQUIRED;
}
my $filter = "$uidattr=$name";
my $status = $ld->search_s($basedn,LDAP_SCOPE_SUBTREE,$filter,["c"],1);
if ($status != LDAP_SUCCESS)
{
$r->note_basic_auth_failure;
$r->log_reason("user $name: ldap search failed",$r->uri);
$ld->unbind;
return AUTH_REQUIRED;
}
if ($ld->count_entries != 1)
{
$r->note_basic_auth_failure;
$r->log_reason("user $name: username not found",$r->uri);
$ld->unbind;
return AUTH_REQUIRED;
}
$ld->first_entry;
my $dn = $ld->get_dn;
$status = $ld->bind_s($dn,$sent_pwd);
if ($status == LDAP_SUCCESS)
{
$r->push_handlers(PerlAuthzHandler => \&authz);
$ld->unbind;
return OK;
}
$ld->unbind;
$r->note_basic_auth_failure;
$r->log_reason("user $name: password mismatch", $r->uri);
return AUTH_REQUIRED;
}
sub authz
{
my $r = shift;
my $requires = $r->requires;
return OK unless $requires;
my $name = $r->connection->user;
my $basedn = $r->dir_config('BaseDN') || "";
my $ldapserver = $r->dir_config('LDAPServer') || "localhost";
my $ldapport = $r->dir_config('LDAPPort') || 389;
my $uidattr = $r->dir_config('UIDAttr') || "uid";
for my $req (@$requires)
{
my ($require, @rest) = split /\s+/, $req->{requirement};
if ($require eq "user")
{
return OK if grep $name eq $_, @rest;
} elsif ($require eq "valid-user")
{
return OK;
} else {
my $ld = new Net::LDAPapi($ldapserver,$ldapport);
$ld->bind_s;
my $filter = "(&(|($require=" . join(")($require=",@rest) .
"))($uidattr=$name))";
my $status = $ld->search_s($basedn,LDAP_SCOPE_SUBTREE,$filter,["c"],1);
if ($status != LDAP_SUCCESS)
{
$r->note_basic_auth_failure;
$r->log_reason("LDAP Lookup Failed",$r->uri);
$ld->unbind;
return AUTH_REQUIRED;
}
if ($ld->count_entries == 1)
{
$ld->unbind;
return OK;
}
$ld->unbind;
}
}
$r->note_basic_auth_failure;
$r->log_reason("user $name: not authorized", $r->uri);
return AUTH_REQUIRED;
}
1;
__END__
=head1 NAME
Apache::AuthLDAP - mod_perl LDAP Access Control and Authentication Module
=head1 SYNOPSIS
# Authentication Realm and Type (only Basic supported)
AuthName "Foo Bar Authentication"
AuthType Basic
# Any of the following variables can be set. Defaults are listed
# to the right.
PerlSetVar BaseDN o=Foo,c=Bar # Default: Empty String ("")
PerlSetVar LDAPServer ldap.foo.com # Default: localhost
PerlSetVar LDAPPort 389 # Default: 389 (standard LDAP port)
PerlSetVar UIDAttr uid # Default: uid
PerlAuthenHandler Apache::AuthLDAP
# Require lines can be any of the following:
#
require valid-user # Any Valid LDAP User
require user uid1 uid2 uid2 # Allow Any User in List
require ldapattrib val1 val2 # Allow Any User w/ Entry Containing
# Matching Attribute and Value
These directives can also be used in a .htaccess file.
= head1 DESCRIPTION
This perl module is designed to work with mod_perl and my Net::LDAPapi
module (http://www.wwa.com/~donley/).
This version of the module does not support access control based on
LDAP groups, but the next release will. It does support a handy access
control based on attribute and value pairs. This can be used to restrict
access to people whose LDAP entries contain a given department number, etc...
I welcome feedback on this module and the Net::LDAPapi module.
=head1 AUTHOR
Clayton Donley
=head1 COPYRIGHT
Copyright (c) 1998 Clayton Donley
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut