1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
#!/usr/bin/perl -T
use strict;
use Socket;
# Basically you need to add a line like this to /etc/inetd.conf and
# run killall -HUP inetd.
# ident stream tcp nowait nobody /usr/local/sbin/identd.pl /tmp/cgiirc-=nobody
# The parameter on the end is the location of the socket files and
# the user which CGI:IRC is running as, for example
# /tmp/cgiirc-=www-data means that CGI:IRC has the socket_prefix
# set to /tmp/cgiirc- and is running as user www-data. Multiple
# directories can be specified.
# How to deal with unknown requests:
# nouser reply with NO-USER
# reply:text reply with USERID 'text'
# linuxproc use /proc/net/tcp on linux to do 'real' identd replies
# forward:port forward to a real identd
my $reply = "nouser";
# Use custom ident (currently HTTP USER set by CGI:IRC).
my $customident = 0;
# Default:
my %cgiircprefixes = ( '/tmp/cgiirc-' => $<);
%cgiircprefixes = () if @ARGV;
for(@ARGV) {
my($p, $u) = split /=/;
$u = getpwnam($u) || $<;
$cgiircprefixes{$p} = $u;
}
# Taken from midentd
my $in = '';
ret(0, 0, "ERROR : NO-USER") unless sysread STDIN, $in, 128;
my($local, $remote) = $in =~ /^\s*(\d+)\s*,\s*(\d+)/;
ret(0, 0, "ERROR : INVALID-PORT") unless defined $local && defined $remote;
$remote = 0 if $remote !~ /^([ \d])+$/;
$local = 0 if $local !~ /^([ \d])+$/;
if($remote<1 || $remote>65535 || $local<1 || $local>65535) {
ret($local, $remote, "ERROR : INVALID-PORT")
}
my $socket = find_socket($local, $remote);
if(defined $socket) {
my $user = encode_ip($socket);
if($customident && -f "$socket/ident") {
open(TMP, "<$socket/ident") or
ret($local, $remote, "USERID : UNIX : $user");
$user = <TMP>;
chomp($user);
$user ||= encode_ip($socket);
}
ret($local, $remote, "USERID : UNIX : $user");
} else {
if($reply eq 'nouser') {
ret($local, $remote, "ERROR : NO-USER");
} elsif($reply =~ /reply:\s*(.*)/) {
ret($local, $remote, "USERID : UNIX : $1");
} elsif($reply eq 'linuxproc') {
ret($local, $remote, linuxproc($local, $remote));
} elsif($reply =~ /forward:\s*(.*)/) {
print forward($1, $local, $remote);
exit;
}
ret($local, $remote, "ERROR : INVALID-PORT");
}
sub ret{
my($l, $r, $t) = @_;
print "$l , $r : $t\r\n";
exit;
}
sub find_socket {
my($l, $r) = @_;
foreach my $cgiircprefix (keys %cgiircprefixes) {
(my $dir, my $prefix) = $cgiircprefix =~ /^(.*\/)([^\/]+)$/;
opendir(TMPDIR, $dir) or return undef;
for(readdir TMPDIR) {
next unless /^\Q$prefix\E/;
next unless -d $dir . $_ && -x $dir . $_;
next unless $cgiircprefixes{$cgiircprefix} == (stat($dir . $_))[4];
local *TMP;
open(TMP, "<$dir$_/server") or next;
chomp(my $tmp = <TMP>);
next unless $tmp =~ /:$r$/;
chomp($tmp = <TMP>);
next unless $tmp =~ /:$l$/;
close TMP;
closedir TMPDIR;
return $dir . $_;
}
closedir TMPDIR;
}
return undef;
}
sub encode_ip {
my($socket) = @_;
open(TMP, "<$socket/ip") or return 0;
chomp(my $ip = <TMP>);
close TMP;
return join('', map(sprintf("%0.2x", $_), split(/\./, $ip)));
}
sub linuxproc {
my($l, $r) = @_;
open(PNT, "</proc/net/tcp") or return "ERROR : NO-USER";
$_=<PNT>;
while(<PNT>) {
s/^\s+//;
s/\s+/ /g;
my($sl,$local,$remote,$st,$queue,$tr,$retrnsmt,$uid,$timeout,$inode) = split(/\s/);
next unless decode_port($local) == $l && decode_port($remote) == $r;
return "USERID : UNIX : " . getusername($uid);
}
close(PNT);
return "ERROR : NO-USER";
}
sub decode_port{
return hex((split(/:/,shift,2))[1]);
}
sub getusername{
my $uid = shift;
if(my $u=(getpwuid($uid))[0]) {
return $u;
} else {
return $uid;
}
}
sub forward {
my($where, $l, $r) = @_;
eval("use IO::Socket;");
my $forward = IO::Socket::INET->new($where =~ /:/ ? $where : '127.0.0.1:' . $where);
return "$l , $r : ERROR : NO-USER\r\n" unless ref $forward;
print $forward "$l , $r\r\n";
return scalar <$forward>;
}
|