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