1 /*
2 ettercap -- dissector module
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ec.h>
23 #include <ec_dissect.h>
24 #include <ec_packet.h>
25 #include <ec_sslwrap.h>
26
27 /* globals */
28
29 static SLIST_HEAD (, dissect_entry) dissect_list;
30
31 struct dissect_entry {
32 char *name;
33 u_int32 type;
34 u_int8 level;
35 FUNC_DECODER_PTR(decoder);
36 SLIST_ENTRY (dissect_entry) next;
37 };
38
39 /*******************************************/
40
41 /*
42 * compare two session ident
43 *
44 * return 1 if it matches
45 */
46
dissect_match(void * id_sess,void * id_curr)47 int dissect_match(void *id_sess, void *id_curr)
48 {
49 struct dissect_ident *ids = id_sess;
50 struct dissect_ident *id = id_curr;
51
52 /* sanity check */
53 BUG_IF(ids == NULL);
54 BUG_IF(id == NULL);
55
56 /*
57 * is this ident from our level ?
58 * check the magic !
59 */
60 if (ids->magic != id->magic)
61 return 0;
62
63 /* check the protocol */
64 if (ids->L4_proto != id->L4_proto)
65 return 0;
66
67 /* from source to dest */
68 if (ids->L4_src == id->L4_src &&
69 ids->L4_dst == id->L4_dst &&
70 !ip_addr_cmp(&ids->L3_src, &id->L3_src) &&
71 !ip_addr_cmp(&ids->L3_dst, &id->L3_dst) )
72 return 1;
73
74 /* from dest to source */
75 if (ids->L4_src == id->L4_dst &&
76 ids->L4_dst == id->L4_src &&
77 !ip_addr_cmp(&ids->L3_src, &id->L3_dst) &&
78 !ip_addr_cmp(&ids->L3_dst, &id->L3_src) )
79 return 1;
80
81 return 0;
82 }
83
84
85 /*
86 * prepare the ident and the pointer to match function
87 * for a dissector.
88 */
89
dissect_create_session(struct ec_session ** s,struct packet_object * po,void * code)90 void dissect_create_session(struct ec_session **s, struct packet_object *po, void *code)
91 {
92 void *ident;
93
94 DEBUG_MSG("dissect_create_session");
95
96 /* allocate the session */
97 SAFE_CALLOC(*s, 1, sizeof(struct ec_session));
98
99 /* create the ident */
100 (*s)->ident_len = dissect_create_ident(&ident, po, code);
101
102 /* link to the session */
103 (*s)->ident = ident;
104
105 /* the matching function */
106 (*s)->match = &dissect_match;
107 }
108
109 /*
110 * create the ident for a session
111 */
112
dissect_create_ident(void ** i,struct packet_object * po,void * code)113 size_t dissect_create_ident(void **i, struct packet_object *po, void *code)
114 {
115 struct dissect_ident *ident;
116
117 /* allocate the ident for that session */
118 SAFE_CALLOC(ident, 1, sizeof(struct dissect_ident));
119
120 /* the magic number (usually the pointer for the function) */
121 ident->fptr = code;
122
123 /* prepare the ident */
124 memcpy(&ident->L3_src, &po->L3.src, sizeof(struct ip_addr));
125 memcpy(&ident->L3_dst, &po->L3.dst, sizeof(struct ip_addr));
126
127 ident->L4_proto = po->L4.proto;
128
129 ident->L4_src = po->L4.src;
130 ident->L4_dst = po->L4.dst;
131
132 /* return the ident */
133 *i = ident;
134
135 /* return the length of the ident */
136 return sizeof(struct dissect_ident);
137 }
138
139 /*
140 * totally destroy the session bound to this connection
141 */
dissect_wipe_session(struct packet_object * po,void * code)142 void dissect_wipe_session(struct packet_object *po, void *code)
143 {
144 void *ident;
145 struct ec_session *s;
146
147 DEBUG_MSG("dissect_wipe_session");
148
149 /* create an ident to retrieve the session */
150 dissect_create_ident(&ident, po, code);
151
152 /* retrieve the session and delete it */
153 if (session_get_and_del(&s, ident, DISSECT_IDENT_LEN) == -E_NOTFOUND) {
154 SAFE_FREE(ident);
155 return;
156 }
157
158 /* free the session */
159 session_free(s);
160 SAFE_FREE(ident);
161 }
162
163 /*
164 * register a dissector in the dissectors list
165 * and add it to the decoder list.
166 * this list is used by dissect_modify during the parsing
167 * of etter.conf to enable/disable the dissectors via their name.
168 */
dissect_add(char * name,u_int8 level,u_int32 port,FUNC_DECODER_PTR (decoder))169 void dissect_add(char *name, u_int8 level, u_int32 port, FUNC_DECODER_PTR(decoder))
170 {
171 struct dissect_entry *e;
172
173 SAFE_CALLOC(e, 1, sizeof(struct dissect_entry));
174
175 e->name = strdup(name);
176 e->level = level;
177 e->type = port;
178 e->decoder = decoder;
179
180 SLIST_INSERT_HEAD (&dissect_list, e, next);
181
182 /* add the default decoder */
183 add_decoder(level, port, decoder);
184
185 return;
186 }
187
188 /*
189 * remove all istances of a dissector in the dissectors list
190 */
dissect_del(char * name)191 void dissect_del(char *name)
192 {
193 struct dissect_entry *e, *tmp = NULL;
194
195 SLIST_FOREACH_SAFE(e, &dissect_list, next, tmp) {
196 if (!strcasecmp(e->name, name)) {
197 del_decoder(e->level, e->type);
198 SLIST_REMOVE(&dissect_list, e, dissect_entry, next);
199 SAFE_FREE(e);
200 }
201 }
202
203 return;
204 }
205
206 /*
207 * given the name of the dissector add or remove it
208 * from the decoders' table.
209 * is it possible to add multiple port with MODE_ADD
210 */
dissect_modify(int mode,char * name,u_int32 port)211 int dissect_modify(int mode, char *name, u_int32 port)
212 {
213 struct dissect_entry *e;
214 int level;
215 void *decoder;
216
217 SLIST_FOREACH (e, &dissect_list, next) {
218 if (!strcasecmp(e->name, name)) {
219 switch (mode) {
220 case MODE_ADD:
221 DEBUG_MSG("dissect_modify: %s added on %lu", name, (unsigned long)port);
222 /* add in the lists */
223 dissect_add(e->name, e->level, port, e->decoder);
224 return E_SUCCESS;
225 break;
226 case MODE_REP:
227
228 /* save them because the dissect_del may delete this values */
229 level = e->level;
230 decoder = e->decoder;
231
232 /* remove all the previous istances */
233 dissect_del(name);
234
235 /* move the ssl wrapper (even if no wrapper) */
236 sslw_dissect_move(name, port);
237
238 /* a value of 0 will disable the dissector */
239 if (port == 0) {
240 DEBUG_MSG("dissect_modify: %s disabled", name);
241 return E_SUCCESS;
242 }
243
244 DEBUG_MSG("dissect_modify: %s replaced to %lu", name, (unsigned long)port);
245
246 /* add the new value */
247 dissect_add(name, level, port, decoder);
248
249 return E_SUCCESS;
250 break;
251 }
252 }
253 }
254
255 return -E_NOTFOUND;
256 }
257
258 /*
259 * return E_SUCCESS if the dissector is on
260 * the specified port
261 */
dissect_on_port(char * name,u_int16 port)262 int dissect_on_port(char *name, u_int16 port)
263 {
264 struct dissect_entry *e;
265
266 /*
267 * return E_SUCCESS if at least one port is bound
268 * to the dissector name
269 */
270 SLIST_FOREACH (e, &dissect_list, next) {
271 if (!strcasecmp(e->name, name) && e->type == port) {
272 return E_SUCCESS;
273 }
274 }
275
276 return -E_NOTFOUND;
277 }
278
279 /*
280 * return E_SUCCESS if the dissector is on
281 * the specified port of the specified protocol (TCP or UDP)
282 */
dissect_on_port_level(char * name,u_int16 port,u_int8 level)283 int dissect_on_port_level(char *name, u_int16 port, u_int8 level)
284 {
285 struct dissect_entry *e;
286
287 /*
288 * return E_SUCCESS if at least one port is bound
289 * to the dissector name
290 */
291 SLIST_FOREACH (e, &dissect_list, next) {
292 if (!strcasecmp(e->name, name) && e->type == port && e->level == level) {
293 return E_SUCCESS;
294 }
295 }
296
297 return -E_NOTFOUND;
298 }
299
300
301 /* EOF */
302
303 // vim:ts=3:expandtab
304
305