-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathidentd.pl
executable file
·154 lines (129 loc) · 3.99 KB
/
identd.pl
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>;
}