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