pam-modules/examples/ldappubkey
2014-05-21 12:22:05 +03:00

176 lines
4.2 KiB
Perl
Executable file

#! /usr/bin/perl
# This file is part of pam-modules.
# Copyright (C) 2014 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
use Net::LDAP;
=head1 NAME
ldappubkey - get user public ssh keys from the LDAP database
=head1 SYNOPSIS
B<ldappubkey> I<LOGIN>
=head1 DESCRIPTION
Produces on the standard output public ssh keys for the user I<LOGIN>, each
on a separate line. The program is designed for use with B<sshd>(8) version
6.2p1 or higher. Public keys are obtained from a LDAP database. The
configuration is looked up in the following files: B</etc/ldap.conf>,
B</etc/ldap/ldap.conf> and B</etc/openldap/ldap.conf>. These files are
tried in this order and the first one of them that exists is read.
The following configuration statements are used (all keywords are
case-insensitive):
=over 4
=item B<uri> B<ldap[si]://>[I<name>[:I<port>]] ...>
Specifies the URI of the LDAP server (or servers) to connect to. The default
is B<ldap://127.0.0.1>.
=item B<base> I<DN>
Specifies the default base DN to use when performing ldap operations.
The base must be specified as a Distinguished Name in LDAP format.
=item B<binddn> I<DN>
Specifies the default bind DN to use.
=item B<bindpw> I<PASS>
Specifies the password to use with B<binddn>.
=item B<uid> I<ATTR>
Name of the attribute to use instead of B<uid>. The LDAP record is searched
using the filter B<(&(objectClass=posixAccount)(I<ATTR>=I<LOGIN>))>.
=item B<publickeyattribute> I<ATTR>
Name of the attribute which holds the public key. Default is B<grayPublicKey>.
=back
=head1 OPTIONS
=over 4
=item B<-h>
Show program usage.
=item B<--help>
Show detailed help page.
=back
=head1 SEE ALSO
B<sshd>(8), B<sshd_config>(5), B<ldap.conf>(5).
=head1 BUGS
LDAP filter string is hardcoded.
=head1 AUTHOR
Sergey Poznyakoff <gray@gnu.org>
=cut
# ###################################
# Configuration file handling
# ###################################
my %config = ('uri' => 'ldap://127.0.0.1', 'uid' => 'uid',
'publickeyattribute' => 'grayPublicKey');
sub read_config_file($) {
my $config_file = shift;
my $file;
my $line = 0;
open($file, "<", $config_file) or die("cannot open $config_file: $!");
while (<$file>) {
++$line;
chomp;
s/^\s+//;
s/\s+$//;
s/#.*//;
next if ($_ eq "");
my @kwp = split(/\s*\s+\s*/, $_, 2);
$config{lc($kwp[0])} = $kwp[1];
}
close($file);
}
sub assert {
my $mesg = shift;
my $action = shift;
die("An error occurred $action: ".$mesg->error) if ($mesg->code);
return $mesg;
}
# ###################################
# MAIN
# ###################################
die "bad number of arguments; try perldoc $0 for more info"
unless ($#ARGV == 0);
## Read configuration
foreach my $file ("/etc/ldap.conf", "/etc/ldap/ldap.conf",
"/etc/openldap/ldap.conf") {
if (-e $file) {
read_config_file($file);
last;
}
}
my $ldap = Net::LDAP->new($config{'uri'})
or die("Unable to connect to LDAP server $config{'uri'}: $!");
my @bindargs = ();
if (defined($config{'binddn'})) {
push(@bindargs, $config{'binddn'});
push(@bindargs, password => $config{'bindpw'})
if defined($config{'bindpw'});
}
assert($ldap->bind(@bindargs), "binding to the server");
my $attr = $config{'publickeyattribute'};
my $filter = "(&(objectClass=posixAccount)($config{'uid'}=$ARGV[0]))";
my $res = assert($ldap->search(base => $config{'base'},
filter => $filter,
attr => [ $attr ] ),
"searching for $filter in $config{'base'}");
foreach my $entry ($res->entry(0)) {
my $keyref = $entry->get_value($attr, asref => 1);
for (@{$keyref}) {
print "$_\n";
}
}
# END