File: identd.pl

package info (click to toggle)
cgiirc 0.5.4-6sarge1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 916 kB
  • ctags: 424
  • sloc: perl: 8,904; sh: 821; ansic: 132; makefile: 54
file content (139 lines) | stat: -rwxr-xr-x 3,662 bytes parent folder | download
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
#!/usr/bin/perl -T
# Basically you need to add a line like this to /etc/inetd.conf and 
# killall -HUP inetd
# ident	stream	tcp	nowait	nobody	/usr/local/sbin/identd.pl
# see the advanced section of the docs for more details about this.
use strict;
use Socket;

# Prefix/tmp directory that CGI:IRC uses
my $cgiircprefix="/tmp/cgiirc-";

# 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 relies 
# forward:port forward to a real identd
my $reply = "nouser";

# Use custom ident (currently HTTP USER set by CGI:IRC).
my $customident = 0;

# 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 $randomvalue = find_socket($local, $remote);

if(defined $randomvalue) {
   my $user = encode_ip($randomvalue);
   if($customident && -f "$cgiircprefix$randomvalue/ident") {
      open(TMP, "<$cgiircprefix$randomvalue/ident") or
         ret($local, $remote, "USERID : UNIX : $user");
      $user = <TMP>;
      chomp($user);
      $user ||= encode_ip($randomvalue);
   }
	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) = @_;
   (my $dir, my $prefix) = $cgiircprefix =~ /^(.*\/)([^\/]+)$/;
   opendir(TMPDIR, $dir) or return undef;
   for(readdir TMPDIR) {
      next unless /^\Q$prefix\E/;
      next unless -o $dir . $_ && -d $dir . $_;
      
      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;

      $_ = $dir . $_;
      s/^\Q$cgiircprefix\E//;
      return $_;
   }
   closedir TMPDIR;
   return undef;
}

sub encode_ip {
   my($rand) = @_;
   open(TMP, "<$cgiircprefix$rand/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($_=(getpwuid($uid))[0]) {
      return $_;
   } 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>;
}