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

spp_sfportscan.c

Go to the documentation of this file.
00001 /*
00002 **  @file       spp_sfportscan.c
00003 **
00004 **  @author     Daniel Roelker <droelker@sourcefire.com>
00005 **
00006 **  @brief      Portscan detection
00007 **
00008 **  NOTES
00009 **    - User Configuration:  The following is a list of parameters that can
00010 **      be configured through the user interface:
00011 **
00012 **      proto  { tcp udp icmp ip all }
00013 **      scan_type { portscan portsweep decoy_portscan distributed_portscan all }
00014 **      sense_level { high }    # high, medium, low
00015 **      watch_ip { }            # list of IPs, CIDR blocks
00016 **      ignore_scanners { }     # list of IPs, CIDR blocks
00017 **      ignore_scanned { }      # list of IPs, CIDR blocks
00018 **      memcap { 10000000 }     # number of max bytes to allocate
00019 **      logfile { /tmp/ps.log } # file to log detailed portscan info
00020 */
00021 #include <sys/types.h>
00022 #ifndef WIN32
00023     #include <sys/socket.h>
00024     #include <netinet/in.h>
00025     #include <arpa/inet.h>
00026 #endif /* !WIN32 */
00027 
00028 #include "decode.h"
00029 #include "plugbase.h"
00030 #include "generators.h"
00031 #include "event_wrapper.h"
00032 #include "util.h"
00033 #include "ipobj.h"
00034 #include "checksum.h"
00035 #include "packet_time.h"
00036 #include "snort.h"
00037 #include "sfthreshold.h"
00038 
00039 #include "portscan.h"
00040 
00041 #ifdef GIDS
00042 #include "spp_stickydrop.h"
00043 #endif /* GIDS */
00044 
00045 #define DELIMITERS " \t\n"
00046 #define TOKEN_ARG_BEGIN "{"
00047 #define TOKEN_ARG_END   "}"
00048 
00049 #define PROTO_BUFFER_SIZE 256
00050 
00051 extern PV    pv;
00052 extern char *file_name;
00053 extern int   file_line;
00054 
00055 #ifdef GIDS
00056 /* stickydrop */
00057 extern SDtimeout sdt;
00058 #endif /* GIDS */
00059 
00060 static int     g_print_tracker = 0;
00061 static u_char  g_logpath[256];
00062 static FILE   *g_logfile = NULL;
00063 static Packet *g_tmp_pkt;
00064 
00065 int g_include_midstream = 0;
00066 
00067 
00068 /*
00069 **  NAME
00070 **    PortscanPacketInit::
00071 */
00072 /**
00073 **  Initialize the Packet structure buffer so we can generate our
00074 **  alert packets for portscan.  We initialize the various fields in
00075 **  the Packet structure and set the hardware layer for easy identification
00076 **  by user interfaces.
00077 **
00078 **  @return int
00079 **
00080 **  @retval !0 initialization failed
00081 **  @retval  0 success
00082 */
00083 static int PortscanPacketInit(void)
00084 {
00085     const char mac_addr[] = "MACDAD";
00086     Packet *p;
00087 
00088     p = (Packet *)calloc(1, sizeof(Packet));
00089     if(!p)
00090         return -1;
00091 
00092     p->pkth = calloc(1, sizeof(struct pcap_pkthdr) + ETHERNET_HEADER_LEN + 2 +
00093             IP_MAXPACKET);
00094 
00095     if(!p->pkth)
00096         return -1;
00097 
00098     p->pkth = (struct pcap_pkthdr *)(((u_char *)p->pkth));
00099 
00100     /* Add 2 to align iph struct members on 4 byte boundaries - for sparc, etc */
00101     p->pkt  = ((u_char *)p->pkth + sizeof(SnortPktHeader) + 2);
00102     p->eh   = (EtherHdr *)p->pkt;
00103     p->iph  = (IPHdr *)(((u_char *)p->eh) + ETHERNET_HEADER_LEN);
00104     p->data = ((u_char *)p->iph) + sizeof(IPHdr);
00105 
00106     /*
00107     **  Set the ethernet header with our cooked values.
00108     */
00109     p->eh->ether_type = htons(0x0800);
00110     memcpy(p->eh->ether_dst, mac_addr, 6);
00111     memcpy(p->eh->ether_src, mac_addr, 6);
00112 
00113     g_tmp_pkt = p;
00114 
00115     return 0;
00116 }
00117 
00118 /*
00119 **  NAME
00120 **    MakeProtoInfo::
00121 */
00122 /**
00123 **  This routine makes the portscan payload for the events.  The listed
00124 **  info is:
00125 **    - priority count (number of error transmissions RST/ICMP UNREACH)
00126 **    - connection count (number of protocol connections SYN)
00127 **    - ip count (number of IPs that communicated with host)
00128 **    - ip range (low to high range of IPs)
00129 **    - port count (number of port changes that occurred on host)
00130 **    - port range (low to high range of ports connected too)
00131 **
00132 **  @return integer
00133 **
00134 **  @retval -1 buffer not large enough
00135 **  @retval  0 successful
00136 */
00137 static int MakeProtoInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size)
00138 {
00139     unsigned char *ip1;
00140     unsigned char *ip2;
00141     int            dsize;
00142 
00143     if(!total_size || !buffer)
00144         return -1;
00145 
00146     dsize = (IP_MAXPACKET - *total_size);
00147 
00148     if(dsize < PROTO_BUFFER_SIZE)
00149        return -1; 
00150 
00151     ip1 = (char *)&proto->low_ip;
00152     ip2 = (char *)&proto->high_ip;
00153 
00154     if(proto->alerts == PS_ALERT_PORTSWEEP ||
00155        proto->alerts == PS_ALERT_PORTSWEEP_FILTERED)
00156     {
00157         dsize = snprintf((char *)buffer, PROTO_BUFFER_SIZE,
00158                 "Priority Count: %d\n"
00159                 "Connection Count: %d\n"
00160                 "IP Count: %d\n"
00161                 "Scanned IP Range: %d.%d.%d.%d:%d.%d.%d.%d\n"
00162                 "Port/Proto Count: %d\n"
00163                 "Port/Proto Range: %d:%d\n",
00164                 proto->priority_count,
00165                 proto->connection_count,
00166                 proto->u_ip_count,
00167                 ip1[0],ip1[1],ip1[2],ip1[3],
00168                 ip2[0],ip2[1],ip2[2],ip2[3],
00169                 proto->u_port_count,
00170                 proto->low_p,
00171                 proto->high_p);
00172     }
00173     else
00174     {
00175         dsize = snprintf((char *)buffer, PROTO_BUFFER_SIZE,
00176                 "Priority Count: %d\n"
00177                 "Connection Count: %d\n"
00178                 "IP Count: %d\n"
00179                 "Scanner IP Range: %d.%d.%d.%d:%d.%d.%d.%d\n"
00180                 "Port/Proto Count: %d\n"
00181                 "Port/Proto Range: %d:%d\n",
00182                 proto->priority_count,
00183                 proto->connection_count,
00184                 proto->u_ip_count,
00185                 ip1[0],ip1[1],ip1[2],ip1[3],
00186                 ip2[0],ip2[1],ip2[2],ip2[3],
00187                 proto->u_port_count,
00188                 proto->low_p,
00189                 proto->high_p);
00190     }
00191 
00192     *total_size += dsize;
00193 
00194     /*
00195     **  Set the payload size.  This is protocol independent.
00196     */
00197     g_tmp_pkt->dsize = dsize;
00198 
00199     return 0;
00200 }
00201 
00202 static int LogPortscanAlert(Packet *p, char *msg, u_int32_t event_id,
00203         u_int32_t event_ref, u_int32_t gen_id, u_int32_t sig_id)
00204 {
00205     char timebuf[TIMEBUF_SIZE];
00206     u_long src_addr = 0;
00207     u_long dst_addr = 0;
00208 
00209     if(!p->iph)
00210         return -1;
00211 
00212     /* Do not log if being suppressed */
00213     if ( p->iph )
00214     {
00215         src_addr = p->iph->ip_src.s_addr;
00216         dst_addr = p->iph->ip_dst.s_addr;
00217     }
00218 
00219     if( !sfthreshold_test(gen_id, sig_id, src_addr, dst_addr, p->pkth->ts.tv_sec) )
00220     {
00221         return 0;
00222     }
00223 
00224     ts_print((struct timeval *)&p->pkth->ts, timebuf);
00225 
00226     fprintf(g_logfile, "Time: %s\n", timebuf);
00227 
00228     if(event_id)
00229         fprintf(g_logfile, "event_id: %u\n", event_id);
00230     else
00231         fprintf(g_logfile, "event_ref: %u\n", event_ref);
00232 
00233     fprintf(g_logfile, "%s ", inet_ntoa(p->iph->ip_src));
00234     fprintf(g_logfile, "-> %s %s\n", inet_ntoa(p->iph->ip_dst), msg);
00235     fprintf(g_logfile, "%.*s\n", p->dsize, p->data);
00236 
00237     fflush(g_logfile);
00238 
00239     return 0;
00240 }
00241 
00242 static int GeneratePSSnortEvent(Packet *p,u_int32_t gen_id,u_int32_t sig_id, 
00243         u_int32_t sig_rev, u_int32_t class, u_int32_t priority, char *msg)
00244 {
00245     unsigned int event_id;
00246     
00247     event_id = GenerateSnortEvent(p,gen_id,sig_id,sig_rev,class,priority,msg);
00248 
00249     if(g_logfile)
00250         LogPortscanAlert(p, msg, event_id, 0, gen_id, sig_id);
00251 
00252     return event_id;
00253 }
00254 
00255 /*
00256 **  NAME
00257 **    GenerateOpenPortEvent::
00258 */
00259 /**
00260 **  We have to generate open port events differently because we tag these
00261 **  to the original portscan event.
00262 **
00263 **  @return int
00264 **
00265 **  @retval 0 success
00266 */
00267 static int GenerateOpenPortEvent(Packet *p, u_int32_t gen_id, u_int32_t sig_id,
00268         u_int32_t sig_rev, u_int32_t class, u_int32_t pri, 
00269         u_int32_t event_ref, struct timeval *event_time, char *msg)
00270 {
00271     Event event;
00272 
00273     /*
00274     **  This means that we logged an open port, but we don't have a event
00275     **  reference for it, so we don't log a snort event.  We still keep
00276     **  track of it though.
00277     */
00278     if(!event_ref)
00279         return 0;
00280 
00281     /* reset the thresholding subsystem checks for this packet */
00282     sfthreshold_reset();
00283             
00284     SetEvent(&event, gen_id, sig_id, sig_rev, class, pri, event_ref);
00285     //CallAlertFuncs(p,msg,NULL,&event);
00286 
00287     event.ref_time.tv_sec  = event_time->tv_sec;
00288     event.ref_time.tv_usec = event_time->tv_usec;
00289 
00290     if(p)
00291     {
00292         /*
00293          * Do threshold test for suppression and thresholding.  We have to do it
00294          * here since these are tagged packets, which aren't subject to thresholding,
00295          * but we want to do it for open port events.
00296          */
00297         if( !sfthreshold_test(gen_id, sig_id, p->iph->ip_src.s_addr,
00298                             p->iph->ip_dst.s_addr, p->pkth->ts.tv_sec) )
00299         {
00300             return 0;
00301         }
00302 
00303         CallLogFuncs(p,msg,NULL,&event);
00304     }
00305 
00306     if(g_logfile)
00307         LogPortscanAlert(p, msg, 0, event_ref, gen_id, sig_id);
00308 
00309     return event.event_id;
00310 }
00311 
00312 /*
00313 **  NAME
00314 **    MakeOpenPortInfo::
00315 */
00316 /** 
00317 **  Write out the open ports info for open port alerts.
00318 **
00319 **  @return integer
00320 */
00321 static int MakeOpenPortInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size,
00322          void *user)
00323 {
00324     int dsize;
00325 
00326     if(!total_size || !buffer)
00327         return -1;
00328 
00329     dsize = (IP_MAXPACKET - *total_size);
00330 
00331     if(dsize < PROTO_BUFFER_SIZE)
00332        return -1; 
00333 
00334     dsize = snprintf((char *)buffer, PROTO_BUFFER_SIZE,
00335               "Open Port: %u\n", *((unsigned short *)user));
00336 
00337     *total_size += dsize;
00338 
00339     /*
00340     **  Set the payload size.  This is protocol independent.
00341     */
00342     g_tmp_pkt->dsize = dsize;
00343 
00344     return 0;
00345 }
00346 
00347 /*
00348 **  NAME
00349 **    MakePortscanPkt::
00350 */
00351 /*
00352 **  We have to create this fake packet so portscan data can be passed
00353 **  through the unified output.
00354 **
00355 **  We want to copy the network and transport layer headers into our
00356 **  fake packet.
00357 **  
00358 */
00359 static int MakePortscanPkt(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type,
00360         void *user)
00361 {
00362     Packet *p;
00363     unsigned long  tmp_addr;
00364     unsigned int   hlen;
00365     unsigned int   ip_size = 0; 
00366   
00367     if(!ps_pkt && proto_type != PS_PROTO_OPEN_PORT)
00368        return -1;
00369 
00370     if(ps_pkt)
00371     { 
00372         p = (Packet *)ps_pkt->pkt;
00373 
00374         if(!p->iph)
00375             return -1;
00376 
00377         hlen = IP_HLEN(p->iph)<<2;
00378 
00379         if ( p->iph != g_tmp_pkt->iph )
00380             /*
00381              * it happen that ps_pkt->pkt can be the same
00382              * as g_tmp_pkt. Avoid overlapping copy then.
00383              */
00384              memcpy(g_tmp_pkt->iph, p->iph, hlen);
00385 
00386         if(ps_pkt->reverse_pkt)
00387         {
00388             tmp_addr = p->iph->ip_src.s_addr;
00389             g_tmp_pkt->iph->ip_src.s_addr = p->iph->ip_dst.s_addr;
00390             g_tmp_pkt->iph->ip_dst.s_addr = tmp_addr;
00391         }
00392 
00393         ip_size += hlen;
00394 
00395         g_tmp_pkt->iph->ip_proto = 0xff;
00396         g_tmp_pkt->iph->ip_ttl = 0x00;
00397         g_tmp_pkt->data = (u_char *)((u_char *)g_tmp_pkt->iph + hlen);
00398 
00399         g_tmp_pkt->pkth->ts.tv_sec = p->pkth->ts.tv_sec;
00400         g_tmp_pkt->pkth->ts.tv_usec = p->pkth->ts.tv_usec;
00401     }
00402 
00403     switch(proto_type)
00404     {
00405         case PS_PROTO_TCP:
00406         case PS_PROTO_UDP:
00407         case PS_PROTO_ICMP:
00408         case PS_PROTO_IP:
00409             if(MakeProtoInfo(proto, g_tmp_pkt->data, &ip_size))
00410                 return -1;
00411 
00412             break;
00413 
00414         case PS_PROTO_OPEN_PORT:
00415             if(MakeOpenPortInfo(proto, g_tmp_pkt->data, &ip_size, user))
00416                 return -1;
00417 
00418             break;
00419 
00420         default:
00421             return -1;
00422     }
00423 
00424     /*
00425     **  Let's finish up the IP header and checksum.
00426     */
00427     g_tmp_pkt->iph->ip_len = htons((short)ip_size);
00428     g_tmp_pkt->iph->ip_csum = 0;
00429     g_tmp_pkt->iph->ip_csum = 
00430         in_chksum_ip((u_short *)g_tmp_pkt->iph, (IP_HLEN(g_tmp_pkt->iph)<<2));
00431 
00432 
00433     /*
00434     **  And we set the pcap headers correctly so they decode.
00435     */
00436     g_tmp_pkt->pkth->caplen = ip_size + ETHERNET_HEADER_LEN;
00437     g_tmp_pkt->pkth->len    = ip_size + ETHERNET_HEADER_LEN;
00438 
00439     return 0;
00440 }
00441 
00442 static int PortscanAlertTcp(Packet *p, PS_PROTO *proto, int proto_type)
00443 {
00444     int iCtr;
00445     unsigned int event_ref;
00446     int portsweep = 0;
00447     
00448     if(!proto)
00449         return -1;
00450 
00451     switch(proto->alerts)
00452     {
00453         case PS_ALERT_ONE_TO_ONE:
00454             event_ref = GeneratePSSnortEvent(p, GENERATOR_PSNG, 
00455                     PSNG_TCP_PORTSCAN, 0, 0, 3, PSNG_TCP_PORTSCAN_STR);
00456             break;
00457 
00458         case PS_ALERT_ONE_TO_ONE_DECOY:
00459             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00460                     PSNG_TCP_DECOY_PORTSCAN,0,0,3,PSNG_TCP_DECOY_PORTSCAN_STR);
00461             break;
00462 
00463         case PS_ALERT_PORTSWEEP:
00464            event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00465                    PSNG_TCP_PORTSWEEP, 0, 0, 3, PSNG_TCP_PORTSWEEP_STR);
00466            portsweep = 1;
00467            
00468            break;
00469 
00470         case PS_ALERT_DISTRIBUTED:
00471             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00472                     PSNG_TCP_DISTRIBUTED_PORTSCAN, 0, 0, 3, 
00473                     PSNG_TCP_DISTRIBUTED_PORTSCAN_STR);
00474             break;
00475 
00476         case PS_ALERT_ONE_TO_ONE_FILTERED:
00477             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00478                     PSNG_TCP_FILTERED_PORTSCAN,0,0,3, 
00479                     PSNG_TCP_FILTERED_PORTSCAN_STR);
00480             break;
00481 
00482         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
00483             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00484                     PSNG_TCP_FILTERED_DECOY_PORTSCAN, 0,0,3, 
00485                     PSNG_TCP_FILTERED_DECOY_PORTSCAN_STR);
00486             break;
00487 
00488         case PS_ALERT_PORTSWEEP_FILTERED:
00489            event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00490                    PSNG_TCP_PORTSWEEP_FILTERED,0,0,3,
00491                    PSNG_TCP_PORTSWEEP_FILTERED_STR);
00492            portsweep = 1;
00493 
00494            return 0;
00495 
00496         case PS_ALERT_DISTRIBUTED_FILTERED:
00497             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
00498                     PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3, 
00499                     PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
00500             break;
00501 
00502         default:
00503             return 0;
00504     }
00505 
00506     /*
00507     **  Set the current event reference information for any open ports.
00508     */
00509     proto->event_ref  = event_ref;
00510     proto->event_time.tv_sec  = p->pkth->ts.tv_sec;
00511     proto->event_time.tv_usec = p->pkth->ts.tv_usec;
00512 
00513     /*
00514     **  Only log open ports for portsweeps after the alert has been
00515     **  generated.
00516     */
00517     if(proto->open_ports_cnt && !portsweep)
00518     {
00519         for(iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++)
00520         {
00521             PS_PKT ps_pkt;            
00522             
00523             memset(&ps_pkt, 0x00, sizeof(PS_PKT));
00524             ps_pkt.pkt = (void *)p;
00525 
00526             if(MakePortscanPkt(&ps_pkt, proto, PS_PROTO_OPEN_PORT, 
00527                         (void *)&proto->open_ports[iCtr]))
00528                 return -1;
00529 
00530             g_tmp_pkt->pkth->ts.tv_usec += 1;
00531             GenerateOpenPortEvent(g_tmp_pkt,GENERATOR_PSNG,PSNG_OPEN_PORT,
00532                     0,0,3, proto->event_ref, &proto->event_time, 
00533                     PSNG_OPEN_PORT_STR);
00534         }
00535     }
00536 
00537     return 0;
00538 }
00539 
00540 static int PortscanAlertUdp(Packet *p, PS_PROTO *proto, int proto_type)
00541 {
00542     if(!proto)
00543         return -1;
00544 
00545     switch(proto->alerts)
00546     {
00547         case PS_ALERT_ONE_TO_ONE:
00548             GeneratePSSnortEvent(p, GENERATOR_PSNG, PSNG_UDP_PORTSCAN, 0, 0, 3,
00549                     PSNG_UDP_PORTSCAN_STR);
00550             break;
00551 
00552         case PS_ALERT_ONE_TO_ONE_DECOY:
00553             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_DECOY_PORTSCAN, 0, 0, 3,
00554                     PSNG_UDP_DECOY_PORTSCAN_STR);
00555             break;
00556 
00557         case PS_ALERT_PORTSWEEP:
00558            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_PORTSWEEP, 0, 0, 3,
00559                     PSNG_UDP_PORTSWEEP_STR);
00560             break;
00561 
00562         case PS_ALERT_DISTRIBUTED:
00563             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_DISTRIBUTED_PORTSCAN, 
00564                     0, 0, 3, PSNG_UDP_DISTRIBUTED_PORTSCAN_STR);
00565             break;
00566 
00567         case PS_ALERT_ONE_TO_ONE_FILTERED:
00568             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_FILTERED_PORTSCAN,0,0,3,
00569                     PSNG_UDP_FILTERED_PORTSCAN_STR);
00570             break;
00571 
00572         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
00573             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_FILTERED_DECOY_PORTSCAN,
00574                     0,0,3, PSNG_UDP_FILTERED_DECOY_PORTSCAN_STR);
00575             break;
00576 
00577         case PS_ALERT_PORTSWEEP_FILTERED:
00578            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_PORTSWEEP_FILTERED,0,0,3,
00579                     PSNG_UDP_PORTSWEEP_FILTERED_STR);
00580             break;
00581 
00582         case PS_ALERT_DISTRIBUTED_FILTERED:
00583             GeneratePSSnortEvent(p,GENERATOR_PSNG,
00584                     PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3, 
00585                     PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
00586             break;
00587 
00588         default:
00589             break;
00590     }
00591 
00592     return 0;
00593 }
00594 
00595 static int PortscanAlertIp(Packet *p, PS_PROTO *proto, int proto_type)
00596 {
00597     if(!proto)
00598         return -1;
00599 
00600     switch(proto->alerts)
00601     {
00602         case PS_ALERT_ONE_TO_ONE:
00603             GeneratePSSnortEvent(p, GENERATOR_PSNG, PSNG_IP_PORTSCAN, 0, 0, 3,
00604                     PSNG_IP_PORTSCAN_STR);
00605             break;
00606 
00607         case PS_ALERT_ONE_TO_ONE_DECOY:
00608             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_DECOY_PORTSCAN, 0, 0, 3,
00609                     PSNG_IP_DECOY_PORTSCAN_STR);
00610             break;
00611 
00612         case PS_ALERT_PORTSWEEP:
00613            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_PORTSWEEP, 0, 0, 3,
00614                     PSNG_IP_PORTSWEEP_STR);
00615             break;
00616 
00617         case PS_ALERT_DISTRIBUTED:
00618             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_DISTRIBUTED_PORTSCAN, 
00619                     0, 0, 3, PSNG_IP_DISTRIBUTED_PORTSCAN_STR);
00620             break;
00621 
00622         case PS_ALERT_ONE_TO_ONE_FILTERED:
00623             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_FILTERED_PORTSCAN,0,0,3,
00624                     PSNG_IP_FILTERED_PORTSCAN_STR);
00625             break;
00626 
00627         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
00628             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_FILTERED_DECOY_PORTSCAN,
00629                     0,0,3, PSNG_IP_FILTERED_DECOY_PORTSCAN_STR);
00630             break;
00631 
00632         case PS_ALERT_PORTSWEEP_FILTERED:
00633            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_PORTSWEEP_FILTERED,0,0,3,
00634                     PSNG_IP_PORTSWEEP_FILTERED_STR);
00635             break;
00636 
00637         case PS_ALERT_DISTRIBUTED_FILTERED:
00638             GeneratePSSnortEvent(p,GENERATOR_PSNG,
00639                     PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3, 
00640                     PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
00641             break;
00642 
00643         default:
00644             break;
00645     }
00646 
00647     return 0;
00648 }
00649 
00650 static int PortscanAlertIcmp(Packet *p, PS_PROTO *proto, int proto_type)
00651 {
00652     if(!proto)
00653         return -1;
00654 
00655     switch(proto->alerts)
00656     {
00657         case PS_ALERT_PORTSWEEP:
00658            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_ICMP_PORTSWEEP, 0, 0, 3,
00659                     PSNG_ICMP_PORTSWEEP_STR);
00660             break;
00661 
00662         case PS_ALERT_PORTSWEEP_FILTERED:
00663            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_ICMP_PORTSWEEP_FILTERED,0,0,3,
00664                     PSNG_ICMP_PORTSWEEP_FILTERED_STR);
00665             break;
00666 
00667         default:
00668             break;
00669     }
00670 
00671     return 0;
00672 }
00673 
00674 static int PortscanAlert(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type)
00675 {
00676     Packet *p;
00677 
00678     if(!ps_pkt || !ps_pkt->pkt)
00679         return -1;
00680 
00681     p = (Packet *)ps_pkt->pkt;
00682     
00683     if(proto->alerts == PS_ALERT_OPEN_PORT)
00684     {
00685         if(MakePortscanPkt(ps_pkt, proto, PS_PROTO_OPEN_PORT, (void *)&p->sp))
00686             return -1;
00687 
00688         GenerateOpenPortEvent(g_tmp_pkt,GENERATOR_PSNG,PSNG_OPEN_PORT,0,0,3,
00689                 proto->event_ref, &proto->event_time, PSNG_OPEN_PORT_STR);
00690     }
00691     else
00692     {
00693         if(MakePortscanPkt(ps_pkt, proto, proto_type, NULL))
00694             return -1;
00695 
00696         switch(proto_type)
00697         {
00698             case PS_PROTO_TCP:
00699                 PortscanAlertTcp(g_tmp_pkt, proto, proto_type);
00700 
00701 #ifdef GIDS
00702                 if((SppStickydIsRunning()) && sdt.sfportscan)
00703                 {
00704                     AddIpToBlockTree(g_tmp_pkt, 0, sdt.sfportscan);
00705                 }
00706 #endif /* GIDS */
00707 
00708                 break;
00709 
00710             case PS_PROTO_UDP:
00711                 PortscanAlertUdp(g_tmp_pkt, proto, proto_type);
00712 
00713 #ifdef GIDS
00714                 if((SppStickydIsRunning()) && sdt.sfportscan)
00715                 {
00716                     AddIpToBlockTree(g_tmp_pkt, 0, sdt.sfportscan);
00717                 }
00718 #endif /* GIDS */
00719 
00720                 break;
00721 
00722             case PS_PROTO_ICMP:
00723                 PortscanAlertIcmp(g_tmp_pkt, proto, proto_type);
00724 
00725 #ifdef GIDS
00726                 if((SppStickydIsRunning()) && sdt.sfportscan)
00727                 {
00728                     AddIpToBlockTree(g_tmp_pkt, 0, sdt.sfportscan);
00729                 }
00730 #endif /* GIDS */
00731 
00732                 break;
00733 
00734             case PS_PROTO_IP:
00735                 PortscanAlertIp(g_tmp_pkt, proto, proto_type);
00736 
00737 #ifdef GIDS
00738                 if((SppStickydIsRunning()) && sdt.sfportscan)
00739                 {
00740                     AddIpToBlockTree(g_tmp_pkt, 0, sdt.sfportscan);
00741                 }
00742 #endif /* GIDS */
00743 
00744                 break;
00745         }
00746     }
00747 
00748     return 0;
00749 }
00750 
00751 static void PortscanDetect(Packet *p, void *context)
00752 {
00753     PS_PKT ps_pkt;
00754 
00755     if(!p || !p->iph || (p->packet_flags & PKT_REBUILT_STREAM))
00756         return;
00757 
00758     if(!(p->preprocessors & PP_SFPORTSCAN))
00759     {
00760         return;
00761     }
00762 
00763     memset(&ps_pkt, 0x00, sizeof(PS_PKT));
00764     ps_pkt.pkt = (void *)p;
00765 
00766     ps_detect(&ps_pkt);
00767 
00768     if(ps_pkt.scanner && ps_pkt.scanner->proto[ps_pkt.proto_idx].alerts &&
00769             (ps_pkt.scanner->proto[ps_pkt.proto_idx].alerts != PS_ALERT_GENERATED))
00770     {
00771         PortscanAlert(&ps_pkt, &ps_pkt.scanner->proto[ps_pkt.proto_idx], 
00772                 ps_pkt.proto);
00773     }
00774 
00775     if(ps_pkt.scanned && ps_pkt.scanned->proto[ps_pkt.proto_idx].alerts &&
00776             (ps_pkt.scanned->proto[ps_pkt.proto_idx].alerts != PS_ALERT_GENERATED))
00777     {
00778         PortscanAlert(&ps_pkt, &ps_pkt.scanned->proto[ps_pkt.proto_idx], 
00779                 ps_pkt.proto);
00780     }
00781 
00782     return;
00783 }
00784 
00785 static void FatalErrorNoOption(u_char *option)
00786 {
00787     FatalError("%s(%d) => No argument to '%s' config option.\n", 
00788             file_name, file_line, option);
00789 
00790     return;
00791 }
00792 
00793 static void FatalErrorNoEnd(char *option)
00794 {
00795     FatalError("%s(%d) => No ending brace to '%s' config option.\n", 
00796             file_name, file_line, option);
00797 }
00798 
00799 static void FatalErrorInvalidArg(char *option)
00800 {
00801     FatalError("%s(%d) => Invalid argument to '%s' config option.\n", 
00802             file_name, file_line, option);
00803 }
00804 
00805 static void FatalErrorInvalidOption(char *option)
00806 {
00807     FatalError("%s(%d) => Invalid option '%s' to portscan preprocessor.\n", 
00808             file_name, file_line, option);
00809 }
00810 
00811 static void ParseProtos(int *protos)
00812 {
00813     char *pcTok;
00814 
00815     if(!protos)
00816         return;
00817 
00818     *protos = 0;
00819 
00820     pcTok = strtok(NULL, DELIMITERS);
00821     while(pcTok)
00822     {
00823         if(!strcasecmp(pcTok, "tcp"))
00824             *protos |= PS_PROTO_TCP;
00825         else if(!strcasecmp(pcTok, "udp"))
00826             *protos |= PS_PROTO_UDP;
00827         else if(!strcasecmp(pcTok, "icmp"))
00828             *protos |= PS_PROTO_ICMP;
00829         else if(!strcasecmp(pcTok, "ip"))
00830             *protos |= PS_PROTO_IP;
00831         else if(!strcasecmp(pcTok, "all"))
00832             *protos = PS_PROTO_ALL;
00833         else if(!strcasecmp(pcTok, TOKEN_ARG_END))
00834             return;
00835         else
00836             FatalErrorInvalidArg("proto");
00837 
00838         pcTok = strtok(NULL, DELIMITERS);
00839     }
00840 
00841     if(!pcTok)
00842         FatalErrorNoEnd("proto");
00843 
00844     return;
00845 }
00846 
00847 static void ParseScanType(int *scan_types)
00848 {
00849     char *pcTok;
00850     
00851     if(!scan_types)
00852         return;
00853 
00854     *scan_types = 0;
00855 
00856     pcTok = strtok(NULL, DELIMITERS);
00857     while(pcTok)
00858     {
00859         if(!strcasecmp(pcTok, "portscan"))
00860             *scan_types |= PS_TYPE_PORTSCAN;
00861         else if(!strcasecmp(pcTok, "portsweep"))
00862             *scan_types |= PS_TYPE_PORTSWEEP;
00863         else if(!strcasecmp(pcTok, "decoy_portscan"))
00864             *scan_types |= PS_TYPE_DECOYSCAN;
00865         else if(!strcasecmp(pcTok, "distributed_portscan"))
00866             *scan_types |= PS_TYPE_DISTPORTSCAN;
00867         else if(!strcasecmp(pcTok, "all"))
00868             *scan_types = PS_TYPE_ALL;
00869         else if(!strcasecmp(pcTok, TOKEN_ARG_END))
00870             return;
00871         else
00872             FatalErrorInvalidArg("scan_type");
00873 
00874         pcTok = strtok(NULL, DELIMITERS);
00875     }
00876 
00877     if(!pcTok)
00878         FatalErrorNoEnd("scan_type");
00879 
00880     return;
00881 }
00882 
00883 static void ParseSenseLevel(int *sense_level)
00884 {
00885     char *pcTok;
00886     
00887     if(!sense_level)
00888         return;
00889 
00890     *sense_level = 0;
00891 
00892     pcTok = strtok(NULL, DELIMITERS);
00893     while(pcTok)
00894     {
00895         if(!strcasecmp(pcTok, "low"))
00896             *sense_level = PS_SENSE_LOW;
00897         else if(!strcasecmp(pcTok, "medium"))
00898             *sense_level = PS_SENSE_MEDIUM;
00899         else if(!strcasecmp(pcTok, "high"))
00900             *sense_level = PS_SENSE_HIGH;
00901         else if(!strcmp(pcTok, TOKEN_ARG_END))
00902             return;
00903         else
00904             FatalErrorInvalidArg("sense_level");
00905 
00906         pcTok = strtok(NULL, DELIMITERS);
00907     }
00908 
00909     if(!pcTok)
00910         FatalErrorNoEnd("sense_level");
00911 
00912     return;
00913 }
00914 
00915 static void ParseIpList(IPSET **ip_list, char *option)
00916 {
00917     char *pcTok;
00918 
00919     if(!ip_list)
00920         return;
00921 
00922     pcTok = strtok(NULL, TOKEN_ARG_END);
00923     if(!pcTok)
00924         FatalErrorInvalidArg(option);
00925 
00926     *ip_list = ipset_new(IPV4_FAMILY);
00927     if(!*ip_list)
00928         FatalError("Failed to initialize ip_list in portscan preprocessor.\n");
00929 
00930     if(ip4_setparse(*ip_list, pcTok))
00931         FatalError("%s(%d) => Invalid ip_list to '%s' option.\n",
00932                 file_name, file_line, option);
00933 
00934     return;
00935 }
00936 
00937 static void ParseMemcap(int *memcap)
00938 {
00939     char *pcTok;
00940 
00941     if(!memcap)
00942         return;
00943     
00944     *memcap = 0;
00945     
00946     pcTok = strtok(NULL, DELIMITERS);
00947     if(!pcTok)
00948         FatalErrorNoEnd("memcap");
00949 
00950     *memcap = atoi(pcTok);
00951 
00952     if(*memcap <= 0)
00953         FatalErrorInvalidArg("memcap");
00954 
00955     pcTok = strtok(NULL, DELIMITERS);
00956     if(!pcTok)
00957         FatalErrorNoEnd("memcap");
00958 
00959     if(strcmp(pcTok, TOKEN_ARG_END))
00960         FatalErrorInvalidArg("memcap");
00961     
00962     return;
00963 }
00964 
00965 static void PrintPortscanConf(int detect_scans, int detect_scan_type,
00966         int sense_level, IPSET *scanner, IPSET *scanned, IPSET *watch,
00967         int memcap)
00968 {
00969     char buf[STD_BUF+1];
00970     char ip_str[80], mask_str[80];
00971     int proto_cnt = 0;
00972     CIDRBLOCK *p;
00973 
00974     LogMessage("Portscan Detection Config:\n");
00975     
00976     memset(buf, 0, STD_BUF+1);
00977     snprintf(buf, STD_BUF, "    Detect Protocols:  ");
00978     if(detect_scans & PS_PROTO_TCP)  { sfsnprintfappend(buf, STD_BUF, "TCP ");  proto_cnt++; }
00979     if(detect_scans & PS_PROTO_UDP)  { sfsnprintfappend(buf, STD_BUF, "UDP ");  proto_cnt++; }
00980     if(detect_scans & PS_PROTO_ICMP) { sfsnprintfappend(buf, STD_BUF, "ICMP "); proto_cnt++; }
00981     if(detect_scans & PS_PROTO_IP)   { sfsnprintfappend(buf, STD_BUF, "IP");    proto_cnt++; }
00982     LogMessage("%s\n", buf);
00983 
00984     memset(buf, 0, STD_BUF+1);
00985     snprintf(buf, STD_BUF, "    Detect Scan Type:  ");
00986     if(detect_scan_type & PS_TYPE_PORTSCAN)
00987         sfsnprintfappend(buf, STD_BUF, "portscan ");
00988     if(detect_scan_type & PS_TYPE_PORTSWEEP)
00989         sfsnprintfappend(buf, STD_BUF, "portsweep ");
00990     if(detect_scan_type & PS_TYPE_DECOYSCAN)
00991         sfsnprintfappend(buf, STD_BUF, "decoy_portscan ");
00992     if(detect_scan_type & PS_TYPE_DISTPORTSCAN)
00993         sfsnprintfappend(buf, STD_BUF, "distributed_portscan");
00994     LogMessage("%s\n", buf);
00995 
00996     memset(buf, 0, STD_BUF+1);
00997     snprintf(buf, STD_BUF, "    Sensitivity Level: ");
00998     if(sense_level == PS_SENSE_HIGH)
00999         sfsnprintfappend(buf, STD_BUF, "High/Experimental");
01000     if(sense_level == PS_SENSE_MEDIUM)
01001         sfsnprintfappend(buf, STD_BUF, "Medium");
01002     if(sense_level == PS_SENSE_LOW)
01003         sfsnprintfappend(buf, STD_BUF, "Low");
01004     LogMessage("%s\n", buf);
01005 
01006     LogMessage("    Memcap (in bytes): %d\n", memcap);
01007     LogMessage("    Number of Nodes:   %d\n",
01008             memcap / (sizeof(PS_PROTO)*proto_cnt-1));
01009 
01010     if(g_logpath[0])
01011         LogMessage("    Logfile:           %s\n", g_logpath); 
01012 
01013     if(scanner)
01014     {
01015         LogMessage("    Ignore Scanner IP List:\n");
01016         for(p = (CIDRBLOCK*)sflist_first(&scanner->cidr_list);
01017             p;
01018             p = (CIDRBLOCK*)sflist_next(&scanner->cidr_list))
01019         {
01020             ip4_sprintx(ip_str, sizeof(ip_str), &p->ip);
01021             ip4_sprintx(mask_str, sizeof(mask_str), &p->mask);
01022 
01023             if(p->notflag)
01024                 LogMessage("        !%s / %s\n", ip_str, mask_str);
01025             else
01026                 LogMessage("        %s / %s\n", ip_str, mask_str);
01027         }
01028     }
01029 
01030     if(scanned)
01031     {
01032         LogMessage("    Ignore Scanned IP List:\n");
01033         for(p = (CIDRBLOCK*)sflist_first(&scanned->cidr_list);
01034             p;
01035             p = (CIDRBLOCK*)sflist_next(&scanned->cidr_list))
01036         {
01037             ip4_sprintx(ip_str, sizeof(ip_str), &p->ip);
01038             ip4_sprintx(mask_str, sizeof(mask_str), &p->mask);
01039 
01040             if(p->notflag)
01041                 LogMessage("        !%s / %s\n", ip_str, mask_str);
01042             else
01043                 LogMessage("        %s / %s\n", ip_str, mask_str);
01044         }
01045     }
01046 
01047     if(watch)
01048     {
01049         LogMessage("    Ignore Watch IP List:\n");
01050         for(p = (CIDRBLOCK*)sflist_first(&watch->cidr_list);
01051             p;
01052             p = (CIDRBLOCK*)sflist_next(&watch->cidr_list))
01053         {
01054             ip4_sprintx(ip_str, sizeof(ip_str), &p->ip);
01055             ip4_sprintx(mask_str, sizeof(mask_str), &p->mask);
01056 
01057             if(p->notflag)
01058                 LogMessage("        !%s / %s\n", ip_str, mask_str);
01059             else
01060                 LogMessage("        %s / %s\n", ip_str, mask_str);
01061         }
01062     }
01063 
01064     LogMessage("\n");
01065 
01066     return;
01067 }
01068 
01069 static void ParseLogFile(FILE **flog, u_char *logfile, int logfile_size)
01070 {
01071     char *pcTok;
01072 
01073     pcTok = strtok(NULL, DELIMITERS);
01074     if(!pcTok)
01075         FatalErrorNoEnd("logfile");
01076 
01077     if(pcTok[0] == '/')
01078         snprintf(logfile, logfile_size, "%s", pcTok);
01079     else
01080         snprintf(logfile, logfile_size, "%s/%s", pv.log_dir,pcTok);
01081 
01082     pcTok = strtok(NULL, DELIMITERS);
01083     if(!pcTok)
01084         FatalErrorNoEnd("logfile");
01085 
01086     if(strcmp(pcTok, TOKEN_ARG_END))
01087         FatalErrorInvalidArg("logfile");
01088 
01089     *flog = fopen(logfile, "a+");
01090     if(!(*flog))
01091         FatalError("%s(%d) => '%s' could not be opened.\n", 
01092                 file_name, file_line, logfile);
01093     
01094     return;
01095 }
01096     
01097 static void PortscanInit(u_char *args)
01098 {
01099     int    sense_level = PS_SENSE_LOW;
01100     int    protos      = (PS_PROTO_TCP | PS_PROTO_UDP);
01101     int    scan_types  = PS_TYPE_ALL;
01102     int    memcap      = 1048576;
01103     IPSET *ignore_scanners = NULL;
01104     IPSET *ignore_scanned = NULL;
01105     IPSET *watch_ip = NULL;
01106     char  *pcTok;
01107     int    iRet;
01108 
01109     g_logpath[0] = 0x00;
01110 
01111     if(args)
01112     {
01113         pcTok = strtok(args, DELIMITERS);
01114         while(pcTok)
01115         {
01116             if(!strcasecmp(pcTok, "proto"))
01117             {
01118                 pcTok = strtok(NULL, DELIMITERS);
01119                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01120                     FatalErrorNoOption("proto");
01121 
01122                 ParseProtos(&protos);
01123             }
01124             else if(!strcasecmp(pcTok, "scan_type"))
01125             {
01126                 pcTok = strtok(NULL, DELIMITERS);
01127                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01128                     FatalErrorNoOption("scan_type");
01129 
01130                 ParseScanType(&scan_types);
01131             }
01132             else if(!strcasecmp(pcTok, "sense_level"))
01133             {
01134                 pcTok = strtok(NULL, DELIMITERS);
01135                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01136                     FatalErrorNoOption("sense_level");
01137 
01138                 ParseSenseLevel(&sense_level);
01139             }
01140             else if(!strcasecmp(pcTok, "ignore_scanners"))
01141             {
01142                 pcTok = strtok(NULL, DELIMITERS);
01143                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01144                     FatalErrorNoOption("ignore_scanners");
01145 
01146                 ParseIpList(&ignore_scanners, "ignore_scanners");
01147             }
01148             else if(!strcasecmp(pcTok, "ignore_scanned"))
01149             {
01150                 pcTok = strtok(NULL, DELIMITERS);
01151                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01152                     FatalErrorNoOption("ignore_scanned");
01153 
01154                 ParseIpList(&ignore_scanned, "ignore_scanned");
01155             }
01156             else if(!strcasecmp(pcTok, "watch_ip"))
01157             {
01158                 pcTok = strtok(NULL, DELIMITERS);
01159                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01160                     FatalErrorNoOption("watch_ip");
01161 
01162                 ParseIpList(&watch_ip, "watch_ip");
01163             }
01164             else if(!strcasecmp(pcTok, "print_tracker"))
01165             {
01166                 g_print_tracker = 1;
01167             }
01168             else if(!strcasecmp(pcTok, "memcap"))
01169             {
01170                 pcTok = strtok(NULL, DELIMITERS);
01171                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01172                     FatalErrorNoOption("memcap");
01173 
01174                 ParseMemcap(&memcap);
01175             }
01176             else if(!strcasecmp(pcTok, "logfile"))
01177             {
01178                 pcTok = strtok(NULL, DELIMITERS);
01179                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
01180                     FatalErrorNoOption("logfile");
01181 
01182                 ParseLogFile(&g_logfile, g_logpath, sizeof(g_logpath));
01183             }
01184             else if(!strcasecmp(pcTok, "include_midstream"))
01185             {
01186                 g_include_midstream = 1;
01187             }
01188             else
01189             {
01190                 FatalErrorInvalidOption(pcTok);
01191             }
01192 
01193             pcTok = strtok(NULL, DELIMITERS);
01194         }
01195     }
01196 
01197     if((iRet = ps_init(protos, scan_types, sense_level, ignore_scanners,
01198                 ignore_scanned, watch_ip, memcap)))
01199     {
01200         if(iRet == -2)
01201         {
01202             FatalError("%s(%d) => 'memcap' limit not sufficient to run "
01203                        "sfportscan preprocessor.  Please increase this "
01204                        "value or keep the default memory usage.\n", 
01205                        file_name, file_line);
01206         }
01207 
01208         FatalError("Failed to initialize the sfportscan detection module.  "
01209                    "Please check your configuration before submitting a "
01210                    "bug.\n");
01211     }
01212 
01213     AddFuncToPreprocList(PortscanDetect);
01214 
01215     PrintPortscanConf(protos, scan_types, sense_level, ignore_scanners,
01216             ignore_scanned, watch_ip, memcap);
01217 
01218     PortscanPacketInit();
01219 
01220     return;
01221 }
01222 
01223 void SetupPsng(void)
01224 {
01225     RegisterPreprocessor("sfportscan", PortscanInit);
01226 
01227     return;
01228 }

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