import java.net.*;
import java.io.*;

public class CodeRedLogger
{
   public static void main(String[] args)
   {
      try
      {
         if (args.length == 0)
         {
            CodeRedLogger logger = new CodeRedLogger();
            logger.doServer();
         }
         else
         {
            int inf = testInfected(InetAddress.getByName(args[0]));
            printResults(inf, args[0]);
         }
      }
      catch (Throwable t)
      {
         t.printStackTrace();
      }
   }

   public void doServer()
      throws IOException
   {
      ServerSocket ss = new ServerSocket(80);
      while (true)
      {
         try
         {
            Socket client = ss.accept();
            System.out.println("\t...connect from: " + client.getInetAddress());
            new ClientThread(client).run();
         }
         catch (IOException e)
         {
            System.err.println("\t...exception: " + e.toString());
         }
      }
   }

   class ClientThread extends Thread
   {
      public ClientThread(Socket client) { m_client = client; }

      public void run() {
         try
         {
            m_client.setSoTimeout(60000); // read timeout of 1 minute
            BufferedReader rdr = new BufferedReader(new InputStreamReader(
               m_client.getInputStream(), "UTF-8"));

            String attack = rdr.readLine();
            if (attack == null)
               return;

            System.out.println("\t..." + m_client.getInetAddress() + ": " + attack);

            if (!attack.toUpperCase().startsWith("GET /DEFAULT.IDA?"))
            {
               return;
            }

            rdr.close();
            m_client.close();

            int inf = testInfected(m_client.getInetAddress());
            printResults(inf, m_client.getInetAddress().toString());
         }
         catch (Throwable t)
         {
            System.out.println("\t..." + m_client.getInetAddress() + ": " + t.toString());
         }
         finally
         {
            System.out.println("\t..." + m_client.getInetAddress() + " finished");
            try  { m_client.close(); } catch (IOException e) { /* ignore */ }
         }
      }

      private Socket m_client;
   }

   private static void printResults(int inf, String str)
   {
      if (inf == 1)
         System.out.println(str + ": VULNERABLE");
      else if (inf == 0)
         System.out.println(str + ": PATCHED");
      else if (inf == -1)
         System.out.println(str + ": COULD NOT CONNECT");
      else if (inf == -2)
         System.out.println(str + ": UNKNOWN");
      else
         System.out.println(str + ": ???");
   }

   private static int testInfected(InetAddress addr)
      throws IOException
   {
      // try to connect back to the client on port 80, see if they're vulnerable
      System.out.println("\t...connecting to: " + addr);
      Socket reverse;
      try
      {
         reverse = new Socket(addr, 80);
      }
      catch (Throwable t)
      {
         return -1; // couldn't connect
      }

      try
      {
         reverse.setSoTimeout(60000);
         Writer w = new OutputStreamWriter(reverse.getOutputStream(), "UTF-8");
         w.write("GET /NULL.ida?");
         w.write(ms_reverseRequest);
         w.write("=x HTTP/1.0\r\n\r\n");
         w.flush();
         System.out.println("\t...sent request to: " + addr);

         BufferedReader revRdr = new BufferedReader(new InputStreamReader(
            reverse.getInputStream(), "UTF-8"));

         String line = revRdr.readLine();
         for (int i = 0; i < 30 && line != null; i++)
         {
            // System.out.println(line);
            line = revRdr.readLine();
            if (line.indexOf("The IDQ file NULL.ida could not be found.") >= 0)
               return 1; // unpatched
            else if (line.indexOf("Error 0x80040e14 caught while processing query") >= 0)
               return 0; // patched
         }

         return -2; // who knows
      }
      finally
      {
         reverse.close();
      }
   }

   private static String ms_reverseRequest;
   static
   {
      StringBuffer buff = new StringBuffer(200);
      for (int i = 0; i < 200; i++)
      {
         buff.append('x');
      }

      ms_reverseRequest = buff.toString();
   }
}