00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdlib.h>
00010 #include <string.h>
00011
00012
00013
00014
00015
00016 #include "generators.h"
00017 #include "event_wrapper.h"
00018 #include "event_queue.h"
00019
00020 #include "util.h"
00021 #include "plugbase.h"
00022 #include "parser.h"
00023 #include "snort.h"
00024
00025
00026 #include "inline.h"
00027
00028
00029 #include "sfthreshold.h"
00030
00031
00032
00033
00034 #include "debug.h"
00035
00036 #include "str_search.h"
00037 #include "xlink2state.h"
00038
00039
00040 XLINK2STATE *_xlink;
00041 static u_int _xlink2state_ports[65535];
00042 static u_int _xlink2state_disabled = 0;
00043 static u_int _xlink2state_drop = 0;
00044 static Packet *_xlink2state_pkt = NULL;
00045
00046
00047
00048
00049 #define START_LIST "{"
00050 #define END_LIST "}"
00051 #define PORTS "ports"
00052 #define DISABLE "disable"
00053 #define INLINE_DROP "drop"
00054 #define CONF_SEPARATORS " \t\n\r"
00055
00056 #define ERRSTRLEN 512
00057
00058
00059
00060
00061
00062
00063
00064
00065 void XLINK2STATE_Init(void)
00066 {
00067
00068 SearchInit(1);
00069
00070
00071 SearchInit(1);
00072
00073 SearchAdd(0, "X-LINK2STATE", 0);
00074
00075 SearchPrepPatterns(0);
00076
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 void XLINK2STATE_SessionFree(void * v)
00088 {
00089 XLINK2STATE *x = (XLINK2STATE *) v;
00090
00091 if ( x )
00092 free(x);
00093 return;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 static void XLINK2STATE_Setup(Packet *p)
00105 {
00106 Session *ssnptr;
00107
00108
00109 ssnptr = (Session *) (p->ssnptr);
00110
00111 if ( ssnptr && ssnptr->preproc_data == NULL )
00112 {
00113 XLINK2STATE *x = (XLINK2STATE *) malloc(sizeof(XLINK2STATE));
00114 if ( x == NULL )
00115 {
00116 FatalError("%s(%d) => Failed to allocate for X-Link2State session data\n",
00117 file_name, file_line);
00118 return;
00119 }
00120 memset(x, 0, sizeof(XLINK2STATE));
00121 ssnptr->preproc_data = x;
00122 ssnptr->preproc_free = XLINK2STATE_SessionFree;
00123 }
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 static int IsServer(unsigned short port)
00137 {
00138 if( _xlink2state_ports[port] )
00139 {
00140 return 1;
00141 }
00142
00143 return 0;
00144 }
00145
00146 static char * safe_strchr(char *buf, char c, u_int len)
00147 {
00148 char *p = buf;
00149 int i = 0;
00150
00151 while ( i < len )
00152 {
00153 if ( *p == c )
00154 {
00155 return p;
00156 }
00157 i++;
00158 p++;
00159 }
00160
00161 return NULL;
00162 }
00163
00164 int ParseXLink2State(int id, u_int8_t *x)
00165 {
00166 char *eq;
00167 char *start;
00168 char *lf;
00169 int len = 0;
00170 u_int x_len;
00171
00172
00173 x_len = _xlink2state_pkt->dsize - (x - _xlink2state_pkt->data);
00174
00175 eq = safe_strchr(x, '=', x_len);
00176 if ( !eq )
00177 return 0;
00178
00179
00180
00181
00182
00183
00184 if ( *(eq+1) == '{' )
00185 {
00186
00187 start = eq + 2;
00188 sscanf(start, "%x", &len);
00189 }
00190 else
00191 {
00192 start = eq + 1;
00193 }
00194
00195 if ( len == 0 )
00196 {
00197 lf = safe_strchr(x, '\n', x_len);
00198 if ( !lf )
00199 return 0;
00200
00201 len = lf - start;
00202 }
00203 _xlink->length += len;
00204
00205 if ( _xlink->length > 1024 )
00206 {
00207
00208
00209
00210 if (_xlink2state_drop && InlineMode())
00211 {
00212 _xlink2state_pkt->packet_flags |= PKT_INLINE_DROP;
00213 InlineDrop();
00214 }
00215
00216
00217 if( !sfthreshold_test( GENERATOR_SMTP,
00218 1,
00219 _xlink2state_pkt->iph->ip_src.s_addr,
00220 _xlink2state_pkt->iph->ip_dst.s_addr,
00221 _xlink2state_pkt->pkth->ts.tv_sec) )
00222 {
00223 _xlink->alerted = 1;
00224 return 1;
00225 }
00226
00227 SnortEventqAdd(GENERATOR_SMTP, 1, 1, 0, 3, "X-Link2State length greater than 1024", 0);
00228 _xlink->alerted = 1;
00229
00230 return 1;
00231 }
00232
00233 return 0;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 int StrFound(void *id, int index, void *data)
00247 {
00248 int iid = (int)(long) id;
00249 u_int8_t *buf = (char *) data;
00250 u_int8_t *ptr = buf + index;
00251
00252
00253
00254
00255 return ParseXLink2State(iid, ptr);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265 static void XLINK2STATE_ProcessPacket(Packet *p)
00266 {
00267 int strFound;
00268 Session *ssnptr = NULL;
00269
00270 if(!p->ssnptr)
00271 {
00272 return;
00273 }
00274 ssnptr = (Session *)p->ssnptr;
00275
00276 _xlink = (XLINK2STATE *) ssnptr->preproc_data;
00277
00278
00279
00280 _xlink2state_pkt = p;
00281
00282
00283 if ( _xlink->alerted )
00284 {
00285 if (_xlink2state_drop && InlineMode())
00286 {
00287 _xlink2state_pkt->packet_flags |= PKT_INLINE_DROP;
00288 InlineDrop();
00289 }
00290 return;
00291 }
00292
00293
00294 strFound = SearchFindString(0, p->data, p->dsize, StrFound);
00295
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305 void SnortXLINK2STATE(Packet *p)
00306 {
00307
00308 if ( _xlink2state_disabled )
00309 return;
00310
00311
00312
00313 if ( !IsServer(p->dp) )
00314 return;
00315
00316
00317 if (p->dsize < 18)
00318 return;
00319
00320 XLINK2STATE_Setup(p);
00321
00322 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, " <SMTP packet from client>\n"););
00323
00324 if (p->packet_flags & PKT_STREAM_INSERT)
00325 {
00326
00327 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Client packet will be reassembled\n"));
00328 return;
00329 }
00330
00331
00332 XLINK2STATE_ProcessPacket(p);
00333 }
00334
00335
00336
00337 static int PrintConfig(void)
00338 {
00339 int i;
00340 char buf[STD_BUF+1];
00341
00342 LogMessage("X-Link2State Config:\n");
00343
00344 memset(buf, 0, STD_BUF+1);
00345 snprintf(buf, STD_BUF, " Ports: ");
00346 for(i = 0; i < 65536; i++)
00347 {
00348 if(_xlink2state_ports[i])
00349 {
00350 sfsnprintfappend(buf, STD_BUF, "%d ", i);
00351 }
00352 }
00353 LogMessage("%s\n", buf);
00354 if (InlineMode())
00355 LogMessage(" Drop Packets (inline only): %s\n", _xlink2state_drop ? "YES" : "NO");
00356
00357 return 0;
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 static int ProcessPorts(char *ErrorString, int ErrStrLen)
00381 {
00382 char *pcToken;
00383 char *pcEnd;
00384 int iPort;
00385 int iEndPorts = 0;
00386
00387
00388 _xlink2state_ports[SMTP_DEFAULT_SERVER_PORT] = 0;
00389
00390 pcToken = strtok(NULL, CONF_SEPARATORS);
00391 if(!pcToken)
00392 {
00393 snprintf(ErrorString, ErrStrLen,
00394 "Invalid port list format.");
00395
00396 return -1;
00397 }
00398
00399 if(strcmp(START_LIST, pcToken))
00400 {
00401 snprintf(ErrorString, ErrStrLen,
00402 "Must start a port list with the '%s' token.",
00403 START_LIST);
00404
00405 return -1;
00406 }
00407
00408 while((pcToken = strtok(NULL, CONF_SEPARATORS)))
00409 {
00410 if(!strcmp(END_LIST, pcToken))
00411 {
00412 iEndPorts = 1;
00413 break;
00414 }
00415
00416 iPort = strtol(pcToken, &pcEnd, 10);
00417
00418
00419
00420
00421 if(*pcEnd)
00422 {
00423 snprintf(ErrorString, ErrStrLen,
00424 "Invalid port number.");
00425
00426 return -1;
00427 }
00428
00429 if(iPort < 0 || iPort > 65535)
00430 {
00431 snprintf(ErrorString, ErrStrLen,
00432 "Invalid port number. Must be between 0 and "
00433 "65535.");
00434
00435 return -1;
00436 }
00437
00438 _xlink2state_ports[iPort] = 1;
00439 }
00440
00441 if(!iEndPorts)
00442 {
00443 snprintf(ErrorString, ErrStrLen,
00444 "Must end '%s' configuration with '%s'.",
00445 PORTS, END_LIST);
00446
00447 return -1;
00448 }
00449
00450 return 0;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 void XLINK2STATE_ParseArgs(u_char *args)
00467 {
00468 int ret = 0;
00469 char *arg;
00470 char errStr[ERRSTRLEN];
00471 int errStrLen = ERRSTRLEN;
00472
00473 _xlink2state_ports[SMTP_DEFAULT_SERVER_PORT] = 1;
00474
00475 if ( args == NULL )
00476 {
00477 return;
00478 }
00479
00480 arg = strtok(args, CONF_SEPARATORS);
00481
00482 while ( arg != NULL )
00483 {
00484 if ( !strcasecmp(PORTS, arg) )
00485 {
00486 ret = ProcessPorts(errStr, errStrLen);
00487 if ( ret == -1 )
00488 break;
00489 }
00490 else if ( !strcasecmp(DISABLE, arg) )
00491 {
00492 _xlink2state_disabled = 1;
00493 }
00494 else if ( !strcasecmp(INLINE_DROP, arg) )
00495 {
00496 if (InlineMode())
00497 _xlink2state_drop = 1;
00498 else
00499 LogMessage("%s(%d) WARNING: drop keyword ignored."
00500 "snort is not in inline mode\n",
00501 file_name, file_line);
00502 }
00503
00504
00505 arg = strtok(NULL, CONF_SEPARATORS);
00506 }
00507
00508 if ( ret < 0 )
00509 {
00510
00511
00512
00513 if(*errStr)
00514 {
00515 FatalError("%s(%d) => %s\n",
00516 file_name, file_line, errStr);
00517 }
00518 else
00519 {
00520 FatalError("%s(%d) => Undefined Error.\n",
00521 file_name, file_line);
00522 }
00523 }
00524
00525 PrintConfig();
00526 }
00527