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.

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