Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

portscan.c

Go to the documentation of this file.
00001 /*
00002 **  @file       portscan.c
00003 **
00004 **  @author     Daniel Roelker <droelker@sourcefire.com>
00005 **
00006 **  @brief      Detect portscans
00007 **
00008 **  NOTES
00009 **    - Marc Norton and Jeremy Hewlett were involved in the requirements and
00010 **      design of this portscan detection engine.
00011 **    - Thanks to Judy Novak for her suggestion to log open ports
00012 **      on hosts that are portscanned.  This idea makes portscan a lot more
00013 **      useful for analysts.
00014 **
00015 **  The philosophy of portscan detection that we use is based on a generic
00016 **  network attack methodology: reconnaissance, network service enumeration,
00017 **  and service exploitation.
00018 **
00019 **  The reconnaissance phase determines what types of network protocols and
00020 **  services that a host supports.  This is the traditional phase where a
00021 **  portscan occurs.  An important requirement of this phase is that an
00022 **  attacker does not already know what protocols and services are supported
00023 **  by the destination host.  If an attacker does know what services are
00024 **  open on the destination host then there is no need for this phase.
00025 **  Because of this requirement, we assume that if an attacker engages in this
00026 **  phase that they do not have prior knowledege to what services are open.
00027 **  So, the attacker will need to query the ports or protocols they are
00028 **  interested in.  Most or at least some of these queries will be negative
00029 **  and take the form of either an invalid response (TCP RSTs, ICMP
00030 **  unreachables) or no response (in which case the host is firewalled or
00031 **  filtered).  We detect portscans from these negative queries.
00032 **  
00033 **  The primary goal of this portscan detection engine is to catch nmap and
00034 **  variant scanners.  The engine tracks connection attempts on TCP, UDP,
00035 **  ICMP, and IP Protocols.  If there is a valid response, the connection
00036 **  is marked as valid.  If there is no response or a invalid response
00037 **  (TCP RST), then we track these attempts separately, so we know the
00038 **  number of invalid responses and the number of connection attempts that
00039 **  generated no response.  These two values differentiate between a
00040 **  normal scan and a filtered scan.
00041 **
00042 **  We detect four different scan types, and each scan type has its own
00043 **  negative query characteristics.  This is how we determine what type
00044 **  of scan we are seeing.  The different scans are:
00045 **
00046 **    - Portscan
00047 **    - Decoy Portscan
00048 **    - Distributed Portscan
00049 **    - Portsweep
00050 **
00051 **  Portscan:  A portscan is a basic one host to one host scan where
00052 **  multiple ports are scanned on the destination host.  We detect these
00053 **  scans by looking for a low number of hosts that contacted the
00054 **  destination host and a high number of unique ports and a high number
00055 **  of invalid responses or connections.
00056 **
00057 **  Distributed Portscan:  A distributed portscan occurs when many hosts
00058 **  connect to a single destination host and multiple ports are scanned
00059 **  on the destination host.  We detect these scans by looking for a high
00060 **  number of hosts that contacted the destination host and a high number
00061 **  of unique ports with a high number of invalid responses or connections.
00062 **
00063 **  Decoy Portscan:  A decoy portscan is a variation on a distributed
00064 **  portscan, the difference being that a decoy portscan connects to a
00065 **  single port multiple times.  This shows up in the unqiue port count that
00066 **  is tracked.  There's still many hosts connecting to the destination host.
00067 **
00068 **  Portsweep:  A portsweep is a basic one host to many host scan where
00069 **  one to a few ports are scanned on each host.  We detect these scans by
00070 **  looking at src hosts for a high number of contacted hosts and a low
00071 **  number of unique ports with a high number of invalid responses or
00072 **  connections.
00073 **
00074 **  Each of these scans can also be detected as a filtered portscan, or a
00075 **  portscan where there wasn't invalid responses and the responses have
00076 **  been firewalled in some way.
00077 ** 
00078 */
00079 #include <stdlib.h>
00080 #include <string.h>
00081 #include <sys/types.h>
00082 #ifndef WIN32
00083     #include <sys/socket.h>
00084     #include <netinet/in.h>
00085     #include <arpa/inet.h>
00086 #endif /* !WIN32 */
00087 
00088 #include "portscan.h"
00089 #include "decode.h"
00090 #include "packet_time.h"
00091 #include "sfxhash.h"
00092 #include "ipobj.h"
00093 #include "flow.h"
00094 
00095 typedef struct s_PS_INIT
00096 {
00097     int detect_scans;
00098     int detect_scan_type;
00099     int sense_level;
00100     int proto_cnt;
00101     IPSET *ignore_scanners;
00102     IPSET *ignore_scanned;
00103     IPSET *watch_ip;
00104 
00105 } PS_INIT;
00106 
00107 typedef struct s_PS_HASH_KEY
00108 {
00109     unsigned long scanner;
00110     unsigned long scanned;
00111 
00112 } PS_HASH_KEY;
00113 
00114 typedef struct s_PS_ALERT_CONF
00115 {
00116     short connection_count;
00117     short priority_count;
00118     short u_ip_count;
00119     short u_port_count;
00120 
00121 } PS_ALERT_CONF;
00122 
00123 static int      g_ps_tracker_size;
00124 static PS_INIT  g_ps_init;
00125 static SFXHASH *g_hash;
00126 
00127 extern int g_include_midstream;
00128 
00129 /*
00130 **  Scanning configurations.  This is where we configure what the thresholds
00131 **  are for the different types of scans, protocols, and sense levels.  If
00132 **  you want to tweak the sense levels, change the values here.
00133 */
00134 /*
00135 **  TCP alert configurations
00136 */
00137 static PS_ALERT_CONF g_tcp_low_ps =       {0,5,25,5};
00138 static PS_ALERT_CONF g_tcp_low_decoy_ps = {0,15,50,30};
00139 static PS_ALERT_CONF g_tcp_low_sweep =    {0,5,5,15};
00140 static PS_ALERT_CONF g_tcp_low_dist_ps =  {0,15,50,15};
00141 
00142 static PS_ALERT_CONF g_tcp_med_ps =       {200,10,60,15};
00143 static PS_ALERT_CONF g_tcp_med_decoy_ps = {200,30,120,60};
00144 static PS_ALERT_CONF g_tcp_med_sweep =    {30,7,7,10};
00145 static PS_ALERT_CONF g_tcp_med_dist_ps =  {200,30,120,30};
00146 
00147 static PS_ALERT_CONF g_tcp_hi_ps =        {200,5,100,10};
00148 static PS_ALERT_CONF g_tcp_hi_decoy_ps =  {200,7,200,60};
00149 static PS_ALERT_CONF g_tcp_hi_sweep =     {30,3,3,10};
00150 static PS_ALERT_CONF g_tcp_hi_dist_ps =   {200,5,200,10};
00151 
00152 /*
00153 **  UDP alert configurations
00154 */
00155 static PS_ALERT_CONF g_udp_low_ps =       {0,5,25,5};
00156 static PS_ALERT_CONF g_udp_low_decoy_ps = {0,15,50,30};
00157 static PS_ALERT_CONF g_udp_low_sweep =    {0,5,5,15};
00158 static PS_ALERT_CONF g_udp_low_dist_ps =  {0,15,50,15};
00159 
00160 static PS_ALERT_CONF g_udp_med_ps =       {200,10,60,15};
00161 static PS_ALERT_CONF g_udp_med_decoy_ps = {200,30,120,60};
00162 static PS_ALERT_CONF g_udp_med_sweep =    {30,5,5,20};
00163 static PS_ALERT_CONF g_udp_med_dist_ps =  {200,30,120,30};
00164 
00165 static PS_ALERT_CONF g_udp_hi_ps =        {200,3,100,10};
00166 static PS_ALERT_CONF g_udp_hi_decoy_ps =  {200,7,200,60};
00167 static PS_ALERT_CONF g_udp_hi_sweep =     {30,3,3,10};
00168 static PS_ALERT_CONF g_udp_hi_dist_ps =   {200,3,200,10};
00169 
00170 /*
00171 **  IP Protocol alert configurations
00172 */
00173 static PS_ALERT_CONF g_ip_low_ps =        {0,10,10,50};
00174 static PS_ALERT_CONF g_ip_low_decoy_ps =  {0,40,50,25};
00175 static PS_ALERT_CONF g_ip_low_sweep =     {0,10,10,10};
00176 static PS_ALERT_CONF g_ip_low_dist_ps =   {0,15,25,50};
00177 
00178 static PS_ALERT_CONF g_ip_med_ps =        {200,10,10,50};
00179 static PS_ALERT_CONF g_ip_med_decoy_ps =  {200,40,50,25};
00180 static PS_ALERT_CONF g_ip_med_sweep =     {30,10,10,10};
00181 static PS_ALERT_CONF g_ip_med_dist_ps =   {200,15,25,50};
00182 
00183 static PS_ALERT_CONF g_ip_hi_ps =         {200,3,3,10};
00184 static PS_ALERT_CONF g_ip_hi_decoy_ps =   {200,7,15,5};
00185 static PS_ALERT_CONF g_ip_hi_sweep =      {30,3,3,7};
00186 static PS_ALERT_CONF g_ip_hi_dist_ps =    {200,3,11,10};
00187 
00188 /*
00189 **  ICMP alert configurations
00190 */
00191 static PS_ALERT_CONF g_icmp_low_sweep =   {0,5,5,5};
00192 static PS_ALERT_CONF g_icmp_med_sweep =   {20,5,5,5};
00193 static PS_ALERT_CONF g_icmp_hi_sweep =    {10,3,3,5};
00194 
00195 /*
00196 **  NAME
00197 **    ps_tracker_free::
00198 */
00199 /**
00200 **  This function is passed into the hash algorithm, so that
00201 **  we only reuse nodes that aren't priority nodes.  We have to make
00202 **  sure that we only track so many priority nodes, otherwise we could
00203 **  have all priority nodes and not be able to allocate more.
00204 */
00205 static int ps_tracker_free(void *key, void *data)
00206 {
00207     PS_TRACKER *tracker;
00208     int         iCtr;
00209     time_t      pkt_time;
00210 
00211     if(!key || !data)
00212         return 0;
00213 
00214     tracker = (PS_TRACKER *)data;
00215     if(!tracker->priority_node)
00216         return 0;
00217 
00218     /*
00219     **  Cycle through the protos to see if it's past the time.
00220     **  We only get here if we ARE a priority node.
00221     */
00222     pkt_time = packet_timeofday();
00223     for(iCtr = 0; iCtr < g_ps_init.proto_cnt; iCtr++)
00224     {
00225         if(tracker->proto[iCtr].window >= pkt_time)
00226             return 1;
00227     }
00228 
00229     return 0;
00230 }
00231 
00232 /*
00233 **  NAME
00234 **    ps_init::
00235 */
00236 /*
00237 **  Initialize the portscan infrastructure.  We check to make sure that
00238 **  we have enough memory to support at least 100 nodes.
00239 ** 
00240 **  @return int
00241 **  
00242 **  @retval -2 memcap is too low
00243 */
00244 int ps_init(int detect_scans, int detect_scan_type, int sense_level,
00245         IPSET *scanner, IPSET *scanned, IPSET *watch, int memcap)
00246 {
00247     int proto_cnt = 0;
00248     int datasize;
00249 
00250     proto_cnt += ((detect_scans & PS_PROTO_TCP)  ? 1 : 0);
00251     proto_cnt += ((detect_scans & PS_PROTO_UDP)  ? 1 : 0);
00252     proto_cnt += ((detect_scans & PS_PROTO_ICMP) ? 1 : 0);
00253     proto_cnt += ((detect_scans & PS_PROTO_IP)   ? 1 : 0);
00254 
00255     if(!proto_cnt)
00256         return -1;
00257 
00258    if(!(detect_scan_type & PS_TYPE_ALL)) 
00259        return -1;
00260 
00261    if(sense_level < 1 || sense_level > 3)
00262        return -1;
00263 
00264    /*
00265    **  Set the datasize that the hash will be keeping track of.  This
00266    **  changes dynamically based on the number of protocols that we are
00267    **  tracking.
00268    */
00269    datasize = sizeof(PS_TRACKER) + (sizeof(PS_PROTO)*(proto_cnt - 1));
00270 
00271    if(memcap <= 0 || memcap < (datasize * 100))
00272        return -2;
00273 
00274    g_hash = sfxhash_new(50000, sizeof(PS_HASH_KEY), datasize, 
00275            memcap, 1, ps_tracker_free, NULL, 1);
00276 
00277    if(!g_hash)
00278        return -1;
00279 
00280    g_ps_init.detect_scans     = detect_scans;
00281    g_ps_init.detect_scan_type = detect_scan_type;
00282    g_ps_init.sense_level      = sense_level;
00283    g_ps_init.ignore_scanners  = scanner;
00284    g_ps_init.ignore_scanned   = scanned;
00285    g_ps_init.watch_ip         = watch;
00286 
00287    g_ps_tracker_size = datasize;
00288 
00289    return 0;
00290 }
00291 
00292 /*
00293 **  NAME
00294 **    ps_ignore_ip::
00295 */
00296 /**
00297 **  Check scanner and scanned ips to see if we can filter them out.
00298 */
00299 static int ps_ignore_ip(unsigned long scanner, unsigned long scanned)
00300 {
00301     if(g_ps_init.ignore_scanners)
00302     {
00303         if(ipset_contains(g_ps_init.ignore_scanners, &scanner, IPV4_FAMILY))
00304             return 1;
00305     }
00306 
00307     if(g_ps_init.ignore_scanned)
00308     {
00309         if(ipset_contains(g_ps_init.ignore_scanned, &scanned, IPV4_FAMILY))
00310             return 1;
00311     }
00312 
00313     return 0;
00314 }
00315 
00316 /*
00317 **  NAME
00318 **    ps_filter_ignore::
00319 */
00320 /**
00321 **  Check the incoming packet to decide whether portscan detection cares
00322 **  about this packet.  We try to ignore as many packets as possible.
00323 */
00324 static int ps_filter_ignore(PS_PKT *ps_pkt)
00325 {
00326     Packet  *p;
00327     FLOW    *flow;
00328     int      reverse_pkt = 0;
00329     unsigned long scanner;
00330     unsigned long scanned;
00331 
00332     p = (Packet *)ps_pkt->pkt;
00333 
00334     if(!p->iph)
00335         return 1;
00336 
00337     if(p->tcph)
00338     {
00339         if(!g_ps_init.detect_scans & PS_PROTO_TCP)
00340             return 1;
00341    
00342         /*
00343         **  This is where we check all of snort's flags for different
00344         **  TCP session scenarios.  The checks cover:
00345         **
00346         **    - dropping packets in established sessions, but not the
00347         **      TWH packet.
00348         **    - dropping the SYN/ACK packet from the server on a valid
00349         **      connection (we'll catch the TWH later if it happens).
00350         */
00351         /*
00352         **  Ignore packets that are already part of an established TCP
00353         **  stream. 
00354         */
00355         if(((p->packet_flags & (PKT_STREAM_EST | PKT_STREAM_TWH)) 
00356                 == PKT_STREAM_EST) && !(p->tcph->th_flags & TH_RST))
00357         {
00358             return 1;
00359         }
00360 
00361         /*
00362         **  Ignore the server's initial response, unless it's to RST
00363         **  the connection.
00364         */
00365         /*
00366         if(!(p->tcph->th_flags & TH_RST) &&
00367            !(p->packet_flags & (PKT_STREAM_EST)) &&
00368             (p->packet_flags & PKT_FROM_SERVER))
00369         {
00370             return 1;
00371         }
00372         */
00373     }
00374     else if(p->udph)
00375     {
00376         if(!g_ps_init.detect_scans & PS_PROTO_UDP)
00377             return 1;
00378     }
00379     else if(p->icmph)
00380     {
00381         if(p->icmph->type != ICMP_DEST_UNREACH &&
00382            !g_ps_init.detect_scans & PS_PROTO_ICMP)
00383         {
00384             return 1;
00385         }
00386     }
00387     else
00388     {
00389         if(!g_ps_init.detect_scans & PS_PROTO_IP)
00390             return 1;
00391     }
00392 
00393     /*
00394     **  Check if the packet is reversed
00395     */
00396     if((p->packet_flags & PKT_FROM_SERVER))
00397     {
00398         reverse_pkt = 1;
00399     }
00400     else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH)
00401     {
00402         reverse_pkt = 1;
00403     }
00404     else if((p->udph || p->iph) && p->flow)
00405     {
00406         flow = (FLOW *)p->flow;
00407         if(flow->stats.direction == FROM_RESPONDER)
00408             reverse_pkt = 1;
00409     }
00410 
00411     scanner = ntohl(p->iph->ip_src.s_addr);
00412     scanned = ntohl(p->iph->ip_dst.s_addr);
00413     
00414     if(reverse_pkt)
00415     {
00416         if(ps_ignore_ip(scanned, scanner))
00417             return 1;
00418     }
00419     else
00420     {
00421         if(ps_ignore_ip(scanner, scanned))
00422             return 1;
00423     }
00424     
00425     ps_pkt->reverse_pkt = reverse_pkt;
00426 
00427     if(g_ps_init.watch_ip)
00428     {
00429         if(ipset_contains(g_ps_init.watch_ip, &scanner, IPV4_FAMILY))
00430             return 0;
00431 
00432         if(ipset_contains(g_ps_init.watch_ip, &scanned, IPV4_FAMILY))
00433             return 0;
00434 
00435         return 1;
00436     }
00437 
00438     return 0;
00439 }
00440 
00441 /*
00442 **  NAME
00443 **    ps_tracker_init::
00444 */
00445 /**
00446 **  Right now all we do is memset, but just in case we want to do more
00447 **  initialization has been extracted.
00448 */
00449 static int ps_tracker_init(PS_TRACKER *tracker)
00450 {
00451     memset(tracker, 0x00, g_ps_tracker_size);
00452 
00453     return 0;
00454 }
00455 
00456 /*
00457 **  NAME
00458 **    ps_tracker_get::
00459 */
00460 /**
00461 **  Get a tracker node by either finding one or starting a new one.  We may
00462 **  return NULL, in which case we wait till the next packet.
00463 */
00464 static int ps_tracker_get(PS_TRACKER **ht, PS_HASH_KEY *key)
00465 {
00466     int iRet;
00467 
00468     *ht = (PS_TRACKER *)sfxhash_find(g_hash, (void *)key);
00469     if(!(*ht))
00470     {
00471         iRet = sfxhash_add(g_hash, (void *)key, NULL);
00472         if(iRet == SFXHASH_OK)
00473         {
00474             *ht = (PS_TRACKER *)sfxhash_mru(g_hash);
00475             if(!(*ht))
00476                 return -1;
00477 
00478             ps_tracker_init(*ht);
00479         }
00480         else
00481         {
00482             return -1;
00483         }
00484     }
00485 
00486     return 0;
00487 }
00488 
00489 static int ps_tracker_lookup(PS_PKT *ps_pkt, PS_TRACKER **scanner,
00490                              PS_TRACKER **scanned)
00491 {
00492     PS_HASH_KEY key;
00493     Packet     *p;
00494 
00495     if(!ps_pkt->pkt)
00496         return -1;
00497 
00498     p = (Packet *)ps_pkt->pkt;
00499 
00500     /*
00501     **  Let's lookup the host that is being scanned, taking into account
00502     **  the pkt may be reversed.
00503     */
00504     if(g_ps_init.detect_scan_type & 
00505             (PS_TYPE_PORTSCAN | PS_TYPE_DECOYSCAN | PS_TYPE_DISTPORTSCAN))
00506     {
00507         key.scanner = 0;
00508         
00509         if(ps_pkt->reverse_pkt)
00510             key.scanned = p->iph->ip_src.s_addr;
00511         else
00512             key.scanned = p->iph->ip_dst.s_addr;
00513 
00514         /*
00515         **  Get the scanned tracker.
00516         */
00517         if(ps_tracker_get(scanned, &key))
00518             return -1;
00519     }
00520 
00521     /*
00522     **  Let's lookup the host that is scanning.
00523     */
00524     if(g_ps_init.detect_scan_type & PS_TYPE_PORTSWEEP)
00525     {
00526         key.scanned = 0;
00527         
00528         if(ps_pkt->reverse_pkt)
00529             key.scanner = p->iph->ip_dst.s_addr;
00530         else
00531             key.scanner = p->iph->ip_src.s_addr;
00532 
00533         /*
00534         **  Get the scanner tracker
00535         */
00536         if(ps_tracker_get(scanner, &key))
00537             return -1;
00538     }
00539 
00540     return 0;
00541 }
00542 
00543 /*
00544 **  NAME
00545 **    ps_get_proto_index::
00546 */
00547 /**
00548 **  This logic finds the index to the proto array based on the
00549 **  portscan configuration.  We need special logic because the 
00550 **  index of the protocol changes based on the configuration.
00551 */
00552 static int ps_get_proto_index(PS_PKT *ps_pkt, int *proto_index, int *proto)
00553 {
00554     Packet *p;
00555     int     found = 0;
00556 
00557     if(!ps_pkt || !ps_pkt->pkt || !proto_index || !proto)
00558         return -1;
00559 
00560     p = (Packet *)ps_pkt->pkt;
00561     *proto_index = 0;
00562     *proto = 0;
00563 
00564     if(!found && g_ps_init.detect_scans & PS_PROTO_TCP)
00565     {
00566         if(p->tcph) 
00567         {
00568             found = 1;
00569             *proto = PS_PROTO_TCP;
00570         }
00571         else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH &&
00572                 p->icmph->code == ICMP_PORT_UNREACH && p->orig_tcph)
00573         {
00574             found = 1;
00575             *proto = PS_PROTO_TCP;
00576         }
00577         else 
00578         {
00579             (*proto_index)++;
00580         }
00581     }
00582 
00583     if(!found && g_ps_init.detect_scans & PS_PROTO_UDP)
00584     {
00585         if(p->udph)
00586         { 
00587             found = 1;
00588             *proto = PS_PROTO_UDP;
00589         }
00590         else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH &&
00591                 p->icmph->code == ICMP_PORT_UNREACH && p->orig_udph)
00592         {
00593             found = 1;
00594             *proto = PS_PROTO_UDP;
00595         }
00596         else 
00597         {
00598             (*proto_index)++;
00599         }
00600     }
00601 
00602     if(!found && g_ps_init.detect_scans & PS_PROTO_IP)
00603     {
00604         if(p->iph && !p->icmph)
00605         {
00606             found = 1;
00607             *proto = PS_PROTO_IP;
00608         }
00609         else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH &&
00610                 p->icmph->code == ICMP_PROT_UNREACH)
00611         {
00612             found = 1;
00613             *proto = PS_PROTO_IP;
00614         }
00615         else
00616         {
00617             (*proto_index)++;
00618         }
00619     }
00620 
00621     if(!found && g_ps_init.detect_scans & PS_PROTO_ICMP)
00622     {
00623         if(p->icmph) 
00624         {
00625             found = 1;
00626             *proto = PS_PROTO_ICMP;
00627         }
00628         else 
00629         {
00630             (*proto_index)++;
00631         }
00632     }
00633 
00634     if(!found)
00635     {
00636         *proto = 0;
00637         *proto_index = 0;
00638         return -1;
00639     }
00640 
00641     return 0;
00642 }
00643 
00644 /*
00645 **  NAME
00646 **    ps_proto_update_window::
00647 */
00648 /**
00649 **  Update the proto time windows based on the portscan sensitivity
00650 **  level.
00651 */
00652 static int ps_proto_update_window(PS_PROTO *proto, time_t pkt_time)
00653 {
00654     time_t interval;
00655 
00656     switch(g_ps_init.sense_level)
00657     {
00658         case PS_SENSE_LOW:
00659             //interval = 15;
00660             interval = 60;
00661             break;
00662 
00663         case PS_SENSE_MEDIUM:
00664             //interval = 15;
00665             interval = 90;
00666             break;
00667 
00668         case PS_SENSE_HIGH:
00669             interval = 600;
00670             break;
00671 
00672         default:
00673             return -1;
00674     }
00675 
00676     /*
00677     **  If we are outside of the window, reset our ps counters.
00678     */
00679     if(pkt_time > proto->window)
00680     {
00681         memset(proto, 0x00, sizeof(PS_PROTO));
00682 
00683         proto->window = pkt_time + interval;
00684 
00685         return 0;
00686     }
00687 
00688     return 0;
00689 }
00690 
00691 /*
00692 **  NAME
00693 **    ps_proto_update::
00694 */
00695 /**
00696 **  This function updates the PS_PROTO structure.
00697 **
00698 **  @param PS_PROTO pointer to structure to update
00699 **  @param int      number to increment portscan counter
00700 **  @param u_long   IP address of other host
00701 **  @param u_short  port/ip_proto to track
00702 **  @param time_t   time the packet was received. update windows.
00703 */
00704 static int ps_proto_update(PS_PROTO *proto, int ps_cnt, int pri_cnt, u_long ip,
00705         u_short port, time_t pkt_time)
00706 {
00707     if(!proto)
00708         return 0;
00709 
00710     /*
00711     **  If the ps_cnt is negative, that means we are just taking off
00712     **  for valid connection, and we don't want to do anything else,
00713     **  like update ip/port, etc.
00714     */
00715     if(ps_cnt < 0)
00716     {
00717         proto->connection_count += ps_cnt;
00718         if(proto->connection_count < 0)
00719             proto->connection_count = 0;
00720 
00721         return 0;
00722     }
00723 
00724     /*
00725     **  If we are updating a priority cnt, it means we already did the
00726     **  unique port and IP on the connection packet.
00727     **
00728     **  Priority points are only added for invalid response packets.
00729     */
00730     if(pri_cnt)
00731     {
00732         proto->priority_count += pri_cnt;
00733         if(proto->priority_count < 0)
00734             proto->priority_count = 0;
00735 
00736         return 0;
00737     }
00738 
00739     /*
00740     **  Do time check first before we update the counters, so if
00741     **  we need to reset them we do it before we update them.
00742     */
00743     if(ps_proto_update_window(proto, pkt_time))
00744         return -1;
00745 
00746     /*
00747     **  Update ps counter
00748     */
00749     proto->connection_count += ps_cnt;
00750     if(proto->connection_count < 0)
00751         proto->connection_count = 0;
00752 
00753     if(proto->u_ips != ip)
00754     {
00755         proto->u_ip_count++;
00756         proto->u_ips = ip;
00757     }
00758 
00759     if(proto->low_ip)
00760     {
00761         if(proto->low_ip > ip)
00762             proto->low_ip = ip;
00763     }
00764     else
00765     {
00766         proto->low_ip = ip;
00767     }
00768 
00769     if(proto->high_ip)
00770     {
00771         if(proto->high_ip < ip)
00772             proto->high_ip = ip;
00773     }
00774     else
00775     {
00776         proto->high_ip = ip;
00777     }
00778 
00779     if(proto->u_ports != port)
00780     {
00781         proto->u_port_count++;
00782         proto->u_ports = port;
00783     }
00784     
00785     if(proto->low_p)
00786     {
00787         if(proto->low_p > port)
00788             proto->low_p = port;
00789     }
00790     else
00791     {
00792         proto->low_p = port;
00793     }
00794 
00795     if(proto->high_p)
00796     {
00797         if(proto->high_p < port)
00798             proto->high_p = port;
00799     }
00800     else
00801     {
00802         proto->high_p = port;
00803     }
00804 
00805     return 0;
00806 }
00807 
00808 static int ps_update_open_ports(PS_PROTO *proto, unsigned short port)
00809 {
00810     int iCtr;
00811     
00812     for(iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++)
00813     {
00814         if(port == proto->open_ports[iCtr])
00815             return 0;
00816     }
00817     
00818     if(iCtr < (PS_OPEN_PORTS - 1))
00819     {
00820         proto->open_ports[iCtr] = port;
00821         proto->open_ports_cnt++;
00822 
00823         if(proto->alerts == PS_ALERT_GENERATED)
00824         {
00825             proto->alerts = PS_ALERT_OPEN_PORT;
00826         }
00827     }
00828 
00829     return 0;
00830 }
00831     
00832 /*
00833 **  NAME
00834 **    ps_tracker_update_tcp::
00835 */
00836 /**
00837 **  Determine how to update the portscan counter depending on the type
00838 **  of TCP packet we have.
00839 **
00840 **  We are concerned with three types of TCP packets:
00841 **  
00842 **    - initiating TCP packets (we don't care about flags)
00843 **    - TCP 3-way handshake packets (we decrement the counter)
00844 **    - TCP reset packets on unestablished streams.
00845 */
00846 static int ps_tracker_update_tcp(PS_PKT *ps_pkt, PS_TRACKER *scanner,
00847         PS_TRACKER *scanned, int proto_idx)
00848 {
00849     Packet  *p;
00850     Session *ssn;
00851     time_t  pkt_time;
00852     FLOW    *flow;
00853     
00854 
00855     p = (Packet *)ps_pkt->pkt;
00856     pkt_time = packet_timeofday();
00857 
00858     ssn  = (Session *)p->ssnptr;
00859     flow = (FLOW *)p->flow;
00860 
00861     /*
00862     **  Handle the initiating packet.
00863     **
00864     **  If this what stream4 considers to be a valid initiator, then
00865     **  we will use the available stream4 information.  Otherwise, we
00866     **  can just revert to flow and look for initiators and responders.
00867     **
00868     **  The "midstream" logic below says that, if we include sessions
00869     **  picked up midstream, then we don't care about the MIDSTREAM flag.
00870     **  Otherwise, only consider streams not picked up midstream.
00871     */
00872     if(ssn)
00873     {
00874         if((ssn->session_flags & SSNFLAG_SEEN_CLIENT) && 
00875            !(ssn->session_flags & SSNFLAG_SEEN_SERVER) &&
00876            (g_include_midstream || !(ssn->session_flags & SSNFLAG_MIDSTREAM)))
00877         {
00878             if(scanned)
00879             {
00880                 ps_proto_update(&scanned->proto[proto_idx],1,0,
00881                                  p->iph->ip_src.s_addr,p->dp, pkt_time);
00882             }
00883 
00884             if(scanner)
00885             {
00886                 ps_proto_update(&scanner->proto[proto_idx],1,0,
00887                                  p->iph->ip_dst.s_addr,p->dp, pkt_time);
00888             }
00889         }
00890         /*
00891         **  Handle the final packet of the three-way handshake.
00892         */
00893         else if(p->packet_flags & PKT_STREAM_TWH)
00894         {
00895             if(scanned)
00896                 ps_proto_update(&scanned->proto[proto_idx],-1,0,0,0,0);
00897 
00898             if(scanner)
00899                 ps_proto_update(&scanner->proto[proto_idx],-1,0,0,0,0);
00900         }
00901         /*
00902         **  RST packet on unestablished streams
00903         */
00904         else if((p->packet_flags & PKT_FROM_SERVER) &&
00905                 (p->tcph->th_flags & TH_RST) &&
00906                 (!(p->packet_flags & PKT_STREAM_EST) ||
00907                 (ssn->session_flags & SSNFLAG_MIDSTREAM)))
00908         {
00909             if(scanned)
00910             {
00911                 ps_proto_update(&scanned->proto[proto_idx],0,1,0,0,0);
00912                 scanned->priority_node = 1;
00913             }
00914 
00915             if(scanner)
00916             {
00917                 ps_proto_update(&scanner->proto[proto_idx],0,1,0,0,0);
00918                 scanner->priority_node = 1;
00919             }
00920         }
00921         /*
00922         **  We only get here on the server's response to the intial
00923         **  client connection.
00924         **
00925         **  That's why we use the sp, because that's the port that is
00926         **  open.
00927         */
00928         else if((p->packet_flags & PKT_FROM_SERVER) &&
00929                 !(p->packet_flags & PKT_STREAM_EST))
00930         {
00931             if(scanned)
00932                 ps_update_open_ports(&scanned->proto[proto_idx], p->sp);
00933         
00934             if(scanner)
00935             {
00936                 if(scanner->proto[proto_idx].alerts == PS_ALERT_GENERATED)
00937                     scanner->proto[proto_idx].alerts = PS_ALERT_OPEN_PORT;
00938             }
00939         }
00940     }
00941     /*
00942     **  If we are an icmp unreachable, deal with it here.
00943     */
00944     else if(p->icmph && p->orig_tcph)
00945     {
00946         if(scanned)
00947         {
00948             ps_proto_update(&scanned->proto[proto_idx],0,1,0,0,0);
00949             scanned->priority_node = 1;
00950         }
00951 
00952         if(scanner)
00953         {
00954             ps_proto_update(&scanner->proto[proto_idx],0,1,0,0,0);
00955             scanner->priority_node = 1;
00956         }
00957     }
00958     /*
00959     **  If we're none of the above, revert to flow to do some basic
00960     **  processing.  This means that the TCP packet we got is not
00961     **  considered a valid initiator, so we didn't start a stream
00962     **  tracker.
00963     */
00964     else if(flow)
00965     {
00966         if(flow->stats.direction == FROM_INITIATOR)
00967         {
00968             if(scanned)
00969             {
00970                 ps_proto_update(&scanned->proto[proto_idx],1,0,
00971                                  p->iph->ip_src.s_addr,p->dp, pkt_time);
00972             }
00973 
00974             if(scanner)
00975             {
00976                 ps_proto_update(&scanner->proto[proto_idx],1,0,
00977                                  p->iph->ip_dst.s_addr,p->dp, pkt_time);
00978             }
00979         }
00980         else if(flow->stats.direction == FROM_RESPONDER &&
00981                 (p->tcph->th_flags & TH_RST))
00982         {
00983             if(scanned)
00984             {
00985                 ps_proto_update(&scanned->proto[proto_idx],0,1,0,0,0);
00986                 scanned->priority_node = 1;
00987             }
00988 
00989             if(scanner)
00990             {
00991                 ps_proto_update(&scanner->proto[proto_idx],0,1,0,0,0);
00992                 scanner->priority_node = 1;
00993             }
00994         }
00995     }
00996 
00997     return 0;
00998 }
00999 
01000 static int ps_tracker_update_ip(PS_PKT *ps_pkt, PS_TRACKER *scanner,
01001         PS_TRACKER *scanned, int proto_idx)
01002 {
01003     Packet *p;
01004     time_t  pkt_time;
01005     FLOW   *flow;
01006     
01007     p = (Packet *)ps_pkt->pkt;
01008     pkt_time = packet_timeofday();
01009 
01010     if(p->iph)
01011     {
01012         if(p->icmph)
01013         {
01014             if(p->icmph->type == ICMP_DEST_UNREACH &&
01015                p->icmph->code == ICMP_PROT_UNREACH)
01016             {
01017                 if(scanned)
01018                 {
01019                     ps_proto_update(&scanned->proto[proto_idx],0,1,0,0,0);
01020                     scanned->priority_node = 1;
01021                 }
01022 
01023                 if(scanner)
01024                 {
01025                     ps_proto_update(&scanner->proto[proto_idx],0,1,0,0,0);
01026                     scanner->priority_node = 1;
01027                 }
01028             }
01029 
01030             return 0;
01031         }
01032 
01033         if(p->flow)
01034         {
01035             flow = (FLOW *)p->flow;
01036             if(flow->stats.direction == FROM_INITIATOR)
01037             {
01038                 if(scanned)
01039                 {
01040                     ps_proto_update(&scanned->proto[proto_idx],1,0,
01041                         p->iph->ip_src.s_addr,(u_short)p->iph->ip_proto, pkt_time);
01042                 }
01043 
01044                 if(scanner)
01045                 {
01046                     ps_proto_update(&scanner->proto[proto_idx],1,0,
01047                         p->iph->ip_dst.s_addr,(u_short)p->iph->ip_proto, pkt_time);
01048                 }
01049             }
01050             else if(flow->stats.direction == FROM_RESPONDER)
01051             {
01052                 if(scanned)
01053                     ps_proto_update(&scanned->proto[proto_idx],-1,0,0,0,0);
01054 
01055                 if(scanner)
01056                     ps_proto_update(&scanner->proto[proto_idx],-1,0,0,0,0);
01057             }
01058         }
01059     }
01060 
01061     return 0;
01062 }
01063 
01064 static int ps_tracker_update_udp(PS_PKT *ps_pkt, PS_TRACKER *scanner,
01065         PS_TRACKER *scanned, int proto_idx)
01066 {
01067     Packet  *p;
01068     time_t  pkt_time;
01069     FLOW    *flow;
01070     
01071     p = (Packet *)ps_pkt->pkt;
01072     pkt_time = packet_timeofday();
01073 
01074     if(p->icmph)
01075     { 
01076         if(p->icmph->type == ICMP_DEST_UNREACH &&
01077            p->icmph->code == ICMP_PORT_UNREACH)
01078         {
01079             if(scanned)
01080             {
01081                 ps_proto_update(&scanned->proto[proto_idx],0,1,0,0,0);
01082                 scanned->priority_node = 1;
01083             }
01084 
01085             if(scanner)
01086             {
01087                 ps_proto_update(&scanner->proto[proto_idx],0,1,0,0,0);
01088                 scanner->priority_node = 1;
01089             }
01090         }
01091     }
01092     else if(p->udph)
01093     {
01094         if(p->flow)
01095         {
01096             flow = (FLOW *)p->flow;
01097             if(flow->stats.direction == FROM_INITIATOR)
01098             {
01099                 if(scanned)
01100                 {
01101                     ps_proto_update(&scanned->proto[proto_idx],1,0,
01102                                      p->iph->ip_src.s_addr,p->dp, pkt_time);
01103                 }
01104 
01105                 if(scanner)
01106                 {
01107                     ps_proto_update(&scanner->proto[proto_idx],1,0,
01108                                      p->iph->ip_dst.s_addr,p->dp, pkt_time);
01109                 }
01110             }
01111             else if(flow->stats.direction == FROM_RESPONDER)
01112             {
01113                 if(scanned)
01114                     ps_proto_update(&scanned->proto[proto_idx],-1,0,0,0,0);
01115 
01116                 if(scanner)
01117                     ps_proto_update(&scanner->proto[proto_idx],-1,0,0,0,0);
01118             }
01119         }
01120     }
01121 
01122     return 0;
01123 }
01124 
01125 static int ps_tracker_update_icmp(PS_PKT *ps_pkt, PS_TRACKER *scanner,
01126         PS_TRACKER *scanned, int proto_idx)
01127 {
01128     Packet  *p;
01129     time_t  pkt_time;
01130     
01131     p = (Packet *)ps_pkt->pkt;
01132     pkt_time = packet_timeofday();
01133 
01134     if(p->icmph)
01135     {
01136         switch(p->icmph->type)
01137         {
01138             case ICMP_ECHO:
01139             case ICMP_TIMESTAMP:
01140             case ICMP_ADDRESS:
01141             case ICMP_INFO_REQUEST:
01142 
01143                 if(scanner)
01144                 {
01145                     ps_proto_update(&scanner->proto[proto_idx],1,0,
01146                                      p->iph->ip_dst.s_addr, 0, pkt_time);
01147                 }
01148                 
01149                 break;
01150 
01151             case ICMP_DEST_UNREACH:
01152 
01153                 if(scanner)
01154                 {
01155                     ps_proto_update(&scanner->proto[proto_idx],0,1,0,0,0);
01156                     scanner->priority_node = 1;
01157                 }
01158 
01159                 break;
01160 
01161             default:
01162                 break;
01163         }
01164     }
01165 
01166     return 0;
01167 }
01168 
01169 /*
01170 **  NAME
01171 **    ps_tracker_update::
01172 */
01173 /**
01174 **  At this point, we should only be looking at tranport protocols
01175 **  that we want to.  For instance, if we aren't doing UDP portscans
01176 **  then we won't see UDP packets here because they were ignored.
01177 **
01178 **  This is where we evaluate the packet to add/subtract portscan
01179 **  tracker values and prioritize a tracker.  We also update the
01180 **  time windows.
01181 */
01182 static int ps_tracker_update(PS_PKT *ps_pkt, PS_TRACKER *scanner,
01183         PS_TRACKER *scanned)
01184 {
01185     Packet *p;
01186     int     proto_idx;
01187     int     proto;
01188 
01189     p = (Packet *)ps_pkt->pkt;
01190 
01191     if(ps_get_proto_index(ps_pkt, &proto_idx, &proto))
01192         return -1;
01193 
01194     if(scanner && scanner->proto[proto_idx].alerts)
01195         scanner->proto[proto_idx].alerts = PS_ALERT_GENERATED;
01196     if(scanned && scanned->proto[proto_idx].alerts)
01197         scanned->proto[proto_idx].alerts = PS_ALERT_GENERATED;
01198     
01199     switch(proto)
01200     {
01201         case PS_PROTO_TCP:
01202             if(ps_tracker_update_tcp(ps_pkt, scanner, scanned, proto_idx))
01203                 return -1;
01204 
01205             break;
01206 
01207         case PS_PROTO_UDP:
01208             if(ps_tracker_update_udp(ps_pkt, scanner, scanned, proto_idx))
01209                 return -1;
01210 
01211             break;
01212 
01213         case PS_PROTO_ICMP:
01214             if(ps_tracker_update_icmp(ps_pkt, scanner, scanned, proto_idx))
01215                 return -1;
01216 
01217             break;
01218 
01219         case PS_PROTO_IP:
01220             if(ps_tracker_update_ip(ps_pkt, scanner, scanned, proto_idx))
01221                 return -1;
01222 
01223             break;
01224 
01225         default:
01226             return -1;
01227     }
01228 
01229     ps_pkt->proto     = proto;
01230     ps_pkt->proto_idx = proto_idx;
01231 
01232     return 0;
01233 }
01234 
01235 static int ps_alert_one_to_one(PS_PROTO *scanner, PS_PROTO *scanned,
01236         PS_ALERT_CONF *conf)
01237 {
01238     if(!conf)
01239         return -1;
01240 
01241     /*
01242     **  Let's evaluate the scanned host.
01243     */
01244     if(scanned && !scanned->alerts)
01245     {
01246         if(scanned->priority_count >= conf->priority_count)
01247         {
01248             if(scanned->u_ip_count < conf->u_ip_count &&
01249                scanned->u_port_count >= conf->u_port_count)
01250             {
01251                 if(scanner)
01252                 {
01253                     if(scanner->priority_count >= conf->priority_count)
01254                     {
01255                         /*
01256                         **  Now let's check to make sure this is one
01257                         **  to one
01258                         */
01259                         scanned->alerts = PS_ALERT_ONE_TO_ONE;
01260                         return 0;
01261                     }
01262                 }
01263                 else
01264                 {
01265                     /*
01266                     **  If there is no scanner, then we do the best we can.
01267                     */
01268                     scanned->alerts = PS_ALERT_ONE_TO_ONE;
01269                     return 0;
01270                 }
01271             }
01272         }
01273         if(scanned->connection_count >= conf->connection_count)
01274         {
01275             if(conf->connection_count == 0)
01276                 return 0;
01277 
01278             if(scanned->u_ip_count < conf->u_ip_count &&
01279                scanned->u_port_count >= conf->u_port_count)
01280             {
01281                 scanned->alerts = PS_ALERT_ONE_TO_ONE_FILTERED;
01282                 return 0;
01283             }
01284         }
01285     }
01286 
01287     return 0;
01288 
01289 }
01290 
01291 static int ps_alert_one_to_one_decoy(PS_PROTO *scanner, PS_PROTO *scanned,
01292         PS_ALERT_CONF *conf)
01293 {
01294     if(!conf)
01295         return -1;
01296 
01297     if(scanned && !scanned->alerts)
01298     {
01299         if(scanned->priority_count >= conf->priority_count)
01300         {
01301             if(scanned->u_ip_count >= conf->u_ip_count &&
01302                scanned->u_port_count >= conf->u_port_count)
01303             {
01304                 scanned->alerts = PS_ALERT_ONE_TO_ONE_DECOY;
01305                 return 0;
01306             }
01307         }
01308         if(scanned->connection_count >= conf->connection_count)
01309         {
01310             if(conf->connection_count == 0)
01311                 return 0;
01312 
01313             if(scanned->u_ip_count >= conf->u_ip_count &&
01314                scanned->u_port_count >= conf->u_port_count)
01315             {
01316                 scanned->alerts = PS_ALERT_ONE_TO_ONE_DECOY_FILTERED;
01317                 return 0;
01318             }
01319         }
01320     }
01321 
01322     return 0;
01323 }
01324 
01325 static int ps_alert_many_to_one(PS_PROTO *scanner, PS_PROTO *scanned,
01326         PS_ALERT_CONF *conf)
01327 {
01328     if(!conf)
01329         return -1;
01330 
01331     if(scanned && !scanned->alerts)
01332     {
01333         if(scanned->priority_count >= conf->priority_count)
01334         {
01335             if(scanned->u_ip_count <= conf->u_ip_count &&
01336                scanned->u_port_count >= conf->u_port_count)
01337             {
01338                 scanned->alerts = PS_ALERT_DISTRIBUTED;
01339                 return 0;
01340             }
01341         }
01342         if(scanned->connection_count >= conf->connection_count)
01343         {
01344             if(conf->connection_count == 0)
01345                 return 0;
01346 
01347             if(scanned->u_ip_count <= conf->u_ip_count &&
01348                scanned->u_port_count >= conf->u_port_count)
01349             {
01350                 scanned->alerts = PS_ALERT_DISTRIBUTED_FILTERED;
01351                 return 0;
01352             }
01353         }
01354     }
01355             
01356     return 0;
01357 }
01358 
01359 static int ps_alert_one_to_many(PS_PROTO *scanner, PS_PROTO *scanned,
01360         PS_ALERT_CONF *conf)
01361 {
01362     if(!conf)
01363         return -1;
01364 
01365     if(scanner && !scanner->alerts)
01366     {
01367         if(scanner->priority_count >= conf->priority_count)
01368         {
01369             if(scanner->u_ip_count >= conf->u_ip_count &&
01370                scanner->u_port_count <= conf->u_port_count)
01371             {
01372                 scanner->alerts = PS_ALERT_PORTSWEEP;
01373                 return 1;
01374             }
01375         }
01376         if(scanner->connection_count >= conf->connection_count)
01377         {
01378             if(conf->connection_count == 0)
01379                 return 0;
01380 
01381             if(scanner->u_ip_count >= conf->u_ip_count &&
01382                scanner->u_port_count <= conf->u_ip_count)
01383             {
01384                 scanner->alerts = PS_ALERT_PORTSWEEP_FILTERED;
01385                 return 1;
01386             }
01387         }
01388     }
01389             
01390     return 0;
01391 }
01392 
01393 static int ps_alert_tcp(PS_PROTO *scanner, PS_PROTO *scanned)
01394 {
01395     static PS_ALERT_CONF *one_to_one;
01396     static PS_ALERT_CONF *one_to_one_decoy;
01397     static PS_ALERT_CONF *one_to_many;
01398     static PS_ALERT_CONF *many_to_one;
01399 
01400     /*
01401     ** Set the configurations depending on the sensitivity
01402     ** level.
01403     */
01404     switch(g_ps_init.sense_level)
01405     {
01406         case PS_SENSE_HIGH:
01407             one_to_one       = &g_tcp_hi_ps;
01408             one_to_one_decoy = &g_tcp_hi_decoy_ps;
01409             one_to_many      = &g_tcp_hi_sweep;
01410             many_to_one      = &g_tcp_hi_dist_ps;
01411 
01412             break;
01413 
01414         case PS_SENSE_MEDIUM:
01415             one_to_one       = &g_tcp_med_ps;
01416             one_to_one_decoy = &g_tcp_med_decoy_ps;
01417             one_to_many      = &g_tcp_med_sweep;
01418             many_to_one      = &g_tcp_med_dist_ps;
01419 
01420             break;
01421 
01422         case PS_SENSE_LOW:
01423             one_to_one       = &g_tcp_low_ps;
01424             one_to_one_decoy = &g_tcp_low_decoy_ps;
01425             one_to_many      = &g_tcp_low_sweep;
01426             many_to_one      = &g_tcp_low_dist_ps;
01427 
01428             break;
01429 
01430         default:
01431             return -1;
01432     }
01433 
01434     /*
01435     **  Do detection on the different portscan types.
01436     */
01437     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSCAN) &&
01438         ps_alert_one_to_one(scanner, scanned, one_to_one))
01439     {
01440         return 0;
01441     }
01442 
01443     if((g_ps_init.detect_scan_type & PS_TYPE_DECOYSCAN) &&
01444         ps_alert_one_to_one_decoy(scanner, scanned, one_to_one_decoy))
01445     {
01446         return 0;
01447     }
01448     
01449     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSWEEP) && 
01450         ps_alert_one_to_many(scanner, scanned, one_to_many))
01451     {
01452         return 0;
01453     }
01454 
01455     if((g_ps_init.detect_scan_type & PS_TYPE_DISTPORTSCAN) &&
01456         ps_alert_many_to_one(scanner, scanned, many_to_one))
01457     {
01458         return 0;
01459     }
01460     
01461     return 0;
01462 }
01463 
01464 static int ps_alert_ip(PS_PROTO *scanner, PS_PROTO *scanned)
01465 {
01466     static PS_ALERT_CONF *one_to_one;
01467     static PS_ALERT_CONF *one_to_one_decoy;
01468     static PS_ALERT_CONF *one_to_many;
01469     static PS_ALERT_CONF *many_to_one;
01470 
01471     /*
01472     ** Set the configurations depending on the sensitivity
01473     ** level.
01474     */
01475     switch(g_ps_init.sense_level)
01476     {
01477         case PS_SENSE_HIGH:
01478             one_to_one       = &g_ip_hi_ps;
01479             one_to_one_decoy = &g_ip_hi_decoy_ps;
01480             one_to_many      = &g_ip_hi_sweep;
01481             many_to_one      = &g_ip_hi_dist_ps;
01482 
01483             break;
01484 
01485         case PS_SENSE_MEDIUM:
01486             one_to_one       = &g_ip_med_ps;
01487             one_to_one_decoy = &g_ip_med_decoy_ps;
01488             one_to_many      = &g_ip_med_sweep;
01489             many_to_one      = &g_ip_med_dist_ps;
01490 
01491             break;
01492 
01493         case PS_SENSE_LOW:
01494             one_to_one       = &g_ip_low_ps;
01495             one_to_one_decoy = &g_ip_low_decoy_ps;
01496             one_to_many      = &g_ip_low_sweep;
01497             many_to_one      = &g_ip_low_dist_ps;
01498 
01499             break;
01500 
01501         default:
01502             return -1;
01503     }
01504 
01505     /*
01506     **  Do detection on the different portscan types.
01507     */
01508     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSCAN) &&
01509         ps_alert_one_to_one(scanner, scanned, one_to_one))
01510     {
01511         return 0;
01512     }
01513 
01514     if((g_ps_init.detect_scan_type & PS_TYPE_DECOYSCAN) &&
01515         ps_alert_one_to_one_decoy(scanner, scanned, one_to_one_decoy))
01516     {
01517         return 0;
01518     }
01519     
01520     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSWEEP) && 
01521         ps_alert_one_to_many(scanner, scanned, one_to_many))
01522     {
01523         return 0;
01524     }
01525 
01526     if((g_ps_init.detect_scan_type & PS_TYPE_DISTPORTSCAN) &&
01527         ps_alert_many_to_one(scanner, scanned, many_to_one))
01528     {
01529         return 0;
01530     }
01531     
01532     return 0;
01533 }
01534 
01535 static int ps_alert_udp(PS_PROTO *scanner, PS_PROTO *scanned)
01536 {
01537     static PS_ALERT_CONF *one_to_one;
01538     static PS_ALERT_CONF *one_to_one_decoy;
01539     static PS_ALERT_CONF *one_to_many;
01540     static PS_ALERT_CONF *many_to_one;
01541 
01542     /*
01543     ** Set the configurations depending on the sensitivity
01544     ** level.
01545     */
01546     switch(g_ps_init.sense_level)
01547     {
01548         case PS_SENSE_HIGH:
01549             one_to_one       = &g_udp_hi_ps;
01550             one_to_one_decoy = &g_udp_hi_decoy_ps;
01551             one_to_many      = &g_udp_hi_sweep;
01552             many_to_one      = &g_udp_hi_dist_ps;
01553 
01554             break;
01555 
01556         case PS_SENSE_MEDIUM:
01557             one_to_one       = &g_udp_med_ps;
01558             one_to_one_decoy = &g_udp_med_decoy_ps;
01559             one_to_many      = &g_udp_med_sweep;
01560             many_to_one      = &g_udp_med_dist_ps;
01561 
01562             break;
01563 
01564         case PS_SENSE_LOW:
01565             one_to_one       = &g_udp_low_ps;
01566             one_to_one_decoy = &g_udp_low_decoy_ps;
01567             one_to_many      = &g_udp_low_sweep;
01568             many_to_one      = &g_udp_low_dist_ps;
01569 
01570             break;
01571 
01572         default:
01573             return -1;
01574     }
01575 
01576     /*
01577     **  Do detection on the different portscan types.
01578     */
01579     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSCAN) &&
01580         ps_alert_one_to_one(scanner, scanned, one_to_one))
01581     {
01582         return 0;
01583     }
01584 
01585     if((g_ps_init.detect_scan_type & PS_TYPE_DECOYSCAN) &&
01586         ps_alert_one_to_one_decoy(scanner, scanned, one_to_one_decoy))
01587     {
01588         return 0;
01589     }
01590     
01591     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSWEEP) && 
01592         ps_alert_one_to_many(scanner, scanned, one_to_many))
01593     {
01594         return 0;
01595     }
01596 
01597     if((g_ps_init.detect_scan_type & PS_TYPE_DISTPORTSCAN) &&
01598         ps_alert_many_to_one(scanner, scanned, many_to_one))
01599     {
01600         return 0;
01601     }
01602     
01603     return 0;
01604 }
01605 
01606 static int ps_alert_icmp(PS_PROTO *scanner, PS_PROTO *scanned)
01607 {
01608     static PS_ALERT_CONF *one_to_many;
01609 
01610     /*
01611     ** Set the configurations depending on the sensitivity
01612     ** level.
01613     */
01614     switch(g_ps_init.sense_level)
01615     {
01616         case PS_SENSE_HIGH:
01617             one_to_many = &g_icmp_hi_sweep;
01618 
01619             break;
01620 
01621         case PS_SENSE_MEDIUM:
01622             one_to_many = &g_icmp_med_sweep;
01623 
01624             break;
01625 
01626         case PS_SENSE_LOW:
01627             one_to_many = &g_icmp_low_sweep;
01628 
01629             break;
01630 
01631         default:
01632             return -1;
01633     }
01634 
01635     /*
01636     **  Do detection on the different portscan types.
01637     */
01638     if((g_ps_init.detect_scan_type & PS_TYPE_PORTSWEEP) && 
01639         ps_alert_one_to_many(scanner, scanned, one_to_many))
01640     {
01641         return 0;
01642     }
01643     
01644     return 0;
01645 }
01646 /*
01647 **  NAME
01648 **    ps_tracker_alert::
01649 */
01650 /**
01651 **  This function evaluates the scanner and scanned trackers and if
01652 **  applicable, generate an alert or alerts for either of the trackers.
01653 **
01654 **  The following alerts can be generated:
01655 **    - One to One Portscan
01656 **    - One to One Decoy Portscan
01657 **    - One to Many Portsweep
01658 **    - Distributed Portscan (Many to One)
01659 **    - Filtered Portscan?
01660 */
01661 static int ps_tracker_alert(PS_PKT *ps_pkt, PS_TRACKER *scanner,
01662         PS_TRACKER *scanned)
01663 {
01664     if(!ps_pkt)
01665         return -1;
01666 
01667     switch(ps_pkt->proto)
01668     {
01669         case PS_PROTO_TCP:
01670             ps_alert_tcp((scanner ? &scanner->proto[ps_pkt->proto_idx] : NULL),
01671                     (scanned ? &scanned->proto[ps_pkt->proto_idx] : NULL));
01672 
01673             break;
01674 
01675         case PS_PROTO_UDP:
01676             ps_alert_udp((scanner ? &scanner->proto[ps_pkt->proto_idx] : NULL),
01677                     (scanned ? &scanned->proto[ps_pkt->proto_idx] : NULL));
01678 
01679             break;
01680 
01681         case PS_PROTO_ICMP:
01682             ps_alert_icmp((scanner ? &scanner->proto[ps_pkt->proto_idx] : NULL),
01683                     (scanned ? &scanned->proto[ps_pkt->proto_idx] : NULL));
01684 
01685             break;
01686 
01687         case PS_PROTO_IP:
01688             ps_alert_ip((scanner ? &scanner->proto[ps_pkt->proto_idx] : NULL),
01689                     (scanned ? &scanned->proto[ps_pkt->proto_idx] : NULL));
01690             break;
01691 
01692         default:
01693             return -1;
01694     }
01695 
01696     return 0;
01697 }
01698 
01699 /*
01700 **  NAME
01701 **    ps_detect::
01702 */
01703 /**
01704 **  The design of portscan is as follows:
01705 **
01706 **    - Filter Packet.  Is the packet part of the ignore or watch list?  Is
01707 **      the packet part of an established TCP session (we ignore it)?
01708 **
01709 **    - Tracker Lookup.  We lookup trackers for src and dst if either is in
01710 **      the watch list, or not in the ignore list if there is no watch list.
01711 **      If there is not tracker, we create a new one and keep track, both of
01712 **      the scanned host and the scanning host.
01713 **
01714 **    - Tracker Update.  We update the tracker using the incoming packet.  If
01715 **      the update causes a portscan alert, then we move into the log alert
01716 **      phase.
01717 **
01718 **    - Tracker Evaluate.  Generate an alert from the updated tracker.  We
01719 **      decide whether we are logging a portscan or sweep (based on the
01720 **      scanning or scanned host, we decide which is more relevant).
01721 */
01722 int ps_detect(PS_PKT *p)
01723 {
01724     PS_TRACKER *scanner = NULL;
01725     PS_TRACKER *scanned = NULL;
01726 
01727     if(!p || !p->pkt)
01728         return -1;
01729 
01730     if(ps_filter_ignore(p))
01731         return 0;
01732 
01733     //printf("** ignore\n");
01734 
01735     if(ps_tracker_lookup(p, &scanner, &scanned))
01736         return 0;
01737 
01738     //printf("** lookup\n");
01739     if(ps_tracker_update(p, scanner, scanned))
01740         return 0;
01741 
01742     //printf("** update\n");
01743     if(ps_tracker_alert(p, scanner, scanned))
01744         return 0;
01745 
01746     //printf("** alert\n");
01747     p->scanner = scanner;
01748     p->scanned = scanned;
01749     
01750     return 1;
01751 }
01752 
01753 static void ps_proto_print(PS_PROTO *proto)
01754 {
01755     int            iCtr;
01756     struct in_addr ip;
01757 
01758     if(!proto)
01759         return;
01760 
01761     printf("    priority count    = %d\n", proto->priority_count);
01762     printf("    connection count  = %d\n", proto->connection_count);
01763     printf("    unique IP count   = %d\n", proto->u_ip_count);
01764     
01765     ip.s_addr = proto->low_ip;
01766     printf("    IP range          = %s:", inet_ntoa(ip));
01767     ip.s_addr = proto->high_ip;
01768     printf("%s\n", inet_ntoa(ip));
01769             
01770     printf("    unique port count = %d\n", proto->u_port_count);
01771     printf("    port range        = %d:%d\n", proto->low_p, proto->high_p);
01772 
01773     printf("    open ports        = ");
01774 
01775     for(iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++)
01776     {
01777         printf("%d ", proto->open_ports[iCtr]);
01778     }
01779     printf("\n");
01780 
01781     printf("    alerts            = %.2x\n", proto->alerts);
01782 
01783     ip.s_addr = proto->u_ips;
01784     printf("    Last IP:   %s\n", inet_ntoa(ip));
01785     printf("    Last Port: %d\n", proto->u_ports);
01786 
01787     printf("    Time:      %s\n", ctime(&proto->window));
01788 
01789     return;
01790 }
01791 
01792 void ps_tracker_print(PS_TRACKER* ps_tracker)
01793 {
01794     int proto_index = 0;
01795 
01796     if(!ps_tracker)
01797         return;
01798 
01799     printf("    -- PS_TRACKER --\n");
01800     printf("    priority_node = %d\n", ps_tracker->priority_node);
01801 
01802     if(g_ps_init.detect_scans & PS_PROTO_TCP)
01803     {
01804         printf("    ** TCP **\n");
01805         ps_proto_print(&ps_tracker->proto[proto_index]);
01806         proto_index++;
01807     }
01808     if(g_ps_init.detect_scans & PS_PROTO_UDP)
01809     {
01810         printf("    ** UDP **\n");
01811         ps_proto_print(&ps_tracker->proto[proto_index]);
01812         proto_index++;
01813     }
01814     if(g_ps_init.detect_scans & PS_PROTO_IP)
01815     {
01816         printf("    ** IP **\n");
01817         ps_proto_print(&ps_tracker->proto[proto_index]);
01818         proto_index++;
01819     }
01820     if(g_ps_init.detect_scans & PS_PROTO_ICMP)
01821     {
01822         printf("    ** ICMP **\n");
01823         ps_proto_print(&ps_tracker->proto[proto_index]);
01824         proto_index++;
01825     }
01826 
01827     printf("    -- END --\n\n");
01828 
01829     return;
01830 }

Generated on Sun May 14 14:51:15 2006 by  doxygen 1.4.2