001 #!/usr/bin/perl 002 use English; 003 use Socket; 004 sub bynum {$a <=> $b;} 005 sub childhnd { 006 $childs--; 007 wait(); 008 return; 009 } 010 sub timeout { 011 exit(0); 012 } 013 sub dprint { 014 my($line)=@_; 015 unless ($SILENT) 016 { 017 print "$line"; 018 } 019 } 020 if ($ARGV[0] =~ /^silent$/i) {$SILENT=1;} 021 $|=1; 022 &dprint("\n***** Random Ident Server 0.9.0b *****\n"); 023 opendir(ISPELL,"/usr/lib/ispell")|| die "No /usr/lib/ispell dir found\n"; 024 @files=readdir(ISPELL); 025 closedir(ISPELL); 026 $index=0; 027 while (($index <= $#files)&&(!$usefile)) 028 { 029 $file=$files[$index]; 030 if ($file =~ /\.hash$/) 031 { 032 $usefile=$file; 033 } 034 $index++; 035 } 036 unless ($usefile) {print "No hash file found in /usr/lib/ispell\n";exit;} 037 &dprint("* Using file /usr/lib/ispell/$usefile\n"); 038 &dprint("* Counting usable words\n"); 039 open(STR1,"/usr/bin/strings /usr/lib/ispell/$usefile|")||die "Cant start strings"; 040 while() 041 { 042 chomp(); 043 chomp(); 044 $line=lc($_); 045 $len=length($line); 046 if (($line =~ /^[a-z]+$/)&&($len > 4) && ($len < 13)) 047 { 048 $maxword++; 049 if (($maxword % 40) == 0) { &dprint("\r working: | ($maxword)")}; 050 if (($maxword % 40) == 10) { &dprint("\r working: / ($maxword)")}; 051 if (($maxword % 40) == 20) { &dprint("\r working: - ($maxword)")}; 052 if (($maxword % 40) == 30) { &dprint("\r working: \\ ($maxword)")}; 053 } 054 } 055 &dprint("\r \r"); 056 close(STR1); 057 $count=0; 058 $maxcount=1024+int(rand(2048)); 059 &dprint("* Generating random selection of $maxcount from $maxword\n"); 060 $setsize=$maxword; 061 @fetched=(); 062 $fnum=0; 063 while($fnum < $maxcount) 064 { 065 $rnum=int(rand($setsize)); 066 foreach $old (@fetched) 067 { 068 if ($old <= $rnum) {$rnum++;} 069 } 070 $continue=1; 071 while($continue) 072 { 073 $continue=0; 074 foreach $old (@fetched) 075 { 076 if ($old == $rnum) 077 { 078 $rnum++; 079 $continue=1; 080 } 081 } 082 } 083 $fetched[$fnum]=$rnum; 084 $fnum++; 085 $pnum=int(($fnum*$fnum*1000)/($maxcount*$maxcount))/10; 086 if (($fnum %8)==0) {&dprint("\r working: | ($pnum \%)");} 087 if (($fnum %8)==2) {&dprint("\r working: / ($pnum \%)");} 088 if (($fnum %8)==4) {&dprint("\r working: - ($pnum \%)");} 089 if (($fnum %8)==6) {&dprint("\r working: \\ ($pnum \%)");} 090 } 091 &dprint("\r \r"); 092 &dprint("* Generating insertion table\n"); 093 foreach $index (0 .. $#fetched) 094 { 095 $inserttable{$fetched[$index]}=$index; 096 } 097 open(STR1,"/usr/bin/strings /usr/lib/ispell/$usefile|")||die "Cant start strings"; 098 &dprint("* Aquiring names\n"); 099 $count=0; 100 while() 101 { 102 chomp(); 103 chomp(); 104 $line=lc($_); 105 $len=length($line); 106 if (($line =~ /^[a-z]+$/)&&($len > 4) && ($len < 13)) 107 { 108 if (defined($inserttable{$count})) 109 { 110 $words[$inserttable{$count}] =$line; 111 } 112 $count++; 113 $countp=int(1000*$count/$maxword)/10; 114 if (($count % 40) == 0) { &dprint("\r working: | ($countp \%)")}; 115 if (($count % 40) == 10) { &dprint("\r working: / ($countp \%)")}; 116 if (($count % 40) == 20) { &dprint("\r working: - ($countp \%)")}; 117 if (($count % 40) == 30) { &dprint("\r working: \\ ($countp \%)")}; 118 } 119 } 120 &dprint("\r \r"); 121 &dprint("* $maxcount words fetched\n"); 122 &dprint(" (local ports belonging to each uniq modulus of $maxcount get\n"); 123 &dprint(" a dictionary word assigned to them)\n"); 124 125 if ($< != 0) 126 { 127 print "Need to be root to bind to the ident port\n"; 128 exit; 129 } 130 ($pnam,$dummy,$myuid,$mygid)=getpwnam("nobody"); 131 unless (($myuid) && ($mygid)) 132 { 133 print "No user nobody defined\n"; 134 exit; 135 } 136 if (open(PID,"/tmp/rident.pid")) 137 { 138 &dprint("* PID file found\n"); 139 $opid=; 140 chomp($opid); 141 close(PID); 142 unless ($opid =~ /^\d+$/) 143 { 144 print "HEY, SOMEONE FUCKED UP MY PIDFILE /tmp/rident.pid\n"; 145 exit; 146 } 147 &dprint("* Checking for process with pid $opid\n"); 148 open(PS,"/bin/ps -p $opid|"); 149 $killit=0; 150 while () 151 { 152 if (/ridentd.pl/) 153 { 154 $killit=1; 155 } 156 } 157 if ($killit) 158 { 159 &dprint("* Killing old instance\n"); 160 kill(9,$opid); 161 sleep(1); 162 } 163 else 164 { 165 &dprint("* pid file apears to be old\n"); 166 } 167 } 168 &dprint("* Binding to port 113\n"); 169 $port=113; 170 $proto=getprotobyname('tcp'); 171 socket(Server,PF_INET,SOCK_STREAM,$proto)|| die "socket $!"; 172 setsockopt(Server,SOL_SOCKET,SO_REUSEADDR,pack("l",1))|| die "setsockopt $!"; 173 bind(Server,sockaddr_in($port,INADDR_ANY))|| die "bind: $!"; 174 listen(Server,SOMAXCON)||die "listen: $!"; 175 &dprint("* Forking to background\n"); 176 $pid=fork(); 177 unless (defined($pid)) { 178 print "ERR: Forking error\n"; 179 exit; 180 } 181 if ($pid) 182 { 183 open(PID,">/tmp/rident.pid"); 184 print PID "$pid\n"; 185 close(PID); 186 exit; 187 } 188 &dprint("* BG Process active\n"); 189 &dprint("* BG Process seting uid/gid to nobody $myuid/$mygid\n"); 190 unless ($)=$mygid) {print "Unable to set group ID to $mygid\n";exit;} 191 unless ($>=$myuid) {print "Unable to set user ID to $myuid\n";exit;} 192 &dprint("* Looking if we can do socketpair lookups : "); 193 if (-r "/proc/net/tcp") { 194 &dprint("Yep: LINUX\n"); 195 $LOOKUP="LINUX"; 196 } 197 else { 198 &dprint("NO !!!\n"); 199 $LOOKUP=0; 200 } 201 $childs=0; 202 $SIG{'CHLD'}='childhnd'; 203 while($paddr = accept(Client,Server)) 204 { 205 ($remoteport,$remoteip)=sockaddr_in($paddr); 206 $remoteip=unpack("L",$remoteip); 207 #Limmited forking and extra sleeping, better for the service than the system to be dossed 208 if ($childs < 10) 209 { 210 $pid=fork(); 211 unless (defined($pid)) { 212 print "ERR: Forking error\n"; 213 exit; 214 } 215 if ($pid==0) 216 { 217 select Client;$|=1;select(STDOUT); 218 $SIG{"ALARM"}='timeout'; 219 alarm(10); 220 $firstline=; 221 if ($firstline =~ /(\d+)\s*,\s*(\d*)/) 222 { 223 $port=$1; 224 $port2=$2; 225 $found=1; 226 #If there is no portablility for the lookup just skip it 227 if ($LOOKUP eq "LINUX") 228 { 229 $found=0; 230 231 $rip=sprintf("%lX",$remoteip); 232 while (length($rip) < 8) {$rip = "0$rip";} 233 $rprt=sprintf("%X",$port2); 234 while (length($rprt) < 4) {$rprt = "0$rprt";} 235 $lprt=sprintf("%X",$port); 236 while (length($lprt) < 4) {$lprt = "0$lprt";} 237 open(TCPFIL,"/proc/net/tcp"); 238 while() 239 { 240 if (/:$lprt\s+${rip}:$rprt\s+/) 241 { 242 $found=1; 243 } 244 } 245 } 246 if ($found) 247 { 248 $word=$words[$port % $maxcount]; 249 print Client "${port},${port2}:USERID:OTHER:$word\n"; 250 } 251 else 252 { 253 print Client "${port},${port2}:ERROR:NO-USER\n"; 254 } 255 } 256 close(Client); 257 sleep(2); 258 exit; 259 } 260 else 261 { 262 $childs++; 263 } 264 } 265 else 266 { 267 print Client "0,0:ERROR:UNKNOWN-ERROR\n"; 268 close(Client); 269 } 270 } 271 print "* BG Process had a unforseen problem (rident)\n";