00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024
00025 #include <sys/types.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <ctype.h>
00029
00030 #include "rules.h"
00031 #include "decode.h"
00032 #include "plugbase.h"
00033 #include "parser.h"
00034 #include "debug.h"
00035 #include "util.h"
00036 #include "plugin_enum.h"
00037
00038 #define M_NORMAL 0
00039 #define M_ALL 1
00040 #define M_ANY 2
00041 #define M_NOT 3
00042
00043 typedef struct _TCPFlagCheckData
00044 {
00045 u_char mode;
00046 u_char tcp_flags;
00047 u_char tcp_mask;
00048
00049 } TCPFlagCheckData;
00050
00051 void TCPFlagCheckInit(char *, OptTreeNode *, int);
00052 void ParseTCPFlags(char *, OptTreeNode *);
00053 int CheckTcpFlags(Packet *, struct _OptTreeNode *, OptFpList *);
00054
00055
00056
00057 void SetupTCPFlagCheck(void)
00058 {
00059 RegisterPlugin("flags", TCPFlagCheckInit);
00060 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: TCPFlagCheck Initialized!\n"););
00061 }
00062
00063
00064
00065 void TCPFlagCheckInit(char *data, OptTreeNode *otn, int protocol)
00066 {
00067 if(protocol != IPPROTO_TCP)
00068 {
00069 FatalError("Line %s (%d): TCP Options on non-TCP rule\n", file_name, file_line);
00070 }
00071
00072
00073 if(otn->ds_list[PLUGIN_TCP_FLAG_CHECK])
00074 {
00075 FatalError("%s(%d): Multiple TCP flags options in rule\n", file_name,
00076 file_line);
00077 }
00078
00079 otn->ds_list[PLUGIN_TCP_FLAG_CHECK] = (TCPFlagCheckData *)
00080 SnortAlloc(sizeof(TCPFlagCheckData));
00081
00082
00083 ParseTCPFlags(data, otn);
00084
00085 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Adding TCP flag check function (%p) to list\n",
00086 CheckTcpFlags););
00087
00088
00089 AddOptFuncToList(CheckTcpFlags, otn);
00090
00091 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "OTN function CheckTcpFlags added to rule!\n"););
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 void ParseTCPFlags(char *rule, OptTreeNode *otn)
00108 {
00109 char *fptr;
00110 char *fend;
00111 int comma_set = 0;
00112 TCPFlagCheckData *idx;
00113
00114 idx = otn->ds_list[PLUGIN_TCP_FLAG_CHECK];
00115
00116 fptr = rule;
00117
00118
00119 if(fptr == NULL)
00120 {
00121 FatalError("[!] ERROR Line %s (%d): Flags missing in TCP flag rule\n", file_name, file_line);
00122 }
00123
00124 while(isspace((u_char) *fptr))
00125 fptr++;
00126
00127 if(strlen(fptr) == 0)
00128 {
00129 FatalError("[!] ERROR Line %s (%d): Flags missing in TCP flag rule\n", file_name, file_line);
00130 }
00131
00132
00133 fend = fptr + strlen(fptr);
00134
00135 idx->mode = M_NORMAL;
00136
00137 while(fptr < fend && comma_set == 0)
00138 {
00139 switch(*fptr)
00140 {
00141 case 'f':
00142 case 'F':
00143 idx->tcp_flags |= R_FIN;
00144 break;
00145
00146 case 's':
00147 case 'S':
00148 idx->tcp_flags |= R_SYN;
00149 break;
00150
00151 case 'r':
00152 case 'R':
00153 idx->tcp_flags |= R_RST;
00154 break;
00155
00156 case 'p':
00157 case 'P':
00158 idx->tcp_flags |= R_PSH;
00159 break;
00160
00161 case 'a':
00162 case 'A':
00163 idx->tcp_flags |= R_ACK;
00164 break;
00165
00166 case 'u':
00167 case 'U':
00168 idx->tcp_flags |= R_URG;
00169 break;
00170
00171 case '0':
00172 idx->tcp_flags = 0;
00173 break;
00174
00175 case '1':
00176 idx->tcp_flags |= R_RES1;
00177 break;
00178
00179 case '2':
00180 idx->tcp_flags |= R_RES2;
00181 break;
00182
00183 case '!':
00184
00185 idx->mode = M_NOT;
00186 break;
00187 case '*':
00188
00189 idx->mode = M_ANY;
00190 break;
00191 case '+':
00192
00193 idx->mode = M_ALL;
00194 break;
00195 case ',':
00196 comma_set = 1;
00197 break;
00198 default:
00199 FatalError("%s(%d): bad TCP flag = \"%c\"\n"
00200 "Valid otions: UAPRSF12 or 0 for NO flags (e.g. NULL scan),"
00201 " and !, + or * for modifiers\n",
00202 file_name, file_line, *fptr);
00203 }
00204
00205 fptr++;
00206 }
00207
00208 while(isspace((u_char) *fptr))
00209 fptr++;
00210
00211
00212
00213 while(fptr < fend && comma_set == 1)
00214 {
00215 switch(*fptr)
00216 {
00217 case 'f':
00218 case 'F':
00219 idx->tcp_mask |= R_FIN;
00220 break;
00221
00222 case 's':
00223 case 'S':
00224 idx->tcp_mask |= R_SYN;
00225 break;
00226
00227 case 'r':
00228 case 'R':
00229 idx->tcp_mask |= R_RST;
00230 break;
00231
00232 case 'p':
00233 case 'P':
00234 idx->tcp_mask |= R_PSH;
00235 break;
00236
00237 case 'a':
00238 case 'A':
00239 idx->tcp_mask |= R_ACK;
00240 break;
00241
00242 case 'u':
00243 case 'U':
00244 idx->tcp_mask |= R_URG;
00245 break;
00246
00247 case '1':
00248 idx->tcp_mask |= R_RES1;
00249 break;
00250
00251 case '2':
00252 idx->tcp_mask |= R_RES2;
00253 break;
00254 default:
00255 FatalError(" Line %s (%d): bad TCP flag = \"%c\"\n Valid otions: UAPRS12 \n",
00256 file_name, file_line, *fptr);
00257 }
00258
00259 fptr++;
00260 }
00261 }
00262
00263
00264 int CheckTcpFlags(Packet *p, struct _OptTreeNode *otn_idx, OptFpList *fp_list)
00265 {
00266 TCPFlagCheckData *flagptr;
00267 u_char tcp_flags;
00268
00269
00270 flagptr = otn_idx->ds_list[PLUGIN_TCP_FLAG_CHECK];
00271
00272 if(!p->tcph)
00273 {
00274
00275
00276 return 0;
00277 }
00278
00279
00280
00281
00282 tcp_flags = p->tcph->th_flags & (0xFF ^ flagptr->tcp_mask);
00283
00284 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, " <!!> CheckTcpFlags: "););
00285
00286 switch((flagptr->mode))
00287 {
00288 case M_NORMAL:
00289 if(flagptr->tcp_flags == tcp_flags)
00290 {
00291 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got TCP [default] flag match!\n"););
00292 return fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
00293 }
00294 else
00295 {
00296 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n"););
00297 }
00298 break;
00299
00300 case M_ALL:
00301
00302 if((flagptr->tcp_flags & tcp_flags) == flagptr->tcp_flags)
00303 {
00304 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Got TCP [ALL] flag match!\n"););
00305 return fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
00306 }
00307 else
00308 {
00309 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n"););
00310 }
00311 break;
00312
00313 case M_NOT:
00314 if((flagptr->tcp_flags & tcp_flags) == 0)
00315 {
00316 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got TCP [NOT] flag match!\n"););
00317 return fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
00318 }
00319 else
00320 {
00321 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "No match\n"););
00322 }
00323 break;
00324
00325 case M_ANY:
00326 if((flagptr->tcp_flags & tcp_flags) != 0)
00327 {
00328 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got TCP [ANY] flag match!\n"););
00329 return fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
00330 }
00331 else
00332 {
00333 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n"););
00334 }
00335 break;
00336
00337 default:
00338 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "TCP flag check went to default case"
00339 " for some silly reason\n"););
00340 break;
00341 }
00342
00343 return 0;
00344 }
00345