1 /*
2  * init_wslua.c
3  *
4  * Wireshark's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14 
15 #include "config.h"
16 
17 #include "wslua.h"
18 #include "init_wslua.h"
19 #include <epan/dissectors/packet-frame.h>
20 #include <math.h>
21 #include <stdio.h>
22 #include <epan/expert.h>
23 #include <epan/ex-opt.h>
24 #include <wsutil/privileges.h>
25 #include <wsutil/file_util.h>
26 #include <wsutil/wslog.h>
27 
28 /* linked list of Lua plugins */
29 typedef struct _wslua_plugin {
30     gchar       *name;            /**< plugin name */
31     gchar       *version;         /**< plugin version */
32     gchar       *filename;        /**< plugin filename */
33     struct _wslua_plugin *next;
34 } wslua_plugin;
35 
36 static wslua_plugin *wslua_plugin_list = NULL;
37 
38 static lua_State* L = NULL;
39 
40 /* XXX: global variables? Really?? Yuck. These could be done differently,
41    using the Lua registry */
42 packet_info* lua_pinfo;
43 struct _wslua_treeitem* lua_tree;
44 tvbuff_t* lua_tvb;
45 wslua_logger_t wslua_logger;
46 int lua_dissectors_table_ref = LUA_NOREF;
47 int lua_heur_dissectors_table_ref = LUA_NOREF;
48 
49 static int proto_lua = -1;
50 
51 static int hf_wslua_fake = -1;
52 static int hf_wslua_text = -1;
53 
54 static expert_field ei_lua_error = EI_INIT;
55 
56 static expert_field ei_lua_proto_checksum_comment = EI_INIT;
57 static expert_field ei_lua_proto_checksum_chat    = EI_INIT;
58 static expert_field ei_lua_proto_checksum_note    = EI_INIT;
59 static expert_field ei_lua_proto_checksum_warn    = EI_INIT;
60 static expert_field ei_lua_proto_checksum_error   = EI_INIT;
61 
62 static expert_field ei_lua_proto_sequence_comment = EI_INIT;
63 static expert_field ei_lua_proto_sequence_chat    = EI_INIT;
64 static expert_field ei_lua_proto_sequence_note    = EI_INIT;
65 static expert_field ei_lua_proto_sequence_warn    = EI_INIT;
66 static expert_field ei_lua_proto_sequence_error   = EI_INIT;
67 
68 static expert_field ei_lua_proto_response_comment = EI_INIT;
69 static expert_field ei_lua_proto_response_chat    = EI_INIT;
70 static expert_field ei_lua_proto_response_note    = EI_INIT;
71 static expert_field ei_lua_proto_response_warn    = EI_INIT;
72 static expert_field ei_lua_proto_response_error   = EI_INIT;
73 
74 static expert_field ei_lua_proto_request_comment = EI_INIT;
75 static expert_field ei_lua_proto_request_chat    = EI_INIT;
76 static expert_field ei_lua_proto_request_note    = EI_INIT;
77 static expert_field ei_lua_proto_request_warn    = EI_INIT;
78 static expert_field ei_lua_proto_request_error   = EI_INIT;
79 
80 static expert_field ei_lua_proto_undecoded_comment = EI_INIT;
81 static expert_field ei_lua_proto_undecoded_chat    = EI_INIT;
82 static expert_field ei_lua_proto_undecoded_note    = EI_INIT;
83 static expert_field ei_lua_proto_undecoded_warn    = EI_INIT;
84 static expert_field ei_lua_proto_undecoded_error   = EI_INIT;
85 
86 static expert_field ei_lua_proto_reassemble_comment = EI_INIT;
87 static expert_field ei_lua_proto_reassemble_chat    = EI_INIT;
88 static expert_field ei_lua_proto_reassemble_note    = EI_INIT;
89 static expert_field ei_lua_proto_reassemble_warn    = EI_INIT;
90 static expert_field ei_lua_proto_reassemble_error   = EI_INIT;
91 
92 static expert_field ei_lua_proto_malformed_comment = EI_INIT;
93 static expert_field ei_lua_proto_malformed_chat    = EI_INIT;
94 static expert_field ei_lua_proto_malformed_note    = EI_INIT;
95 static expert_field ei_lua_proto_malformed_warn    = EI_INIT;
96 static expert_field ei_lua_proto_malformed_error   = EI_INIT;
97 
98 static expert_field ei_lua_proto_debug_comment = EI_INIT;
99 static expert_field ei_lua_proto_debug_chat    = EI_INIT;
100 static expert_field ei_lua_proto_debug_note    = EI_INIT;
101 static expert_field ei_lua_proto_debug_warn    = EI_INIT;
102 static expert_field ei_lua_proto_debug_error   = EI_INIT;
103 
104 static expert_field ei_lua_proto_protocol_comment = EI_INIT;
105 static expert_field ei_lua_proto_protocol_chat    = EI_INIT;
106 static expert_field ei_lua_proto_protocol_note    = EI_INIT;
107 static expert_field ei_lua_proto_protocol_warn    = EI_INIT;
108 static expert_field ei_lua_proto_protocol_error   = EI_INIT;
109 
110 static expert_field ei_lua_proto_security_comment = EI_INIT;
111 static expert_field ei_lua_proto_security_chat    = EI_INIT;
112 static expert_field ei_lua_proto_security_note    = EI_INIT;
113 static expert_field ei_lua_proto_security_warn    = EI_INIT;
114 static expert_field ei_lua_proto_security_error   = EI_INIT;
115 
116 static expert_field ei_lua_proto_comments_comment = EI_INIT;
117 static expert_field ei_lua_proto_comments_chat    = EI_INIT;
118 static expert_field ei_lua_proto_comments_note    = EI_INIT;
119 static expert_field ei_lua_proto_comments_warn    = EI_INIT;
120 static expert_field ei_lua_proto_comments_error   = EI_INIT;
121 
122 static expert_field ei_lua_proto_decryption_comment = EI_INIT;
123 static expert_field ei_lua_proto_decryption_chat    = EI_INIT;
124 static expert_field ei_lua_proto_decryption_note    = EI_INIT;
125 static expert_field ei_lua_proto_decryption_warn    = EI_INIT;
126 static expert_field ei_lua_proto_decryption_error   = EI_INIT;
127 
128 static expert_field ei_lua_proto_assumption_comment = EI_INIT;
129 static expert_field ei_lua_proto_assumption_chat    = EI_INIT;
130 static expert_field ei_lua_proto_assumption_note    = EI_INIT;
131 static expert_field ei_lua_proto_assumption_warn    = EI_INIT;
132 static expert_field ei_lua_proto_assumption_error   = EI_INIT;
133 
134 static expert_field ei_lua_proto_deprecated_comment = EI_INIT;
135 static expert_field ei_lua_proto_deprecated_chat    = EI_INIT;
136 static expert_field ei_lua_proto_deprecated_note    = EI_INIT;
137 static expert_field ei_lua_proto_deprecated_warn    = EI_INIT;
138 static expert_field ei_lua_proto_deprecated_error   = EI_INIT;
139 
140 static gboolean
lua_pinfo_end(wmem_allocator_t * allocator _U_,wmem_cb_event_t event _U_,void * user_data _U_)141 lua_pinfo_end(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
142         void *user_data _U_)
143 {
144     clear_outstanding_Tvb();
145     clear_outstanding_TvbRange();
146     clear_outstanding_Pinfo();
147     clear_outstanding_Column();
148     clear_outstanding_Columns();
149     clear_outstanding_PrivateTable();
150     clear_outstanding_TreeItem();
151     clear_outstanding_FieldInfo();
152     clear_outstanding_FuncSavers();
153 
154     /* keep invoking this callback later? */
155     return FALSE;
156 }
157 
wslua_not_register_menu(lua_State * LS)158 static int wslua_not_register_menu(lua_State* LS) {
159     luaL_error(LS,"too late to register a menu");
160     return 0;
161 }
162 
163 /* a getter for wslua_tree.c's TreeItem_add_item_any() to use */
get_hf_wslua_text(void)164 int get_hf_wslua_text(void) {
165     return hf_wslua_text;
166 }
167 
dissect_lua(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)168 int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
169     int consumed_bytes = tvb_captured_length(tvb);
170     tvbuff_t *saved_lua_tvb = lua_tvb;
171     packet_info *saved_lua_pinfo = lua_pinfo;
172     struct _wslua_treeitem *saved_lua_tree = lua_tree;
173     lua_pinfo = pinfo;
174     lua_tvb = tvb;
175 
176     /*
177      * almost equivalent to Lua:
178      * dissectors[current_proto](tvb,pinfo,tree)
179      */
180 
181     lua_settop(L,0);
182 
183     lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
184 
185     lua_pushstring(L, pinfo->current_proto);
186     lua_gettable(L, -2);
187 
188     lua_remove(L,1);
189 
190 
191     if (lua_isfunction(L,1)) {
192 
193         push_Tvb(L,tvb);
194         push_Pinfo(L,pinfo);
195         lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
196         proto_item_set_hidden(lua_tree->item);
197 
198         if  ( lua_pcall(L,3,1,0) ) {
199             proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: %s", lua_tostring(L,-1));
200         } else {
201 
202             /* if the Lua dissector reported the consumed bytes, pass it to our caller */
203             if (lua_isnumber(L, -1)) {
204                 /* we got the consumed bytes or the missing bytes as a negative number */
205                 consumed_bytes = wslua_togint(L, -1);
206                 lua_pop(L, 1);
207             }
208         }
209 
210     } else {
211         proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
212                     "Lua Error: did not find the %s dissector in the dissectors table", pinfo->current_proto);
213     }
214 
215     wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL);
216 
217     lua_pinfo = saved_lua_pinfo;
218     lua_tree = saved_lua_tree;
219     lua_tvb = saved_lua_tvb;
220 
221     return consumed_bytes;
222 
223 }
224 
225 /** Type of a heuristic dissector, used in heur_dissector_add().
226  *
227  * @param tvb the tvbuff with the (remaining) packet data
228  * @param pinfo the packet info of this packet (additional info)
229  * @param tree the protocol tree to be build or NULL
230  * @return TRUE if the packet was recognized by the sub-dissector (stop dissection here)
231  */
heur_dissect_lua(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)232 gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
233     gboolean result = FALSE;
234     tvbuff_t *saved_lua_tvb = lua_tvb;
235     packet_info *saved_lua_pinfo = lua_pinfo;
236     struct _wslua_treeitem *saved_lua_tree = lua_tree;
237     lua_tvb = tvb;
238     lua_pinfo = pinfo;
239 
240     ws_assert(tvb && pinfo);
241 
242     if (!pinfo->heur_list_name || !pinfo->current_proto) {
243         proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
244                 "internal error in heur_dissect_lua: NULL list name or current proto");
245         return FALSE;
246     }
247 
248     /* heuristic functions are stored in a table in the registry; the registry has a
249      * table at reference lua_heur_dissectors_table_ref, and that table has keys for
250      * the heuristic listname (e.g., "udp", "tcp", etc.), and that key's value is a
251      * table of keys of the Proto->name, and their value is the function.
252      * So it's like registry[table_ref][heur_list_name][proto_name] = func
253      */
254 
255     lua_settop(L,0);
256 
257     /* get the table of all lua heuristic dissector lists */
258     lua_rawgeti(L, LUA_REGISTRYINDEX, lua_heur_dissectors_table_ref);
259 
260     /* get the table inside that, for the lua heuristic dissectors of the requested heur list */
261     if (!wslua_get_table(L, -1, pinfo->heur_list_name)) {
262         /* this shouldn't happen */
263         lua_settop(L,0);
264         proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
265                 "internal error in heur_dissect_lua: no %s heur list table", pinfo->heur_list_name);
266         return FALSE;
267     }
268 
269     /* get the table inside that, for the specific lua heuristic dissector */
270     if (!wslua_get_field(L,-1,pinfo->current_proto)) {
271         /* this shouldn't happen */
272         lua_settop(L,0);
273         proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
274                 "internal error in heur_dissect_lua: no %s heuristic dissector for list %s",
275                         pinfo->current_proto, pinfo->heur_list_name);
276         return FALSE;
277     }
278 
279     /* remove the table of all lists (the one in the registry) */
280     lua_remove(L,1);
281     /* remove the heur_list_name heur list table */
282     lua_remove(L,1);
283 
284     if (!lua_isfunction(L,-1)) {
285         /* this shouldn't happen */
286         lua_settop(L,0);
287         proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
288                 "internal error in heur_dissect_lua: %s heuristic dissector is not a function", pinfo->current_proto);
289         return FALSE;
290     }
291 
292     push_Tvb(L,tvb);
293     push_Pinfo(L,pinfo);
294     lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
295     proto_item_set_hidden(lua_tree->item);
296 
297     if  ( lua_pcall(L,3,1,0) ) {
298         proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
299                 "Lua Error: error calling %s heuristic dissector: %s", pinfo->current_proto, lua_tostring(L,-1));
300         lua_settop(L,0);
301     } else {
302         if (lua_isboolean(L, -1) || lua_isnil(L, -1)) {
303             result = lua_toboolean(L, -1);
304         } else if (lua_type(L, -1) == LUA_TNUMBER) {
305             result = lua_tointeger(L,-1) != 0 ? TRUE : FALSE;
306         } else {
307             proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
308                     "Lua Error: invalid return value from Lua %s heuristic dissector", pinfo->current_proto);
309         }
310         lua_pop(L, 1);
311     }
312 
313     wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL);
314 
315     lua_pinfo = saved_lua_pinfo;
316     lua_tree = saved_lua_tree;
317     lua_tvb = saved_lua_tvb;
318 
319     return result;
320 }
321 
iter_table_and_call(lua_State * LS,const gchar * table_name,lua_CFunction error_handler)322 static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFunction error_handler) {
323     lua_settop(LS,0);
324 
325     lua_pushcfunction(LS,error_handler);
326     lua_getglobal(LS, table_name);
327 
328     if (!lua_istable(LS, 2)) {
329         report_failure("Lua: either `%s' does not exist or it is not a table!\n",table_name);
330         lua_close(LS);
331         L = NULL;
332         return;
333     }
334 
335     lua_pushnil(LS);
336 
337     while (lua_next(LS, 2)) {
338         const gchar* name = lua_tostring(L,-2);
339 
340         if (lua_isfunction(LS,-1)) {
341 
342             if ( lua_pcall(LS,0,0,1) ) {
343                     lua_pop(LS,1);
344             }
345 
346         } else {
347             report_failure("Lua: Something not a function got its way into the %s.%s",table_name,name);
348             lua_close(LS);
349             L = NULL;
350             return;
351         }
352     }
353 
354     lua_settop(LS,0);
355 }
356 
357 
init_error_handler(lua_State * LS)358 static int init_error_handler(lua_State* LS) {
359     const gchar* error =  lua_tostring(LS,1);
360     report_failure("Lua: Error during execution of initialization:\n %s",error);
361     return 0;
362 }
363 
364 
365 static gboolean init_routine_initialized = FALSE;
wslua_init_routine(void)366 static void wslua_init_routine(void) {
367 
368     if ( ! init_routine_initialized ) {
369         /*
370          * This must be done only once during the entire life of
371          * tshark/wireshark, because it must be done only once per the life of
372          * the Lua state/engine, so we guard this with the boolean above;
373          * otherwise it would occur every time a file is opened (every time
374          * epan_new() is called).
375          *
376          * If we ever allow the Lua state to be restarted, or to have multiple
377          * Lua states, we'll need to change this.
378          */
379         lua_prime_all_fields(NULL);
380         init_routine_initialized = TRUE;
381     }
382 
383     if (L) {
384         iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler);
385     }
386 
387 }
388 
wslua_cleanup_routine(void)389 static void wslua_cleanup_routine(void) {
390     if (L) {
391         iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler);
392     }
393 }
394 
prefs_changed_error_handler(lua_State * LS)395 static int prefs_changed_error_handler(lua_State* LS) {
396     const gchar* error =  lua_tostring(LS,1);
397     report_failure("Lua: Error during execution of prefs apply callback:\n %s",error);
398     return 0;
399 }
400 
wslua_prefs_changed(void)401 void wslua_prefs_changed(void) {
402     if (L) {
403         iter_table_and_call(L, WSLUA_PREFS_CHANGED,prefs_changed_error_handler);
404     }
405 }
406 
getF(lua_State * LS _U_,void * ud,size_t * size)407 static const char *getF(lua_State *LS _U_, void *ud, size_t *size)
408 {
409     FILE *f=(FILE *)ud;
410     static char buff[512];
411     if (feof(f)) return NULL;
412     *size=fread(buff,1,sizeof(buff),f);
413     return (*size>0) ? buff : NULL;
414 }
415 
error_handler_with_callback(lua_State * LS)416 static int error_handler_with_callback(lua_State *LS) {
417 #if LUA_VERSION_NUM >= 502
418     const char *msg = lua_tostring(LS, 1);
419     luaL_traceback(LS, LS, msg, 1);     /* push message with traceback.  */
420     lua_remove(LS, -2);                 /* remove original msg */
421 #else
422     /* Return error message, unmodified */
423     (void)LS;
424 #endif
425     return 1;
426 }
427 
wslua_add_plugin(const gchar * name,const gchar * version,const gchar * filename)428 static void wslua_add_plugin(const gchar *name, const gchar *version, const gchar *filename)
429 {
430     wslua_plugin *new_plug, *lua_plug;
431 
432     lua_plug = wslua_plugin_list;
433     new_plug = g_new(wslua_plugin, 1);
434 
435     if (!lua_plug) { /* the list is empty */
436         wslua_plugin_list = new_plug;
437     } else {
438         while (lua_plug->next != NULL) {
439             lua_plug = lua_plug->next;
440         }
441         lua_plug->next = new_plug;
442     }
443 
444     new_plug->name = g_strdup(name);
445     new_plug->version = g_strdup(version);
446     new_plug->filename = g_strdup(filename);
447     new_plug->next = NULL;
448 }
449 
wslua_clear_plugin_list(void)450 static void wslua_clear_plugin_list(void)
451 {
452     wslua_plugin *lua_plug;
453 
454     while (wslua_plugin_list) {
455         lua_plug = wslua_plugin_list;
456         wslua_plugin_list = wslua_plugin_list->next;
457         g_free (lua_plug->name);
458         g_free (lua_plug->version);
459         g_free (lua_plug->filename);
460         g_free (lua_plug);
461     }
462 }
463 
lua_script_push_args(const int script_num)464 static int lua_script_push_args(const int script_num) {
465     gchar* argname = g_strdup_printf("lua_script%d", script_num);
466     const gchar* argvalue = NULL;
467     int i, count = ex_opt_count(argname);
468 
469     for (i = 0; i < count; i++) {
470         argvalue = ex_opt_get_nth(argname, i);
471         lua_pushstring(L,argvalue);
472     }
473 
474     g_free(argname);
475     return count;
476 }
477 
478 #define FILE_NAME_KEY "__FILE__"
479 #define DIR_NAME_KEY "__DIR__"
480 #define DIR_SEP_NAME_KEY "__DIR_SEPARATOR__"
481 /* assumes a loaded chunk's function is on top of stack */
set_file_environment(const gchar * filename,const gchar * dirname)482 static void set_file_environment(const gchar* filename, const gchar* dirname) {
483     const char* path;
484 
485     lua_newtable(L); /* environment for script (index 3) */
486 
487     lua_pushstring(L, filename); /* tell the script about its filename */
488     lua_setfield(L, -2, FILE_NAME_KEY); /* make it accessible at __FILE__ */
489 
490     lua_pushstring(L, dirname); /* tell the script about its dirname */
491     lua_setfield(L, -2, DIR_NAME_KEY); /* make it accessible at __DIR__ */
492 
493     lua_pushstring(L, G_DIR_SEPARATOR_S); /* tell the script the directory separator */
494     lua_setfield(L, -2, DIR_SEP_NAME_KEY); /* make it accessible at __DIR__ */
495 
496     lua_newtable(L); /* new metatable */
497 
498 #if LUA_VERSION_NUM >= 502
499     lua_pushglobaltable(L);
500 #else
501     lua_pushvalue(L, LUA_GLOBALSINDEX);
502 #endif
503     /* prepend the directory name to _G.package.path */
504     lua_getfield(L, -1, "package"); /* get the package table from the global table */
505     lua_getfield(L, -1, "path");    /* get the path field from the package table */
506     path = luaL_checkstring(L, -1); /* get the path string */
507     lua_pop(L, 1);                  /* pop the path string */
508     /* prepend the various paths */
509     lua_pushfstring(L, "%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s",
510                     dirname, get_plugins_pers_dir(), get_plugins_dir(), path);
511     lua_setfield(L, -2, "path");    /* set the new string to be the path field of the package table */
512     lua_setfield(L, -2, "package"); /* set the package table to be the package field of the global */
513 
514     lua_setfield(L, -2, "__index"); /* make metatable's __index point to global table */
515 
516     lua_setmetatable(L, -2); /* pop metatable, set it as metatable of environment */
517 
518 #if LUA_VERSION_NUM >= 502
519     lua_setupvalue(L, -2, 1); /* pop environment and assign it to upvalue 1 */
520 #else
521     lua_setfenv(L, -2); /* pop environment and set it as the func's environment */
522 #endif
523 }
524 
525 
526 /* If file_count > 0 then it's a command-line-added user script, and the count
527  * represents which user script it is (first=1, second=2, etc.).
528  * If dirname != NULL, then it's a user script and the dirname will get put in a file environment
529  * If dirname == NULL then it's a wireshark script and no file environment is created
530  */
lua_load_script(const gchar * filename,const gchar * dirname,const int file_count)531 static gboolean lua_load_script(const gchar* filename, const gchar* dirname, const int file_count) {
532     FILE* file;
533     int error;
534     int numargs = 0;
535 
536     if (! ( file = ws_fopen(filename,"r")) ) {
537         report_open_failure(filename,errno,FALSE);
538         return FALSE;
539     }
540 
541     lua_settop(L,0);
542 
543     lua_pushcfunction(L, error_handler_with_callback);
544     /* The source argument should start with '@' to indicate a file. */
545     lua_pushfstring(L, "@%s", filename);
546 
547 #if LUA_VERSION_NUM >= 502
548     error = lua_load(L, getF, file, lua_tostring(L, -1), NULL);
549 #else
550     error = lua_load(L, getF, file, lua_tostring(L, -1));
551 #endif
552 
553     switch (error) {
554         case 0: /* LUA_OK */
555             if (dirname) {
556                 set_file_environment(filename, dirname);
557             }
558             if (file_count > 0) {
559                 numargs = lua_script_push_args(file_count);
560             }
561             error = lua_pcall(L, numargs, 0, 1);
562             if (error) {
563                 switch (error) {
564                     case LUA_ERRRUN:
565                         report_failure("Lua: Error during loading:\n%s", lua_tostring(L, -1));
566                         break;
567                     case LUA_ERRMEM:
568                         report_failure("Lua: Error during loading: out of memory");
569                         break;
570                     case LUA_ERRERR:
571                         report_failure("Lua: Error during loading: error while retrieving error message");
572                         break;
573                     default:
574                         report_failure("Lua: Error during loading: unknown error %d", error);
575                         break;
576                 }
577             }
578             break;
579 
580         case LUA_ERRSYNTAX:
581             report_failure("Lua: syntax error: %s", lua_tostring(L, -1));
582             break;
583 
584         case LUA_ERRMEM:
585             report_failure("Lua: memory allocation error during precompilation of %s", filename);
586             break;
587 
588         default:
589             report_failure("Lua: unknown error during precompilation of %s: %d", filename, error);
590             break;
591     }
592     fclose(file);
593     lua_pop(L, 2);  /* pop the filename and error handler */
594     return error == 0;
595 }
596 
597 /* This one is used to load the init.lua scripts, or anything else
598  * that shouldn't really be considered a real plugin.
599  */
lua_load_internal_script(const gchar * filename)600 static gboolean lua_load_internal_script(const gchar* filename) {
601     return lua_load_script(filename, NULL, 0);
602 }
603 
604 /* This one is used to load plugins: either from the plugin directories,
605  *   or from the command line.
606  */
lua_load_plugin_script(const gchar * name,const gchar * filename,const gchar * dirname,const int file_count)607 static gboolean lua_load_plugin_script(const gchar* name,
608                                        const gchar* filename,
609                                        const gchar* dirname,
610                                        const int file_count)
611 {
612     if (lua_load_script(filename, dirname, file_count)) {
613         wslua_add_plugin(name, get_current_plugin_version(), filename);
614         clear_current_plugin_version();
615         return TRUE;
616     }
617     return FALSE;
618 }
619 
620 
basic_logger(const gchar * log_domain,enum ws_log_level log_level,const gchar * message,gpointer user_data _U_)621 static void basic_logger(const gchar *log_domain,
622                           enum ws_log_level log_level,
623                           const gchar *message,
624                           gpointer user_data _U_) {
625     ws_log(log_domain, log_level, "%s", message);
626 }
627 
wslua_panic(lua_State * LS)628 static int wslua_panic(lua_State* LS) {
629     ws_error("LUA PANIC: %s",lua_tostring(LS,-1));
630     /** ws_error() does an abort() and thus never returns **/
631     return 0; /* keep gcc happy */
632 }
633 
string_compare(gconstpointer a,gconstpointer b)634 static gint string_compare(gconstpointer a, gconstpointer b) {
635     return strcmp((const char*)a, (const char*)b);
636 }
637 
lua_load_plugins(const char * dirname,register_cb cb,gpointer client_data,gboolean count_only,const gboolean is_user,GHashTable * loaded_files)638 static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client_data,
639                             gboolean count_only, const gboolean is_user, GHashTable *loaded_files)
640 {
641     WS_DIR        *dir;             /* scanned directory */
642     WS_DIRENT     *file;            /* current file */
643     gchar         *filename, *dot;
644     const gchar   *name;
645     int            plugins_counter = 0;
646     GList         *sorted_dirnames = NULL;
647     GList         *sorted_filenames = NULL;
648     GList         *l = NULL;
649 
650     if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
651         while ((file = ws_dir_read_name(dir)) != NULL) {
652             name = ws_dir_get_name(file);
653 
654             if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
655                 continue;        /* skip "." and ".." */
656 
657             filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
658             if (test_for_directory(filename) == EISDIR) {
659                 sorted_dirnames = g_list_prepend(sorted_dirnames, (gpointer)filename);
660                 continue;
661             }
662 
663             /* skip files starting wih . */
664             if (name[0] == '.') {
665                 g_free(filename);
666                 continue;
667             }
668 
669             /* skip anything but files with .lua suffix */
670             dot = strrchr(name, '.');
671             if (dot == NULL || g_ascii_strcasecmp(dot+1, "lua") != 0) {
672                 g_free(filename);
673                 continue;
674             }
675 
676             if (file_exists(filename)) {
677                 sorted_filenames = g_list_prepend(sorted_filenames, (gpointer)filename);
678             }
679             else {
680                 g_free(filename);
681             }
682         }
683         ws_dir_close(dir);
684     }
685 
686     /* Depth first; ie, process subdirectories (in ASCIIbetical order) before files */
687     if (sorted_dirnames != NULL) {
688         sorted_dirnames = g_list_sort(sorted_dirnames, string_compare);
689         for (l = sorted_dirnames; l != NULL; l = l->next) {
690             plugins_counter += lua_load_plugins((const char *)l->data, cb, client_data, count_only, is_user, loaded_files);
691         }
692         g_list_free_full(sorted_dirnames, g_free);
693     }
694 
695     /* Process files in ASCIIbetical order */
696     if (sorted_filenames != NULL) {
697         sorted_filenames = g_list_sort(sorted_filenames, string_compare);
698         for (l = sorted_filenames; l != NULL; l = l->next) {
699             filename = (gchar *)l->data;
700             name = strrchr(filename, G_DIR_SEPARATOR) + 1;
701 
702             /* Check if we have already loaded this file name, if provided with a set */
703             if (loaded_files && g_hash_table_lookup_extended(loaded_files, name, NULL, NULL)) {
704                 continue;
705             }
706 
707             if (!count_only) {
708                 if (cb)
709                     (*cb)(RA_LUA_PLUGINS, name, client_data);
710                 lua_load_plugin_script(name, filename, is_user ? dirname : NULL, 0);
711 
712                 if (loaded_files) {
713                     g_hash_table_insert(loaded_files, g_strdup(name), NULL);
714                 }
715             }
716             plugins_counter++;
717         }
718         g_list_free_full(sorted_filenames, g_free);
719     }
720 
721     return plugins_counter;
722 }
723 
lua_load_global_plugins(register_cb cb,gpointer client_data,gboolean count_only)724 static int lua_load_global_plugins(register_cb cb, gpointer client_data,
725                                     gboolean count_only)
726 {
727     return lua_load_plugins(get_plugins_dir(), cb, client_data, count_only, FALSE, NULL);
728 }
729 
lua_load_pers_plugins(register_cb cb,gpointer client_data,gboolean count_only)730 static int lua_load_pers_plugins(register_cb cb, gpointer client_data,
731                                     gboolean count_only)
732 {
733     int plugins_counter = 0;
734 
735     /* aux table (set) to make sure we only load each file once (by name) */
736     GHashTable *loaded_user_scripts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
737 
738     /* load user scripts */
739     plugins_counter += lua_load_plugins(get_plugins_pers_dir(), cb, client_data, count_only, TRUE, loaded_user_scripts);
740 
741     /* for backward compatibility check old plugin directory */
742     char *old_path = get_persconffile_path("plugins", FALSE);
743     if (strcmp(get_plugins_pers_dir(), old_path) != 0) {
744         plugins_counter += lua_load_plugins(old_path, cb, client_data, count_only, TRUE, loaded_user_scripts);
745     }
746     g_free(old_path);
747 
748     g_hash_table_destroy(loaded_user_scripts);
749 
750     return plugins_counter;
751 }
752 
wslua_count_plugins(void)753 int wslua_count_plugins(void) {
754     gchar* filename;
755     int plugins_counter;
756 
757     /* count global scripts */
758     plugins_counter = lua_load_global_plugins(NULL, NULL, TRUE);
759 
760     /* count users init.lua */
761     filename = get_persconffile_path("init.lua", FALSE);
762     if ((file_exists(filename))) {
763         plugins_counter++;
764     }
765     g_free(filename);
766 
767     /* count user scripts */
768     plugins_counter += lua_load_pers_plugins(NULL, NULL, TRUE);
769 
770     /* count scripts from command line */
771     plugins_counter += ex_opt_count("lua_script");
772 
773     return plugins_counter;
774 }
775 
wslua_plugins_get_descriptions(wslua_plugin_description_callback callback,void * user_data)776 void wslua_plugins_get_descriptions(wslua_plugin_description_callback callback, void *user_data) {
777     wslua_plugin  *lua_plug;
778 
779     for (lua_plug = wslua_plugin_list; lua_plug != NULL; lua_plug = lua_plug->next)
780     {
781         callback(lua_plug->name, lua_plug->version, wslua_plugin_type_name(),
782                  lua_plug->filename, user_data);
783     }
784 }
785 
786 static void
print_wslua_plugin_description(const char * name,const char * version,const char * description,const char * filename,void * user_data _U_)787 print_wslua_plugin_description(const char *name, const char *version,
788                                const char *description, const char *filename,
789                                void *user_data _U_)
790 {
791     printf("%s\t%s\t%s\t%s\n", name, version, description, filename);
792 }
793 
794 void
wslua_plugins_dump_all(void)795 wslua_plugins_dump_all(void)
796 {
797     wslua_plugins_get_descriptions(print_wslua_plugin_description, NULL);
798 }
799 
wslua_plugin_type_name(void)800 const char *wslua_plugin_type_name(void) {
801     return "lua script";
802 }
803 
804 static ei_register_info* ws_lua_ei = NULL;
805 static int ws_lua_ei_len = 0;
806 
807 expert_field*
wslua_get_expert_field(const int group,const int severity)808 wslua_get_expert_field(const int group, const int severity)
809 {
810     int i;
811     const ei_register_info *ei = ws_lua_ei;
812 
813     ws_assert(ei);
814 
815     for (i=0; i < ws_lua_ei_len; i++, ei++) {
816         if (ei->eiinfo.group == group && ei->eiinfo.severity == severity)
817             return ei->ids;
818     }
819 
820     return &ei_lua_error;
821 }
822 
823 static void *
wslua_allocf(void * ud _U_,void * ptr,size_t osize _U_,size_t nsize)824 wslua_allocf(void *ud _U_, void *ptr, size_t osize _U_, size_t nsize)
825 {
826     /* g_realloc frees ptr if nsize==0 and returns NULL (as desired).
827      * Furthermore it simplifies error handling by aborting on OOM */
828     return g_realloc(ptr, nsize);
829 }
830 
wslua_init(register_cb cb,gpointer client_data)831 void wslua_init(register_cb cb, gpointer client_data) {
832     gchar* filename;
833     const funnel_ops_t* ops = funnel_get_funnel_ops();
834     gboolean enable_lua = TRUE;
835     gboolean run_anyway = FALSE;
836     expert_module_t* expert_lua;
837     int file_count = 1;
838     static gboolean first_time = TRUE;
839     int i;
840 
841     static hf_register_info hf[] = {
842         { &hf_wslua_fake,
843           { "Wireshark Lua fake item",     "_ws.lua.fake",
844             FT_NONE, BASE_NONE, NULL, 0x0,
845             "Fake internal item for Wireshark Lua", HFILL }},
846         { &hf_wslua_text,
847           { "Wireshark Lua text",     "_ws.lua.text",
848             FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
849     };
850 
851     static ei_register_info ei[] = {
852         /* the following are created so we can continue to support the TreeItem_add_expert_info()
853            function to Lua scripts. That function doesn't know what registered protocol to use,
854            so it uses the "_ws.lua" one. */
855         /* XXX: it seems to me we should not be offering PI_GROUP_MASK nor PI_SEVERITY_MASK since
856            they are not real settings, so I'm not adding them below (should they also not be exported
857            into Lua? they are right now.) */
858         /* NOTE: do not add expert entries at the top of this array - only at the bottom. This array
859            is not only used by expert.c, but also by wslua_get_expert_field() to find the appropriate
860            "dummy" entry. So this array's ordering matters. */
861         { &ei_lua_proto_checksum_comment,   { "_ws.lua.proto.comment", PI_CHECKSUM, PI_COMMENT ,"Protocol Comment", EXPFILL }},
862         { &ei_lua_proto_checksum_chat,      { "_ws.lua.proto.chat",    PI_CHECKSUM, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
863         { &ei_lua_proto_checksum_note,      { "_ws.lua.proto.note",    PI_CHECKSUM, PI_NOTE    ,"Protocol Note",    EXPFILL }},
864         { &ei_lua_proto_checksum_warn,      { "_ws.lua.proto.warning", PI_CHECKSUM, PI_WARN    ,"Protocol Warning", EXPFILL }},
865         { &ei_lua_proto_checksum_error,     { "_ws.lua.proto.error",   PI_CHECKSUM, PI_ERROR   ,"Protocol Error",   EXPFILL }},
866 
867         { &ei_lua_proto_sequence_comment,   { "_ws.lua.proto.comment", PI_SEQUENCE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
868         { &ei_lua_proto_sequence_chat,      { "_ws.lua.proto.chat",    PI_SEQUENCE, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
869         { &ei_lua_proto_sequence_note,      { "_ws.lua.proto.note",    PI_SEQUENCE, PI_NOTE    ,"Protocol Note",    EXPFILL }},
870         { &ei_lua_proto_sequence_warn,      { "_ws.lua.proto.warning", PI_SEQUENCE, PI_WARN    ,"Protocol Warning", EXPFILL }},
871         { &ei_lua_proto_sequence_error,     { "_ws.lua.proto.error",   PI_SEQUENCE, PI_ERROR   ,"Protocol Error",   EXPFILL }},
872 
873         { &ei_lua_proto_response_comment,   { "_ws.lua.proto.comment", PI_RESPONSE_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
874         { &ei_lua_proto_response_chat,      { "_ws.lua.proto.chat",    PI_RESPONSE_CODE, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
875         { &ei_lua_proto_response_note,      { "_ws.lua.proto.note",    PI_RESPONSE_CODE, PI_NOTE    ,"Protocol Note",    EXPFILL }},
876         { &ei_lua_proto_response_warn,      { "_ws.lua.proto.warning", PI_RESPONSE_CODE, PI_WARN    ,"Protocol Warning", EXPFILL }},
877         { &ei_lua_proto_response_error,     { "_ws.lua.proto.error",   PI_RESPONSE_CODE, PI_ERROR   ,"Protocol Error",   EXPFILL }},
878 
879         { &ei_lua_proto_request_comment,    { "_ws.lua.proto.comment", PI_REQUEST_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
880         { &ei_lua_proto_request_chat,       { "_ws.lua.proto.chat",    PI_REQUEST_CODE, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
881         { &ei_lua_proto_request_note,       { "_ws.lua.proto.note",    PI_REQUEST_CODE, PI_NOTE    ,"Protocol Note",    EXPFILL }},
882         { &ei_lua_proto_request_warn,       { "_ws.lua.proto.warning", PI_REQUEST_CODE, PI_WARN    ,"Protocol Warning", EXPFILL }},
883         { &ei_lua_proto_request_error,      { "_ws.lua.proto.error",   PI_REQUEST_CODE, PI_ERROR   ,"Protocol Error",   EXPFILL }},
884 
885         { &ei_lua_proto_undecoded_comment,  { "_ws.lua.proto.comment", PI_UNDECODED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
886         { &ei_lua_proto_undecoded_chat,     { "_ws.lua.proto.chat",    PI_UNDECODED, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
887         { &ei_lua_proto_undecoded_note,     { "_ws.lua.proto.note",    PI_UNDECODED, PI_NOTE    ,"Protocol Note",    EXPFILL }},
888         { &ei_lua_proto_undecoded_warn,     { "_ws.lua.proto.warning", PI_UNDECODED, PI_WARN    ,"Protocol Warning", EXPFILL }},
889         { &ei_lua_proto_undecoded_error,    { "_ws.lua.proto.error",   PI_UNDECODED, PI_ERROR   ,"Protocol Error",   EXPFILL }},
890 
891         { &ei_lua_proto_reassemble_comment, { "_ws.lua.proto.comment", PI_REASSEMBLE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
892         { &ei_lua_proto_reassemble_chat,    { "_ws.lua.proto.chat",    PI_REASSEMBLE, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
893         { &ei_lua_proto_reassemble_note,    { "_ws.lua.proto.note",    PI_REASSEMBLE, PI_NOTE    ,"Protocol Note",    EXPFILL }},
894         { &ei_lua_proto_reassemble_warn,    { "_ws.lua.proto.warning", PI_REASSEMBLE, PI_WARN    ,"Protocol Warning", EXPFILL }},
895         { &ei_lua_proto_reassemble_error,   { "_ws.lua.proto.error",   PI_REASSEMBLE, PI_ERROR   ,"Protocol Error",   EXPFILL }},
896 
897         { &ei_lua_proto_malformed_comment,  { "_ws.lua.proto.comment", PI_MALFORMED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
898         { &ei_lua_proto_malformed_chat,     { "_ws.lua.proto.chat",    PI_MALFORMED, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
899         { &ei_lua_proto_malformed_note,     { "_ws.lua.proto.note",    PI_MALFORMED, PI_NOTE    ,"Protocol Note",    EXPFILL }},
900         { &ei_lua_proto_malformed_warn,     { "_ws.lua.proto.warning", PI_MALFORMED, PI_WARN    ,"Protocol Warning", EXPFILL }},
901         { &ei_lua_proto_malformed_error,    { "_ws.lua.proto.error",   PI_MALFORMED, PI_ERROR   ,"Protocol Error",   EXPFILL }},
902 
903         { &ei_lua_proto_debug_comment,      { "_ws.lua.proto.comment", PI_DEBUG, PI_COMMENT ,"Protocol Comment", EXPFILL }},
904         { &ei_lua_proto_debug_chat,         { "_ws.lua.proto.chat",    PI_DEBUG, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
905         { &ei_lua_proto_debug_note,         { "_ws.lua.proto.note",    PI_DEBUG, PI_NOTE    ,"Protocol Note",    EXPFILL }},
906         { &ei_lua_proto_debug_warn,         { "_ws.lua.proto.warning", PI_DEBUG, PI_WARN    ,"Protocol Warning", EXPFILL }},
907         { &ei_lua_proto_debug_error,        { "_ws.lua.proto.error",   PI_DEBUG, PI_ERROR   ,"Protocol Error",   EXPFILL }},
908 
909         { &ei_lua_proto_protocol_comment,   { "_ws.lua.proto.comment", PI_PROTOCOL, PI_COMMENT ,"Protocol Comment", EXPFILL }},
910         { &ei_lua_proto_protocol_chat,      { "_ws.lua.proto.chat",    PI_PROTOCOL, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
911         { &ei_lua_proto_protocol_note,      { "_ws.lua.proto.note",    PI_PROTOCOL, PI_NOTE    ,"Protocol Note",    EXPFILL }},
912         { &ei_lua_proto_protocol_warn,      { "_ws.lua.proto.warning", PI_PROTOCOL, PI_WARN    ,"Protocol Warning", EXPFILL }},
913         { &ei_lua_proto_protocol_error,     { "_ws.lua.proto.error",   PI_PROTOCOL, PI_ERROR   ,"Protocol Error",   EXPFILL }},
914 
915         { &ei_lua_proto_security_comment,   { "_ws.lua.proto.comment", PI_SECURITY, PI_COMMENT ,"Protocol Comment", EXPFILL }},
916         { &ei_lua_proto_security_chat,      { "_ws.lua.proto.chat",    PI_SECURITY, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
917         { &ei_lua_proto_security_note,      { "_ws.lua.proto.note",    PI_SECURITY, PI_NOTE    ,"Protocol Note",    EXPFILL }},
918         { &ei_lua_proto_security_warn,      { "_ws.lua.proto.warning", PI_SECURITY, PI_WARN    ,"Protocol Warning", EXPFILL }},
919         { &ei_lua_proto_security_error,     { "_ws.lua.proto.error",   PI_SECURITY, PI_ERROR   ,"Protocol Error",   EXPFILL }},
920 
921         { &ei_lua_proto_comments_comment,   { "_ws.lua.proto.comment", PI_COMMENTS_GROUP, PI_COMMENT ,"Protocol Comment", EXPFILL }},
922         { &ei_lua_proto_comments_chat,      { "_ws.lua.proto.chat",    PI_COMMENTS_GROUP, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
923         { &ei_lua_proto_comments_note,      { "_ws.lua.proto.note",    PI_COMMENTS_GROUP, PI_NOTE    ,"Protocol Note",    EXPFILL }},
924         { &ei_lua_proto_comments_warn,      { "_ws.lua.proto.warning", PI_COMMENTS_GROUP, PI_WARN    ,"Protocol Warning", EXPFILL }},
925         { &ei_lua_proto_comments_error,     { "_ws.lua.proto.error",   PI_COMMENTS_GROUP, PI_ERROR   ,"Protocol Error",   EXPFILL }},
926 
927         { &ei_lua_proto_decryption_comment, { "_ws.lua.proto.comment", PI_DECRYPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }},
928         { &ei_lua_proto_decryption_chat,    { "_ws.lua.proto.chat",    PI_DECRYPTION, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
929         { &ei_lua_proto_decryption_note,    { "_ws.lua.proto.note",    PI_DECRYPTION, PI_NOTE    ,"Protocol Note",    EXPFILL }},
930         { &ei_lua_proto_decryption_warn,    { "_ws.lua.proto.warning", PI_DECRYPTION, PI_WARN    ,"Protocol Warning", EXPFILL }},
931         { &ei_lua_proto_decryption_error,   { "_ws.lua.proto.error",   PI_DECRYPTION, PI_ERROR   ,"Protocol Error",   EXPFILL }},
932 
933         { &ei_lua_proto_assumption_comment, { "_ws.lua.proto.comment", PI_ASSUMPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }},
934         { &ei_lua_proto_assumption_chat,    { "_ws.lua.proto.chat",    PI_ASSUMPTION, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
935         { &ei_lua_proto_assumption_note,    { "_ws.lua.proto.note",    PI_ASSUMPTION, PI_NOTE    ,"Protocol Note",    EXPFILL }},
936         { &ei_lua_proto_assumption_warn,    { "_ws.lua.proto.warning", PI_ASSUMPTION, PI_WARN    ,"Protocol Warning", EXPFILL }},
937         { &ei_lua_proto_assumption_error,   { "_ws.lua.proto.error",   PI_ASSUMPTION, PI_ERROR   ,"Protocol Error",   EXPFILL }},
938 
939         { &ei_lua_proto_deprecated_comment, { "_ws.lua.proto.comment", PI_DEPRECATED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
940         { &ei_lua_proto_deprecated_chat,    { "_ws.lua.proto.chat",    PI_DEPRECATED, PI_CHAT    ,"Protocol Chat",    EXPFILL }},
941         { &ei_lua_proto_deprecated_note,    { "_ws.lua.proto.note",    PI_DEPRECATED, PI_NOTE    ,"Protocol Note",    EXPFILL }},
942         { &ei_lua_proto_deprecated_warn,    { "_ws.lua.proto.warning", PI_DEPRECATED, PI_WARN    ,"Protocol Warning", EXPFILL }},
943         { &ei_lua_proto_deprecated_error,   { "_ws.lua.proto.error",   PI_DEPRECATED, PI_ERROR   ,"Protocol Error",   EXPFILL }},
944 
945         /* this one is for reporting errors executing Lua code */
946         { &ei_lua_error, { "_ws.lua.error", PI_UNDECODED, PI_ERROR ,"Lua Error", EXPFILL }},
947     };
948 
949     if (first_time) {
950         ws_lua_ei = ei;
951         ws_lua_ei_len = array_length(ei);
952     }
953 
954     /* set up the logger */
955     wslua_logger = ops ? ops->logger : basic_logger;
956 
957     if (!L) {
958         L = lua_newstate(wslua_allocf, NULL);
959     }
960 
961     WSLUA_INIT(L);
962 
963 #if LUA_VERSION_NUM == 501
964     /* table.unpack was introduced with Lua 5.2, alias it to unpack. */
965     lua_getglobal(L, "table");
966     lua_getglobal(L, "unpack");
967     lua_setfield(L, -2, "unpack");
968     lua_pop(L, 1);
969 #endif
970 
971     if (first_time) {
972         proto_lua = proto_register_protocol("Lua Dissection", "Lua Dissection", "_ws.lua");
973         proto_register_field_array(proto_lua, hf, array_length(hf));
974         expert_lua = expert_register_protocol(proto_lua);
975         expert_register_field_array(expert_lua, ei, array_length(ei));
976     }
977 
978     lua_atpanic(L,wslua_panic);
979 
980     /*
981      * The init_routines table (accessible by the user).
982      *
983      * For a table a, a.init is syntactic sugar for a["init"], and
984      *
985      *    function t.a.b.c.f () body end
986      *
987      * is syntactic sugar for
988      *
989      *    t.a.b.c.f = function () body end
990      *
991      * so
992      *
993      *    function proto.init () body end
994      *
995      * means
996      *
997      *    proto["init"] = function () body end
998      *
999      * and the Proto class has an "init" method, with Proto_set_init()
1000      * being the setter for that method; that routine adds the Lua
1001      * function passed to it as a Lua argument to the WSLUA_INIT_ROUTINES
1002      * table - i.e., "init_routines".
1003      */
1004     lua_newtable (L);
1005     lua_setglobal(L, WSLUA_INIT_ROUTINES);
1006 
1007     /* the dissectors table goes in the registry (not accessible) */
1008     lua_newtable (L);
1009     lua_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1010     lua_newtable (L);
1011     lua_heur_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1012 
1013     /* the preferences apply_cb table (accessible by the user) */
1014     lua_newtable (L);
1015     lua_setglobal(L, WSLUA_PREFS_CHANGED);
1016 
1017     /* set running_superuser variable to its proper value */
1018     WSLUA_REG_GLOBAL_BOOL(L,"running_superuser",started_with_special_privs());
1019 
1020     /* special constant used by PDU reassembly handling */
1021     /* see dissect_lua() for notes */
1022     WSLUA_REG_GLOBAL_NUMBER(L,"DESEGMENT_ONE_MORE_SEGMENT",DESEGMENT_ONE_MORE_SEGMENT);
1023 
1024     /* load system's init.lua */
1025     filename = get_datafile_path("init.lua");
1026     if (( file_exists(filename))) {
1027         lua_load_internal_script(filename);
1028     }
1029 
1030     g_free(filename);
1031     filename = NULL;
1032 
1033     /* check if lua is to be disabled */
1034     lua_getglobal(L, "disable_lua"); // 2.6 and earlier, deprecated
1035     if (lua_isboolean(L,-1)) {
1036         enable_lua = ! lua_toboolean(L,-1);
1037     }
1038     lua_pop(L,1);  /* pop the getglobal result */
1039 
1040     lua_getglobal(L, "enable_lua"); // 3.0 and later
1041     if (lua_isboolean(L,-1)) {
1042         enable_lua = lua_toboolean(L,-1);
1043     }
1044     lua_pop(L,1);  /* pop the getglobal result */
1045 
1046     if (!enable_lua) {
1047         /* disable lua */
1048         lua_close(L);
1049         L = NULL;
1050         first_time = FALSE;
1051         return;
1052     }
1053 
1054     /* load global scripts */
1055     lua_load_global_plugins(cb, client_data, FALSE);
1056 
1057     /* check whether we should run other scripts even if running superuser */
1058     lua_getglobal(L,"run_user_scripts_when_superuser");
1059 
1060     if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) {
1061         run_anyway = TRUE;
1062     }
1063     lua_pop(L,1);  /* pop the getglobal result */
1064 
1065     /* if we are indeed superuser run user scripts only if told to do so */
1066     if ( (!started_with_special_privs()) || run_anyway ) {
1067         /* load users init.lua */
1068         filename = get_persconffile_path("init.lua", FALSE);
1069         if ((file_exists(filename))) {
1070             if (cb)
1071                 (*cb)(RA_LUA_PLUGINS, get_basename(filename), client_data);
1072             lua_load_internal_script(filename);
1073         }
1074         g_free(filename);
1075 
1076         /* load user scripts */
1077         lua_load_pers_plugins(cb, client_data, FALSE);
1078 
1079         /* load scripts from command line */
1080         for (i = 0; i < ex_opt_count("lua_script"); i++) {
1081             const gchar *script_filename = ex_opt_get_nth("lua_script", i);
1082             char* dirname = g_strdup(script_filename);
1083             char* dname = get_dirname(dirname);
1084 
1085             if (cb)
1086                 (*cb)(RA_LUA_PLUGINS, get_basename(script_filename), client_data);
1087 
1088             lua_load_plugin_script(ws_dir_get_name(script_filename),
1089                                    script_filename,
1090                                    dname ? dname : "",
1091                                    file_count);
1092             file_count++;
1093             g_free(dirname);
1094         }
1095     }
1096 
1097     if (first_time) {
1098         /* at this point we're set up so register the init and cleanup routines */
1099         register_init_routine(wslua_init_routine);
1100         register_cleanup_routine(wslua_cleanup_routine);
1101     }
1102 
1103     /*
1104      * after this point it is too late to register a menu
1105      * disable the function to avoid weirdness
1106      */
1107     lua_pushcfunction(L, wslua_not_register_menu);
1108     lua_setglobal(L, "register_menu");
1109 
1110     /* set up some essential globals */
1111     lua_pinfo = NULL;
1112     lua_tree = NULL;
1113     lua_tvb = NULL;
1114 
1115     Proto_commit(L);
1116 
1117     first_time = FALSE;
1118 }
1119 
wslua_early_cleanup(void)1120 void wslua_early_cleanup(void) {
1121     wslua_deregister_protocols(L);
1122 }
1123 
wslua_reload_plugins(register_cb cb,gpointer client_data)1124 void wslua_reload_plugins (register_cb cb, gpointer client_data) {
1125     const funnel_ops_t* ops = funnel_get_funnel_ops();
1126 
1127     if (cb)
1128         (*cb)(RA_LUA_DEREGISTER, NULL, client_data);
1129 
1130     if (ops->close_dialogs)
1131         ops->close_dialogs();
1132 
1133     wslua_deregister_heur_dissectors(L);
1134     wslua_deregister_protocols(L);
1135     wslua_deregister_dissector_tables(L);
1136     wslua_deregister_listeners(L);
1137     wslua_deregister_fields(L);
1138     wslua_deregister_filehandlers(L);
1139     wslua_deregister_menus();
1140     wslua_clear_plugin_list();
1141 
1142     wslua_cleanup();
1143     wslua_init(cb, client_data);    /* reinitialize */
1144 }
1145 
wslua_cleanup(void)1146 void wslua_cleanup(void) {
1147     /* cleanup lua */
1148     if (L) {
1149         lua_close(L);
1150         L = NULL;
1151     }
1152     init_routine_initialized = FALSE;
1153 }
1154 
wslua_state(void)1155 lua_State* wslua_state(void) { return L; }
1156 
1157 /*
1158  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1159  *
1160  * Local variables:
1161  * c-basic-offset: 4
1162  * tab-width: 8
1163  * indent-tabs-mode: nil
1164  * End:
1165  *
1166  * vi: set shiftwidth=4 tabstop=8 expandtab:
1167  * :indentSize=4:tabSize=8:noTabs=true:
1168  */
1169