1 /****************************************************************************
2  *
3  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4  * Copyright (C) 2004-2013 Sourcefire, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License Version 2 as
8  * published by the Free Software Foundation.  You may not use, modify or
9  * distribute this program under any other version of the GNU General
10  * Public License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *
21  ****************************************************************************/
22 
23 /*
24 **  @file       spp_sfportscan.c
25 **
26 **  @author     Daniel Roelker <droelker@sourcefire.com>
27 **
28 **  @brief      Portscan detection
29 **
30 **  NOTES
31 **    - User Configuration:  The following is a list of parameters that can
32 **      be configured through the user interface:
33 **
34 **      proto  { tcp udp icmp ip all }
35 **      scan_type { portscan portsweep decoy_portscan distributed_portscan all }
36 **      sense_level { high }    # high, medium, low
37 **      watch_ip { }            # list of IPs, CIDR blocks
38 **      ignore_scanners { }     # list of IPs, CIDR blocks
39 **      ignore_scanned { }      # list of IPs, CIDR blocks
40 **      memcap { 10000000 }     # number of max bytes to allocate
41 **      logfile { /tmp/ps.log } # file to log detailed portscan info
42 */
43 
44 #include <assert.h>
45 #include <sys/types.h>
46 #include <errno.h>
47 
48 #ifndef WIN32
49 # include <sys/socket.h>
50 # include <netinet/in.h>
51 # include <arpa/inet.h>
52 #endif /* !WIN32 */
53 
54 #ifdef HAVE_CONFIG_H
55 #include "config.h"
56 #endif
57 
58 #include "decode.h"
59 #include "encode.h"
60 #include "plugbase.h"
61 #include "generators.h"
62 #include "event_wrapper.h"
63 #include "util.h"
64 #include "ipobj.h"
65 #include "checksum.h"
66 #include "packet_time.h"
67 #include "snort.h"
68 #include "sfthreshold.h"
69 #include "sfsnprintfappend.h"
70 #include "sf_iph.h"
71 #include "session_api.h"
72 #include "sfdaq.h"
73 
74 #include "portscan.h"
75 
76 #include "profiler.h"
77 #include "reload.h"
78 
79 #ifdef REG_TEST
80 #include "reg_test.h"
81 #endif
82 
83 
84 #define DELIMITERS " \t\n"
85 #define TOKEN_ARG_BEGIN "{"
86 #define TOKEN_ARG_END   "}"
87 
88 #define PROTO_BUFFER_SIZE 256
89 
90 extern char *file_name;
91 extern int   file_line;
92 
93 tSfPolicyUserContextId portscan_config = NULL;
94 PortscanConfig *portscan_eval_config = NULL;
95 
96 static Packet *g_tmp_pkt = NULL;
97 static FILE   *g_logfile = NULL;
98 
99 #ifdef PERF_PROFILING
100 PreprocStats sfpsPerfStats;
101 #endif
102 
103 static void PortscanResetFunction(int signal, void *foo);
104 static void PortscanResetStatsFunction(int signal, void *foo);
105 static void ParsePortscan(struct _SnortConfig *, PortscanConfig *, char *);
106 static void PortscanFreeConfigs(tSfPolicyUserContextId );
107 static void PortscanFreeConfig(PortscanConfig *);
108 static void PortscanOpenLogFile(struct _SnortConfig *, void *);
109 static int PortscanGetProtoBits(int);
110 
111 #ifdef SNORT_RELOAD
112 static void PortscanReload(struct _SnortConfig *, char *, void **);
113 static int PortscanReloadVerify(struct _SnortConfig *, void *);
114 static void * PortscanReloadSwap(struct _SnortConfig *, void *);
115 static void PortscanReloadSwapFree(void *);
116 #endif
117 
118 /*
119 **  NAME
120 **    PortscanPacketInit::
121 */
122 /**
123 **  Initialize the Packet structure buffer so we can generate our
124 **  alert packets for portscan.  We initialize the various fields in
125 **  the Packet structure and set the hardware layer for easy identification
126 **  by user interfaces.
127 **
128 **  @return int
129 **
130 **  @retval !0 initialization failed
131 **  @retval  0 success
132 */
133 #define IPPROTO_PS 0xFF
134 
PortscanPacketInit(void)135 static int PortscanPacketInit(void)
136 {
137     g_tmp_pkt = Encode_New();
138     return 0;
139 }
140 
PortscanCleanExitFunction(int signal,void * foo)141 void PortscanCleanExitFunction(int signal, void *foo)
142 {
143     ps_cleanup();
144 
145     Encode_Delete(g_tmp_pkt);
146     g_tmp_pkt = NULL;
147 
148     PortscanFreeConfigs(portscan_config);
149     portscan_config = NULL;
150 }
151 
152 
PortscanResetFunction(int signal,void * foo)153 static void PortscanResetFunction(int signal, void *foo)
154 {
155     ps_reset();
156 }
157 
PortscanResetStatsFunction(int signal,void * foo)158 static void PortscanResetStatsFunction(int signal, void *foo)
159 {
160     return;
161 }
162 
163 /*
164 **  NAME
165 **    MakeProtoInfo::
166 */
167 /**
168 **  This routine makes the portscan payload for the events.  The listed
169 **  info is:
170 **    - priority count (number of error transmissions RST/ICMP UNREACH)
171 **    - connection count (number of protocol connections SYN)
172 **    - ip count (number of IPs that communicated with host)
173 **    - ip range (low to high range of IPs)
174 **    - port count (number of port changes that occurred on host)
175 **    - port range (low to high range of ports connected too)
176 **
177 **  @return integer
178 **
179 **  @retval -1 buffer not large enough
180 **  @retval  0 successful
181 */
MakeProtoInfo(PS_PROTO * proto,u_char * buffer,u_int * total_size)182 static int MakeProtoInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size)
183 {
184     int             dsize;
185     sfaddr_t        *ip1, *ip2;
186 
187 
188     if(!total_size || !buffer)
189         return -1;
190 
191     dsize = (g_tmp_pkt->max_dsize - *total_size);
192 
193     if(dsize < PROTO_BUFFER_SIZE)
194        return -1;
195 
196     ip1 = &proto->low_ip;
197     ip2 = &proto->high_ip;
198 
199     if(proto->alerts == PS_ALERT_PORTSWEEP ||
200        proto->alerts == PS_ALERT_PORTSWEEP_FILTERED)
201     {
202         SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE,
203                       "Priority Count: %d\n"
204                       "Connection Count: %d\n"
205                       "IP Count: %d\n"
206                       "Scanned IP Range: %s:",
207                       proto->priority_count,
208                       proto->connection_count,
209                       proto->u_ip_count,
210                       inet_ntoa(ip1));
211 
212         /* Now print the high ip into the buffer.  This saves us
213          * from having to copy the results of inet_ntoa (which is
214          * a static buffer) to avoid the reuse of that buffer when
215          * more than one use of inet_ntoa is within the same printf.
216          */
217         SnortSnprintfAppend((char *)buffer, PROTO_BUFFER_SIZE,
218                       "%s\n"
219                       "Port/Proto Count: %d\n"
220                       "Port/Proto Range: %d:%d\n",
221                       inet_ntoa(ip2),
222                       proto->u_port_count,
223                       proto->low_p,
224                       proto->high_p);
225     }
226     else
227     {
228         SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE,
229                       "Priority Count: %d\n"
230                       "Connection Count: %d\n"
231                       "IP Count: %d\n"
232                       "Scanner IP Range: %s:",
233                       proto->priority_count,
234                       proto->connection_count,
235                       proto->u_ip_count,
236                       inet_ntoa(ip1)
237                       );
238 
239         /* Now print the high ip into the buffer.  This saves us
240          * from having to copy the results of inet_ntoa (which is
241          * a static buffer) to avoid the reuse of that buffer when
242          * more than one use of inet_ntoa is within the same printf.
243          */
244         SnortSnprintfAppend((char *)buffer, PROTO_BUFFER_SIZE,
245                       "%s\n"
246                       "Port/Proto Count: %d\n"
247                       "Port/Proto Range: %d:%d\n",
248                       inet_ntoa(ip2),
249                       proto->u_port_count,
250                       proto->low_p,
251                       proto->high_p);
252     }
253 
254     dsize = SnortStrnlen((const char *)buffer, PROTO_BUFFER_SIZE);
255     *total_size += dsize;
256 
257     /*
258     **  Set the payload size.  This is protocol independent.
259     */
260     g_tmp_pkt->dsize = dsize;
261 
262     return 0;
263 }
264 
LogPortscanAlert(Packet * p,const char * msg,uint32_t event_id,uint32_t event_ref,uint32_t gen_id,uint32_t sig_id)265 static int LogPortscanAlert(Packet *p, const char *msg, uint32_t event_id,
266         uint32_t event_ref, uint32_t gen_id, uint32_t sig_id)
267 {
268     char timebuf[TIMEBUF_SIZE];
269     sfaddr_t* src_addr;
270     sfaddr_t* dst_addr;
271 
272     if(!p->iph_api)
273         return -1;
274 
275     /* Do not log if being suppressed */
276     src_addr = GET_SRC_IP(p);
277     dst_addr = GET_DST_IP(p);
278 
279     if( sfthreshold_test(gen_id, sig_id, src_addr, dst_addr, p->pkth->ts.tv_sec) )
280     {
281         return 0;
282     }
283 
284     ts_print((struct timeval *)&p->pkth->ts, timebuf);
285 
286     fprintf(g_logfile, "Time: %s\n", timebuf);
287 
288     if(event_id)
289         fprintf(g_logfile, "event_id: %u\n", event_id);
290     else
291         fprintf(g_logfile, "event_ref: %u\n", event_ref);
292 
293     fprintf(g_logfile, "%s ", inet_ntoa(GET_SRC_ADDR(p)));
294     fprintf(g_logfile, "-> %s %s\n", inet_ntoa(GET_DST_ADDR(p)), msg);
295     fprintf(g_logfile, "%.*s\n", p->dsize, p->data);
296 
297     fflush(g_logfile);
298 
299     return 0;
300 }
301 
GeneratePSSnortEvent(Packet * p,uint32_t gen_id,uint32_t sig_id,uint32_t sig_rev,uint32_t class,uint32_t priority,const char * msg)302 static int GeneratePSSnortEvent(Packet *p,uint32_t gen_id,uint32_t sig_id,
303         uint32_t sig_rev, uint32_t class, uint32_t priority, const char *msg)
304 {
305     unsigned int event_id;
306 
307     event_id = GenerateSnortEvent(p,gen_id,sig_id,sig_rev,class,priority,msg);
308 
309     if(g_logfile)
310         LogPortscanAlert(p, msg, event_id, 0, gen_id, sig_id);
311 
312     return event_id;
313 }
314 
315 /*
316 **  NAME
317 **    GenerateOpenPortEvent::
318 */
319 /**
320 **  We have to generate open port events differently because we tag these
321 **  to the original portscan event.
322 **
323 **  @return int
324 **
325 **  @retval 0 success
326 */
GenerateOpenPortEvent(Packet * p,uint32_t gen_id,uint32_t sig_id,uint32_t sig_rev,uint32_t class,uint32_t pri,uint32_t event_ref,struct timeval * event_time,const char * msg)327 static int GenerateOpenPortEvent(Packet *p, uint32_t gen_id, uint32_t sig_id,
328         uint32_t sig_rev, uint32_t class, uint32_t pri,
329         uint32_t event_ref, struct timeval *event_time, const char *msg)
330 {
331     Event event;
332 
333     /*
334     **  This means that we logged an open port, but we don't have a event
335     **  reference for it, so we don't log a snort event.  We still keep
336     **  track of it though.
337     */
338     if(!event_ref)
339         return 0;
340 
341     /* reset the thresholding subsystem checks for this packet */
342     sfthreshold_reset();
343 
344 #if !defined(FEAT_OPEN_APPID)
345     SetEvent(&event, gen_id, sig_id, sig_rev, class, pri, event_ref);
346 #else /* defined(FEAT_OPEN_APPID) */
347     SetEvent(&event, gen_id, sig_id, sig_rev, class, pri, event_ref, NULL);
348 #endif /* defined(FEAT_OPEN_APPID) */
349     //CallAlertFuncs(p,msg,NULL,&event);
350 
351     event.ref_time.tv_sec  = event_time->tv_sec;
352     event.ref_time.tv_usec = event_time->tv_usec;
353 
354     if(p)
355     {
356         /*
357          * Do threshold test for suppression and thresholding.  We have to do it
358          * here since these are tagged packets, which aren't subject to thresholding,
359          * but we want to do it for open port events.
360          */
361         if( sfthreshold_test(gen_id, sig_id, GET_SRC_IP(p),
362                             GET_DST_IP(p), p->pkth->ts.tv_sec) )
363         {
364             return 0;
365         }
366 
367         CallLogFuncs(p,msg,NULL,&event);
368     }
369     else
370     {
371         return -1;
372     }
373 
374     if(g_logfile)
375         LogPortscanAlert(p, msg, 0, event_ref, gen_id, sig_id);
376 
377     return event.event_id;
378 }
379 
380 /*
381 **  NAME
382 **    MakeOpenPortInfo::
383 */
384 /**
385 **  Write out the open ports info for open port alerts.
386 **
387 **  @return integer
388 */
MakeOpenPortInfo(PS_PROTO * proto,u_char * buffer,u_int * total_size,void * user)389 static int MakeOpenPortInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size,
390          void *user)
391 {
392     int dsize;
393 
394     if(!total_size || !buffer)
395         return -1;
396 
397     dsize = (g_tmp_pkt->max_dsize - *total_size);
398 
399     if(dsize < PROTO_BUFFER_SIZE)
400        return -1;
401 
402     SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE,
403                   "Open Port: %u\n", *((unsigned short *)user));
404 
405     dsize = SnortStrnlen((const char *)buffer, PROTO_BUFFER_SIZE);
406     *total_size += dsize;
407 
408     /*
409     **  Set the payload size.  This is protocol independent.
410     */
411     g_tmp_pkt->dsize = dsize;
412 
413     return 0;
414 }
415 
416 /*
417 **  NAME
418 **    MakePortscanPkt::
419 */
420 /*
421 **  We have to create this fake packet so portscan data can be passed
422 **  through the unified output.
423 **
424 **  We want to copy the network and transport layer headers into our
425 **  fake packet.
426 **
427 */
MakePortscanPkt(PS_PKT * ps_pkt,PS_PROTO * proto,int proto_type,void * user)428 static int MakePortscanPkt(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type,
429         void *user)
430 {
431     unsigned int ip_size = 0;
432     Packet* p = (Packet *)ps_pkt->pkt;
433     EncodeFlags flags = ENC_FLAG_NET;
434 
435     if (!IsIP(p))
436         return -1;
437 
438     if ( !ps_pkt->reverse_pkt )
439         flags |= ENC_FLAG_FWD;
440 
441     if (p != g_tmp_pkt)
442     {
443 #if defined(HAVE_DAQ_ADDRESS_SPACE_ID) && defined(DAQ_VERSION) && DAQ_VERSION > 6
444       DAQ_PktHdr_t phdr;
445       memcpy(&phdr, &p->pkth, sizeof(*p->pkth));
446       if (p->pkth->flags & DAQ_PKT_FLAG_REAL_ADDRESSES)
447       {
448         phdr.flags &= ~(DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
449         if (flags & ENC_FLAG_FWD)
450         {
451           phdr.flags |= phdr.flags & (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
452           phdr.real_sIP = p->pkth->real_sIP;
453           phdr.real_dIP = p->pkth->real_dIP;
454         }
455         else
456         {
457           if (p->pkth->flags & DAQ_PKT_FLAG_REAL_SIP_V6)
458             phdr.flags |= DAQ_PKT_FLAG_REAL_DIP_V6;
459           if (p->pkth->flags & DAQ_PKT_FLAG_REAL_DIP_V6)
460             phdr.flags |= DAQ_PKT_FLAG_REAL_SIP_V6;
461           phdr.real_sIP = p->pkth->real_dIP;
462           phdr.real_dIP = p->pkth->real_sIP;
463         }
464 
465       }
466       Encode_Format_With_DAQ_Info(flags, p, g_tmp_pkt, PSEUDO_PKT_PS, &phdr, 0);
467 #elif defined(HAVE_DAQ_ACQUIRE_WITH_META) && defined(DAQ_VERSION) && DAQ_VERSION > 6
468       Encode_Format_With_DAQ_Info(flags, p, g_tmp_pkt, PSEUDO_PKT_PS, 0);
469 #else
470         Encode_Format(flags, p, g_tmp_pkt, PSEUDO_PKT_PS);
471 #endif
472     }
473 
474     switch (proto_type)
475     {
476         case PS_PROTO_TCP:
477             g_tmp_pkt->ps_proto = IPPROTO_TCP;
478             break;
479         case PS_PROTO_UDP:
480             g_tmp_pkt->ps_proto = IPPROTO_UDP;
481             break;
482         case PS_PROTO_ICMP:
483             g_tmp_pkt->ps_proto = IPPROTO_ICMP;
484             break;
485         case PS_PROTO_IP:
486             g_tmp_pkt->ps_proto = IPPROTO_IP;
487             break;
488         case PS_PROTO_OPEN_PORT:
489             g_tmp_pkt->ps_proto = GET_IPH_PROTO(p);
490             break;
491         default:
492             return -1;
493     }
494 
495     if(IS_IP4(p))
496     {
497         ((IPHdr*)g_tmp_pkt->iph)->ip_proto = IPPROTO_PS;
498         g_tmp_pkt->inner_ip4h.ip_proto = IPPROTO_PS;
499     }
500     else
501     {
502         if ( g_tmp_pkt->raw_ip6h )
503             ((IP6RawHdr*)g_tmp_pkt->raw_ip6h)->ip6nxt = IPPROTO_PS;
504         g_tmp_pkt->inner_ip6h.next = IPPROTO_PS;
505         g_tmp_pkt->ip6h = &g_tmp_pkt->inner_ip6h;
506     }
507 
508     switch(proto_type)
509     {
510         case PS_PROTO_TCP:
511         case PS_PROTO_UDP:
512         case PS_PROTO_ICMP:
513         case PS_PROTO_IP:
514             if(MakeProtoInfo(proto, (u_char*)g_tmp_pkt->data, &ip_size))
515                 return -1;
516 
517             break;
518 
519         case PS_PROTO_OPEN_PORT:
520             if(MakeOpenPortInfo(proto, (u_char*)g_tmp_pkt->data, &ip_size, user))
521                 return -1;
522 
523             break;
524 
525         default:
526             return -1;
527     }
528 
529     /*
530     **  Let's finish up the IP header and checksum.
531     */
532     Encode_Update(g_tmp_pkt);
533 
534     if(IS_IP4(g_tmp_pkt))
535     {
536         g_tmp_pkt->inner_ip4h.ip_len = ((IPHdr *)g_tmp_pkt->iph)->ip_len;
537     }
538     else if (IS_IP6(g_tmp_pkt))
539     {
540         g_tmp_pkt->inner_ip6h.len = htons((uint16_t)ip_size);
541     }
542 
543     return 0;
544 }
545 
PortscanAlertTcp(Packet * p,PS_PROTO * proto,int proto_type)546 static int PortscanAlertTcp(Packet *p, PS_PROTO *proto, int proto_type)
547 {
548     int iCtr;
549     unsigned int event_ref;
550     int portsweep = 0;
551 
552     if(!proto)
553         return -1;
554 
555     switch(proto->alerts)
556     {
557         case PS_ALERT_ONE_TO_ONE:
558             event_ref = GeneratePSSnortEvent(p, GENERATOR_PSNG,
559                     PSNG_TCP_PORTSCAN, 0, 0, 3, PSNG_TCP_PORTSCAN_STR);
560             break;
561 
562         case PS_ALERT_ONE_TO_ONE_DECOY:
563             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
564                     PSNG_TCP_DECOY_PORTSCAN,0,0,3,PSNG_TCP_DECOY_PORTSCAN_STR);
565             break;
566 
567         case PS_ALERT_PORTSWEEP:
568            event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
569                    PSNG_TCP_PORTSWEEP, 0, 0, 3, PSNG_TCP_PORTSWEEP_STR);
570            portsweep = 1;
571 
572            break;
573 
574         case PS_ALERT_DISTRIBUTED:
575             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
576                     PSNG_TCP_DISTRIBUTED_PORTSCAN, 0, 0, 3,
577                     PSNG_TCP_DISTRIBUTED_PORTSCAN_STR);
578             break;
579 
580         case PS_ALERT_ONE_TO_ONE_FILTERED:
581             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
582                     PSNG_TCP_FILTERED_PORTSCAN,0,0,3,
583                     PSNG_TCP_FILTERED_PORTSCAN_STR);
584             break;
585 
586         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
587             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
588                     PSNG_TCP_FILTERED_DECOY_PORTSCAN, 0,0,3,
589                     PSNG_TCP_FILTERED_DECOY_PORTSCAN_STR);
590             break;
591 
592         case PS_ALERT_PORTSWEEP_FILTERED:
593            event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
594                    PSNG_TCP_PORTSWEEP_FILTERED,0,0,3,
595                    PSNG_TCP_PORTSWEEP_FILTERED_STR);
596            portsweep = 1;
597 
598            return 0;
599 
600         case PS_ALERT_DISTRIBUTED_FILTERED:
601             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
602                     PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3,
603                     PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
604             break;
605 
606         default:
607             return 0;
608     }
609 
610     /*
611     **  Set the current event reference information for any open ports.
612     */
613     proto->event_ref  = event_ref;
614     proto->event_time.tv_sec  = p->pkth->ts.tv_sec;
615     proto->event_time.tv_usec = p->pkth->ts.tv_usec;
616 
617     /*
618     **  Only log open ports for portsweeps after the alert has been
619     **  generated.
620     */
621     if(proto->open_ports_cnt && !portsweep)
622     {
623         for(iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++)
624         {
625             DAQ_PktHdr_t *pkth = (DAQ_PktHdr_t *)g_tmp_pkt->pkth;
626             PS_PKT ps_pkt;
627 
628             memset(&ps_pkt, 0x00, sizeof(PS_PKT));
629             ps_pkt.pkt = (void *)p;
630 
631             if(MakePortscanPkt(&ps_pkt, proto, PS_PROTO_OPEN_PORT,
632                         (void *)&proto->open_ports[iCtr]))
633                 return -1;
634 
635             pkth->ts.tv_usec += 1;
636             GenerateOpenPortEvent(g_tmp_pkt,GENERATOR_PSNG,PSNG_OPEN_PORT,
637                     0,0,3, proto->event_ref, &proto->event_time,
638                     PSNG_OPEN_PORT_STR);
639         }
640     }
641 
642     return 0;
643 }
644 
PortscanAlertUdp(Packet * p,PS_PROTO * proto,int proto_type)645 static int PortscanAlertUdp(Packet *p, PS_PROTO *proto, int proto_type)
646 {
647     if(!proto)
648         return -1;
649 
650     switch(proto->alerts)
651     {
652         case PS_ALERT_ONE_TO_ONE:
653             GeneratePSSnortEvent(p, GENERATOR_PSNG, PSNG_UDP_PORTSCAN, 0, 0, 3,
654                     PSNG_UDP_PORTSCAN_STR);
655             break;
656 
657         case PS_ALERT_ONE_TO_ONE_DECOY:
658             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_DECOY_PORTSCAN, 0, 0, 3,
659                     PSNG_UDP_DECOY_PORTSCAN_STR);
660             break;
661 
662         case PS_ALERT_PORTSWEEP:
663            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_PORTSWEEP, 0, 0, 3,
664                     PSNG_UDP_PORTSWEEP_STR);
665             break;
666 
667         case PS_ALERT_DISTRIBUTED:
668             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_DISTRIBUTED_PORTSCAN,
669                     0, 0, 3, PSNG_UDP_DISTRIBUTED_PORTSCAN_STR);
670             break;
671 
672         case PS_ALERT_ONE_TO_ONE_FILTERED:
673             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_FILTERED_PORTSCAN,0,0,3,
674                     PSNG_UDP_FILTERED_PORTSCAN_STR);
675             break;
676 
677         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
678             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_FILTERED_DECOY_PORTSCAN,
679                     0,0,3, PSNG_UDP_FILTERED_DECOY_PORTSCAN_STR);
680             break;
681 
682         case PS_ALERT_PORTSWEEP_FILTERED:
683            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_PORTSWEEP_FILTERED,0,0,3,
684                     PSNG_UDP_PORTSWEEP_FILTERED_STR);
685             break;
686 
687         case PS_ALERT_DISTRIBUTED_FILTERED:
688             GeneratePSSnortEvent(p,GENERATOR_PSNG,
689                     PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3,
690                     PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
691             break;
692 
693         default:
694             break;
695     }
696 
697     return 0;
698 }
699 
PortscanAlertIp(Packet * p,PS_PROTO * proto,int proto_type)700 static int PortscanAlertIp(Packet *p, PS_PROTO *proto, int proto_type)
701 {
702     if(!proto)
703         return -1;
704 
705     switch(proto->alerts)
706     {
707         case PS_ALERT_ONE_TO_ONE:
708             GeneratePSSnortEvent(p, GENERATOR_PSNG, PSNG_IP_PORTSCAN, 0, 0, 3,
709                     PSNG_IP_PORTSCAN_STR);
710             break;
711 
712         case PS_ALERT_ONE_TO_ONE_DECOY:
713             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_DECOY_PORTSCAN, 0, 0, 3,
714                     PSNG_IP_DECOY_PORTSCAN_STR);
715             break;
716 
717         case PS_ALERT_PORTSWEEP:
718            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_PORTSWEEP, 0, 0, 3,
719                     PSNG_IP_PORTSWEEP_STR);
720             break;
721 
722         case PS_ALERT_DISTRIBUTED:
723             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_DISTRIBUTED_PORTSCAN,
724                     0, 0, 3, PSNG_IP_DISTRIBUTED_PORTSCAN_STR);
725             break;
726 
727         case PS_ALERT_ONE_TO_ONE_FILTERED:
728             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_FILTERED_PORTSCAN,0,0,3,
729                     PSNG_IP_FILTERED_PORTSCAN_STR);
730             break;
731 
732         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
733             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_FILTERED_DECOY_PORTSCAN,
734                     0,0,3, PSNG_IP_FILTERED_DECOY_PORTSCAN_STR);
735             break;
736 
737         case PS_ALERT_PORTSWEEP_FILTERED:
738            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_PORTSWEEP_FILTERED,0,0,3,
739                     PSNG_IP_PORTSWEEP_FILTERED_STR);
740             break;
741 
742         case PS_ALERT_DISTRIBUTED_FILTERED:
743             GeneratePSSnortEvent(p,GENERATOR_PSNG,
744                     PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3,
745                     PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
746             break;
747 
748         default:
749             break;
750     }
751 
752     return 0;
753 }
754 
PortscanAlertIcmp(Packet * p,PS_PROTO * proto,int proto_type)755 static int PortscanAlertIcmp(Packet *p, PS_PROTO *proto, int proto_type)
756 {
757     if(!proto)
758         return -1;
759 
760     switch(proto->alerts)
761     {
762         case PS_ALERT_PORTSWEEP:
763            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_ICMP_PORTSWEEP, 0, 0, 3,
764                     PSNG_ICMP_PORTSWEEP_STR);
765             break;
766 
767         case PS_ALERT_PORTSWEEP_FILTERED:
768            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_ICMP_PORTSWEEP_FILTERED,0,0,3,
769                     PSNG_ICMP_PORTSWEEP_FILTERED_STR);
770             break;
771 
772         default:
773             break;
774     }
775 
776     return 0;
777 }
778 
PortscanAlert(PS_PKT * ps_pkt,PS_PROTO * proto,int proto_type)779 static int PortscanAlert(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type)
780 {
781     Packet *p;
782 
783     if(!ps_pkt || !ps_pkt->pkt)
784         return -1;
785 
786     p = (Packet *)ps_pkt->pkt;
787 
788     if(proto->alerts == PS_ALERT_OPEN_PORT)
789     {
790         if(MakePortscanPkt(ps_pkt, proto, PS_PROTO_OPEN_PORT, (void *)&p->sp))
791             return -1;
792 
793         GenerateOpenPortEvent(g_tmp_pkt,GENERATOR_PSNG,PSNG_OPEN_PORT,0,0,3,
794                 proto->event_ref, &proto->event_time, PSNG_OPEN_PORT_STR);
795     }
796     else
797     {
798         if(MakePortscanPkt(ps_pkt, proto, proto_type, NULL))
799             return -1;
800 
801         switch(proto_type)
802         {
803             case PS_PROTO_TCP:
804                 PortscanAlertTcp(g_tmp_pkt, proto, proto_type);
805                 break;
806 
807             case PS_PROTO_UDP:
808                 PortscanAlertUdp(g_tmp_pkt, proto, proto_type);
809                 break;
810 
811             case PS_PROTO_ICMP:
812                 PortscanAlertIcmp(g_tmp_pkt, proto, proto_type);
813                 break;
814 
815             case PS_PROTO_IP:
816                 PortscanAlertIp(g_tmp_pkt, proto, proto_type);
817                 break;
818         }
819     }
820 
821     sfthreshold_reset();
822 
823     return 0;
824 }
825 
PortscanDetect(Packet * p,void * context)826 static void PortscanDetect(Packet *p, void *context)
827 {
828     PS_PKT ps_pkt;
829     tSfPolicyId policy_id = getNapRuntimePolicy();
830     PortscanConfig *pPolicyConfig = NULL;
831     PROFILE_VARS;
832 
833     assert(IPH_IS_VALID(p));
834 
835     if ( p->packet_flags & PKT_REBUILT_STREAM )
836         return;
837 
838     sfPolicyUserPolicySet (portscan_config, policy_id);
839     pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetCurrent(portscan_config);
840 
841     if ( pPolicyConfig == NULL )
842         return;
843 
844     portscan_eval_config = pPolicyConfig;
845 
846     PREPROC_PROFILE_START(sfpsPerfStats);
847 
848     memset(&ps_pkt, 0x00, sizeof(PS_PKT));
849     ps_pkt.pkt = (void *)p;
850 
851     /* See if there is already an exisiting node in the hash table */
852     ps_detect(&ps_pkt);
853 
854     if (ps_pkt.scanner && ps_pkt.scanner->proto.alerts &&
855        (ps_pkt.scanner->proto.alerts != PS_ALERT_GENERATED))
856     {
857         PortscanAlert(&ps_pkt, &ps_pkt.scanner->proto, ps_pkt.proto);
858     }
859 
860     if (ps_pkt.scanned && ps_pkt.scanned->proto.alerts &&
861         (ps_pkt.scanned->proto.alerts != PS_ALERT_GENERATED))
862     {
863         PortscanAlert(&ps_pkt, &ps_pkt.scanned->proto, ps_pkt.proto);
864     }
865 
866     PREPROC_PROFILE_END(sfpsPerfStats);
867 }
868 
FatalErrorNoOption(u_char * option)869 NORETURN static void FatalErrorNoOption(u_char *option)
870 {
871     FatalError("%s(%d) => No argument to '%s' config option.\n",
872             file_name, file_line, option);
873 }
874 
FatalErrorNoEnd(char * option)875 NORETURN static void FatalErrorNoEnd(char *option)
876 {
877     FatalError("%s(%d) => No ending brace to '%s' config option.\n",
878             file_name, file_line, option);
879 }
880 
FatalErrorInvalidArg(char * option)881 NORETURN static void FatalErrorInvalidArg(char *option)
882 {
883     FatalError("%s(%d) => Invalid argument to '%s' config option.\n",
884             file_name, file_line, option);
885 }
886 
FatalErrorInvalidOption(char * option)887 NORETURN static void FatalErrorInvalidOption(char *option)
888 {
889     FatalError("%s(%d) => Invalid option '%s' to portscan preprocessor.\n",
890             file_name, file_line, option);
891 }
892 
ParseProtos(int * protos,char ** savptr)893 static void ParseProtos(int *protos, char **savptr)
894 {
895     char *pcTok;
896 
897     if(!protos)
898         return;
899 
900     *protos = 0;
901 
902     pcTok = strtok_r(NULL, DELIMITERS, savptr);
903     while(pcTok)
904     {
905         if(!strcasecmp(pcTok, "tcp"))
906             *protos |= PS_PROTO_TCP;
907         else if(!strcasecmp(pcTok, "udp"))
908             *protos |= PS_PROTO_UDP;
909         else if(!strcasecmp(pcTok, "icmp"))
910             *protos |= PS_PROTO_ICMP;
911         else if(!strcasecmp(pcTok, "ip"))
912             *protos |= PS_PROTO_IP;
913         else if(!strcasecmp(pcTok, "all"))
914             *protos = PS_PROTO_ALL;
915         else if(!strcasecmp(pcTok, TOKEN_ARG_END))
916             return;
917         else
918             FatalErrorInvalidArg("proto");
919 
920         pcTok = strtok_r(NULL, DELIMITERS, savptr);
921     }
922 
923     if(!pcTok)
924         FatalErrorNoEnd("proto");
925 
926     return;
927 }
928 
ParseScanType(int * scan_types,char ** savptr)929 static void ParseScanType(int *scan_types, char **savptr)
930 {
931     char *pcTok;
932 
933     if(!scan_types)
934         return;
935 
936     *scan_types = 0;
937 
938     pcTok = strtok_r(NULL, DELIMITERS, savptr);
939     while(pcTok)
940     {
941         if(!strcasecmp(pcTok, "portscan"))
942             *scan_types |= PS_TYPE_PORTSCAN;
943         else if(!strcasecmp(pcTok, "portsweep"))
944             *scan_types |= PS_TYPE_PORTSWEEP;
945         else if(!strcasecmp(pcTok, "decoy_portscan"))
946             *scan_types |= PS_TYPE_DECOYSCAN;
947         else if(!strcasecmp(pcTok, "distributed_portscan"))
948             *scan_types |= PS_TYPE_DISTPORTSCAN;
949         else if(!strcasecmp(pcTok, "all"))
950             *scan_types = PS_TYPE_ALL;
951         else if(!strcasecmp(pcTok, TOKEN_ARG_END))
952             return;
953         else
954             FatalErrorInvalidArg("scan_type");
955 
956         pcTok = strtok_r(NULL, DELIMITERS, savptr);
957     }
958 
959     if(!pcTok)
960         FatalErrorNoEnd("scan_type");
961 
962     return;
963 }
964 
ParseSenseLevel(int * sense_level,char ** savptr)965 static void ParseSenseLevel(int *sense_level, char **savptr)
966 {
967     char *pcTok;
968 
969     if(!sense_level)
970         return;
971 
972     *sense_level = 0;
973 
974     pcTok = strtok_r(NULL, DELIMITERS, savptr);
975     while(pcTok)
976     {
977         if(!strcasecmp(pcTok, "low"))
978             *sense_level = PS_SENSE_LOW;
979         else if(!strcasecmp(pcTok, "medium"))
980             *sense_level = PS_SENSE_MEDIUM;
981         else if(!strcasecmp(pcTok, "high"))
982             *sense_level = PS_SENSE_HIGH;
983         else if(!strcmp(pcTok, TOKEN_ARG_END))
984             return;
985         else
986             FatalErrorInvalidArg("sense_level");
987 
988         pcTok = strtok_r(NULL, DELIMITERS, savptr);
989     }
990 
991     if(!pcTok)
992         FatalErrorNoEnd("sense_level");
993 
994     return;
995 }
996 
ParseIpList(IPSET ** ip_list,char * option,char ** savptr)997 static void ParseIpList(IPSET **ip_list, char *option, char **savptr)
998 {
999     char *pcTok;
1000 
1001     if(!ip_list)
1002         return;
1003 
1004     pcTok = strtok_r(NULL, TOKEN_ARG_END, savptr);
1005     if(!pcTok)
1006         FatalErrorInvalidArg(option);
1007 
1008     *ip_list = ipset_new();
1009     if(!*ip_list)
1010         FatalError("Failed to initialize ip_list in portscan preprocessor.\n");
1011 
1012     if(ipset_parse(*ip_list, pcTok))
1013         FatalError("%s(%d) => Invalid ip_list to '%s' option.\n",
1014                 file_name, file_line, option);
1015 
1016     return;
1017 }
1018 
ParseMemcap(unsigned long * memcap,char ** savptr)1019 static void ParseMemcap(unsigned long *memcap, char **savptr)
1020 {
1021     char *pcTok;
1022     char *p;
1023 
1024     if(!memcap)
1025         return;
1026 
1027     *memcap = 0;
1028 
1029     pcTok = strtok_r(NULL, DELIMITERS, savptr);
1030     if(!pcTok)
1031         FatalErrorNoEnd("memcap");
1032 
1033     *memcap = strtoul(pcTok, &p, 10);
1034 
1035     if(!*pcTok || *pcTok == '-' || *p)
1036         FatalErrorInvalidArg("memcap");
1037 
1038     pcTok = strtok_r(NULL, DELIMITERS, savptr);
1039     if(!pcTok)
1040         FatalErrorNoEnd("memcap");
1041 
1042     if(strcmp(pcTok, TOKEN_ARG_END))
1043         FatalErrorInvalidArg("memcap");
1044 
1045     return;
1046 }
1047 
PrintIPPortSet(IP_PORT * p)1048 static void PrintIPPortSet(IP_PORT *p)
1049 {
1050     char ip_str[80], output_str[80];
1051     PORTRANGE *pr;
1052 
1053     SnortSnprintf(ip_str, sizeof(ip_str), "%s", sfip_to_str(&p->ip.addr));
1054 
1055     if(p->notflag)
1056         SnortSnprintf(output_str, sizeof(output_str), "        !%s", ip_str);
1057     else
1058         SnortSnprintf(output_str, sizeof(output_str), "        %s", ip_str);
1059 
1060     if (p->ip.bits != 128)
1061         SnortSnprintfAppend(output_str, sizeof(output_str), "/%d",
1062                             (sfaddr_family(&p->ip.addr) == AF_INET) ? ((p->ip.bits >= 96) ? p->ip.bits - 96 : -1) : p->ip.bits);
1063 
1064     pr=(PORTRANGE*)sflist_first(&p->portset.port_list);
1065     if ( pr && pr->port_lo != 0 )
1066         SnortSnprintfAppend(output_str, sizeof(output_str), " : ");
1067     for( ; pr != 0;
1068         pr=(PORTRANGE*)sflist_next(&p->portset.port_list) )
1069     {
1070         if ( pr->port_lo != 0)
1071         {
1072             SnortSnprintfAppend(output_str, sizeof(output_str), "%d", pr->port_lo);
1073             if ( pr->port_hi != pr->port_lo )
1074             {
1075                 SnortSnprintfAppend(output_str, sizeof(output_str), "-%d", pr->port_hi);
1076             }
1077             SnortSnprintfAppend(output_str, sizeof(output_str), " ");
1078         }
1079     }
1080     LogMessage("%s\n", output_str);
1081 }
1082 
PrintPortscanConf(int detect_scans,int detect_scan_type,int sense_level,IPSET * scanner,IPSET * scanned,IPSET * watch,unsigned long memcap,char * logpath,int disabled)1083 static void PrintPortscanConf(int detect_scans, int detect_scan_type,
1084         int sense_level, IPSET *scanner, IPSET *scanned, IPSET *watch,
1085         unsigned long memcap, char *logpath, int disabled)
1086 {
1087     char buf[STD_BUF + 1];
1088     int proto_cnt = 0;
1089     IP_PORT *p;
1090 
1091     LogMessage("Portscan Detection Config:\n");
1092     if(disabled)
1093     {
1094            LogMessage("    Portscan Detection: INACTIVE\n");
1095     }
1096     memset(buf, 0, STD_BUF + 1);
1097     if (!disabled)
1098     {
1099         SnortSnprintf(buf, STD_BUF + 1, "    Detect Protocols:  ");
1100         if(detect_scans & PS_PROTO_TCP)  { sfsnprintfappend(buf, STD_BUF, "TCP ");  proto_cnt++; }
1101         if(detect_scans & PS_PROTO_UDP)  { sfsnprintfappend(buf, STD_BUF, "UDP ");  proto_cnt++; }
1102         if(detect_scans & PS_PROTO_ICMP) { sfsnprintfappend(buf, STD_BUF, "ICMP "); proto_cnt++; }
1103         if(detect_scans & PS_PROTO_IP)   { sfsnprintfappend(buf, STD_BUF, "IP");    proto_cnt++; }
1104         LogMessage("%s\n", buf);
1105     }
1106 
1107     if (!disabled)
1108     {
1109         memset(buf, 0, STD_BUF + 1);
1110         SnortSnprintf(buf, STD_BUF + 1, "    Detect Scan Type:  ");
1111         if(detect_scan_type & PS_TYPE_PORTSCAN)
1112             sfsnprintfappend(buf, STD_BUF, "portscan ");
1113         if(detect_scan_type & PS_TYPE_PORTSWEEP)
1114             sfsnprintfappend(buf, STD_BUF, "portsweep ");
1115         if(detect_scan_type & PS_TYPE_DECOYSCAN)
1116             sfsnprintfappend(buf, STD_BUF, "decoy_portscan ");
1117         if(detect_scan_type & PS_TYPE_DISTPORTSCAN)
1118             sfsnprintfappend(buf, STD_BUF, "distributed_portscan");
1119         LogMessage("%s\n", buf);
1120     }
1121 
1122     if (!disabled)
1123     {
1124         memset(buf, 0, STD_BUF + 1);
1125         SnortSnprintf(buf, STD_BUF + 1, "    Sensitivity Level: ");
1126         if(sense_level == PS_SENSE_HIGH)
1127             sfsnprintfappend(buf, STD_BUF, "High/Experimental");
1128         if(sense_level == PS_SENSE_MEDIUM)
1129             sfsnprintfappend(buf, STD_BUF, "Medium");
1130         if(sense_level == PS_SENSE_LOW)
1131             sfsnprintfappend(buf, STD_BUF, "Low");
1132         LogMessage("%s\n", buf);
1133     }
1134 
1135     LogMessage("    Memcap (in bytes): %lu\n", memcap);
1136 
1137     if (!disabled)
1138     {
1139         LogMessage("    Number of Nodes:   %ld\n",
1140             memcap / (sizeof(PS_PROTO)*proto_cnt-1));
1141 
1142         if (logpath != NULL)
1143             LogMessage("    Logfile:           %s\n", logpath);
1144 
1145         if(scanner)
1146         {
1147             LogMessage("    Ignore Scanner IP List:\n");
1148             for(p = (IP_PORT*)sflist_first(&scanner->ip_list);
1149                 p;
1150                 p = (IP_PORT*)sflist_next(&scanner->ip_list))
1151             {
1152                 PrintIPPortSet(p);
1153             }
1154         }
1155 
1156         if(scanned)
1157         {
1158             LogMessage("    Ignore Scanned IP List:\n");
1159             for(p = (IP_PORT*)sflist_first(&scanned->ip_list);
1160                 p;
1161                 p = (IP_PORT*)sflist_next(&scanned->ip_list))
1162             {
1163                 PrintIPPortSet(p);
1164             }
1165         }
1166 
1167         if(watch)
1168         {
1169             LogMessage("    Watch IP List:\n");
1170             for(p = (IP_PORT*)sflist_first(&watch->ip_list);
1171                 p;
1172                 p = (IP_PORT*)sflist_next(&watch->ip_list))
1173             {
1174                 PrintIPPortSet(p);
1175             }
1176         }
1177     }
1178 }
1179 
ParseLogFile(struct _SnortConfig * sc,PortscanConfig * config,char ** savptr)1180 static void ParseLogFile(struct _SnortConfig *sc, PortscanConfig *config, char **savptr)
1181 {
1182     char *pcTok;
1183 
1184     if (config == NULL)
1185         return;
1186 
1187     pcTok = strtok_r(NULL, DELIMITERS, savptr);
1188     if (pcTok == NULL)
1189     {
1190         FatalError("%s(%d) => No ending brace to '%s' config option.\n",
1191                    file_name, file_line, "logfile");
1192     }
1193 
1194     config->logfile = ProcessFileOption(sc, pcTok);
1195 
1196     pcTok = strtok_r(NULL, DELIMITERS, savptr);
1197     if (pcTok == NULL)
1198     {
1199         FatalError("%s(%d) => No ending brace to '%s' config option.\n",
1200                    file_name, file_line, "logfile");
1201     }
1202 
1203     if (strcmp(pcTok, TOKEN_ARG_END) != 0)
1204     {
1205         FatalError("%s(%d) => Invalid argument to '%s' config option.\n",
1206                    file_name, file_line, "logfile");
1207     }
1208 }
1209 
1210 #ifdef REG_TEST
PrintPORTSCANSize(void)1211 static inline void PrintPORTSCANSize(void)
1212 {
1213     LogMessage("\nPORTSCAN Session Size: %lu\n", (long unsigned int)sizeof(PS_TRACKER));
1214 }
1215 #endif
1216 
PortscanInit(struct _SnortConfig * sc,char * args)1217 static void PortscanInit(struct _SnortConfig *sc, char *args)
1218 {
1219     tSfPolicyId policy_id = getParserPolicy(sc);
1220     PortscanConfig *pPolicyConfig = NULL;
1221 
1222 #ifdef REG_TEST
1223     PrintPORTSCANSize();
1224 #endif
1225 
1226     if (portscan_config == NULL)
1227     {
1228         portscan_config = sfPolicyConfigCreate();
1229         PortscanPacketInit();
1230 
1231         AddFuncToPreprocCleanExitList(PortscanCleanExitFunction, NULL, PRIORITY_SCANNER, PP_SFPORTSCAN);
1232         AddFuncToPreprocResetList(PortscanResetFunction, NULL, PRIORITY_SCANNER, PP_SFPORTSCAN);
1233         AddFuncToPreprocResetStatsList(PortscanResetStatsFunction, NULL, PRIORITY_SCANNER, PP_SFPORTSCAN);
1234         AddFuncToPreprocPostConfigList(sc, PortscanOpenLogFile, NULL);
1235 
1236 #ifdef PERF_PROFILING
1237         RegisterPreprocessorProfile("sfportscan", &sfpsPerfStats, 0, &totalPerfStats, NULL);
1238 #endif
1239     }
1240 
1241     if ((policy_id != 0) && (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config)) == NULL))
1242     {
1243         ParseError("Portscan: Must configure default policy if other "
1244                    "policies are going to be configured.");
1245     }
1246 
1247     sfPolicyUserPolicySet (portscan_config, policy_id);
1248     pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetCurrent(portscan_config);
1249     if (pPolicyConfig)
1250     {
1251         ParseError("Can only configure sfportscan once.\n");
1252     }
1253     pPolicyConfig = (PortscanConfig *)SnortAlloc(sizeof(PortscanConfig));
1254     if (!pPolicyConfig)
1255     {
1256         ParseError("SFPORTSCAN preprocessor: memory allocate failed.\n");
1257     }
1258 
1259     sfPolicyUserDataSetCurrent(portscan_config, pPolicyConfig);
1260     ParsePortscan(sc, pPolicyConfig, args);
1261 
1262     if (policy_id == 0)
1263     {
1264         ps_init_hash(pPolicyConfig->memcap);
1265     }
1266     else
1267     {
1268         pPolicyConfig->memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->memcap;
1269 
1270         if (pPolicyConfig->logfile != NULL)
1271         {
1272             ParseError("Portscan:  logfile can only be configured in "
1273                        "default policy.\n");
1274         }
1275     }
1276 
1277     if ( !pPolicyConfig->disabled )
1278     {
1279         AddFuncToPreprocList(sc, PortscanDetect, PRIORITY_SCANNER, PP_SFPORTSCAN,
1280                              PortscanGetProtoBits(pPolicyConfig->detect_scans));
1281         session_api->enable_preproc_all_ports( sc,
1282                                                PP_SFPORTSCAN,
1283                                                PortscanGetProtoBits(pPolicyConfig->detect_scans) );
1284     }
1285 }
1286 
SetupSfPortscan(void)1287 void SetupSfPortscan(void)
1288 {
1289 #ifndef SNORT_RELOAD
1290     RegisterPreprocessor("sfportscan", PortscanInit);
1291 #else
1292     RegisterPreprocessor("sfportscan", PortscanInit, PortscanReload,
1293                          PortscanReloadVerify, PortscanReloadSwap,
1294                          PortscanReloadSwapFree);
1295 #endif
1296 }
1297 
ParsePortscan(struct _SnortConfig * sc,PortscanConfig * config,char * args)1298 static void ParsePortscan(struct _SnortConfig *sc, PortscanConfig *config, char *args)
1299 {
1300     int    sense_level = PS_SENSE_LOW;
1301     int    protos      = (PS_PROTO_TCP | PS_PROTO_UDP);
1302     int    scan_types  = PS_TYPE_ALL;
1303     unsigned long memcap = 1048576;
1304     IPSET *ignore_scanners = NULL;
1305     IPSET *ignore_scanned = NULL;
1306     IPSET *watch_ip = NULL;
1307     char  *pcTok, *savpcTok = NULL;
1308     int    iRet;
1309 
1310     if (args != NULL)
1311     {
1312         pcTok = strtok_r(args, DELIMITERS, &savpcTok);
1313         //pcTok = strtok(args, DELIMITERS);
1314         while(pcTok)
1315         {
1316             if(!strcasecmp(pcTok, "proto"))
1317             {
1318                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1319                 //pcTok = strtok(NULL, DELIMITERS);
1320                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1321                     FatalErrorNoOption((u_char *)"proto");
1322 
1323                 ParseProtos(&protos, &savpcTok);
1324             }
1325             else if(!strcasecmp(pcTok, "scan_type"))
1326             {
1327                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1328                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1329                     FatalErrorNoOption((u_char *)"scan_type");
1330 
1331                 ParseScanType(&scan_types, &savpcTok);
1332             }
1333             else if(!strcasecmp(pcTok, "sense_level"))
1334             {
1335                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1336                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1337                     FatalErrorNoOption((u_char *)"sense_level");
1338 
1339                 ParseSenseLevel(&sense_level, &savpcTok);
1340             }
1341             else if(!strcasecmp(pcTok, "ignore_scanners"))
1342             {
1343                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1344                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1345                     FatalErrorNoOption((u_char *)"ignore_scanners");
1346 
1347                 ParseIpList(&ignore_scanners, "ignore_scanners", &savpcTok);
1348             }
1349             else if(!strcasecmp(pcTok, "ignore_scanned"))
1350             {
1351                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1352                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1353                     FatalErrorNoOption((u_char *)"ignore_scanned");
1354 
1355                 ParseIpList(&ignore_scanned, "ignore_scanned", &savpcTok);
1356             }
1357             else if(!strcasecmp(pcTok, "watch_ip"))
1358             {
1359                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1360                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1361                     FatalErrorNoOption((u_char *)"watch_ip");
1362 
1363                 ParseIpList(&watch_ip, "watch_ip", &savpcTok);
1364             }
1365             else if(!strcasecmp(pcTok, "print_tracker"))
1366             {
1367                 config->print_tracker = 1;
1368             }
1369             else if(!strcasecmp(pcTok, "memcap"))
1370             {
1371                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1372                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1373                     FatalErrorNoOption((u_char *)"memcap");
1374 
1375                 ParseMemcap(&memcap, &savpcTok);
1376             }
1377             else if(!strcasecmp(pcTok, "logfile"))
1378             {
1379                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1380                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
1381                     FatalErrorNoOption((u_char *)"logfile");
1382 
1383                 ParseLogFile(sc, config, &savpcTok);
1384             }
1385             else if(!strcasecmp(pcTok, "include_midstream"))
1386             {
1387                 /* Do not ignore packets in sessions picked up mid-stream */
1388                 config->include_midstream = 1;
1389             }
1390             else if(!strcasecmp(pcTok, "detect_ack_scans"))
1391             {
1392                 /*
1393                  *  We will only see ack scan packets if we are looking at sessions that the
1394                  *    have been flagged as being picked up mid-stream
1395                  */
1396                 config->include_midstream = 1;
1397             }
1398             else if(!strcasecmp(pcTok, "disabled"))
1399             {
1400                 config->disabled = 1;
1401             }
1402             else
1403             {
1404                 FatalErrorInvalidOption(pcTok);
1405             }
1406 
1407             pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
1408         }
1409     }
1410 
1411     iRet = ps_init(sc, config, protos, scan_types, sense_level, ignore_scanners,
1412                    ignore_scanned, watch_ip, memcap);
1413     if (iRet)
1414     {
1415         if(iRet == -2)
1416         {
1417             FatalError("%s(%d) => 'memcap' limit not sufficient to run "
1418                        "sfportscan preprocessor.  Please increase this "
1419                        "value or keep the default memory usage.\n",
1420                        file_name, file_line);
1421         }
1422 
1423         FatalError("Failed to initialize the sfportscan detection module.  "
1424                    "Please check your configuration before submitting a "
1425                    "bug.\n");
1426     }
1427 
1428     PrintPortscanConf(protos, scan_types, sense_level, ignore_scanners,
1429                       ignore_scanned, watch_ip, memcap, config->logfile, config->disabled);
1430 }
1431 
PortscanOpenLogFile(struct _SnortConfig * sc,void * data)1432 static void PortscanOpenLogFile(struct _SnortConfig *sc, void *data)
1433 {
1434     PortscanConfig *pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config) ;
1435     if ((  pPolicyConfig== NULL) ||
1436         (pPolicyConfig->logfile == NULL))
1437     {
1438         return;
1439     }
1440 
1441     g_logfile = fopen(pPolicyConfig->logfile, "a+");
1442     if (g_logfile == NULL)
1443     {
1444         FatalError("Portscan log file '%s' could not be opened: %s.\n",
1445                    pPolicyConfig->logfile, strerror(errno));
1446     }
1447 }
1448 
PortscanFreeConfigPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)1449 static int PortscanFreeConfigPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId, void* pData )
1450 {
1451     PortscanConfig *pPolicyConfig = (PortscanConfig *)pData;
1452     sfPolicyUserDataClear (config, policyId);
1453     PortscanFreeConfig(pPolicyConfig);
1454     return 0;
1455 }
PortscanFreeConfigs(tSfPolicyUserContextId config)1456 static void PortscanFreeConfigs(tSfPolicyUserContextId config)
1457 {
1458 
1459     if (config == NULL)
1460         return;
1461 
1462     sfPolicyUserDataFreeIterate (config, PortscanFreeConfigPolicy);
1463     sfPolicyConfigDelete(config);
1464 
1465 }
1466 
PortscanFreeConfig(PortscanConfig * config)1467 static void PortscanFreeConfig(PortscanConfig *config)
1468 {
1469     if (config == NULL)
1470         return;
1471 
1472     if (config->logfile)
1473         free(config->logfile);
1474 
1475     if (config->ignore_scanners != NULL)
1476         ipset_free(config->ignore_scanners);
1477 
1478     if (config->ignore_scanned != NULL)
1479         ipset_free(config->ignore_scanned);
1480 
1481     if (config->watch_ip != NULL)
1482         ipset_free(config->watch_ip);
1483 
1484     free(config);
1485 }
1486 
PortscanGetProtoBits(int detect_scans)1487 static int PortscanGetProtoBits(int detect_scans)
1488 {
1489     int proto_bits = PROTO_BIT__IP;
1490 
1491     if (detect_scans & PS_PROTO_IP)
1492     {
1493         proto_bits |= PROTO_BIT__ICMP;
1494     }
1495 
1496     if (detect_scans & PS_PROTO_UDP)
1497     {
1498         proto_bits |= PROTO_BIT__ICMP;
1499         proto_bits |= PROTO_BIT__UDP;
1500     }
1501 
1502     if (detect_scans & PS_PROTO_ICMP)
1503         proto_bits |= PROTO_BIT__ICMP;
1504 
1505     if (detect_scans & PS_PROTO_TCP)
1506     {
1507         proto_bits |= PROTO_BIT__ICMP;
1508         proto_bits |= PROTO_BIT__TCP;
1509     }
1510 
1511     return proto_bits;
1512 }
1513 
1514 #ifdef SNORT_RELOAD
PortscanReload(struct _SnortConfig * sc,char * args,void ** new_config)1515 static void PortscanReload(struct _SnortConfig *sc, char *args, void **new_config)
1516 {
1517     tSfPolicyUserContextId portscan_swap_config = (tSfPolicyUserContextId)*new_config;
1518     tSfPolicyId policy_id = getParserPolicy(sc);
1519     PortscanConfig *pPolicyConfig = NULL;
1520 
1521     if (!portscan_swap_config)
1522     {
1523         portscan_swap_config = sfPolicyConfigCreate();
1524         *new_config = (void *)portscan_swap_config;
1525     }
1526 
1527     if ((policy_id != 0) && (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config)) == NULL))
1528     {
1529         ParseError("Portscan: Must configure default policy if other "
1530                    "policies are going to be configured.");
1531     }
1532 
1533 
1534     sfPolicyUserPolicySet (portscan_swap_config, policy_id);
1535 
1536     pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetCurrent(portscan_swap_config);
1537     if (pPolicyConfig)
1538     {
1539         ParseError("Can only configure sfportscan once.\n");
1540     }
1541 
1542     pPolicyConfig = (PortscanConfig *)SnortAlloc(sizeof(PortscanConfig));
1543     if (!pPolicyConfig)
1544     {
1545         ParseError("SFPORTSCAN preprocessor: memory allocate failed.\n");
1546     }
1547 
1548 
1549     sfPolicyUserDataSetCurrent(portscan_swap_config, pPolicyConfig);
1550     ParsePortscan(sc, pPolicyConfig, args);
1551 
1552     if (policy_id != 0)
1553     {
1554         pPolicyConfig->memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->memcap;
1555 
1556         if (pPolicyConfig->logfile != NULL)
1557         {
1558             ParseError("Portscan:  logfile can only be configured in "
1559                        "default policy.\n");
1560         }
1561     }
1562 
1563     if ( !pPolicyConfig->disabled )
1564     {
1565         AddFuncToPreprocList(sc, PortscanDetect, PRIORITY_SCANNER, PP_SFPORTSCAN,
1566                              PortscanGetProtoBits(pPolicyConfig->detect_scans));
1567         session_api->enable_preproc_all_ports( sc,
1568                                               PP_SFPORTSCAN,
1569                                               PortscanGetProtoBits(pPolicyConfig->detect_scans) );
1570     }
1571 }
1572 
PortscanReloadAdjust(bool idle,tSfPolicyId raPolicyId,void * userData)1573 static bool PortscanReloadAdjust(bool idle, tSfPolicyId raPolicyId, void* userData)
1574 {
1575     unsigned max_work = idle ? 512 : 32;
1576     unsigned long memcap = *(unsigned long *)userData;
1577     return ps_reload_adjust(memcap, max_work);
1578 }
1579 
PortscanReloadVerify(struct _SnortConfig * sc,void * swap_config)1580 static int PortscanReloadVerify(struct _SnortConfig *sc, void *swap_config)
1581 {
1582     tSfPolicyUserContextId portscan_swap_config = (tSfPolicyUserContextId)swap_config;
1583     static unsigned long new_memcap;
1584     unsigned long old_memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->memcap;
1585     new_memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->memcap;
1586     tSfPolicyId policy_id = getParserPolicy(sc);
1587 
1588     if ((portscan_swap_config == NULL) || (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config)) == NULL) ||
1589         (portscan_config == NULL) || (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config)) == NULL))
1590     {
1591         return 0;
1592     }
1593 
1594     if (old_memcap != new_memcap)
1595     {
1596 #ifdef REG_TEST
1597         if (REG_TEST_FLAG_PORTSCAN_RELOAD & getRegTestFlags())
1598         {
1599             printf("portscan memcap old conf : %lu new conf : %lu\n",old_memcap,new_memcap);
1600         }
1601 #endif
1602         /* If memcap is less than  hash overhead bytes, restart is needed */
1603         if( new_memcap > ps_hash_overhead_bytes())
1604         {
1605             ReloadAdjustRegister(sc, "PortscanReload", policy_id, &PortscanReloadAdjust, &new_memcap, NULL);
1606         }
1607         else
1608         {
1609             ErrorMessage("Portscan Reload: New memcap %lu s lower than  minimum memory needed for hash table %u, and it requires a restart.\n", new_memcap, ps_hash_overhead_bytes());
1610             return -1;
1611         }
1612     }
1613     return 0;
1614 }
1615 
PortscanReloadSwap(struct _SnortConfig * sc,void * swap_config)1616 static void * PortscanReloadSwap(struct _SnortConfig *sc, void  *swap_config)
1617 {
1618     tSfPolicyUserContextId portscan_swap_config = (tSfPolicyUserContextId)swap_config;
1619     tSfPolicyUserContextId old_config = portscan_config;
1620     bool log_file_swap = false;
1621 
1622     if (portscan_swap_config == NULL)
1623         return NULL;
1624 
1625     if ((((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile != NULL) &&
1626         (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile != NULL))
1627     {
1628         if (strcasecmp(((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile,
1629                        ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile) != 0)
1630         {
1631             log_file_swap = true;
1632         }
1633     }
1634     else if (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile != ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile)
1635     {
1636         log_file_swap = true;
1637     }
1638 
1639     if(log_file_swap)
1640     {
1641         char *new_logfile = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile;
1642 #ifdef REG_TEST
1643         char *old_logfile = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile;
1644         if (REG_TEST_FLAG_PORTSCAN_RELOAD & getRegTestFlags())
1645         {
1646             printf("portscan Logfile  old: %s , new: %s \n", old_logfile?old_logfile:"NULL", new_logfile?new_logfile:"NULL");
1647         }
1648 #endif
1649         if(g_logfile)
1650         {
1651             fclose(g_logfile);
1652             g_logfile = NULL;
1653         }
1654         if(new_logfile)
1655         {
1656             g_logfile = fopen(new_logfile, "a");
1657             if (g_logfile == NULL)
1658             {
1659                 FatalError("Portscan log file '%s' could not be opened: %s.\n",
1660                         new_logfile, strerror(errno));
1661             }
1662         }
1663     }
1664 
1665     portscan_config = portscan_swap_config;
1666     return (void *)old_config;
1667 }
1668 
PortscanReloadSwapFree(void * data)1669 static void PortscanReloadSwapFree(void *data)
1670 {
1671     if (data == NULL)
1672         return;
1673 
1674     PortscanFreeConfigs((tSfPolicyUserContextId)data);
1675 }
1676 #endif
1677 
1678