#!/usr/bin/perl # $Id: ud-fingerserv,v 1.6 1999/10/17 01:36:33 tausq Exp $ # (c) 1999 Randolph Chung. Licensed under the GPL. use lib '/home/randolph/projects/userdir-ldap/web'; use strict vars; #use Apache::Registry; use IO::Handle; use IO::Socket; use POSIX qw(:sys_wait_h); use Getopt::Std; use Util; use Net::LDAP qw(:all); # Global settings... my %config = &Util::ReadConfigFile; my %opts; getopts("iqhv", \%opts); my $use_inetd = $config{use_inetd} || $opts{i}; $| = 1; my %attrs = ( 'cn' => 'First name', 'mn' => 'Middle name', 'sn' => 'Last name', 'keyfingerprint' => 'Fingerprint', 'key' => 'Key block', 'ircnick' => 'IRC nickname' ); my @summarykeys = ('cn', 'mn', 'sn', 'ircnick', 'keyfingerprint', 'key'); $SIG{__DIE__} = \&DieHandler; $SIG{INT} = \&DieHandler; $SIG{CHLD} = \&Reaper; &help if (defined($opts{h})); #my $logfh = STDOUT; #TODO &log("Binding to LDAP server at $config{ldaphost}") if (defined($opts{v})); my $ldap = Net::LDAP->new($config{ldaphost}) || die $1; $ldap->bind; if (!$use_inetd) { &log("Binding to port 79") if (defined($opts{v})); my $server = IO::Socket::INET->new(Proto => 'tcp', LocalPort => 'finger(79)', Listen => SOMAXCONN, Reuse => 1); die "Cannot listen on finger port" unless $server; &log("[Server listening for connections]"); my ($pid, $client, $hostinfo); while ($client = $server->accept()) { &log("Forking to handle client request") if (defined($opts{v})); next if $pid = fork; # parent die "fork: $!" unless defined $pid; # child $client->autoflush(1); my $hostinfo = gethostbyaddr($client->peeraddr, AF_INET); &log(sprintf("[Connect from %s]", $hostinfo || $client->peerhost)); my $query = <$client>; &ProcessQuery($client, $query); $client->close; exit; } continue { $client->close; } } else { # inetd &log("inetd mode"); my $sockaddr = getpeername(STDIN); my ($port, $addr) = unpack_sockaddr_in(getpeername(STDIN)); &log(sprintf("[Connect from %s (%s)]", gethostbyaddr($addr, AF_INET), inet_ntoa($addr))); my $query = ; &ProcessQuery(\*STDOUT, $query); exit; } $ldap->unbind; sub DieHandler { $ldap->unbind if (defined($ldap)); exit 0; } sub Reaper { 1 until (-1 == waitpid(-1, WNOHANG)); $SIG{CHLD} = \&Reaper; } sub ProcessQuery { my $client = shift; my $query = shift; my ($uid, $fields, $mesg, $entries, $dn, $key, $pid, $data); $query =~ s/[^\/,0-9a-z]//gi; # be paranoid about input my ($uid, $fields) = split(/\//, $query, 2); &log("Looking up $uid at $config{basedn}, uid=$uid"); $mesg = $ldap->search(base => $config{basedn}, filter => "uid=$uid"); $mesg->code && die $mesg->error; $entries = $mesg->as_struct; foreach $dn (sort {$entries->{$a}->{sn}->[0] <=> $entries->{$b}->{sn}->[0]} keys(%$entries)) { $data = $entries->{$dn}; $data->{key} = []; foreach (@{$data->{keyfingerprint}}) { push (@{$data->{key}}, "\n".&Util::FetchKey($_)); } print $client "$dn\n"; if (!$fields) { foreach $key (@summarykeys) { foreach (@{$data->{$key}}) { print $client "$attrs{$key}: "; print $client "$_\n"; } } } else { # print "$fields\n"; foreach $key (split(/,/, $fields)) { foreach (@{$data->{$key}}) { print $client "$attrs{$key}: "; print $client "$_\n"; } } } } } sub help { print "fingerserv [-i | -q | -v | -h]\n"; print "-i = inetd mode; otherwise runs standalone\n"; print "-q = quiet mode; no output\n"; print "-v = verbose mode\n"; print "-h = this help message\n"; exit 0; } sub log { my $msg = shift; return if (defined($opts{q})); my $time = localtime; print STDERR "$time $msg\n"; }