1 /*
2 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3 * Version 2, December 2004
4 *
5 * Copyright (C) 2012-2013 Sebastien Tricaud <sebastien@honeynet.org>
6 *
7 * Everyone is permitted to copy and distribute verbatim or modified
8 * copies of this license document, and changing it is allowed as long
9 * as the name is changed.
10 *
11 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
12 * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
13 *
14 * 0. You just DO WHAT THE FUCK YOU WANT TO.
15 */
16
17 #ifdef LINUX
18 #define _GNU_SOURCE
19 #endif
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <dirent.h>
24 #include <string.h>
25 #include <stdint.h>
26
27 #include <faup/faup.h>
28 #include <faup/datadir.h>
29 #include <faup/modules.h>
30 #include <faup/output.h>
31
faup_modules_new(faup_handler_t * fh)32 int faup_modules_new(faup_handler_t *fh)
33 {
34 int count;
35
36 if (!fh->options) {
37 fprintf(stderr, "Options have not been initialized! Make sure they are set before calling %s\n", __FUNCTION__);
38 return -1;
39 }
40
41 switch(fh->options->exec_modules) {
42 case FAUP_MODULES_NOEXEC:
43 fh->modules = NULL;
44 break;
45 case FAUP_MODULES_EXECPATH:
46 fh->modules = faup_modules_load_from_datadir();
47 break;
48 case FAUP_MODULES_EXECARG:
49 fh->modules = faup_modules_load_from_arg(fh->options->modules_argv, fh->options->modules_argc);
50 break;
51 default:
52 fprintf(stderr, "*** Huh? We should never be there (%s)!\n", __FUNCTION__);
53 }
54
55 return 0;
56 }
57
faup_modules_terminate(faup_modules_t * modules)58 void faup_modules_terminate(faup_modules_t *modules)
59 {
60 if (!modules) {
61 return;
62 }
63
64 int count = 0;
65 while (count < modules->nb_modules) {
66 if (modules->module[count].lua_state) {
67 lua_close(modules->module[count].lua_state);
68 }
69 if (modules->module[count].module_path) {
70 free(modules->module[count].module_path);
71 }
72 free(modules->module[count].module_name);
73 count++;
74 }
75
76 free(modules->module);
77 free(modules);
78 }
79
faup_modules_load_from_datadir(void)80 faup_modules_t *faup_modules_load_from_datadir(void)
81 {
82 faup_modules_t *modules = NULL;
83 int count = 0;
84
85 modules = malloc(sizeof(faup_modules_t));
86 if (!modules) {
87 fprintf(stderr, "Cannot allocate modules!\n");
88 return NULL;
89 }
90 modules->nb_modules = faup_modules_foreach_filelist(NULL, NULL, NULL, NULL);
91 if (modules->nb_modules <= 0) {
92 // We have no modules enabled
93 free(modules);
94 return NULL;
95 }
96 modules->module = malloc(sizeof(faup_module_t) * modules->nb_modules);
97 if (!modules->module) {
98 fprintf(stderr, "Cannot allocate modules->module!\n");
99 free(modules);
100 return NULL;
101 }
102 faup_modules_foreach_filelist(modules, NULL, faup_module_register, (void *)(intptr_t)count);
103
104 return modules;
105 }
106
faup_modules_load_from_arg(char ** argv,int argc)107 faup_modules_t *faup_modules_load_from_arg(char **argv, int argc)
108 {
109 faup_modules_t *modules = NULL;
110 FILE *fp;
111 int count;
112 int modules_that_do_not_count = 0;
113 int retval;
114
115
116 bool a_module_was_registered;
117
118 modules = malloc(sizeof(faup_modules_t));
119 if (!modules) {
120 fprintf(stderr, "Cannot allocate modules in %s\n", __FUNCTION__);
121 return NULL;
122 }
123 modules->module = malloc(sizeof(faup_module_t) * argc);
124 modules->nb_modules = 0;
125 if (!modules->module) {
126 fprintf(stderr, "Cannot allocate modules->module in %s\n", __FUNCTION__);
127 free(modules);
128 return NULL;
129 }
130 for (count = 0; count < argc; count++) {
131 a_module_was_registered = false;
132 // We try first to open a local file
133 fp = fopen(argv[count], "r");
134 if (fp) { // Found
135 fclose(fp);
136
137 retval = faup_module_register(modules, NULL, argv[count], NULL, count - modules_that_do_not_count);
138 if (retval == 0) {
139 modules->nb_modules++;
140 a_module_was_registered = true;
141 }
142 } else {
143 // The module was not discovered localy, so we get it from "modules_available"
144 char *load_path = NULL;
145 char *available_module = NULL;
146 char *module_to_load = argv[count];
147
148 load_path = malloc(17 /* modules_available */ + 1 /* FAUP_OS_DIRSEP */ + strlen(module_to_load));
149 if (!load_path) {
150 fprintf(stderr, "Cannot Allocate Modules Loading Path!");
151 return NULL;
152 }
153 /* retval = asprintf(&load_path, "modules_available%s%s", FAUP_OS_DIRSEP, argv[count]); */
154 retval = asprintf(&load_path, "modules_available");
155 available_module = faup_datadir_get_file(load_path, false);
156 free(load_path);
157
158 fp = fopen(available_module, "r");
159 if (fp) {
160 retval = faup_module_register(modules, NULL, available_module, NULL, count - modules_that_do_not_count);
161 if (retval == 0) {
162 modules->nb_modules++;
163 a_module_was_registered = true;
164
165 }
166 fclose(fp);
167 } else {
168 fprintf(stderr, "Cannot register the module '%s': Not found in modules_available nor local path!\n", argv[count]);
169 }
170
171 }
172
173 if (!a_module_was_registered) {
174 modules_that_do_not_count++;
175 }
176
177 }
178
179 return modules;
180 }
181
182
faup_module_register(faup_modules_t * modules,char * modules_dir,char * module,void * user_data,int count)183 int faup_module_register(faup_modules_t *modules, char *modules_dir, char *module, void *user_data, int count)
184 {
185 int retval;
186
187 // printf("Register module with module %s and count %d\n", module, count);
188
189 if (modules_dir) {
190 retval = asprintf(&modules->module[count].module_path, "%s%s%s", modules_dir, FAUP_OS_DIRSEP, module);
191 if (retval < 0) {
192 fprintf(stderr, "Cannot allocate in %s with parameter '%s%s%s'\n", __FUNCTION__, modules_dir, FAUP_OS_DIRSEP, module);
193 return -1;
194 }
195 } else {
196 modules->module[count].module_path = strdup(module);
197 }
198
199 modules->module[count].module_name = strdup(module);
200
201 //#ifdef FAUP_DEBUG
202 // printf("Loading module from path:%s\n", modules->module[count].module_path);
203 //#endif
204
205 modules->module[count].lua_state = luaL_newstate();
206 luaL_openlibs(modules->module[count].lua_state);
207
208 retval = luaL_loadfile(modules->module[count].lua_state, modules->module[count].module_path);
209 if (retval) goto err;
210
211 // Lua library requires that we load the file first
212 retval = lua_pcall(modules->module[count].lua_state, 0, 0, 0);
213 if (retval) goto err;
214
215 return 0;
216
217 err:
218 fprintf(stderr, "*** Error(%s): %s\n", __FUNCTION__, lua_tostring(modules->module[count].lua_state, -1));
219 free(modules->module[count].module_path);
220 return -1;
221 }
222
223
faup_modules_foreach_filelist(faup_modules_t * modules,char * force_path,int (* cb_modules_foreach)(faup_modules_t * modules,char * modules_dir,char * module,void * user_data,int count),void * user_data)224 int faup_modules_foreach_filelist(faup_modules_t *modules, char *force_path, int (*cb_modules_foreach)(faup_modules_t *modules, char *modules_dir, char *module, void *user_data, int count), void *user_data)
225 {
226 char *modules_dir;
227 DIR *modules_dir_fp;
228 struct dirent *modules_dir_file;
229 int count = 0;
230
231 if (!force_path) {
232 modules_dir = faup_datadir_get_file("modules_enabled", false);
233 } else {
234 modules_dir = force_path;
235 }
236 modules_dir_fp = opendir(modules_dir);
237 if (!modules_dir_fp) {
238 free(modules_dir);
239 return -1;
240 }
241
242 modules_dir_file = readdir(modules_dir_fp);
243 while (modules_dir_file) {
244 if (modules_dir_file->d_name[0] != '.') {
245 size_t filelen = strlen(modules_dir_file->d_name);
246 if (filelen > FAUP_MODULE_NAME_MAXLEN) {
247 fprintf(stderr, "*** Error(%s): Module file name too long (>128). Won't execute!\n", __FUNCTION__);
248 count++;
249 continue;
250 }
251
252 if (cb_modules_foreach) cb_modules_foreach(modules, modules_dir, modules_dir_file->d_name, user_data, count);
253 count++;
254 }
255 modules_dir_file = readdir(modules_dir_fp);
256 }
257 closedir(modules_dir_fp);
258
259 if (!force_path) {
260 free(modules_dir);
261 }
262
263 return count;
264 }
265
266
faup_modules_list(faup_modules_t * modules,char * modules_dir,char * module,void * user_data,int count)267 void faup_modules_list(faup_modules_t *modules, char *modules_dir, char *module, void *user_data, int count)
268 {
269 printf("%s\n", module);
270 }
271
faup_modules_decode_url_start(faup_handler_t const * fh,const char * url,size_t url_len)272 faup_modules_transformed_url_t *faup_modules_decode_url_start(faup_handler_t const* fh, const char *url, size_t url_len)
273 {
274 faup_modules_t *modules = (faup_modules_t *)fh->modules;
275 faup_modules_transformed_url_t *transformed_url = NULL;
276 const char *new_url = NULL;
277 int count;
278 int retval;
279
280 // No modules have been loaded, no need to go further!
281 if (!modules) {
282 return NULL;
283 }
284
285 transformed_url = malloc(sizeof(faup_modules_transformed_url_t));
286 if (!transformed_url) {
287 fprintf(stderr, "(%s) Cannot allocate URL for transformed url by modules!\n", __FUNCTION__);
288 return NULL;
289 }
290
291 // For every loaded module, we run the function 'faup_url_in'
292 for (count=0; count < modules->nb_modules; count++) {
293 lua_getglobal(modules->module[count].lua_state, "faup_url_in");
294 if (!new_url) {
295 lua_pushstring(modules->module[count].lua_state, url);
296 } else {
297 lua_pushstring(modules->module[count].lua_state, new_url);
298 }
299 retval = lua_pcall(modules->module[count].lua_state, 1, 1, 0);
300 if (retval) {
301 // This module has no faup_url_in function. Nothing wrong here, we can continue
302 continue;
303 //fprintf(stderr, "*** Error(%s): %s\n", __FUNCTION__, lua_tostring(modules->module[count].lua_state, -1));
304 //return NULL;
305 }
306
307 new_url = lua_tostring(modules->module[count].lua_state, -1);
308 }
309
310 if (new_url) {
311 //printf("new url=%s, size=%zd\n", new_url, strlen(new_url));
312 transformed_url->url = new_url;
313 transformed_url->url_len = strlen(new_url);
314 } else {
315 transformed_url->url = url;
316 transformed_url->url_len = url_len;
317 }
318
319 return transformed_url;
320 }
321
faup_modules_transformed_url_free(faup_modules_transformed_url_t * transformed_url)322 void faup_modules_transformed_url_free(faup_modules_transformed_url_t *transformed_url)
323 {
324 //free((void *)transformed_url->url);
325 free(transformed_url);
326 }
327
_faup_add_keyval_dict(faup_modules_t * modules,int count,char * key,int val)328 void _faup_add_keyval_dict(faup_modules_t *modules, int count, char *key, int val)
329 {
330 lua_pushstring(modules->module[count].lua_state, key); // -2
331 lua_pushinteger(modules->module[count].lua_state, val); // -3
332 lua_settable(modules->module[count].lua_state, -3);
333
334 }
335
_faup_add_keyvalstr_dict(faup_modules_t * modules,int count,char * key,char * val)336 void _faup_add_keyvalstr_dict(faup_modules_t *modules, int count, char *key, char *val)
337 {
338 lua_pushstring(modules->module[count].lua_state, key); // -2
339 lua_pushstring(modules->module[count].lua_state, val); // -2
340 lua_settable(modules->module[count].lua_state, -3);
341
342 }
343
344
_faup_add_feature(faup_modules_t * modules,int count,faup_feature_t feature,char * pos_key,char * size_key)345 void _faup_add_feature(faup_modules_t *modules, int count, faup_feature_t feature, char *pos_key, char *size_key)
346 {
347 if (faup_features_exist(feature)) {
348 _faup_add_keyval_dict(modules, count, pos_key, feature.pos);
349 _faup_add_keyval_dict(modules, count, size_key, feature.size);
350 } else {
351 _faup_add_keyval_dict(modules, count, pos_key, -1);
352 _faup_add_keyval_dict(modules, count, size_key, 0);
353 }
354 }
355
faup_modules_url_output(faup_handler_t * fh,FILE * out)356 bool faup_modules_url_output(faup_handler_t *fh, FILE* out)
357 {
358 int retval;
359 int count;
360 faup_modules_t *modules = fh->modules;
361 const char *transformed_url = NULL;
362
363 bool module_executed = false;
364
365 if (!modules) {
366 return false;
367 }
368
369 for (count = 0; count < modules->nb_modules; count++) {
370 lua_getglobal(modules->module[count].lua_state, "faup_output");
371 if(!lua_isfunction(modules->module[count].lua_state, -1)) {
372 //printf("No such function: 'faup_output'\n");
373 // Since that function does not exists in the module, we skip it!
374 continue;
375 }
376
377 lua_pushstring(modules->module[count].lua_state, fh->faup.org_str);
378
379 // Table for positions
380 lua_newtable(modules->module[count].lua_state); // -1
381
382 _faup_add_feature(modules, count, fh->faup.features.scheme, "scheme.pos", "scheme.size");
383 _faup_add_feature(modules, count, fh->faup.features.hierarchical, "hierarchical.pos", "hierarchical.size");
384 _faup_add_feature(modules, count, fh->faup.features.credential, "credential.pos", "credential.size");
385 _faup_add_feature(modules, count, fh->faup.features.host, "host.pos", "host.size");
386 _faup_add_feature(modules, count, fh->faup.features.subdomain, "subdomain.pos", "subdomain.size");
387 _faup_add_feature(modules, count, fh->faup.features.domain, "domain.pos", "domain.size");
388 _faup_add_feature(modules, count, fh->faup.features.domain_without_tld, "domain_without_tld.pos", "domain_without_tld.size");
389 _faup_add_feature(modules, count, fh->faup.features.tld, "tld.pos", "tld.size");
390 _faup_add_feature(modules, count, fh->faup.features.port, "port.pos", "port.size");
391 _faup_add_feature(modules, count, fh->faup.features.resource_path, "resource_path.pos", "resource_path.size");
392 _faup_add_feature(modules, count, fh->faup.features.query_string, "query_string.pos", "query_string.size");
393 _faup_add_feature(modules, count, fh->faup.features.fragment, "fragment.pos", "fragment.size");
394
395 _faup_add_keyvalstr_dict(modules, count, "url_type", faup_output_get_string_from_url_type(fh));
396
397
398 // If the function does not exists, we just ignore it
399 retval = lua_pcall(modules->module[count].lua_state, 2, 2, 0);
400 if (retval == 0) {
401 module_executed = true;
402 transformed_url = lua_tostring(modules->module[count].lua_state, -1);
403 if (transformed_url) {
404 fh->faup.org_str = transformed_url;
405 }
406
407 lua_pushnil(modules->module[count].lua_state);
408 const char *k;
409 int v;
410
411 while (lua_next(modules->module[count].lua_state, -2)) { // The table is is -2 in the stack
412 v = lua_tointeger(modules->module[count].lua_state, -1);
413 lua_pop(modules->module[count].lua_state, 1);
414 k = lua_tostring(modules->module[count].lua_state, -1);
415
416 if (!strcmp(k, "scheme.pos")) {
417 fh->faup.features.scheme.pos = v;
418 }
419 if (!strcmp(k, "scheme.size")) {
420 fh->faup.features.scheme.size = v;
421
422 }
423 if (!strcmp(k, "hierarchical.pos")) {
424 fh->faup.features.hierarchical.pos = v;
425 }
426 if (!strcmp(k, "hierarchical.size")) {
427 fh->faup.features.hierarchical.size = v;
428
429 }
430 if (!strcmp(k, "credential.pos")) {
431 fh->faup.features.credential.pos = v;
432 }
433 if (!strcmp(k, "credential.size")) {
434 fh->faup.features.credential.size = v;
435
436 }
437 if (!strcmp(k, "host.pos")) {
438 fh->faup.features.host.pos = v;
439 }
440 if (!strcmp(k, "host.size")) {
441 fh->faup.features.host.size = v;
442
443 }
444 if (!strcmp(k, "subdomain.pos")) {
445 fh->faup.features.subdomain.pos = v;
446 }
447 if (!strcmp(k, "subdomain.size")) {
448 fh->faup.features.subdomain.size = v;
449
450 }
451 if (!strcmp(k, "domain.pos")) {
452 fh->faup.features.domain.pos = v;
453 }
454 if (!strcmp(k, "domain.size")) {
455 fh->faup.features.domain.size = v;
456
457 }
458 if (!strcmp(k, "domain_without_tld.pos")) {
459 fh->faup.features.domain_without_tld.pos = v;
460 }
461 if (!strcmp(k, "domain_without_tld.size")) {
462 fh->faup.features.domain_without_tld.size = v;
463
464 }
465 if (!strcmp(k, "tld.pos")) {
466 fh->faup.features.tld.pos = v;
467 }
468 if (!strcmp(k, "tld.size")) {
469 fh->faup.features.tld.size = v;
470
471 }
472 if (!strcmp(k, "port.pos")) {
473 fh->faup.features.port.pos = v;
474 }
475 if (!strcmp(k, "port.size")) {
476 fh->faup.features.port.size = v;
477
478 }
479 if (!strcmp(k, "resource_path.pos")) {
480 fh->faup.features.resource_path.pos = v;
481 }
482 if (!strcmp(k, "resource_path.size")) {
483 fh->faup.features.resource_path.size = v;
484
485 }
486 if (!strcmp(k, "query_string.pos")) {
487 fh->faup.features.query_string.pos = v;
488 }
489 if (!strcmp(k, "query_string.size")) {
490 fh->faup.features.query_string.size = v;
491
492 }
493 if (!strcmp(k, "fragment.pos")) {
494 fh->faup.features.fragment.pos = v;
495 }
496 if (!strcmp(k, "fragment.size")) {
497 fh->faup.features.fragment.size = v;
498
499 }
500 }
501 } else { // if (retval == 0) {
502 fprintf(stderr, "*** Error(%s)[in script:%s]: %s\n", __FUNCTION__, modules->module[count].module_name, lua_tostring(modules->module[count].lua_state, -1));
503 }
504 }
505
506 return module_executed;
507 }
508
509