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.2b *****\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 (-l "/tmp/rident.pid") { 137 print "PANIC: It apears someone has tempored with the pid file /tmp/rident.pid\n"; 138 exit; 139 } 140 if (open(PID,"/tmp/rident.pid")) 141 { 142 &dprint("* PID file found\n"); 143 $opid=; 144 chomp($opid); 145 close(PID); 146 unless ($opid =~ /^\d+$/) 147 { 148 print "PANIC: It apears someone has tempored with the pid file /tmp/rident.pid\n"; 149 exit; 150 } 151 &dprint("* Checking for process with pid $opid\n"); 152 open(PS,"/bin/ps -p $opid|"); 153 $killit=0; 154 while () 155 { 156 if (/ridentd.pl/) 157 { 158 $killit=1; 159 } 160 } 161 if ($killit) 162 { 163 &dprint("* Killing old instance\n"); 164 kill(9,$opid); 165 sleep(1); 166 } 167 else 168 { 169 &dprint("* pid file apears to be old\n"); 170 } 171 } 172 &dprint("* Binding to port 113\n"); 173 $port=113; 174 $proto=getprotobyname('tcp'); 175 socket(Server,PF_INET,SOCK_STREAM,$proto)|| die "socket $!"; 176 setsockopt(Server,SOL_SOCKET,SO_REUSEADDR,pack("l",1))|| die "setsockopt $!"; 177 bind(Server,sockaddr_in($port,INADDR_ANY))|| die "bind: $!"; 178 listen(Server,SOMAXCON)||die "listen: $!"; 179 &dprint("* Forking to background\n"); 180 $pid=fork(); 181 unless (defined($pid)) { 182 print "ERR: Forking error\n"; 183 exit; 184 } 185 if ($pid) 186 { 187 if (-e "/tmp/rident.pid") { 188 unlink("/tmp/rident.pid"); #fix to bug reported by Martin 189 # on Mar 24 2004 to FullDisclosure. Tnx Martin, but it would help 190 # a lot if next time you find such a serious bug, you could also 191 # report it the author/vendor. 192 } 193 open(PID,">/tmp/rident.pid"); 194 print PID "$pid\n"; 195 close(PID); 196 exit; 197 } 198 &dprint("* BG Process active\n"); 199 &dprint("* BG Process seting uid/gid to nobody $myuid/$mygid\n"); 200 unless ($)=$mygid) {print "Unable to set group ID to $mygid\n";exit;} 201 unless ($>=$myuid) {print "Unable to set user ID to $myuid\n";exit;} 202 &dprint("* Looking if we can do socketpair lookups : "); 203 if (-r "/proc/net/tcp") { 204 &dprint("Yep: LINUX\n"); 205 $LOOKUP="LINUX"; 206 } 207 else { 208 &dprint("NO !!!\n"); 209 $LOOKUP=0; 210 } 211 $childs=0; 212 $SIG{'CHLD'}='childhnd'; 213 while($paddr = accept(Client,Server)) 214 { 215 ($remoteport,$remoteip)=sockaddr_in($paddr); 216 $remoteip=unpack("L",$remoteip); 217 #Limmited forking and extra sleeping, better for the service than the system to be dossed 218 if ($childs < 10) 219 { 220 $pid=fork(); 221 unless (defined($pid)) { 222 print "ERR: Forking error\n"; 223 exit; 224 } 225 if ($pid==0) 226 { 227 select Client;$|=1;select(STDOUT); 228 $SIG{"ALARM"}='timeout'; 229 alarm(10); 230 $firstline=; 231 if ($firstline =~ /(\d+)\s*,\s*(\d*)/) 232 { 233 $port=$1; 234 $port2=$2; 235 $found=1; 236 #If there is no portablility for the lookup just skip it 237 if ($LOOKUP eq "LINUX") 238 { 239 $found=0; 240 $rip=sprintf("%lX",$remoteip); 241 while (length($rip) < 8) {$rip = "0$rip";} 242 $rprt=sprintf("%X",$port2); 243 while (length($rprt) < 4) {$rprt = "0$rprt";} 244 $lprt=sprintf("%X",$port); 245 while (length($lprt) < 4) {$lprt = "0$lprt";} 246 open(TCPFIL,"/proc/net/tcp"); 247 while() 248 { 249 if (/:$lprt\s+${rip}:$rprt\s+/) 250 { 251 $found=1; 252 } 253 } 254 } 255 if ($found) 256 { 257 $word=$words[$port % $maxcount]; 258 print Client "${port},${port2}:USERID:OTHER:$word\n"; 259 } 260 else 261 { 262 print Client "${port},${port2}:ERROR:NO-USER\n"; 263 } 264 } 265 close(Client); 266 sleep(2); 267 exit; 268 } 269 else 270 { 271 $childs++; 272 } 273 } 274 else 275 { 276 print Client "0,0:ERROR:UNKNOWN-ERROR\n"; 277 close(Client); 278 } 279 } 280 print "* BG Process had a unforseen problem (rident)\n";