00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #ifdef HAVE_CONFIG_H
00077 #include "config.h"
00078 #endif
00079
00080 #ifndef DEBUG
00081 #ifndef INLINE
00082 #define INLINE inline
00083 #endif
00084 #else
00085 #ifdef INLINE
00086 #undef INLINE
00087 #endif
00088 #define INLINE
00089 #endif
00090
00091
00092 #include <sys/types.h>
00093 #include <stdlib.h>
00094 #include <string.h>
00095 #include <errno.h>
00096 #ifndef WIN32
00097 #include <sys/socket.h>
00098 #include <netinet/in.h>
00099 #include <arpa/inet.h>
00100 #endif
00101 #include <time.h>
00102 #include <rpc/types.h>
00103
00104 #ifdef HAVE_STRINGS_H
00105 #include <strings.h>
00106 #endif
00107
00108 #include "bounds.h"
00109 #include "decode.h"
00110 #include "event.h"
00111 #include "debug.h"
00112 #include "util.h"
00113 #include "plugbase.h"
00114 #include "parser.h"
00115 #include "mstring.h"
00116 #include "checksum.h"
00117 #include "log.h"
00118 #include "generators.h"
00119 #include "detect.h"
00120 #include "perf.h"
00121 #include "timersub.h"
00122 #include "ubi_SplayTree.h"
00123 #include "snort.h"
00124 #include "stream.h"
00125 #include "spp_stream4.h"
00126 #include "snort_packet_header.h"
00127 #include "event_queue.h"
00128 #include "inline.h"
00129
00130 #include "sfghash.h"
00131 #include "snort_stream4_session.h"
00132
00133
00134
00135
00136 #define CLOSED 0
00137 #define LISTEN 1
00138 #define SYN_RCVD 2
00139 #define SYN_SENT 3
00140 #define ESTABLISHED 4
00141 #define CLOSE_WAIT 5
00142 #define LAST_ACK 6
00143 #define FIN_WAIT_1 7
00144 #define CLOSING 8
00145 #define FIN_WAIT_2 9
00146 #define TIME_WAIT 10
00147
00148
00149 #define NMAP_FINGERPRINT_2S 30
00150 #define NMAP_FINGERPRINT_NULL 31
00151 #define NMAP_FINGERPRINT_UPSF 32
00152 #define NMAP_FINGERPRINT_ZERO_ACK 33
00153
00154 #define ACTION_NOTHING 0x00000000
00155 #define ACTION_FLUSH_SERVER_STREAM 0x00000001
00156 #define ACTION_FLUSH_CLIENT_STREAM 0x00000002
00157 #define ACTION_DROP_SESSION 0x00000004
00158 #define ACTION_ACK_SERVER_DATA 0x00000008
00159 #define ACTION_ACK_CLIENT_DATA 0x00000010
00160 #define ACTION_DATA_ON_SYN 0x00000020
00161 #define ACTION_SET_SERVER_ISN 0x00000040
00162 #define ACTION_COMPLETE_TWH 0x00000080
00163 #define ACTION_ALERT_NMAP_FINGERPRINT 0x00000100
00164 #define ACTION_INC_PORT 0x00000200
00165
00166 #define FROM_SERVER 0
00167 #define FROM_CLIENT 1
00168
00169 #define PRUNE_QUANTA 30
00170 #define STREAM4_MEMORY_CAP 8388608
00171 #define STREAM4_MAX_SESSIONS 8192
00172 #define STREAM4_CLEANUP 5
00173 #define STREAM4_CACHE_PERCENT 0.1
00174 #define STREAM4_TTL_LIMIT 5
00175 #define DEFAULT_STREAM_TRACKERS 256000
00176
00177 #define STATS_HUMAN_READABLE 1
00178 #define STATS_MACHINE_READABLE 2
00179 #define STATS_BINARY 3
00180
00181 #define STATS_MAGIC 0xDEAD029A
00182
00183 #define REVERSE 0
00184 #define NO_REVERSE 1
00185
00186 #define METHOD_FAVOR_NEW 0x01
00187 #define METHOD_FAVOR_OLD 0x02
00188
00189
00190 #define UNESTABLISHED_MAX_PCOUNT 300
00191
00192
00193 #define MAX_STREAM_SIZE (IP_MAXPACKET - IP_HEADER_LEN - TCP_HEADER_LEN - ETHERNET_HEADER_LEN)
00194
00195
00196 #define SEQ_LT(a,b) ((int)((a) - (b)) < 0)
00197 #define SEQ_LEQ(a,b) ((int)((a) - (b)) <= 0)
00198 #define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
00199 #define SEQ_GEQ(a,b) ((int)((a) - (b)) >= 0)
00200 #define SEQ_EQ(a,b) ((int)((a) - (b)) == 0)
00201
00202 #define NO_CHK_SEQ 0
00203 #define CHK_SEQ 1
00204
00205 #define S4I
00206
00207
00208 #ifndef SNORT_20
00209 extern char *file_name;
00210 extern int *file_line;
00211 extern int opdsize;
00212 #endif
00213
00214
00215
00216
00217
00218 #if defined (SOLARIS) || defined (SUNOS) || defined (__sparc__) || defined(__sparc64__) || defined (HPUX)
00219 #define SPARC_TWIDDLE 2
00220 #else
00221 #define SPARC_TWIDDLE 0
00222 #endif
00223
00224
00225 #define SELF_PRES_THRESHOLD 50
00226 #define SELF_PRES_PERIOD 90
00227
00228 #define SUSPEND_THRESHOLD 200
00229 #define SUSPEND_PERIOD 30
00230
00231 #define OPS_NORMAL 0
00232 #define OPS_SELF_PRESERVATION 1
00233 #define OPS_SUSPEND 2
00234
00235 #define MAXSIZE_IP 65535
00236 #define MAX_TRACKER_AMOUNT (MAX_STREAM_SIZE + 4000)
00237
00238
00239
00240
00241 #define FCOUNT 64
00242 #define STREAM4_FLUSH_BASE 512
00243 #define STREAM4_FLUSH_RANGE 1213
00244
00245 #define FLUSH_BEHAVIOR_RANDOM -1
00246 #define FLUSH_BEHAVIOR_DEFAULT 0
00247 #define FLUSH_BEHAVIOR_LARGE 1
00248
00249
00250 static u_int32_t old_flush_points[FCOUNT] = { 128, 217, 189, 130, 240, 221, 134, 129,
00251 250, 232, 141, 131, 144, 177, 201, 130,
00252 230, 190, 177, 142, 130, 200, 173, 129,
00253 250, 244, 174, 151, 201, 190, 180, 198,
00254 220, 201, 142, 185, 219, 129, 194, 140,
00255 145, 191, 197, 183, 199, 220, 231, 245,
00256 233, 135, 143, 158, 174, 194, 200, 180,
00257 201, 142, 153, 187, 173, 199, 143, 201 };
00258
00259 static u_int32_t new_flush_points[FCOUNT] = { 1280, 2176, 1895, 1303, 2402, 2211, 1340, 1298,
00260 2500, 2320, 1413, 1313, 1444, 1776, 2015, 1305,
00261 2130, 1190, 1377, 1492, 1380, 2100, 1373, 1029,
00262 750, 444, 874, 551, 401, 390, 1801, 1898,
00263 2260, 2601, 642, 485, 619, 929, 794, 340,
00264 445, 1911, 497, 883, 399, 2201, 2431, 2145,
00265 433, 735, 543, 658, 1174, 2042, 1200, 1800,
00266 2015, 1142, 1530, 487, 673, 899, 743, 2101 };
00267
00268 #ifdef DEBUG
00269 static char *state_names[] = { "CLOSED",
00270 "LISTEN",
00271 "SYN_RCVD",
00272 "SYN_SENT",
00273 "ESTABLISHED",
00274 "CLOSE_WAIT",
00275 "LAST_ACK",
00276 "FIN_WAIT_1",
00277 "CLOSING",
00278 "FIN_WAIT_2",
00279 "TIME_WAIT"};
00280 #endif
00281
00282 #ifdef GIDS
00283 #define STREAM4INLINE_WINDOW_SIZE 7000
00284 #define STREAM4INLINE_CUT_OFF_PERC 33
00285 #define MAX_SEQ_NUM 4294967295UL
00286
00287 char packet_added_to_stream;
00288 #endif
00289
00290
00291 typedef struct _OverlapData
00292 {
00293 u_int32_t seq_low;
00294 u_int32_t seq_hi;
00295
00296 } OverlapData;
00297
00298 typedef struct _BuildData
00299 {
00300 Stream *stream;
00301 u_int8_t *buf;
00302 u_int32_t total_size;
00303
00304 } BuildData;
00305
00306 typedef struct _BinStats
00307 {
00308 u_int32_t start_time;
00309 u_int32_t end_time;
00310 u_int32_t sip;
00311 u_int32_t cip;
00312 u_int16_t sport;
00313 u_int16_t cport;
00314 u_int32_t spackets;
00315 u_int32_t cpackets;
00316 u_int32_t sbytes;
00317 u_int32_t cbytes;
00318 } BinStats;
00319
00320 typedef struct _StatsLog
00321 {
00322 FILE *fp;
00323 char *filename;
00324
00325 } StatsLog;
00326
00327 typedef struct _StatsLogHeader
00328 {
00329 u_int32_t magic;
00330 u_int32_t version_major;
00331 u_int32_t version_minor;
00332 u_int32_t timezone;
00333 } StatsLogHeader;
00334
00335 typedef struct _S4Emergency
00336 {
00337 long end_time;
00338 char old_reassemble_client;
00339 char old_reassemble_server;
00340 char old_reassembly_alerts;
00341 int old_assurance_mode;
00342 char old_stateful_mode;
00343 u_int32_t new_session_count;
00344 int status;
00345 } S4Emergency;
00346
00347 typedef struct _StreamKey
00348 {
00349 u_int32_t sip;
00350 u_int32_t cip;
00351 u_int16_t sport;
00352 u_int16_t cport;
00353 } STREAM_KEY;
00354
00355 typedef Session *SessionPtr;
00356
00357 StatsLog *stats_log;
00358
00359
00360 #ifndef USE_HASH_TABLE
00361 static ubi_trRoot s_cache;
00362 static ubi_trRootPtr RootPtr = &s_cache;
00363 int GetSessionCount();
00364 #endif
00365
00366 u_int32_t safe_alloc_faults;
00367
00368
00369 Packet *stream_pkt;
00370
00371
00372
00373 extern int do_detect;
00374
00375
00376 FILE *session_log;
00377 Stream4Data s4data;
00378 u_int32_t stream4_memory_usage;
00379 u_int32_t ps_memory_usage;
00380
00381
00382 S4Emergency s4_emergency;
00383
00384
00385 u_int32_t flush_points[FCOUNT];
00386
00387
00388 void *SafeAlloc(unsigned long, int, Session *);
00389 void ParseStream4Args(char *);
00390 void Stream4InitReassembler(u_char *);
00391 void ReassembleStream4(Packet *, void *);
00392 #if !defined(USE_HASH_TABLE) && !defined(USE_SPLAY_TREE)
00393 Session *GetSession(Packet *);
00394 #endif
00395 Session *CreateNewSession(Packet *, u_int32_t, u_int32_t);
00396 void DropSession(Session *);
00397 void DeleteSession(Session *, u_int32_t);
00398 void DeleteSpd(ubi_trRootPtr);
00399 int GetDirection(Session *, Packet *);
00400 void Stream4ShutdownFunction(int, void *);
00401 void Stream4CleanExitFunction(int, void *);
00402 void Stream4RestartFunction(int, void *);
00403 void PrintSessionCache();
00404 int CheckRst(Session *, int, u_int32_t, Packet *);
00405 #ifdef GIDS
00406 void SegmentTruncTraverse(Stream *, u_int16_t);
00407 #endif
00408 int PruneSessionCache(u_int32_t, int, Session *);
00409 #ifdef GIDS
00410 int StoreStreamPkt(Session *, Packet *, u_int32_t);
00411 #else
00412 void StoreStreamPkt(Session *, Packet *, u_int32_t);
00413 #endif
00414 void FlushStream(Stream *, Packet *, int);
00415 #ifdef GIDS
00416 void TruncStream(Stream *s, Packet *p);
00417 #endif
00418 void InitStream4Pkt();
00419 int BuildPacket(Stream *, u_int32_t, Packet *, int);
00420 int CheckPorts(u_int16_t, u_int16_t);
00421 void PortscanWatch(Session *, u_int32_t);
00422 void PortscanDeclare(Packet *);
00423 void AddNewTarget(ubi_trRootPtr, u_int32_t, u_int16_t, u_int8_t);
00424 void AddNewPort(ubi_trRootPtr, u_int16_t, u_int8_t);
00425 int LogStream(Stream *);
00426 void WriteSsnStats(BinStats *);
00427 void OpenStatsFile();
00428 static int RetransTooFast(struct timeval *old, struct timeval *new);
00429 void Stream4Init(u_char *);
00430 void PreprocFunction(Packet *);
00431 void PreprocRestartFunction(int);
00432 void PreprocCleanExitFunction(int);
00433 static INLINE int isBetween(u_int32_t low, u_int32_t high, u_int32_t cur);
00434 static INLINE int NotForStream4(Packet *p);
00435 static INLINE int SetFinSent(Packet *p, Session *ssn, int direction);
00436 static INLINE int WithinSessionLimits(Packet *p, Stream *stream);
00437
00438
00439 static INLINE void StreamSegmentSub(Stream *stream, u_int16_t sub);
00440 static INLINE void StreamSegmentAdd(Stream *stream, u_int16_t add);
00441
00442
00443
00444
00445
00446
00447
00448 int UpdateState(Session *, Packet *, u_int32_t);
00449 int UpdateState2(Session *, Packet *, u_int32_t);
00450 int UpdateStateAsync(Session *, Packet *, u_int32_t);
00451
00452 static void TcpAction(Session *ssn, Packet *p, int action, int direction,
00453 u_int32_t pkt_seq, u_int32_t pkt_ack);
00454 static void TcpActionAsync(Session *ssn, Packet *p, int action, int direction,
00455 u_int32_t pkt_seq, u_int32_t pkt_ack);
00456 int LoadStateTable(const u_int32_t thetime, const char *path);
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 static INLINE int isBetween(u_int32_t low, u_int32_t high, u_int32_t cur)
00470 {
00471 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"(%u,%u,%u) = (low, high, cur)\n",
00472 low,high,cur););
00473 return (cur - low) <= (high - low);
00474 }
00475
00476
00477 #ifdef USE_HASH_TABLE
00478 #else
00479 int GetSessionCount()
00480 {
00481 return ubi_trCount(RootPtr);
00482 }
00483
00484 static int CompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00485 {
00486 Session *nSession;
00487 Session *iSession;
00488
00489 nSession = ((Session *)NodePtr);
00490 iSession = (Session *)ItemPtr;
00491
00492 if(nSession->server.ip < iSession->server.ip) return 1;
00493 else if(nSession->server.ip > iSession->server.ip) return -1;
00494
00495 if(nSession->client.ip < iSession->client.ip) return 1;
00496 else if(nSession->client.ip > iSession->client.ip) return -1;
00497
00498 if(nSession->server.port < iSession->server.port) return 1;
00499 else if(nSession->server.port > iSession->server.port) return -1;
00500
00501 if(nSession->client.port < iSession->client.port) return 1;
00502 else if(nSession->client.port > iSession->client.port) return -1;
00503
00504 return 0;
00505 }
00506 #endif
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 static int RetransTooFast(struct timeval *old, struct timeval *cur)
00517 {
00518 struct timeval diff;
00519
00520 TIMERSUB(cur, old, &diff);
00521
00522
00523 if(diff.tv_sec > 1)
00524 return 0;
00525 else if(diff.tv_sec == 1 && diff.tv_usec > 100)
00526 return 0;
00527
00528 return 1;
00529 }
00530
00531 static int DataCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00532 {
00533 StreamPacketData *nStream;
00534 StreamPacketData *iStream;
00535
00536 nStream = ((StreamPacketData *)NodePtr);
00537 iStream = ((StreamPacketData *)ItemPtr);
00538
00539 if(nStream->seq_num < iStream->seq_num) return 1;
00540 else if(nStream->seq_num > iStream->seq_num) return -1;
00541
00542 return 0;
00543 }
00544
00545 static int OverlapCompareFunc(ubi_trItemPtr ItemPtr, void *data)
00546 {
00547 OverlapData *overlap_info = (OverlapData *)data;
00548 StreamPacketData *iStream;
00549 iStream = ((StreamPacketData *)ItemPtr);
00550
00551 if ((iStream->seq_num > overlap_info->seq_low) &&
00552 (iStream->seq_num < overlap_info->seq_hi))
00553 return 1;
00554
00555 return 0;
00556 }
00557
00558 static void KillSpd(ubi_trNodePtr NodePtr)
00559 {
00560 StreamPacketData *tmp;
00561
00562 tmp = (StreamPacketData *)NodePtr;
00563
00564 stream4_memory_usage -= tmp->pkt_size;
00565 free(tmp->pktOrig);
00566
00567 stream4_memory_usage -= sizeof(StreamPacketData);
00568 free(tmp);
00569 }
00570
00571
00572 static void TraverseFunc(ubi_trNodePtr NodePtr, void *build_data)
00573 {
00574 Stream *s;
00575 StreamPacketData *spd;
00576 BuildData *bd;
00577 u_int8_t *buf;
00578 int trunc_size;
00579 int offset = 0;
00580
00581 if(s4data.stop_traverse)
00582 return;
00583
00584 spd = (StreamPacketData *) NodePtr;
00585 bd = (BuildData *) build_data;
00586 s = bd->stream;
00587 buf = bd->buf;
00588
00589
00590
00591
00592
00593 if(spd->payload_size == 0)
00594 {
00595 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "not reassembling because "
00596 "the payload size is zero.\n"););
00597 spd->chuck = SEG_FULL;
00598 return;
00599 }
00600 else if(SEQ_EQ(s->base_seq, s->last_ack))
00601 {
00602 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "not reassembling because "
00603 "base_seq = last_ack (%u).\n", s->base_seq););
00604 return;
00605 }
00606
00607
00608 else if(SEQ_LEQ(spd->seq_num, s->base_seq) &&
00609 SEQ_LEQ(spd->seq_num + spd->payload_size, s->base_seq))
00610 {
00611
00612 spd->chuck = SEG_FULL;
00613 return;
00614 }
00615
00616 else if(SEQ_LT(spd->seq_num, s->base_seq) &&
00617 isBetween(s->base_seq+1, s->last_ack, (spd->seq_num + spd->payload_size)))
00618 {
00619
00620
00621
00622 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Incompleted segment, copying up "
00623 "to last-ack\n"););
00624
00625
00626 trunc_size = (spd->seq_num+spd->payload_size) - s->base_seq;
00627
00628
00629 offset = s->base_seq - spd->seq_num;
00630
00631 if(trunc_size < 65500 && trunc_size > 0)
00632 {
00633 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Copying %d bytes into buffer, "
00634 "offset %d, buf %p\n", trunc_size, offset,
00635 buf););
00636 SafeMemcpy(buf, spd->payload+offset, trunc_size,
00637 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00638 pc.rebuilt_segs++;
00639 bd->total_size += trunc_size;
00640 }
00641 else
00642 {
00643 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Woah, got bad TCP segment "
00644 "trunctation value (%d)\n", trunc_size););
00645 }
00646
00647 spd->chuck = SEG_FULL;
00648 }
00649
00650 else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) &&
00651 isBetween(s->base_seq, s->last_ack, (spd->seq_num + spd->payload_size)))
00652 {
00653 offset = spd->seq_num - s->base_seq;
00654
00655 s->next_seq = spd->seq_num + spd->payload_size;
00656
00657 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Copying %d bytes into buffer, "
00658 "offset %d, buf %p\n", spd->payload_size, offset,
00659 buf););
00660
00661 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00662 "spd->seq_num (%u) s->last_ack (%u) "
00663 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
00664 "offset(%u), MAX(%u)\n",
00665 spd->seq_num, s->last_ack, s->base_seq,
00666 spd->payload_size, s->next_seq, offset,
00667 MAX_STREAM_SIZE));
00668
00669 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
00670 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00671
00672 pc.rebuilt_segs++;
00673
00674 spd->chuck = SEG_FULL;
00675 bd->total_size += spd->payload_size;
00676 }
00677 else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) &&
00678 SEQ_GT((spd->seq_num + spd->payload_size), s->last_ack))
00679 {
00680
00681
00682
00683
00684 trunc_size = s->last_ack - spd->seq_num;
00685
00686 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Truncating overlap of %d bytes\n",
00687 spd->seq_num + spd->payload_size - s->last_ack);
00688 DebugMessage(DEBUG_STREAM, " => trunc info seq: 0x%X "
00689 "size: %d last_ack: 0x%X\n",
00690 spd->seq_num, spd->payload_size, s->last_ack);
00691 );
00692
00693 offset = spd->seq_num - s->base_seq;
00694
00695 if(trunc_size < (65500-offset) && trunc_size > 0)
00696 {
00697 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Copying %d bytes into buffer, "
00698 "offset %d, buf %p\n", trunc_size, offset,
00699 buf););
00700 SafeMemcpy(buf+offset, spd->payload, trunc_size,
00701 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00702 pc.rebuilt_segs++;
00703 bd->total_size += trunc_size;
00704 spd->chuck = SEG_PARTIAL;
00705 }
00706 else
00707 {
00708 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Woah, got bad TCP segment "
00709 "trunctation value (%d)\n", trunc_size););
00710 }
00711 }
00712 else if(SEQ_GEQ(spd->seq_num,s->last_ack))
00713 {
00714
00715 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00716 " => Segment is past last ack'd data, "
00717 "ignoring for now...\n");
00718 DebugMessage(DEBUG_STREAM, " => (%d bytes @ seq 0x%X, "
00719 "ack: 0x%X)\n", spd->payload_size, spd->seq_num, s->last_ack);
00720 );
00721
00722
00723
00724
00725 s4data.stop_traverse = 1;
00726
00727 s4data.stop_seq = s->last_ack;
00728 }
00729 else
00730 {
00731
00732
00733
00734
00735
00736 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00737 "Ended up in the default case somehow.. !\n"
00738 "spd->seq_num(%u) spd->payload_size(%u)\n",
00739 spd->seq_num, spd->payload_size););
00740 }
00741 }
00742
00743 #ifdef GIDS
00744
00745
00746
00747
00748 static void TraverseFuncRebuildAll(ubi_trNodePtr NodePtr, void *build_data)
00749 {
00750 Stream *s;
00751 StreamPacketData *spd;
00752 BuildData *bd;
00753 u_int8_t *buf;
00754 int trunc_size = 0;
00755 int offset = 0;
00756
00757
00758 if(s4data.stop_traverse)
00759 return;
00760
00761 spd = (StreamPacketData *) NodePtr;
00762 bd = (BuildData *) build_data;
00763 s = bd->stream;
00764 buf = bd->buf;
00765
00766 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00767 "REASS: before: spd->seq_num (%u) s->last_ack (%u) "
00768 "s->base_seq(%u) size: (%u) s->next_seq(%u)\n",
00769 spd->seq_num, s->last_ack, s->base_seq,
00770 spd->payload_size, s->next_seq));
00771
00772
00773
00774 if(SEQ_LEQ(spd->seq_num, s->base_seq) &&
00775 SEQ_LEQ(spd->seq_num + spd->payload_size, s->base_seq))
00776 {
00777
00778 spd->chuck = SEG_FULL;
00779 return;
00780 }
00781
00782 else if(SEQ_LT(spd->seq_num, s->base_seq) &&
00783 isBetween(s->base_seq+1, s->last_ack, (spd->seq_num + spd->payload_size)))
00784 {
00785
00786
00787
00788 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Incompleted segment, copying up "
00789 "to last-ack\n"););
00790
00791
00792 trunc_size = (spd->seq_num+spd->payload_size) - s->base_seq;
00793
00794
00795 offset = s->base_seq - spd->seq_num;
00796
00797 if(trunc_size < 65500 && trunc_size > 0)
00798 {
00799 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS: starts outside ends inside: Copying %d bytes into buffer, "
00800 "offset %d, buf %p\n", trunc_size, offset,
00801 buf););
00802
00803 SafeMemcpy(buf, spd->payload+offset, trunc_size,
00804 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00805
00806 pc.rebuilt_segs++;
00807 bd->total_size += trunc_size;
00808 }
00809 else
00810 {
00811 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Woah, got bad TCP segment "
00812 "trunctation value (%d)\n", trunc_size););
00813 }
00814
00815 spd->chuck = SEG_FULL;
00816
00817 }
00818
00819 else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) &&
00820 isBetween(s->base_seq, s->last_ack, (spd->seq_num + spd->payload_size)))
00821 {
00822 offset = spd->seq_num - s->base_seq;
00823
00824 s->next_seq = spd->seq_num + spd->payload_size;
00825
00826 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS: in bounds: Copying %d bytes into buffer, "
00827 "offset %d, buf %p\n", spd->payload_size, offset,
00828 buf););
00829
00830 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00831 "spd->seq_num (%u) s->last_ack (%u) "
00832 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
00833 "offset(%u), MAX(%u)\n",
00834 spd->seq_num, s->last_ack, s->base_seq,
00835 spd->payload_size, s->next_seq, offset,
00836 MAX_STREAM_SIZE));
00837
00838 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
00839 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00840
00841 pc.rebuilt_segs++;
00842
00843 spd->chuck = SEG_FULL;
00844 bd->total_size += spd->payload_size;
00845 }
00846 else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) &&
00847 SEQ_GT((spd->seq_num + spd->payload_size), s->last_ack))
00848 {
00849 offset = spd->seq_num - s->base_seq;
00850
00851 s->next_seq = spd->seq_num + spd->payload_size;
00852
00853 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS: start in end out: Copying %d bytes into buffer, "
00854 "offset %d, buf %p\n", spd->payload_size, offset,
00855 buf););
00856
00857 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00858 "spd->seq_num (%u) s->last_ack (%u) "
00859 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
00860 "offset(%u), MAX(%u)\n",
00861 spd->seq_num, s->last_ack, s->base_seq,
00862 spd->payload_size, s->next_seq, offset,
00863 MAX_STREAM_SIZE));
00864
00865 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
00866 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00867
00868 pc.rebuilt_segs++;
00869
00870 spd->chuck = SEG_FULL;
00871 bd->total_size += spd->payload_size;
00872 }
00873 else if(SEQ_GEQ(spd->seq_num,s->last_ack))
00874 {
00875 offset = spd->seq_num - s->base_seq;
00876
00877 if(offset >= (MAX_STREAM_SIZE - spd->payload_size) &&
00878 SEQ_GT(spd->seq_num,s->next_seq))
00879 {
00880 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS: completely out: LONER! (offset %d seq_num %u next_seq %u).",
00881 offset, spd->seq_num, s->next_seq););
00882
00883 return;
00884 }
00885
00886
00887 s->next_seq = spd->seq_num + spd->payload_size;
00888
00889 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS: completely out: Copying %d bytes into buffer, "
00890 "offset %d, buf %p\n", spd->payload_size, offset,
00891 buf););
00892
00893 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00894 "spd->seq_num (%u) s->last_ack (%u) "
00895 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
00896 "offset(%u), MAX(%u)\n",
00897 spd->seq_num, s->last_ack, s->base_seq,
00898 spd->payload_size, s->next_seq, offset,
00899 MAX_STREAM_SIZE));
00900
00901 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
00902 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
00903
00904 pc.rebuilt_segs++;
00905
00906 spd->chuck = SEG_FULL;
00907 bd->total_size += spd->payload_size;
00908 }
00909 else
00910 {
00911
00912
00913
00914
00915
00916 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00917 "Ended up in the default case somehow.. !\n"
00918 "spd->seq_num(%u) spd->payload_size(%u)\n",
00919 spd->seq_num, spd->payload_size););
00920 }
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 static void TraverseFuncRebuildAllWrap(ubi_trNodePtr NodePtr, void *build_data)
00934 {
00935 Stream *s;
00936 StreamPacketData *spd;
00937 BuildData *bd;
00938 u_int8_t *buf;
00939 int trunc_size = 0;
00940 int offset = 0;
00941
00942 u_int32_t before_size;
00943
00944
00945
00946 if(s4data.stop_traverse)
00947 return;
00948
00949 spd = (StreamPacketData *) NodePtr;
00950 bd = (BuildData *) build_data;
00951 s = bd->stream;
00952 buf = bd->buf;
00953
00954
00955 before_size = MAX_SEQ_NUM - s->base_seq;
00956
00957
00958 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
00959 "REASS_WRAP: before: spd->seq_num (%u, seq_num+payloadsize: %u) s->last_ack (%u) s->base_seq(%u) before(%u) size: (%u) s->next_seq(%u), offset(%u), MAX(%u)\n",
00960 spd->seq_num, spd->seq_num+spd->payload_size, s->last_ack, s->base_seq, before_size, spd->payload_size, s->next_seq, offset, MAX_STREAM_SIZE));
00961
00962
00963 if(SEQ_LEQ(spd->seq_num, s->base_seq) &&
00964 SEQ_LEQ(spd->seq_num + spd->payload_size, s->base_seq))
00965 {
00966
00967 spd->chuck = SEG_FULL;
00968 return;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 else if (SEQ_LT(spd->seq_num, s->base_seq)
00980 &&
00981 (SEQ_GEQ((spd->seq_num + spd->payload_size), s->base_seq) ||
00982 SEQ_LEQ((spd->seq_num + spd->payload_size), s->last_ack)))
00983 {
00984
00985
00986
00987 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: Incompleted segment, copying up to last-ack\n"););
00988
00989
00990
00991
00992
00993
00994
00995 if((spd->seq_num+spd->payload_size) > s->base_seq)
00996 {
00997
00998 trunc_size = (spd->seq_num+spd->payload_size) - s->base_seq;
00999
01000 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: packet ends before we wrap, "
01001 "so trunc_size(%d) = (spd->seq_num+spd->payload_size(%u)) - s->base_seq(%u)\n",
01002 trunc_size, (spd->seq_num+spd->payload_size), s->base_seq););
01003 }
01004 else
01005 {
01006
01007
01008
01009 before_size = MAX_SEQ_NUM - s->base_seq;
01010
01011
01012 trunc_size = before_size + (spd->seq_num+spd->payload_size);
01013
01014 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: packet ends after we wrap, "
01015 "so trunc_size(%d) = before_size(%u) + (spd->seq_num+spd->payload_size(%u))\n",
01016 trunc_size, before_size, (spd->seq_num+spd->payload_size)););
01017 }
01018
01019
01020
01021
01022 offset = s->base_seq - spd->seq_num;
01023
01024
01025 if(trunc_size < 65500 && trunc_size > 0)
01026 {
01027 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: starts outside ends inside: Copying %d bytes into buffer, "
01028 "offset %d, buf %p\n", trunc_size, offset, buf););
01029
01030 SafeMemcpy(buf, spd->payload+offset, trunc_size,
01031 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
01032
01033 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: SafeMemcpy completed\n"););
01034
01035 pc.rebuilt_segs++;
01036 bd->total_size += trunc_size;
01037 }
01038 else
01039 {
01040 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: Woah, got bad TCP segment "
01041 "trunctation value (%d)\n", trunc_size););
01042 }
01043
01044 spd->chuck = SEG_FULL;
01045
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 else if((SEQ_GT(spd->seq_num,s->base_seq) || SEQ_LT(spd->seq_num,s->last_ack-1))
01069 &&
01070 (SEQ_GT(spd->seq_num+spd->payload_size,s->base_seq) || SEQ_LT(spd->seq_num+spd->payload_size,s->last_ack)))
01071 {
01072
01073 if(SEQ_LT(spd->seq_num,s->last_ack-1) || SEQ_LT(spd->seq_num+spd->payload_size,s->last_ack))
01074 {
01075 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: packet before wrap\n"););
01076
01077 offset = spd->seq_num - s->base_seq;
01078 }
01079
01080 else if(SEQ_GT(spd->seq_num,s->base_seq) || SEQ_LT(spd->seq_num+spd->payload_size,s->last_ack))
01081 {
01082 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: starts before wrap, ends after it\n"););
01083
01084 offset = spd->seq_num - s->base_seq;
01085 }
01086
01087 else
01088 {
01089
01090 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: completely after the wrap\n"););
01091
01092 offset = spd->seq_num + before_size;
01093 }
01094
01095
01096 s->next_seq = spd->seq_num + spd->payload_size;
01097
01098 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: in bounds: Copying %d bytes into buffer, "
01099 "offset %d, buf %p\n", spd->payload_size, offset, buf););
01100
01101 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
01102 "REASS_WRAP: spd->seq_num (%u) s->last_ack (%u) "
01103 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
01104 "offset(%u), MAX(%u)\n",
01105 spd->seq_num, s->last_ack, s->base_seq,
01106 spd->payload_size, s->next_seq, offset,
01107 MAX_STREAM_SIZE));
01108
01109 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
01110 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
01111
01112 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: SafeMemcpy completed\n"););
01113
01114 pc.rebuilt_segs++;
01115
01116 spd->chuck = SEG_FULL;
01117 bd->total_size += spd->payload_size;
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 else if((SEQ_GT(spd->seq_num,s->base_seq) || SEQ_LT(spd->seq_num,s->last_ack))
01131 &&
01132 SEQ_GT(spd->seq_num+spd->payload_size,s->last_ack))
01133 {
01134
01135 if(SEQ_LT(spd->seq_num,s->last_ack))
01136 {
01137 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: entirely after the wrap\n"););
01138
01139 offset = before_size + spd->seq_num;
01140 }
01141
01142 else
01143 {
01144 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: packet starts before the wrap, ends after it\n"););
01145
01146 offset = spd->seq_num - s->base_seq;
01147 }
01148
01149 s->next_seq = spd->seq_num + spd->payload_size;
01150
01151 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: start in end out: Copying %d bytes into buffer, "
01152 "offset %d, buf %p\n", spd->payload_size, offset,
01153 buf););
01154
01155 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
01156 "REASS_WRAP: spd->seq_num (%u) s->last_ack (%u) "
01157 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
01158 "offset(%u), MAX(%u)\n",
01159 spd->seq_num, s->last_ack, s->base_seq,
01160 spd->payload_size, s->next_seq, offset,
01161 MAX_STREAM_SIZE));
01162
01163 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
01164 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
01165
01166 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: SafeMemcpy completed\n"););
01167
01168 pc.rebuilt_segs++;
01169
01170 spd->chuck = SEG_FULL;
01171 bd->total_size += spd->payload_size;
01172 }
01173 else if(SEQ_GEQ(spd->seq_num,s->last_ack))
01174 {
01175 offset = spd->seq_num + before_size;
01176
01177 s->next_seq = spd->seq_num + spd->payload_size;
01178
01179 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: completely out: Copying %d bytes into buffer, "
01180 "offset %d, buf %p\n", spd->payload_size, offset,
01181 buf););
01182
01183 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
01184 "REASS_WRAP: spd->seq_num (%u) s->last_ack (%u) "
01185 "s->base_seq(%u) size: (%u) s->next_seq(%u), "
01186 "offset(%u), MAX(%u)\n",
01187 spd->seq_num, s->last_ack, s->base_seq,
01188 spd->payload_size, s->next_seq, offset,
01189 MAX_STREAM_SIZE));
01190
01191 SafeMemcpy(buf+offset, spd->payload, spd->payload_size,
01192 stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE);
01193
01194 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REASS_WRAP: SafeMemcpy completed\n"););
01195
01196 pc.rebuilt_segs++;
01197
01198 spd->chuck = SEG_FULL;
01199 bd->total_size += spd->payload_size;
01200 }
01201 else
01202 {
01203
01204
01205
01206
01207
01208 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
01209 "REASS_WRAP: Ended up in the default case somehow.. !\n"
01210 "spd->seq_num(%u) spd->payload_size(%u)\n",
01211 spd->seq_num, spd->payload_size););
01212 }
01213 }
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 void SegmentTruncTraverse(Stream *s, u_int16_t bytes_to_clear)
01226 {
01227 StreamPacketData *spd = NULL;
01228 StreamPacketData *foo = NULL;
01229 StreamPacketData *savspd = NULL;
01230 u_int16_t removed_so_far = 0;
01231 char quit_on_limit_reached = 0;
01232
01233
01234
01235 if (!s->data.root)
01236 return;
01237
01238 spd = (StreamPacketData *) ubi_btFirst((ubi_btNodePtr)&s->data);
01239
01240
01241 while(spd != NULL && ubi_trCount(&s->data) > 1)
01242 {
01243
01244
01245
01246 if((MAX_SEQ_NUM - MAX_STREAM_SIZE) < spd->seq_num &&
01247 (spd->seq_num - MAX_STREAM_SIZE) > s->last_ack &&
01248 (spd->seq_num - (MAX_STREAM_SIZE * 2)) > s->base_seq)
01249 {
01250
01251
01252 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
01253 "TRUNC(pre-wrap leftover cleanup): spd->seq_num (%u) s->last_ack (%u) "
01254 "s->base_seq(%u) size: (%u) s->next_seq(%u)\n",
01255 spd->seq_num, s->last_ack, s->base_seq,
01256 spd->payload_size, s->next_seq));
01257
01258 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC(pre-wrap leftover cleanup): adjusting s->bytes_tracked: %u. Going to sub %u...\n", s->bytes_tracked, spd->payload_size););
01259
01260
01261 quit_on_limit_reached = 0;
01262 }
01263 else
01264 {
01265 quit_on_limit_reached = 1;
01266
01267
01268
01269
01270 if(SEQ_LEQ(spd->seq_num, s->base_seq) &&
01271 SEQ_LEQ(spd->seq_num + spd->payload_size, s->base_seq))
01272 {
01273 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: packet before current window, base: %u.\n", s->base_seq););
01274
01275
01276 }
01277
01278 else if(SEQ_LT(spd->seq_num, s->base_seq) &&
01279 isBetween(s->base_seq+1, s->last_ack, (spd->seq_num + spd->payload_size)))
01280 {
01281 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: Packet starts before current window, base: %u.\n", s->base_seq););
01282
01283
01284 s->base_seq = spd->seq_num + spd->payload_size;
01285
01286 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: adjusted base to: %u.\n", s->base_seq););
01287 }
01288
01289 else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) &&
01290 isBetween(s->base_seq, s->last_ack, (spd->seq_num + spd->payload_size)))
01291 {
01292 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: Packet in current window, base: %u.\n", s->base_seq););
01293
01294
01295 s->base_seq = spd->seq_num + spd->payload_size;
01296
01297 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: adjusted base to: %u.\n", s->base_seq););
01298 }
01299 else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) &&
01300 SEQ_GT((spd->seq_num + spd->payload_size), s->last_ack))
01301 {
01302 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: Packet partly outside current window, base: %u.\n", s->base_seq););
01303
01304
01305 s->base_seq = spd->seq_num + spd->payload_size;
01306
01307 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: adjusted base to: %u.\n", s->base_seq););
01308 }
01309 else if(SEQ_GEQ(spd->seq_num,s->last_ack))
01310 {
01311 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: Packet totally past the current window, base: %u.\n", s->base_seq););
01312
01313
01314 s->base_seq = spd->seq_num + spd->payload_size;
01315
01316 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TRUNC: adjusted base to: %u.\n", s->base_seq););
01317 }
01318 }
01319
01320 savspd = spd;
01321 spd = (StreamPacketData *) ubi_btNext((ubi_btNodePtr)spd);
01322 #ifdef DEBUG
01323 if(savspd->chuck == SEG_FULL)
01324 {
01325 DebugMessage(DEBUG_STREAM, "[sct] chucking used segment\n");
01326 }
01327 else
01328 {
01329 DebugMessage(DEBUG_STREAM, "[sct] tossing unused segment\n");
01330 }
01331 #endif
01332
01333
01334 foo = (StreamPacketData *) ubi_sptRemove(&s->data,
01335 (ubi_btNodePtr) savspd);
01336
01337
01338 StreamSegmentSub(s, foo->payload_size);
01339
01340
01341 removed_so_far += foo->payload_size;
01342
01343
01344 stream4_memory_usage -= foo->pkt_size;
01345 free(foo->pktOrig);
01346 stream4_memory_usage -= sizeof(StreamPacketData);
01347 free(foo);
01348
01349
01350
01351 if(quit_on_limit_reached == 1)
01352 {
01353 if(removed_so_far >= bytes_to_clear)
01354 {
01355
01356 break;
01357 }
01358 }
01359 }
01360
01361 return;
01362 }
01363
01364
01365 #endif
01366
01367
01368 void SegmentCleanTraverse(Stream *s)
01369 {
01370 StreamPacketData *spd;
01371 StreamPacketData *foo;
01372
01373 if (!s->data.root)
01374 return;
01375
01376 spd = (StreamPacketData *) ubi_btFirst((ubi_btNodePtr)&s->data);
01377
01378 while(spd != NULL)
01379 {
01380 if(spd->chuck == SEG_FULL || SEQ_GEQ(s->last_ack,(spd->seq_num+spd->payload_size)))
01381 {
01382 StreamPacketData *savspd = spd;
01383 spd = (StreamPacketData *) ubi_btNext((ubi_btNodePtr)spd);
01384 #ifdef DEBUG
01385 if(savspd->chuck == SEG_FULL)
01386 {
01387 DebugMessage(DEBUG_STREAM, "[sct] chucking used segment\n");
01388 }
01389 else
01390 {
01391 DebugMessage(DEBUG_STREAM, "[sct] tossing unused segment\n");
01392 }
01393 #endif
01394 foo = (StreamPacketData *) ubi_sptRemove(&s->data,
01395 (ubi_btNodePtr) savspd);
01396 StreamSegmentSub(s, foo->payload_size);
01397
01398 stream4_memory_usage -= foo->pkt_size;
01399 free(foo->pktOrig);
01400 stream4_memory_usage -= sizeof(StreamPacketData);
01401 free(foo);
01402 }
01403 else
01404 {
01405 spd = (StreamPacketData *) ubi_btNext((ubi_btNodePtr)spd);
01406 }
01407 }
01408 }
01409
01410
01411 void DirectLogTcpdump(struct pcap_pkthdr *, u_int8_t *);
01412
01413 static void LogTraverse(ubi_trNodePtr NodePtr, void *foo)
01414 {
01415 StreamPacketData *spd;
01416
01417 spd = (StreamPacketData *) NodePtr;
01418
01419 DirectLogTcpdump((struct pcap_pkthdr *)&spd->pkth, spd->pkt);
01420 }
01421
01422 void *SafeAlloc(unsigned long size, int tv_sec, Session *ssn)
01423 {
01424 void *tmp;
01425
01426 stream4_memory_usage += size;
01427
01428
01429 if(stream4_memory_usage > s4data.memcap)
01430 {
01431 pc.str_mem_faults++;
01432 sfPerf.sfBase.iStreamFaults++;
01433 if(!PruneSessionCache((u_int32_t)tv_sec, 0, ssn))
01434 {
01435
01436
01437
01438
01439 #ifdef GIDS
01440 if(s4data.stream4inline_mode && s4data.truncate)
01441 TruncSessionCache((u_int32_t)tv_sec, 15, ssn);
01442 else
01443 #endif
01444 PruneSessionCache(0, 5, ssn);
01445 }
01446 }
01447
01448 tmp = (void *) calloc(size, sizeof(char));
01449
01450 if(tmp == NULL)
01451 {
01452 FatalError("Unable to allocate memory! (%lu bytes in use)\n",
01453 (unsigned long)stream4_memory_usage);
01454 }
01455
01456 return tmp;
01457 }
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 void SetupStream4()
01472 {
01473
01474
01475 RegisterPreprocessor("stream4", Stream4Init);
01476 RegisterPreprocessor("stream4_reassemble", Stream4InitReassembler);
01477
01478 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Preprocessor: Stream4 is setup...\n"););
01479 }
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492 void Stream4Init(u_char *args)
01493 {
01494 char logfile[STD_BUF];
01495
01496 s4data.stream4_active = 1;
01497 pv.stateful = 1;
01498 s4data.memcap = STREAM4_MEMORY_CAP;
01499 s4data.max_sessions = STREAM4_MAX_SESSIONS;
01500
01501 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "log_dir is %s\n", pv.log_dir););
01502
01503
01504 s4data.sp_threshold = SELF_PRES_THRESHOLD;
01505 s4data.sp_period = SELF_PRES_PERIOD;
01506 s4data.suspend_threshold = SUSPEND_THRESHOLD;
01507 s4data.suspend_period = SUSPEND_PERIOD;
01508 s4data.state_protection = 0;
01509
01510 s4_emergency.end_time = 0;
01511 s4_emergency.new_session_count = 0;
01512 s4_emergency.status = OPS_NORMAL;
01513
01514
01515 ParseStream4Args(args);
01516
01517 snprintf(logfile, STD_BUF, "%s/%s", pv.log_dir, "session.log");
01518
01519 if(s4data.track_stats_flag)
01520 {
01521 if((session_log = fopen(logfile, "a+")) == NULL)
01522 {
01523 FatalError("Unable to write to \"%s\": %s\n", logfile,
01524 strerror(errno));
01525 }
01526 }
01527
01528 s4data.last_prune_time = 0;
01529
01530 stream_pkt = (Packet *) SafeAlloc(sizeof(Packet), 0, NULL);
01531
01532 InitStream4Pkt();
01533
01534
01535 snort_runtime.capabilities.stateful_inspection = 1;
01536
01537 #ifdef USE_HASH_TABLE
01538 InitSessionCache();
01539 #else
01540 (void)ubi_trInitTree(RootPtr,
01541 CompareFunc,
01542 0);
01543 #endif
01544
01545 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Preprocessor: Stream4 Initialized\n"););
01546
01547
01548 AddFuncToPreprocList(ReassembleStream4);
01549 AddFuncToShutdownList(Stream4ShutdownFunction, NULL);
01550 AddFuncToCleanExitList(Stream4CleanExitFunction, NULL);
01551 AddFuncToRestartList(Stream4RestartFunction, NULL);
01552 }
01553
01554 void DisplayStream4Config(void)
01555 {
01556 LogMessage("Stream4 config:\n");
01557 LogMessage(" Stateful inspection: %s\n",
01558 s4data.stateful_inspection_flag ? "ACTIVE": "INACTIVE");
01559 LogMessage(" Session statistics: %s\n",
01560 s4data.track_stats_flag ? "ACTIVE":"INACTIVE");
01561 LogMessage(" Session timeout: %d seconds\n", s4data.timeout);
01562 LogMessage(" Session memory cap: %lu bytes\n", (unsigned long)s4data.memcap);
01563 LogMessage(" Session count max: %d sessions\n", (unsigned long)s4data.max_sessions);
01564 if (s4data.cache_clean_percent != 0)
01565 LogMessage(" Session cleanup percentage: %f %%\n", s4data.cache_clean_percent);
01566 else
01567 LogMessage(" Session cleanup count: %d\n", s4data.cache_clean_sessions);
01568 LogMessage(" State alerts: %s\n",
01569 s4data.state_alerts ? "ACTIVE":"INACTIVE");
01570 LogMessage(" Evasion alerts: %s\n",
01571 s4data.evasion_alerts ? "ACTIVE":"INACTIVE");
01572 LogMessage(" Scan alerts: %s\n",
01573 s4data.ps_alerts ? "ACTIVE":"INACTIVE");
01574 LogMessage(" Log Flushed Streams: %s\n",
01575 s4data.log_flushed_streams ? "ACTIVE":"INACTIVE");
01576 LogMessage(" MinTTL: %d\n", s4data.min_ttl);
01577 LogMessage(" TTL Limit: %d\n", s4data.ttl_limit);
01578 LogMessage(" Async Link: %d\n", s4data.asynchronous_link);
01579 LogMessage(" State Protection: %d\n", s4data.state_protection);
01580 LogMessage(" Self preservation threshold: %d\n", s4data.sp_threshold);
01581 LogMessage(" Self preservation period: %d\n", s4data.sp_period);
01582 LogMessage(" Suspend threshold: %d\n", s4data.suspend_threshold);
01583 LogMessage(" Suspend period: %d\n", s4data.suspend_period);
01584 LogMessage(" Enforce TCP State: %s\n",
01585 s4data.enforce_state ? "ACTIVE" : "INACTIVE");
01586 LogMessage(" Midstream Drop Alerts: %s\n",
01587 s4data.ms_inline_alerts ? "ACTIVE" : "INACTIVE");
01588 if (s4data.server_inspect_limit > 0)
01589 LogMessage(" Server Data Inspection Limit: %d\n",
01590 s4data.server_inspect_limit);
01591
01592 #ifdef GIDS
01593 LogMessage("Inline-mode options:\n");
01594 LogMessage(" Inline-mode enabled? (stream4inline): %s\n", s4data.stream4inline_mode ? "Yes" : "No");
01595 LogMessage(" Sliding Windowsize (window_size): %u (max full conn: %u)\n", s4data.stream4inline_window_size, s4data.memcap / s4data.stream4inline_window_size);
01596 LogMessage(" Memcap reached method (truncate): %s\n", s4data.truncate ? "Truncate" : "Prune");
01597 LogMessage(" Truncate percentage (truncate_percentage): %d\n", s4data.truncate_cut_off_perc);
01598
01599 LogMessage(" DROP out-of-window packets (drop_out_of_window): %s\n", s4data.drop_out_of_window ? "Yes" : "No");
01600 LogMessage(" DROP data on unestablised session state (drop_data_on_unest): %s\n", s4data.drop_data_on_unest ? "Yes" : "No");
01601 LogMessage(" DROP no tcp-flags on establised packets (drop_no_tcp_on_est): %s\n", s4data.drop_no_tcp_on_est ? "Yes" : "No");
01602 LogMessage(" DROP packet not within session limits (drop_not_in_limits): %s\n", s4data.drop_not_in_limits ? "Yes" : "No");
01603 LogMessage(" DROP ttl evasion (drop_ttl_evasion): %s\n", s4data.drop_ttl_evasion ? "Yes" : "No");
01604
01605 LogMessage(" Store/Load state from/to disk: %s\n", s4data.store_state_to_disk ? "Yes" : "No");
01606 if(s4data.store_state_to_disk)
01607 LogMessage(" State file: %s\n", s4data.state_file);
01608 #endif
01609 }
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 void ParseStream4Args(char *args)
01625 {
01626 char **toks;
01627 int num_toks;
01628 int num_statefiletoks;
01629 int i;
01630 char *index;
01631 char **stoks = NULL;
01632 char **statefiletoks = NULL;
01633 int s_toks;
01634
01635 s4data.timeout = PRUNE_QUANTA;
01636 s4data.memcap = STREAM4_MEMORY_CAP;
01637 s4data.max_sessions = STREAM4_MAX_SESSIONS;
01638 s4data.cache_clean_percent = 0;
01639 s4data.cache_clean_sessions = STREAM4_CLEANUP;
01640 s4data.stateful_inspection_flag = 1;
01641 s4data.state_alerts = 0;
01642 s4data.evasion_alerts = 1;
01643 s4data.ps_alerts = 0;
01644 s4data.reassemble_client = s4data.reassemble_server = 0;
01645 s4data.log_flushed_streams = 0;
01646 s4data.min_ttl = 1;
01647 s4data.path_mtu = 1460;
01648 s4data.ttl_limit = STREAM4_TTL_LIMIT;
01649 s4data.asynchronous_link = 0;
01650 s4data.flush_data_diff_size = 500;
01651 s4data.zero_flushed_packets = 0;
01652 s4data.flush_on_alert = 0;
01653 s4data.overlap_limit = -1;
01654 s4data.server_inspect_limit = -1;
01655
01656
01657 s4data.flush_behavior = FLUSH_BEHAVIOR_DEFAULT;
01658 s4data.flush_range = STREAM4_FLUSH_RANGE;
01659 s4data.flush_base = STREAM4_FLUSH_BASE;
01660 s4data.flush_seed = getpid() + time(NULL);
01661
01662 #ifdef GIDS
01663
01664 s4data.stream4inline_mode = 0;
01665 s4data.stream4inline_window_size = STREAM4INLINE_WINDOW_SIZE;
01666 s4data.truncate = 0;
01667 s4data.truncate_cut_off_perc = STREAM4INLINE_CUT_OFF_PERC;
01668 s4data.drop_out_of_window = 0;
01669 s4data.drop_data_on_unest = 0;
01670 s4data.drop_data_on_unest = 0;
01671 s4data.drop_no_tcp_on_est = 0;
01672 s4data.drop_not_in_limits = 0;
01673 s4data.drop_ttl_evasion = 0;
01674 s4data.store_state_to_disk = 0;
01675 memset(s4data.state_file, 0, sizeof(s4data.state_file));
01676 #endif
01677
01678
01679 if(args == NULL || args[0] == '\0')
01680 {
01681 DisplayStream4Config();
01682 return;
01683 }
01684
01685 i=0;
01686
01687 toks = mSplit(args, ",", 20, &num_toks, 0);
01688
01689 while(i < num_toks)
01690 {
01691 index = toks[i];
01692
01693 while(isspace((int)*index)) index++;
01694
01695 stoks = mSplit(index, " ", 4, &s_toks, 0);
01696
01697 if(!strcasecmp(stoks[0], "noinspect"))
01698 {
01699 s4data.stateful_inspection_flag = 0;
01700 }
01701 else if(!strcasecmp(stoks[0], "asynchronous_link"))
01702 {
01703 s4data.asynchronous_link = 1;
01704 }
01705 else if(!strcasecmp(stoks[0], "keepstats"))
01706 {
01707 s4data.track_stats_flag = STATS_HUMAN_READABLE;
01708
01709 if(s_toks > 1)
01710 {
01711 if(!strcasecmp(stoks[1], "machine"))
01712 {
01713 s4data.track_stats_flag = STATS_MACHINE_READABLE;
01714 }
01715 else if(!strcasecmp(stoks[1], "binary"))
01716 {
01717 s4data.track_stats_flag = STATS_BINARY;
01718 stats_log = (StatsLog *) calloc(sizeof(StatsLog),
01719 sizeof(char));
01720 stats_log->filename = strdup("snort-unified.stats");
01721 OpenStatsFile();
01722 }
01723 else
01724 {
01725 ErrorMessage("Bad stats mode for stream4, ignoring\n");
01726 s4data.track_stats_flag = 0;
01727 }
01728 }
01729 }
01730 else if(!strcasecmp(stoks[0], "detect_scans"))
01731 {
01732 s4data.ps_alerts = 1;
01733 }
01734 else if(!strcasecmp(stoks[0], "log_flushed_streams"))
01735 {
01736 s4data.log_flushed_streams = 1;
01737 }
01738 else if(!strcasecmp(stoks[0], "detect_state_problems"))
01739 {
01740 s4data.state_alerts = 1;
01741 }
01742 else if(!strcasecmp(stoks[0], "disable_evasion_alerts"))
01743 {
01744 s4data.evasion_alerts = 0;
01745 }
01746 else if(!strcasecmp(stoks[0], "timeout"))
01747 {
01748 if(isdigit((int)stoks[1][0]))
01749 {
01750 s4data.timeout = atoi(stoks[1]);
01751 }
01752 else
01753 {
01754 LogMessage("WARNING %s(%d) => Bad timeout in config file, "
01755 "defaulting to %d seconds\n", file_name, file_line,
01756 PRUNE_QUANTA);
01757
01758 s4data.timeout = PRUNE_QUANTA;
01759 }
01760 }
01761 else if(!strcasecmp(stoks[0], "memcap"))
01762 {
01763 if(isdigit((int)stoks[1][0]))
01764 {
01765 s4data.memcap = atoi(stoks[1]);
01766
01767 if(s4data.memcap < 16384)
01768 {
01769 LogMessage("WARNING %s(%d) => Ludicrous (<16k) memcap "
01770 "size, setting to default (%d bytes)\n", file_name,
01771 file_line, STREAM4_MEMORY_CAP);
01772
01773 s4data.memcap = STREAM4_MEMORY_CAP;
01774 }
01775 }
01776 else
01777 {
01778 FatalError("%s(%d) => Bad memcap in config file, %d\n",
01779 file_name, file_line);
01780 }
01781 }
01782 else if(!strcasecmp(stoks[0], "max_sessions"))
01783 {
01784 if(isdigit((int)stoks[1][0]))
01785 {
01786 s4data.max_sessions = atoi(stoks[1]);
01787
01788 if(s4data.max_sessions < 8192)
01789 {
01790 LogMessage("WARNING %s(%d) => Ludicrous (<8k) max_sessions "
01791 "size, setting to default (%d sessions)\n", file_name,
01792 file_line, STREAM4_MAX_SESSIONS);
01793
01794 s4data.max_sessions = STREAM4_MAX_SESSIONS;
01795 }
01796 }
01797 else
01798 {
01799 FatalError("%s(%d) => Bad max_sessions in config file, %d\n",
01800 file_name, file_line);
01801 }
01802 }
01803 else if(!strcasecmp(stoks[0], "cache_clean_percent"))
01804 {
01805 if(isdigit((int)stoks[1][0]))
01806 {
01807 s4data.cache_clean_percent = atof(stoks[1]);
01808
01809 if ((s4data.cache_clean_percent < 0) ||
01810 (s4data.cache_clean_percent > 5))
01811 {
01812 LogMessage("WARNING %s(%d) => Ludicrous (%f) cache cleanup "
01813 "percentage, setting to default (%f %%)\n",
01814 file_name, file_line, STREAM4_CACHE_PERCENT);
01815
01816 s4data.cache_clean_percent = STREAM4_CACHE_PERCENT;
01817 }
01818 }
01819 else
01820 {
01821 FatalError("%s(%d) => Bad cache cleanup percent in "
01822 "config file, %d\n", file_name, file_line);
01823
01824 }
01825 }
01826 else if(!strcasecmp(stoks[0], "cache_clean_sessions"))
01827 {
01828 if(isdigit((int)stoks[1][0]))
01829 {
01830 s4data.cache_clean_sessions = atoi(stoks[1]);
01831 }
01832 else
01833 {
01834 FatalError("%s(%d) => Bad cache cleanup value in "
01835 "config file\n", file_name, file_line);
01836
01837 }
01838 }
01839 else if(!strcasecmp(stoks[0], "ttl_limit"))
01840 {
01841 if(s_toks > 1)
01842 {
01843 if(stoks[1] == NULL || stoks[1][0] == '\0')
01844 {
01845 FatalError("%s(%d) => ttl_limit requires an integer argument\n",
01846 file_name,file_line);
01847 }
01848
01849 if(isdigit((int)stoks[1][0]))
01850 {
01851 s4data.ttl_limit = atoi(stoks[1]);
01852 }
01853 else
01854 {
01855 LogMessage("WARNING %s(%d) => Bad TTL Limit"
01856 "size, setting to default (%d\n", file_name,
01857 file_line, STREAM4_TTL_LIMIT);
01858
01859 s4data.ttl_limit = STREAM4_TTL_LIMIT;
01860 }
01861 }
01862 else
01863 {
01864 FatalError("%s(%d) => ttl_limit requires an integer argument\n",
01865 file_name,file_line);
01866 }
01867 }
01868 else if(!strcasecmp(stoks[0], "self_preservation_threshold"))
01869 {
01870 if(isdigit((int)stoks[1][0]))
01871 {
01872 s4data.sp_threshold = atoi(stoks[1]);
01873 }
01874 else
01875 {
01876 LogMessage("WARNING %s(%d) => Bad sp_threshold in config file, "
01877 "defaulting to %d new sessions/second\n", file_name,
01878 file_line, SELF_PRES_THRESHOLD);
01879
01880 s4data.sp_threshold = SELF_PRES_THRESHOLD;
01881 }
01882 }
01883 else if(!strcasecmp(stoks[0], "self_preservation_period"))
01884 {
01885 if(isdigit((int)stoks[1][0]))
01886 {
01887 s4data.sp_period = atoi(stoks[1]);
01888 }
01889 else {
01890 LogMessage("WARNING %s(%d) => Bad sp_period in config file, "
01891 "defaulting to %d seconds\n", file_name, file_line,
01892 SELF_PRES_PERIOD);
01893
01894 s4data.sp_period = SELF_PRES_PERIOD;
01895 }
01896 }
01897 else if(!strcasecmp(stoks[0], "suspend_threshold"))
01898 {
01899 if(isdigit((int)stoks[1][0]))
01900 {
01901 s4data.suspend_threshold = atoi(stoks[1]);
01902 }
01903 else
01904 {
01905 LogMessage("WARNING %s(%d) => Bad suspend_threshold in config "
01906 "file, defaulting to %d new sessions/second\n",
01907 file_name, file_line, SUSPEND_THRESHOLD);
01908
01909 s4data.suspend_threshold = SUSPEND_THRESHOLD;
01910 }
01911 }
01912 else if(!strcasecmp(stoks[0], "suspend_period"))
01913 {
01914 if(isdigit((int)stoks[1][0]))
01915 {
01916 s4data.suspend_period = atoi(stoks[1]);
01917 }
01918 else
01919 {
01920 LogMessage("WARNING %s(%d) => Bad suspend_period in config file, "
01921 "defaulting to %d seconds\n", file_name, file_line,
01922 SUSPEND_PERIOD);
01923
01924 s4data.suspend_period = SUSPEND_PERIOD;
01925 }
01926 }
01927 else if(!strcasecmp(stoks[0], "enforce_state"))
01928 {
01929 s4data.enforce_state = 1;
01930 }
01931 else if(!strcasecmp(stoks[0], "midstream_drop_alerts"))
01932 {
01933 s4data.ms_inline_alerts = 1;
01934 }
01935 else if(!strcasecmp(stoks[0], "state_protection"))
01936 {
01937 s4data.state_protection = 1;
01938 }
01939 else if(!strcasecmp(stoks[0], "server_inspect_limit"))
01940 {
01941 if(isdigit((int)stoks[1][0]))
01942 {
01943 s4data.server_inspect_limit = atoi(stoks[1]);
01944 }
01945 else
01946 {
01947 FatalError("WARNING %s(%d) => Bad server_inspect_limit in "
01948 "config file\n", file_name, file_line);
01949 }
01950 }
01951 #ifdef GIDS
01952 else if(!strcasecmp(stoks[0], "stream4inline"))
01953 {
01954 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "stream4inline mode enabled\n"););
01955 s4data.stream4inline_mode = 1;
01956 LogMessage("stream4inline mode enabled\n");
01957 }
01958 else if(!strcasecmp(stoks[0], "truncate"))
01959 {
01960 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "truncating mode enabled\n"););
01961 s4data.truncate = 1;
01962 LogMessage("truncating mode enabled\n");
01963 }
01964 else if(!strcasecmp(stoks[0], "window_size"))
01965 {
01966 if(isdigit((int)stoks[1][0]))
01967 {
01968 s4data.stream4inline_window_size = atoi(stoks[1]);
01969 }
01970 else
01971 {
01972 LogMessage("WARNING %s(%d) => Bad window size in config file, "
01973 "defaulting to %d bytes\n", file_name, file_line,
01974 STREAM4INLINE_WINDOW_SIZE);
01975 }
01976 }
01977 else if(!strcasecmp(stoks[0], "truncate_percentage"))
01978 {
01979 if(isdigit((int)stoks[1][0]))
01980 {
01981 s4data.truncate_cut_off_perc = atoi(stoks[1]);
01982 if(s4data.truncate_cut_off_perc == 0)
01983 {
01984 s4data.truncate_cut_off_perc = STREAM4INLINE_CUT_OFF_PERC;
01985 }
01986 else if(s4data.truncate_cut_off_perc > 100)
01987 {
01988 s4data.truncate_cut_off_perc = 100;
01989 }
01990 }
01991 else
01992 {
01993 LogMessage("WARNING %s(%d) => Bad cut-off percentage in config file, "
01994 "defaulting to %d precent\n", file_name, file_line,
01995 STREAM4INLINE_CUT_OFF_PERC);
01996 }
01997 }
01998 else if(!strcasecmp(stoks[0], "drop_out_of_window"))
01999 {
02000 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "drop_out_of_window mode enabled\n"););
02001 s4data.drop_out_of_window = 1;
02002 LogMessage("drop_out_of_window mode enabled\n");
02003 }
02004 else if(!strcasecmp(stoks[0], "drop_data_on_unest"))
02005 {
02006 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "drop_data_on_unest mode enabled\n"););
02007 s4data.drop_data_on_unest = 1;
02008 LogMessage("drop_data_on_unest mode enabled\n");
02009 }
02010 else if(!strcasecmp(stoks[0], "drop_no_tcp_on_est"))
02011 {
02012 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "drop_no_tcp_on_est mode enabled\n"););
02013 s4data.drop_no_tcp_on_est = 1;
02014 LogMessage("drop_no_tcp_on_est mode enabled\n");
02015 }
02016 else if(!strcasecmp(stoks[0], "drop_not_in_limits"))
02017 {
02018 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "drop_no_in_limits mode enabled\n"););
02019 s4data.drop_not_in_limits = 1;
02020 LogMessage("drop_not_in_limits mode enabled\n");
02021 }
02022 else if(!strcasecmp(stoks[0], "drop_ttl_evasion"))
02023 {
02024 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "drop_ttl_evasion mode enabled\n"););
02025 s4data.drop_ttl_evasion = 1;
02026 LogMessage("drop_ttl_evasion mode enabled\n");
02027 }
02028 else if(!strncasecmp(index, "state_file", 10))
02029 {
02030 s4data.store_state_to_disk = 1;
02031
02032
02033 statefiletoks = mSplit(index, " ", 1, &num_statefiletoks, 0);
02034
02035
02036 if(strlcpy(s4data.state_file, statefiletoks[1], sizeof(s4data.state_file)) >= sizeof(s4data.state_file))
02037 {
02038 FatalError("The state_file location supplied in the config is too long\n");
02039 }
02040 mSplitFree(&statefiletoks, num_statefiletoks);
02041 }
02042 #endif
02043 else
02044 {
02045 FatalError("%s(%d) => Unknown stream4: option: %s\n",
02046 file_name, file_line, stoks[0]);
02047 }
02048
02049 mSplitFree(&stoks, s_toks);
02050
02051 i++;
02052 }
02053
02054 mSplitFree(&toks, num_toks);
02055
02056 DisplayStream4Config();
02057 }
02058
02059
02060 void Stream4InitReassembler(u_char *args)
02061 {
02062 char buf[STD_BUF+1];
02063 char **toks;
02064 char **stoks;
02065 int num_toks = 0;
02066 int num_args;
02067 int i;
02068 int j = 0;
02069 char *index;
02070 char *value;
02071
02072 if(s4data.stream4_active == 0)
02073 {
02074 FatalError("Please activate stream4 before trying to "
02075 "activate stream4_reassemble\n");
02076 }
02077
02078 s4data.reassembly_alerts = 1;
02079 s4data.reassemble_client = 1;
02080 s4data.reassemble_server = 0;
02081 s4data.flush_on_alert = 0;
02082 s4data.assemble_ports[21] = 1;
02083 s4data.assemble_ports[23] = 1;
02084 s4data.assemble_ports[25] = 1;
02085 s4data.assemble_ports[42] = 1;
02086 s4data.assemble_ports[53] = 1;
02087 s4data.assemble_ports[80] = 1;
02088 s4data.assemble_ports[110] = 1;
02089 s4data.assemble_ports[111] = 1;
02090 s4data.assemble_ports[135] = 1;
02091 s4data.assemble_ports[136] = 1;
02092 s4data.assemble_ports[137] = 1;
02093 s4data.assemble_ports[139] = 1;
02094 s4data.assemble_ports[143] = 1;
02095 s4data.assemble_ports[445] = 1;
02096 s4data.assemble_ports[513] = 1;
02097 s4data.assemble_ports[1433] = 1;
02098 s4data.assemble_ports[1521] = 1;
02099 s4data.assemble_ports[3306] = 1;
02100 s4data.reassy_method = METHOD_FAVOR_OLD;
02101
02102
02103 s4data.emergency_ports[21] = 1;
02104 s4data.emergency_ports[23] = 1;
02105 s4data.emergency_ports[25] = 1;
02106 s4data.emergency_ports[42] = 1;
02107 s4data.emergency_ports[53] = 1;
02108 s4data.emergency_ports[80] = 1;
02109 s4data.emergency_ports[110] = 1;
02110 s4data.emergency_ports[111] = 1;
02111 s4data.emergency_ports[135] = 1;
02112 s4data.emergency_ports[136] = 1;
02113 s4data.emergency_ports[137] = 1;
02114 s4data.emergency_ports[139] = 1;
02115 s4data.emergency_ports[143] = 1;
02116 s4data.emergency_ports[445] = 1;
02117 s4data.emergency_ports[513] = 1;
02118 s4data.emergency_ports[1433] = 1;
02119 s4data.emergency_ports[1521] = 1;
02120 s4data.emergency_ports[3306] = 1;
02121
02122 if (args != NULL)
02123 {
02124 toks = mSplit(args, ",", 12, &num_toks, 0);
02125 }
02126
02127 i=0;
02128
02129 while(i < num_toks)
02130 {
02131 index = toks[i];
02132 while(isspace((int)*index)) index++;
02133
02134 if(!strncasecmp(index, "clientonly", 10))
02135 {
02136 s4data.reassemble_client = 1;
02137 s4data.reassemble_server = 0;
02138 }
02139 else if(!strncasecmp(index, "serveronly", 10))
02140 {
02141 s4data.reassemble_server = 1;
02142 s4data.reassemble_client = 0;
02143 }
02144 else if(!strncasecmp(index, "both", 4))
02145 {
02146 s4data.reassemble_client = 1;
02147 s4data.reassemble_server = 1;
02148 }
02149 else if(!strncasecmp(index, "noalerts", 8))
02150 {
02151 s4data.reassembly_alerts = 0;
02152 }
02153 else if(!strncasecmp(index, "favor_old", 9))
02154 {
02155 s4data.reassy_method = METHOD_FAVOR_OLD;
02156 }
02157 else if(!strncasecmp(index, "favor_new", 9))
02158 {
02159 s4data.reassy_method = METHOD_FAVOR_NEW;
02160 }
02161 else if(!strncasecmp(index, "flush_on_alert", 9))
02162 {
02163 s4data.flush_on_alert = 1;
02164 }
02165 else if(!strncasecmp(index, "overlap_limit", 9))
02166 {
02167 stoks = mSplit(index, " ", 2, &num_args, 0);
02168 value = stoks[1];
02169 if((num_args == 2) && (isdigit((int)value[0])))
02170 {
02171 s4data.overlap_limit = atoi(value);
02172 }
02173 else
02174 {
02175 FatalError("%s(%d) => Bad overlap_limit value in "
02176 "config file\n", file_name, file_line);
02177 }
02178 mSplitFree(&stoks, num_args);
02179 }
02180 else if(!strncasecmp(index, "flush_behavior", 14))
02181 {
02182 stoks = mSplit(index, " ", 2, &num_args, 0);
02183 value = stoks[1];
02184 if(num_args != 2)
02185 {
02186 FatalError("%s(%d) => Bad flush_behavior value in "
02187 "config file\n", file_name, file_line);
02188 }
02189 if (!strncasecmp(value, "default", 7))
02190 {
02191 s4data.flush_behavior = FLUSH_BEHAVIOR_DEFAULT;
02192 }
02193 else if (!strncasecmp(value, "random", 6))
02194 {
02195 s4data.flush_behavior = FLUSH_BEHAVIOR_RANDOM;
02196 }
02197 else if (!strncasecmp(value, "large_window", 12))
02198 {
02199 s4data.flush_behavior = FLUSH_BEHAVIOR_LARGE;
02200 }
02201 else
02202 {
02203 FatalError("%s(%d) => Invalid flush_behavior value (%s) in "
02204 "config file\n", file_name, file_line, value);
02205 }
02206
02207 mSplitFree(&stoks, num_args);
02208 }
02209 else if(!strncasecmp(index, "flush_seed", 10))
02210 {
02211 stoks = mSplit(index, " ", 2, &num_args, 0);
02212 value = stoks[1];
02213 if((num_args == 2) && (isdigit((int)value[0])))
02214 {
02215 s4data.flush_seed = atoi(value) + time(NULL);
02216 }
02217 else
02218 {
02219 FatalError("%s(%d) => Unsupported flush_seed value in "
02220 "config file\n", file_name, file_line);
02221 }
02222 mSplitFree(&stoks, num_args);
02223 }
02224 else if(!strncasecmp(index, "flush_base", 10))
02225 {
02226 stoks = mSplit(index, " ", 2, &num_args, 0);
02227 value = stoks[1];
02228 if((num_args == 2) && (isdigit((int)value[0])))
02229 {
02230 s4data.flush_base = atoi(value);
02231 }
02232 else
02233 {
02234 FatalError("%s(%d) => Bad flush_base value in "
02235 "config file\n", file_name, file_line);
02236 }
02237 mSplitFree(&stoks, num_args);
02238
02239 if((s4data.flush_base < 1) || (s4data.flush_base > 32768))
02240 {
02241 FatalError("%s(%d) => Unsupported flush_base value (%d bytes) in "
02242 "config file\n",
02243 file_name, file_line, s4data.flush_base);
02244 }
02245 }
02246 else if(!strncasecmp(index, "flush_range", 11))
02247 {
02248 stoks = mSplit(index, " ", 2, &num_args, 0);
02249 value = stoks[1];
02250 if((num_args == 2) && (isdigit((int)value[0])))
02251 {
02252 s4data.flush_range = atoi(value);
02253 }
02254 else
02255 {
02256 FatalError("%s(%d) => Bad flush_range in config file\n",
02257 file_name, file_line);
02258 }
02259 mSplitFree(&stoks, num_args);
02260
02261 if((s4data.flush_range < 512) || (s4data.flush_range > 32767))
02262 {
02263 FatalError("%s(%d) => Unsupported flush_range value "
02264 "(%d bytes) in config file\n",
02265 file_name, file_line, s4data.flush_range);
02266 }
02267 }
02268 else if(!strncasecmp(index, "ports", 5))
02269 {
02270 char **ports;
02271 int num_ports;
02272 char *port;
02273 int j = 0;
02274 u_int32_t portnum;
02275
02276 for(j = 0;j<65535;j++)
02277 {
02278 s4data.assemble_ports[j] = 0;
02279 }
02280
02281 ports = mSplit(index, " ", 40, &num_ports, 0);
02282
02283 j = 1;
02284
02285 while(j < num_ports)
02286 {
02287 port = ports[j];
02288
02289 if(isdigit((int)port[0]))
02290 {
02291 portnum = atoi(port);
02292
02293 if(portnum > 65535)
02294 {
02295 FatalError("%s(%d) => Bad port list to "
02296 "reassembler\n", file_name, file_line);
02297 }
02298
02299 s4data.assemble_ports[portnum] = 1;
02300 }
02301 else if(!strncasecmp(port, "all", 3))
02302 {
02303 memset(&s4data.assemble_ports, 1, 65536);
02304 }
02305 else if(!strncasecmp(port, "default", 7))
02306 {
02307 s4data.assemble_ports[21] = 1;
02308 s4data.assemble_ports[23] = 1;
02309 s4data.assemble_ports[25] = 1;
02310 s4data.assemble_ports[42] = 1;
02311 s4data.assemble_ports[53] = 1;
02312 s4data.assemble_ports[80] = 1;
02313 s4data.assemble_ports[110] = 1;
02314 s4data.assemble_ports[111] = 1;
02315 s4data.assemble_ports[135] = 1;
02316 s4data.assemble_ports[136] = 1;
02317 s4data.assemble_ports[137] = 1;
02318 s4data.assemble_ports[139] = 1;
02319 s4data.assemble_ports[143] = 1;
02320 s4data.assemble_ports[445] = 1;
02321 s4data.assemble_ports[513] = 1;
02322 s4data.assemble_ports[1433] = 1;
02323 s4data.assemble_ports[1521] = 1;
02324 s4data.assemble_ports[3306] = 1;
02325 }
02326
02327 j++;
02328 }
02329
02330 mSplitFree(&ports, num_ports);
02331 }
02332 else if(!strncasecmp(index, "emergency_ports", 15))
02333 {
02334 char **ports;
02335 int num_ports;
02336 char *port;
02337 int j = 0;
02338 u_int32_t portnum;
02339
02340 for(j = 0;j<65535;j++)
02341 {
02342 s4data.emergency_ports[j] = 0;
02343 }
02344
02345 ports = mSplit(args, " ", 40, &num_ports, 0);
02346
02347 j = 0;
02348
02349 while(j < num_ports)
02350 {
02351 port = ports[j];
02352
02353 if(isdigit((int)port[0]))
02354 {
02355 portnum = atoi(port);
02356
02357 if(portnum > 65535)
02358 {
02359 FatalError("%s(%d) => Bad port list to "
02360 "reassembler\n", file_name, file_line);
02361 }
02362
02363 s4data.emergency_ports[portnum] = 1;
02364 }
02365 else if(!strncasecmp(port, "all", 3))
02366 {
02367 memset(&s4data.emergency_ports, 1, 65536);
02368 }
02369 else if(!strncasecmp(port, "default", 7))
02370 {
02371 s4data.emergency_ports[21] = 1;
02372 s4data.emergency_ports[23] = 1;
02373 s4data.emergency_ports[25] = 1;
02374 s4data.emergency_ports[42] = 1;
02375 s4data.emergency_ports[53] = 1;
02376 s4data.emergency_ports[80] = 1;
02377 s4data.emergency_ports[110] = 1;
02378 s4data.emergency_ports[111] = 1;
02379 s4data.emergency_ports[135] = 1;
02380 s4data.emergency_ports[136] = 1;
02381 s4data.emergency_ports[137] = 1;
02382 s4data.emergency_ports[139] = 1;
02383 s4data.emergency_ports[143] = 1;
02384 s4data.emergency_ports[445] = 1;
02385 s4data.emergency_ports[513] = 1;
02386 s4data.emergency_ports[1433] = 1;
02387 s4data.emergency_ports[1521] = 1;
02388 s4data.emergency_ports[3306] = 1;
02389 }
02390
02391 j++;
02392 }
02393
02394 mSplitFree(&ports, num_ports);
02395 }
02396 else if(!strcasecmp(index, "zero_flushed_packets"))
02397 {
02398 s4data.zero_flushed_packets = 1;
02399 }
02400 else if(!strncasecmp(index, "flush_data_diff_size",
02401 strlen("flush_data_diff_size")))
02402 {
02403
02404 char *number_str;
02405 number_str = strrchr(index,' ');
02406
02407 if(number_str && *number_str != '\0')
02408 {
02409 number_str++;
02410 }
02411
02412 if(number_str && *number_str != '\0' && (isdigit((int)*number_str)))
02413 {
02414 s4data.flush_data_diff_size = atoi(number_str);
02415
02416 if(s4data.flush_data_diff_size < 0)
02417 {
02418 FatalError("%s(%d) => Bad flush_data_diff_size in "
02419 "config file\n", file_name, file_line);
02420 }
02421 }
02422 else
02423 {
02424 FatalError("%s(%d) => Bad flush_data_diff_size in config file\n",
02425 file_name, file_line);
02426 }
02427 }
02428 else
02429 {
02430 FatalError("%s(%d) => Bad stream4_reassemble option "
02431 "specified: \"%s\"\n", file_name, file_line, toks[i]);
02432 }
02433
02434 i++;
02435 }
02436
02437 if (num_toks)
02438 mSplitFree(&toks, num_toks);
02439
02440
02441 if ( s4data.flush_behavior == FLUSH_BEHAVIOR_LARGE )
02442 {
02443
02444 int elm;
02445 for( elm = 0; elm < FCOUNT; elm += 1 )
02446 {
02447 flush_points[elm] = new_flush_points[elm];
02448 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Setting new static "
02449 "flush value of (%d bytes) at index %d\n",
02450 flush_points[elm],elm););
02451
02452 }
02453 LogMessage("WARNING %s(%d) => flush_behavior set in "
02454 "config file, using new static flushpoints (%d)\n",
02455 file_name, file_line, s4data.flush_behavior);
02456
02457 }
02458 else if ( s4data.flush_behavior == FLUSH_BEHAVIOR_RANDOM )
02459 {
02460
02461 int elm;
02462 int rfp;
02463 srand(s4data.flush_seed);
02464 for( elm = 0; elm < FCOUNT; elm += 1 )
02465 {
02466 rfp = rand() % s4data.flush_range;
02467 flush_points[elm] = rfp + s4data.flush_base;
02468 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Setting random "
02469 "flush value of (%d bytes) at index %d\n",
02470 flush_points[elm],elm););
02471 }
02472 }
02473 else
02474 {
02475
02476 int elm;
02477 for( elm = 0; elm < FCOUNT; elm += 1 )
02478 {
02479 flush_points[elm] = old_flush_points[elm];
02480 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Setting old static "
02481 "flush value of %d bytes) at index %d\n",
02482 flush_points[elm],elm););
02483 }
02484 LogMessage("WARNING %s(%d) => flush_behavior set in "
02485 "config file, using old static flushpoints (%d)\n",
02486 file_name, file_line, s4data.flush_behavior);
02487 }
02488
02489
02490
02491 if(s4data.store_state_to_disk == 1)
02492 {
02493 struct timeval t;
02494 memset(&t, 0, sizeof(struct timeval));
02495 gettimeofday(&t, NULL);
02496
02497 LoadStateTable(t.tv_sec,s4data.state_file);
02498 }
02499
02500
02501 LogMessage("Stream4_reassemble config:\n");
02502 LogMessage(" Server reassembly: %s\n",
02503 s4data.reassemble_server ? "ACTIVE": "INACTIVE");
02504 LogMessage(" Client reassembly: %s\n",
02505 s4data.reassemble_client ? "ACTIVE": "INACTIVE");
02506 LogMessage(" Reassembler alerts: %s\n",
02507 s4data.reassembly_alerts ? "ACTIVE": "INACTIVE");
02508 LogMessage(" Zero out flushed packets: %s\n",
02509 s4data.zero_flushed_packets ? "ACTIVE": "INACTIVE");
02510 LogMessage(" Flush stream on alert: %s\n",
02511 s4data.flush_on_alert ? "ACTIVE": "INACTIVE");
02512 LogMessage(" flush_data_diff_size: %d\n",
02513 s4data.flush_data_diff_size);
02514 LogMessage(" Reassembler Packet Preferance : %s\n",
02515 s4data.reassy_method == METHOD_FAVOR_NEW ?
02516 "Favor New" : "Favor Old");
02517 LogMessage(" Packet Sequence Overlap Limit: %d\n",
02518 s4data.overlap_limit);
02519 LogMessage(" Flush behavior: %s\n",
02520 s4data.flush_behavior == FLUSH_BEHAVIOR_DEFAULT ? "Small (<255 bytes)":
02521 (s4data.flush_behavior == FLUSH_BEHAVIOR_LARGE ? "Large (<2550 bytes)" :
02522 "random"));
02523 if (s4data.flush_behavior == FLUSH_BEHAVIOR_RANDOM)
02524 {
02525 LogMessage(" Flush base: %d\n", s4data.flush_base);
02526 LogMessage(" Flush seed: %d\n", s4data.flush_seed);
02527 LogMessage(" Flush range: %d\n", s4data.flush_range);
02528 }
02529
02530 memset(buf, 0, STD_BUF+1);
02531 snprintf(buf, STD_BUF, " Ports: ");
02532
02533 for(i=0;i<65536;i++)
02534 {
02535 if(s4data.assemble_ports[i])
02536 {
02537 sfsnprintfappend(buf, STD_BUF, "%d ", i);
02538 j++;
02539 }
02540
02541 if(j > 20)
02542 {
02543 LogMessage("%s...\n", buf);
02544 return;
02545 }
02546 }
02547
02548 LogMessage("%s\n", buf);
02549 memset(buf, 0, STD_BUF+1);
02550 snprintf(buf, STD_BUF, " Emergency Ports: ");
02551 j=0;
02552
02553 for(i=0;i<65536;i++)
02554 {
02555 if(s4data.emergency_ports[i])
02556 {
02557 sfsnprintfappend(buf, STD_BUF, "%d ", i);
02558 j++;
02559 }
02560
02561 if(j > 20)
02562 {
02563 LogMessage("%s...\n", buf);
02564 return;
02565 }
02566 }
02567
02568 LogMessage("%s\n", buf);
02569
02570 return;
02571 }
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584 static INLINE int SetFinSent(Packet *p, Session *ssn, int direction)
02585 {
02586 Stream *stream;
02587
02588 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "SetFinSet() called for %s\n",
02589 direction ? "FROM_CLIENT":"FROM_SERVER"););
02590
02591 if(direction == FROM_SERVER)
02592 {
02593 stream = &ssn->server;
02594 ssn->session_flags |= SSNFLAG_SERVER_FIN;
02595 }
02596 else
02597 {
02598 stream = &ssn->client;
02599 ssn->session_flags |= SSNFLAG_CLIENT_FIN;
02600 }
02601
02602 stream->next_seq = ntohl(p->tcph->th_seq);
02603
02604 return 0;
02605 }
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616 static INLINE int NotForStream4(Packet *p)
02617 {
02618 if(!(p->preprocessors & PP_STREAM4))
02619 {
02620 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
02621 "p->preprocessors does not have STREAM4\n"););
02622 return 1;
02623 }
02624
02625 if(p->tcph == NULL)
02626 {
02627 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "p->tcph is null, returning\n"););
02628 return 1;
02629 }
02630
02631 if(p->packet_flags & PKT_REBUILT_STREAM)
02632 {
02633 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REBUILT_STREAM returning\n"););
02634 return 1;
02635 }
02636
02637 if(s4_emergency.status != OPS_NORMAL)
02638 {
02639
02640
02641
02642
02643 if(p->pkth->ts.tv_sec >= s4_emergency.end_time)
02644 {
02645 s4_emergency.status = OPS_NORMAL;
02646 s4_emergency.end_time = 0;
02647 s4_emergency.new_session_count = 0;
02648 s4data.reassembly_alerts = s4_emergency.old_reassembly_alerts;
02649 s4data.reassemble_client = s4_emergency.old_reassemble_client;
02650 s4data.reassemble_server = s4_emergency.old_reassemble_server;
02651 pv.assurance_mode = s4_emergency.old_assurance_mode;
02652 pv.stateful = s4_emergency.old_stateful_mode;
02653 }
02654
02655 if(s4_emergency.status == OPS_SUSPEND)
02656 {
02657 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "OPS_SUSPEND returning\n"););
02658 return 1;
02659 }
02660 }
02661
02662
02663 if(p->csum_flags & CSE_IP || p->csum_flags & CSE_TCP)
02664 {
02665 DEBUG_WRAP(
02666 u_int8_t c1 = (p->csum_flags & CSE_IP);
02667 u_int8_t c2 = (p->csum_flags & CSE_TCP);
02668 DebugMessage(DEBUG_STREAM, "IP CHKSUM: %d, CSE_TCP: %d",
02669 c1,c2);
02670 DebugMessage(DEBUG_STREAM, "Bad checksum returning\n");
02671 );
02672
02673 p->packet_flags |= PKT_STREAM_UNEST_UNI;
02674 return 1;
02675 }
02676
02677 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Packet is for stream4...\n"););
02678 return 0;
02679 }
02680
02681
02682
02683
02684
02685
02686
02687
02688 static INLINE void StreamSegmentSub(Stream *stream, u_int16_t sub)
02689 {
02690
02691 #ifdef _DEBUG_SEGMENTS
02692 DebugMessage(DEBUG_STREAM, "[sss] %u -> %u (mem: %u)\n,",
02693 stream->bytes_tracked,
02694 stream->bytes_tracked - sub,
02695 stream4_memory_usage);
02696 #endif
02697
02698 if((stream->bytes_tracked - sub) > stream->bytes_tracked)
02699 {
02700 stream->bytes_tracked = 0;
02701 }
02702 else
02703 {
02704 stream->bytes_tracked -= sub;
02705 }
02706
02707 }
02708
02709
02710
02711
02712
02713
02714
02715
02716 static INLINE void StreamSegmentAdd(Stream *stream, u_int16_t add)
02717 {
02718
02719 #ifdef _DEBUG_SEGMENTS
02720 DebugMessage(DEBUG_STREAM, "[ssa] %u -> %u (mem: %u)\n,",
02721 stream->bytes_tracked,
02722 stream->bytes_tracked + add,
02723 stream4_memory_usage);
02724 #endif
02725
02726
02727 if((stream->bytes_tracked + add) < stream->bytes_tracked)
02728 {
02729 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"[E] How'd we get this high?\n"););
02730 return;
02731 }
02732 else
02733 {
02734 stream->bytes_tracked += add;
02735 stream->bytes_sent += add;
02736 stream->pkts_sent++;
02737 }
02738
02739 }
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751 static INLINE int WithinSessionLimits(Packet *p, Stream *stream)
02752 {
02753 u_int32_t limit;
02754
02755 return 1;
02756
02757
02758
02759 if(((Session *)(p->ssnptr))->session_flags & SSNFLAG_MIDSTREAM)
02760 {
02761 limit = 5000;
02762 }
02763 else
02764 {
02765 limit = (MAX_STREAM_SIZE + 5000);
02766 }
02767
02768 if((stream->bytes_tracked + p->dsize) >= limit)
02769 {
02770
02771
02772
02773 StreamSegmentSub(stream, p->dsize);
02774 return 0;
02775 }
02776
02777 return 1;
02778 }
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793 static INLINE void PruneCheck(Packet *p)
02794 {
02795
02796 if (!s4data.last_prune_time)
02797 {
02798 s4data.last_prune_time = p->pkth->ts.tv_sec;
02799 return;
02800 }
02801
02802 if( (u_int)(p->pkth->ts.tv_sec) > s4data.last_prune_time + s4data.timeout)
02803 {
02804 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Prune time quanta exceeded, pruning "
02805 "stream cache\n"););
02806
02807 sfPerf.sfBase.iStreamTimeouts++;
02808
02809 PruneSessionCache(p->pkth->ts.tv_sec, 0, NULL);
02810 s4data.last_prune_time = p->pkth->ts.tv_sec;
02811
02812 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Pruned for timeouts, %lu sessions "
02813 "active, %lu bytes " "in use\n",
02814 (unsigned long int) GetSessionCount(), stream4_memory_usage);
02815 DebugMessage(DEBUG_STREAM, "Stream4 memory cap hit %lu times\n",
02816 safe_alloc_faults););
02817 }
02818
02819 }
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833 void ReassembleStream4(Packet *p, void *context)
02834 {
02835 Session *ssn = NULL;
02836 int action;
02837 int reassemble = 0;
02838 u_int32_t pkt_seq;
02839 u_int32_t pkt_ack;
02840 int direction;
02841 static int alert_once_emerg = 0;
02842 static int alert_once_suspend = 0;
02843 #ifdef GIDS
02844
02845 Stream *s;
02846 int stream_size = 0;
02847 opdsize = 0;
02848 #endif
02849 #ifdef DEBUG
02850 static int pcount = 0;
02851 char flagbuf[9];
02852
02853 pcount++;
02854
02855 DebugMessage(DEBUG_STREAM, "pcount stream packet %d\n",pcount);
02856 #endif
02857
02858 if(NotForStream4(p))
02859 return;
02860
02861 pc.tcp_stream_pkts++;
02862
02863 reassemble = CheckPorts(p->sp, p->dp);
02864
02865
02866 if(s4data.stateful_inspection_flag == 0 && !reassemble)
02867 {
02868 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
02869 "No stateful inspection on this port, returning"););
02870 return;
02871 }
02872
02873 DEBUG_WRAP(
02874 CreateTCPFlagString(p, flagbuf);
02875 DebugMessage((DEBUG_STREAM|DEBUG_STREAM_STATE),
02876 "Got Packet 0x%X:%d(%d) -> 0x%X:%d(%d) %s\nseq: 0x%X ack:0x%X\n",
02877 p->iph->ip_src.s_addr,
02878 p->sp, p->tcph->th_sport,
02879 p->iph->ip_dst.s_addr,
02880 p->dp, p->tcph->th_dport,
02881 flagbuf,
02882 ntohl(p->tcph->th_seq), ntohl(p->tcph->th_ack));
02883 );
02884
02885 pkt_seq = ntohl(p->tcph->th_seq);
02886 pkt_ack = ntohl(p->tcph->th_ack);
02887
02888 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"pkt_seq: %u, pkt_ack: %u\n",
02889 pkt_seq, pkt_ack););
02890
02891
02892 ssn = GetSession(p);
02893 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"ssn == %p\n", ssn);
02894 DumpStateTable(NULL););
02895
02896
02897
02898
02899
02900
02901 if(!ssn && s4data.enforce_state)
02902 {
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913 if(!InlineMode())
02914 {
02915 if((p->tcph->th_flags & (TH_SYN|TH_RST)) != TH_SYN)
02916 {
02917 do_detect = 0;
02918 p->preprocessors = 0;
02919
02920 return;
02921 }
02922 }
02923 else
02924 {
02925
02926
02927
02928 if((p->tcph->th_flags & (TH_SYN|TH_ACK|TH_PUSH|TH_FIN|TH_RST))
02929 != TH_SYN)
02930 {
02931 do_detect = 0;
02932 p->preprocessors = 0;
02933
02934 InlineDrop();
02935
02936 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
02937 "Lets drop this its not a synner\n"););
02938
02939 return;
02940 }
02941 }
02942 }
02943
02944 if(ssn == NULL)
02945 {
02946 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Calling CreateNewSession()\n"););
02947
02948 p->packet_flags |= PKT_FROM_CLIENT;
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958 if((s4_emergency.status == OPS_NORMAL) ||
02959 ((p->tcph->th_flags & TH_NORESERVED) == TH_SYN))
02960 {
02961 ssn = CreateNewSession(p, pkt_seq, pkt_ack);
02962
02963 if(ssn != NULL && ((p->tcph->th_flags & TH_NORESERVED) != TH_SYN))
02964 {
02965 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
02966 "Picking up session midstream\n"););
02967
02968 ssn->session_flags |= SSNFLAG_MIDSTREAM;
02969 }
02970
02971
02972
02973
02974
02975
02976
02977 if(s4data.state_protection)
02978 ++s4_emergency.new_session_count;
02979
02980
02981 if(ssn != NULL)
02982 {
02983 AddStreamSession(&sfPerf.sfBase);
02984 }
02985 }
02986 else
02987 {
02988 ssn = NULL;
02989 }
02990
02991 if(s4data.state_protection)
02992 {
02993 if(s4_emergency.new_session_count >= s4data.suspend_threshold)
02994 {
02995 s4_emergency.status = OPS_SUSPEND;
02996 s4_emergency.end_time = p->pkth->ts.tv_sec + s4data.suspend_period;
02997 pv.assurance_mode = ASSURE_ALL;
02998 pv.stateful = 0;
02999
03000 if(alert_once_suspend == 0)
03001 {
03002 SnortEventqAdd(GENERATOR_SPP_STREAM4,
03003 STREAM4_SUSPEND,
03004 1,
03005 0,
03006 3,
03007 STREAM4_SUSPEND_STR,
03008 0);
03009
03010 alert_once_suspend = 1;
03011 }
03012 }
03013 else if(s4_emergency.new_session_count >= s4data.sp_threshold)
03014 {
03015 s4_emergency.status = OPS_SELF_PRESERVATION;
03016 s4_emergency.end_time = p->pkth->ts.tv_sec + s4data.sp_period;
03017 s4_emergency.old_reassembly_alerts = s4data.reassembly_alerts;
03018 s4_emergency.old_reassemble_client = s4data.reassemble_client;
03019 s4_emergency.old_reassemble_server = s4data.reassemble_server;
03020 s4_emergency.old_assurance_mode = pv.assurance_mode;
03021 s4_emergency.old_stateful_mode = pv.stateful;
03022
03023 if(alert_once_emerg == 0)
03024 {
03025 SnortEventqAdd(GENERATOR_SPP_STREAM4,
03026 STREAM4_EMERGENCY,
03027 1,
03028 0,
03029 3,
03030 STREAM4_EMERGENCY_STR,
03031 0);
03032
03033 alert_once_emerg = 1;
03034 }
03035 }
03036 }
03037
03038 p->packet_flags = PKT_STREAM_UNEST_UNI;
03039
03040 if(ssn == NULL)
03041 {
03042 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"NULL SSN, maybe in emergency in "
03043 "CreateNewSession, returning\n"););
03044
03045
03046
03047
03048
03049
03050
03051
03052 if(s4_emergency.status != OPS_NORMAL)
03053 {
03054 DisableDetect(p);
03055 }
03056
03057 return;
03058 }
03059 }
03060 else
03061 {
03062 if(p->dsize != 0 && s4_emergency.status == OPS_NORMAL)
03063 s4_emergency.new_session_count = 0;
03064 }
03065
03066
03067 p->ssnptr = ssn;
03068
03069 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03070 "[i] Tracked Bytes: (client: %d, server: %d)\n",
03071 ssn->client.bytes_tracked,
03072 ssn->server.bytes_tracked););
03073
03074
03075 if((direction = GetDirection(ssn, p)) == FROM_SERVER)
03076 {
03077 p->packet_flags |= PKT_FROM_SERVER;
03078 ssn->client.win_size = ntohs(p->tcph->th_win);
03079 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "server packet: %s\n", flagbuf););
03080 }
03081 else
03082 {
03083 p->packet_flags |= PKT_FROM_CLIENT;
03084 ssn->server.win_size = ntohs(p->tcph->th_win);
03085 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "client packet: %s\n", flagbuf););
03086 }
03087
03088 if (p->dsize > 0)
03089 {
03090 if ((p->packet_flags & PKT_FROM_SERVER) &&
03091 (s4data.server_inspect_limit > 0))
03092 {
03093
03094
03095
03096
03097
03098 if (ssn->server.bytes_inspected > s4data.server_inspect_limit)
03099 {
03100 p->bytes_to_inspect = -1;
03101 }
03102 else
03103 {
03104 if (p->dsize + ssn->server.bytes_inspected >
03105 s4data.server_inspect_limit)
03106 {
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117 p->bytes_to_inspect = s4data.server_inspect_limit -
03118 ssn->server.bytes_inspected;
03119 }
03120 }
03121 ssn->server.bytes_inspected += p->dsize;
03122 }
03123 else
03124 {
03125 ssn->server.bytes_inspected = 0;
03126 }
03127 }
03128
03129
03130 ssn->last_session_time = p->pkth->ts.tv_sec;
03131
03132
03133 if(s4data.asynchronous_link)
03134 {
03135 action = UpdateStateAsync(ssn, p, pkt_seq);
03136 }
03137 else
03138 {
03139 action = UpdateState2(ssn, p, pkt_seq);
03140 }
03141
03142 packet_added_to_stream = 0;
03143
03144
03145 if(p->dsize && reassemble)
03146 {
03147 #ifdef GIDS
03148 if(!s4data.stream4inline_mode)
03149 {
03150 #endif
03151
03152 StoreStreamPkt(ssn, p, pkt_seq);
03153 #ifdef GIDS
03154 }
03155 else
03156 {
03157
03158 if(direction == FROM_SERVER)
03159 s = &ssn->server;
03160 else
03161 s = &ssn->client;
03162
03163 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
03164 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Going to try to store packet size %d, count: %lu...\n", p->dsize, ubi_trCount(&s->data)););
03165
03166
03167
03168
03169
03170
03171
03172
03173 if(!(StoreStreamPkt(ssn, p, pkt_seq)))
03174 {
03175 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
03176 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"WARNING: the storing failed: count: %lu, s->bytes_tracked: %u, going to sub...\n", ubi_trCount(&s->data), s->bytes_tracked););
03177
03178
03179
03180 if(direction == FROM_SERVER)
03181 StreamSegmentSub(&ssn->server, p->dsize);
03182 else
03183 StreamSegmentSub(&ssn->client, p->dsize);
03184
03185 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
03186 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"WARNING: the storing failed: after sub: s->bytes_tracked: %u...\n", s->bytes_tracked););
03187 }
03188 }
03189 #endif
03190 }
03191 else
03192 {
03193
03194
03195 if(direction == FROM_SERVER)
03196 StreamSegmentSub(&ssn->server, p->dsize);
03197 else
03198 StreamSegmentSub(&ssn->client, p->dsize);
03199 }
03200
03201 if ((s4data.overlap_limit > 0) &&
03202 (ssn->client.overlap_pkts > s4data.overlap_limit))
03203 {
03204
03205
03206 action |= ACTION_FLUSH_CLIENT_STREAM;
03207
03208 if(s4data.evasion_alerts)
03209 {
03210 SnortEventqAdd(GENERATOR_SPP_STREAM4,
03211 STREAM4_OVERLAP_LIMIT,
03212 1,
03213 0,
03214 3,
03215 STREAM4_OVERLAP_LIMIT_STR,
03216 0);
03217 }
03218 }
03219
03220 if ((s4data.overlap_limit > 0) &&
03221 (ssn->server.overlap_pkts > s4data.overlap_limit))
03222 {
03223
03224
03225 action |= ACTION_FLUSH_SERVER_STREAM;
03226
03227 if(s4data.evasion_alerts)
03228 {
03229 SnortEventqAdd(GENERATOR_SPP_STREAM4,
03230 STREAM4_OVERLAP_LIMIT,
03231 1,
03232 0,
03233 3,
03234 STREAM4_OVERLAP_LIMIT_STR,
03235 0);
03236 }
03237 }
03238
03239
03240
03241
03242
03243 if(s4data.asynchronous_link)
03244 {
03245 TcpActionAsync(ssn, p, action, direction, pkt_seq, pkt_ack);
03246 }
03247 else
03248 {
03249 TcpAction(ssn, p, action, direction, pkt_seq, pkt_ack);
03250 }
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261 if(p->ssnptr == ssn)
03262 {
03263
03264 if(((s4data.asynchronous_link == 0) &&
03265 (((ssn->session_flags & (SSNFLAG_SEEN_SERVER|SSNFLAG_SEEN_CLIENT))
03266 == (SSNFLAG_SEEN_SERVER|SSNFLAG_SEEN_CLIENT)) &&
03267 (ssn->server.state >= ESTABLISHED) &&
03268 (ssn->client.state >= ESTABLISHED))) ||
03269 ((s4data.asynchronous_link == 1) &&
03270 ((((ssn->session_flags & SSNFLAG_SEEN_CLIENT)) &&
03271 (ssn->client.state >= ESTABLISHED)) ||
03272 (((ssn->session_flags & SSNFLAG_SEEN_SERVER)) &&
03273 (ssn->server.state >= ESTABLISHED)))))
03274 {
03275 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03276 "Stream is established!,ssnflags = 0x%x\n",
03277 ssn->session_flags););
03278
03279 ssn->session_flags |= SSNFLAG_ESTABLISHED;
03280 }
03281 else
03282 {
03283 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Stream is not established!\n"););
03284
03285 if((ssn->session_flags & (SSNFLAG_SEEN_SERVER|SSNFLAG_SEEN_CLIENT))
03286 == (SSNFLAG_SEEN_SERVER|SSNFLAG_SEEN_CLIENT))
03287 {
03288
03289
03290
03291
03292
03293 p->packet_flags |= PKT_STREAM_UNEST_BI;
03294 }
03295 else
03296 {
03297
03298
03299
03300
03301 p->packet_flags |= PKT_STREAM_UNEST_UNI;
03302 }
03303 }
03304
03305 if(ssn->session_flags & SSNFLAG_ESTABLISHED)
03306 {
03307
03308
03309
03310 p->packet_flags |= PKT_STREAM_EST;
03311
03312 if(p->packet_flags & PKT_STREAM_UNEST_UNI)
03313 {
03314 p->packet_flags ^= PKT_STREAM_UNEST_UNI;
03315 }
03316
03317 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03318 "Marking stream as established\n"););
03319 #ifdef DEBUG
03320 if(p->packet_flags & PKT_FROM_CLIENT)
03321 {
03322 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03323 "pkt is from client\n"););
03324 }
03325
03326 if(p->packet_flags & PKT_FROM_SERVER)
03327 {
03328 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03329 "pkt is from server\n"););
03330 }
03331 #endif
03332 }
03333 }
03334
03335
03336 PrintSessionCache();
03337
03338
03339 PruneCheck(p);
03340
03341 #ifdef GIDS
03342
03343 if(!s4data.stream4inline_mode)
03344 return;
03345
03346
03347
03348
03349 if(p->dsize == 0)
03350 return;
03351
03352 if(packet_added_to_stream == 0)
03353 {
03354
03355 return;
03356 }
03357
03358
03359
03360 if(direction == FROM_SERVER)
03361 s = &ssn->server;
03362 else
03363 s = &ssn->client;
03364
03365
03366 stream_size = s->bytes_tracked;
03367
03368
03369
03370
03371 if(stream_size > (s4data.stream4inline_window_size * 2) || stream_size > MAX_STREAM_SIZE)
03372 {
03373 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Truncating stream that is out of control...(stream_size %d (max %d or %d)).\n",
03374 stream_size, s4data.stream4inline_window_size * 2, MAX_STREAM_SIZE););
03375 TruncStream(s, p);
03376
03377
03378 stream_size = s->bytes_tracked;
03379 }
03380
03381 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s:\n", p->sp, p->dp, flagbuf););
03382 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"p->dsize: %5d, seq_num: %u stream_size: %d (pkts %u, bytes %u, btracked: %u), stream_size_last_ack: %d, count: %lu\n", p->dsize, p->tcph->th_seq, stream_size, s->pkts_sent, s->bytes_sent, s->bytes_tracked, s->last_ack - s->base_seq + p->dsize, ubi_trCount(&s->data)););
03383
03384
03385
03386 if(stream_size > 0 && ubi_trCount(&s->data))
03387 {
03388
03389 direction = NO_REVERSE;
03390
03391
03392 if(BuildPacket(s, stream_size, p, direction))
03393 {
03394 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
03395 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Passing large packet on 0 size stream cache (after BP)\n"););
03396 }
03397 else
03398 {
03399
03400 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
03401 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"stream_pkt->dsize: %5d, p->dsize: %5d, stream_size: %d (pkts %u, bytes %u, btracked: %u)\n\n", stream_pkt->dsize, p->dsize, stream_size, s->pkts_sent, s->bytes_sent, s->bytes_tracked););
03402
03403
03404
03405 opdsize = p->dsize;
03406 p->data = stream_pkt->data;
03407 p->dsize = stream_pkt->dsize;
03408 p->packet_flags = stream_pkt->packet_flags;
03409 p->streamptr = stream_pkt->streamptr;
03410 }
03411 }
03412 else
03413 {
03414 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
03415 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Passing large packet on 0 size stream cache\n"););
03416 }
03417
03418
03419
03420
03421
03422
03423 #endif
03424
03425 return;
03426 }
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442 void INLINE QueueState(u_int8_t transition, Stream *sptr,
03443 u_int8_t expected_flags, u_int32_t seq_num, u_int8_t chk_seq)
03444 {
03445 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03446 "[^^] Queing transition to %s, flag 0x%X, seq: 0x%X\n",
03447 state_names[transition], expected_flags, seq_num););
03448
03449 sptr->state_queue = transition;
03450 sptr->expected_flags = expected_flags;
03451 sptr->stq_chk_seq = chk_seq;
03452 sptr->trans_seq = seq_num;
03453 return;
03454 }
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465 int INLINE EvalStateQueue(Stream *sptr, u_int8_t flags, u_int32_t ack)
03466 {
03467 if(sptr->expected_flags != 0)
03468 {
03469 if((flags & sptr->expected_flags) != 0)
03470 {
03471 if(sptr->stq_chk_seq && (SEQ_GEQ(ack, sptr->trans_seq)))
03472 {
03473
03474 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03475 "[^^] Accepting %s state transition\n",
03476 state_names[sptr->state_queue]););
03477 sptr->state = sptr->state_queue;
03478 sptr->expected_flags = 0;
03479 sptr->trans_seq = 0;
03480 return 1;
03481 }
03482 else if(!sptr->stq_chk_seq)
03483 {
03484 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03485 "[^^] Accepting %s state transition\n",
03486 state_names[sptr->state_queue]););
03487 sptr->state = sptr->state_queue;
03488 sptr->expected_flags = 0;
03489 sptr->trans_seq = 0;
03490 return 1;
03491
03492 }
03493 else
03494 {
03495 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03496 "[!!] sptr->stq_chk_seq: %d "
03497 "[ack: 0x%X expected: 0x%X]\n", sptr->stq_chk_seq,
03498 ack, sptr->trans_seq););
03499 }
03500 }
03501 else
03502 {
03503 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03504 "[!!] flags: 0x%X expected: 0x%X, bitwise: 0x%X\n",
03505 flags, sptr->expected_flags,
03506 (flags&sptr->expected_flags)););
03507 }
03508 }
03509
03510 return 0;
03511 }
03512
03513
03514
03515 int UpdateState2(Session *ssn, Packet *p, u_int32_t pkt_seq)
03516 {
03517 int direction;
03518 int retcode = 0;
03519 Stream *talker = NULL;
03520 Stream *listener = NULL;
03521 DEBUG_WRAP(
03522 char *t = NULL;
03523 char *l = NULL;
03524 );
03525
03526 direction = GetDirection(ssn, p);
03527
03528 if(p->tcph->th_flags & TH_FIN)
03529 {
03530 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03531 "Marking that a fin was was sent %s\n",
03532 (direction ? "FROM_CLIENT" : "FROM_SERVER")););
03533 SetFinSent(p, ssn, direction);
03534 }
03535
03536 if(direction == FROM_SERVER)
03537 {
03538 ssn->session_flags |= SSNFLAG_SEEN_SERVER;
03539 talker = &ssn->server;
03540 listener = &ssn->client;
03541
03542 DEBUG_WRAP(
03543 t = strdup("Server");
03544 l = strdup("Client"););
03545 }
03546 else
03547 {
03548 ssn->session_flags |= SSNFLAG_SEEN_CLIENT;
03549 talker = &ssn->client;
03550 listener = &ssn->server;
03551
03552 DEBUG_WRAP(
03553 t = strdup("Client");
03554 l = strdup("Server"););
03555 }
03556
03557 EvalStateQueue(talker, p->tcph->th_flags, ntohl(p->tcph->th_ack));
03558
03559 if(talker->state != ESTABLISHED)
03560 {
03561 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03562 " %s [talker] state: %s\n", t, state_names[talker->state]););
03563 }
03564 if(listener->state != ESTABLISHED)
03565 {
03566 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03567 " %s state: %s\n", l, state_names[listener->state]););
03568 }
03569
03570 StreamSegmentAdd(talker, p->dsize);
03571
03572 if(talker->state == ESTABLISHED)
03573 {
03574 listener->win_size = ntohs(p->tcph->th_win);
03575 }
03576
03577 if(p->tcph->th_flags & TH_RST)
03578 {
03579
03580 if(CheckRst(ssn, direction, pkt_seq, p))
03581 {
03582 int action = ACTION_FLUSH_CLIENT_STREAM |
03583 ACTION_FLUSH_SERVER_STREAM |
03584 ACTION_DROP_SESSION;
03585
03586 ssn->client.state = CLOSED;
03587 ssn->server.state = CLOSED;
03588
03589 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03590 " Client Transition: CLOSED\n");
03591 DebugMessage(DEBUG_STREAM_STATE,
03592 " Server Transision: CLOSED\n");
03593 if(l) free(l);
03594 if(t) free(t););
03595
03596 if ( p->tcph->th_flags & TH_ACK )
03597 {
03598 if ( direction == FROM_SERVER )
03599 {
03600 action |= ACTION_ACK_CLIENT_DATA;
03601 }
03602 else
03603 {
03604 action |= ACTION_ACK_SERVER_DATA;
03605 }
03606 }
03607
03608 return action;
03609 }
03610 }
03611
03612 switch(listener->state)
03613 {
03614 case LISTEN:
03615
03616
03617
03618
03619
03620
03621
03622 if((p->tcph->th_flags & TH_SYN) &&
03623 !(p->tcph->th_flags & TH_RST))
03624 {
03625 QueueState(SYN_RCVD, listener, TH_SYN| TH_ACK, 0, NO_CHK_SEQ);
03626
03627 if(talker->state != SYN_SENT)
03628 {
03629 talker->state = SYN_SENT;
03630 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03631 " %s Transition: SYN_SENT\n", t););
03632 }
03633 }
03634
03635 if(p->dsize != 0)
03636 retcode |= ACTION_DATA_ON_SYN;
03637 break;
03638
03639 case SYN_SENT:
03640 if((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK))
03641 {
03642 if(talker->state != SYN_RCVD)
03643 {
03644 talker->state = SYN_RCVD;
03645
03646 DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
03647 " %s Transition: SYN_RCVD\n", t););
03648 }
03649
03650 QueueState(ESTABLISHED, listener, TH_ACK, pkt_seq, CHK_SEQ);
03651
03652
03653 if((p->tcph->th_flags & TH_RES2) &&
03654 ssn->session_flags & SSNFLAG_ECN_CLIENT_QUERY)
03655 {
03656 ssn->session_flags |= SSNFLAG_ECN_SERVER_REPLY;
03657 }
03658
03659 retcode |= ACTION_SET_SERVER_ISN;
03660 }
03661
03662 break;
03663
03664 case SYN_RCVD:
03665 if(p->tcph->th_flags & TH_ACK)
03666 {
03667 listener->state = ESTABLISHED;
03668 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03669 " %s Transition: ESTABLISHED\n", l););
03670 retcode |= ACTION_COMPLETE_TWH;
03671 }
03672
03673 break;
03674
03675 case ESTABLISHED:
03676 if(p->tcph->th_flags & TH_ACK)
03677 {
03678 if(direction == FROM_CLIENT)
03679 retcode |= ACTION_ACK_SERVER_DATA;
03680 else
03681 retcode |= ACTION_ACK_CLIENT_DATA;
03682 }
03683
03684 if((p->tcph->th_flags & TH_FIN) == TH_FIN)
03685 {
03686 talker->state = FIN_WAIT_1;
03687 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03688 " %s Transition: FIN_WAIT_1\n", t););
03689 QueueState(CLOSE_WAIT, listener, TH_ACK, pkt_seq, CHK_SEQ);
03690 }
03691
03692 break;
03693
03694 case CLOSE_WAIT:
03695 QueueState(LAST_ACK, talker, TH_FIN, pkt_seq, NO_CHK_SEQ);
03696
03697 if(p->tcph->th_flags == TH_ACK)
03698 {
03699 if(direction == FROM_CLIENT)
03700 retcode |= ACTION_ACK_SERVER_DATA;
03701 else
03702 retcode |= ACTION_ACK_CLIENT_DATA;
03703 }
03704
03705 break;
03706
03707 case LAST_ACK:
03708 if(p->tcph->th_flags & TH_ACK)
03709 {
03710 listener->state = CLOSED;
03711 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03712 " %s Transition: CLOSED\n", l););
03713
03714 if(talker->state == TIME_WAIT)
03715 {
03716 talker->state = CLOSED;
03717 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03718 " %s Transition: CLOSED\n", t););
03719 }
03720
03721 retcode |= (ACTION_FLUSH_CLIENT_STREAM |
03722 ACTION_FLUSH_SERVER_STREAM |
03723 ACTION_DROP_SESSION);
03724 }
03725
03726 break;
03727
03728 case FIN_WAIT_1:
03729 if((p->tcph->th_flags & (TH_ACK|TH_FIN)) == (TH_ACK|TH_FIN))
03730 {
03731 talker->state = LAST_ACK;
03732 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
03733 " %s Transition: LAST_ACK\n", t););
03734 QueueState(TIME_WAIT, listener, TH_ACK, pkt_seq, CHK_SEQ);
03735
03736 if(direction == FROM_CLIENT)
03737 retcode |= ACTION_ACK_SERVER_DATA;
03738 else
03739 retcode |= ACTION_ACK_CLIENT_DATA;
03740 }
03741 else if(p->tcph->th_flags == TH_ACK)
03742 {
03743 QueueState(LAST_ACK, talker, TH_FIN, pkt_seq, NO_CHK_SEQ);
03744 listener->state = FIN_WAIT_2;
03745 DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
03746 " %s Transition: FIN_WAIT_2\n", l););
03747
03748 if(direction == FROM_CLIENT)
03749 retcode |= ACTION_ACK_SERVER_DATA;
03750 else
03751 retcode |= ACTION_ACK_CLIENT_DATA;
03752 }
03753
03754 break;
03755
03756 case FIN_WAIT_2:
03757 if(p->tcph->th_flags == (TH_FIN|TH_ACK))
03758 {
03759 talker->state = LAST_ACK;
03760 QueueState(TIME_WAIT, listener, TH_ACK, pkt_seq, CHK_SEQ);
03761
03762 if(direction == FROM_CLIENT)
03763 retcode |= ACTION_FLUSH_CLIENT_STREAM | ACTION_ACK_SERVER_DATA;
03764 else
03765 retcode |= ACTION_FLUSH_SERVER_STREAM | ACTION_ACK_CLIENT_DATA;
03766 }
03767 else if(p->tcph->th_flags == TH_FIN)
03768 {
03769 talker->state = LAST_ACK;
03770 DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
03771 " %s Transition: LAST_ACK\n", t););
03772
03773 QueueState(TIME_WAIT, listener, TH_ACK, pkt_seq, CHK_SEQ);
03774
03775 if(direction == FROM_CLIENT)
03776 retcode |= ACTION_FLUSH_SERVER_STREAM;
03777 else
03778 retcode |= ACTION_FLUSH_CLIENT_STREAM;
03779 }
03780
03781 break;
03782
03783 case TIME_WAIT:
03784 case CLOSED:
03785 return ACTION_FLUSH_CLIENT_STREAM | ACTION_DROP_SESSION;
03786 }
03787
03788 DEBUG_WRAP(
03789 if(l) free(l);
03790 if(t) free(t););
03791
03792 return retcode;
03793 }
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804 int UpdateStateAsync(Session *ssn, Packet *p, u_int32_t pkt_seq)
03805 {
03806 int direction;
03807
03808 direction = GetDirection(ssn, p);
03809
03810 switch(direction)
03811 {
03812 case FROM_SERVER:
03813 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03814 "Client State: SYN_SENT\n"););
03815
03816 StreamSegmentAdd(&ssn->server, p->dsize);
03817
03818 ssn->session_flags |= SSNFLAG_SEEN_SERVER;
03819
03820 switch(ssn->server.state)
03821 {
03822 case SYN_RCVD:
03823
03824
03825
03826 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03827 "Server state: SYN_RCVD\n"););
03828 if((p->tcph->th_flags & TH_NORESERVED) == (TH_SYN|TH_ACK))
03829 {
03830 ssn->server.state = ESTABLISHED;
03831 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03832 " Server Transition: ESTABLISHED\n"););
03833 return ACTION_COMPLETE_TWH;
03834 }
03835 return ACTION_NOTHING;
03836
03837 case ESTABLISHED:
03838 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03839 "Server state: ESTABLISHED\n"););
03840 if(p->tcph->th_flags & TH_FIN)
03841 {
03842 ssn->server.state = CLOSED;
03843 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03844 " Client Transition: FIN_WAIT_1\n"););
03845
03846 return ACTION_FLUSH_SERVER_STREAM|ACTION_DROP_SESSION;
03847 }
03848 else if(p->tcph->th_flags & TH_RST)
03849 {
03850 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03851 "Got RST (0x%X)\n",
03852 p->tcph->th_flags););
03853 ssn->server.state = CLOSED;
03854 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03855 " Server Transition: CLOSED\n"););
03856
03857 return ACTION_FLUSH_SERVER_STREAM | ACTION_DROP_SESSION;
03858 }
03859
03860 return ACTION_NOTHING;
03861 }
03862
03863 case FROM_CLIENT:
03864
03865 StreamSegmentAdd(&ssn->client, p->dsize);
03866
03867 ssn->session_flags |= SSNFLAG_SEEN_CLIENT;
03868
03869 switch(ssn->client.state)
03870 {
03871 case SYN_SENT:
03872 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03873 "Client State: SYN_SENT\n"););
03874 if(p->tcph->th_flags & TH_RST)
03875 {
03876 ssn->client.state = CLOSED;
03877
03878 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03879 " Client Transition: CLOSED -- RESET\n"););
03880
03881 return ACTION_FLUSH_CLIENT_STREAM | ACTION_DROP_SESSION;
03882 }
03883 else if(p->tcph->th_flags & TH_ACK)
03884 {
03885 ssn->client.state = ESTABLISHED;
03886
03887 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03888 " Client Transition: ESTABLISHED\n"););
03889
03890 return ACTION_NOTHING;
03891 }
03892
03893
03894 return ACTION_NOTHING;
03895
03896
03897 case ESTABLISHED:
03898 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03899 "Client state: ESTABLISHED\n"););
03900
03901 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03902 "Session State: ESTABLISHED\n"););
03903 ssn->session_flags |= SSNFLAG_ESTABLISHED;
03904
03905
03906 if(p->tcph->th_flags & TH_FIN)
03907 {
03908 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03909 "Got FIN (0x%X)\n",
03910 p->tcph->th_flags););
03911 ssn->client.state = CLOSED;
03912 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03913 " Client Transition: CLOSEd\n"););
03914
03915 return ACTION_FLUSH_CLIENT_STREAM|ACTION_DROP_SESSION;
03916 }
03917 else if(p->tcph->th_flags & TH_RST)
03918 {
03919 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03920 "Got RST (0x%X)\n",
03921 p->tcph->th_flags););
03922 ssn->client.state = CLOSED;
03923 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
03924 " Client Transition: Closed\n"););
03925
03926 return ACTION_FLUSH_CLIENT_STREAM | ACTION_DROP_SESSION;
03927 }
03928 break;
03929 }
03930 }
03931
03932 return ACTION_NOTHING;
03933 }
03934
03935
03936
03937 Session *CreateNewSession(Packet *p, u_int32_t pkt_seq, u_int32_t pkt_ack)
03938 {
03939 Session *idx = NULL;
03940 static u_int8_t savedfpi;
03941 u_int8_t fpi;
03942
03943
03944
03945 savedfpi++;
03946 fpi = savedfpi % FCOUNT;
03947 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Using flush value of "
03948 "(%d bytes) at index %d\n", flush_points[fpi],fpi););
03949
03950
03951
03952
03953
03954
03955
03956 switch(p->tcph->th_flags)
03957 {
03958 case TH_RES1|TH_RES2|TH_SYN:
03959 if(p->iph->ip_tos == 0x02)
03960 {
03961
03962 p->packet_flags |= PKT_ECN;
03963 }
03964
03965
03966
03967 case TH_SYN:
03968 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[A] initializing new session "
03969 "(%d bytes)\n", sizeof(Session)););
03970
03971 #ifdef USE_HASH_TABLE
03972 idx = GetNewSession(p);
03973 #else
03974 idx = (Session *) SafeAlloc(sizeof(Session), p->pkth->ts.tv_sec,
03975 NULL);
03976 #endif
03977
03978 if(s4data.reassemble_server)
03979 (void)ubi_trInitTree(&idx->server.data,
03980 DataCompareFunc,
03981 ubi_trDUPKEY);
03982 else
03983 idx->server.data.root = NULL;
03984
03985 if(s4data.reassemble_client)
03986 (void)ubi_trInitTree(&idx->client.data,
03987 DataCompareFunc,
03988 ubi_trDUPKEY);
03989 else
03990 idx->client.data.root = NULL;
03991
03992 idx->server.state = LISTEN;
03993 idx->server.ip = p->iph->ip_dst.s_addr;
03994 idx->server.port = p->dp;
03995
03996 idx->client.state = SYN_SENT;
03997 idx->client.ip = p->iph->ip_src.s_addr;
03998 idx->client.port = p->sp;
03999 idx->client.isn = pkt_seq;
04000 idx->server.win_size = ntohs(p->tcph->th_win);
04001
04002 idx->start_time = p->pkth->ts.tv_sec;
04003 idx->last_session_time = p->pkth->ts.tv_sec;
04004
04005 idx->session_flags |= SSNFLAG_SEEN_CLIENT;
04006
04007 if(p->packet_flags & PKT_ECN)
04008 {
04009 idx->session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
04010 }
04011
04012 idx->flush_point = flush_points[fpi];
04013 break;
04014
04015 case TH_RES2|TH_SYN|TH_ACK:
04016 if(p->iph->ip_tos == 0x02)
04017 {
04018 p->packet_flags |= PKT_ECN;
04019 }
04020 else
04021 {
04022 if(s4data.ps_alerts)
04023 {
04024 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04025 STREAM4_STEALTH_ACTIVITY,
04026 1,
04027 0,
04028 3,
04029 STREAM4_STEALTH_ACTIVITY_STR,
04030 0);
04031
04032 break;
04033 }
04034
04035 return NULL;
04036 }
04037
04038
04039
04040 case TH_SYN|TH_ACK:
04041 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[A] initializing new session "
04042 "(%d bytes)\n", sizeof(Session)););
04043
04044 #ifdef USE_HASH_TABLE
04045 idx = GetNewSession(p);
04046 #else
04047 idx = (Session *) SafeAlloc(sizeof(Session), p->pkth->ts.tv_sec,
04048 NULL);
04049 #endif
04050
04051 if(s4data.reassemble_server)
04052 (void)ubi_trInitTree(&idx->server.data,
04053 DataCompareFunc,
04054 ubi_trDUPKEY);
04055 else
04056 idx->server.data.root = NULL;
04057
04058 if(s4data.reassemble_client)
04059 (void)ubi_trInitTree(&idx->client.data,
04060 DataCompareFunc,
04061 ubi_trDUPKEY);
04062 else
04063 idx->client.data.root = NULL;
04064
04065 idx->server.state = SYN_RCVD;
04066 idx->client.state = SYN_SENT;
04067
04068 idx->server.ip = p->iph->ip_src.s_addr;
04069 idx->server.port = p->sp;
04070 idx->server.isn = pkt_seq;
04071 idx->client.win_size = ntohs(p->tcph->th_win);
04072
04073 idx->client.ip = p->iph->ip_dst.s_addr;
04074 idx->client.port = p->dp;
04075 idx->client.isn = pkt_ack-1;
04076
04077 idx->start_time = p->pkth->ts.tv_sec;
04078 idx->last_session_time = p->pkth->ts.tv_sec;
04079 idx->session_flags = SSNFLAG_SEEN_SERVER;
04080 idx->flush_point = flush_points[fpi];
04081 break;
04082
04083 case TH_ACK:
04084 case TH_ACK|TH_PUSH:
04085 case TH_FIN|TH_ACK:
04086 case TH_ACK|TH_URG:
04087 case TH_ACK|TH_PUSH|TH_URG:
04088 case TH_FIN|TH_ACK|TH_URG:
04089 case TH_ACK|TH_PUSH|TH_FIN:
04090 case TH_ACK|TH_PUSH|TH_FIN|TH_URG:
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[A] initializing new session "
04102 "(%d bytes)\n", sizeof(Session)););
04103
04104 #ifdef USE_HASH_TABLE
04105 idx = GetNewSession(p);
04106 #else
04107 idx = (Session *) SafeAlloc(sizeof(Session), p->pkth->ts.tv_sec,
04108 NULL);
04109 #endif
04110
04111 if(s4data.reassemble_server)
04112 (void)ubi_trInitTree(&idx->server.data,
04113 DataCompareFunc,
04114 ubi_trDUPKEY);
04115 else
04116 idx->server.data.root = NULL;
04117
04118 if(s4data.reassemble_client)
04119 (void)ubi_trInitTree(&idx->client.data,
04120 DataCompareFunc,
04121 ubi_trDUPKEY);
04122 else
04123 idx->client.data.root = NULL;
04124
04125 idx->server.state = ESTABLISHED;
04126 idx->client.state = ESTABLISHED;
04127
04128 if ( p->dp <= p->sp )
04129 {
04130 idx->server.ip = p->iph->ip_dst.s_addr;
04131 idx->server.port = p->dp;
04132 idx->server.isn = pkt_ack-1;
04133 idx->server.last_ack = pkt_ack;
04134 idx->server.base_seq = idx->server.last_ack;
04135 idx->server.win_size = ntohs(p->tcph->th_win);
04136
04137 idx->client.ip = p->iph->ip_src.s_addr;
04138 idx->client.port = p->sp;
04139 idx->client.isn = pkt_seq-1;
04140 idx->client.last_ack = pkt_seq;
04141 idx->client.base_seq = idx->client.last_ack;
04142 idx->session_flags = SSNFLAG_SEEN_CLIENT;
04143 }
04144 else
04145 {
04146 idx->client.ip = p->iph->ip_dst.s_addr;
04147 idx->client.port = p->dp;
04148 idx->client.isn = pkt_ack-1;
04149 idx->client.last_ack = pkt_ack;
04150 idx->client.base_seq = idx->client.last_ack;
04151 idx->client.win_size = ntohs(p->tcph->th_win);
04152
04153 idx->server.ip = p->iph->ip_src.s_addr;
04154 idx->server.port = p->sp;
04155 idx->server.isn = pkt_seq-1;
04156 idx->server.last_ack = pkt_seq;
04157 idx->server.base_seq = idx->server.last_ack;
04158 idx->session_flags = SSNFLAG_SEEN_SERVER;
04159 }
04160 idx->start_time = p->pkth->ts.tv_sec;
04161 idx->last_session_time = p->pkth->ts.tv_sec;
04162 idx->flush_point = flush_points[fpi];
04163 break;
04164
04165 case TH_RES2|TH_SYN:
04166 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[A] initializing new session "
04167 "(%d bytes)\n", sizeof(Session));
04168 DebugMessage(DEBUG_STREAM,
04169 "nmap fingerprint scan 2SYN packet!\n"););
04170 #ifdef USE_HASH_TABLE
04171 idx = GetNewSession(p);
04172 #else
04173 idx = (Session *) SafeAlloc(sizeof(Session), p->pkth->ts.tv_sec, NULL);
04174 #endif
04175
04176 if(s4data.reassemble_server)
04177 (void)ubi_trInitTree(&idx->server.data,
04178 DataCompareFunc,
04179 ubi_trDUPKEY);
04180 else
04181 idx->server.data.root = NULL;
04182
04183 if(s4data.reassemble_client)
04184 (void)ubi_trInitTree(&idx->client.data,
04185 DataCompareFunc,
04186 ubi_trDUPKEY);
04187 else
04188 idx->client.data.root = NULL;
04189
04190 idx->server.state = NMAP_FINGERPRINT_2S;
04191 idx->client.state = NMAP_FINGERPRINT_2S;
04192
04193 idx->server.ip = p->iph->ip_dst.s_addr;
04194 idx->server.port = p->dp;
04195
04196 idx->client.ip = p->iph->ip_src.s_addr;
04197 idx->client.port = p->sp;
04198 idx->client.port++;
04199 idx->client.isn = pkt_seq;
04200 idx->server.win_size = ntohs(p->tcph->th_win);
04201
04202 idx->start_time = p->pkth->ts.tv_sec;
04203 idx->last_session_time = p->pkth->ts.tv_sec;
04204
04205 idx->session_flags = SSNFLAG_SEEN_CLIENT|SSNFLAG_NMAP;
04206 idx->flush_point = flush_points[fpi];
04207
04208 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"init nmap for sip: 0x%X sp: %d "
04209 "cip: 0x%X cp: %d\n",
04210 idx->server.ip, idx->server.port,
04211 idx->client.ip, idx->client.port););
04212
04213 break;
04214 case TH_SYN|TH_RST|TH_ACK|TH_FIN|TH_PUSH|TH_URG:
04215 if(s4data.ps_alerts)
04216 {
04217
04218 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04219 STREAM4_STEALTH_FULL_XMAS,
04220 1,
04221 0,
04222 3,
04223 STREAM4_STEALTH_FULL_XMAS_STR,
04224 0);
04225 }
04226
04227 break;
04228
04229 case TH_SYN|TH_ACK|TH_URG|TH_PUSH:
04230 if(s4data.ps_alerts)
04231 {
04232 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04233 STREAM4_STEALTH_SAPU,
04234 1,
04235 0,
04236 3,
04237 STREAM4_STEALTH_SAPU_STR,
04238 0);
04239 }
04240
04241 break;
04242
04243 case TH_FIN:
04244 if(s4data.ps_alerts)
04245 {
04246 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04247 STREAM4_STEALTH_FIN_SCAN,
04248 1,
04249 0,
04250 3,
04251 STREAM4_STEALTH_FIN_SCAN_STR,
04252 0);
04253 }
04254
04255 break;
04256
04257 case TH_SYN|TH_FIN:
04258 if(s4data.ps_alerts)
04259 {
04260 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04261 STREAM4_STEALTH_SYN_FIN_SCAN,
04262 1,
04263 0,
04264 3,
04265 STREAM4_STEALTH_SYN_FIN_SCAN_STR,
04266 0);
04267 }
04268
04269 break;
04270
04271 case 0:
04272 if(s4data.ps_alerts)
04273 {
04274 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04275 STREAM4_STEALTH_NULL_SCAN,
04276 1,
04277 0,
04278 3,
04279 STREAM4_STEALTH_NULL_SCAN_STR,
04280 0);
04281 }
04282
04283 break;
04284
04285 case TH_FIN|TH_PUSH|TH_URG:
04286 if(s4data.ps_alerts)
04287 {
04288 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04289 STREAM4_STEALTH_NMAP_XMAS_SCAN,
04290 1,
04291 0,
04292 3,
04293 STREAM4_STEALTH_NMAP_XMAS_SCAN_STR,
04294 0);
04295 }
04296
04297 break;
04298
04299 case TH_URG:
04300 case TH_PUSH:
04301 case TH_FIN|TH_URG:
04302 case TH_PUSH|TH_FIN:
04303 case TH_URG|TH_PUSH:
04304 if(s4data.ps_alerts)
04305 {
04306 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04307 STREAM4_STEALTH_VECNA_SCAN,
04308 1,
04309 0,
04310 3,
04311 STREAM4_STEALTH_VECNA_SCAN_STR,
04312 0);
04313 }
04314
04315 break;
04316
04317 case TH_RST:
04318 case TH_RST|TH_ACK:
04319 break;
04320
04321 default:
04322
04323
04324
04325 if(s4data.ps_alerts)
04326 {
04327 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04328 STREAM4_STEALTH_ACTIVITY,
04329 1,
04330 0,
04331 3,
04332 STREAM4_STEALTH_ACTIVITY_STR,
04333 0);
04334
04335 break;
04336 }
04337
04338 return NULL;
04339 }
04340
04341 if(idx)
04342 {
04343 #ifdef USE_HASH_TABLE
04344 #else
04345 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04346 "Inserting session into session tree...\n"););
04347 if(ubi_sptInsert(RootPtr,(ubi_btNodePtr)idx,(ubi_btNodePtr)idx, NULL)
04348 == ubi_trFALSE)
04349 {
04350 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04351 "sptInsert failed, that's going to "
04352 "make life difficult\n"););
04353
04354 stream4_memory_usage -= sizeof(Session);
04355 free(idx);
04356 return NULL;
04357 }
04358 #endif
04359 pc.tcp_streams++;
04360 }
04361
04362 return idx;
04363 }
04364
04365
04366
04367 void DeleteSession(Session *ssn, u_int32_t time)
04368 {
04369 struct in_addr foo;
04370 register int s;
04371 struct tm *lt;
04372 struct tm *et;
04373 Session *killme;
04374
04375 RemoveStreamSession(&sfPerf.sfBase);
04376
04377 if(ssn == NULL)
04378 return;
04379
04380 if(s4data.track_stats_flag == STATS_HUMAN_READABLE)
04381 {
04382 lt = localtime((time_t *) &ssn->start_time);
04383 s = (ssn->start_time + thiszone) % 86400;
04384
04385 fprintf(session_log, "[*] Session stats:\n Start Time: ");
04386 fprintf(session_log, "%02d/%02d/%02d-%02d:%02d:%02d", lt->tm_mon+1,
04387 lt->tm_mday, lt->tm_year - 100, s/3600, (s%3600)/60, s%60);
04388
04389 et = localtime((time_t *) &ssn->last_session_time);
04390 s = (ssn->last_session_time + thiszone) % 86400;
04391 fprintf(session_log, " End Time: %02d/%02d/%02d-%02d:%02d:%02d\n",
04392 et->tm_mon+1, et->tm_mday, et->tm_year - 100, s/3600,
04393 (s%3600)/60, s%60);
04394
04395 foo.s_addr = ssn->server.ip;
04396 fprintf(session_log, " Server IP: %s ", inet_ntoa(foo));
04397 fprintf(session_log, "port: %d pkts: %u bytes: %u\n",
04398 ssn->server.port, ssn->server.pkts_sent,
04399 ssn->server.bytes_sent);
04400 foo.s_addr = ssn->client.ip;
04401 fprintf(session_log, " Client IP: %s ", inet_ntoa(foo));
04402 fprintf(session_log, "port: %d pkts: %u bytes: %u\n",
04403 ssn->client.port, ssn->client.pkts_sent,
04404 ssn->client.bytes_sent);
04405
04406 }
04407 else if(s4data.track_stats_flag == STATS_MACHINE_READABLE)
04408 {
04409 lt = localtime((time_t *) &ssn->start_time);
04410 s = (ssn->start_time + thiszone) % 86400;
04411
04412 fprintf(session_log, "[*] Session => Start: ");
04413 fprintf(session_log, "%02d/%02d/%02d-%02d:%02d:%02d", lt->tm_mon+1,
04414 lt->tm_mday, lt->tm_year - 100, s/3600, (s%3600)/60, s%60);
04415
04416 et = localtime((time_t *) &ssn->last_session_time);
04417 s = (ssn->last_session_time + thiszone) % 86400;
04418 fprintf(session_log, " End Time: %02d/%02d/%02d-%02d:%02d:%02d",
04419 et->tm_mon+1, et->tm_mday, et->tm_year - 100, s/3600,
04420 (s%3600)/60, s%60);
04421
04422 foo.s_addr = ssn->server.ip;
04423 fprintf(session_log, "[Server IP: %s ", inet_ntoa(foo));
04424 fprintf(session_log, "port: %d pkts: %u bytes: %u]",
04425 ssn->server.port, ssn->server.pkts_sent,
04426 ssn->server.bytes_sent);
04427 foo.s_addr = ssn->client.ip;
04428 fprintf(session_log, " [Client IP: %s ", inet_ntoa(foo));
04429 fprintf(session_log, "port: %d pkts: %u bytes: %u]\n",
04430 ssn->client.port, ssn->client.pkts_sent,
04431 ssn->client.bytes_sent);
04432 }
04433 else if(s4data.track_stats_flag == STATS_BINARY)
04434 {
04435 BinStats bs;
04436
04437 bs.start_time = ssn->start_time;
04438 bs.end_time = ssn->last_session_time;
04439 bs.sip = ssn->server.ip;
04440 bs.cip = ssn->client.ip;
04441 bs.sport = ssn->server.port;
04442 bs.cport = ssn->client.port;
04443 bs.spackets = ssn->server.pkts_sent;
04444 bs.cpackets = ssn->client.pkts_sent;
04445 bs.sbytes = ssn->server.bytes_sent;
04446 bs.cbytes = ssn->client.bytes_sent;
04447
04448 WriteSsnStats(&bs);
04449 }
04450
04451 #ifdef USE_HASH_TABLE
04452 killme = RemoveSession(ssn);
04453
04454 DropSession(killme);
04455 #else
04456 if(ubi_trCount(RootPtr))
04457 {
04458 killme = (Session *) ubi_sptRemove(RootPtr, (ubi_btNodePtr) ssn);
04459
04460 DropSession(killme);
04461 }
04462 #endif
04463 }
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497
04498 int CheckRst(Session *ssn, int direction, u_int32_t pkt_seq, Packet *p)
04499 {
04500 Stream *s;
04501 static StreamPacketData spd;
04502 spd.seq_num = pkt_seq;
04503
04504
04505 if( !s4data.stateful_inspection_flag )
04506 return 0;
04507
04508 if(direction == FROM_SERVER)
04509 {
04510 s = &ssn->server;
04511 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"--RST From Server!\n"););
04512 }
04513 else
04514 {
04515 s = &ssn->client;
04516 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"--RST From Client!\n"););
04517 }
04518
04519 {
04520 DEBUG_WRAP(struct in_addr foo;);
04521 DEBUG_WRAP(foo.s_addr=s->ip;
04522 DebugMessage(DEBUG_STREAM,
04523 "--RST packet from %s!\n",inet_ntoa(foo));
04524 DebugMessage(DEBUG_STREAM,
04525 "--pkt seq: %u last_ack: %u base-seq: %u next-seq: %u "
04526 "bytes-sent: %u bytes-tracked: %u win: %u \n",
04527 pkt_seq,s->last_ack,s->base_seq,s->next_seq,s->bytes_sent,
04528 s->bytes_tracked,s->win_size););
04529 }
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552 if( !SEQ_EQ(pkt_seq,s->base_seq+s->bytes_sent) )
04553 {
04554 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04555 "Bad RST packet, bad sequence or no ack, no cookie!\n");
04556 DebugMessage(DEBUG_STREAM, "pkt seq: 0x%X last_ack: 0x%X "
04557 "win: 0x%X\n", pkt_seq, s->last_ack, s->win_size););
04558
04559
04560 if(s4data.evasion_alerts)
04561 {
04562 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04563 STREAM4_EVASIVE_RST,
04564 1,
04565 0,
04566 3,
04567 STREAM4_EVASIVE_RST_STR,
04568 0);
04569 }
04570
04571 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04572 "Ignoring a RST (1)...pkt_seq=%u\n",pkt_seq););
04573 return 0;
04574 }
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587 if( ubi_sptFind(&s->data,(ubi_btItemPtr)(&spd)) &&
04588 SEQ_LT(s->last_ack,s->base_seq+s->bytes_sent) )
04589 {
04590 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04591 "Ignoring a RST (2)...pkt_seq=%u\n",pkt_seq););
04592 return 0;
04593 }
04594
04595 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04596 "Not Ignoring a RST...pkt_seq=%u\n",pkt_seq););
04597
04598 return 1;
04599 }
04600
04601 void FlushDeletedStream(Session *ssn, Stream *s)
04602 {
04603 Packet p;
04604 StreamPacketData *spd;
04605 if (s)
04606 {
04607 if (ubi_trCount((ubi_btNodePtr)&s->data))
04608 {
04609
04610
04611 ubi_btRootPtr RootPtr = &s->data;
04612 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
04613 "Dropping session... reassembling before purge\n"););
04614 spd = (StreamPacketData *)ubi_trLast(RootPtr->root);
04615
04616
04617
04618
04619 (*grinder)(&p, (struct pcap_pkthdr *)&spd->pkth, spd->pkt);
04620 p.ssnptr = ssn;
04621 p.streamptr = s;
04622 FlushStream(s, &p, NO_REVERSE);
04623 }
04624 }
04625 }
04626
04627 void DropSession(Session *ssn)
04628 {
04629 Stream *s;
04630 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Dropping session %p\n", ssn););
04631
04632 if(ssn == NULL)
04633 return;
04634
04635 if (s4data.reassemble_server)
04636 {
04637 s = &ssn->server;
04638 FlushDeletedStream(ssn, s);
04639 }
04640
04641 if (s4data.reassemble_client)
04642 {
04643 s = &ssn->client;
04644 FlushDeletedStream(ssn, s);
04645 }
04646
04647 DeleteSpd((ubi_trRootPtr)&ssn->server.data);
04648
04649 DeleteSpd((ubi_trRootPtr)&ssn->client.data);
04650
04651 if (ssn->preproc_free)
04652 {
04653 ssn->preproc_free(ssn->preproc_data);
04654 ssn->preproc_data = NULL;
04655 ssn->preproc_free = NULL;
04656 }
04657
04658 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[F] Freeing %d byte session\n",
04659 sizeof(Session)););
04660
04661 #ifdef USE_HASH_TABLE
04662 #else
04663 stream4_memory_usage -= sizeof(Session);
04664 free(ssn);
04665 #endif
04666 }
04667
04668
04669
04670 void DeleteSpd(ubi_trRootPtr Root)
04671 {
04672 (void)ubi_trKillTree(Root, KillSpd);
04673 }
04674
04675
04676 int GetDirection(Session *ssn, Packet *p)
04677 {
04678 if(p->iph->ip_src.s_addr == ssn->client.ip)
04679 {
04680 return FROM_CLIENT;
04681 }
04682 else if(((p->tcph->th_flags & TH_NORESERVED) == TH_SYN) &&
04683 !(ssn->session_flags & SSNFLAG_ESTABLISHED))
04684 {
04685 ssn->client.port = p->sp;
04686 ssn->client.ip = p->iph->ip_src.s_addr;
04687 ssn->server.port = p->dp;
04688 ssn->server.ip = p->iph->ip_dst.s_addr;
04689 return FROM_CLIENT;
04690 }
04691
04692 return FROM_SERVER;
04693 }
04694
04695 #ifdef USE_HASH_TABLE
04696 #elif defined(USE_SPLAY_TREE)
04697 #else
04698 Session *GetSession(Packet *p)
04699 {
04700 Session idx;
04701 Session *returned;
04702 #ifdef DEBUG
04703 char flagbuf[9];
04704 CreateTCPFlagString(p, flagbuf);
04705 #endif
04706
04707 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Trying to get session...\n"););
04708 idx.server.ip = p->iph->ip_src.s_addr;
04709 idx.client.ip = p->iph->ip_dst.s_addr;
04710 idx.server.port = p->sp;
04711 idx.client.port = p->dp;
04712
04713 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Looking for sip: 0x%X sp: %d cip: "
04714 "0x%X cp: %d flags: %s\n", idx.server.ip, idx.server.port,
04715 idx.client.ip, idx.client.port, flagbuf););
04716
04717 returned = (Session *) ubi_sptFind(RootPtr, (ubi_btItemPtr)&idx);
04718
04719 if(returned == NULL)
04720 {
04721 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "GetSession forward didn't work, "
04722 "trying backwards...\n"););
04723 idx.server.ip = p->iph->ip_dst.s_addr;
04724 idx.client.ip = p->iph->ip_src.s_addr;
04725 idx.server.port = p->dp;
04726 idx.client.port = p->sp;
04727 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Looking for sip: 0x%X sp: %d "
04728 "cip: 0x%X cp: %d flags: %s\n", idx.server.ip,
04729 idx.server.port, idx.client.ip, idx.client.port,
04730 flagbuf););
04731 returned = (Session *) ubi_sptFind(RootPtr, (ubi_btItemPtr)&idx);
04732 }
04733
04734 if(returned == NULL)
04735 {
04736 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Unable to find session\n"););
04737 }
04738 else
04739 {
04740 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Found session\n"););
04741 }
04742
04743 return returned;
04744
04745 }
04746 #endif
04747
04748 void Stream4ShutdownFunction(int signal, void *foo)
04749 {
04750
04751 if(s4data.store_state_to_disk == 1)
04752 {
04753 DumpStateTable(s4data.state_file);
04754 }
04755
04756 PurgeSessionCache();
04757 }
04758
04759 void Stream4CleanExitFunction(int signal, void *foo)
04760 {
04761 if(s4data.track_stats_flag)
04762 {
04763 if(s4data.track_stats_flag != STATS_BINARY)
04764 fclose(session_log);
04765 else
04766 if(stats_log != NULL)
04767 fclose(stats_log->fp);
04768 }
04769 }
04770
04771
04772 void Stream4RestartFunction(int signal, void *foo)
04773 {
04774
04775 if(s4data.store_state_to_disk == 1)
04776 {
04777 DumpStateTable(s4data.state_file);
04778 }
04779
04780 if(s4data.track_stats_flag)
04781 {
04782 if(s4data.track_stats_flag != STATS_BINARY)
04783 fclose(session_log);
04784 else
04785 if(stats_log != NULL)
04786 fclose(stats_log->fp);
04787 }
04788 }
04789
04790
04791 static u_int32_t GetTcpTimestamp(Packet *p, u_int32_t *ts)
04792 {
04793 u_int32_t i = 0;
04794
04795 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
04796 "Getting timestamp...\n"););
04797 while(i < p->tcp_option_count && i < 40)
04798 {
04799 if(p->tcp_options[i].code == TCPOPT_TIMESTAMP)
04800 {
04801 *ts = EXTRACT_32BITS(p->tcp_options[i].data);
04802 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
04803 "Found timestamp %lu\n", *ts););
04804 return 1;
04805 }
04806
04807 i++;
04808 }
04809
04810 *ts = 0;
04811
04812 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
04813 "No timestamp...\n"););
04814
04815 return 0;
04816 }
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831 #ifdef GIDS
04832 int StoreStreamPkt(Session *ssn, Packet *p, u_int32_t pkt_seq)
04833 #else
04834 void StoreStreamPkt(Session *ssn, Packet *p, u_int32_t pkt_seq)
04835 #endif
04836 {
04837 Stream *s;
04838 StreamPacketData *spd;
04839 StreamPacketData *returned;
04840 StreamPacketData *foo;
04841 ubi_btNodePtr oldNode;
04842
04843 int direction = GetDirection(ssn, p);
04844
04845
04846 if(direction == FROM_CLIENT)
04847 {
04848 if(!s4data.reassemble_client)
04849 {
04850 #ifdef GIDS
04851 packet_added_to_stream = 0;
04852 return 0;
04853 #else
04854 return;
04855 #endif
04856 }
04857
04858 s = &ssn->client;
04859
04860 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Storing client packet (%d bytes)\n",
04861 p->pkth->caplen););
04862
04863
04864
04865
04866
04867
04868
04869
04870 if(s4data.ttl_limit)
04871 {
04872 if(ssn->ttl && p->iph->ip_ttl < 10)
04873 {
04874 if(abs(ssn->ttl - p->iph->ip_ttl) >= s4data.ttl_limit)
04875 {
04876 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04877 STREAM4_TTL_EVASION,
04878 1,
04879 0,
04880 3,
04881 STREAM4_TTL_EVASION_STR,
04882 0);
04883 #ifdef GIDS
04884 packet_added_to_stream = 0;
04885
04886 if(s4data.drop_ttl_evasion == 1)
04887 {
04888
04889 InlineDrop();
04890 }
04891 return 0;
04892 #else
04893 return;
04894 #endif
04895 }
04896 }
04897 else
04898 {
04899 ssn->ttl = p->iph->ip_ttl;
04900
04901 }
04902 }
04903 }
04904 else
04905 {
04906 if(!s4data.reassemble_server)
04907 {
04908 #ifdef GIDS
04909 packet_added_to_stream = 0;
04910 return 0;
04911 #else
04912 return;
04913 #endif
04914 }
04915
04916 s = &ssn->server;
04917
04918 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Storing server packet (%d bytes)\n",
04919 p->pkth->caplen););
04920 }
04921
04922 if ((p->tcph->th_flags == 0) &&
04923 (ssn->session_flags & SSNFLAG_ESTABLISHED))
04924 {
04925 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Dropping packet in established session "
04926 "(%d bytes) without TCP Flags\n", p->pkth->caplen););
04927
04928 if(s4data.evasion_alerts)
04929 {
04930 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04931 STREAM4_TCP_NO_ACK,
04932 1,
04933 0,
04934 3,
04935 STREAM4_TCP_NO_ACK_STR,
04936 0);
04937 }
04938
04939 #ifdef GIDS
04940 packet_added_to_stream = 0;
04941
04942 if(s4data.drop_no_tcp_on_est == 1)
04943 {
04944
04945 InlineDrop();
04946 }
04947 return 0;
04948 #else
04949 return;
04950 #endif
04951 }
04952
04953
04954 if((pkt_seq < s->last_ack) && (s->last_ack > 0) &&
04955 (direction == FROM_CLIENT))
04956 {
04957 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"EVASIVE RETRANS: pkt seq: 0x%X "
04958 "stream->last_ack: 0x%X\n", pkt_seq, s->last_ack););
04959
04960 if(s4data.state_alerts)
04961 {
04962 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04963 STREAM4_EVASIVE_RETRANS,
04964 1,
04965 0,
04966 3,
04967 STREAM4_EVASIVE_RETRANS_STR,
04968 0);
04969 }
04970
04971 #ifdef GIDS
04972 packet_added_to_stream = 0;
04973 return 0;
04974 #else
04975 return;
04976 #endif
04977 }
04978
04979
04980 if(((pkt_seq + p->dsize - s->last_ack) > s->win_size) &&
04981 (s->win_size > 0) && direction == FROM_CLIENT)
04982 {
04983
04984
04985
04986
04987
04988 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "WINDOW VIOLATION: seq: 0x%X "
04989 "last_ack: 0x%X dsize: %d " "window: 0x%X\n",
04990 pkt_seq, s->last_ack, p->dsize, s->win_size););
04991
04992 if(s4data.state_alerts)
04993 {
04994 SnortEventqAdd(GENERATOR_SPP_STREAM4,
04995 STREAM4_WINDOW_VIOLATION,
04996 1,
04997 0,
04998 3,
04999 STREAM4_WINDOW_VIOLATION_STR,
05000 0);
05001 }
05002
05003 #ifdef GIDS
05004 packet_added_to_stream = 0;
05005
05006 if(s4data.drop_out_of_window == 1)
05007 {
05008 InlineDrop();
05009 }
05010 return 0;
05011 #else
05012 return;
05013 #endif
05014 }
05015
05016 if(!WithinSessionLimits(p, s))
05017 {
05018 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[S4] Not within session limits!\n"););
05019 #ifdef GIDS
05020 packet_added_to_stream = 0;
05021 if(s4data.drop_not_in_limits == 1)
05022 {
05023
05024 InlineDrop();
05025 }
05026 return 0;
05027 #else
05028 return;
05029 #endif
05030 }
05031
05032
05033
05034 if(s->state >= ESTABLISHED)
05035 {
05036 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[A] Allocating %d bytes for "
05037 "StreamPacketData\n", sizeof(StreamPacketData)););
05038
05039 spd = (StreamPacketData *) SafeAlloc(sizeof(StreamPacketData),
05040 p->pkth->ts.tv_sec, ssn);
05041
05042 spd->seq_num = pkt_seq;
05043 spd->payload_size = p->dsize;
05044 spd->cksum = p->tcph->th_sum;
05045
05046
05047 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[A] Allocating %u bytes for packet\n",
05048 p->pkth->caplen););
05049
05050 spd->pktOrig = spd->pkt = (u_int8_t *) SafeAlloc(p->pkth->caplen + SPARC_TWIDDLE,
05051 p->pkth->ts.tv_sec, ssn);
05052 spd->pkt += SPARC_TWIDDLE;
05053 spd->pkt_size = p->pkth->caplen + SPARC_TWIDDLE;
05054
05055
05056 memcpy(spd->pkt, p->pkt, p->pkth->caplen);
05057
05058
05059 memcpy(&spd->pkth, p->pkth, sizeof(SnortPktHeader));
05060
05061
05062 spd->payload = spd->pkt + (p->data - p->pkt);
05063 }
05064 else
05065 {
05066 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "WARNING: Data on unestablished "
05067 "session state: %d)!\n", s->state););
05068 #ifdef GIDS
05069 packet_added_to_stream = 0;
05070
05071 if(s4data.drop_data_on_unest == 1)
05072 {
05073
05074 InlineDrop();
05075 }
05076 return 0;
05077 #else
05078 return;
05079 #endif
05080 }
05081
05082
05083 returned = (StreamPacketData *) ubi_sptFind(&s->data, (ubi_btItemPtr)spd);
05084
05085 if(returned != NULL)
05086 {
05087 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05088 "WARNING: returned packet not null\n"););
05089 if(returned->payload_size == p->dsize)
05090 {
05091
05092 if(s->last_ack < pkt_seq + p->dsize)
05093 {
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05116 "Checking Packet Contents versus Packet Store\n"););
05117
05118 if(returned->cksum != p->tcph->th_sum)
05119 {
05120 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "TCP Checksums not equal\n"););
05121
05122 if (s4data.reassy_method == METHOD_FAVOR_NEW)
05123 {
05124
05125 foo = (StreamPacketData *) ubi_sptRemove(&s->data,
05126 (ubi_btNodePtr) returned);
05127
05128 StreamSegmentSub(s, foo->payload_size);
05129
05130 stream4_memory_usage -= foo->pkt_size;
05131 free(foo->pktOrig);
05132
05133 stream4_memory_usage -= sizeof(StreamPacketData);
05134 free(foo);
05135
05136
05137 if(s4data.evasion_alerts)
05138 {
05139 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05140 STREAM4_EVASIVE_RETRANS_DATA,
05141 1,
05142 0,
05143 3,
05144 STREAM4_EVASIVE_RETRANS_DATA_STR,
05145 0);
05146 }
05147
05148 }
05149 else
05150 {
05151
05152 stream4_memory_usage -= spd->pkt_size;
05153 free(spd->pktOrig);
05154
05155 stream4_memory_usage -= sizeof(StreamPacketData);
05156 free(spd);
05157
05158 if(s4data.evasion_alerts)
05159 {
05160 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05161 STREAM4_EVASIVE_RETRANS_DATA,
05162 1,
05163 0,
05164 3,
05165 STREAM4_EVASIVE_RETRANS_DATA_STR,
05166 0);
05167 }
05168
05169
05170 #ifdef GIDS
05171 packet_added_to_stream = 0;
05172 return 0;
05173 #else
05174 return;
05175 #endif
05176 }
05177 }
05178 else
05179 {
05180 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05181 "TCP Checksums equal..."
05182 " returning; see comment in src\n"););
05183
05184
05185
05186
05187
05188
05189
05190
05191 stream4_memory_usage -= spd->pkt_size;
05192 free(spd->pktOrig);
05193
05194 stream4_memory_usage -= sizeof(StreamPacketData);
05195 free(spd);
05196
05197 #ifdef GIDS
05198 packet_added_to_stream = 0;
05199 return 0;
05200 #else
05201 return;
05202 #endif
05203 }
05204 }
05205 else
05206 {
05207
05208 StreamSegmentSub(s, spd->payload_size);
05209
05210 stream4_memory_usage -= spd->pkt_size;
05211 free(spd->pktOrig);
05212
05213 stream4_memory_usage -= sizeof(StreamPacketData);
05214 free(spd);
05215
05216 if(s4data.state_alerts)
05217 {
05218 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05219 STREAM4_EVASIVE_RETRANS,
05220 1,
05221 0,
05222 3,
05223 STREAM4_EVASIVE_RETRANS_STR,
05224 0);
05225 }
05226 #ifdef GIDS
05227 packet_added_to_stream = 0;
05228 return 1;
05229 #else
05230 return;
05231 #endif
05232 }
05233 }
05234 else if(returned->payload_size < p->dsize)
05235 {
05236 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05237 "Duplicate packet with forward overlap\n"););
05238
05239
05240 if(s->last_ack > pkt_seq + p->dsize)
05241 {
05242 StreamSegmentSub(s, spd->payload_size);
05243
05244
05245 stream4_memory_usage -= spd->pkt_size;
05246 free(spd->pktOrig);
05247
05248 stream4_memory_usage -= sizeof(StreamPacketData);
05249 free(spd);
05250
05251 if(s4data.evasion_alerts)
05252 {
05253 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05254 STREAM4_FORWARD_OVERLAP,
05255 1,
05256 0,
05257 3,
05258 STREAM4_FORWARD_OVERLAP_STR,
05259 0);
05260 }
05261
05262 #ifdef GIDS
05263 packet_added_to_stream = 0;
05264 return 1;
05265 #else
05266 return;
05267 #endif
05268 }
05269 else
05270 {
05271 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05272 "Adding un-ack'd duplicate packet with forward overlap\n"););
05273
05274 s->overlap_pkts++;
05275 #if 0
05276 foo = (StreamPacketData *) ubi_sptRemove(&s->data,
05277 (ubi_btNodePtr) returned);
05278
05279 StreamSegmentSub(s, foo->payload_size);
05280
05281
05282 stream4_memory_usage -= foo->pkt_size;
05283 free(foo->pkt);
05284
05285 stream4_memory_usage -= sizeof(StreamPacketData);
05286 free(foo);
05287 #endif
05288 }
05289 }
05290 else if(returned->payload_size > p->dsize)
05291 {
05292
05293 if(s->last_ack > pkt_seq + p->dsize)
05294 {
05295 StreamSegmentSub(s, spd->payload_size);
05296
05297
05298 stream4_memory_usage -= spd->pkt_size;
05299 free(spd->pktOrig);
05300
05301 stream4_memory_usage -= sizeof(StreamPacketData);
05302 free(spd);
05303
05304 if(s4data.state_alerts)
05305 {
05306 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05307 STREAM4_EVASIVE_RETRANS,
05308 1,
05309 0,
05310 3,
05311 STREAM4_EVASIVE_RETRANS_STR,
05312 0);
05313 }
05314 #ifdef GIDS
05315 packet_added_to_stream = 0;
05316 return 1;
05317 #else
05318 return;
05319 #endif
05320 }
05321 else
05322 {
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05340 "Checking if we are retranmitting too fast\n"););
05341 if(RetransTooFast(&returned->pkth.ts,
05342 (struct timeval *) &p->pkth->ts))
05343 {
05344 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05345 "Generating packets retranmissions "
05346 "faster than we should\n"););
05347
05348 stream4_memory_usage -= spd->pkt_size;
05349 free(spd->pktOrig);
05350
05351 stream4_memory_usage -= sizeof(StreamPacketData);
05352 free(spd);
05353
05354 if(s4data.evasion_alerts)
05355 {
05356 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05357 STREAM4_EVASIVE_RETRANS_DATASPLIT,
05358 1,
05359 0,
05360 3,
05361 STREAM4_EVASIVE_RETRANS_DATASPLIT_STR,
05362 0);
05363
05364 }
05365 #ifdef GIDS
05366 packet_added_to_stream = 0;
05367 return 0;
05368 #else
05369 return;
05370 #endif
05371 }
05372 #if 0
05373 else
05374 {
05375 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05376 "Replacing un-ack'd segment in Packet Store\n"););
05377
05378 foo = (StreamPacketData *) ubi_sptRemove(&s->data,
05379 (ubi_btNodePtr) returned);
05380
05381 stream4_memory_usage -= foo->pkt_size;
05382 free(foo->pkt);
05383
05384 stream4_memory_usage -= sizeof(StreamPacketData);
05385 free(foo);
05386 }
05387 #endif
05388 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05389 "Adding un-ack'd duplicate packet with backwards overlap\n"););
05390 s->overlap_pkts++;
05391
05392 }
05393 }
05394 }
05395 else
05396 {
05397
05398
05399 OverlapData overlapData;
05400 overlapData.seq_low = pkt_seq;
05401 overlapData.seq_hi = pkt_seq + spd->pkt_size;
05402 if (ubi_trCheck(&s->data, OverlapCompareFunc, (void *)&overlapData))
05403 {
05404 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05405 "Adding non-duplicate packet with overlap\n"););
05406 s->overlap_pkts++;
05407 }
05408 }
05409
05410
05411
05412 {
05413 u_int32_t timestamp;
05414 if (GetTcpTimestamp(p, ×tamp) == 1)
05415 {
05416 if ((timestamp == 0) &&
05417 (ssn->session_flags & SSNFLAG_ESTABLISHED) &&
05418 ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == TH_ACK))
05419 {
05420 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
05421 "Not inserting packet with 0 timestamp\n"););
05422
05423 stream4_memory_usage -= spd->pkt_size;
05424 free(spd->pktOrig);
05425
05426 stream4_memory_usage -= sizeof(StreamPacketData);
05427 free(spd);
05428
05429 if(s4data.state_alerts)
05430 {
05431 SnortEventqAdd(GENERATOR_SPP_STREAM4,
05432 STREAM4_ZERO_TIMESTAMP,
05433 1,
05434 0,
05435 3,
05436 STREAM4_ZERO_TIMESTAMP_STR,
05437 0);
05438 }
05439
05440 #ifdef GIDS
05441 packet_added_to_stream = 0;
05442 printf("DROP: ZERO TIMESTAMP\n");
05443 InlineDrop();
05444 return 0;
05445 #else
05446 return;
05447 #endif
05448 }
05449 }
05450 }
05451
05452 if(ubi_sptInsert(&s->data,(ubi_btNodePtr)spd,(ubi_btNodePtr)spd, &oldNode)
05453 == ubi_trFALSE)
05454 {
05455 LogMessage("sptInsert failed, that sucks\n");
05456
05457
05458 stream4_memory_usage -= spd->pkt_size;
05459 free(spd->pktOrig);
05460
05461 stream4_memory_usage -= sizeof(StreamPacketData);
05462 free(spd);
05463 #ifdef GIDS
05464 packet_added_to_stream = 0;
05465 return 0;
05466 #else
05467 return;
05468 #endif
05469 }
05470
05471 p->packet_flags |= PKT_STREAM_INSERT;
05472
05473 #ifdef GIDS
05474 packet_added_to_stream = 1;
05475 return 1;
05476 #else
05477 return;
05478 #endif
05479 }
05480
05481
05482 void FlushStream(Stream *s, Packet *p, int direction)
05483 {
05484 int stream_size;
05485
05486 int gotevent = 0;
05487
05488 sfPerf.sfBase.iStreamFlushes++;
05489
05490 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "FlushStream Entered:"
05491 "last_ack(%u) base_seq(%u) trCount(%u)\ng",
05492 s->last_ack, s->base_seq, ubi_trCount(&s->data)););
05493
05494 #ifdef GIDS
05495 if(!s4data.stream4inline_mode)
05496 {
05497 #endif
05498 stream_size = s->last_ack - s->base_seq;
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509 if(stream_size >= MAX_STREAM_SIZE)
05510 {
05511 #ifdef DEBUG
05512 DebugMessage(DEBUG_STREAM,
05513 "stream_size(%u) > MAX_STREAM_SIZE(%u)\n",
05514 stream_size, MAX_STREAM_SIZE);
05515
05516 DebugMessage(DEBUG_STREAM,
05517 "Adjusting s->base_seq(%u) -> %u %u\n",
05518 s->base_seq, s->last_ack - MAX_STREAM_SIZE,
05519 s->last_ack - (MAX_STREAM_SIZE));
05520
05521 #endif
05522 stream_size = MAX_STREAM_SIZE - 1;
05523 s->base_seq = s->last_ack - stream_size;
05524 }
05525
05526 if(stream_size > 0 && ubi_trCount(&s->data))
05527 {
05528
05529 if(BuildPacket(s, stream_size, p, direction))
05530 {
05531 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Passing large packet "
05532 "on 0 size stream cache\n"););
05533 return;
05534 }
05535
05536
05537
05538 if(stream_pkt->dsize > 0)
05539 {
05540 gotevent = Preprocess(stream_pkt);
05541
05542 if(s4data.zero_flushed_packets)
05543 bzero(stream_pkt->data, stream_pkt->dsize);
05544
05545 if ( p->ssnptr )
05546 {
05547
05548 Session *ssn = p->ssnptr;
05549
05550 ssn->alert_count = 0;
05551 }
05552
05553 if(gotevent)
05554 {
05555 LogStream(s);
05556 }
05557 }
05558
05559 SegmentCleanTraverse(s);
05560 return;
05561 }
05562 else
05563 {
05564 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Passing large packet on "
05565 "0 size stream cache\n"););
05566 }
05567
05568 #ifdef GIDS
05569 }
05570 #endif
05571
05572 s->bytes_tracked = 0;
05573 s->overlap_pkts = 0;
05574 DeleteSpd(&s->data);
05575 }
05576
05577
05578 #ifdef GIDS
05579
05580
05581
05582 void TruncStream(Stream *s, Packet *p)
05583 {
05584 u_int16_t bytes_to_clear = 0;
05585 #ifdef DEBUG
05586 char flagbuf[9];
05587 #endif
05588
05589
05590 s4data.stop_traverse = 0;
05591
05592 if(s->bytes_tracked && ubi_trCount(&s->data))
05593 {
05594
05595 bytes_to_clear = s->bytes_tracked - s4data.stream4inline_window_size;
05596
05597 #ifdef DEBUG
05598 CreateTCPFlagString(p, flagbuf);
05599 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"P: %5d -> %5d %s: ", p->sp, p->dp, flagbuf););
05600 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"stream_size: %5d: Going to try to truncate %d bytes\n", s->bytes_tracked, bytes_to_clear););
05601 #endif
05602
05603
05604
05605 SegmentTruncTraverse(s, bytes_to_clear);
05606 }
05607 }
05608 #endif
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624 int AlertFlushStream(Packet *p)
05625 {
05626 Session *ssn;
05627 Stream *stream;
05628 int nodecount = 0;
05629
05630 if (!p->ssnptr)
05631 return 0;
05632
05633 ssn = p->ssnptr;
05634
05635 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Flushing stream due to an alert!\n"););
05636
05637 #ifdef GIDS
05638
05639
05640
05641
05642
05643 if(s4data.stream4inline_mode && s4data.enforce_state && iv.drop && p->tcph != NULL)
05644 {
05645 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "okay, try to drop the session.\n"););
05646
05647 if(ssn == NULL)
05648 {
05649 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Nothing to Flush!\n"););
05650 return 0;
05651 }
05652 DeleteSession(ssn, p->pkth->ts.tv_sec);
05653 return(0);
05654 }
05655 #endif
05656
05657 if(NotForStream4(p))
05658 {
05659 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Don't Flush a Rebuilt Stream\n"););
05660 return 0;
05661 }
05662
05663 if(!s4data.flush_on_alert)
05664 {
05665 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Don't Flush a Rebuilt Stream on Alert from indviidual packet\n"););
05666 return 0;
05667 }
05668
05669 if(ssn == NULL)
05670 {
05671 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Nothing to Flush!\n"););
05672 return 0;
05673 }
05674
05675 if(GetDirection(ssn, p) == FROM_SERVER)
05676 {
05677 stream = &ssn->server;
05678
05679 if(s4data.reassemble_server)
05680 {
05681 FlushStream(stream, p, NO_REVERSE);
05682 }
05683 else
05684 {
05685
05686
05687
05688
05689 DeleteSpd(&stream->data);
05690 stream->bytes_tracked = 0;
05691 stream->overlap_pkts = 0;
05692 }
05693 }
05694 else
05695 {
05696 stream = &ssn->client;
05697
05698 if(s4data.reassemble_client)
05699 {
05700 FlushStream(stream, p, NO_REVERSE);
05701 }
05702 else
05703 {
05704
05705
05706
05707
05708 DeleteSpd(&stream->data);
05709 stream->bytes_tracked = 0;
05710 stream->overlap_pkts = 0;
05711 }
05712 }
05713
05714 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[AFS] Bytes Tracked: %u\n",
05715 stream->bytes_tracked););
05716 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[AFS] Bytes Tracked: %u\n",
05717 stream->bytes_tracked););
05718
05719 if(p->tcph)
05720 {
05721 #ifdef GIDS
05722
05723
05724 if(!s4data.stream4inline_mode)
05725 {
05726 #endif
05727 stream->base_seq = ntohl(p->tcph->th_seq) + p->dsize;
05728 stream->last_ack = stream->base_seq;
05729 #ifdef GIDS
05730 }
05731 #endif
05732 }
05733
05734 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Moved the base_seq to %u!\n",
05735 stream->base_seq););
05736
05737 return nodecount;
05738 }
05739
05740
05741
05742
05743
05744
05745
05746
05747
05748
05749
05750
05751 int LogStream(Stream *s)
05752 {
05753 int nodecount = 0;
05754
05755 if((pv.log_bitmap & LOG_TCPDUMP) && s4data.log_flushed_streams)
05756 {
05757 nodecount = ubi_trCount(&s->data);
05758 if (s4data.reassy_method == METHOD_FAVOR_OLD)
05759 {
05760 (void)ubi_trTraverse(&s->data, LogTraverse, s);
05761 }
05762 else
05763 {
05764 (void)ubi_trTraverseReverse(&s->data, LogTraverse, s);
05765 }
05766 }
05767
05768 return nodecount;
05769 }
05770
05771
05772
05773 void InitStream4Pkt()
05774 {
05775 stream_pkt->pkth = calloc(sizeof(SnortPktHeader)+
05776 ETHERNET_HEADER_LEN +
05777 SPARC_TWIDDLE + IP_MAXPACKET,
05778 sizeof(char));
05779
05780 stream_pkt->pkt = ((u_int8_t *)stream_pkt->pkth) + sizeof(SnortPktHeader);
05781 stream_pkt->eh = (EtherHdr *)((u_int8_t *)stream_pkt->pkt + SPARC_TWIDDLE);
05782 stream_pkt->iph =
05783 (IPHdr *)((u_int8_t *)stream_pkt->eh + ETHERNET_HEADER_LEN);
05784 stream_pkt->tcph = (TCPHdr *)((u_int8_t *)stream_pkt->iph + IP_HEADER_LEN);
05785
05786 stream_pkt->data = (u_int8_t *)stream_pkt->tcph + TCP_HEADER_LEN;
05787
05788
05789
05790
05791
05792
05793
05794
05795 stream_pkt->eh->ether_type = htons(0x0800);
05796 SET_IP_VER(stream_pkt->iph, 0x4);
05797 SET_IP_HLEN(stream_pkt->iph, 0x5);
05798 stream_pkt->iph->ip_proto = IPPROTO_TCP;
05799 stream_pkt->iph->ip_ttl = 0xF0;
05800 stream_pkt->iph->ip_len = 0x5;
05801 stream_pkt->iph->ip_tos = 0x10;
05802
05803 SET_TCP_OFFSET(stream_pkt->tcph,0x5);
05804 stream_pkt->tcph->th_flags = TH_PUSH|TH_ACK;
05805 }
05806
05807
05808
05809
05810
05811
05812
05813
05814
05815
05816
05817
05818
05819 int BuildPacket(Stream *s, u_int32_t stream_size, Packet *p, int direction)
05820 {
05821 BuildData bd;
05822 unsigned short zero_size = 1500;
05823 Session *ssn;
05824 u_int32_t ip_len;
05825 ip_len = stream_size + IP_HEADER_LEN + TCP_HEADER_LEN;
05826
05827 stream_pkt->pkth->ts.tv_sec = p->pkth->ts.tv_sec;
05828 stream_pkt->pkth->ts.tv_usec = p->pkth->ts.tv_usec;
05829
05830 stream_pkt->pkth->caplen = ip_len + ETHERNET_HEADER_LEN;
05831 stream_pkt->pkth->len = stream_pkt->pkth->caplen;
05832
05833 stream_pkt->iph->ip_len = htons((u_short) ip_len);
05834
05835 if(direction == REVERSE)
05836 {
05837 if(p->eh != NULL)
05838 {
05839 memcpy(stream_pkt->eh->ether_dst, p->eh->ether_src, 6);
05840 memcpy(stream_pkt->eh->ether_src, p->eh->ether_dst, 6);
05841 }
05842
05843 stream_pkt->tcph->th_sport = p->tcph->th_dport;
05844 stream_pkt->tcph->th_dport = p->tcph->th_sport;
05845 stream_pkt->iph->ip_src.s_addr = p->iph->ip_dst.s_addr;
05846 stream_pkt->iph->ip_dst.s_addr = p->iph->ip_src.s_addr;
05847 stream_pkt->sp = p->dp;
05848 stream_pkt->dp = p->sp;
05849 }
05850 else
05851 {
05852 if(p->eh != NULL)
05853 {
05854 memcpy(stream_pkt->eh->ether_dst, p->eh->ether_dst, 6);
05855 memcpy(stream_pkt->eh->ether_src, p->eh->ether_src, 6);
05856 }
05857
05858 stream_pkt->tcph->th_sport = p->tcph->th_sport;
05859 stream_pkt->tcph->th_dport = p->tcph->th_dport;
05860 stream_pkt->iph->ip_src.s_addr = p->iph->ip_src.s_addr;
05861 stream_pkt->iph->ip_dst.s_addr = p->iph->ip_dst.s_addr;
05862 stream_pkt->sp = p->sp;
05863 stream_pkt->dp = p->dp;
05864 }
05865
05866 stream_pkt->tcph->th_seq = p->tcph->th_seq;
05867 stream_pkt->tcph->th_ack = p->tcph->th_ack;
05868 stream_pkt->tcph->th_win = p->tcph->th_win;
05869
05870 s4data.stop_traverse = 0;
05871
05872 bd.stream = s;
05873 bd.buf = stream_pkt->data;
05874 bd.total_size = 0;
05875
05876
05877 #ifdef GIDS
05878 if(!s4data.stream4inline_mode)
05879 #endif
05880 if (s4data.reassy_method == METHOD_FAVOR_OLD)
05881 {
05882 (void)ubi_trTraverse(&s->data, TraverseFunc, &bd);
05883 }
05884 else
05885 {
05886 (void)ubi_trTraverseReverse(&s->data, TraverseFunc, &bd);
05887 }
05888 #ifdef GIDS
05889 else
05890 {
05891 if (s4data.reassy_method == METHOD_FAVOR_OLD)
05892 {
05893
05894 if(s->base_seq > s->last_ack
05895 &&
05896 ((s->base_seq - s->last_ack) > (MAX_STREAM_SIZE * 2)))
05897 {
05898 (void)ubi_trTraverse(&s->data, TraverseFuncRebuildAllWrap, &bd);
05899 }
05900 else
05901 {
05902 (void)ubi_trTraverse(&s->data, TraverseFuncRebuildAll, &bd);
05903 }
05904 }
05905 else
05906 {
05907
05908 if(s->base_seq > s->last_ack
05909 &&
05910 ((s->base_seq - s->last_ack) > (MAX_STREAM_SIZE * 2)))
05911 {
05912 (void)ubi_trTraverseReverse(&s->data, TraverseFuncRebuildAllWrap, &bd);
05913 }
05914 else
05915 {
05916 (void)ubi_trTraverseReverse(&s->data, TraverseFuncRebuildAll, &bd);
05917 }
05918 }
05919 }
05920 #endif
05921
05922 if(bd.total_size < stream_size)
05923 {
05924 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "bd.total_size(%u) < stream_size(%u):"
05925 "Incomplete segment -- packet loss or weird\n",
05926 bd.total_size, stream_size););
05927
05928
05929
05930 if(bd.total_size == 0)
05931 {
05932 stream_pkt->dsize = 0;
05933 return -1;
05934 }
05935 }
05936 else if(bd.total_size > stream_size)
05937 {
05938 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "stream_size(%u) < bd.total_size(%u):"
05939 "Overlapping segments -- packet loss or weird\n",
05940 stream_size, bd.total_size););
05941 }
05942
05943
05944
05945
05946 if(s4data.stop_traverse)
05947 {
05948 if(s4data.stop_seq < s->base_seq)
05949 {
05950 stream_size = s->base_seq - s4data.stop_seq;
05951 }
05952 else
05953 {
05954 stream_size = s4data.stop_seq - s->base_seq;
05955 }
05956
05957
05958
05959
05960
05961 if(stream_size >= MAX_STREAM_SIZE)
05962 {
05963 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Truncating %d bytes from stream",
05964 stream_size - MAX_STREAM_SIZE););
05965
05966 stream_size = MAX_STREAM_SIZE - 1;
05967 }
05968
05969 ip_len = IP_HEADER_LEN + TCP_HEADER_LEN + stream_size;
05970
05971 stream_pkt->dsize = (unsigned short)stream_size;
05972
05973 stream_pkt->pkth->caplen = ETHERNET_HEADER_LEN + ip_len;
05974 stream_pkt->pkth->len = stream_pkt->pkth->caplen;
05975
05976 stream_pkt->iph->ip_len = htons( (u_short) ip_len );
05977 }
05978 else
05979 {
05980 stream_pkt->dsize = (unsigned short)stream_size;
05981 }
05982
05983 s4data.stop_traverse = 0;
05984
05985 stream_pkt->tcp_option_count = 0;
05986 stream_pkt->tcp_lastopt_bad = 0;
05987 stream_pkt->packet_flags = (PKT_REBUILT_STREAM|PKT_STREAM_EST);
05988
05989 ssn = p->ssnptr;
05990 stream_pkt->ssnptr = p->ssnptr;
05991
05992 stream_pkt->streamptr = (void *) s;
05993
05994 if(stream_pkt->sp == ssn->client.port)
05995 {
05996 stream_pkt->packet_flags |= PKT_FROM_CLIENT;
05997 }
05998 else
05999 {
06000 stream_pkt->packet_flags |= PKT_FROM_SERVER;
06001 }
06002
06003 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06004 "Built packet to %s from %x with %u byte payload, "
06005 "Direction: %s\n",
06006 inet_ntoa(stream_pkt->iph->ip_src),
06007 stream_pkt->iph->ip_dst,
06008 stream_pkt->dsize,
06009 (stream_pkt->packet_flags & PKT_FROM_SERVER)
06010 ? "from_server" : "from_client"););
06011
06012 pc.rebuilt_tcp++;
06013
06014 #ifdef DEBUG
06015 if(stream_pkt->packet_flags & PKT_FROM_CLIENT)
06016 {
06017 DebugMessage(DEBUG_STREAM, "packet is from client!\n");
06018 }
06019
06020 if(stream_pkt->packet_flags & PKT_FROM_SERVER)
06021 {
06022 DebugMessage(DEBUG_STREAM, "packet is from server!\n");
06023 }
06024
06025 if (DEBUG_STREAM & GetDebugLevel())
06026 {
06027 ClearDumpBuf();
06028 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
06029 PrintIPPkt(stdout, IPPROTO_TCP, stream_pkt);
06030 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
06031 ClearDumpBuf();
06032
06033
06034
06035
06036 }
06037 #endif
06038
06039
06040 if(abs(stream_pkt->dsize - bd.total_size) >= s4data.flush_data_diff_size)
06041 {
06042
06043 if(s4data.zero_flushed_packets)
06044 {
06045
06046 if(stream_size && stream_size < zero_size)
06047 {
06048 zero_size = (unsigned short)stream_size;
06049 }
06050
06051 if(zero_size > 0)
06052 bzero(stream_pkt->data, zero_size);
06053 }
06054 }
06055
06056 return 0;
06057 }
06058
06059
06060 int CheckPorts(u_int16_t port1, u_int16_t port2)
06061 {
06062 switch(s4_emergency.status)
06063 {
06064 case OPS_NORMAL:
06065 if(s4data.assemble_ports[port1] || s4data.assemble_ports[port2])
06066 {
06067 return 1;
06068 }
06069 break;
06070
06071 case OPS_SELF_PRESERVATION:
06072 if(s4data.emergency_ports[port1] || s4data.emergency_ports[port2])
06073 {
06074 return 1;
06075 }
06076 break;
06077 }
06078
06079 return 0;
06080 }
06081
06082
06083 void OpenStatsFile()
06084 {
06085 time_t curr_time;
06086 char logdir[STD_BUF];
06087 int value;
06088 StatsLogHeader hdr;
06089
06090 bzero(logdir, STD_BUF);
06091 curr_time = time(NULL);
06092
06093 if(stats_log->filename[0] == '/')
06094 value = snprintf(logdir, STD_BUF, "%s.%lu", stats_log->filename,
06095 (unsigned long)curr_time);
06096 else
06097 value = snprintf(logdir, STD_BUF, "%s/%s.%lu", pv.log_dir,
06098 stats_log->filename, (unsigned long)curr_time);
06099
06100 if(value == -1)
06101 {
06102 FatalError("ERROR: log file logging path and file name are "
06103 "too long, aborting!\n");
06104 }
06105
06106 printf("stream4:OpenStatsFile() Opening %s\n", logdir);
06107
06108 if((stats_log->fp=fopen(logdir, "w+")) == NULL)
06109 {
06110 FatalError("stream4:OpenStatsFile(%s): %s\n", logdir, strerror(errno));
06111 }
06112
06113 hdr.magic = STATS_MAGIC;
06114 hdr.version_major = 1;
06115 hdr.version_minor = 81;
06116 hdr.timezone = 1;
06117
06118 if(fwrite((char *)&hdr, sizeof(hdr), 1, stats_log->fp) != 1)
06119 {
06120 FatalError("stream4:OpenStatsFile(): %s\n", strerror(errno));
06121 }
06122
06123 fflush(stats_log->fp);
06124
06125
06126 if(stats_log->filename != NULL)
06127 {
06128 free(stats_log->filename);
06129
06130 stats_log->filename = strdup(logdir);
06131 }
06132
06133 return;
06134 }
06135
06136
06137
06138 void WriteSsnStats(BinStats *bs)
06139 {
06140 fwrite(bs, sizeof(BinStats), 1, stats_log->fp);
06141 fflush(stats_log->fp);
06142 return;
06143 }
06144
06145 static void TcpAction(Session *ssn, Packet *p, int action, int direction,
06146 u_int32_t pkt_seq, u_int32_t pkt_ack)
06147 {
06148 if(action == ACTION_NOTHING)
06149 {
06150 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "returning -- action nothing\n"););
06151 return;
06152 }
06153 else
06154 {
06155 if((action & ACTION_SET_SERVER_ISN) &&
06156 (ssn->session_flags & SSNFLAG_MIDSTREAM))
06157 {
06158
06159
06160
06161
06162
06163
06164 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06165 "Midstream session SYN-ACK; setting seqs;"
06166 "removing midstream notification\n"););
06167 ssn->client.last_ack = pkt_ack;
06168 ssn->server.last_ack = pkt_seq;
06169
06170 ssn->server.base_seq = ssn->server.last_ack;
06171 ssn->client.base_seq = ssn->client.last_ack;
06172
06173
06174
06175
06176
06177 }
06178 else if(action & ACTION_SET_SERVER_ISN)
06179 {
06180 ssn->server.isn = pkt_seq;
06181 ssn->client.win_size = ntohs(p->tcph->th_win);
06182
06183 if(pkt_ack == (ssn->client.isn+1))
06184 {
06185 ssn->client.last_ack = ssn->client.isn+1;
06186 }
06187 else
06188 {
06189
06190 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06191 "WARNING: Got unexpected SYN ACK from server!\n");
06192 DebugMessage(DEBUG_STREAM,
06193 "expected: 0x%X received: 0x%X\n"););
06194 ssn->client.last_ack = pkt_ack;
06195 }
06196 }
06197
06198
06199 if(action & ACTION_COMPLETE_TWH)
06200 {
06201
06202
06203
06204
06205 p->packet_flags |= PKT_STREAM_TWH;
06206
06207
06208 if(pkt_ack == ssn->server.isn+1)
06209 {
06210 ssn->server.last_ack = ssn->server.isn+1;
06211 }
06212 else
06213 {
06214 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "WARNING: Fishy TWH from client "
06215 "(0x%X:%d->0x%X:%d) (ack: 0x%X isn: 0x%X)\n",
06216 p->iph->ip_src.s_addr, p->sp, p->iph->ip_dst.s_addr,
06217 p->dp, pkt_ack, ssn->server.isn););
06218
06219 ssn->server.last_ack = pkt_ack;
06220 }
06221
06222 ssn->server.base_seq = ssn->server.last_ack;
06223 ssn->client.base_seq = ssn->client.last_ack;
06224 }
06225
06226
06227
06228
06229
06230 if(action & ACTION_DATA_ON_SYN)
06231 {
06232 if(p->tcph->th_flags & TH_SYN)
06233 {
06234
06235 if(s4data.evasion_alerts)
06236 {
06237 SnortEventqAdd(GENERATOR_SPP_STREAM4,
06238 STREAM4_DATA_ON_SYN,
06239 1,
06240 0,
06241 3,
06242 STREAM4_DATA_ON_SYN_STR,
06243 0);
06244 }
06245
06246 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06247 "WARNING: Data on SYN packet!\n"););
06248 return;
06249 }
06250 }
06251
06252 if(action & ACTION_INC_PORT)
06253 {
06254 ssn->client.port++;
06255 }
06256
06257
06258 if(action & ACTION_ACK_CLIENT_DATA)
06259 {
06260 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06261 "client.base_seq(%u) client.last_ack(%u) offset(%u)\n",
06262 ssn->client.base_seq,ssn->client.last_ack,
06263 (ssn->client.last_ack - ssn->client.base_seq)););
06264
06265 if((p->tcph->th_flags & TH_RST) && pkt_ack == 0)
06266 {
06267
06268
06269 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[R] Reset Handled\n"););
06270 }
06271
06272 else if((ssn->session_flags & SSNFLAG_CLIENT_FIN) &&
06273 (ssn->client.next_seq + 1 == pkt_ack))
06274 {
06275
06276
06277 ssn->client.last_ack = pkt_ack - 1;
06278 }
06279 else if(SEQ_LT(ssn->client.last_ack, pkt_ack))
06280 {
06281
06282
06283
06284
06285
06286 ssn->client.last_ack = pkt_ack;
06287 }
06288
06289 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "client.base_seq(%u) "
06290 "client.last_ack(%u) client.next_seq(%u)\n",
06291 ssn->client.base_seq,ssn->client.last_ack,
06292 ssn->client.next_seq););
06293
06294 if(ssn->session_flags & SSNFLAG_ESTABLISHED)
06295 {
06296 Stream *s;
06297
06298 s = &ssn->client;
06299
06300 #ifdef GIDS
06301 if((!s4data.stream4inline_mode &&
06302 (ssn->client.last_ack - ssn->client.base_seq) > ssn->flush_point &&
06303 ubi_trCount(&s->data) > 1) ||
06304 (s4data.stream4inline_mode &&
06305 (ssn->client.bytes_tracked > (ssn->flush_point + s4data.stream4inline_window_size)) &&
06306 ubi_trCount(&s->data) > 1))
06307 #else
06308 if((ssn->client.last_ack - ssn->client.base_seq) > ssn->flush_point
06309 && ubi_trCount(&s->data) > 1)
06310 #endif
06311 {
06312 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06313 "Flushing Client packet buffer "
06314 "(%d bytes a: 0x%X b: 0x%X pkts: %d)\n",
06315 (ssn->client.last_ack - ssn->client.base_seq),
06316 ssn->client.last_ack, ssn->client.base_seq,
06317 ubi_trCount(&s->data)););
06318
06319 if(s4data.reassemble_client)
06320 {
06321 #ifdef GIDS
06322 if(!s4data.stream4inline_mode)
06323 {
06324 #endif
06325 FlushStream(&ssn->client, p, REVERSE);
06326 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "after truncate: ssn->client.base_seq(%u) = ssn->client.last_ack = %u\n", ssn->client.base_seq, ssn->client.last_ack););
06327 ssn->client.base_seq = ssn->client.last_ack;
06328 #ifdef GIDS
06329 }
06330 else
06331 TruncStream(&ssn->client, p);
06332 #endif
06333 }
06334 }
06335 else
06336 {
06337 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06338 "%d (%d) bytes to go before we flush: "
06339 "(%d) segments stored\n",
06340 (ssn->flush_point-
06341 (ssn->client.last_ack - ssn->client.base_seq)),
06342 (ssn->client.last_ack - ssn->client.base_seq),
06343 ubi_trCount(&ssn->client.data)););
06344 }
06345 }
06346 #ifdef GIDS
06347 if(s4data.stream4inline_mode)
06348 {
06349 if(ssn->client.last_ack > ssn->client.base_seq)
06350 {
06351 if((ssn->client.last_ack - ssn->client.base_seq) >= (2 * s4data.stream4inline_window_size))
06352 {
06353 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ: client: adjusting base_seq because last_ack(%u) "
06354 "is way larger than base_seq(%u): > 2 * window_size(%d)\n",
06355 ssn->client.last_ack, ssn->client.base_seq,
06356 s4data.stream4inline_window_size););
06357
06358 ssn->client.base_seq = ssn->client.last_ack - s4data.stream4inline_window_size;
06359
06360 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ: base_seq is now %u\n",
06361 ssn->client.base_seq););
06362 }
06363 }
06364
06365
06366
06367
06368
06369
06370
06371
06372
06373
06374
06375
06376
06377 else if(ssn->client.base_seq > ssn->client.last_ack)
06378 {
06379
06380 if((ssn->client.base_seq - ssn->client.last_ack) > (MAX_STREAM_SIZE * 2))
06381 {
06382 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(client) base_seq %u > last_ack %u, diff (%u)\n", ssn->client.base_seq, ssn->client.last_ack, ssn->client.base_seq - ssn->client.last_ack););
06383
06384 if(((MAX_SEQ_NUM - ssn->client.base_seq) + ssn->client.last_ack) >= (2 * s4data.stream4inline_window_size))
06385 {
06386
06387 ssn->client.base_seq = ssn->client.last_ack - s4data.stream4inline_window_size;
06388
06389 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(client) base_seq is now %u\n", ssn->client.base_seq););
06390 }
06391 else
06392 {
06393 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(client, no wrap) base_seq %u > last_ack %u, diff (%u)\n", ssn->client.base_seq, ssn->client.last_ack, ssn->client.base_seq - ssn->client.last_ack););
06394 }
06395 }
06396 else
06397 {
06398 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(client) base_seq %u > last_ack %u\n", ssn->client.base_seq, ssn->client.last_ack););
06399 }
06400 }
06401 }
06402 #endif
06403 }
06404
06405
06406 if(action & ACTION_ACK_SERVER_DATA)
06407 {
06408 if((p->tcph->th_flags & TH_RST) && pkt_ack == 0)
06409 {
06410
06411
06412 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[R] Reset Handled\n"););
06413 }
06414 else if((ssn->session_flags & SSNFLAG_CLIENT_FIN) &&
06415 (ssn->server.next_seq + 1 == pkt_ack))
06416 {
06417
06418 ssn->server.last_ack = pkt_ack - 1;
06419 }
06420 else if(SEQ_LT(ssn->server.last_ack, pkt_ack))
06421 {
06422 ssn->server.last_ack = pkt_ack;
06423 }
06424
06425 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "server.base_seq(%u) "
06426 "server.last_ack(%u) server.next_seq(%u)\n",
06427 ssn->server.base_seq,ssn->server.last_ack,
06428 ssn->server.next_seq););
06429
06430 if(ssn->session_flags & SSNFLAG_ESTABLISHED)
06431 {
06432 Stream *s;
06433
06434 s = &ssn->server;
06435
06436 #ifdef GIDS
06437 if((!s4data.stream4inline_mode &&
06438 ((ssn->server.last_ack - ssn->server.base_seq) > ssn->flush_point &&
06439 ubi_trCount(&s->data) > 1)) ||
06440 (s4data.stream4inline_mode &&
06441 (ssn->server.bytes_tracked > (ssn->flush_point + s4data.stream4inline_window_size)) &&
06442 ubi_trCount(&s->data) > 1))
06443 #else
06444 if((ssn->server.last_ack - ssn->server.base_seq) > ssn->flush_point
06445 && ubi_trCount(&s->data) > 1)
06446 #endif
06447 {
06448 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06449 "Flushing Server packet buffer "
06450 "(%d bytes a: 0x%X b: 0x%X)\n",
06451 (ssn->server.last_ack - ssn->server.base_seq),
06452 ssn->server.last_ack, ssn->server.base_seq););
06453
06454 if(s4data.reassemble_server)
06455 {
06456 #ifdef GIDS
06457 if(!s4data.stream4inline_mode)
06458 {
06459 #endif
06460 FlushStream(&ssn->server, p, REVERSE);
06461 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "after trunc: ssn->server.base_seq(%u) = ssn->server.last_ack = %u\n", ssn->server.base_seq, ssn->server.last_ack););
06462 ssn->server.base_seq = ssn->server.last_ack;
06463 #ifdef GIDS
06464 }
06465 else
06466 TruncStream(&ssn->server, p);
06467 #endif
06468 }
06469 }
06470 }
06471 #ifdef GIDS
06472 if(s4data.stream4inline_mode)
06473 {
06474 if(ssn->server.last_ack > ssn->server.base_seq)
06475 {
06476 if((ssn->server.last_ack - ssn->server.base_seq) >= (2 * s4data.stream4inline_window_size))
06477 {
06478 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ: server: adjusting base_seq because last_ack(%u)"
06479 "is way larger than base_seq(%u): > 2 * window_size(%d)\n",
06480 ssn->server.last_ack, ssn->server.base_seq,
06481 s4data.stream4inline_window_size););
06482
06483 ssn->server.base_seq = ssn->server.last_ack - s4data.stream4inline_window_size;
06484
06485 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ: base_seq is now %u\n",
06486 ssn->server.base_seq););
06487 }
06488 }
06489
06490 else if(ssn->server.base_seq > ssn->server.last_ack)
06491 {
06492
06493 if((ssn->server.base_seq - ssn->server.last_ack) > (MAX_STREAM_SIZE * 2))
06494 {
06495 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(server) base_seq %u > last_ack %u, diff (%u)\n", ssn->server.base_seq, ssn->server.last_ack, ssn->server.base_seq - ssn->server.last_ack););
06496
06497
06498 if(((MAX_SEQ_NUM - ssn->server.base_seq) + ssn->server.last_ack) >= (2 * s4data.stream4inline_window_size))
06499 {
06500 ssn->server.base_seq = ssn->server.last_ack - s4data.stream4inline_window_size;
06501
06502 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ: base_seq is now %u\n", ssn->server.base_seq););
06503 }
06504 else
06505 {
06506 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(server, no wrap) base_seq %u > last_ack %u, diff (%u)\n", ssn->server.base_seq, ssn->server.last_ack, ssn->server.base_seq - ssn->server.last_ack););
06507 }
06508 }
06509 else
06510 {
06511 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "BASE_SEQ:(server) base_seq %u > last_ack %u\n", ssn->server.base_seq, ssn->server.last_ack););
06512 }
06513 }
06514 }
06515 #endif
06516 }
06517
06518 if(s4data.ps_alerts && (action & ACTION_ALERT_NMAP_FINGERPRINT))
06519 {
06520 SnortEventqAdd(GENERATOR_SPP_STREAM4,
06521 STREAM4_STEALTH_NMAP_FINGERPRINT,
06522 1,
06523 0,
06524 3,
06525 STREAM4_STEALTH_NMAP_FINGERPRINT_STR,
06526 0);
06527 return;
06528 }
06529
06530 if(action & ACTION_FLUSH_SERVER_STREAM)
06531 {
06532 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "flushing server stream, ending "
06533 "session: %d\n", s4data.reassemble_server););
06534
06535 if(s4data.reassemble_server)
06536 {
06537 if(direction == FROM_SERVER)
06538 {
06539 FlushStream(&ssn->server, p, NO_REVERSE);
06540 }
06541 else
06542 {
06543 FlushStream(&ssn->server, p, REVERSE);
06544 }
06545 }
06546
06547 p->packet_flags |= PKT_STREAM_EST;
06548 }
06549
06550 if(action & ACTION_FLUSH_CLIENT_STREAM)
06551 {
06552 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "flushing client stream, ending "
06553 "session\n"););
06554
06555 if(s4data.reassemble_client)
06556 {
06557 if(direction == FROM_CLIENT)
06558 {
06559 FlushStream(&ssn->client, p, NO_REVERSE);
06560 }
06561 else
06562 {
06563 FlushStream(&ssn->client, p, REVERSE);
06564 }
06565 }
06566
06567 p->packet_flags |= PKT_STREAM_EST;
06568 }
06569
06570 if(action & ACTION_DROP_SESSION)
06571 {
06572 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Dumping session\n"););
06573 DeleteSession(ssn, p->pkth->ts.tv_sec);
06574 p->ssnptr = NULL;
06575 }
06576 }
06577 }
06578
06579 static void TcpActionAsync(Session *ssn, Packet *p, int action, int direction,
06580 u_int32_t pkt_seq, u_int32_t pkt_ack)
06581 {
06582 if(direction == FROM_CLIENT)
06583 {
06584 if(!ssn->client.isn)
06585 {
06586 ssn->client.isn = pkt_seq;
06587 }
06588
06589 ssn->client.last_ack = pkt_seq;
06590
06591 }
06592 else
06593 {
06594 if(!ssn->server.isn)
06595 {
06596 ssn->server.isn = pkt_seq;
06597 }
06598
06599 ssn->server.last_ack = pkt_seq;
06600 }
06601
06602
06603 if(action == ACTION_NOTHING)
06604 {
06605 return;
06606 }
06607 else
06608 {
06609 if(action & ACTION_SET_SERVER_ISN)
06610 {
06611 ssn->server.isn = pkt_seq;
06612 ssn->client.win_size = ntohs(p->tcph->th_win);
06613
06614 if(pkt_ack == (ssn->client.isn+1))
06615 {
06616 ssn->client.last_ack = ssn->client.isn+1;
06617 }
06618 else
06619 {
06620
06621 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06622 "WARNING: Got unexpected SYN ACK from server!\n");
06623 DebugMessage(DEBUG_STREAM,
06624 "expected: 0x%X received: 0x%X\n"););
06625 ssn->client.last_ack = pkt_ack;
06626 }
06627 }
06628
06629
06630 if(action & ACTION_COMPLETE_TWH)
06631 {
06632
06633
06634
06635
06636 p->packet_flags |= PKT_STREAM_TWH;
06637
06638
06639 if(pkt_ack == ssn->server.isn+1)
06640 {
06641 ssn->server.last_ack = ssn->server.isn+1;
06642 }
06643 else
06644 {
06645 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06646 "WARNING: Fishy TWH from client "
06647 "(0x%X:%d->0x%X:%d) (ack: 0x%X isn: 0x%X)\n",
06648 p->iph->ip_src.s_addr, p->sp, p->iph->ip_dst.s_addr,
06649 p->dp, pkt_ack, ssn->server.isn););
06650
06651 ssn->server.last_ack = pkt_ack;
06652 }
06653
06654 ssn->server.base_seq = ssn->server.last_ack;
06655 ssn->client.base_seq = ssn->client.last_ack;
06656 }
06657
06658
06659
06660
06661
06662 if(action & ACTION_DATA_ON_SYN)
06663 {
06664 if(p->tcph->th_flags & TH_SYN)
06665 {
06666
06667 if(s4data.evasion_alerts)
06668 {
06669 SnortEventqAdd(GENERATOR_SPP_STREAM4,
06670 STREAM4_DATA_ON_SYN,
06671 1,
06672 0,
06673 3,
06674 STREAM4_DATA_ON_SYN_STR,
06675 0);
06676 }
06677
06678 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06679 "WARNING: Data on SYN packet!\n"););
06680 return;
06681 }
06682 }
06683
06684 if(action & ACTION_INC_PORT)
06685 {
06686 ssn->client.port++;
06687 }
06688
06689
06690 if(action & ACTION_ACK_CLIENT_DATA)
06691 {
06692 Stream *s;
06693
06694 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06695 "client.base_seq(%u) client.last_ack(%u)\n",
06696 ssn->client.base_seq,ssn->client.last_ack););
06697
06698 if((p->tcph->th_flags & TH_RST) && pkt_ack == 0)
06699 {
06700
06701
06702 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[R] Reset Handled\n"););
06703 }
06704
06705 else if((ssn->session_flags & SSNFLAG_CLIENT_FIN) &&
06706 (ssn->client.next_seq + 1 == pkt_ack))
06707 {
06708
06709
06710 ssn->client.last_ack = pkt_ack - 1;
06711 }
06712 else
06713 {
06714 ssn->client.last_ack = pkt_ack;
06715 }
06716
06717 s = &ssn->client;
06718
06719 if((ssn->client.last_ack - ssn->client.base_seq) > ssn->flush_point
06720 && ubi_trCount(&s->data) > 1)
06721 {
06722 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06723 "Flushing Client packet buffer "
06724 "(%d bytes a: 0x%X b: 0x%X pkts: %d)\n",
06725 (ssn->client.last_ack - ssn->client.base_seq),
06726 ssn->client.last_ack, ssn->client.base_seq,
06727 ubi_trCount(&s->data)););
06728
06729 if(s4data.reassemble_client)
06730 {
06731 FlushStream(&ssn->client, p, REVERSE);
06732 }
06733
06734 ssn->client.base_seq = ssn->client.last_ack;
06735 }
06736 }
06737
06738
06739 if(action & ACTION_ACK_SERVER_DATA)
06740 {
06741 Stream *s;
06742
06743 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06744 "server.base_seq(%u) server.last_ack(%u)\n",
06745 ssn->server.base_seq,ssn->server.last_ack););
06746
06747 if((p->tcph->th_flags & TH_RST) && pkt_ack == 0)
06748 {
06749
06750
06751 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[R] Reset Handled\n"););
06752 }
06753 else if((ssn->session_flags & SSNFLAG_CLIENT_FIN) &&
06754 (ssn->server.next_seq + 1 == pkt_ack))
06755 {
06756
06757 ssn->server.last_ack = pkt_ack - 1;
06758 }
06759 else
06760 {
06761 ssn->server.last_ack = pkt_ack;
06762 }
06763
06764
06765 s = &ssn->server;
06766
06767 if((ssn->server.last_ack - ssn->server.base_seq) > ssn->flush_point
06768 && ubi_trCount(&s->data) > 1)
06769 {
06770 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
06771 "Flushing Server packet buffer "
06772 "(%d bytes a: 0x%X b: 0x%X)\n",
06773 (ssn->server.last_ack - ssn->server.base_seq),
06774 ssn->server.last_ack, ssn->server.base_seq););
06775
06776 if(s4data.reassemble_server)
06777 {
06778 FlushStream(&ssn->server, p, REVERSE);
06779 }
06780
06781 ssn->server.base_seq = ssn->server.last_ack;
06782 }
06783 }
06784
06785 if(s4data.ps_alerts && (action & ACTION_ALERT_NMAP_FINGERPRINT))
06786 {
06787 SnortEventqAdd(GENERATOR_SPP_STREAM4,
06788 STREAM4_STEALTH_NMAP_FINGERPRINT,
06789 1,
06790 0,
06791 3,
06792 STREAM4_STEALTH_NMAP_FINGERPRINT_STR,
06793 0);
06794 return;
06795 }
06796
06797 if(action & ACTION_FLUSH_SERVER_STREAM)
06798 {
06799 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "flushing server stream, ending "
06800 "session: %d\n", s4data.reassemble_server););
06801
06802 if(s4data.reassemble_server)
06803 {
06804 if(direction == FROM_SERVER)
06805 {
06806 FlushStream(&ssn->server, p, NO_REVERSE);
06807 }
06808 else
06809 {
06810 FlushStream(&ssn->server, p, REVERSE);
06811 }
06812 }
06813 }
06814
06815 if(action & ACTION_FLUSH_CLIENT_STREAM)
06816 {
06817 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "flushing client stream, ending "
06818 "session\n"););
06819
06820 if(s4data.reassemble_client)
06821 {
06822 if(direction == FROM_CLIENT)
06823 {
06824 FlushStream(&ssn->client, p, NO_REVERSE);
06825 }
06826 else
06827 {
06828 FlushStream(&ssn->client, p, REVERSE);
06829 }
06830 }
06831 }
06832
06833 if(action & ACTION_DROP_SESSION)
06834 {
06835 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Dumping session\n"););
06836 DeleteSession(ssn, p->pkth->ts.tv_sec);
06837 p->ssnptr = NULL;
06838 }
06839 }
06840 }
06841
06842
06843
06844 struct parse_v1_file
06845 {
06846 char statestr[16];
06847
06848
06849 u_int32_t session_flags;
06850
06851 u_int32_t start_time;
06852 u_int32_t last_session_time;
06853
06854
06855 u_int32_t c_ip;
06856 u_int16_t c_port;
06857 u_int32_t c_isn;
06858 u_int32_t c_base_seq;
06859 u_int32_t c_last_ack;
06860 u_int16_t c_win_size;
06861 u_int32_t c_pkts_sent;
06862 u_int32_t c_bytes_sent;
06863
06864
06865 u_int32_t s_ip;
06866 u_int16_t s_port;
06867 u_int32_t s_isn;
06868 u_int32_t s_base_seq;
06869 u_int32_t s_last_ack;
06870 u_int16_t s_win_size;
06871 u_int32_t s_pkts_sent;
06872 u_int32_t s_bytes_sent;
06873 };
06874
06875
06876
06877
06878
06879 static void InitFakePkt(Packet *p)
06880 {
06881 p->pkth = calloc(sizeof(SnortPktHeader)+
06882 ETHERNET_HEADER_LEN +
06883 SPARC_TWIDDLE + IP_MAXPACKET,
06884 sizeof(char));
06885
06886 p->pkt = ((u_int8_t *)p->pkth) + sizeof(SnortPktHeader);
06887 p->eh = (EtherHdr *)((u_int8_t *)p->pkt + SPARC_TWIDDLE);
06888 p->iph =
06889 (IPHdr *)((u_int8_t *)p->eh + ETHERNET_HEADER_LEN);
06890 p->tcph = (TCPHdr *)((u_int8_t *)p->iph + IP_HEADER_LEN);
06891
06892 p->data = (u_int8_t *)p->tcph + TCP_HEADER_LEN;
06893
06894
06895
06896
06897
06898
06899
06900
06901 p->eh->ether_type = htons(0x0800);
06902 SET_IP_VER(p->iph, 0x4);
06903 SET_IP_HLEN(p->iph, 0x5);
06904 p->iph->ip_proto = IPPROTO_TCP;
06905 p->iph->ip_ttl = 0xF0;
06906 p->iph->ip_len = 0x5;
06907 p->iph->ip_tos = 0x10;
06908
06909 SET_TCP_OFFSET(p->tcph,0x5);
06910 p->tcph->th_flags = TH_PUSH|TH_ACK;
06911 }
06912
06913
06914
06915
06916
06917 static char parse_one_v1(u_int32_t thetime, Packet *fakep, struct parse_v1_file *parse)
06918 {
06919 Session *ssn;
06920 static u_int8_t savedfpi;
06921 u_int8_t fpi;
06922
06923
06924
06925
06926 if(parse->last_session_time + s4data.timeout < thetime)
06927 {
06928 return 0;
06929 }
06930
06931 parse->session_flags |= SSNFLAG_SEEN_CLIENT;
06932 parse->session_flags |= SSNFLAG_SEEN_SERVER;
06933
06934 if(strcmp(parse->statestr, "ESTABLISHED") == 0)
06935 parse->session_flags |= SSNFLAG_ESTABLISHED;
06936 else if(strcmp(parse->statestr, "MIDSTREAM") == 0)
06937 parse->session_flags |= SSNFLAG_MIDSTREAM;
06938
06939 #ifdef DEBUG
06940
06941 if(parse->session_flags & SSNFLAG_ESTABLISHED)
06942 fprintf(stdout, "ESTABLISHED ");
06943 else if(parse->session_flags & SSNFLAG_MIDSTREAM)
06944 fprintf(stdout, "MIDSTREAM ");
06945 else
06946 {
06947 return 0;
06948 }
06949
06950
06951 fprintf(stdout, "%u %u ", (u_int)parse->start_time,
06952 (u_int)parse->last_session_time);
06953
06954
06955 fprintf(stdout, "%u %u %u %u %u %u %u %u ",
06956 parse->c_ip, parse->c_port,
06957 parse->c_isn, parse->c_base_seq, parse->c_last_ack,
06958 parse->c_win_size, parse->c_pkts_sent, parse->c_bytes_sent);
06959
06960
06961 fprintf(stdout, "%u %u %u %u %u %u %u %u ",
06962 parse->s_ip, parse->s_port,
06963 parse->s_isn, parse->s_base_seq, parse->s_last_ack,
06964 parse->s_win_size, parse->s_pkts_sent, parse->s_bytes_sent);
06965
06966 fprintf(stdout, "\n");
06967 #endif
06968
06969 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"cip: 0x%X cp: %d sip: 0x%X sp: %d\n",
06970 parse->c_ip, parse->c_port, parse->s_ip, parse->s_port););
06971
06972
06973
06974
06975
06976
06977
06978
06979 fakep->iph->ip_src.s_addr = parse->c_ip;
06980 fakep->iph->ip_dst.s_addr = parse->s_ip;
06981 fakep->tcph->th_sport = htons(parse->c_port);
06982 fakep->tcph->th_dport = htons(parse->s_port);
06983 fakep->pkth->ts.tv_sec = 0;
06984
06985
06986 ssn = GetNewSession(fakep);
06987
06988 if(s4data.reassemble_server)
06989 (void)ubi_trInitTree(&ssn->server.data,
06990 DataCompareFunc,
06991 ubi_trDUPKEY);
06992 else
06993 ssn->server.data.root = NULL;
06994
06995 if(s4data.reassemble_client)
06996 (void)ubi_trInitTree(&ssn->client.data,
06997 DataCompareFunc,
06998 ubi_trDUPKEY);
06999 else
07000 ssn->client.data.root = NULL;
07001
07002
07003 ssn->session_flags = parse->session_flags;
07004 ssn->start_time = parse->start_time;
07005 ssn->last_session_time = parse->last_session_time;
07006
07007 savedfpi++;
07008 fpi = savedfpi % FCOUNT;
07009 ssn->flush_point = flush_points[fpi];
07010
07011
07012 ssn->client.state = ESTABLISHED;
07013 ssn->client.ip = parse->c_ip;
07014 ssn->client.port = parse->c_port;
07015 ssn->client.isn = parse->c_isn;
07016 ssn->client.base_seq = parse->c_base_seq;
07017 ssn->client.last_ack = parse->c_last_ack;
07018 ssn->client.win_size = parse->c_win_size;
07019 ssn->client.pkts_sent = parse->c_pkts_sent;
07020 ssn->client.bytes_sent = parse->c_bytes_sent;
07021
07022
07023 ssn->server.state = ESTABLISHED;
07024 ssn->server.ip = parse->s_ip;
07025 ssn->server.port = parse->s_port;
07026 ssn->server.isn = parse->s_isn;
07027 ssn->server.base_seq = parse->s_base_seq;
07028 ssn->server.last_ack = parse->s_last_ack;
07029 ssn->server.win_size = parse->s_win_size;
07030 ssn->server.pkts_sent = parse->s_pkts_sent;
07031 ssn->server.bytes_sent = parse->s_bytes_sent;
07032
07033 return 1;
07034 }
07035
07036
07037 int LoadStateTable(const u_int32_t thetime, const char *path)
07038 {
07039 FILE *fp = NULL;
07040 char buf[512] = "", version[16] = "";
07041
07042
07043 int res = 0;
07044 struct parse_v1_file parse;
07045 u_int32_t loadcnt = 0;
07046 u_int32_t skipcnt = 0;
07047 Packet fakepkt;
07048
07049 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"start\n"););
07050
07051
07052 InitFakePkt(&fakepkt);
07053 memset(&parse, 0, sizeof(parse));
07054
07055
07056
07057 fp = fopen(path, "r");
07058 if(fp == NULL)
07059 {
07060 printf("Opening '%s' failed: %s.\n", path, strerror(errno));
07061 return 0;
07062 }
07063
07064 while(fgets(buf, sizeof(buf), fp) != NULL)
07065 {
07066 if(buf[0] != '#')
07067 {
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082 res = sscanf(buf, "%15s %u %u %u %hu %u %u %u %hu %u %u %u %hu %u %u %u %hu %u %u",
07083 parse.statestr, &parse.start_time, &parse.last_session_time,
07084 &parse.c_ip, &parse.c_port, &parse.c_isn, &parse.c_base_seq,
07085 &parse.c_last_ack, &parse.c_win_size, &parse.c_pkts_sent,
07086 &parse.c_bytes_sent,
07087
07088 &parse.s_ip, &parse.s_port, &parse.s_isn, &parse.s_base_seq,
07089 &parse.s_last_ack, &parse.s_win_size, &parse.s_pkts_sent,
07090 &parse.s_bytes_sent);
07091 if(res == 19)
07092 {
07093 if(parse_one_v1(thetime, &fakepkt, &parse) == 1)
07094 {
07095 pc.tcp_streams++;
07096 loadcnt++;
07097 }
07098 else
07099 {
07100 skipcnt++;
07101 }
07102 }
07103 else
07104 {
07105 res = sscanf(buf, "%15s", version);
07106 if(res == 1)
07107 {
07108 if(strncmp(version,"version", 7) == 0)
07109 {
07110
07111
07112 }
07113 else
07114 {
07115 skipcnt++;
07116 }
07117 }
07118 else
07119 {
07120 skipcnt++;
07121 }
07122 }
07123 }
07124 }
07125
07126 fclose(fp);
07127
07128 LogMessage("Loaded %u connections from the state file.\n", loadcnt);
07129
07130 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"end: loadcnt %u, skipcnt: %u, total: %u\n",
07131 loadcnt, skipcnt, loadcnt+skipcnt););
07132 return 0;
07133 }