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 #ifdef HAVE_CONFIG_H
00045 #include "config.h"
00046 #endif
00047
00048 #include <sys/types.h>
00049 #include <stdlib.h>
00050 #include <ctype.h>
00051
00052 #ifdef HAVE_STRINGS_H
00053 #include <strings.h>
00054 #endif
00055
00056 #include "decode.h"
00057 #include "plugbase.h"
00058 #include "parser.h"
00059 #include "log.h"
00060 #include "debug.h"
00061 #include "util.h"
00062
00063 #include "mstring.h"
00064 #include "snort.h"
00065 #include "detect.h"
00066 #include "log.h"
00067 #include "generators.h"
00068 #include "event_queue.h"
00069
00070 extern char *file_name;
00071 extern int file_line;
00072 extern int do_detect;
00073
00074 #define OPT_ALERT_FRAGMENTS "alert_fragments"
00075 #define OPT_ALERT_MULTIPLE_REQUESTS "no_alert_multiple_requests"
00076 #define OPT_ALERT_LARGE_FRAGMENTS "no_alert_large_fragments"
00077 #define OPT_ALERT_INCOMPLETE "no_alert_incomplete"
00078
00079 #define TEXT_ALERT_MULTIPLE_REQUESTS "alert_multiple_requests"
00080 #define TEXT_ALERT_LARGE_FRAGMENTS "alert_large_fragments"
00081 #define TEXT_ALERT_INCOMPLETE "alert_incomplete"
00082
00083 #define RPC_CLASS DECODE_CLASS
00084
00085 typedef struct _RpcDecodeData
00086 {
00087 char alert_fragments;
00088 char alert_incomplete;
00089 char alert_multi;
00090 char alert_large;
00091 } RpcDecodeData;
00092
00093 static RpcDecodeData rpcpreprocdata;
00094 static char RpcDecodePorts[65536/8];
00095
00096 void RpcDecodeInit(u_char *);
00097 void RpcDecodeInitIgnore(u_char *);
00098 void PreprocRpcDecode(Packet *, void *);
00099 void SetRpcPorts(char *);
00100 int ConvertRPC(Packet *);
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 void SetupRpcDecode()
00114 {
00115
00116
00117 RegisterPreprocessor("rpc_decode", RpcDecodeInit);
00118
00119 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"Preprocessor: RpcDecode in setup...\n"););
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 void RpcDecodeInit(u_char *args)
00136 {
00137 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"Preprocessor: RpcDecode Initialized\n"););
00138
00139 bzero(&rpcpreprocdata,sizeof(RpcDecodeData));
00140
00141
00142 rpcpreprocdata.alert_multi = 1;
00143 rpcpreprocdata.alert_incomplete = 1;
00144 rpcpreprocdata.alert_large = 1;
00145
00146
00147 SetRpcPorts(args);
00148
00149
00150 AddFuncToPreprocList(PreprocRpcDecode);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 void SetRpcPorts(char *portlist)
00165 {
00166 char portstr[STD_BUF];
00167 char **toks;
00168 int is_reset = 0;
00169 int num_toks;
00170 int num;
00171
00172 if(portlist == NULL || *portlist == '\0')
00173 {
00174 portlist = "111 32771";
00175 }
00176
00177
00178 toks = mSplit(portlist, " ", 31, &num_toks, '\\');
00179
00180 LogMessage("rpc_decode arguments:\n");
00181
00182
00183 for(num = 0; num < num_toks; num++)
00184 {
00185 if(isdigit((int)toks[num][0]))
00186 {
00187 char *num_p = NULL;
00188 long t_num;
00189
00190 t_num = strtol(toks[num], &num_p, 10);
00191
00192 if(*num_p != '\0')
00193 {
00194 FatalError("ERROR %s(%d) => Port Number invalid format: %s\n",
00195 file_name, file_line, toks[num]);
00196 }
00197 else if(t_num < 0 || t_num > 65535)
00198 {
00199 FatalError("ERROR %s(%d) => Port Number out of range: %ld\n",
00200 file_name, file_line, t_num);
00201 }
00202
00203
00204
00205 if(!is_reset)
00206 {
00207 bzero(&RpcDecodePorts, sizeof(RpcDecodePorts));
00208 portstr[0] = '\0';
00209 is_reset = 1;
00210 }
00211
00212
00213
00214
00215 RpcDecodePorts[(t_num/8)] |= 1<<(t_num%8);
00216 strlcat(portstr, toks[num], STD_BUF - 1);
00217 strlcat(portstr, " ", STD_BUF - 1);
00218 }
00219 else if(!strcasecmp(OPT_ALERT_MULTIPLE_REQUESTS,toks[num]))
00220 {
00221 rpcpreprocdata.alert_multi = 0;
00222 }
00223 else if(!strcasecmp(OPT_ALERT_INCOMPLETE,toks[num]))
00224 {
00225 rpcpreprocdata.alert_incomplete = 0;
00226 }
00227 else if(!strcasecmp(OPT_ALERT_LARGE_FRAGMENTS,toks[num]))
00228 {
00229 rpcpreprocdata.alert_large = 0;
00230 }
00231 else if(!strcasecmp(OPT_ALERT_FRAGMENTS,toks[num]))
00232 {
00233 rpcpreprocdata.alert_fragments = 1;
00234 }
00235 else
00236 {
00237 FatalError("ERROR %s(%d) => Unknown argument to rpc_decode "
00238 "preprocessor: \"%s\"\n",
00239 file_name, file_line, toks[num]);
00240 }
00241 }
00242
00243 mSplitFree(&toks, num_toks);
00244
00245
00246 LogMessage(" Ports to decode RPC on: %s\n", portstr);
00247 LogMessage(" %s: %s\n", OPT_ALERT_FRAGMENTS, rpcpreprocdata.alert_fragments ? "ACTIVE": "INACTIVE");
00248 LogMessage(" %s: %s\n", TEXT_ALERT_LARGE_FRAGMENTS, rpcpreprocdata.alert_large ? "ACTIVE": "INACTIVE");
00249 LogMessage(" %s: %s\n", TEXT_ALERT_INCOMPLETE, rpcpreprocdata.alert_incomplete ? "ACTIVE": "INACTIVE");
00250 LogMessage(" %s: %s\n", TEXT_ALERT_MULTIPLE_REQUESTS, rpcpreprocdata.alert_multi ? "ACTIVE": "INACTIVE");
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 void PreprocRpcDecode(Packet *p, void *context)
00266 {
00267 int ret = 0;
00268
00269 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"rpc decoder init on %d bytes\n", p->dsize););
00270
00271
00272
00273 if(!PacketIsTCP(p))
00274 {
00275 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"It isn't TCP session traffic\n"););
00276 return;
00277 }
00278
00279 if (!(p->preprocessors & PP_RPCDECODE))
00280 {
00281 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"Packet isn't taged for RPC inspection\n"););
00282 return;
00283 }
00284
00285 if((snort_runtime.capabilities.stateful_inspection == 1) &&
00286 (p->packet_flags & PKT_FROM_SERVER))
00287 {
00288 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"This is from a server\n"););
00289 return;
00290 }
00291
00292
00293
00294 if(!(RpcDecodePorts[(p->dp/8)] & (1<<(p->dp%8))))
00295 {
00296 return;
00297 }
00298
00299 ret = ConvertRPC(p);
00300 DEBUG_WRAP(DebugMessage(DEBUG_RPC,"Got ret: %d from ConvertRPC\n", ret););
00301
00302 if(ret != 0)
00303 {
00304 switch(ret)
00305 {
00306 case RPC_FRAG_TRAFFIC:
00307 if(rpcpreprocdata.alert_fragments)
00308 {
00309 SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_FRAG_TRAFFIC,
00310 1, RPC_CLASS, 3, RPC_FRAG_TRAFFIC_STR, 0);
00311 }
00312 break;
00313 case RPC_MULTIPLE_RECORD:
00314 if(rpcpreprocdata.alert_multi)
00315 {
00316 SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_MULTIPLE_RECORD,
00317 1, RPC_CLASS, 3, RPC_MULTIPLE_RECORD_STR, 0);
00318 }
00319 break;
00320 case RPC_LARGE_FRAGSIZE:
00321 if(rpcpreprocdata.alert_large)
00322 {
00323 SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_LARGE_FRAGSIZE,
00324 1, RPC_CLASS, 3, RPC_LARGE_FRAGSIZE_STR, 0);
00325 }
00326 break;
00327 case RPC_INCOMPLETE_SEGMENT:
00328 if(rpcpreprocdata.alert_incomplete)
00329 {
00330 SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_INCOMPLETE_SEGMENT,
00331 1, RPC_CLASS, 3, RPC_INCOMPLETE_SEGMENT_STR, 0);
00332 }
00333 break;
00334 case RPC_ZERO_LENGTH_FRAGMENT:
00335 if(rpcpreprocdata.alert_multi)
00336 {
00337 SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_ZERO_LENGTH_FRAGMENT,
00338 1, RPC_CLASS, 3, RPC_ZERO_LENGTH_FRAGMENT_STR, 0);
00339 }
00340 break;
00341 }
00342 }
00343
00344 return;
00345 }
00346
00347
00348 #define MSB 0x80000000
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 int ConvertRPC(Packet *p)
00388 {
00389 u_int8_t *data = p->data;
00390 u_int16_t *size = &(p->dsize);
00391 u_int8_t *rpc;
00392 u_int8_t *index;
00393 u_int8_t *end;
00394 u_int16_t psize = *size;
00395 int i = 0;
00396 int length;
00397 int last_fragment = 0;
00398 int decoded_len = 4;
00399 u_int32_t fraghdr;
00400 int fragcount = 0;
00401
00402 if(psize < 32)
00403 {
00404 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Returning due to"
00405 " small packet size: %d\n ", psize););
00406 return 0;
00407 }
00408
00409
00410 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Got RPC traffic (%d bytes)!\n", psize););
00411
00412
00413 *((u_int8_t *) &fraghdr) = data[0];
00414 *(((u_int8_t *) &fraghdr) + 1) = data[1];
00415 *(((u_int8_t *) &fraghdr) + 2) = data[2];
00416 *(((u_int8_t *) &fraghdr) + 3) = data[3];
00417
00418
00419
00420 fraghdr = ntohl(fraghdr);
00421 length = fraghdr & 0x7FFFFFFF;
00422
00423
00424 if(fraghdr & MSB)
00425 {
00426
00427 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Found Last Fragment: %u!\n",fraghdr););
00428
00429 if((length + 4 != psize) && !(p->packet_flags & PKT_REBUILT_STREAM))
00430 {
00431 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "It's not the only thing in this buffer!"
00432 " length: %d psize: %d!\n", length, psize););
00433 return RPC_MULTIPLE_RECORD;
00434 }
00435 else if ( length == 0 )
00436 {
00437 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Zero-length RPC fragment detected."
00438 " length: %d psize: %d.\n", length, psize););
00439 return RPC_ZERO_LENGTH_FRAGMENT;
00440 }
00441 return 0;
00442 }
00443 else if(rpcpreprocdata.alert_fragments)
00444 {
00445 return RPC_FRAG_TRAFFIC;
00446 }
00447
00448 rpc = (u_int8_t *) data;
00449 index = (u_int8_t *) data;
00450 end = (u_int8_t *) data + psize;
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 rpc += 4;
00463
00464
00465
00466
00467
00468 while(((end - index) >= 4) && (last_fragment == 0))
00469 {
00470
00471
00472
00473 *((u_int8_t *) &fraghdr) = index[0];
00474 *(((u_int8_t *) &fraghdr) + 1) = index[1];
00475 *(((u_int8_t *) &fraghdr) + 2) = index[2];
00476 *(((u_int8_t *) &fraghdr) + 3) = index[3];
00477
00478 fraghdr = ntohl(fraghdr);
00479 length = fraghdr & 0x7FFFFFFF;
00480
00481
00482
00483 index += 4;
00484
00485 if(fraghdr & MSB)
00486 {
00487 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Last Fragment detected\n"););
00488 last_fragment = 1;
00489 }
00490
00491 if((length + decoded_len) < decoded_len)
00492 {
00493
00494
00495
00496
00497 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Integer Overflow"
00498 " field(%d) exceeds packet size(%d)\n",
00499 length, psize););
00500 return RPC_LARGE_FRAGSIZE;
00501 }
00502
00503 decoded_len += length;
00504
00505 if(length > psize)
00506 {
00507 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Length of"
00508 " field(%d) exceeds packet size(%d)\n",
00509 length, psize););
00510
00511
00512 return RPC_INCOMPLETE_SEGMENT;
00513 }
00514 else if(decoded_len > psize)
00515 {
00516
00517
00518
00519 DEBUG_WRAP(DebugMessage(DEBUG_RPC, " Decoded Length (%d)"
00520 "exceeds packet size(%d)\n",
00521 decoded_len, psize););
00522 return RPC_LARGE_FRAGSIZE;
00523 }
00524 else if((index + length) > end)
00525 {
00526 DEBUG_WRAP(DebugMessage(DEBUG_RPC,
00527 "returning LARGE_FRAGSIZE"
00528 "since we'd read past our end\n"););
00529 return RPC_LARGE_FRAGSIZE;
00530 }
00531 else
00532 {
00533 fragcount++;
00534
00535 DEBUG_WRAP(DebugMessage(DEBUG_RPC,
00536 "length: %d size: %d decoded_len: %d\n",
00537 length, psize, decoded_len););
00538
00539 if(fragcount == 1)
00540 {
00541
00542
00543 rpc += length;
00544 index += length;
00545 }
00546 else
00547 {
00548 for (i=0; i < length; i++, rpc++, index++)
00549 {
00550 *rpc = *index;
00551 }
00552 }
00553 }
00554 }
00555
00556
00557
00558
00559
00560 fraghdr = ntohl(decoded_len);
00561
00562 data[0] = *((u_int8_t *) &fraghdr);
00563 data[1] = *(((u_int8_t *) &fraghdr) + 1);
00564 data[2] = *(((u_int8_t *) &fraghdr) + 2);
00565 data[3] = *(((u_int8_t *) &fraghdr) + 3);
00566
00567 data[0] |= 0x80;
00568
00569
00570
00571
00572
00573 if(decoded_len + ((fragcount - 1) * 4) != psize)
00574 {
00575 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "decoded len does not compute: %d\n",
00576 decoded_len););
00577 return RPC_MULTIPLE_RECORD;
00578 }
00579
00580
00581
00582
00583
00584
00585 *size = decoded_len;
00586
00587 DEBUG_WRAP(DebugMessage(DEBUG_RPC, "New size: %d\n", decoded_len);
00588 DebugMessage(DEBUG_RPC, "converted data:\n");
00589
00590 );
00591 return 0;
00592 }
00593