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 <ctype.h>
00028 #ifndef WIN32
00029 #include <rpc/rpc.h>
00030 #endif
00031
00032 #include "rules.h"
00033 #include "decode.h"
00034 #include "plugbase.h"
00035 #include "parser.h"
00036 #include "debug.h"
00037 #include "util.h"
00038 #include "plugin_enum.h"
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef IXDR_GET_LONG
00047 #define IXDR_GET_LONG IXDR_GET_INT32
00048 #endif
00049
00050 typedef struct _RpcCheckData
00051 {
00052 u_long program;
00053 u_long vers;
00054 u_long proc;
00055 int flags;
00056
00057 } RpcCheckData;
00058
00059 #define RPC_CHECK_PROG 1
00060 #define RPC_CHECK_VERS 2
00061 #define RPC_CHECK_PROC 4
00062
00063 void RpcCheckInit(char *, OptTreeNode *, int);
00064 void ParseRpc(char *, OptTreeNode *);
00065 int CheckRpc(Packet *, struct _OptTreeNode *, OptFpList *);
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 void SetupRpcCheck(void)
00081 {
00082
00083 RegisterPlugin("rpc", RpcCheckInit);
00084
00085 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: RPCCheck Initialized\n"););
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void RpcCheckInit(char *data, OptTreeNode *otn, int protocol)
00103 {
00104 if(protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
00105 {
00106 FatalError("%s(%d) => Bad protocol in RPC Check rule...\n",
00107 file_name, file_line);
00108 }
00109
00110
00111 if(otn->ds_list[PLUGIN_RPC_CHECK])
00112 {
00113 FatalError("%s(%d): Multiple rpc options in rule\n", file_name,
00114 file_line);
00115 }
00116
00117
00118
00119 otn->ds_list[PLUGIN_RPC_CHECK] = (RpcCheckData *)
00120 SnortAlloc(sizeof(RpcCheckData));
00121
00122
00123
00124 ParseRpc(data, otn);
00125
00126
00127
00128 AddOptFuncToList(CheckRpc, otn);
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 void ParseRpc(char *data, OptTreeNode *otn)
00146 {
00147 RpcCheckData *ds_ptr;
00148 char *tmp;
00149
00150
00151
00152 ds_ptr = otn->ds_list[PLUGIN_RPC_CHECK];
00153 ds_ptr->flags=0;
00154
00155
00156 while(isspace((int)*data)) data++;
00157
00158 if(*data != '*')
00159 {
00160 ds_ptr->program = strtoul(data,&tmp,0);
00161 ds_ptr->flags|=RPC_CHECK_PROG;
00162 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Set RPC program to %lu\n", ds_ptr->program););
00163 }
00164 if(*tmp == '\0') return;
00165 data=++tmp;
00166 if(*data != '*')
00167 {
00168 ds_ptr->vers = strtoul(data,&tmp,0);
00169 ds_ptr->flags|=RPC_CHECK_VERS;
00170 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Set RPC vers to %lu\n", ds_ptr->vers););
00171 }
00172 else
00173 {
00174 tmp++;
00175 }
00176 if(*tmp == '\0') return;
00177 data=++tmp;
00178 if(*data != '*')
00179 {
00180 ds_ptr->proc = strtoul(data,&tmp,0);
00181 ds_ptr->flags|=RPC_CHECK_PROC;
00182 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Set RPC proc to %lu\n", ds_ptr->proc););
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 int CheckRpc(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00200 {
00201 RpcCheckData *ds_ptr;
00202 unsigned char* c=(unsigned char*)p->data;
00203 u_long xid, rpcvers, prog, vers, proc;
00204 enum msg_type direction;
00205 #ifdef DEBUG
00206 int i;
00207 #endif
00208 if(!p->iph || (p->iph->ip_proto == IPPROTO_TCP && !p->tcph)
00209 || (p->iph->ip_proto == IPPROTO_UDP && !p->udph))
00210 return 0;
00211
00212
00213
00214 if(p->iph->ip_proto == IPPROTO_TCP)
00215 {
00216
00217 c+=4;
00218
00219 if(p->dsize<28)
00220 {
00221 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "RPC packet too small"););
00222 return 0;
00223 }
00224 }
00225 else
00226 {
00227
00228 if(p->dsize<24)
00229 {
00230 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "RPC packet too small"););
00231 return 0;
00232 }
00233 }
00234
00235 #ifdef DEBUG
00236 DebugMessage(DEBUG_PLUGIN,"<---xid---> <---dir---> <---rpc--->"
00237 " <---prog--> <---vers--> <---proc-->\n");
00238 for(i=0; i<24; i++)
00239 {
00240 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%02X ",c[i]););
00241 }
00242 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"\n"););
00243 #endif
00244
00245
00246 xid = IXDR_GET_LONG (c);
00247
00248
00249 direction = IXDR_GET_ENUM (c, enum msg_type);
00250
00251
00252 if(direction != CALL)
00253 {
00254 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "RPC packet not a call"););
00255 return 0;
00256 }
00257
00258
00259 rpcvers = IXDR_GET_LONG (c);
00260
00261
00262 if(rpcvers != RPC_MSG_VERSION)
00263 {
00264 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"RPC msg version invalid"););
00265 return 0;
00266 }
00267
00268
00269 prog = IXDR_GET_LONG (c);
00270 vers = IXDR_GET_LONG (c);
00271 proc = IXDR_GET_LONG (c);
00272
00273 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"RPC decoded to: %lu %lu %lu\n",
00274 prog,vers,proc););
00275
00276 ds_ptr=(RpcCheckData *)otn->ds_list[PLUGIN_RPC_CHECK];
00277
00278 DEBUG_WRAP(
00279 DebugMessage(DEBUG_PLUGIN, "RPC matching on: %d %d %d\n",
00280 ds_ptr->flags & RPC_CHECK_PROG,ds_ptr->flags & RPC_CHECK_VERS,
00281 ds_ptr->flags & RPC_CHECK_PROC););
00282 if(!(ds_ptr->flags & RPC_CHECK_PROG) ||
00283 ds_ptr->program == prog)
00284 {
00285 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"RPC program matches"););
00286 if(!(ds_ptr->flags & RPC_CHECK_VERS) ||
00287 ds_ptr->vers == vers)
00288 {
00289 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"RPC version matches"););
00290 if(!(ds_ptr->flags & RPC_CHECK_PROC) ||
00291 ds_ptr->proc == proc)
00292 {
00293 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"RPC proc matches"););
00294 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Yippee! Found one!"););
00295
00296 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00297 }
00298 }
00299 }
00300 else
00301 {
00302
00303 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"RPC not equal\n"););
00304 }
00305
00306
00307 return 0;
00308 }