1 /*
2     etterlog -- decode a stream and extract file from it
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 
23 #include <el.h>
24 #include <el_functions.h>
25 
26 #include <fcntl.h>
27 #ifdef HAVE_LIBGEN_H
28    #include <libgen.h>
29 #endif
30 
31 #ifdef OS_WINDOWS
32    #define MKDIR(path,acc)  mkdir(path)
33 #else
34    #define MKDIR(path,acc)  mkdir(path,acc)
35 #endif
36 
37 /* globals */
38 
39 static SLIST_HEAD (, dec_entry) extractor_table;
40 
41 struct dec_entry {
42    u_int8 level;
43    u_int32 type;
44    FUNC_EXTRACTOR_PTR(extractor);
45    SLIST_ENTRY (dec_entry) next;
46 };
47 
48 /*******************************************/
49 
50 /*
51  * decode the stream
52  */
decode_stream(struct stream_object * so)53 int decode_stream(struct stream_object *so)
54 {
55    struct so_list *pl;
56    FUNC_EXTRACTOR_PTR(app_extractor);
57    int ret = 0;
58 
59    /* get the port used by the stream, looking at the first packet */
60    pl = TAILQ_FIRST(&so->so_head);
61 
62    /*
63     * we should run the extractor on both the tcp/udp ports
64     * since we may be interested in both client and server traffic.
65     */
66    switch (pl->po.L4.proto) {
67       case NL_TYPE_TCP:
68          app_extractor = get_extractor(APP_LAYER_TCP, ntohs(pl->po.L4.src));
69          EXECUTE_EXTRACTOR(app_extractor, so, ret);
70          app_extractor = get_extractor(APP_LAYER_TCP, ntohs(pl->po.L4.dst));
71          EXECUTE_EXTRACTOR(app_extractor, so, ret);
72          break;
73 
74       case NL_TYPE_UDP:
75          app_extractor = get_extractor(APP_LAYER_UDP, ntohs(pl->po.L4.src));
76          EXECUTE_EXTRACTOR(app_extractor, so, ret);
77          app_extractor = get_extractor(APP_LAYER_UDP, ntohs(pl->po.L4.dst));
78          EXECUTE_EXTRACTOR(app_extractor, so, ret);
79          break;
80    }
81 
82    /* if at least one extractor has found something ret is positive */
83    return ret;
84 }
85 
86 
87 /*
88  * add a extractor to the extractors table
89  */
add_extractor(u_int8 level,u_int32 type,FUNC_EXTRACTOR_PTR (extractor))90 void add_extractor(u_int8 level, u_int32 type, FUNC_EXTRACTOR_PTR(extractor))
91 {
92    struct dec_entry *e;
93 
94    SAFE_CALLOC(e, 1, sizeof(struct dec_entry));
95 
96    e->level = level;
97    e->type = type;
98    e->extractor = extractor;
99 
100    SLIST_INSERT_HEAD(&extractor_table, e, next);
101 
102    return;
103 }
104 
105 
106 /*
107  * get a extractor from the extractors table
108  */
get_extractor(u_int8 level,u_int32 type)109 void * get_extractor(u_int8 level, u_int32 type)
110 {
111    struct dec_entry *e;
112    void *ret;
113 
114    SLIST_FOREACH (e, &extractor_table, next) {
115       if (e->level == level && e->type == type) {
116          ret = (void *)e->extractor;
117          return ret;
118       }
119    }
120 
121    return NULL;
122 }
123 
124 /*
125  * open a file to write into.
126  * the file are saved in a subdirectories structure like this:
127  *    - host
128  *       - proto
129  *          - stealed_file
130  * e.g.:
131  *    - 192.168.0.1
132  *       - HTTP
133  *          - images
134  *             - a.gif
135  *             - b.gif
136  *          - styles
137  *             - style.css
138  *          - index.html
139  *          - foo.php
140  */
decode_to_file(char * host,char * proto,char * file)141 int decode_to_file(char *host, char *proto, char *file)
142 {
143 #define BASE_DIR  "./decoded_files"
144    char dir[1024];
145    char *p;
146    char *path = strdup(file);
147    char *filetmp = strdup(file);
148    int fd;
149 
150    /* always create the base, host and proto directory */
151    strcpy(dir, BASE_DIR);
152    MKDIR(dir, 0700);
153    strlcat(dir, "/", sizeof(dir));
154    strlcat(dir, host, sizeof(dir));
155    MKDIR(dir, 0700);
156    strlcat(dir, "/", sizeof(dir));
157    strlcat(dir, proto, sizeof(dir));
158    MKDIR(dir, 0700);
159 
160    /* now 'dir' contains "BASE_DIR/host/proto" */
161 
162    /* parse the file to be created and create the required subdirectories */
163    for (p = strsep(&path, "/"); p != NULL; p = strsep(&path, "/")) {
164       strlcat(dir, "/", sizeof(dir));
165       strlcat(dir, p, sizeof(dir));
166 
167       /* the token is a directory, create it */
168       if (strcmp(p, basename(filetmp))) {
169          MKDIR(dir, 0700);
170       } else {
171          /* exit the parsing and open the file */
172          break;
173       }
174    }
175 
176    /* actually open the file */
177    fd = open(dir, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0600);
178 
179    SAFE_FREE(filetmp);
180    SAFE_FREE(path);
181 
182    return fd;
183 }
184 
185 
186 /* EOF */
187 
188 // vim:ts=3:expandtab
189 
190