<?php
/*  
 * Analysis Console for Intrusion Databases (ACID)
 *
 * Author: Roman Danyliw <rdd@cert.org>, <roman@danyliw.com>
 *         MSSQL support by Charles Hand <charlieh@silicondefense.com>
 *
 * Copyright (C) 2000, 2001 Carnegie Mellon University
 * Portions Copyright (C) 2001 Iowa National Guard
 * (see the file 'acid_main.php' for license details)
 *
 * Purpose: support routines for processing criteria 
 *
 */

include_once("acid_signature.inc");

function PrintCriteriaState()
{
  GLOBAL $time, $time_cnt, 
         $sig, $sig_type, 
         $sensor, 
         $ag,
         $ip_addr, $ip_addrs, $ip_addr_cnt, 
         $ip_field, $ip_field_cnt,
         $tcp_port, $tcp_port_cnt, 
         $tcp_flags, 
         $tcp_field, $tcp_field_cnt,
         $udp_port, $udp_port_cnt, 
         $udp_field, $udp_field_cnt,
         $icmp_field, $icmp_field_cnt,
         $data, $data_cnt, 
         $layer4, $MAX_ROWS,
         $new, $submit, $sort_order, $num_result_rows,
         $current_view, $caller, $action, $action_arg,
         $sort_order, $debug_mode;

  if ( $debug_mode >= 2 )
  {
  echo "<PRE>";
  echo "<B>sensor:</B> $sensor<BR>\n
        <B>AG:</B> $ag<BR>\n
        <B>signature</B>";
  print_r($sig);
  echo "<BR><B>time ($time_cnt):</B><BR>";
  print_r($time);
  echo "<BR><B>IP addresses ($ip_addr_cnt):</B><BR>";
  print_r($ip_addr);
  echo "<BR>===================================================<BR>";
  print_r($ip_addrs);
  echo "<BR><B>IP fields ($ip_field_cnt):</B><BR>";
  print_r($ip_field);
  echo "<BR><B>TCP ports ($tcp_port_cnt):</B><BR>";
  print_r($tcp_port);
  echo "<BR><B>TCP flags:</B><BR>";
  print_r($tcp_flags);
  echo "<BR><B>TCP field ($tcp_field_cnt):</B><BR>";
  print_r($tcp_field);
  echo "<BR><B>UDP ports ($udp_port_cnt):</B><BR>";
  print_r($udp_port);
  echo "<BR><B>UDP field ($udp_field_cnt):</B><BR>";
  print_r($udp_field);
  echo "<BR><B>ICMP field ($icmp_field_cnt):</B><BR>";
  print_r($icmp_field);
  echo "<BR><B>Data ($data_cnt):</B><BR>";
  print_r($data);
  echo "</PRE>";
  }

  if ( $debug_mode >= 1 )
  {
  echo "<PRE>
        <B>new:</B> '$new'   
        <B>submit:</B> '$submit'
        <B>sort_order:</B> '$sort_order'
        <B>num_result_rows:</B> '$num_result_rows'  <B>current_view:</B> '$current_view'
        <B>layer4:</B> '$layer4'  <B>caller:</B> '$caller'
        <B>action:</B> '$action'  <B>action_arg:</B> '$action_arg'
        </PRE>";
  }
}

function FieldRows2sql($field, $cnt, &$s_sql)
{
  $tmp2 = "";
  for ( $i = 0; $i < $cnt; $i++ )
  {
      $tmp = "";
      if ( $field[$i][3] != "" && $field[$i][1] != " ")
      {
         $tmp = $field[$i][0]." ".$field[$i][1]." ".$field[$i][2]."".
                $field[$i][3]."".$field[$i][4]." ".$field[$i][5];
      }
      else
      {
         if ( $field[$i][3] != "" && $field[$i][1] == " ")
            ErrorMessage("<B>Criteria warning:</B> A value of '".$field[$i][3]."' was entered for a protocol field, but
                         the particular field was not specified.");
         if ( ($field[$i][1] != " " && $field[$i][1] != "") && $field[$i][3] == "" )
            ErrorMessage("<B>Criteria warning:</B> A field of '".$field[$i][1]."' was selected indicating that it
                          should be a criteria, but no value was specified on which to match.");
      }
      $tmp2 = $tmp2.$tmp;

      if ( $i > 0 && $field[$i-1][5] == ' ' )
         ErrorMessage("<B>Criteria warning:</B> Multiple protocol field criteria entered without a boolean 
                       operator (e.g. AND, OR) between them.");
  }

  if ( $tmp2 != "" )
  {
     $s_sql = $s_sql." AND ( ".$tmp2." )";
     return 1;
  }

  return 0;
}

function formatTimeDigit($time_digit)
{
   if ( strlen($time_digit) == 2 )
      return $time_digit;
   else
      return ('0'.$time_digit);
}

function addSQLItem(&$sstring, $what_to_add)
{
   if (strlen($sstring) == 0 )
        $sstring = '('.$what_to_add;
   else
        $sstring = $sstring." AND ".$what_to_add;
}

function DateTimeRows2sql($field, $cnt, &$s_sql)
{
  GLOBAL $db;
  $tmp2 = "";
  for ( $i = 0; $i < $cnt; $i++ )
  {
      $tmp = "";
      if ( $field[$i][1] != " " && $field[$i][1] != "")
      {
         $op = $field[$i][1];
     
         $t = "";

         /* Build the SQL string when >, >=, <, <= operator is used */
         if ( $op != "=" )
         {
            /* date */
            if ( $field[$i][4] != " " )
            {
               /* create the date string */
               $t = $field[$i][4];                             /* year */
               if ( $field[$i][2] != " " )
               {
                  $t = $t."-".$field[$i][2];                       /* month */
                  if ( $field[$i][3] != "" )
                     $t = $t."-".FormatTimeDigit($field[$i][3]);   /* day */                
                  else
                     $t = $t."-01";
               }
               else
                  $t = $t."-01-01";
            }
            /* time */
            // For MSSQL, you must have colons in the time fields. 
            // Otherwise, the DATEDIFF function will return Arithmetic Overflow
            if ( $field[$i][5] != "" )
            {
               $t = $t." ".FormatTimeDigit($field[$i][5]);         /* hour */
               if ( $field[$i][6] != "" )
               {
                  if ($db_DB_type != "mssql")
                    $t = $t.FormatTimeDigit($field[$i][6]);          /* minute */
                  else
                    $t = $t.":".FormatTimeDigit($field[$i][6]);
                  if ( $field[$i][7] != "" )
                     if ($db->DB_type != "mssql")
                       $t = $t.FormatTimeDigit($field[$i][7]);
                     else
                       $t = $t.":".FormatTimeDigit($field[$i][7]);
                  else
                     if ($db->DB_type != "mssql")
                       $t = $t."00"; //":00";
                     else
                       $t = $t.":00";
               }
               else
                  if ($db->DB_type != "mssql")
                    $t = $t."0000";  //":00:00";
                  else
                    $t = $t.":00:00";
            }
            /* fixup if have a > by adding an extra day */
            else if ( $op == ">" && $field[$i][4] != " " )
                $t = $t." 23:59:59";
            /* fixup if have a <= by adding an extra day */
            else if ( $op == "<=" && $field[$i][4] != " " )
                $t = $t." 23:59:59";
            
            /* neither date or time */
            if ( $field[$i][4] == " " && $field[$i][5] == "" )
               ErrorMessage("<B>Criteria warning:</B> A operator of '".$field[$i][1].
                            "' was selected indicating that some
                            date/time criteria should be matched, but no value was specified.");
            
            /* date or date/time */
            else if ( ($field[$i][4] != " " && $field[$i][5] != "") || $field[$i][4] != " ")
              $tmp = $field[$i][0].
                      $db->acidSQL_UNIXTIME("timestamp",$op, 
                                            $db->acidSQL_UNIXTIME("'".$t."'","","")).
                                                                  $field[$i][8].' '.$field[$i][9];
            /* time */
            else if ( ($field[$i][5] != " ") && ($field[$i][5] != "") )
            {
               ErrorMessage("<B>Criteria ERROR:</B>".
                            " (Invalid Hour) No date criteria were entered with the specified time.");
            }
         }

         /* Build the SQL string when the = operator is used */
         else
         {
            /* date */
            if ( $field[$i][4] != " " ) 
               addSQLItem($tmp, $db->acidSQL_YEAR("timestamp", "=", $field[$i][4]) );
            if ( $field[$i][2] != " " ) 
               addSQLItem($tmp, $db->acidSQL_MONTH("timestamp", "=", $field[$i][2]) );
            if ( $field[$i][3] != ""  ) 
               addSQLItem($tmp, $db->acidSQL_DAY("timestamp", "=", $field[$i][3]) );

            /* time */
            if ( $field[$i][5] != "" ) 
               addSQLItem($tmp, $db->acidSQL_HOUR("timestamp", "=", $field[$i][5]) );
            if ( $field[$i][6] != "" ) 
               addSQLItem($tmp, $db->acidSQL_MINUTE("timestamp", "=", $field[$i][6]) );
            if ( $field[$i][7] != "" ) 
               addSQLItem($tmp, $db->acidSQL_SECOND("timestamp", "=", $field[$i][7]) );

            /* neither date or time */
            if ( $tmp == "" )
               ErrorMessage("<B>Criteria warning:</B> A operator of '".$field[$i][1].
                            "' was selected indicating that some".
                            "date/time criteria should be matched, but no value was specified.");
            else
               $tmp = $field[$i][0].$tmp.')'.$field[$i][8].$field[$i][9];
         }
      }
      else
      {
         if ( ($field[$i][2] != " " || $field[$i][3] != "" || $field[$i][4] != " ") && 
               $field[$i][1] == " ")
            ErrorMessage("<B>Criteria warning:</B> A date/time value of '".
                          $field[$i][2]."-".$field[$i][3]."-".$field[$i][4]." ".
                          $field[$i][5].":".$field[6].":".$field[7]."' was entered 
                          but no operator was selected.");
      }

      if ( $i > 0 && $field[$i-1][9] == ' ' && $field[$i-1][4] != " ")
         ErrorMessage("<B>Criteria warning:</B> ".
                      "Multiple Time/Date criteria entered without a boolean ".
                      "operator (e.g. AND, OR) between them.");
      $tmp2 = $tmp2.$tmp;
  }

  if ( $tmp2 != "" )
  {
     $s_sql = $s_sql." AND (".$tmp2.") ";
     return 1;
  }

  return 0;
}

function FormatPayload($payload_str, $data_encode)
/* Accepts a payload string and decides whether any conversion is necessary
   to create a sql call into the DB.  Currently we only are concerned with
   hex <=> ascii. 
 */
{
  /* if the source is hex strip out any spaces and \n */
  if ( $data_encode == "hex" )
  {
     $payload_str = str_replace("\n", "", $payload_str);
     $payload_str = str_replace(" ", "", $payload_str);
  }

  /* If both the source type and conversion type are the same OR
        no conversion type is specified THEN return the plain string */
  if ( ($data_encode[0] == $data_encode[1]) ||
       $data_encode[1] == " " )
       return $payload_str;
  else
  {
     $tmp = "";

     /* hex => ascii */
     if ( $data_encode[0] == "hex" && $data_encode[1] == "ascii" )
        for ( $i = 0; $i < strlen($payload_str); $i += 2)
        {
            $t = hexdec($payload_str[$i].$payload_str[$i+1]);
                 
            if ( $t > 32 && $t < ord("z"))
                 $tmp = $tmp.chr($t);
            else
                 $tmp = $tmp.'.';
        }

     /* ascii => hex */
     else if ( $data_encode[0] == "ascii" && $data_encode[1] == "hex" )
        for ( $i = 0; $i < strlen($payload_str); $i++ )
            $tmp = $tmp.dechex(ord($payload_str[$i]));

     return $tmp;
  }

  return "";    /* should be unreachable */
}

function DataRows2sql($field, $cnt, $data_encode, &$s_sql)
{
  $tmp2 = "";
  for ( $i = 0; $i < $cnt; $i++ )
  {
      $tmp = "";
      if ( $field[$i][2] != "" && $field[$i][1] != " ")
      {
         $tmp = $field[$i][0]." data_payload ".$field[$i][1]." '%".FormatPayload($field[$i][2], $data_encode).
                "%' ".$field[$i][3]."".$field[$i][4]." ".$field[$i][5];
      }
      else
      {
         if ( $field[$i][2] != "" && $field[$i][1] == " ")
            ErrorMessage("<B>Criteria warning:</B> A payload value of '".$field[$i][2]."' was entered for a 
                          payload criteria field, but an operator (e.g. has, has not) was not specified.");
         if ( ($field[$i][1] != " " && $field[$i][1] != "") && $field[$i][2] == "" )
            ErrorMessage("<B>Criteria warning:</B> An operator of '".$field[$i][1]."' was selected indicating that
                         payload should be a criteria, but no value on which to match was specified.");
      }
      $tmp2 = $tmp2.$tmp;

      if ( $i > 0 && $field[$i-1][4] == ' ' )
         ErrorMessage("<B>Criteria warning:</B> Multiple Data payload criteria entered without a boolean 
                      operator (e.g. AND, OR) between them.");
  }

  if ( $tmp2 != "" )
  {
     $s_sql = $s_sql." AND ( ".$tmp2." )";
     return 1;
  }

  return 0;
}

function PrintCriteria($caller)
{
  GLOBAL $db, $cs, $last_num_alerts, $time, $time_cnt, $sig, $sig_type, 
         $sensor, $ag, $sig_class,
         $ip_addr, $ip_addr_cnt, $ip_field, $ip_field_cnt,
         $tcp_port, $tcp_port_cnt, $tcp_flags, $tcp_field, $tcp_field_cnt,
         $udp_port, $udp_port_cnt, $udp_field, $udp_field_cnt,
         $icmp_field, $icmp_field_cnt,
         $have_meta, $have_ip, $have_tcp, $have_udp, $have_icmp, $have_data,
         $layer4, $data, $data_cnt, $data_encode, $save_criteria;

  /* Generate the Criteria entered into a human readable form */
  $human_fields["ip_src"] = "Source Address";
  $human_fields["ip_dst"] = "Dest. Address";
  $human_fields["ip_both"] = "Source or Dest. Address";
  $human_fields["ip_ttl"] = "TTL";
  $human_fields["ip_tos"] = "TOS";
  $human_fields["ip_id"] = "ID";
  $human_fields["ip_off"] = "offset";
  $human_fields["ip_len"] = "length";
  $human_fields["ip_csum"] = "chksum";
  $human_fields["layer4_sport"] = "source port";
  $human_fields["layer4_dport"] = "dest port";
  $human_fields[""] = "";  
  $human_fields["tcp_win"] = "window";  
  $human_fields["tcp_urp"] = "urp";
  $human_fields["tcp_seq"] = "seq #";
  $human_fields["tcp_ack"] = "ack";
  $human_fields["tcp_off"] = "offset";
  $human_fields["tcp_res"] = "res";
  $human_fields["tcp_csum"] = "chksum";  
  $human_fields["udp_len"] = "length";  
  $human_fields["udp_csum"] = "chksum";
  $human_fields["icmp_type"] = "type";
  $human_fields["icmp_code"] = "code";
  $human_fields["icmp_csum"] = "chksum";
  $human_fields["icmp_id"] = "id";
  $human_fields["icmp_seq"] = "seq";
  $human_fields["LIKE"] = "contains";
  $human_fields["="] = "=";  
  $human_fields["1"] = "F";
  $human_fields["2"] = "S";
  $human_fields["4"] = "R";
  $human_fields["8"] = "P";
  $human_fields["16"] = "A";
  $human_fields["32"] = "U";
  $human_fields["64"] = "[R0]";
  $human_fields["128"] = "[R1]";

  //$save_criteria = '&nbsp<B>Queried DB on </B><FONT> : '.date("D F d, Y H:i:s",time()).'</FONT>  
  $save_criteria = '
   <TABLE CELLSPACING=1 CELLPADDING=2 BORDER=0 BGCOLOR="#FFFFFF">
    <TR>
        <TD CLASS="metatitle">Meta Criteria</TD>
        <TD>';

  /* If printing any of the LAST-X stats then ignore all the other criteria */
  if (  $caller == "last_tcp" || $caller == "last_udp" || 
        $caller == "last_icmp" || $caller == "last_any" ) 
  {
    $save_criteria = $save_criteria.'&nbsp;&nbsp;';
    if ( $caller == "last_tcp" )
       $save_criteria = $save_criteria.'Last '.$last_num_alerts.' TCP Alerts'; 
    else if ( $caller == "last_udp" )
       $save_criteria = $save_criteria.'Last '.$last_num_alerts.' UDP Alerts'; 
    else if ( $caller == "last_icmp" )
       $save_criteria = $save_criteria.'Last '.$last_num_alerts.' ICMP Alerts'; 
    else if ( $caller == "last_any" )
       $save_criteria = $save_criteria.'Last '.$last_num_alerts.' Alerts';
    
    $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR></TABLE>';
    echo $save_criteria;
    return;
  }

//  if ( $have_meta == 1 )
//  {
     $tmp_len = strlen($save_criteria);

     if ( $sensor != " " && $sensor != "" )
        $save_criteria = $save_criteria.'Sensor = ['.$sensor.'] '.
                         GetSensorName($sensor, $db).
                         $cs->GetClearCriteriaString("sensor").'<BR>';
 
     if ( $ag != " " && $ag != "" )
        $save_criteria = $save_criteria.'Alert Group = ['.$ag.'] '.GetAGNameByID($ag, $db).
                         $cs->GetClearCriteriaString("ag").'<BR>';

     if ( $sig[0] != " " && $sig[1] != "" )
     {
        if ( $sig[0] == '=' && $sig[2] == '!=' )
           $tmp_human = '!=';
        else if ( $sig[0] == '=' && $sig[2] == '=' )
           $tmp_human = '=';
        else if ( $sig[0] == 'LIKE' && $sig[2] == '!=' )
           $tmp_human = ' does not contain ';
        else if ( $sig[0] == 'LIKE' && $sig[2] == '=' )
           $tmp_human = ' contains ';

        $save_criteria = $save_criteria.'Signature '.$tmp_human.' "';
        if ( ($db->acidGetDBVersion() >= 100) && $sig_type == 1 )
           $save_criteria = $save_criteria.BuildSigByID($sig[1], $db).'" '.
                            $cs->GetClearCriteriaString("sig");
        else
          $save_criteria = $save_criteria.$sig[1].
                           $cs->GetClearCriteriaString("sig");

        $save_criteria = $save_criteria.'<BR>';
     }

     if ( $db->acidGetDBVersion() >= 103 )
     {
        if ( $sig_class != " " && $sig_class != "" )
        {
          if ( $sig_class == "null")
             $save_criteria = $save_criteria.'Signature Classification = '.
                              '<I>unclassified</I><BR>';
          else
             $save_criteria = $save_criteria.'Signature Classification = '.
                              GetSigClassName($sig_class, $db).
                              $cs->GetClearCriteriaString("sig_class").'<BR>';
        }
     }

     $tmp_len2 = strlen($save_criteria);
     for ($i = 0; $i < $time_cnt; $i++)
     {
         if ( $time[$i][1] != " " )
         { 
            $save_criteria = $save_criteria.'<CODE>'.$time[$i][0].' time '.$time[$i][1].' [ ';

            /* date */
            if ( $time[$i][2] == " " && $time[$i][3] == "" && $time[$i][4] == " " )
               $save_criteria = $save_criteria." </CODE><I>any date</I><CODE>";
            else
               $save_criteria = $save_criteria.(($time[$i][2] == " ") ? "* / " : $time[$i][2]." / ").
                                               (($time[$i][3] == "" ) ? "* / " : $time[$i][3]." / ").
                                               (($time[$i][4] == " ") ? "*  " : $time[$i][4]." "); 
            $save_criteria = $save_criteria.'] [';
            /* time */
            if ( $time[$i][5] == "" && $time[$i][6] == "" && $time[$i][7] == "" )
               $save_criteria = $save_criteria."</CODE><I>any time</I><CODE>";
            else
               $save_criteria = $save_criteria.(($time[$i][5] == "") ? "* : " : $time[$i][5]." : ").
                                               (($time[$i][6] == "") ? "* : " : $time[$i][6]." : ").
                                               (($time[$i][7] == "") ? "*  " : $time[$i][7]." "); 
            $save_criteria = $save_criteria.$time[$i][8].$time[$i][9];
            $save_criteria = $save_criteria.']';
            $save_criteria = $save_criteria.'</CODE><BR>';
         }             
     }
     if ( $tmp_len2 < strlen($save_criteria) )
       $save_criteria = $save_criteria.$cs->GetClearCriteriaString("time");


    if ( $tmp_len == strlen($save_criteria) ) 
       $save_criteria = $save_criteria.'<I> &nbsp&nbsp any </I>';

  $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR>';

  $save_criteria = $save_criteria.'
    <TR>
        <TD CLASS="iptitle">IP Criteria</TD>
        <TD>';
//  if ( $have_ip == 1 )
//  {

     $tmp_len = strlen($save_criteria);
     $have_criteria = 0;
     for ( $i = 0; $i < $ip_addr_cnt; $i++ )
     {
           $tmp = "";
           if ( isset($ip_addr[$i][3]) && $ip_addr[$i][3] != "" )
           {
              $tmp = $tmp.$ip_addr[$i][3];
              if ( $ip_addr[$i][4] != "" )
              {
                 $tmp = $tmp.".".$ip_addr[$i][4];
                 if ( $ip_addr[$i][5] != "" )
                 {
                    $tmp = $tmp.".".$ip_addr[$i][5];
                    if ( $ip_addr[$i][6] != "" )
                    {
                       if ( ($ip_addr[$i][3].".".$ip_addr[$i][4].".".
                             $ip_addr[$i][5].".".$ip_addr[$i][6]) == NULL_IP)
                         $tmp = " unknown ";
                       else
                         $tmp = $tmp.".".$ip_addr[$i][6];
                    }
                    else
                       $tmp = $tmp.'.*';
                 }
                 else
                    $tmp = $tmp.'.*.*';
              }
              else
                 $tmp = $tmp.'.*.*.*';
             }
             /* Make sure that the IP isn't blank */
             if ( $tmp != "" )
             {
                $mask = "";
                if ( $ip_addr[$i][10] != "" )
                   $mask = "/".$ip_addr[$i][10];

                $save_criteria = $save_criteria.$ip_addr[$i][0].
                                 $human_fields[($ip_addr[$i][1])].' '.$ip_addr[$i][2].
                                 ' '.$tmp.' '.$ip_addr[$i][8].' '.$ip_addr[$i][9].$mask.
                                 $cs->GetClearCriteriaString("ip_addr")."<BR>";
             }
     }

     $tmp_len2 = strlen($save_criteria);
     for ( $i = 0; $i < $ip_field_cnt; $i++ )
     {
         if ($ip_field[$i][1] != " " && $ip_field[$i][3] != "" )
            $save_criteria = $save_criteria.$ip_field[$i][0].$human_fields[($ip_field[$i][1])].' '.
                             $ip_field[$i][2].' '.$ip_field[$i][3].$ip_field[$i][4].' '.$ip_field[$i][5];
     }
     if ( $tmp_len2 < strlen($save_criteria) )
       $save_criteria = $save_criteria.$cs->GetClearCriteriaString("ip_field"); 

    if ( $tmp_len == strlen($save_criteria) ) 
       $save_criteria = $save_criteria.'<I> &nbsp&nbsp any </I>';    

  $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR>';

  if ( $layer4 == "TCP" )
  {
    $save_criteria = $save_criteria.'
      <TR>
        <TD CLASS="layer4title">TCP Criteria</TD>
        <TD>';

     if ( $have_tcp == 1 )
     {
       $have_criteria = 0;
       for ( $i = 0; $i < $tcp_port_cnt; $i++ )
       {
         if ($tcp_port[$i][1] != " " && $tcp_port[$i][3] != "" )
         {
            $save_criteria = $save_criteria.$tcp_port[$i][0].$human_fields[($tcp_port[$i][1])].' '.
                             $tcp_port[$i][2].' '.$tcp_port[$i][3].$tcp_port[$i][4].' '.$tcp_port[$i][5];
            $have_criteria++;
         }
       }       

       if ( $have_criteria > 0 )  
          $save_criteria = $save_criteria. $cs->GetClearCriteriaString("tcp_port").'<BR>';

       if ( isset($tcp_flags[$i][0]) && ($tcp_flags[$i][0] != " ") && ($tcp_flags[$i][0] != "") )
       {
          $save_criteria = $save_criteria.'flags '.$tcp_flags[0].' ';
          for ( $i = 8; $i >=1; $i-- )
             if ( $tcp_flags[$i] == "" )
                $save_criteria = $save_criteria.'-';
             else
                $save_criteria = $save_criteria.$human_fields[($tcp_flags[$i])];
           $save_criteria = $save_criteria.
                            $cs->GetClearCriteriaString("tcp_flags").'<BR>';
       }

       $have_criteria = 0;
       for ( $i = 0; $i < $tcp_field_cnt; $i++ )
         if ($tcp_field[$i][1] != " " && $tcp_field[$i][3] != "" )
         {
            $save_criteria = $save_criteria.$tcp_field[$i][0].$human_fields[($tcp_field[$i][1])].' '.
                             $tcp_field[$i][2].' '.$tcp_field[$i][3].$tcp_field[$i][4].' '.$tcp_field[$i][5];
            $have_criteria = 1;
         }
       if ( $have_criteria )
         $save_criteria = $save_criteria.$cs->GetClearCriteriaString("tcp_field");
     }
     else
        $save_criteria = $save_criteria.'<I> &nbsp&nbsp any </I>';

     $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR>';
  }

  else if ( $layer4 == "UDP" )
  {
    $save_criteria = $save_criteria.'
      <TR>
        <TD CLASS="layer4title">UDP Criteria</TD>
        <TD>';

     if ( $have_udp == 1 )
     {

       $have_criteria = 0;
       for ( $i = 0; $i < $udp_port_cnt; $i++ )
       {
         if ($udp_port[$i][1] != " " && $udp_port[$i][3] != "" )
         {
            $save_criteria = $save_criteria.$udp_port[$i][0].$human_fields[($udp_port[$i][1])].' '.
                             $udp_port[$i][2].' '.$udp_port[$i][3].$udp_port[$i][4].' '.$udp_port[$i][5];
            $have_criteria = 1;
         }
       }

       if ($have_criteria)
         $save_criteria = $save_criteria.$cs->GetClearCriteriaString("udp_port").'<BR>';

       $have_criteria = 0;
       for ( $i = 0; $i < $udp_field_cnt; $i++ )
       {
         if ($udp_field[$i][1] != " " && $udp_field[$i][3] != "" )
         {
            $save_criteria = $save_criteria.$udp_field[$i][0].$human_fields[($udp_field[$i][1])].' '.
                             $udp_field[$i][2].' '.$udp_field[$i][3].$udp_field[$i][4].' '.$udp_field[$i][5];
            $have_criteria = 1;
         }
       }

       if ( $have_criteria )
         $save_criteria = $save_criteria.$cs->GetClearCriteriaString("udp_field");
     }
     else
        $save_criteria = $save_criteria.'<I> &nbsp&nbsp any </I>';

     $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR>';
  }

  else if ( $layer4 == "ICMP" )
  {
    $save_criteria = $save_criteria.'
      <TR>
        <TD CLASS="layer4title">ICMP Criteria</TD>
        <TD>';

     if ( $have_icmp == 1 )
     {
       for ( $i = 0; $i < $icmp_field_cnt; $i++ )
       {
         if ($icmp_field[$i][1] != " " && $icmp_field[$i][3] != "" )
            $save_criteria = $save_criteria.$icmp_field[$i][0].$human_fields[($icmp_field[$i][1])].' '.
                             $icmp_field[$i][2].' '.$icmp_field[$i][3].$icmp_field[$i][4].' '.$icmp_field[$i][5];
       }

       $save_criteria = $save_criteria.$cs->GetClearCriteriaString("icmp_field");
     }
     else
        $save_criteria = $save_criteria.'<I> &nbsp&nbsp any </I>';

     $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR>';
  }

  else
  {
     $save_criteria = $save_criteria.'
      <TR>
        <TD CLASS="layer4title">Layer 4 Criteria</TD>
        <TD> <I> &nbsp&nbsp none </I></TD></TR>';
  }

  /* Payload ************** */
  $save_criteria = $save_criteria.'  
    <TR>
        <TD CLASS="payloadtitle">Payload Criteria</TD>
        <TD>';
  if ( $have_data == 1 )
  {       
       if ( $data_encode[0] != " " && $data_encode[1] != " ")
       {
          $save_criteria = $save_criteria.' (data encoded as '.$data_encode[0];
          $save_criteria = $save_criteria.' => '.$data_encode[1];
          $save_criteria = $save_criteria.')<BR>';
       }
       else
          $save_criteria = $save_criteria.' (no data conversion, assuming criteria in DB native encoding)<BR>';

       for ( $i = 0; $i < $data_cnt; $i++ )
       {
         if ($data[$i][1] != " " && $data[$i][2] != "" )
            $save_criteria = $save_criteria.$data[$i][0].$data[$i][1].' "'.$data[$i][2].
                             '" '.$data[$i][3].' '.$data[$i][4];
       }
       
       $save_criteria = $save_criteria.$cs->GetClearCriteriaString("data");
  }
  else
     $save_criteria = $save_criteria.'<I> &nbsp&nbsp any </I>';

  $save_criteria = $save_criteria.'&nbsp;&nbsp;</TD></TR>';

  
  $save_criteria = $save_criteria.'
  
  </TABLE>'; 

  $save_criteria = '&nbsp<B>Queried DB on </B><FONT> : '.date("D F d, Y H:i:s",time()).'</FONT>'.
                   '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#000000">'.
                   '<TR><TD>'.
         
                   '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=1 BGCOLOR="#DDDDDD"><TR><TD>'.

                   $save_criteria.

                   '</TD></TR></TABLE>'.

                   '</TD></TR>'.
                   '</TABLE>';


  echo $save_criteria;
}

/********************************************************************************************/
function ProcessCriteria()
{
  GLOBAL $db, $time, $time_cnt, $sig, $sig_type, $sig_class, $sensor, $ag,
         $ip_addr, $ip_addr_cnt, $ip_field, $ip_field_cnt,
         $tcp_port, $tcp_port_cnt, $tcp_flags, $tcp_field, $tcp_field_cnt,
         $udp_port, $udp_port_cnt, $udp_field, $udp_field_cnt,
         $icmp_field, $icmp_field_cnt,
         $have_meta, $have_ip, $have_tcp, $have_udp, $have_icmp, $have_data,
         $layer4, $data, $data_cnt, $data_encode, $save_criteria,
         $join_sql, $where_sql, $criteria_sql, $sql, $debug_mode,
         $caller, $DBtype;

  /* the JOIN criteria */
  $ip_join_sql  = " LEFT JOIN iphdr ON acid_event.sid=iphdr.sid AND acid_event.cid=iphdr.cid ";
  $tcp_join_sql = " LEFT JOIN tcphdr ON acid_event.sid=tcphdr.sid AND acid_event.cid=tcphdr.cid ";
  $udp_join_sql = " LEFT JOIN udphdr ON acid_event.sid=udphdr.sid AND acid_event.cid=udphdr.cid ";
  $icmp_join_sql= " LEFT JOIN icmphdr ON acid_event.sid=icmphdr.sid AND acid_event.cid=icmphdr.cid ";
  $data_join_sql= " LEFT JOIN data ON acid_event.sid=data.sid AND acid_event.cid=data.cid ";
  $ag_join_sql  = " LEFT JOIN acid_ag_alert ON acid_event.sid=acid_ag_alert.ag_sid AND acid_event.cid=acid_ag_alert.ag_cid "; 

  $sig_join_sql = "";

  $sql = "SELECT acid_event.sid, acid_event.cid, signature, timestamp, ".
         "acid_event.ip_src, acid_event.ip_dst, acid_event.ip_proto FROM acid_event";
 
  $where_sql = " WHERE ";
  $criteria_sql = " acid_event.sid > 0";
  $join_sql = "";

  /* ********************** Meta Criteria ******************************************** */

  $tmp_meta = "";
  /* Sensor */
  if ( $sensor != "" && $sensor != " " )
     $tmp_meta = $tmp_meta." AND acid_event.sid=".$sensor;

  /* Alert Group */
  if ( $ag != "" && $ag != " " )
  {
     $tmp_meta = $tmp_meta." AND ag_id =".$ag;
     $join_sql = $join_sql.$ag_join_sql;
  }

  /* Signature */
  if ( $sig[0] != " " && $sig[0] != "" && $sig[1] != "" )
  {
     $sig_neg = "";
     if ( $sig[2] == "!=" )
        $sig_neg = " NOT ";

     if ( $db->acidGetDBVersion() >= 100 )
     {
        /* If given a sig ID instead of a name */
        if ( ($sig_type == 1) && ($sig[0] == "=") )
        {
           $tmp_meta = $tmp_meta." AND (signature='".$sig[1]."') ";
        }
        else
        {
           if ( $sig[0] == "=" )
              if ($db->DB_type != "mssql")
                $tmp_meta = $tmp_meta." AND ".$sig_neg." (sig_name='".$sig[1]."') ";
              else 
                $tmp_meta = $tmp_meta." AND ".$sig_neg." (sig_name LIKE '".MssqlKludgeValue($sig[1])."') ";
           else if ($sig[0] == "LIKE" )
              $tmp_meta = $tmp_meta." AND ".$sig_neg." (sig_name LIKE '%".$sig[1]."%') ";
        }
     }
     else
     {
       if ( $sig[0] == "=" )
         $tmp_meta = $tmp_meta." AND ".$sig_neg." (signature='".$sig[1]."') ";
       else if ($sig[0] == "LIKE" )
         $tmp_meta = $tmp_meta." AND ".$sig_neg." (signature LIKE '%".$sig[1]."%') ";
     }
  }

  /* Signature Classification */
  if ( $sig_class != " " && $sig_class != "" && $sig_class != "0")
  {
     $tmp_meta = $tmp_meta." AND sig_class_id = ".$sig_class;
  }
  else if ($sig_class == "0")
  {
     $tmp_meta = $tmp_meta." AND (sig_class_id is null OR sig_class_id = 0)";
  }

  /* Date/Time */
  DateTimeRows2sql($time, $time_cnt, $tmp_meta);

  if ( $tmp_meta != "" )
  {
     $have_meta = 1;
     $criteria_sql = $criteria_sql.$tmp_meta;
  }
  else
     $have_meta = 0;

  /* ********************** IP Criteria ********************************************** */ 

  // $tmp_cnt = strlen($criteria_sql);

  /* IP Addresses */
  $tmp2 = "";
 
  for ( $i = 0; $i < $ip_addr_cnt; $i++ )
  {
     $tmp = "";
     if ( isset($ip_addr[$i][3]) && $ip_addr[$i][1] != " ")
     {
        if ( ($ip_addr[$i][3] != "") && ($ip_addr[$i][4] != "") &&
             ($ip_addr[$i][5] != "") && ($ip_addr[$i][6] != "" ) )
        {
           /* if use illegal 256.256.256.256 address then
            *  this is the special case where need to search for portscans
            */
           if ( ($ip_addr[$i][3] == "256") && ($ip_addr[$i][4] == "256") &&
                ($ip_addr[$i][5] == "256") && ($ip_addr[$i][6] == "256" ) )
           {
             $tmp = $tmp." acid_event.".$ip_addr[$i][1]." IS NULL"." ";
           }
           else
           {
             if ( $ip_addr[$i][10] == "" )
             {
             $tmp = $tmp." acid_event.".$ip_addr[$i][1].$ip_addr[$i][2].
                    acidIP2Long($ip_addr[$i][3].".". 
                                $ip_addr[$i][4].".".
                                $ip_addr[$i][5].".".
                                $ip_addr[$i][6])." ";
             }
             else
             {
                $mask = getIPMask($ip_addr[$i][3].".". 
                                  $ip_addr[$i][4].".".
                                  $ip_addr[$i][5].".".
                                  $ip_addr[$i][6], $ip_addr[$i][10]);
                if ( $ip_addr[$i][2] == "!=" )
                   $tmp_op = " NOT ";
                else 
                   $tmp_op = "";

                $tmp = $tmp.$tmp_op." (acid_event.".$ip_addr[$i][1].">=".
                               acidIP2Long($mask[0])." AND ".
                               "acid_event.".$ip_addr[$i][1]."<=".
                               acidIP2Long($mask[1]).")"; 
             }       
           }
        }
        /* if have chosen the address type to be both source and destination */
        if ( ereg("ip_both", $tmp) )
        {
           $tmp_src = ereg_replace("ip_both","ip_src",$tmp);
           $tmp_dst = ereg_replace("ip_both","ip_dst",$tmp);
           
           if ( $ip_addr[$i][2] == '=' )
             $tmp = "(".$tmp_src.') OR ('.$tmp_dst.')';
           else
             $tmp = "(".$tmp_src.') AND ('.$tmp_dst.')';
        }
           
        $tmp = $ip_addr[$i][0]."(".$tmp.")".$ip_addr[$i][8].$ip_addr[$i][9];
     }
     else if ( (isset($ip_addr[$i][3]) && $ip_addr[$i][3] != "" ) || $ip_addr[$i][1] != " " )
     {
        /* IP_addr_type, but MALFORMED IP address */
        if ( $ip_addr[$i][1] != " " && $ip_addr[$i][3] == "" && 
             ($ip_addr[$i][4] != "" || $ip_addr[$i][5] != "" || $ip_addr[$i][6] != "" ) )
            ErrorMessage("<B>Criteria warning:</B> Invalid IP address criteria ' *.".
                         $ip_addr[$i][4].".".$ip_addr[$i][5].".".$ip_addr[$i][6]." '");

        /* ADDRESS, but NO IP_addr_type was given */
        if ( isset($ip_addr[$i][3]) && $ip_addr[$i][1] == " ")
           ErrorMessage("<B>Criteria warning:</B> A IP address of '".
                        $ip_addr[$i][3].".".$ip_addr[$i][4].".".
                        $ip_addr[$i][5].".".$ip_addr[$i][6]."' was entered 
                        for as a criteria value, but the type of address 
                        (e.g. source, destination) was not specified.");

        /* IP_addr_type IS FILLED, but no ADDRESS */
        if ( ($ip_addr[$i][1] != " " && $ip_addr[$i][1] != "") && $ip_addr[$i][3] == "" )
           ErrorMessage("<B>Criteria warning:</B> An IP address of type '".
                        $ip_addr[$i][1]."' was selected (at #".$i.") 
                        indicating that an IP address should be a criteria, 
                        but no address on which to match 
                        was specified.");
     }
     $tmp2 = $tmp2.$tmp;

     if ( ($i > 0 && $ip_addr[$i-1][9] == ' ' && $ip_addr[$i-1][3] != "") )
        ErrorMessage("<B>Criteria warning:</B> Multiple IP address criteria entered without a boolean 
                     operator (e.g. AND, OR) between IP Criteria #$i and #".($i+1).".");
  }

  if ( $tmp2 != "" )
     $criteria_sql = $criteria_sql." AND ( ".$tmp2." )";  

  $tmp_cnt = strlen($criteria_sql);

  /* IP Fields */
  FieldRows2sql($ip_field, $ip_field_cnt, $criteria_sql);

  if ( $tmp_cnt != strlen($criteria_sql) )
     $have_ip = 1;
  else
     $have_ip = 0;

  /* Layer-4 encapsulation */
  /* if ( $caller != "" $caller == "" || 
       $caller == "last_tcp" || $caller == "last_udp" || $caller == "last_icmp" ) */
     if ( $layer4 == "TCP" )
        $criteria_sql = $criteria_sql." AND acid_event.ip_proto= 6";  
     else if ( $layer4 == "UDP" )
        $criteria_sql = $criteria_sql." AND acid_event.ip_proto= 17";
     else if ( $layer4 == "ICMP" )
         $criteria_sql = $criteria_sql." AND acid_event.ip_proto= 1";

  /* Build the final IP criteria */
  if ( $have_ip == 1 )
     $join_sql = $ip_join_sql.$join_sql;

  /* ********************** TCP Criteria ********************************************** */
if ( $layer4 == "TCP" )
{
  $have_tcp = 0;
  $proto_tmp = "";
  /* TCP Ports */
  FieldRows2sql($tcp_port, $tcp_port_cnt, $proto_tmp);
  if ( $proto_tmp != "" ) $have_tcp = 1;
  $criteria_sql = $criteria_sql.$proto_tmp;
  $proto_tmp = "";

  /* TCP Flags */
  if ( isset($tcp_flags) )
  {
    if ( $tcp_flags[0] == "contains" || $tcp_flags[0] == "is" )
    {
      $flag_tmp = $tcp_flags[1]+$tcp_flags[2]+$tcp_flags[3]+$tcp_flags[4]+
                  $tcp_flags[5]+$tcp_flags[6]+$tcp_flags[7]+$tcp_flags[8];
      if ( $tcp_flags[0] == "is" )
        $proto_tmp = $proto_tmp.' AND tcp_flags='.$flag_tmp;
      else if ( $tcp_flags[0] == "contains" )
        $proto_tmp = $proto_tmp.' AND (tcp_flags & '.$flag_tmp.' = '.$flag_tmp." )";
      else 
        $proto_tmp = "";
    }
  }

  /* TCP Fields */
  FieldRows2sql($tcp_field, $tcp_field_cnt, $proto_tmp);

  /* TCP Options 
   *  - not implemented
   */

  if ( $proto_tmp != "" )
  {
     $have_tcp = 1;
     $criteria_sql = $criteria_sql.$proto_tmp;
     $join_sql = $tcp_join_sql.$join_sql;
  }
}

  /* ********************** UDP Criteria ********************************************* */
if ( $layer4 == "UDP" )
{
  $proto_tmp = "";
  $have_udp = 0;

  /* UDP Ports */
  FieldRows2sql($udp_port, $udp_port_cnt, $proto_tmp);
  if ( $proto_tmp != "" ) $have_udp = 1;
  $criteria_sql = $criteria_sql.$proto_tmp;
  $proto_tmp = "";

  /* UDP Fields */
  FieldRows2sql($udp_field, $udp_field_cnt, $proto_tmp);

  if ( $proto_tmp != "" )
  {
     $have_udp = 1;
     $criteria_sql = $criteria_sql.$proto_tmp;
     $join_sql = $udp_join_sql.$join_sql;
  }
}

  /* ********************** ICMP Criteria ******************************************** */
if ( $layer4 == "ICMP" )
{
  $proto_tmp = "";
  /* ICMP Fields */
  FieldRows2sql($icmp_field, $icmp_field_cnt, $proto_tmp);

  if ( $proto_tmp != "" )
  {
     $have_icmp = 1;
     $criteria_sql = $criteria_sql.$proto_tmp;
     $join_sql = $icmp_join_sql.$join_sql;
  }
  else
     $have_icmp = 0;
}

  /* ********************** Payload Criteria ***************************************** */  

  $tmp_payload = "";
  DataRows2sql($data, $data_cnt, $data_encode, $tmp_payload);

  if ( $tmp_payload != "" )
  {
     $have_data = 1;
     $criteria_sql = $criteria_sql.$tmp_payload;
     $join_sql = $data_join_sql.$join_sql;
  }
  else
     $have_data = 0;

  $csql[0] = $join_sql;
  $csql[1] = $criteria_sql;

  return $csql;
}

?>
