innd 2.3.1-2 with LDAP authentication - can read but cannot post
Kim Moir
Kim_Moir at oti.com
Fri Oct 18 19:39:42 UTC 2002
Hi
I'm trying to integrate innd 2.3.1-2 (Red Hat rpm) with ldap.
I based the nnrpd_auth.pl code on the example listed here
http://www.isc.org/ml-archives/inn-workers/2000/11/msg00196.html
I can authenticate through my browser and access the server to read the
newsgroups. However, I cannot post to the newsgroups. The browser reports
an "Error with the news server" however, there aren't any error messages
reflected in any of the logs in /var/log/news/
I've attempted to follow some of the suggestions in this article which
seems to describe the same problem. Unfortunately, I still can't post!
http://www.isc.org/ml-archives/inn-workers/2001/11/msg00145.html
Any suggestions you might have to allow posting to the newsgroups would be
much appreciated!
My nrrpd.access looks like this to force ldap authentication
*::::!*
My nnrpd_auth.pl looks like this.
#
# $Id: nnrpd_auth.pl.in,v 1.3 2000/09/18 22:38:49 kondou Exp $
#
# Sample authentication code for nnrpd hook.
# We do this via LDAP.
#
# This file is loaded when nnrpd starts up. If it defines a sub named
# `authenticate', then that function will be called during processing of a
# connect, auth request or disconnect. Attributes about the connection are
# passed to the program in the %attributes global variable. It should
return
# an array with 5 elements:
#
# 1) NNTP response code. Should be one of the codes from %connectcodes or
%authcodes
# 2) Reading Allowed. Should be a boolean value.
# 3) Posting Allowed. Should be a boolean value.
# 4) Wildmat expression that says what groups to provide access to.
# 5) Maximum bytes per second a client is permitted to use for retrieving
# articles
#
# All five of these are required. If there is a problem with them then
nnrpd
# will die and syslog the exact reason.
#
# Sample Auth program
#
use vars qw(@readerconfig);
use Mozilla::LDAP::Conn;
$defaultgroups = "*";
require "/usr/lib/innshellvars.pl";
my (%connectcodes) = ("read/post" => 200, "read" => 201, "authneeded" =>
480, "permdenied" => 502);
my (%authcodes) = ("allowed" => 281, "denied" => 502);
%server = (
"host" => "myservername.com",
"port" => "389",
"root" => "o=myOrg",
"cert" => "",
"scope" => "subtree"
);
sub loadnnrp {
my($file) = shift(@_);
my($block, $perm, $user, $pass, %tmp);
open(F, $file) || die "Could not open $file: $!\n";
while (<F>) {
my (%tmp);
chomp;
s/\#.*//g;
($block, $perm, $user, $pass, $tmp{groups}) = split(/:/);
if (!defined($tmp{groups})) {
undef %tmp;
next;
}
# Change the glob-type pattern to a regexp
if ( ! ($block =~ /(\d+\.\d+\.\d+\.\d+)\/(\d+)/))
{
# turn a glob type pattern into a regexp
# escape dots
$block =~ s/\./\./g;
# turn ? into .
$block =~ s/\?/./g;
# turn * into .*
$block =~ s/\*/.*/g;
}
$tmp{block} = $block;
$tmp{canread} = 1 if ($perm =~ /r/i);
$tmp{canpost} = 1 if ($perm =~ /p/i);
unshift(@readerconfig, \%tmp);
}
close(F);
}
# This is called by nnrpd when it first starts up.
sub auth_init {
# ancient crud. we oughta nuke this stuff eventually ;)
&loadnnrp($inn::newsetc . "/nnrp.access");
&loadnnrp($inn::newsetc . "/readers.conf");
# for standalone nnrpd, optimization would be to make it do a LDAP server
# connection here, to do it only _once_ and then reuse the open
connection
# for trying each user. (similarly, don't tear down connection after each
# user lookup, perhaps only upon nnrpd exit if it is posslbe to trap
that.)
}
# This is called when a user connects or authenticates
sub authenticate {
my $key;
foreach $key (keys %attributes) {
}
if ($attributes{type} eq "connect") {
my (@results) = checkhost();
return @results;
} elsif ($attributes{type} eq "authenticate") {
return checkuser();
} elsif ($attributes{type} eq "disconnect") {
}
return 502;
}
sub ldap_connect {
Mozilla::LDAP::Utils::userCredentials(\%server);
$conn = new Mozilla::LDAP::Conn(\%server);
return $conn;
}
sub ldap_disconnect {
# Close the connection
$conn->close if $conn;
}
sub checkuser {
my $user = $attributes{'username'};
my $pass = $attributes{'password'};
# filling in some blanks
$server{bind} = "cn=$user, o=myOrg";
$server{pswd} = "$pass";
# try to connect to the LDAP server as the user, with creds
ldap_connect();
# if either the user's password didn't match or the LDAP server is
# unavailable, then we can't proceed any further.
if (! $conn)
{
# error...bailing out. no way to be descriptive to user abt error,
alas
# I'd suggest adding some code to determine what kind of error, and
# possibly page an admin if server is unreachable or unavailable,
# as opposed to a simply incorrect password case. this kind of
thing
# is highly site-specific.
# so.
# we tell user that their request was denied, and refuse to serve
'em
# "sorry, pal."
# print "denied";
return ($authcodes{'denied'}, undef, undef, undef, undef);
}
# this is only a quick proof of concept example; trivial to extend your
# LDAP schema to contain attribs to store this info, and to check it
# for now, we'll just hardcode it to 'y' to allow posting if user auth'd
ok
$news_post = "y";
$news_post = "1";
# same deal as above, regarding default subscription/groups
if (!defined($subscription)) {
$subscription = $defaultgroups;
}
# be friendly to the LDAP server, and close the connection
ldap_disconnect();
# happy is he who pleases the user with a 'yer good, go for it!'
return ($authcodes{'allowed'}, 1, $news_post , $subscription, 1000000);
}
sub permtocode {
my ($read, $post) = @_;
return $connectcodes{'read/post'} if ($post);
return $connectcodes{'read'} if ($read);
return $connectcodes{'authneeded'};
}
sub checkhost {
my ($key, $block, $mask, $ip);
foreach $key (@readerconfig) {
# Process CIDR style entries first
my ($read, $post) = ($key->{canread}, $key->{canpost});
if ($key->{block} =~ /(\d+\.\d+\.\d+\.\d+)\/(\d+)/) {
$block = unpack('N', pack('C4', split(/\./, $1)));
$mask = (0xffffffff << (32 - $2)) & 0xffffffff;
$block = $block & $mask;
$ip = unpack('N', pack('C4', split(/\./, $attributes{ipaddress})));
if (($ip & $mask) == $block) {
return (permtocode($read, $post) , $read, $post, $key->{groups},
undef);
}
}
if ($attributes{ipaddress} =~ /$key->{block}/) {
return (permtocode($read, $post), $read, $post, $key->{groups},
undef);
}
if ($attributes{hostname} =~ /$key->{block}/) {
return (permtocode($read, $post), $read, $post, $key->{groups},
undef);
}
}
return ($connectcodes{'permdenied'}, undef, undef, undef, undef);
}
More information about the inn-workers
mailing list