You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_common.c 53KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "lua_common.h"
  17. #include "lptree.h"
  18. #include "utlist.h"
  19. #include "unix-std.h"
  20. #include "worker_util.h"
  21. #include "ottery.h"
  22. #include "rspamd_control.h"
  23. #include "lua_thread_pool.h"
  24. #include "libstat/stat_api.h"
  25. #include "libserver/rspamd_control.h"
  26. #include <math.h>
  27. #include <sys/wait.h>
  28. /* Lua module init function */
  29. #define MODULE_INIT_FUNC "module_init"
  30. #ifdef WITH_LUA_TRACE
  31. ucl_object_t *lua_traces;
  32. #endif
  33. const luaL_reg null_reg[] = {
  34. {"__tostring", rspamd_lua_class_tostring},
  35. {NULL, NULL}
  36. };
  37. LUA_FUNCTION_DEF (worker, get_name);
  38. LUA_FUNCTION_DEF (worker, get_stat);
  39. LUA_FUNCTION_DEF (worker, get_index);
  40. LUA_FUNCTION_DEF (worker, get_pid);
  41. LUA_FUNCTION_DEF (worker, is_scanner);
  42. LUA_FUNCTION_DEF (worker, is_primary_controller);
  43. LUA_FUNCTION_DEF (worker, spawn_process);
  44. const luaL_reg worker_reg[] = {
  45. LUA_INTERFACE_DEF (worker, get_name),
  46. LUA_INTERFACE_DEF (worker, get_stat),
  47. LUA_INTERFACE_DEF (worker, get_index),
  48. LUA_INTERFACE_DEF (worker, get_pid),
  49. LUA_INTERFACE_DEF (worker, spawn_process),
  50. LUA_INTERFACE_DEF (worker, is_scanner),
  51. LUA_INTERFACE_DEF (worker, is_primary_controller),
  52. {"__tostring", rspamd_lua_class_tostring},
  53. {NULL, NULL}
  54. };
  55. static const char rspamd_modules_state_global[] = "rspamd_plugins_state";
  56. static GQuark
  57. lua_error_quark (void)
  58. {
  59. return g_quark_from_static_string ("lua-routines");
  60. }
  61. /* Util functions */
  62. /**
  63. * Create new class and store metatable on top of the stack
  64. * @param L
  65. * @param classname name of class
  66. * @param func table of class methods
  67. */
  68. void
  69. rspamd_lua_new_class (lua_State * L,
  70. const gchar *classname,
  71. const struct luaL_reg *methods)
  72. {
  73. luaL_newmetatable (L, classname); /* mt */
  74. lua_pushstring (L, "__index");
  75. lua_pushvalue (L, -2); /* pushes the metatable */
  76. lua_settable (L, -3); /* metatable.__index = metatable */
  77. lua_pushstring (L, "class"); /* mt,"__index",it,"class" */
  78. lua_pushstring (L, classname); /* mt,"__index",it,"class",classname */
  79. lua_rawset (L, -3); /* mt,"__index",it */
  80. luaL_register (L, NULL, methods);
  81. }
  82. /**
  83. * Create and register new class with static methods and store metatable on top of the stack
  84. */
  85. void
  86. rspamd_lua_new_class_full (lua_State *L,
  87. const gchar *classname,
  88. const gchar *static_name,
  89. const struct luaL_reg *methods,
  90. const struct luaL_reg *func)
  91. {
  92. rspamd_lua_new_class (L, classname, methods);
  93. luaL_register (L, static_name, func);
  94. }
  95. static const gchar *
  96. rspamd_lua_class_tostring_buf (lua_State *L, gboolean print_pointer, gint pos)
  97. {
  98. static gchar buf[64];
  99. const gchar *ret = NULL;
  100. gint pop = 0;
  101. if (!lua_getmetatable (L, pos)) {
  102. goto err;
  103. }
  104. lua_pushstring (L, "__index");
  105. lua_gettable (L, -2);
  106. pop ++;
  107. if (!lua_istable (L, -1)) {
  108. goto err;
  109. }
  110. lua_pushstring (L, "class");
  111. lua_gettable (L, -2);
  112. pop ++;
  113. if (!lua_isstring (L, -1)) {
  114. goto err;
  115. }
  116. if (print_pointer) {
  117. rspamd_snprintf (buf, sizeof (buf), "%s(%p)", lua_tostring (L, -1),
  118. lua_touserdata (L, 1));
  119. }
  120. else {
  121. rspamd_snprintf (buf, sizeof (buf), "%s", lua_tostring (L, -1));
  122. }
  123. ret = buf;
  124. err:
  125. lua_pop (L, pop);
  126. return ret;
  127. }
  128. gint
  129. rspamd_lua_class_tostring (lua_State * L)
  130. {
  131. const gchar *p;
  132. p = rspamd_lua_class_tostring_buf (L, TRUE, 1);
  133. if (!p) {
  134. lua_pushstring (L, "invalid object passed to 'lua_common.c:__tostring'");
  135. return lua_error (L);
  136. }
  137. lua_pushstring (L, p);
  138. return 1;
  139. }
  140. void
  141. rspamd_lua_setclass (lua_State * L, const gchar *classname, gint objidx)
  142. {
  143. luaL_getmetatable (L, classname);
  144. if (objidx < 0) {
  145. objidx--;
  146. }
  147. lua_setmetatable (L, objidx);
  148. }
  149. /* assume that table is at the top */
  150. void
  151. rspamd_lua_table_set (lua_State * L, const gchar *index, const gchar *value)
  152. {
  153. lua_pushstring (L, index);
  154. if (value) {
  155. lua_pushstring (L, value);
  156. }
  157. else {
  158. lua_pushnil (L);
  159. }
  160. lua_settable (L, -3);
  161. }
  162. const gchar *
  163. rspamd_lua_table_get (lua_State *L, const gchar *index)
  164. {
  165. const gchar *result;
  166. lua_pushstring (L, index);
  167. lua_gettable (L, -2);
  168. if (!lua_isstring (L, -1)) {
  169. return NULL;
  170. }
  171. result = lua_tostring (L, -1);
  172. lua_pop (L, 1);
  173. return result;
  174. }
  175. static void
  176. lua_add_actions_global (lua_State *L)
  177. {
  178. gint i;
  179. lua_newtable (L);
  180. for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) {
  181. lua_pushstring (L, rspamd_action_to_str (i));
  182. lua_pushinteger (L, i);
  183. lua_settable (L, -3);
  184. }
  185. /* Set global table */
  186. lua_setglobal (L, "rspamd_actions");
  187. }
  188. #ifndef __APPLE__
  189. #define OS_SO_SUFFIX ".so"
  190. #else
  191. #define OS_SO_SUFFIX ".dylib"
  192. #endif
  193. void
  194. rspamd_lua_set_path (lua_State *L, const ucl_object_t *cfg_obj, GHashTable *vars)
  195. {
  196. const gchar *old_path, *additional_path = NULL;
  197. const ucl_object_t *opts = NULL;
  198. const gchar *pluginsdir = RSPAMD_PLUGINSDIR,
  199. *rulesdir = RSPAMD_RULESDIR,
  200. *lualibdir = RSPAMD_LUALIBDIR,
  201. *libdir = RSPAMD_LIBDIR,
  202. *sharedir = RSPAMD_SHAREDIR;
  203. const gchar *t;
  204. gchar path_buf[PATH_MAX];
  205. lua_getglobal (L, "package");
  206. lua_getfield (L, -1, "path");
  207. old_path = luaL_checkstring (L, -1);
  208. if (strstr (old_path, RSPAMD_LUALIBDIR) != NULL) {
  209. /* Path has been already set, do not touch it */
  210. lua_pop (L, 2);
  211. return;
  212. }
  213. if (cfg_obj) {
  214. opts = ucl_object_lookup (cfg_obj, "options");
  215. if (opts != NULL) {
  216. opts = ucl_object_lookup (opts, "lua_path");
  217. if (opts != NULL && ucl_object_type (opts) == UCL_STRING) {
  218. additional_path = ucl_object_tostring (opts);
  219. }
  220. }
  221. }
  222. /* Try environment */
  223. t = getenv ("SHAREDIR");
  224. if (t) {
  225. sharedir = t;
  226. }
  227. t = getenv ("PLUGINSDIR");
  228. if (t) {
  229. pluginsdir = t;
  230. }
  231. t = getenv ("RULESDIR");
  232. if (t) {
  233. rulesdir = t;
  234. }
  235. t = getenv ("LUALIBDIR");
  236. if (t) {
  237. lualibdir = t;
  238. }
  239. t = getenv ("LIBDIR");
  240. if (t) {
  241. libdir = t;
  242. }
  243. t = getenv ("RSPAMD_LIBDIR");
  244. if (t) {
  245. libdir = t;
  246. }
  247. if (vars) {
  248. t = g_hash_table_lookup (vars, "PLUGINSDIR");
  249. if (t) {
  250. pluginsdir = t;
  251. }
  252. t = g_hash_table_lookup (vars, "SHAREDIR");
  253. if (t) {
  254. sharedir = t;
  255. }
  256. t = g_hash_table_lookup (vars, "RULESDIR");
  257. if (t) {
  258. rulesdir = t;
  259. }
  260. t = g_hash_table_lookup (vars, "LUALIBDIR");
  261. if (t) {
  262. lualibdir = t;
  263. }
  264. t = g_hash_table_lookup (vars, "LIBDIR");
  265. if (t) {
  266. libdir = t;
  267. }
  268. t = g_hash_table_lookup (vars, "RSPAMD_LIBDIR");
  269. if (t) {
  270. libdir = t;
  271. }
  272. }
  273. if (additional_path) {
  274. rspamd_snprintf (path_buf, sizeof (path_buf),
  275. "%s/lua/?.lua;"
  276. "%s/?.lua;"
  277. "%s/?.lua;"
  278. "%s/?/init.lua;"
  279. "%s/rspamd/?.lua;"
  280. "%s;"
  281. "%s",
  282. RSPAMD_CONFDIR,
  283. rulesdir,
  284. lualibdir, lualibdir,
  285. /* Rspamd specific: lualib/rspamd */
  286. lualibdir,
  287. additional_path, old_path);
  288. }
  289. else {
  290. rspamd_snprintf (path_buf, sizeof (path_buf),
  291. "%s/lua/?.lua;"
  292. "%s/?.lua;"
  293. "%s/?.lua;"
  294. "%s/?/init.lua;"
  295. "%s/rspamd/?.lua;"
  296. "%s",
  297. RSPAMD_CONFDIR, rulesdir,
  298. lualibdir, lualibdir,
  299. /* Rspamd specific: lualib/rspamd */
  300. lualibdir,
  301. old_path);
  302. }
  303. lua_pop (L, 1);
  304. lua_pushstring (L, path_buf);
  305. lua_setfield (L, -2, "path");
  306. lua_getglobal (L, "package");
  307. lua_getfield (L, -1, "cpath");
  308. old_path = luaL_checkstring (L, -1);
  309. additional_path = NULL;
  310. if (opts != NULL) {
  311. opts = ucl_object_lookup (opts, "lua_cpath");
  312. if (opts != NULL && ucl_object_type (opts) == UCL_STRING) {
  313. additional_path = ucl_object_tostring (opts);
  314. }
  315. }
  316. if (additional_path) {
  317. rspamd_snprintf (path_buf, sizeof (path_buf),
  318. "%s/?%s;"
  319. "%s;"
  320. "%s",
  321. libdir,
  322. OS_SO_SUFFIX,
  323. additional_path,
  324. old_path);
  325. }
  326. else {
  327. rspamd_snprintf (path_buf, sizeof (path_buf),
  328. "%s/?%s;"
  329. "%s",
  330. libdir,
  331. OS_SO_SUFFIX,
  332. old_path);
  333. }
  334. lua_pop (L, 1);
  335. lua_pushstring (L, path_buf);
  336. lua_setfield (L, -2, "cpath");
  337. lua_pop (L, 1);
  338. }
  339. static gint
  340. rspamd_lua_cmp_version_components (const gchar *comp1, const gchar *comp2)
  341. {
  342. guint v1, v2;
  343. v1 = strtoul (comp1, NULL, 10);
  344. v2 = strtoul (comp2, NULL, 10);
  345. return v1 - v2;
  346. }
  347. static int
  348. rspamd_lua_rspamd_version_cmp (lua_State *L)
  349. {
  350. const gchar *ver;
  351. gchar **components;
  352. gint ret = 0;
  353. if (lua_type (L, 2) == LUA_TSTRING) {
  354. ver = lua_tostring (L, 2);
  355. components = g_strsplit_set (ver, ".-_", -1);
  356. if (!components) {
  357. return luaL_error (L, "invalid arguments to 'cmp': %s", ver);
  358. }
  359. if (components[0]) {
  360. ret = rspamd_lua_cmp_version_components (components[0],
  361. RSPAMD_VERSION_MAJOR);
  362. }
  363. if (ret) {
  364. goto set;
  365. }
  366. if (components[1]) {
  367. ret = rspamd_lua_cmp_version_components (components[1],
  368. RSPAMD_VERSION_MINOR);
  369. }
  370. if (ret) {
  371. goto set;
  372. }
  373. if (components[2]) {
  374. ret = rspamd_lua_cmp_version_components (components[2],
  375. RSPAMD_VERSION_PATCH);
  376. }
  377. /*
  378. * XXX: we don't compare git releases assuming that it is meaningless
  379. */
  380. }
  381. else {
  382. return luaL_error (L, "invalid arguments to 'cmp'");
  383. }
  384. set:
  385. g_strfreev (components);
  386. lua_pushinteger (L, ret);
  387. return 1;
  388. }
  389. static int
  390. rspamd_lua_rspamd_version_numeric (lua_State *L)
  391. {
  392. static gint64 version_num = RSPAMD_VERSION_NUM;
  393. const gchar *type;
  394. if (lua_gettop (L) >= 2 && lua_type (L, 1) == LUA_TSTRING) {
  395. type = lua_tostring (L, 1);
  396. if (g_ascii_strcasecmp (type, "short") == 0) {
  397. version_num = RSPAMD_VERSION_MAJOR_NUM * 1000 +
  398. RSPAMD_VERSION_MINOR_NUM * 100 +
  399. RSPAMD_VERSION_PATCH_NUM * 10;
  400. }
  401. else if (g_ascii_strcasecmp (type, "main") == 0) {
  402. version_num = RSPAMD_VERSION_MAJOR_NUM * 1000 +
  403. RSPAMD_VERSION_MINOR_NUM * 100;
  404. }
  405. else if (g_ascii_strcasecmp (type, "major") == 0) {
  406. version_num = RSPAMD_VERSION_MAJOR_NUM;
  407. }
  408. else if (g_ascii_strcasecmp (type, "minor") == 0) {
  409. version_num = RSPAMD_VERSION_MINOR_NUM;
  410. }
  411. else if (g_ascii_strcasecmp (type, "patch") == 0) {
  412. version_num = RSPAMD_VERSION_PATCH_NUM;
  413. }
  414. }
  415. lua_pushinteger (L, version_num);
  416. return 1;
  417. }
  418. static int
  419. rspamd_lua_rspamd_version (lua_State *L)
  420. {
  421. const gchar *result = NULL, *type;
  422. if (lua_gettop (L) == 0) {
  423. result = RVERSION;
  424. }
  425. else if (lua_gettop (L) >= 1 && lua_type (L, 1) == LUA_TSTRING) {
  426. /* We got something like string */
  427. type = lua_tostring (L, 1);
  428. if (g_ascii_strcasecmp (type, "short") == 0) {
  429. result = RSPAMD_VERSION_MAJOR
  430. "." RSPAMD_VERSION_MINOR
  431. "." RSPAMD_VERSION_PATCH;
  432. }
  433. else if (g_ascii_strcasecmp (type, "main") == 0) {
  434. result = RSPAMD_VERSION_MAJOR "." RSPAMD_VERSION_MINOR;
  435. }
  436. else if (g_ascii_strcasecmp (type, "major") == 0) {
  437. result = RSPAMD_VERSION_MAJOR;
  438. }
  439. else if (g_ascii_strcasecmp (type, "minor") == 0) {
  440. result = RSPAMD_VERSION_MINOR;
  441. }
  442. else if (g_ascii_strcasecmp (type, "patch") == 0) {
  443. result = RSPAMD_VERSION_PATCH;
  444. }
  445. else if (g_ascii_strcasecmp (type, "id") == 0) {
  446. result = RID;
  447. }
  448. else if (g_ascii_strcasecmp (type, "num") == 0) {
  449. return rspamd_lua_rspamd_version_numeric (L);
  450. }
  451. else if (g_ascii_strcasecmp (type, "cmp") == 0) {
  452. return rspamd_lua_rspamd_version_cmp (L);
  453. }
  454. }
  455. lua_pushstring (L, result);
  456. return 1;
  457. }
  458. void
  459. rspamd_lua_set_globals (struct rspamd_config *cfg, lua_State *L,
  460. GHashTable *vars)
  461. {
  462. struct rspamd_config **pcfg;
  463. gint orig_top = lua_gettop (L);
  464. /* First check for global variable 'config' */
  465. lua_getglobal (L, "config");
  466. if (lua_isnil (L, -1)) {
  467. /* Assign global table to set up attributes */
  468. lua_newtable (L);
  469. lua_setglobal (L, "config");
  470. }
  471. lua_getglobal (L, "metrics");
  472. if (lua_isnil (L, -1)) {
  473. lua_newtable (L);
  474. lua_setglobal (L, "metrics");
  475. }
  476. lua_getglobal (L, "composites");
  477. if (lua_isnil (L, -1)) {
  478. lua_newtable (L);
  479. lua_setglobal (L, "composites");
  480. }
  481. lua_getglobal (L, "rspamd_classifiers");
  482. if (lua_isnil (L, -1)) {
  483. lua_newtable (L);
  484. lua_setglobal (L, "rspamd_classifiers");
  485. }
  486. lua_getglobal (L, "classifiers");
  487. if (lua_isnil (L, -1)) {
  488. lua_newtable (L);
  489. lua_setglobal (L, "classifiers");
  490. }
  491. lua_getglobal (L, "rspamd_version");
  492. if (lua_isnil (L, -1)) {
  493. lua_pushcfunction (L, rspamd_lua_rspamd_version);
  494. lua_setglobal (L, "rspamd_version");
  495. }
  496. if (cfg != NULL) {
  497. pcfg = lua_newuserdata (L, sizeof (struct rspamd_config *));
  498. rspamd_lua_setclass (L, "rspamd{config}", -1);
  499. *pcfg = cfg;
  500. lua_setglobal (L, "rspamd_config");
  501. }
  502. lua_settop (L, orig_top);
  503. /* Set known paths as rspamd_paths global */
  504. lua_getglobal (L, "rspamd_paths");
  505. if (lua_isnil (L, -1)) {
  506. const gchar *confdir = RSPAMD_CONFDIR,
  507. *local_confdir = RSPAMD_LOCAL_CONFDIR,
  508. *rundir = RSPAMD_RUNDIR,
  509. *dbdir = RSPAMD_DBDIR,
  510. *logdir = RSPAMD_LOGDIR,
  511. *wwwdir = RSPAMD_WWWDIR,
  512. *pluginsdir = RSPAMD_PLUGINSDIR,
  513. *rulesdir = RSPAMD_RULESDIR,
  514. *lualibdir = RSPAMD_LUALIBDIR,
  515. *prefix = RSPAMD_PREFIX,
  516. *sharedir = RSPAMD_SHAREDIR;
  517. const gchar *t;
  518. /* Try environment */
  519. t = getenv ("SHAREDIR");
  520. if (t) {
  521. sharedir = t;
  522. }
  523. t = getenv ("PLUGINSDIR");
  524. if (t) {
  525. pluginsdir = t;
  526. }
  527. t = getenv ("RULESDIR");
  528. if (t) {
  529. rulesdir = t;
  530. }
  531. t = getenv ("DBDIR");
  532. if (t) {
  533. dbdir = t;
  534. }
  535. t = getenv ("RUNDIR");
  536. if (t) {
  537. rundir = t;
  538. }
  539. t = getenv ("LUALIBDIR");
  540. if (t) {
  541. lualibdir = t;
  542. }
  543. t = getenv ("LOGDIR");
  544. if (t) {
  545. logdir = t;
  546. }
  547. t = getenv ("WWWDIR");
  548. if (t) {
  549. wwwdir = t;
  550. }
  551. t = getenv ("CONFDIR");
  552. if (t) {
  553. confdir = t;
  554. }
  555. t = getenv ("LOCAL_CONFDIR");
  556. if (t) {
  557. local_confdir = t;
  558. }
  559. if (vars) {
  560. t = g_hash_table_lookup (vars, "SHAREDIR");
  561. if (t) {
  562. sharedir = t;
  563. }
  564. t = g_hash_table_lookup (vars, "PLUGINSDIR");
  565. if (t) {
  566. pluginsdir = t;
  567. }
  568. t = g_hash_table_lookup (vars, "RULESDIR");
  569. if (t) {
  570. rulesdir = t;
  571. }
  572. t = g_hash_table_lookup (vars, "LUALIBDIR");
  573. if (t) {
  574. lualibdir = t;
  575. }
  576. t = g_hash_table_lookup (vars, "RUNDIR");
  577. if (t) {
  578. rundir = t;
  579. }
  580. t = g_hash_table_lookup (vars, "WWWDIR");
  581. if (t) {
  582. wwwdir = t;
  583. }
  584. t = g_hash_table_lookup (vars, "CONFDIR");
  585. if (t) {
  586. confdir = t;
  587. }
  588. t = g_hash_table_lookup (vars, "LOCAL_CONFDIR");
  589. if (t) {
  590. local_confdir = t;
  591. }
  592. t = g_hash_table_lookup (vars, "DBDIR");
  593. if (t) {
  594. dbdir = t;
  595. }
  596. t = g_hash_table_lookup (vars, "LOGDIR");
  597. if (t) {
  598. logdir = t;
  599. }
  600. }
  601. lua_createtable (L, 0, 9);
  602. rspamd_lua_table_set (L, RSPAMD_SHAREDIR_INDEX, sharedir);
  603. rspamd_lua_table_set (L, RSPAMD_CONFDIR_INDEX, confdir);
  604. rspamd_lua_table_set (L, RSPAMD_LOCAL_CONFDIR_INDEX, local_confdir);
  605. rspamd_lua_table_set (L, RSPAMD_RUNDIR_INDEX, rundir);
  606. rspamd_lua_table_set (L, RSPAMD_DBDIR_INDEX, dbdir);
  607. rspamd_lua_table_set (L, RSPAMD_LOGDIR_INDEX, logdir);
  608. rspamd_lua_table_set (L, RSPAMD_WWWDIR_INDEX, wwwdir);
  609. rspamd_lua_table_set (L, RSPAMD_PLUGINSDIR_INDEX, pluginsdir);
  610. rspamd_lua_table_set (L, RSPAMD_RULESDIR_INDEX, rulesdir);
  611. rspamd_lua_table_set (L, RSPAMD_LUALIBDIR_INDEX, lualibdir);
  612. rspamd_lua_table_set (L, RSPAMD_PREFIX_INDEX, prefix);
  613. lua_setglobal (L, "rspamd_paths");
  614. }
  615. lua_settop (L, orig_top);
  616. }
  617. #ifdef WITH_LUA_TRACE
  618. static gint
  619. lua_push_trace_data (lua_State *L)
  620. {
  621. if (lua_traces) {
  622. ucl_object_push_lua (L, lua_traces, true);
  623. }
  624. else {
  625. lua_pushnil (L);
  626. }
  627. return 1;
  628. }
  629. #endif
  630. lua_State *
  631. rspamd_lua_init ()
  632. {
  633. lua_State *L;
  634. L = luaL_newstate ();
  635. luaL_openlibs (L);
  636. luaopen_logger (L);
  637. luaopen_mempool (L);
  638. luaopen_config (L);
  639. luaopen_map (L);
  640. luaopen_trie (L);
  641. luaopen_task (L);
  642. luaopen_textpart (L);
  643. luaopen_mimepart (L);
  644. luaopen_image (L);
  645. luaopen_url (L);
  646. luaopen_classifier (L);
  647. luaopen_statfile (L);
  648. luaopen_regexp (L);
  649. luaopen_cdb (L);
  650. luaopen_xmlrpc (L);
  651. luaopen_http (L);
  652. luaopen_redis (L);
  653. luaopen_upstream (L);
  654. lua_add_actions_global (L);
  655. luaopen_dns_resolver (L);
  656. luaopen_rsa (L);
  657. luaopen_ip (L);
  658. luaopen_expression (L);
  659. luaopen_text (L);
  660. luaopen_util (L);
  661. luaopen_tcp (L);
  662. luaopen_html (L);
  663. luaopen_fann (L);
  664. luaopen_sqlite3 (L);
  665. luaopen_cryptobox (L);
  666. luaopen_dns (L);
  667. luaL_newmetatable (L, "rspamd{ev_base}");
  668. lua_pushstring (L, "class");
  669. lua_pushstring (L, "rspamd{ev_base}");
  670. lua_rawset (L, -3);
  671. lua_pop (L, 1);
  672. luaL_newmetatable (L, "rspamd{session}");
  673. lua_pushstring (L, "class");
  674. lua_pushstring (L, "rspamd{session}");
  675. lua_rawset (L, -3);
  676. lua_pop (L, 1);
  677. rspamd_lua_new_class (L, "rspamd{worker}", worker_reg);
  678. rspamd_lua_add_preload (L, "lpeg", luaopen_lpeg);
  679. luaopen_ucl (L);
  680. rspamd_lua_add_preload (L, "ucl", luaopen_ucl);
  681. /* Add plugins global */
  682. lua_newtable (L);
  683. lua_setglobal (L, "rspamd_plugins");
  684. /* Set PRNG */
  685. lua_getglobal (L, "math");
  686. lua_pushstring (L, "randomseed");
  687. lua_gettable (L, -2);
  688. lua_pushinteger (L, ottery_rand_uint64 ());
  689. lua_pcall (L, 1, 0, 0);
  690. lua_pop (L, 1); /* math table */
  691. /* Modules state */
  692. lua_newtable (L);
  693. /*
  694. * rspamd_plugins_state = {
  695. * enabled = {},
  696. * disabled_unconfigured = {},
  697. * disabled_redis = {},
  698. * disabled_explicitly = {},
  699. * disabled_failed = {},
  700. * disabled_experimental = {},
  701. * }
  702. */
  703. #define ADD_TABLE(name) do { \
  704. lua_pushstring (L, #name); \
  705. lua_newtable (L); \
  706. lua_settable (L, -3); \
  707. } while (0)
  708. ADD_TABLE (enabled);
  709. ADD_TABLE (disabled_unconfigured);
  710. ADD_TABLE (disabled_redis);
  711. ADD_TABLE (disabled_explicitly);
  712. ADD_TABLE (disabled_failed);
  713. ADD_TABLE (disabled_experimental);
  714. #undef ADD_TABLE
  715. lua_setglobal (L, rspamd_modules_state_global);
  716. #ifdef WITH_LUA_TRACE
  717. lua_pushcfunction (L, lua_push_trace_data);
  718. lua_setglobal (L, "get_traces");
  719. #endif
  720. return L;
  721. }
  722. /**
  723. * Initialize new locked lua_State structure
  724. */
  725. struct lua_locked_state *
  726. rspamd_init_lua_locked (struct rspamd_config *cfg)
  727. {
  728. struct lua_locked_state *new;
  729. new = g_malloc0 (sizeof (struct lua_locked_state));
  730. new->L = rspamd_lua_init ();
  731. new->m = rspamd_mutex_new ();
  732. return new;
  733. }
  734. /**
  735. * Free locked state structure
  736. */
  737. void
  738. rspamd_free_lua_locked (struct lua_locked_state *st)
  739. {
  740. g_assert (st != NULL);
  741. lua_close (st->L);
  742. rspamd_mutex_free (st->m);
  743. g_free (st);
  744. }
  745. void
  746. rspamd_plugins_table_push_elt (lua_State *L, const gchar *field_name,
  747. const gchar *new_elt)
  748. {
  749. lua_getglobal (L, rspamd_modules_state_global);
  750. lua_pushstring (L, field_name);
  751. lua_gettable (L, -2);
  752. lua_pushstring (L, new_elt);
  753. lua_newtable (L);
  754. lua_settable (L, -3);
  755. lua_pop (L, 2); /* Global + element */
  756. }
  757. gboolean
  758. rspamd_init_lua_filters (struct rspamd_config *cfg, gboolean force_load)
  759. {
  760. struct rspamd_config **pcfg;
  761. GList *cur;
  762. struct script_module *module;
  763. lua_State *L = cfg->lua_state;
  764. GString *tb;
  765. gint err_idx;
  766. cur = g_list_first (cfg->script_modules);
  767. while (cur) {
  768. module = cur->data;
  769. if (module->path) {
  770. if (!force_load) {
  771. if (!rspamd_config_is_module_enabled (cfg, module->name)) {
  772. cur = g_list_next (cur);
  773. continue;
  774. }
  775. }
  776. lua_pushcfunction (L, &rspamd_lua_traceback);
  777. err_idx = lua_gettop (L);
  778. if (luaL_loadfile (L, module->path) != 0) {
  779. msg_err_config ("load of %s failed: %s", module->path,
  780. lua_tostring (L, -1));
  781. lua_pop (L, 1); /* Error function */
  782. rspamd_plugins_table_push_elt (L, "disabled_failed",
  783. module->name);
  784. cur = g_list_next (cur);
  785. continue;
  786. }
  787. /* Initialize config structure */
  788. pcfg = lua_newuserdata (L, sizeof (struct rspamd_config *));
  789. rspamd_lua_setclass (L, "rspamd{config}", -1);
  790. *pcfg = cfg;
  791. lua_setglobal (L, "rspamd_config");
  792. if (lua_pcall (L, 0, 0, err_idx) != 0) {
  793. tb = lua_touserdata (L, -1);
  794. msg_err_config ("init of %s failed: %v",
  795. module->path,
  796. tb);
  797. g_string_free (tb, TRUE);
  798. lua_pop (L, 2); /* Result and error function */
  799. rspamd_plugins_table_push_elt (L, "disabled_failed",
  800. module->name);
  801. cur = g_list_next (cur);
  802. continue;
  803. }
  804. if (!force_load) {
  805. msg_info_config ("init lua module %s", module->name);
  806. }
  807. lua_pop (L, 1); /* Error function */
  808. }
  809. cur = g_list_next (cur);
  810. }
  811. return TRUE;
  812. }
  813. void
  814. rspamd_lua_dumpstack (lua_State *L)
  815. {
  816. gint i, t, r = 0;
  817. gint top = lua_gettop (L);
  818. gchar buf[BUFSIZ];
  819. r += rspamd_snprintf (buf + r, sizeof (buf) - r, "lua stack: ");
  820. for (i = 1; i <= top; i++) { /* repeat for each level */
  821. t = lua_type (L, i);
  822. switch (t)
  823. {
  824. case LUA_TSTRING: /* strings */
  825. r += rspamd_snprintf (buf + r,
  826. sizeof (buf) - r,
  827. "str: %s",
  828. lua_tostring (L, i));
  829. break;
  830. case LUA_TBOOLEAN: /* booleans */
  831. r += rspamd_snprintf (buf + r, sizeof (buf) - r,
  832. lua_toboolean (L, i) ? "bool: true" : "bool: false");
  833. break;
  834. case LUA_TNUMBER: /* numbers */
  835. r += rspamd_snprintf (buf + r,
  836. sizeof (buf) - r,
  837. "number: %.2f",
  838. lua_tonumber (L, i));
  839. break;
  840. default: /* other values */
  841. r += rspamd_snprintf (buf + r,
  842. sizeof (buf) - r,
  843. "type: %s",
  844. lua_typename (L, t));
  845. break;
  846. }
  847. if (i < top) {
  848. r += rspamd_snprintf (buf + r, sizeof (buf) - r, " -> "); /* put a separator */
  849. }
  850. }
  851. msg_info (buf);
  852. }
  853. gpointer
  854. rspamd_lua_check_class (lua_State *L, gint index, const gchar *name)
  855. {
  856. gpointer p;
  857. if (lua_type (L, index) == LUA_TUSERDATA) {
  858. p = lua_touserdata (L, index);
  859. if (p) {
  860. if (lua_getmetatable (L, index)) {
  861. lua_getfield (L, LUA_REGISTRYINDEX, name); /* get correct metatable */
  862. if (lua_rawequal (L, -1, -2)) { /* does it have the correct mt? */
  863. lua_pop (L, 2); /* remove both metatables */
  864. return p;
  865. }
  866. lua_pop (L, 2);
  867. }
  868. }
  869. }
  870. return NULL;
  871. }
  872. int
  873. rspamd_lua_typerror (lua_State *L, int narg, const char *tname)
  874. {
  875. const char *msg = lua_pushfstring (L, "%s expected, got %s", tname,
  876. luaL_typename (L, narg));
  877. return luaL_argerror (L, narg, msg);
  878. }
  879. void
  880. rspamd_lua_add_preload (lua_State *L, const gchar *name, lua_CFunction func)
  881. {
  882. lua_getglobal (L, "package");
  883. lua_pushstring (L, "preload");
  884. lua_gettable (L, -2);
  885. lua_pushcfunction (L, func);
  886. lua_setfield (L, -2, name);
  887. lua_pop (L, 2); /* preload key + global package */
  888. }
  889. gboolean
  890. rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
  891. GError **err, const gchar *extraction_pattern, ...)
  892. {
  893. const gchar *p, *key = NULL, *end, *cls;
  894. va_list ap;
  895. gboolean required = FALSE, failed = FALSE, is_table;
  896. gchar classbuf[128];
  897. enum {
  898. read_key = 0,
  899. read_arg,
  900. read_class_start,
  901. read_class,
  902. read_semicolon
  903. } state = read_key;
  904. gsize keylen = 0, *valuelen, clslen;
  905. gint idx = 0, t;
  906. g_assert (extraction_pattern != NULL);
  907. if (pos < 0) {
  908. /* Get absolute pos */
  909. pos = lua_gettop (L) + pos + 1;
  910. }
  911. if (lua_type (L, pos) == LUA_TTABLE) {
  912. is_table = TRUE;
  913. }
  914. else {
  915. is_table = FALSE;
  916. idx = pos;
  917. }
  918. p = extraction_pattern;
  919. end = p + strlen (extraction_pattern);
  920. va_start (ap, extraction_pattern);
  921. while (p <= end) {
  922. switch (state) {
  923. case read_key:
  924. if (*p == '=') {
  925. if (key == NULL) {
  926. g_set_error (err, lua_error_quark (), 1, "cannot read key");
  927. va_end (ap);
  928. return FALSE;
  929. }
  930. state = read_arg;
  931. keylen = p - key;
  932. }
  933. else if (*p == '*' && key == NULL) {
  934. required = TRUE;
  935. }
  936. else if (key == NULL) {
  937. key = p;
  938. }
  939. p ++;
  940. break;
  941. case read_arg:
  942. g_assert (keylen != 0);
  943. if (is_table) {
  944. lua_pushlstring (L, key, keylen);
  945. lua_gettable (L, pos);
  946. idx = -1;
  947. }
  948. t = lua_type (L, idx);
  949. switch (g_ascii_toupper (*p)) {
  950. case 'S':
  951. if (t == LUA_TSTRING) {
  952. *(va_arg (ap, const gchar **)) = lua_tostring (L, idx);
  953. }
  954. else if (t == LUA_TNIL || t == LUA_TNONE) {
  955. failed = TRUE;
  956. *(va_arg (ap, const gchar **)) = NULL;
  957. }
  958. else {
  959. g_set_error (err,
  960. lua_error_quark (),
  961. 1,
  962. "bad type for key:"
  963. " %.*s: '%s', '%s' is expected",
  964. (gint) keylen,
  965. key,
  966. lua_typename (L, lua_type (L, idx)), "string");
  967. va_end (ap);
  968. return FALSE;
  969. }
  970. if (is_table) {
  971. lua_pop (L, 1);
  972. }
  973. break;
  974. case 'I':
  975. if (t == LUA_TNUMBER) {
  976. *(va_arg (ap, gint64 *)) = lua_tonumber (L, idx);
  977. }
  978. else if (t == LUA_TNIL || t == LUA_TNONE) {
  979. failed = TRUE;
  980. *(va_arg (ap, gint64 *)) = 0;
  981. }
  982. else {
  983. g_set_error (err,
  984. lua_error_quark (),
  985. 1,
  986. "bad type for key:"
  987. " %.*s: '%s', '%s' is expected",
  988. (gint) keylen,
  989. key,
  990. lua_typename (L, lua_type (L, idx)),
  991. "int64");
  992. va_end (ap);
  993. return FALSE;
  994. }
  995. if (is_table) {
  996. lua_pop (L, 1);
  997. }
  998. break;
  999. case 'F':
  1000. if (t == LUA_TFUNCTION) {
  1001. if (!is_table) {
  1002. lua_pushvalue (L, idx);
  1003. }
  1004. *(va_arg (ap, gint *)) = luaL_ref (L, LUA_REGISTRYINDEX);
  1005. }
  1006. else if (t == LUA_TNIL || t == LUA_TNONE) {
  1007. failed = TRUE;
  1008. *(va_arg (ap, gint *)) = -1;
  1009. if (is_table) {
  1010. lua_pop (L, 1);
  1011. }
  1012. }
  1013. else {
  1014. g_set_error (err,
  1015. lua_error_quark (),
  1016. 1,
  1017. "bad type for key:"
  1018. " %.*s: '%s', '%s' is expected",
  1019. (gint) keylen,
  1020. key,
  1021. lua_typename (L, lua_type (L, idx)),
  1022. "function");
  1023. va_end (ap);
  1024. if (is_table) {
  1025. lua_pop (L, 1);
  1026. }
  1027. return FALSE;
  1028. }
  1029. /* luaL_ref pops argument from the stack */
  1030. break;
  1031. case 'B':
  1032. if (t == LUA_TBOOLEAN) {
  1033. *(va_arg (ap, gboolean *)) = lua_toboolean (L, idx);
  1034. }
  1035. else if (t == LUA_TNIL || t == LUA_TNONE) {
  1036. failed = TRUE;
  1037. *(va_arg (ap, gboolean *)) = 0;
  1038. }
  1039. else {
  1040. g_set_error (err,
  1041. lua_error_quark (),
  1042. 1,
  1043. "bad type for key:"
  1044. " %.*s: '%s', '%s' is expected",
  1045. (gint) keylen,
  1046. key,
  1047. lua_typename (L, lua_type (L, idx)),
  1048. "bool");
  1049. va_end (ap);
  1050. return FALSE;
  1051. }
  1052. if (is_table) {
  1053. lua_pop (L, 1);
  1054. }
  1055. break;
  1056. case 'N':
  1057. if (t == LUA_TNUMBER) {
  1058. *(va_arg (ap, gdouble *)) = lua_tonumber (L, idx);
  1059. }
  1060. else if (t == LUA_TNIL || t == LUA_TNONE) {
  1061. failed = TRUE;
  1062. *(va_arg (ap, gdouble *)) = 0;
  1063. }
  1064. else {
  1065. g_set_error (err,
  1066. lua_error_quark (),
  1067. 1,
  1068. "bad type for key:"
  1069. " %.*s: '%s', '%s' is expected",
  1070. (gint) keylen,
  1071. key,
  1072. lua_typename (L, lua_type (L, idx)),
  1073. "double");
  1074. va_end (ap);
  1075. return FALSE;
  1076. }
  1077. if (is_table) {
  1078. lua_pop (L, 1);
  1079. }
  1080. break;
  1081. case 'D':
  1082. if (t == LUA_TNUMBER) {
  1083. *(va_arg (ap, gdouble *)) = lua_tonumber (L, idx);
  1084. }
  1085. else if (t == LUA_TNIL || t == LUA_TNONE) {
  1086. failed = TRUE;
  1087. *(va_arg (ap, gdouble *)) = NAN;
  1088. }
  1089. else {
  1090. g_set_error (err,
  1091. lua_error_quark (),
  1092. 1,
  1093. "bad type for key:"
  1094. " %.*s: '%s', '%s' is expected",
  1095. (gint) keylen,
  1096. key,
  1097. lua_typename (L, lua_type (L, idx)),
  1098. "double");
  1099. va_end (ap);
  1100. return FALSE;
  1101. }
  1102. if (is_table) {
  1103. lua_pop (L, 1);
  1104. }
  1105. break;
  1106. case 'V':
  1107. valuelen = va_arg (ap, gsize *);
  1108. if (t == LUA_TSTRING) {
  1109. *(va_arg (ap, const gchar **)) = lua_tolstring (L, idx,
  1110. valuelen);
  1111. }
  1112. else if (t == LUA_TNIL || t == LUA_TNONE) {
  1113. failed = TRUE;
  1114. *(va_arg (ap, const char **)) = NULL;
  1115. *valuelen = 0;
  1116. }
  1117. else {
  1118. g_set_error (err,
  1119. lua_error_quark (),
  1120. 1,
  1121. "bad type for key:"
  1122. " %.*s: '%s', '%s' is expected",
  1123. (gint) keylen,
  1124. key,
  1125. lua_typename (L, lua_type (L, idx)),
  1126. "string");
  1127. va_end (ap);
  1128. return FALSE;
  1129. }
  1130. if (is_table) {
  1131. lua_pop (L, 1);
  1132. }
  1133. break;
  1134. case 'O':
  1135. if (t != LUA_TNONE) {
  1136. *(va_arg (ap, ucl_object_t **)) = ucl_object_lua_import (L,
  1137. idx);
  1138. }
  1139. else {
  1140. failed = TRUE;
  1141. *(va_arg (ap, ucl_object_t **)) = NULL;
  1142. }
  1143. if (is_table) {
  1144. lua_pop (L, 1);
  1145. }
  1146. break;
  1147. case 'U':
  1148. if (t == LUA_TNIL || t == LUA_TNONE) {
  1149. failed = TRUE;
  1150. *(va_arg (ap, void **)) = NULL;
  1151. }
  1152. else if (t != LUA_TUSERDATA) {
  1153. g_set_error (err,
  1154. lua_error_quark (),
  1155. 1,
  1156. "bad type for key:"
  1157. " %.*s: '%s', '%s' is expected",
  1158. (gint) keylen,
  1159. key,
  1160. lua_typename (L, lua_type (L, idx)),
  1161. "int64");
  1162. va_end (ap);
  1163. return FALSE;
  1164. }
  1165. state = read_class_start;
  1166. clslen = 0;
  1167. cls = NULL;
  1168. p ++;
  1169. continue;
  1170. default:
  1171. g_assert (0);
  1172. break;
  1173. }
  1174. if (failed && required) {
  1175. g_set_error (err, lua_error_quark (), 2, "required parameter "
  1176. "%.*s is missing", (gint)keylen, key);
  1177. va_end (ap);
  1178. return FALSE;
  1179. }
  1180. if (!is_table) {
  1181. idx ++;
  1182. }
  1183. /* Reset read params */
  1184. state = read_semicolon;
  1185. failed = FALSE;
  1186. required = FALSE;
  1187. keylen = 0;
  1188. key = NULL;
  1189. p ++;
  1190. break;
  1191. case read_class_start:
  1192. if (*p == '{') {
  1193. cls = p + 1;
  1194. state = read_class;
  1195. }
  1196. else {
  1197. if (is_table) {
  1198. lua_pop (L, 1);
  1199. }
  1200. g_set_error (err, lua_error_quark (), 2, "missing classname for "
  1201. "%.*s", (gint)keylen, key);
  1202. va_end (ap);
  1203. return FALSE;
  1204. }
  1205. p ++;
  1206. break;
  1207. case read_class:
  1208. if (*p == '}') {
  1209. clslen = p - cls;
  1210. if (clslen == 0) {
  1211. if (is_table) {
  1212. lua_pop (L, 1);
  1213. }
  1214. g_set_error (err,
  1215. lua_error_quark (),
  1216. 2,
  1217. "empty classname for "
  1218. "%*.s",
  1219. (gint) keylen,
  1220. key);
  1221. va_end (ap);
  1222. return FALSE;
  1223. }
  1224. rspamd_snprintf (classbuf, sizeof (classbuf), "rspamd{%*s}",
  1225. (gint) clslen, cls);
  1226. /*
  1227. * We skip class check here for speed in non-table mode
  1228. */
  1229. if (!failed && (!is_table ||
  1230. rspamd_lua_check_class (L, idx, classbuf))) {
  1231. *(va_arg (ap, void **)) = *(void **)lua_touserdata (L, idx);
  1232. }
  1233. else {
  1234. if (!failed) {
  1235. g_set_error (err,
  1236. lua_error_quark (),
  1237. 2,
  1238. "invalid class for key %.*s, expected %s, got %s",
  1239. (gint) keylen,
  1240. key,
  1241. classbuf,
  1242. rspamd_lua_class_tostring_buf (L, FALSE, idx));
  1243. va_end (ap);
  1244. return FALSE;
  1245. }
  1246. }
  1247. if (is_table) {
  1248. lua_pop (L, 1);
  1249. }
  1250. else {
  1251. idx ++;
  1252. }
  1253. if (failed && required) {
  1254. g_set_error (err,
  1255. lua_error_quark (),
  1256. 2,
  1257. "required parameter "
  1258. "%.*s is missing",
  1259. (gint) keylen,
  1260. key);
  1261. va_end (ap);
  1262. return FALSE;
  1263. }
  1264. /* Reset read params */
  1265. state = read_semicolon;
  1266. failed = FALSE;
  1267. required = FALSE;
  1268. keylen = 0;
  1269. key = NULL;
  1270. }
  1271. p ++;
  1272. break;
  1273. case read_semicolon:
  1274. if (*p == ';' || p == end) {
  1275. state = read_key;
  1276. key = NULL;
  1277. keylen = 0;
  1278. failed = FALSE;
  1279. }
  1280. else {
  1281. g_set_error (err, lua_error_quark (), 2, "bad format string: %s,"
  1282. " at char %c, position %d",
  1283. extraction_pattern, *p, (int)(p - extraction_pattern));
  1284. va_end (ap);
  1285. return FALSE;
  1286. }
  1287. p++;
  1288. break;
  1289. }
  1290. }
  1291. va_end (ap);
  1292. return TRUE;
  1293. }
  1294. static void
  1295. rspamd_lua_traceback_string (lua_State *L, GString *s)
  1296. {
  1297. gint i = 1;
  1298. lua_Debug d;
  1299. while (lua_getstack (L, i++, &d)) {
  1300. lua_getinfo (L, "nSl", &d);
  1301. g_string_append_printf (s, " [%d]:{%s:%d - %s [%s]};",
  1302. i - 1, d.short_src, d.currentline,
  1303. (d.name ? d.name : "<unknown>"), d.what);
  1304. }
  1305. }
  1306. gint
  1307. rspamd_lua_traceback (lua_State *L)
  1308. {
  1309. GString *tb;
  1310. tb = rspamd_lua_get_traceback_string (L);
  1311. lua_pushlightuserdata (L, tb);
  1312. return 1;
  1313. }
  1314. GString *
  1315. rspamd_lua_get_traceback_string (lua_State *L)
  1316. {
  1317. GString *tb;
  1318. const gchar *msg = lua_tostring (L, -1);
  1319. tb = g_string_sized_new (100);
  1320. g_string_append_printf (tb, "%s; trace:", msg);
  1321. rspamd_lua_traceback_string (L, tb);
  1322. return tb;
  1323. }
  1324. guint
  1325. rspamd_lua_table_size (lua_State *L, gint tbl_pos)
  1326. {
  1327. guint tbl_size = 0;
  1328. if (!lua_istable (L, tbl_pos)) {
  1329. return 0;
  1330. }
  1331. #if LUA_VERSION_NUM >= 502
  1332. tbl_size = lua_rawlen (L, tbl_pos);
  1333. #else
  1334. tbl_size = lua_objlen (L, tbl_pos);
  1335. #endif
  1336. return tbl_size;
  1337. }
  1338. static void *
  1339. rspamd_lua_check_udata_common (lua_State *L, gint pos, const gchar *classname,
  1340. gboolean fatal)
  1341. {
  1342. void *p = lua_touserdata (L, pos);
  1343. GString *err_msg;
  1344. guint i, top = lua_gettop (L);
  1345. if (p == NULL) {
  1346. goto err;
  1347. }
  1348. else {
  1349. /* Match class */
  1350. if (lua_getmetatable (L, pos)) {
  1351. luaL_getmetatable (L, classname);
  1352. if (!lua_rawequal (L, -1, -2)) {
  1353. goto err;
  1354. }
  1355. }
  1356. else {
  1357. goto err;
  1358. }
  1359. }
  1360. lua_settop (L, top);
  1361. return p;
  1362. err:
  1363. if (fatal) {
  1364. const gchar *actual_classname = NULL;
  1365. if (lua_type (L, pos) == LUA_TUSERDATA && lua_getmetatable (L, pos)) {
  1366. lua_pushstring (L, "__index");
  1367. lua_gettable (L, -2);
  1368. lua_pushstring (L, "class");
  1369. lua_gettable (L, -2);
  1370. actual_classname = lua_tostring (L, -1);
  1371. }
  1372. else {
  1373. actual_classname = lua_typename (L, lua_type (L, pos));
  1374. }
  1375. err_msg = g_string_sized_new (100);
  1376. rspamd_printf_gstring (err_msg, "expected %s at position %d, but userdata has "
  1377. "%s metatable; trace: ",
  1378. classname, pos, actual_classname);
  1379. rspamd_lua_traceback_string (L, err_msg);
  1380. rspamd_printf_gstring (err_msg, " stack(%d): ", top);
  1381. for (i = 1; i <= MIN (top, 10); i ++) {
  1382. if (lua_type (L, i) == LUA_TUSERDATA) {
  1383. const char *clsname;
  1384. if (lua_getmetatable (L, i)) {
  1385. lua_pushstring (L, "__index");
  1386. lua_gettable (L, -2);
  1387. lua_pushstring (L, "class");
  1388. lua_gettable (L, -2);
  1389. clsname = lua_tostring (L, -1);
  1390. }
  1391. else {
  1392. clsname = lua_typename (L, lua_type (L, i));
  1393. }
  1394. rspamd_printf_gstring (err_msg, "[%d: ud=%s] ", i,
  1395. clsname);
  1396. }
  1397. else {
  1398. rspamd_printf_gstring (err_msg, "[%d: %s] ", i,
  1399. lua_typename (L, lua_type (L, i)));
  1400. }
  1401. }
  1402. msg_err ("lua type error: %v", err_msg);
  1403. g_string_free (err_msg, TRUE);
  1404. }
  1405. lua_settop (L, top);
  1406. return NULL;
  1407. }
  1408. void *
  1409. rspamd_lua_check_udata (lua_State *L, gint pos, const gchar *classname)
  1410. {
  1411. return rspamd_lua_check_udata_common (L, pos, classname, TRUE);
  1412. }
  1413. void *
  1414. rspamd_lua_check_udata_maybe (lua_State *L, gint pos, const gchar *classname)
  1415. {
  1416. return rspamd_lua_check_udata_common (L, pos, classname, FALSE);
  1417. }
  1418. struct rspamd_async_session*
  1419. lua_check_session (lua_State * L, gint pos)
  1420. {
  1421. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{session}");
  1422. luaL_argcheck (L, ud != NULL, pos, "'session' expected");
  1423. return ud ? *((struct rspamd_async_session **)ud) : NULL;
  1424. }
  1425. struct event_base*
  1426. lua_check_ev_base (lua_State * L, gint pos)
  1427. {
  1428. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{ev_base}");
  1429. luaL_argcheck (L, ud != NULL, pos, "'event_base' expected");
  1430. return ud ? *((struct event_base **)ud) : NULL;
  1431. }
  1432. static void rspamd_lua_run_postloads_error (struct thread_entry *thread, int ret, const char *msg);
  1433. void
  1434. rspamd_lua_run_postloads (lua_State *L, struct rspamd_config *cfg,
  1435. struct event_base *ev_base, struct rspamd_worker *w)
  1436. {
  1437. struct rspamd_config_post_load_script *sc;
  1438. struct rspamd_config **pcfg;
  1439. struct event_base **pev_base;
  1440. struct rspamd_worker **pw;
  1441. /* Execute post load scripts */
  1442. LL_FOREACH (cfg->on_load, sc) {
  1443. struct thread_entry *thread = lua_thread_pool_get_for_config (cfg);
  1444. thread->error_callback = rspamd_lua_run_postloads_error;
  1445. L = thread->lua_state;
  1446. lua_rawgeti (L, LUA_REGISTRYINDEX, sc->cbref);
  1447. pcfg = lua_newuserdata (L, sizeof (*pcfg));
  1448. *pcfg = cfg;
  1449. rspamd_lua_setclass (L, "rspamd{config}", -1);
  1450. pev_base = lua_newuserdata (L, sizeof (*pev_base));
  1451. *pev_base = ev_base;
  1452. rspamd_lua_setclass (L, "rspamd{ev_base}", -1);
  1453. pw = lua_newuserdata (L, sizeof (*pw));
  1454. *pw = w;
  1455. rspamd_lua_setclass (L, "rspamd{worker}", -1);
  1456. lua_thread_call (thread, 3);
  1457. }
  1458. }
  1459. static void
  1460. rspamd_lua_run_postloads_error (struct thread_entry *thread, int ret, const char *msg)
  1461. {
  1462. struct rspamd_config *cfg = thread->cfg;
  1463. msg_err_config ("error executing post load code: %s", msg);
  1464. }
  1465. static struct rspamd_worker *
  1466. lua_check_worker (lua_State *L, gint pos)
  1467. {
  1468. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{worker}");
  1469. luaL_argcheck (L, ud != NULL, pos, "'worker' expected");
  1470. return ud ? *((struct rspamd_worker **)ud) : NULL;
  1471. }
  1472. static gint
  1473. lua_worker_get_stat (lua_State *L)
  1474. {
  1475. struct rspamd_worker *w = lua_check_worker (L, 1);
  1476. if (w) {
  1477. rspamd_mempool_stat_t mem_st;
  1478. struct rspamd_stat *stat, stat_copy;
  1479. ucl_object_t *top, *sub;
  1480. gint i;
  1481. guint64 spam = 0, ham = 0;
  1482. memset (&mem_st, 0, sizeof (mem_st));
  1483. rspamd_mempool_stat (&mem_st);
  1484. memcpy (&stat_copy, w->srv->stat, sizeof (stat_copy));
  1485. stat = &stat_copy;
  1486. top = ucl_object_typed_new (UCL_OBJECT);
  1487. ucl_object_insert_key (top, ucl_object_fromint (
  1488. stat->messages_scanned), "scanned", 0, false);
  1489. ucl_object_insert_key (top, ucl_object_fromint (
  1490. stat->messages_learned), "learned", 0, false);
  1491. if (stat->messages_scanned > 0) {
  1492. sub = ucl_object_typed_new (UCL_OBJECT);
  1493. for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) {
  1494. ucl_object_insert_key (sub,
  1495. ucl_object_fromint (stat->actions_stat[i]),
  1496. rspamd_action_to_str (i), 0, false);
  1497. if (i < METRIC_ACTION_GREYLIST) {
  1498. spam += stat->actions_stat[i];
  1499. }
  1500. else {
  1501. ham += stat->actions_stat[i];
  1502. }
  1503. }
  1504. ucl_object_insert_key (top, sub, "actions", 0, false);
  1505. }
  1506. else {
  1507. sub = ucl_object_typed_new (UCL_OBJECT);
  1508. for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) {
  1509. ucl_object_insert_key (sub,
  1510. 0,
  1511. rspamd_action_to_str (i), 0, false);
  1512. }
  1513. ucl_object_insert_key (top, sub, "actions", 0, false);
  1514. }
  1515. ucl_object_insert_key (top, ucl_object_fromint (
  1516. spam), "spam_count", 0, false);
  1517. ucl_object_insert_key (top, ucl_object_fromint (
  1518. ham), "ham_count", 0, false);
  1519. ucl_object_insert_key (top,
  1520. ucl_object_fromint (stat->connections_count), "connections", 0, false);
  1521. ucl_object_insert_key (top,
  1522. ucl_object_fromint (stat->control_connections_count),
  1523. "control_connections", 0, false);
  1524. ucl_object_insert_key (top,
  1525. ucl_object_fromint (mem_st.pools_allocated), "pools_allocated", 0,
  1526. false);
  1527. ucl_object_insert_key (top,
  1528. ucl_object_fromint (mem_st.pools_freed), "pools_freed", 0, false);
  1529. ucl_object_insert_key (top,
  1530. ucl_object_fromint (mem_st.bytes_allocated), "bytes_allocated", 0,
  1531. false);
  1532. ucl_object_insert_key (top,
  1533. ucl_object_fromint (
  1534. mem_st.chunks_allocated), "chunks_allocated", 0, false);
  1535. ucl_object_insert_key (top,
  1536. ucl_object_fromint (mem_st.shared_chunks_allocated),
  1537. "shared_chunks_allocated", 0, false);
  1538. ucl_object_insert_key (top,
  1539. ucl_object_fromint (mem_st.chunks_freed), "chunks_freed", 0, false);
  1540. ucl_object_insert_key (top,
  1541. ucl_object_fromint (
  1542. mem_st.oversized_chunks), "chunks_oversized", 0, false);
  1543. ucl_object_push_lua (L, top, true);
  1544. ucl_object_unref (top);
  1545. }
  1546. else {
  1547. return luaL_error (L, "invalid arguments");
  1548. }
  1549. return 1;
  1550. }
  1551. static gint
  1552. lua_worker_get_name (lua_State *L)
  1553. {
  1554. struct rspamd_worker *w = lua_check_worker (L, 1);
  1555. if (w) {
  1556. lua_pushstring (L, g_quark_to_string (w->type));
  1557. }
  1558. else {
  1559. return luaL_error (L, "invalid arguments");
  1560. }
  1561. return 1;
  1562. }
  1563. static gint
  1564. lua_worker_get_index (lua_State *L)
  1565. {
  1566. struct rspamd_worker *w = lua_check_worker (L, 1);
  1567. if (w) {
  1568. lua_pushinteger (L, w->index);
  1569. }
  1570. else {
  1571. return luaL_error (L, "invalid arguments");
  1572. }
  1573. return 1;
  1574. }
  1575. static gint
  1576. lua_worker_get_pid (lua_State *L)
  1577. {
  1578. struct rspamd_worker *w = lua_check_worker (L, 1);
  1579. if (w) {
  1580. lua_pushinteger (L, w->pid);
  1581. }
  1582. else {
  1583. return luaL_error (L, "invalid arguments");
  1584. }
  1585. return 1;
  1586. }
  1587. static gint
  1588. lua_worker_is_scanner (lua_State *L)
  1589. {
  1590. struct rspamd_worker *w = lua_check_worker (L, 1);
  1591. if (w) {
  1592. lua_pushboolean (L, rspamd_worker_is_scanner (w));
  1593. }
  1594. else {
  1595. return luaL_error (L, "invalid arguments");
  1596. }
  1597. return 1;
  1598. }
  1599. static gint
  1600. lua_worker_is_primary_controller (lua_State *L)
  1601. {
  1602. struct rspamd_worker *w = lua_check_worker (L, 1);
  1603. if (w) {
  1604. lua_pushboolean (L, rspamd_worker_is_primary_controller (w));
  1605. }
  1606. else {
  1607. return luaL_error (L, "invalid arguments");
  1608. }
  1609. return 1;
  1610. }
  1611. struct rspamd_lua_process_cbdata {
  1612. gint sp[2];
  1613. gint func_cbref;
  1614. gint cb_cbref;
  1615. gboolean replied;
  1616. gboolean is_error;
  1617. pid_t cpid;
  1618. lua_State *L;
  1619. guint64 sz;
  1620. GString *io_buf;
  1621. GString *out_buf;
  1622. goffset out_pos;
  1623. struct rspamd_worker *wrk;
  1624. struct event_base *ev_base;
  1625. struct event ev;
  1626. };
  1627. static void
  1628. rspamd_lua_execute_lua_subprocess (lua_State *L,
  1629. struct rspamd_lua_process_cbdata *cbdata)
  1630. {
  1631. gint err_idx, r;
  1632. GString *tb;
  1633. guint64 wlen = 0;
  1634. const gchar *ret;
  1635. gsize retlen;
  1636. lua_pushcfunction (L, &rspamd_lua_traceback);
  1637. err_idx = lua_gettop (L);
  1638. lua_rawgeti (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
  1639. if (lua_pcall (L, 0, 1, err_idx) != 0) {
  1640. tb = lua_touserdata (L, -1);
  1641. msg_err ("call to subprocess failed: %v", tb);
  1642. /* Indicate error */
  1643. wlen = (1ULL << 63) + tb->len;
  1644. g_string_free (tb, TRUE);
  1645. r = write (cbdata->sp[1], &wlen, sizeof (wlen));
  1646. if (r == -1) {
  1647. msg_err ("write failed: %s", strerror (errno));
  1648. }
  1649. r = write (cbdata->sp[1], tb->str, tb->len);
  1650. if (r == -1) {
  1651. msg_err ("write failed: %s", strerror (errno));
  1652. }
  1653. lua_pop (L, 1);
  1654. }
  1655. else {
  1656. ret = lua_tolstring (L, -1, &retlen);
  1657. wlen = retlen;
  1658. r = write (cbdata->sp[1], &wlen, sizeof (wlen));
  1659. if (r == -1) {
  1660. msg_err ("write failed: %s", strerror (errno));
  1661. }
  1662. r = write (cbdata->sp[1], ret, retlen);
  1663. if (r == -1) {
  1664. msg_err ("write failed: %s", strerror (errno));
  1665. }
  1666. }
  1667. lua_pop (L, 1); /* Error function */
  1668. }
  1669. static void
  1670. rspamd_lua_call_on_complete (lua_State *L,
  1671. struct rspamd_lua_process_cbdata *cbdata,
  1672. const gchar *err_msg,
  1673. const gchar *data, gsize datalen)
  1674. {
  1675. gint err_idx;
  1676. GString *tb;
  1677. lua_pushcfunction (L, &rspamd_lua_traceback);
  1678. err_idx = lua_gettop (L);
  1679. lua_rawgeti (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
  1680. if (err_msg) {
  1681. lua_pushstring (L, err_msg);
  1682. }
  1683. else {
  1684. lua_pushnil (L);
  1685. }
  1686. if (data) {
  1687. lua_pushlstring (L, data, datalen);
  1688. }
  1689. else {
  1690. lua_pushnil (L);
  1691. }
  1692. if (lua_pcall (L, 2, 0, err_idx) != 0) {
  1693. tb = lua_touserdata (L, -1);
  1694. msg_err ("call to subprocess callback script failed: %v", tb);
  1695. lua_pop (L, 1);
  1696. }
  1697. lua_pop (L, 1); /* Error function */
  1698. }
  1699. static gboolean
  1700. rspamd_lua_cld_handler (struct rspamd_worker_signal_handler *sigh, void *ud)
  1701. {
  1702. struct rspamd_lua_process_cbdata *cbdata = ud;
  1703. struct rspamd_srv_command srv_cmd;
  1704. lua_State *L;
  1705. pid_t died;
  1706. gint res = 0;
  1707. /* Are we called by a correct children ? */
  1708. died = waitpid (cbdata->cpid, &res, WNOHANG);
  1709. if (died <= 0) {
  1710. /* Wait more */
  1711. return TRUE;
  1712. }
  1713. L = cbdata->L;
  1714. msg_info ("handled SIGCHLD from %p", cbdata->cpid);
  1715. if (!cbdata->replied) {
  1716. /* We still need to call on_complete callback */
  1717. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1718. "Worker has died without reply", NULL, 0);
  1719. event_del (&cbdata->ev);
  1720. }
  1721. /* Free structures */
  1722. close (cbdata->sp[0]);
  1723. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
  1724. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
  1725. g_string_free (cbdata->io_buf, TRUE);
  1726. if (cbdata->out_buf) {
  1727. g_string_free (cbdata->out_buf, TRUE);
  1728. }
  1729. /* Notify main */
  1730. memset (&srv_cmd, 0, sizeof (srv_cmd));
  1731. srv_cmd.type = RSPAMD_SRV_ON_FORK;
  1732. srv_cmd.cmd.on_fork.state = child_dead;
  1733. srv_cmd.cmd.on_fork.cpid = cbdata->cpid;
  1734. srv_cmd.cmd.on_fork.ppid = getpid ();
  1735. rspamd_srv_send_command (cbdata->wrk, cbdata->ev_base, &srv_cmd, -1,
  1736. NULL, NULL);
  1737. g_free (cbdata);
  1738. /* We are done with this SIGCHLD */
  1739. return FALSE;
  1740. }
  1741. static void
  1742. rspamd_lua_subprocess_io (gint fd, short what, gpointer ud)
  1743. {
  1744. struct rspamd_lua_process_cbdata *cbdata = ud;
  1745. gssize r;
  1746. if (cbdata->sz == (guint64)-1) {
  1747. guint64 sz;
  1748. /* We read size of reply + flags first */
  1749. r = read (cbdata->sp[0], cbdata->io_buf->str + cbdata->io_buf->len,
  1750. sizeof (guint64) - cbdata->io_buf->len);
  1751. if (r == 0) {
  1752. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1753. "Unexpected EOF", NULL, 0);
  1754. event_del (&cbdata->ev);
  1755. cbdata->replied = TRUE;
  1756. kill (cbdata->cpid, SIGTERM);
  1757. return;
  1758. }
  1759. else if (r == -1) {
  1760. if (errno == EAGAIN || errno == EINTR) {
  1761. return;
  1762. }
  1763. else {
  1764. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1765. strerror (errno), NULL, 0);
  1766. event_del (&cbdata->ev);
  1767. cbdata->replied = TRUE;
  1768. kill (cbdata->cpid, SIGTERM);
  1769. return;
  1770. }
  1771. }
  1772. cbdata->io_buf->len += r;
  1773. if (cbdata->io_buf->len == sizeof (guint64)) {
  1774. memcpy ((guchar *)&sz, cbdata->io_buf->str, sizeof (sz));
  1775. if (sz & (1ULL << 63)) {
  1776. cbdata->is_error = TRUE;
  1777. sz &= ~(1ULL << 63);
  1778. }
  1779. cbdata->io_buf->len = 0;
  1780. cbdata->sz = sz;
  1781. g_string_set_size (cbdata->io_buf, sz + 1);
  1782. cbdata->io_buf->len = 0;
  1783. }
  1784. }
  1785. else {
  1786. /* Read data */
  1787. r = read (cbdata->sp[0], cbdata->io_buf->str + cbdata->io_buf->len,
  1788. cbdata->sz - cbdata->io_buf->len);
  1789. if (r == 0) {
  1790. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1791. "Unexpected EOF", NULL, 0);
  1792. event_del (&cbdata->ev);
  1793. cbdata->replied = TRUE;
  1794. kill (cbdata->cpid, SIGTERM);
  1795. return;
  1796. }
  1797. else if (r == -1) {
  1798. if (errno == EAGAIN || errno == EINTR) {
  1799. return;
  1800. }
  1801. else {
  1802. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1803. strerror (errno), NULL, 0);
  1804. event_del (&cbdata->ev);
  1805. cbdata->replied = TRUE;
  1806. kill (cbdata->cpid, SIGTERM);
  1807. return;
  1808. }
  1809. }
  1810. cbdata->io_buf->len += r;
  1811. if (cbdata->io_buf->len == cbdata->sz) {
  1812. gchar rep[4];
  1813. /* Finished reading data */
  1814. if (cbdata->is_error) {
  1815. cbdata->io_buf->str[cbdata->io_buf->len] = '\0';
  1816. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1817. cbdata->io_buf->str, NULL, 0);
  1818. }
  1819. else {
  1820. rspamd_lua_call_on_complete (cbdata->L, cbdata,
  1821. NULL, cbdata->io_buf->str, cbdata->io_buf->len);
  1822. }
  1823. event_del (&cbdata->ev);
  1824. cbdata->replied = TRUE;
  1825. /* Write reply to the child */
  1826. rspamd_socket_blocking (cbdata->sp[0]);
  1827. memset (rep, 0, sizeof (rep));
  1828. (void)write (cbdata->sp[0], rep, sizeof (rep));
  1829. }
  1830. }
  1831. }
  1832. static gint
  1833. lua_worker_spawn_process (lua_State *L)
  1834. {
  1835. struct rspamd_worker *w = lua_check_worker (L, 1);
  1836. struct rspamd_lua_process_cbdata *cbdata;
  1837. struct rspamd_abstract_worker_ctx *actx;
  1838. struct rspamd_srv_command srv_cmd;
  1839. const gchar *cmdline = NULL, *input = NULL;
  1840. gsize inputlen = 0;
  1841. pid_t pid;
  1842. GError *err = NULL;
  1843. gint func_cbref, cb_cbref;
  1844. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  1845. "func=F;exec=S;stdin=V;*on_complete=F", &func_cbref,
  1846. &cmdline, &inputlen, &input, &cb_cbref)) {
  1847. msg_err ("cannot get parameters list: %e", err);
  1848. if (err) {
  1849. g_error_free (err);
  1850. }
  1851. return 0;
  1852. }
  1853. cbdata = g_malloc0 (sizeof (*cbdata));
  1854. cbdata->cb_cbref = cb_cbref;
  1855. cbdata->func_cbref = func_cbref;
  1856. if (input) {
  1857. cbdata->out_buf = g_string_new_len (input, inputlen);
  1858. cbdata->out_pos = 0;
  1859. }
  1860. if (rspamd_socketpair (cbdata->sp, TRUE) == -1) {
  1861. msg_err ("cannot spawn socketpair: %s", strerror (errno));
  1862. g_free (cbdata);
  1863. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
  1864. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
  1865. return 0;
  1866. }
  1867. actx = w->ctx;
  1868. cbdata->wrk = w;
  1869. cbdata->L = L;
  1870. cbdata->ev_base = actx->ev_base;
  1871. cbdata->sz = (guint64)-1;
  1872. pid = fork ();
  1873. if (pid == -1) {
  1874. msg_err ("cannot spawn process: %s", strerror (errno));
  1875. close (cbdata->sp[0]);
  1876. close (cbdata->sp[1]);
  1877. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
  1878. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
  1879. g_free (cbdata);
  1880. return 0;
  1881. }
  1882. else if (pid == 0) {
  1883. /* Child */
  1884. gint rc;
  1885. gchar inbuf[4];
  1886. rspamd_log_update_pid (w->cf->type, w->srv->logger);
  1887. rc = ottery_init (w->srv->cfg->libs_ctx->ottery_cfg);
  1888. if (rc != OTTERY_ERR_NONE) {
  1889. msg_err ("cannot initialize PRNG: %d", rc);
  1890. abort ();
  1891. }
  1892. rspamd_random_seed_fast ();
  1893. #ifdef HAVE_EVUTIL_RNG_INIT
  1894. evutil_secure_rng_init ();
  1895. #endif
  1896. close (cbdata->sp[0]);
  1897. /* Here we assume that we can block on writing results */
  1898. rspamd_socket_blocking (cbdata->sp[1]);
  1899. event_reinit (cbdata->ev_base);
  1900. g_hash_table_remove_all (w->signal_events);
  1901. rspamd_worker_unblock_signals ();
  1902. rspamd_lua_execute_lua_subprocess (L, cbdata);
  1903. /* Wait for parent to reply and exit */
  1904. rc = read (cbdata->sp[1], inbuf, sizeof (inbuf));
  1905. if (memcmp (inbuf, "\0\0\0\0", 4) == 0) {
  1906. exit (EXIT_SUCCESS);
  1907. }
  1908. else {
  1909. msg_err ("got invalid reply from parent");
  1910. exit (EXIT_FAILURE);
  1911. }
  1912. }
  1913. cbdata->cpid = pid;
  1914. cbdata->io_buf = g_string_sized_new (8);
  1915. /* Notify main */
  1916. memset (&srv_cmd, 0, sizeof (srv_cmd));
  1917. srv_cmd.type = RSPAMD_SRV_ON_FORK;
  1918. srv_cmd.cmd.on_fork.state = child_create;
  1919. srv_cmd.cmd.on_fork.cpid = pid;
  1920. srv_cmd.cmd.on_fork.ppid = getpid ();
  1921. rspamd_srv_send_command (w, cbdata->ev_base, &srv_cmd, -1, NULL, NULL);
  1922. close (cbdata->sp[1]);
  1923. rspamd_socket_nonblocking (cbdata->sp[0]);
  1924. /* Parent */
  1925. rspamd_worker_set_signal_handler (SIGCHLD, w, cbdata->ev_base,
  1926. rspamd_lua_cld_handler,
  1927. cbdata);
  1928. /* Add result pipe waiting */
  1929. event_set (&cbdata->ev, cbdata->sp[0], EV_READ | EV_PERSIST,
  1930. rspamd_lua_subprocess_io, cbdata);
  1931. event_base_set (cbdata->ev_base, &cbdata->ev);
  1932. /* TODO: maybe add timeout? */
  1933. event_add (&cbdata->ev, NULL);
  1934. return 0;
  1935. }
  1936. struct rspamd_lua_ref_cbdata {
  1937. lua_State *L;
  1938. gint cbref;
  1939. };
  1940. static void
  1941. rspamd_lua_ref_dtor (gpointer p)
  1942. {
  1943. struct rspamd_lua_ref_cbdata *cbdata = p;
  1944. luaL_unref (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref);
  1945. }
  1946. void
  1947. rspamd_lua_add_ref_dtor (lua_State *L, rspamd_mempool_t *pool,
  1948. gint ref)
  1949. {
  1950. struct rspamd_lua_ref_cbdata *cbdata;
  1951. if (ref != -1) {
  1952. cbdata = rspamd_mempool_alloc (pool, sizeof (*cbdata));
  1953. cbdata->cbref = ref;
  1954. cbdata->L = L;
  1955. rspamd_mempool_add_destructor (pool, rspamd_lua_ref_dtor, cbdata);
  1956. }
  1957. }
  1958. gboolean
  1959. rspamd_lua_require_function (lua_State *L, const gchar *modname,
  1960. const gchar *funcname)
  1961. {
  1962. gint table_pos;
  1963. lua_getglobal (L, "require");
  1964. if (lua_isnil (L, -1)) {
  1965. lua_pop (L, 1);
  1966. return FALSE;
  1967. }
  1968. lua_pushstring (L, modname);
  1969. /* Now try to call */
  1970. if (lua_pcall (L, 1, 1, 0) != 0) {
  1971. lua_pop (L, 1);
  1972. return FALSE;
  1973. }
  1974. /* Now we should have a table with results */
  1975. if (!lua_istable (L, -1)) {
  1976. lua_pop (L, 1);
  1977. return FALSE;
  1978. }
  1979. table_pos = lua_gettop (L);
  1980. lua_pushstring (L, funcname);
  1981. lua_gettable (L, -2);
  1982. if (lua_type (L, -1) == LUA_TFUNCTION) {
  1983. /* Remove table, preserve just a function */
  1984. lua_remove (L, table_pos);
  1985. return TRUE;
  1986. }
  1987. lua_pop (L, 2);
  1988. return FALSE;
  1989. }
  1990. gboolean
  1991. rspamd_lua_try_load_redis (lua_State *L, const ucl_object_t *obj,
  1992. struct rspamd_config *cfg, gint *ref_id)
  1993. {
  1994. gint res_pos, err_idx;
  1995. struct rspamd_config **pcfg;
  1996. /* Create results table */
  1997. lua_createtable (L, 0, 0);
  1998. res_pos = lua_gettop (L);
  1999. lua_pushcfunction (L, &rspamd_lua_traceback);
  2000. err_idx = lua_gettop (L);
  2001. /* Obtain function */
  2002. if (!rspamd_lua_require_function (L, "lua_redis", "try_load_redis_servers")) {
  2003. msg_err_config ("cannot require lua_redis");
  2004. lua_pop (L, 2);
  2005. return FALSE;
  2006. }
  2007. /* Function arguments */
  2008. ucl_object_push_lua (L, obj, false);
  2009. pcfg = lua_newuserdata (L, sizeof (*pcfg));
  2010. rspamd_lua_setclass (L, "rspamd{config}", -1);
  2011. *pcfg = cfg;
  2012. lua_pushvalue (L, res_pos);
  2013. if (lua_pcall (L, 3, 1, err_idx) != 0) {
  2014. GString *tb;
  2015. tb = lua_touserdata (L, -1);
  2016. msg_err_config ("cannot call lua try_load_redis_servers script: %s", tb->str);
  2017. g_string_free (tb, TRUE);
  2018. lua_settop (L, 0);
  2019. return FALSE;
  2020. }
  2021. if (lua_toboolean (L, -1)) {
  2022. if (ref_id) {
  2023. /* Ref table */
  2024. lua_pushvalue (L, res_pos);
  2025. *ref_id = luaL_ref (L, LUA_REGISTRYINDEX);
  2026. lua_settop (L, 0);
  2027. }
  2028. else {
  2029. /* Leave it on the stack */
  2030. lua_settop (L, res_pos);
  2031. }
  2032. return TRUE;
  2033. }
  2034. else {
  2035. lua_settop (L, 0);
  2036. }
  2037. return FALSE;
  2038. }
  2039. void
  2040. rspamd_lua_push_full_word (lua_State *L, rspamd_stat_token_t *w)
  2041. {
  2042. gint fl_cnt;
  2043. lua_createtable (L, 4, 0);
  2044. if (w->stemmed.len > 0) {
  2045. lua_pushlstring (L, w->stemmed.begin, w->stemmed.len);
  2046. lua_rawseti (L, -2, 1);
  2047. }
  2048. else {
  2049. lua_pushstring (L, "");
  2050. lua_rawseti (L, -2, 1);
  2051. }
  2052. if (w->normalized.len > 0) {
  2053. lua_pushlstring (L, w->normalized.begin, w->normalized.len);
  2054. lua_rawseti (L, -2, 2);
  2055. }
  2056. else {
  2057. lua_pushstring (L, "");
  2058. lua_rawseti (L, -2, 2);
  2059. }
  2060. if (w->original.len > 0) {
  2061. lua_pushlstring (L, w->original.begin, w->original.len);
  2062. lua_rawseti (L, -2, 3);
  2063. }
  2064. else {
  2065. lua_pushstring (L, "");
  2066. lua_rawseti (L, -2, 3);
  2067. }
  2068. /* Flags part */
  2069. fl_cnt = 1;
  2070. lua_createtable (L, 4, 0);
  2071. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_NORMALISED) {
  2072. lua_pushstring (L, "normalised");
  2073. lua_rawseti (L, -2, fl_cnt ++);
  2074. }
  2075. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_BROKEN_UNICODE) {
  2076. lua_pushstring (L, "broken_unicode");
  2077. lua_rawseti (L, -2, fl_cnt ++);
  2078. }
  2079. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_UTF) {
  2080. lua_pushstring (L, "utf");
  2081. lua_rawseti (L, -2, fl_cnt ++);
  2082. }
  2083. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_TEXT) {
  2084. lua_pushstring (L, "text");
  2085. lua_rawseti (L, -2, fl_cnt ++);
  2086. }
  2087. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_HEADER) {
  2088. lua_pushstring (L, "header");
  2089. lua_rawseti (L, -2, fl_cnt ++);
  2090. }
  2091. if (w->flags & (RSPAMD_STAT_TOKEN_FLAG_META|RSPAMD_STAT_TOKEN_FLAG_LUA_META)) {
  2092. lua_pushstring (L, "meta");
  2093. lua_rawseti (L, -2, fl_cnt ++);
  2094. }
  2095. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_STOP_WORD) {
  2096. lua_pushstring (L, "stop_word");
  2097. lua_rawseti (L, -2, fl_cnt ++);
  2098. }
  2099. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_INVISIBLE_SPACES) {
  2100. lua_pushstring (L, "invisible_spaces");
  2101. lua_rawseti (L, -2, fl_cnt ++);
  2102. }
  2103. if (w->flags & RSPAMD_STAT_TOKEN_FLAG_STEMMED) {
  2104. lua_pushstring (L, "stemmed");
  2105. lua_rawseti (L, -2, fl_cnt ++);
  2106. }
  2107. lua_rawseti (L, -2, 4);
  2108. }
  2109. gint
  2110. rspamd_lua_push_words (lua_State *L, GArray *words,
  2111. enum rspamd_lua_words_type how)
  2112. {
  2113. rspamd_stat_token_t *w;
  2114. guint i, cnt;
  2115. lua_createtable (L, words->len, 0);
  2116. for (i = 0, cnt = 1; i < words->len; i ++) {
  2117. w = &g_array_index (words, rspamd_stat_token_t, i);
  2118. switch (how) {
  2119. case RSPAMD_LUA_WORDS_STEM:
  2120. if (w->stemmed.len > 0) {
  2121. lua_pushlstring (L, w->stemmed.begin, w->stemmed.len);
  2122. lua_rawseti (L, -2, cnt ++);
  2123. }
  2124. break;
  2125. case RSPAMD_LUA_WORDS_NORM:
  2126. if (w->normalized.len > 0) {
  2127. lua_pushlstring (L, w->normalized.begin, w->normalized.len);
  2128. lua_rawseti (L, -2, cnt ++);
  2129. }
  2130. break;
  2131. case RSPAMD_LUA_WORDS_RAW:
  2132. if (w->original.len > 0) {
  2133. lua_pushlstring (L, w->original.begin, w->original.len);
  2134. lua_rawseti (L, -2, cnt ++);
  2135. }
  2136. break;
  2137. case RSPAMD_LUA_WORDS_FULL:
  2138. rspamd_lua_push_full_word (L, w);
  2139. /* Push to the resulting vector */
  2140. lua_rawseti (L, -2, cnt ++);
  2141. break;
  2142. }
  2143. }
  2144. return 1;
  2145. }