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 #ifdef HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif
00034
00035
00036 #ifdef ENABLE_RESPONSE
00037 #include <libnet.h>
00038
00039 #include "decode.h"
00040 #include "rules.h"
00041 #include "plugbase.h"
00042 #include "parser.h"
00043 #include "debug.h"
00044 #include "util.h"
00045 #include "log.h"
00046 #include "plugin_enum.h"
00047 #include "snort.h"
00048
00049 typedef struct _RespondData
00050 {
00051 u_int response_flag;
00052 } RespondData;
00053
00054 void RespondInit(char *, OptTreeNode *, int );
00055 void RespondRestartFunction(int, void *);
00056 int ParseResponse(char *);
00057 int SendICMP_UNREACH(int, u_long, u_long, Packet *);
00058 int SendTCPRST(u_long, u_long, u_short, u_short, u_long, u_long);
00059 int Respond(Packet *, RspFpList *);
00060
00061
00062
00063
00064 int nd;
00065 u_int8_t ttl;
00066
00067 char *tcp_pkt;
00068 char *icmp_pkt;
00069
00070 void PrecacheTcp(void);
00071 void PrecacheIcmp(void);
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 void SetupRespond(void)
00085 {
00086 RegisterPlugin("resp", RespondInit);
00087 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: Respond Setup\n"););
00088 nd = -1;
00089 }
00090
00091 void RespondRestartFunction(int signal, void *foo)
00092 {
00093 if (nd != -1)
00094 {
00095 libnet_close_raw_sock(nd);
00096 nd = -1;
00097 }
00098 if (tcp_pkt != NULL)
00099 libnet_destroy_packet((u_char **)&tcp_pkt);
00100 if (icmp_pkt != NULL)
00101 libnet_destroy_packet((u_char **)&icmp_pkt);
00102
00103 return;
00104 }
00105
00106 void RespondInit(char *data, OptTreeNode *otn, int protocol)
00107 {
00108 RespondData *rd;
00109
00110 if(protocol != IPPROTO_TCP && protocol != IPPROTO_UDP &&
00111 protocol != IPPROTO_ICMP)
00112 {
00113 FatalError("%s(%d): Can't respond to IP protocol rules\n",
00114 file_name, file_line);
00115 }
00116 if(nd == -1)
00117 {
00118 if((nd = libnet_open_raw_sock(IPPROTO_RAW)) < 0)
00119 {
00120 FatalError("cannot open raw socket for libnet, exiting...\n");
00121 }
00122 }
00123
00124 ttl = (u_int8_t)libnet_get_prand(PR8);
00125
00126 if(ttl < 64)
00127 {
00128 ttl += 64;
00129 }
00130
00131 if(( rd = (RespondData *)calloc(sizeof(RespondData), sizeof(char))) == NULL)
00132 {
00133 FatalError("sp_respnd RespondInit() calloc failed!\n");
00134 }
00135
00136 rd->response_flag = ParseResponse(data);
00137
00138 AddRspFuncToList(Respond, otn, (void *)rd );
00139 AddFuncToRestartList(RespondRestartFunction, NULL);
00140
00141 return;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 int ParseResponse(char *type)
00156 {
00157 char *p;
00158 int response_flag;
00159 int make_tcp = 0;
00160 int make_icmp = 0;
00161
00162 while(isspace((int) *type))
00163 type++;
00164
00165 if(!type || !(*type))
00166 return 0;
00167
00168 response_flag = 0;
00169
00170 p = strtok(type, ",");
00171 while(p)
00172 {
00173 if(!strncasecmp(p, "rst_snd", 7))
00174 {
00175 response_flag |= RESP_RST_SND;
00176 make_tcp = 1;
00177 }
00178 else if(!strncasecmp(p, "rst_rcv", 7))
00179 {
00180 response_flag |= RESP_RST_RCV;
00181 make_tcp = 1;
00182 }
00183 else if(!strncasecmp(p, "rst_all", 7))
00184 {
00185 response_flag |= (RESP_RST_SND | RESP_RST_RCV);
00186 make_tcp = 1;
00187 }
00188 else if(!strncasecmp(p, "icmp_net", 8))
00189 {
00190 response_flag |= RESP_BAD_NET;
00191 make_icmp = 1;
00192 }
00193 else if(!strncasecmp(p, "icmp_host", 9))
00194 {
00195 response_flag |= RESP_BAD_HOST;
00196 make_icmp = 1;
00197 }
00198 else if(!strncasecmp(p, "icmp_port", 9))
00199 {
00200 response_flag |= RESP_BAD_PORT;
00201 make_icmp = 1;
00202 }
00203 else if(!strncasecmp(p, "icmp_all", 9))
00204 {
00205 response_flag |= (RESP_BAD_NET | RESP_BAD_HOST | RESP_BAD_PORT);
00206 make_icmp = 1;
00207 }
00208 else
00209 {
00210 FatalError("%s(%d): invalid response modifier: %s\n", file_name,
00211 file_line, p);
00212 }
00213
00214 p = strtok(NULL, ",");
00215 }
00216
00217 if(make_tcp)
00218 {
00219 PrecacheTcp();
00220 }
00221
00222 if(make_icmp)
00223 {
00224
00225 PrecacheIcmp();
00226 }
00227
00228 return response_flag;
00229 }
00230
00231
00232 void PrecacheTcp(void)
00233 {
00234 int sz = IP_H + TCP_H;
00235
00236 if((tcp_pkt = calloc(sz, sizeof(char))) == NULL)
00237 {
00238 FatalError("PrecacheTCP() calloc failed!\n");
00239 }
00240
00241 libnet_build_ip( TCP_H
00242 , 0
00243 , (u_short) libnet_get_prand(PRu16)
00244 , 0
00245 , ttl
00246 , IPPROTO_TCP
00247 , 0
00248 , 0
00249 , NULL
00250 , 0
00251 , tcp_pkt
00252 );
00253
00254 libnet_build_tcp( 0
00255 , 0
00256 , 0
00257 , 0
00258 , TH_RST|TH_ACK
00259 , 0
00260 , 0
00261 , NULL
00262 , 0
00263 , tcp_pkt + IP_H
00264 );
00265
00266 return;
00267 }
00268
00269 void PrecacheIcmp(void)
00270 {
00271 int sz = IP_H + ICMP_UNREACH_H + 68;
00272
00273 if((icmp_pkt = calloc(sz, sizeof(char))) == NULL)
00274 {
00275 FatalError("PrecacheIcmp() calloc failed!\n");
00276 }
00277
00278 libnet_build_ip( ICMP_UNREACH_H
00279 , 0
00280 , (u_short) libnet_get_prand(PRu16)
00281 , 0
00282 , ttl
00283 , IPPROTO_ICMP
00284 , 0
00285 , 0
00286 , NULL
00287 , 0
00288 , icmp_pkt
00289 );
00290
00291 libnet_build_icmp_unreach( 3
00292 , 0
00293 , 0
00294 , 0
00295 , 0
00296 , 0
00297 , 0
00298 , 0
00299 , 0
00300 , 0
00301 , NULL
00302 , 0
00303 , icmp_pkt + IP_H
00304 );
00305
00306 return;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 int Respond(Packet *p, RspFpList *fp_list)
00324 {
00325 RespondData *rd = (RespondData *)fp_list->params;
00326
00327 if(!p->iph)
00328 {
00329 return 0;
00330 }
00331
00332 if(rd->response_flag)
00333 {
00334 if(rd->response_flag & (RESP_RST_SND | RESP_RST_RCV))
00335 {
00336 if(p->iph->ip_proto == IPPROTO_TCP && p->tcph != NULL)
00337 {
00338
00339
00340
00341
00342
00343
00344
00345 if((p->tcph->th_flags & (TH_SYN | TH_RST)) != TH_RST)
00346 {
00347 if(rd->response_flag & RESP_RST_SND)
00348 {
00349 SendTCPRST(p->iph->ip_dst.s_addr,
00350 p->iph->ip_src.s_addr,
00351 p->tcph->th_dport, p->tcph->th_sport,
00352 p->tcph->th_ack,
00353 htonl(ntohl(p->tcph->th_seq) + p->dsize));
00354 }
00355
00356 if(rd->response_flag & RESP_RST_RCV)
00357 {
00358 SendTCPRST(p->iph->ip_src.s_addr,
00359 p->iph->ip_dst.s_addr,
00360 p->tcph->th_sport, p->tcph->th_dport,
00361 p->tcph->th_seq,
00362 htonl(ntohl(p->tcph->th_ack) + p->dsize));
00363 }
00364 }
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373 if((p->icmph == NULL) ||
00374 (p->icmph->type == ICMP_ECHO) ||
00375 (p->icmph->type == ICMP_TIMESTAMP) ||
00376 (p->icmph->type == ICMP_INFO_REQUEST) ||
00377 (p->icmph->type == ICMP_ADDRESS))
00378 {
00379 if(rd->response_flag & RESP_BAD_NET)
00380 SendICMP_UNREACH(ICMP_UNREACH_NET, p->iph->ip_dst.s_addr,
00381 p->iph->ip_src.s_addr, p);
00382
00383 if(rd->response_flag & RESP_BAD_HOST)
00384 SendICMP_UNREACH(ICMP_UNREACH_HOST, p->iph->ip_dst.s_addr,
00385 p->iph->ip_src.s_addr, p);
00386
00387 if(rd->response_flag & RESP_BAD_PORT)
00388 SendICMP_UNREACH(ICMP_UNREACH_PORT, p->iph->ip_dst.s_addr,
00389 p->iph->ip_src.s_addr, p);
00390 }
00391 }
00392 return 1;
00393 }
00394
00395
00396 int SendICMP_UNREACH(int code, u_long saddr, u_long daddr, Packet * p)
00397 {
00398 int payload_len, sz;
00399 IPHdr *iph;
00400 ICMPHdr *icmph;
00401
00402 if(p == NULL)
00403 return -1;
00404
00405
00406 if (p->iph->ip_proto == 1 && code == ICMP_UNREACH_PORT)
00407 {
00408 if (pv.verbose_flag)
00409 {
00410 ErrorMessage("ignoring icmp_port set on ICMP packet.\n");
00411 }
00412
00413 return 0;
00414 }
00415
00416 iph = (IPHdr *) icmp_pkt;
00417 icmph = (ICMPHdr *) (icmp_pkt + IP_H);
00418
00419 iph->ip_src.s_addr = saddr;
00420 iph->ip_dst.s_addr = daddr;
00421
00422 icmph->code = code;
00423
00424 if ((payload_len = ntohs(p->iph->ip_len) - (IP_HLEN(p->iph) << 2)) > 8)
00425 payload_len = 8;
00426
00427 memcpy((char *)icmph + ICMP_UNREACH_H, p->iph, (IP_HLEN(p->iph) << 2)
00428 + payload_len);
00429
00430 sz = IP_H + ICMP_UNREACH_H + (IP_HLEN(p->iph) << 2) + payload_len;
00431 iph->ip_len = htons( (u_short) sz);
00432
00433 libnet_do_checksum(icmp_pkt, IPPROTO_ICMP, sz - IP_H);
00434
00435 #ifdef DEBUG
00436 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "firing ICMP response packet\n"););
00437 PrintNetData(stdout, icmp_pkt, sz);
00438 ClearDumpBuf();
00439 #endif
00440 if(libnet_write_ip(nd, icmp_pkt, sz) < sz)
00441 {
00442 libnet_error(LIBNET_ERR_CRITICAL, "SendICMP_UNREACH: libnet_write_ip");
00443 return -1;
00444 }
00445 return 0;
00446 }
00447
00448
00449 int SendTCPRST(u_long saddr, u_long daddr, u_short sport, u_short dport,
00450 u_long seq, u_long ack)
00451 {
00452 int sz = IP_H + TCP_H;
00453 IPHdr *iph;
00454 TCPHdr *tcph;
00455
00456 iph = (IPHdr *) tcp_pkt;
00457 tcph = (TCPHdr *) (tcp_pkt + IP_H);
00458
00459 iph->ip_src.s_addr = saddr;
00460 iph->ip_dst.s_addr = daddr;
00461
00462 tcph->th_sport = sport;
00463 tcph->th_dport = dport;
00464 tcph->th_seq = seq;
00465 tcph->th_ack = ack;
00466
00467 libnet_do_checksum(tcp_pkt, IPPROTO_TCP, sz - IP_H);
00468
00469 DEBUG_WRAP(
00470 PrintNetData(stdout, tcp_pkt, sz);
00471 ClearDumpBuf();
00472 DebugMessage(DEBUG_PLUGIN, "firing response packet\n");
00473 DebugMessage(DEBUG_PLUGIN,
00474 "0x%lX:%u -> 0x%lX:%d (seq: 0x%lX ack: 0x%lX)\n",
00475 saddr, sport, daddr, dport, seq, ack););
00476
00477 if(libnet_write_ip(nd, tcp_pkt, sz) < sz)
00478 {
00479 libnet_error(LIBNET_ERR_CRITICAL, "SendTCPRST: libnet_write_ip");
00480 return -1;
00481 }
00482
00483 return 0;
00484 }
00485
00486 #endif