1<?php
2/*******************************************************************************
3** Basic Analysis and Security Engine (BASE)
4** Copyright (C) 2004 BASE Project Team
5** Copyright (C) 2000 Carnegie Mellon University
6**
7** (see the file 'base_main.php' for license details)
8**
9** Project Leads: Kevin Johnson <kjohnson@secureideas.net>
10**                Sean Muller <samwise_diver@users.sourceforge.net>
11** Built upon work by Roman Danyliw <rdd@cert.org>, <roman@danyliw.com>
12**
13** Purpose: Common Functions
14********************************************************************************
15** Authors:
16********************************************************************************
17** Kevin Johnson <kjohnson@secureideas.net
18**
19********************************************************************************
20*/
21
22function GetSensorIDs($db)
23{
24   $result = $db->baseExecute("SELECT sid FROM sensor;");
25
26   while( $myrow = $result->baseFetchRow() ) {
27	$sensor_ids[] = $myrow[0];
28   }
29
30   $result->baseFreeRows();
31
32   return $sensor_ids;
33}
34
35function GetSensorName($sid, $db)
36{
37    $name = "";
38
39    $temp_sql = "SELECT sid, hostname, interface, filter FROM sensor WHERE sid='".$sid."'";
40    $tmp_result = $db->baseExecute($temp_sql);
41    if ( $tmp_result )
42    {
43       $myrow = $tmp_result->baseFetchRow();
44       $name = $myrow[1].':'.$myrow[2];
45       if ( $myrow[3] != "" )
46          $name = $name.':'.$myrow[3];
47    }
48    $tmp_result->baseFreeRows();
49
50    return $name;
51}
52
53function GetVendor($mac)
54{
55    $mac = str_replace(":", "", $mac);
56    $mac = substr($mac, 0, 6);
57    $vendor = 'unknown';
58
59    if (@$fp = fopen("base_mac_prefixes.map", "r")) {
60       while (!feof($fp)) {
61           $line = fgets($fp);
62           if (strcmp($mac, substr($line, 0, 6)) == 0)
63               $vendor = substr($line, 7, strlen($line)-8);
64       }
65       fclose($fp);
66    }
67    else
68       return "can't open vendor map";
69
70    return $vendor;
71}
72
73function InputSafeSQL (&$SQLstr)
74/* Removes the escape sequence of \' => ' which arise when a variable containing a '-character is passed
75   through a POST query.  This is needed since otherwise the MySQL parser complains */
76{
77   $SQLstr = str_replace("\'", "'", $SQLstr);
78   $SQLstr = str_replace("\\\"", "\"", $SQLstr);
79}
80
81
82function PrintProtocolProfileGraphs ($db)
83{
84   $tcp_cnt = TCPPktCnt($db);
85   $udp_cnt = UDPPktCnt($db);
86   $icmp_cnt = ICMPPktCnt($db);
87   $portscan_cnt = PortscanPktCnt($db);
88   $layer4_cnt = $tcp_cnt + $udp_cnt + $icmp_cnt + $portscan_cnt;
89
90   if ( $tcp_cnt > 0 )
91   {
92      $tcp_percent = round($tcp_cnt/$layer4_cnt*100);
93      if ( $tcp_percent == 0 )
94         $tcp_percent_show = "&lt; 1";
95      else
96         $tcp_percent_show = $tcp_percent;
97   }
98   else
99   {
100      $tcp_percent = 0;
101      $tcp_percent_show = "0";
102   }
103
104   if ( $udp_cnt > 0 )
105   {
106      $udp_percent = round($udp_cnt/$layer4_cnt*100);
107      if ( $udp_percent == 0 )
108         $udp_percent_show = "&lt; 1";
109      else
110         $udp_percent_show = $udp_percent;
111   }
112   else
113   {
114      $udp_percent = 0;
115      $udp_percent_show = "0";
116   }
117
118   if ( $icmp_cnt > 0 )
119   {
120      $icmp_percent = round($icmp_cnt/$layer4_cnt*100);
121      if ( $icmp_percent == 0 )
122         $icmp_percent_show = "&lt; 1";
123       else
124         $icmp_percent_show = $icmp_percent;
125   }
126   else
127   {
128      $icmp_percent = 0;
129      $icmp_percent_show = 0;
130   }
131
132   if ( $portscan_cnt > 0 )
133   {
134      $portscan_percent = round($portscan_cnt/$layer4_cnt*100);
135      if ( $portscan_percent == 0 )
136         $portscan_percent_show = "&lt; 1";
137      else
138         $portscan_percent_show = $portscan_percent;
139   }
140   else
141   {
142      $portscan_percent = 0;
143      $portscan_percent_show = "0";
144   }
145
146   if ( $tcp_percent > 0 )   $color = "#FF0000";  else  $color="#CCCCCC";
147   $rem_percent=100-$tcp_percent;
148   echo '<TABLE WIDTH="100%" BORDER=0>
149         <TR><TD>TCP<A HREF="base_qry_main.php?new=1'.
150                           '&amp;layer4=TCP&amp;num_result_rows=-1&amp;sort_order=time_d&amp;submit='._QUERYDBP.'">
151                           ('.$tcp_percent_show.'%)</A></TD><TD></TD></TR></TABLE>
152                  <TABLE class="summarygraph" WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=0>
153                  <TR><TD ALIGN=CENTER BGCOLOR="'.$color.'" WIDTH="'.$tcp_percent.'%">&nbsp;</TD>';
154                      if ( $tcp_percent > 0 )  echo '<TD BGCOLOR="#CCCCCC" WIDTH="'.$rem_percent.'%">&nbsp;</TD>';
155		      echo '</TR></TABLE>';
156
157    if ( $udp_percent > 0 )   $color = "#FF0000";  else  $color="#CCCCCC";
158    $rem_percent=100-$udp_percent;
159    echo '<TABLE WIDTH="100%" BORDER=0>
160          <TR><TD>UDP<A HREF="base_qry_main.php?new=1'.
161                            '&amp;layer4=UDP&amp;num_result_rows=-1&amp;sort_order=time_d&amp;submit='._QUERYDBP.'">
162                            ('.$udp_percent_show.'%)</A></TD><TD></TD></TR></TABLE>
163                  <TABLE class="summarygraph" WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=0>
164                  <TR><TD ALIGN=CENTER BGCOLOR="'.$color.'" WIDTH="'.$udp_percent.'%">&nbsp;</TD>';
165                      if ( $udp_percent > 0 ) echo '<TD BGCOLOR="#CCCCCC" WIDTH="'.$rem_percent.'%">&nbsp;</TD>';
166		      echo '</TR></TABLE>';
167
168     if ( $icmp_percent > 0 )   $color = "#FF0000";  else  $color="#CCCCCC";
169     $rem_percent=100-$icmp_percent;
170     echo '<TABLE WIDTH="100%" BORDER=0>
171           <TR><TD>ICMP<A HREF="base_qry_main.php?new=1'.
172                              '&amp;layer4=ICMP&amp;num_result_rows=-1&amp;sort_order=time_d&amp;submit='._QUERYDBP.'">
173                              ('.$icmp_percent_show.'%)</A></TD><TD></TD></TR></TABLE>
174                  <TABLE class="summarygraph" WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=0>
175                  <TR><TD ALIGN=CENTER BGCOLOR="'.$color.'" WIDTH="'.$icmp_percent.'%">&nbsp;</TD>';
176                      if ( $icmp_percent > 0 ) echo '<TD BGCOLOR="#CCCCCC" WIDTH="'.$rem_percent.'%">&nbsp;</TD>';
177		      echo '</TR></TABLE>';
178
179     echo '<CENTER><HR NOSHADE WIDTH="70%"></CENTER>';
180
181     if ( $portscan_percent > 0 )   $color = "#FF0000";  else  $color="#CCCCCC";
182     $rem_percent=100-$portscan_percent;
183     echo '<TABLE WIDTH="100%" BORDER=0>
184           <TR><TD>'._PORTSCAN.'
185               <A HREF="base_qry_main.php?new=1'.
186'&amp;layer4=RawIP&amp;num_result_rows=-1&amp;sort_order=time_d&amp;submit='._QUERYDBP.'">('.$portscan_percent_show.'%)</A>
187                    </TD><TD></TD></TR></TABLE>
188                  <TABLE class="summarygraph" WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=0>
189                  <TR><TD ALIGN=CENTER BGCOLOR="'.$color.'" WIDTH="'.$portscan_percent.'%">&nbsp;</TD>';
190                      if ( $portscan_percent > 0 )  echo '<TD BGCOLOR="#CCCCCC" WIDTH="'.$rem_percent.'%">&nbsp;</TD>';
191		      echo '</TR></TABLE>';
192}
193
194function BuildIPFormVars($ipaddr)
195{
196    return ''.
197    '&amp;ip_addr%5B0%5D%5B0%5D=+&amp;ip_addr%5B0%5D%5B1%5D=ip_src&amp;ip_addr%5B0%5D%5B2%5D=%3D'.
198    '&amp;ip_addr%5B0%5D%5B3%5D='.$ipaddr.
199    '&amp;ip_addr%5B0%5D%5B8%5D=+&amp;ip_addr%5B0%5D%5B9%5D=OR'.
200    '&amp;ip_addr%5B1%5D%5B0%5D=+&amp;ip_addr%5B1%5D%5B1%5D=ip_dst&amp;ip_addr%5B1%5D%5B2%5D=%3D'.
201    '&amp;ip_addr%5B1%5D%5B3%5D='.$ipaddr.
202    '&amp;ip_addr%5B1%5D%5B8%5D=+&amp;ip_addr%5B1%5D%5B9%5D=+';
203}
204
205function BuildSrcIPFormVars($ipaddr)
206{
207    return ''.
208    '&amp;ip_addr%5B0%5D%5B0%5D=+&amp;ip_addr%5B0%5D%5B1%5D=ip_src&amp;ip_addr%5B0%5D%5B2%5D=%3D'.
209    '&amp;ip_addr%5B0%5D%5B3%5D='.$ipaddr.
210    '&amp;ip_addr%5B0%5D%5B8%5D=+&amp;ip_addr%5B0%5D%5B9%5D=+';
211}
212
213function BuildDstIPFormVars($ipaddr)
214{
215    return ''.
216    '&amp;ip_addr%5B0%5D%5B0%5D=+&amp;ip_addr%5B0%5D%5B1%5D=ip_dst&amp;ip_addr%5B0%5D%5B2%5D=%3D'.
217    '&amp;ip_addr%5B0%5D%5B3%5D='.$ipaddr.
218    '&amp;ip_addr%5B0%5D%5B8%5D=+&amp;ip_addr%5B0%5D%5B9%5D=+';
219}
220
221function BuildUniqueAddressLink($addr_type, $raw = "" )
222{
223   return '<A HREF="base_stat_uaddr.php?addr_type='.$addr_type.$raw.'">';
224}
225
226function BuildUniqueAlertLink($raw)
227{
228   return '<A HREF="base_stat_alerts.php'.$raw.'">';
229}
230
231function BuildAddressLink($ipaddr, $netmask)
232{
233   return '<A HREF="base_stat_ipaddr.php?ip='.rawurlencode($ipaddr).
234                                       '&amp;netmask='.$netmask.'">';
235}
236
237/* Adds another blank row to a given criteria element */
238function AddCriteriaFormRow ( &$submit, $submit_value, &$cnt, &$criteria_array, $max )
239{
240   $submit = $submit_value;
241
242  ++$cnt;
243  InitArray($criteria_array[$cnt-1], $max, 0, "");
244}
245
246function IPProto2str($ipproto_code)
247{
248   switch($ipproto_code)
249   {
250      case 0:
251          return "IP";
252      case 1:
253          return "ICMP";
254      case 2:
255          return "IGMP";
256      case 4:
257          return "IPIP tunnels";
258      case 6:
259          return "TCP";
260      case 8:
261          return "EGP";
262      case 12:
263          return "PUP";
264      case  17:
265          return "UDP";
266      case 22:
267          return "XNS UDP";
268      case 29:
269          return "SO TP Class 4";
270      case 41:
271          return "IPv6 header";
272      case 43:
273          return "IPv6 routing header";
274      case 44:
275          return "IPv6 fragmentation header";
276      case 46:
277          return "RSVP";
278      case 47:
279          return "GRE";
280      case 50:
281          return "IPSec ESP";
282      case 51:
283          return "IPSec AH";
284      case 58:
285          return "ICMPv6";
286      case 59:
287          return "IPv6 no next header";
288      case 60:
289          return "IPv6 destination options";
290      case 92:
291          return "MTP";
292      case 98:
293          return "Encapsulation header";
294      case 103:
295          return "PIM";
296      case 108:
297          return "COMP";
298      case 255:
299          return "Raw IP";
300      default:
301          return $ipproto_code;
302   }
303}
304
305function TCPOption2str($tcpopt_code)
306/* per RFC 1072, 1323, 1644 */
307{
308   switch($tcpopt_code)
309   {
310      case 2:                  /* TCPOPT_MAXSEG - maximum segment*/
311          return "(2) MSS";
312      case 0:                  /* TCPOPT_EOL */
313          return "(0) EOL";
314      case 1:                  /* TCPOPT_NOP */
315          return "(1) NOP";
316      case 3:                  /* TCPOPT_WSCALE (rfc1072)- window scale factor */
317          return "(3) WS";
318      case 5:                  /* TCPOPT_SACK (rfc1072)- selective ACK */
319          return "(5) SACK";
320      case 4:                  /* TCPOPT_SACKOK (rfc1072)- selective ACK OK */
321          return "(4) SACKOK";
322      case 6:                  /* TCPOPT_ECHO (rfc1072)- echo */
323          return "(6) Echo";
324      case 7:                  /* TCPOPT_ECHOREPLY (rfc1072)- echo reply */
325          return "(7) Echo Reply";
326      case 8:                  /* TCPOPT_TIMESTAMP (rfc1323)- timestamps */
327          return "(8) TS";
328      case 9:                  /* RFC1693 */
329          return "(9) Partial Order Connection Permitted";
330      case 10:                  /* RFC1693 */
331          return "(10) Partial Order Service Profile";
332      case 11:                 /* TCPOPT_CC (rfc1644)- CC options */
333          return "(11) CC";
334      case 12:                 /* TCPOPT_CCNEW (rfc1644)- CC options */
335          return "(12) CCNEW";
336      case 13:                 /* TCPOPT_CCECHO (rfc1644)- CC options */
337          return "(13) CCECHO";
338      case 14:                 /* RFC1146 */
339          return "(14) TCP Alternate Checksum Request";
340      case 15:                 /* RFC1146 */
341          return "(15) TCP Alternate Checksum Data";
342      case 16:
343          return "(16) Skeeter";
344      case 17:
345          return "(17) Bubba";
346      case 18:                 /* Subbu and Monroe */
347          return "(18) Trailer Checksum Option";
348      case 19:                 /* Subbu and Monroe */
349          return "(19) MD5 Signature";
350      case 20:                 /* Scott */
351          return "(20) SCPS Capabilities";
352      case 21:                /* Scott */
353          return "(21) Selective Negative Acknowledgements";
354      case 22:                /* Scott */
355          return "(22) Record Boundaries";
356      case 23:                /* Scott */
357          return "(23) Corruption Experienced";
358      case 24:                /* Sukonnik */
359          return "(24) SNAP";
360      case 25:
361          return "(25) Unassigned";
362      case 26:                /* Bellovin */
363          return "(26) TCP Compression Filter";
364      default:
365          return $tcpopt_code;
366   }
367}
368
369function IPOption2str($ipopt_code)
370{
371   switch($ipopt_code)
372   {
373      case 7:              /* IPOPT_RR */
374          return "RR";
375      case 0:              /* IPOPT_EOL */
376          return "EOL";
377      case 1:              /* IPOPT_NOP */
378          return "NOP";
379      case 0x44:           /* IPOPT_TS */
380          return "TS";
381      case 0x82:           /* IPOPT_SECURITY */
382          return "SEC";
383      case 0x83:           /* IPOPT_LSRR */
384          return "LSRR";
385      case 0x84:           /* IPOPT_LSRR_E */
386          return "LSRR_E";
387      case 0x88:           /* IPOPT_SATID */
388          return "SID";
389      case 0x89:           /* IPOPT_SSRR */
390          return "SSRR";
391  }
392}
393
394function ICMPType2str($icmp_type)
395{
396  switch ($icmp_type)
397  {
398      case 0:                             /* ICMP_ECHOREPLY */
399          return "Echo Reply";
400      case 3:                             /* ICMP_DEST_UNREACH */
401          return "Destination Unreachable";
402      case 4:                             /* ICMP_SOURCE_QUENCH */
403          return "Source Quench";
404      case 5:                             /* ICMP_REDIRECT */
405          return "Redirect";
406      case 8:                             /* ICMP_ECHO */
407          return "Echo Request";
408      case 9:
409          return "Router Advertisement";
410      case 10:
411          return "Router Solicitation";
412      case 11:                            /* ICMP_TIME_EXCEEDED */
413          return "Time Exceeded";
414      case 12:                            /* ICMP_PARAMETERPROB */
415          return "Parameter Problem";
416      case 13:                            /* ICMP_TIMESTAMP */
417          return "Timestamp Request";
418      case 14:                            /* ICMP_TIMESTAMPREPLY */
419          return "Timestamp Reply";
420      case 15:                            /* ICMP_INFO_REQUEST */
421          return "Information Request";
422      case 16:                            /* ICMP_INFO_REPLY */
423          return "Information Reply";
424      case 17:                            /* ICMP_ADDRESS */
425          return "Address Mask Request";
426      case 18:                            /* ICMP_ADDRESSREPLY */
427          return "Address Mask Reply";
428      case 19:
429          return "Reserved (security)";
430      case 20:
431          return "Reserved (robustness)";
432      case 21:
433          return "Reserved (robustness)";
434      case 22:
435          return "Reserved (robustness)";
436      case 23:
437          return "Reserved (robustness)";
438      case 24:
439          return "Reserved (robustness)";
440      case 25:
441          return "Reserved (robustness)";
442      case 26:
443          return "Reserved (robustness)";
444      case 27:
445          return "Reserved (robustness)";
446      case 28:
447          return "Reserved (robustness)";
448      case 29:
449          return "Reserved (robustness)";
450      case 30:
451          return "Traceroute";
452      case 31:
453          return "Datagram Conversion Error";
454      case 32:
455          return "Mobile Host Redirect";
456      case 33:
457          return "IPv6 Where-Are-You";
458      case 34:
459          return "IPv6 I-Am-Here";
460      case 35:
461          return "Mobile Registration Request";
462      case 36:
463          return "Mobile Registration Reply";
464      case 37:
465          return "Domain Name Request";
466      case 38:
467          return "Domain Name Reply";
468      case 39:
469          return "SKIP";
470      case 40:
471          return "Photuris";
472      default:
473          return $icmp_type;
474  }
475}
476
477function ICMPCode2str($icmp_type, $icmp_code)
478{
479  if ( $icmp_type == 3 )
480  {
481     switch ($icmp_code)
482     {
483        case 0:                                    /* ICMP_NET_UNREACH */
484            return "Network Unreachable";
485        case 1:                                    /* ICMP_HOST_UNREACH */
486            return "Host Unreachable";
487        case 2:                                    /* ICMP_PROT_UNREACH */
488            return "Protocol Unreachable";
489        case 3:                                    /* ICMP_PORT_UNREACH */
490            return "Port Unreachable";
491        case 4:                                    /* ICMP_FRAG_NEEDED */
492            return "Fragmentation Needed/DF set";
493        case 5:                                    /* ICMP_SR_FAILED */
494            return "Source Route failed";
495        case 6:                                    /* ICMP_NET_UNKNOWN */
496            return "Network Unknown";
497        case 7:                                    /* ICMP_HOST_UNKNOWN */
498            return "Host Unknown";
499        case 8:                                    /* ICMP_HOST_ISOLATED */
500            return "Host Isolated";
501        case 9:                                    /* ICMP_NET_ANO */
502            return "Network ANO";
503        case 10:                                   /* ICMP_HOST_ANO */
504            return "Host ANO";
505        case 11:                                   /* ICMP_NET_UNR_TOS */
506            return "Network Unreach TOS";
507        case 12:                                   /* ICMP_HOST_UNR_TOS */
508            return "Host Unreach TOS";
509        case 13:                                   /* ICMP_PKT_FILTERED */
510            return "Packet Filtered";
511        case 14:                                   /* ICMP_PREC_VIOLATION */
512            return "Precedence violation";
513        case 15:                                   /* ICMP_PREC_CUTOFF */
514            return "Precedence cut off";
515        default:
516            return $icmp_code;
517     }
518  }
519  elseif ( $icmp_type == 5 )
520  {
521     switch ($icmp_code)
522     {
523        case 0:
524            return "Redirect datagram for network/subnet";
525        case 1:
526            return "Redirect datagram for host";
527        case 2:
528            return "Redirect datagram for ToS and network";
529        case 3:
530            return "Redirect datagram for Tos and host";
531        default:
532            return $icmp_code;
533      }
534   }
535   elseif ( $icmp_type == 9 )
536   {
537      switch ($icmp_code)
538      {
539         case 0:
540             return "Normal router advertisement";
541         case 16:
542             return "Does not route common traffic";
543         default:
544             return $icmp_code;
545      }
546   }
547   elseif ( $icmp_type == 11 )
548   {
549      switch ($icmp_code)
550      {
551         case 0:
552             return "TTL exceeded in transit";
553         case 1:
554             return "Fragment reassembly time exceeded";
555         default:
556             return $icmp_code;
557      }
558   }
559   elseif ( $icmp_type == 12 )
560   {
561      switch ($icmp_code)
562      {
563         case 0:
564             return "Pointer indicates error";
565         case 1:
566             return "Missing a required option";
567         case 2:
568             return "Bad length";
569         default:
570             return $icmp_code;
571      }
572   }
573   elseif ( $icmp_type == 40 )
574   {
575      switch ($icmp_code)
576      {
577         case 0:
578            return "Bad SPI";
579         case 1:
580            return "Authentication failed";
581         case 2:
582            return "Decompression failed";
583         case 3:
584            return "Decryption failed";
585         case 4:
586            return "Need authentication";
587         case 5:
588            return "Need authorization";
589         default:
590             return $icmp_code;
591      }
592   }
593  else
594     return $icmp_code;
595}
596
597function PrintPayloadChar( $char, $output_type )
598{
599   if ( $char >= 32 && $char <= 127 )
600   {
601      if ( $output_type == 2 )
602         return chr($char);
603      else
604         return htmlspecialchars(chr($char));
605   }
606   else
607      return '.';
608}
609
610function PrintBase64PacketPayload ( $encoded_payload, $output_type )
611{
612     /* strip out the <CR> at the end of each block */
613     $encoded_payload = str_replace("\n", "", $encoded_payload);
614
615     $payload = base64_decode($encoded_payload);
616     $len = strlen($payload);
617     $s = " "._LENGTH." = ".strlen($payload)."\n";
618
619     for ($i = 0; $i < strlen($payload); $i++ )
620     {
621          if ( $i % 16 == 0 )
622          {
623             /* dump the ASCII characters */
624             if ( $i != 0 )
625             {
626                $s = $s.'  ';
627                for ($j = $i-16; $j < $i; $j++ )
628                   $s = $s.PrintPayloadChar(ord($payload[$j]), $output_type);
629             }
630             $s = $s.sprintf("\n%03x : ", $i);
631          }
632
633          $s = $s.sprintf("%s ", bin2hex($payload[$i]) );
634     }
635
636     /* print the remained of any ASCII chars */
637     if ( ($i % 16) != 0 )
638     {
639        for ( $j = 0; $j < 16 - ($i % 16); $j++)
640            $s = $s.'   ';
641
642        $s = $s.'  ';
643
644        for ( $j = $len - ($i % 16); $j < $len; $j++ )
645           $s = $s.PrintPayloadChar(ord($payload[$j]), $output_type);
646     } else {
647	$s = $s.'  ';
648	for ( $j = $len - 16; $j < $len && $j > 0; $j++ )
649           $s = $s.PrintPayloadChar(ord($payload[$j]), $output_type);
650     }
651
652     return $s;
653}
654
655function PrintAsciiPacketPayload ( $encoded_payload, $output_type )
656{
657   return wordwrap($encoded_payload, 70);
658}
659
660function PrintHexPacketPayload ( $encoded_payload, $output_type )
661{
662     /* strip out the <CR> at the end of each block */
663     $encoded_payload = str_replace("\n", "", $encoded_payload);
664     $payload = $encoded_payload;
665
666     $len = strlen($payload);
667     $s = " "._LENGTH." = ".(strlen($payload)/2)."\n";
668
669     for ($i = 0; $i < strlen($payload); $i += 2 )
670     {
671          if ( $i % 32 == 0 )
672          {
673             /* dump the ASCII characters */
674             if ( $i != 0 )
675             {
676                $s = $s.'  ';
677                for ($j = $i-32; $j < $i; $j+=2 )
678                {
679                    $t = hexdec($payload[$j].$payload[$j+1]);
680                    $s = $s.PrintPayloadChar($t, $output_type);
681                }
682             }
683             $s = $s.sprintf("\n%03x : ", $i/2);
684          }
685          $s = $s.sprintf("%s%s ", $payload[$i], $payload[$i+1] );
686     }
687
688     /* space through to align end of hex dump */
689     if ( $i % 32 )
690        for ( $j = 0; $j < 32 - ($i % 32); $j+=2)
691           $s = $s.'   ';
692
693     $s = $s.'  ';
694
695     /* print the ASCII decode */
696     if ( $i % 32 )
697        $start = $len - ($i % 32);
698     else
699        $start = $len - 32;
700
701     for ( $j = $start; $j < $i; $j+=2 )
702     {
703        $t = hexdec($payload[$j].$payload[$j+1]);
704        $s = $s.PrintPayloadChar($t, $output_type);
705     }
706
707     return $s;
708}
709
710// ************************************************************************************
711function PrintCleanHexPacketPayload( $encoded_payload, $output_type )
712{
713     $len = strlen($encoded_payload);
714     $s = '';
715     $count = 0;
716     for ($i = 0; $i < $len; $i += 2 )
717     {
718         /* dump the ASCII characters */
719         $t = hexdec($encoded_payload[$i].$encoded_payload[$i+1]);
720         $s_tmp = PrintCleanPayloadChar($t, $output_type);
721
722         /* Join together several sequential non-ASCII characters displaying their count
723          * in one line. It makes easyer to look through payload in plain display mode.
724          * If current character is '<br>' and this is not last character of payload
725          * increment counter, else output non-ASCII count and flush counter.
726          */
727         if ( ($s_tmp == '<br>') && !($i+2 == $len) ) {
728             $count++;
729         } else {
730             if ($count > 1)
731                 $s .= '<DIV class="nonascii">['. $count .' non-ASCII characters]</DIV>';
732             elseif ($count == 1)
733                 $s .= '<br>';
734             $s .= $s_tmp;
735             $count = 0;
736         }
737     }
738     return $s;
739}
740
741function PrintCleanPayloadChar( $char, $output_type )
742{
743   if ( $char >= 32 && $char <= 127 )
744   {
745      if ( $output_type == 2 )
746         return chr($char);
747      else
748         return htmlspecialchars(chr($char));
749   }
750   else
751      return '<br>';
752}
753
754// ************************************************************************************
755
756function PrintPacketPayload($data, $encode_type, $output_type)
757{
758     if ( $output_type == 1 )
759        printf("\n<PRE>\n");
760
761     /* print the packet based on encoding type */;
762     if ( $encode_type == "1" )
763         $payload = PrintBase64PacketPayload($data, $output_type);
764     else if ($encode_type == "0" )
765     {
766         if ( isset($_GET['asciiclean']) && ($_GET['asciiclean'] == 1) || ( (isset($_COOKIE['asciiclean']) && $_COOKIE['asciiclean'] == "clean") && (!isset($_GET['asciiclean'])) ) )
767	 {
768	    // Print clean ascii display
769            $payload = PrintCleanHexPacketPayload($data, $output_type);
770	 }
771	 else
772	 {
773	    $payload = PrintHexPacketPayload($data, $output_type);
774	 }
775     }
776     else if ($encode_type == "2" )
777         $payload = PrintAsciiPacketPayload($data, $output_type);
778
779     if ( $output_type == 1 )
780        echo "$payload\n</PRE>\n";
781
782     return $payload;
783}
784
785function GetQueryResultID($submit, &$seq, &$sid, &$cid)
786{
787  /* extract the sid and cid from the $submit variable of the form
788     #XX-(XX-XX)
789      |   |  |
790      |   |  |--- cid
791      |   |------ sid
792      |---------- sequence number of DB lookup
793  */
794
795  $submit = strstr($submit, "#");
796  $submit = str_replace("#", "", $submit);
797  $submit = str_replace("(", "", $submit);
798  $submit = str_replace(")", "", $submit);
799  $tmp = explode("-", $submit);
800  /* Since the submit variable is not cleaned do so here: */
801  $seq = CleanVariable($tmp[0], VAR_DIGIT);
802  $sid = CleanVariable($tmp[1], VAR_DIGIT);
803  $cid = CleanVariable($tmp[2], VAR_DIGIT);
804}
805
806function ExportPacket($sid, $cid, $db)
807{
808  GLOBAL $action, $action_arg;
809
810  /* Event */
811  $sql2 = "SELECT signature, timestamp FROM acid_event WHERE sid='".$sid."' AND cid='".$cid."'";
812  $result2 = $db->baseExecute($sql2);
813  $myrow2 = $result2->baseFetchRow();
814
815  $s = "------------------------------------------------------------------------------\n";
816  $s = $s."#($sid - $cid) [$myrow2[1]] ".BuildSigByID($myrow2[0], $db, 2)."\r\n";
817
818  $sql4 = "SELECT hostname, interface, filter FROM sensor  WHERE sid='".$sid."'";
819  $result4 = $db->baseExecute($sql4);
820  $myrow4 = $result4->baseFetchRow();
821
822  $result4->baseFreeRows();
823  $result2->baseFreeRows();
824
825  /* IP */
826  $sql2 = "SELECT ip_src, ip_dst, ".
827          "ip_ver, ip_hlen, ip_tos, ip_len, ip_id, ip_flags, ip_off, ip_ttl, ip_csum, ip_proto".
828          " FROM iphdr  WHERE sid='".$sid."' AND cid='".$cid."'";
829
830  $result2 = $db->baseExecute($sql2);
831  $myrow2 = $result2->baseFetchRow();
832  $layer4_proto = $myrow2[11];
833
834  if ( $myrow2[0] != "" )
835  {
836    $sql3 = "SELECT * FROM opt  WHERE sid='".$sid."' AND cid='".$cid."' AND opt_proto='0'";
837    $result3 = $db->baseExecute($sql3);
838    $num_opt = $result3->baseRecordCount();
839
840    $s = $s."IPv$myrow2[2]: ".
841          baseLong2IP($myrow2[0])." -> ".
842          baseLong2IP($myrow2[1])."\n".
843          "      hlen=$myrow2[3] TOS=$myrow2[4] dlen=$myrow2[5] ID=$myrow2[6]".
844          " flags=$myrow2[7] offset=$myrow2[8] TTL=$myrow2[9] chksum=$myrow2[10]\n";
845
846    if ( $num_opt > 0 )
847    {
848      $s = $s."    Options\n";
849      for ( $i = 0; $i < $num_opt; $i++)
850      {
851         $myrow3 = $result3->baseFetchRow();
852         $s = $s."      #".($i+1)." - ".IPOption2str($myrow3[4])." len=$myrow3[5]";
853         if ( $myrow3[5] != 0 )
854            $s = $s." data=$myrow3[6]";
855         $s = $s."\n";
856       }
857    }
858
859    $result3->baseFreeRows();
860  }
861  $result2->baseFreeRows();
862
863  /* TCP */
864  if ( $layer4_proto == "6" )
865  {
866     $sql2 = "SELECT tcp_sport, tcp_dport, tcp_seq, tcp_ack, tcp_off, tcp_res, tcp_flags, tcp_win, ".
867             "       tcp_csum, tcp_urp FROM tcphdr  WHERE sid='".$sid."' AND cid='".$cid."'";
868     $result2 = $db->baseExecute($sql2);
869     $myrow2 = $result2->baseFetchRow();
870
871     $sql3 = "SELECT * FROM opt  WHERE sid='".$sid."' AND cid='".$cid."' AND opt_proto='6'";
872     $result3 = $db->baseExecute($sql3);
873     $num_opt = $result3->baseRecordCount();
874
875     $s = $s."TCP:  port=$myrow2[0] -> dport: $myrow2[1]  flags=";
876
877      if ( ($myrow2[6] & 128) != 0 )  $s = $s.'2';  else $s = $s.'*';
878      if ( ($myrow2[6] & 64 ) != 0 )  $s = $s.'1';  else $s = $s.'*';
879      if ( ($myrow2[6] & 32) != 0  )  $s = $s.'U';  else $s = $s.'*';
880      if ( ($myrow2[6] & 16 ) != 0 )  $s = $s.'A';  else $s = $s.'*';
881      if ( ($myrow2[6] & 8) != 0   )  $s = $s.'P';  else $s = $s.'*';
882      if ( ($myrow2[6] & 4 ) != 0  )  $s = $s.'R';  else $s = $s.'*';
883      if ( ($myrow2[6] & 2 ) != 0  )  $s = $s.'S';  else $s = $s.'*';
884      if ( ($myrow2[6] & 1 ) != 0  )  $s = $s.'F';  else $s = $s.'*';
885
886      $s = $s." seq=$myrow2[2]\n".
887              "      ack=$myrow2[3] off=$myrow2[4] res=$myrow2[5] win=$myrow2[7] urp=$myrow2[9] ".
888              "chksum=$myrow2[8]\n";
889
890      if ( $num_opt != 0)
891      {
892         $s = $s."      Options:\n";
893         for ( $i = 0; $i < $num_opt; $i++)
894         {
895             $myrow3 = $result3->baseFetchRow();
896             $s = $s."       #".($i+1)." - ".TCPOption2str($myrow3[4])." len=$myrow3[5]";
897             if ( $myrow3[5] != 0 )
898                $s = $s." data=".$myrow3[6];
899            $s = $s."\n";
900         }
901      }
902
903      $result2->baseFreeRows();
904      $result3->baseFreeRows();
905  }
906
907  /* UDP */
908  if ( $layer4_proto == "17" )
909  {
910
911     $sql2 = "SELECT * FROM udphdr  WHERE sid='".$sid."' AND cid='".$cid."'";
912     $result2 = $db->baseExecute($sql2);
913     $myrow2 = $result2->baseFetchRow();
914
915     $s = $s."UDP:  port=$myrow2[2] -> dport: $myrow2[3] len=$myrow2[4]\n";
916
917     $result2->baseFreeRows();
918  }
919
920  /* ICMP */
921  if ( $layer4_proto == "1" )
922  {
923     $sql2 = "SELECT icmp_type, icmp_code, icmp_csum, icmp_id, icmp_seq FROM icmphdr ".
924             "WHERE sid='".$sid."' AND cid='".$cid."'";
925     $result2 = $db->baseExecute($sql2);
926     $myrow2 = $result2->baseFetchRow();
927
928     $s = $s."ICMP: type=".ICMPType2str($myrow2[0])." code=".ICMPCode2str($myrow2[0],$myrow2[1])."\n".
929             "      checksum=$myrow2[2] id=$myrow2[3] seq=$myrow2[4]\n";
930
931     $result2->baseFreeRows();
932  }
933
934  /* Print the Payload */
935  $sql2 = "SELECT data_payload FROM data WHERE sid='".$sid."' AND cid='".$cid."'";
936  $result2 = $db->baseExecute($sql2);
937
938  /* get encoding information and detail_level on the payload */
939  $sql3 = 'SELECT encoding, detail FROM sensor WHERE sid='.$sid;
940  $result3 = $db->baseExecute($sql3);
941  $myrow3 = $result3->baseFetchRow();
942
943  $s = $s."Payload: ";
944
945  $myrow2 = $result2->baseFetchRow();
946  if ( $myrow2 )
947  {
948     /* print the packet based on encoding type */
949     $s = $s.PrintPacketPayload($myrow2[0], $myrow3[0], 2)."\n";
950
951     $result3->baseFreeRows();
952  }
953  else
954  {
955     /* Don't have payload so lets print out why by checking the detail level */
956
957     /* if have fast detail level */
958     if ( $myrow3[1] == "0" )
959        $s = $s."Fast logging used so payload was discarded\n";
960     else
961        $s = $s."none\n";
962  }
963
964  $result2->baseFreeRows();
965
966  return $s;
967}
968
969function ExportPacket_summary($sid, $cid, $db, $export_type = 0)
970{
971  GLOBAL $action, $action_arg;
972
973  /* Event */
974  $sql2 = "SELECT signature, timestamp FROM acid_event WHERE sid='".$sid."' AND cid='".$cid."'";
975  $result2 = $db->baseExecute($sql2);
976  $myrow2 = $result2->baseFetchRow();
977
978  $alert_timestamp = $myrow2[1];
979  $alert_sig = BuildSigByID($myrow2[0], $db, 2);
980
981  $result2->baseFreeRows();
982
983  /* IP */
984  $src_ip = $dst_ip = $src_port = $dst_port = "";
985  $sql2 = "SELECT ip_src, ip_dst, ip_proto".
986          " FROM iphdr  WHERE sid='".$sid."' AND cid='".$cid."'";
987
988  $result2 = $db->baseExecute($sql2);
989  $myrow2 = $result2->baseFetchRow();
990
991  $layer4_proto = "";
992  if ( $myrow2[0] != "" )
993  {
994     $src_ip = baseLong2IP($myrow2[0]);
995     $dst_ip = baseLong2IP($myrow2[1]);
996     $layer4_proto = $myrow2[2];
997  }
998  $result2->baseFreeRows();
999
1000  /* TCP */
1001  if ( $layer4_proto == "6" )
1002  {
1003     $sql2 = "SELECT tcp_sport, tcp_dport FROM tcphdr  WHERE sid='".$sid."' AND cid='".$cid."'";
1004     $result2 = $db->baseExecute($sql2);
1005     $myrow2 = $result2->baseFetchRow();
1006
1007     if ( $export_type == 0 )
1008     {
1009        $src_port = ":".$myrow2[0]." -> ";
1010        $dst_port = ":".$myrow2[1];
1011     }
1012     else
1013     {
1014        $src_port = $myrow2[0];
1015        $dst_port = $myrow2[1];
1016     }
1017
1018     $result2->baseFreeRows();
1019  }
1020
1021  /* UDP */
1022  if ( $layer4_proto == "17" )
1023  {
1024
1025     $sql2 = "SELECT * FROM udphdr  WHERE sid='".$sid."' AND cid='".$cid."'";
1026     $result2 = $db->baseExecute($sql2);
1027     $myrow2 = $result2->baseFetchRow();
1028
1029     if ( $export_type == 0 )
1030     {
1031       $src_port = ":".$myrow2[2]." -> ";
1032       $dst_port = ":".$myrow2[3];
1033     }
1034     else
1035     {
1036       $src_port = $myrow2[2];
1037       $dst_port = $myrow2[3];
1038     }
1039
1040     $result2->baseFreeRows();
1041  }
1042
1043  /* ICMP */
1044  if ( $layer4_proto == "1" )
1045  {
1046     if ( $export_type == 0 )
1047       $src_ip = $src_ip." -> ";
1048     $src_port = $dst_port = "";
1049  }
1050
1051 /* Portscan Traffic */
1052   if ( $layer4_proto == "255" )
1053   {
1054      if ( $export_type == 0 )
1055         $src_ip = $src_ip." -> ";
1056   }
1057
1058  if ( $export_type == 0 )
1059  {
1060    $s = sprintf("#%d-%d| [%s] %s%s%s%s %s\r\n",
1061                 $sid, $cid, $alert_timestamp,
1062                 $src_ip, $src_port, $dst_ip, $dst_port,
1063                 $alert_sig);
1064  }
1065  else /* CSV format */
1066  {
1067    $s = sprintf("\"%d\", \"%d\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"\r\n",
1068                 $sid, $cid, $alert_timestamp,
1069                 $src_ip, $src_port, $dst_ip, $dst_port,
1070                 $alert_sig);
1071  }
1072
1073  return $s;
1074}
1075
1076function base_header($url) {
1077    header($url);
1078    exit;
1079}
1080
1081
1082function base_microtime()
1083{
1084  list($usec, $sec) = explode(" ", microtime());
1085  return ((float)$usec + (float)$sec);
1086}
1087