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