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_config.c 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. /*
  2. * Copyright (c) 2009-2012, Vsevolod Stakhov
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "lua_common.h"
  25. #include "expressions.h"
  26. #include "map.h"
  27. #include "message.h"
  28. #include "radix.h"
  29. #include "trie.h"
  30. #include "classifiers/classifiers.h"
  31. /* Config file methods */
  32. LUA_FUNCTION_DEF (config, get_module_opt);
  33. LUA_FUNCTION_DEF (config, get_all_opt);
  34. LUA_FUNCTION_DEF (config, get_mempool);
  35. LUA_FUNCTION_DEF (config, register_function);
  36. LUA_FUNCTION_DEF (config, add_radix_map);
  37. LUA_FUNCTION_DEF (config, add_hash_map);
  38. LUA_FUNCTION_DEF (config, add_kv_map);
  39. LUA_FUNCTION_DEF (config, add_map);
  40. LUA_FUNCTION_DEF (config, get_classifier);
  41. LUA_FUNCTION_DEF (config, register_symbol);
  42. LUA_FUNCTION_DEF (config, register_symbols);
  43. LUA_FUNCTION_DEF (config, register_virtual_symbol);
  44. LUA_FUNCTION_DEF (config, register_callback_symbol);
  45. LUA_FUNCTION_DEF (config, register_callback_symbol_priority);
  46. LUA_FUNCTION_DEF (config, register_pre_filter);
  47. LUA_FUNCTION_DEF (config, register_post_filter);
  48. LUA_FUNCTION_DEF (config, register_module_option);
  49. LUA_FUNCTION_DEF (config, get_api_version);
  50. LUA_FUNCTION_DEF (config, get_key);
  51. LUA_FUNCTION_DEF (config, newindex);
  52. static const struct luaL_reg configlib_m[] = {
  53. LUA_INTERFACE_DEF (config, get_module_opt),
  54. LUA_INTERFACE_DEF (config, get_mempool),
  55. LUA_INTERFACE_DEF (config, get_all_opt),
  56. LUA_INTERFACE_DEF (config, register_function),
  57. LUA_INTERFACE_DEF (config, add_radix_map),
  58. LUA_INTERFACE_DEF (config, add_hash_map),
  59. LUA_INTERFACE_DEF (config, add_kv_map),
  60. LUA_INTERFACE_DEF (config, add_map),
  61. LUA_INTERFACE_DEF (config, get_classifier),
  62. LUA_INTERFACE_DEF (config, register_symbol),
  63. LUA_INTERFACE_DEF (config, register_symbols),
  64. LUA_INTERFACE_DEF (config, register_virtual_symbol),
  65. LUA_INTERFACE_DEF (config, register_callback_symbol),
  66. LUA_INTERFACE_DEF (config, register_callback_symbol_priority),
  67. LUA_INTERFACE_DEF (config, register_module_option),
  68. LUA_INTERFACE_DEF (config, register_pre_filter),
  69. LUA_INTERFACE_DEF (config, register_post_filter),
  70. LUA_INTERFACE_DEF (config, get_api_version),
  71. LUA_INTERFACE_DEF (config, get_key),
  72. {"__tostring", rspamd_lua_class_tostring},
  73. {"__newindex", lua_config_newindex},
  74. {NULL, NULL}
  75. };
  76. /* Radix tree */
  77. LUA_FUNCTION_DEF (radix, get_key);
  78. static const struct luaL_reg radixlib_m[] = {
  79. LUA_INTERFACE_DEF (radix, get_key),
  80. {"__tostring", rspamd_lua_class_tostring},
  81. {NULL, NULL}
  82. };
  83. /* Hash table */
  84. LUA_FUNCTION_DEF (hash_table, get_key);
  85. static const struct luaL_reg hashlib_m[] = {
  86. LUA_INTERFACE_DEF (hash_table, get_key),
  87. {"__tostring", rspamd_lua_class_tostring},
  88. {NULL, NULL}
  89. };
  90. /* Suffix trie */
  91. LUA_FUNCTION_DEF (trie, create);
  92. LUA_FUNCTION_DEF (trie, add_pattern);
  93. LUA_FUNCTION_DEF (trie, search_text);
  94. LUA_FUNCTION_DEF (trie, search_task);
  95. static const struct luaL_reg trielib_m[] = {
  96. LUA_INTERFACE_DEF (trie, add_pattern),
  97. LUA_INTERFACE_DEF (trie, search_text),
  98. LUA_INTERFACE_DEF (trie, search_task),
  99. {"__tostring", rspamd_lua_class_tostring},
  100. {NULL, NULL}
  101. };
  102. static const struct luaL_reg trielib_f[] = {
  103. LUA_INTERFACE_DEF (trie, create),
  104. {NULL, NULL}
  105. };
  106. static struct rspamd_config *
  107. lua_check_config (lua_State * L)
  108. {
  109. void *ud = luaL_checkudata (L, 1, "rspamd{config}");
  110. luaL_argcheck (L, ud != NULL, 1, "'config' expected");
  111. return ud ? *((struct rspamd_config **)ud) : NULL;
  112. }
  113. static radix_tree_t *
  114. lua_check_radix (lua_State * L)
  115. {
  116. void *ud = luaL_checkudata (L, 1, "rspamd{radix}");
  117. luaL_argcheck (L, ud != NULL, 1, "'radix' expected");
  118. return ud ? **((radix_tree_t ***)ud) : NULL;
  119. }
  120. static GHashTable *
  121. lua_check_hash_table (lua_State * L)
  122. {
  123. void *ud = luaL_checkudata (L, 1, "rspamd{hash_table}");
  124. luaL_argcheck (L, ud != NULL, 1, "'hash_table' expected");
  125. return ud ? **((GHashTable ***)ud) : NULL;
  126. }
  127. static rspamd_trie_t *
  128. lua_check_trie (lua_State * L)
  129. {
  130. void *ud = luaL_checkudata (L, 1, "rspamd{trie}");
  131. luaL_argcheck (L, ud != NULL, 1, "'trie' expected");
  132. return ud ? *((rspamd_trie_t **)ud) : NULL;
  133. }
  134. /*** Config functions ***/
  135. static gint
  136. lua_config_get_api_version (lua_State *L)
  137. {
  138. lua_pushinteger (L, RSPAMD_LUA_API_VERSION);
  139. return 1;
  140. }
  141. static gint
  142. lua_config_get_module_opt (lua_State * L)
  143. {
  144. struct rspamd_config *cfg = lua_check_config (L);
  145. const gchar *mname, *optname;
  146. const ucl_object_t *obj;
  147. if (cfg) {
  148. mname = luaL_checkstring (L, 2);
  149. optname = luaL_checkstring (L, 3);
  150. if (mname && optname) {
  151. obj = rspamd_config_get_module_opt (cfg, mname, optname);
  152. if (obj) {
  153. return ucl_object_push_lua (L, obj, TRUE);
  154. }
  155. }
  156. }
  157. lua_pushnil (L);
  158. return 1;
  159. }
  160. static int
  161. lua_config_get_mempool (lua_State * L)
  162. {
  163. rspamd_mempool_t **ppool;
  164. struct rspamd_config *cfg = lua_check_config (L);
  165. if (cfg != NULL) {
  166. ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *));
  167. rspamd_lua_setclass (L, "rspamd{mempool}", -1);
  168. *ppool = cfg->cfg_pool;
  169. }
  170. return 1;
  171. }
  172. static gint
  173. lua_config_get_all_opt (lua_State * L)
  174. {
  175. struct rspamd_config *cfg = lua_check_config (L);
  176. const gchar *mname;
  177. const ucl_object_t *obj;
  178. if (cfg) {
  179. mname = luaL_checkstring (L, 2);
  180. if (mname) {
  181. obj = ucl_obj_get_key (cfg->rcl_obj, mname);
  182. if (obj != NULL) {
  183. return ucl_object_push_lua (L, obj, TRUE);
  184. }
  185. }
  186. }
  187. lua_pushnil (L);
  188. return 1;
  189. }
  190. static gint
  191. lua_config_get_classifier (lua_State * L)
  192. {
  193. struct rspamd_config *cfg = lua_check_config (L);
  194. struct rspamd_classifier_config *clc = NULL, **pclc = NULL;
  195. const gchar *name;
  196. GList *cur;
  197. if (cfg) {
  198. name = luaL_checkstring (L, 2);
  199. cur = g_list_first (cfg->classifiers);
  200. while (cur) {
  201. clc = cur->data;
  202. if (g_ascii_strcasecmp (clc->classifier->name, name) == 0) {
  203. pclc = &clc;
  204. break;
  205. }
  206. cur = g_list_next (cur);
  207. }
  208. if (pclc) {
  209. pclc = lua_newuserdata (L,
  210. sizeof (struct rspamd_classifier_config *));
  211. rspamd_lua_setclass (L, "rspamd{classifier}", -1);
  212. *pclc = clc;
  213. return 1;
  214. }
  215. }
  216. lua_pushnil (L);
  217. return 1;
  218. }
  219. struct lua_callback_data {
  220. union {
  221. gchar *name;
  222. gint ref;
  223. } callback;
  224. gboolean cb_is_ref;
  225. lua_State *L;
  226. gchar *symbol;
  227. };
  228. /*
  229. * Unref symbol if it is local reference
  230. */
  231. static void
  232. lua_destroy_cfg_symbol (gpointer ud)
  233. {
  234. struct lua_callback_data *cd = ud;
  235. /* Unref callback */
  236. if (cd->cb_is_ref) {
  237. luaL_unref (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
  238. }
  239. }
  240. static gboolean
  241. lua_config_function_callback (struct rspamd_task *task,
  242. GList *args,
  243. void *user_data)
  244. {
  245. struct lua_callback_data *cd = user_data;
  246. struct rspamd_task **ptask;
  247. gint i = 1;
  248. struct expression_argument *arg;
  249. GList *cur;
  250. gboolean res = FALSE;
  251. if (cd->cb_is_ref) {
  252. lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
  253. }
  254. else {
  255. lua_getglobal (cd->L, cd->callback.name);
  256. }
  257. ptask = lua_newuserdata (cd->L, sizeof (struct rspamd_task *));
  258. rspamd_lua_setclass (cd->L, "rspamd{task}", -1);
  259. *ptask = task;
  260. /* Now push all arguments */
  261. cur = args;
  262. while (cur) {
  263. arg = get_function_arg (cur->data, task, TRUE);
  264. lua_pushstring (cd->L, (const gchar *)arg->data);
  265. cur = g_list_next (cur);
  266. i++;
  267. }
  268. if (lua_pcall (cd->L, i, 1, 0) != 0) {
  269. msg_info ("error processing symbol %s: call to %s failed: %s",
  270. cd->symbol,
  271. cd->cb_is_ref ? "local function" :
  272. cd->callback.name,
  273. lua_tostring (cd->L, -1));
  274. }
  275. else {
  276. if (lua_isboolean (cd->L, 1)) {
  277. res = lua_toboolean (cd->L, 1);
  278. }
  279. lua_pop (cd->L, 1);
  280. }
  281. return res;
  282. }
  283. static gint
  284. lua_config_register_function (lua_State *L)
  285. {
  286. struct rspamd_config *cfg = lua_check_config (L);
  287. gchar *name;
  288. struct lua_callback_data *cd;
  289. if (cfg) {
  290. name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
  291. cd =
  292. rspamd_mempool_alloc (cfg->cfg_pool,
  293. sizeof (struct lua_callback_data));
  294. if (lua_type (L, 3) == LUA_TSTRING) {
  295. cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool,
  296. luaL_checkstring (L, 3));
  297. cd->cb_is_ref = FALSE;
  298. }
  299. else {
  300. lua_pushvalue (L, 3);
  301. /* Get a reference */
  302. cd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX);
  303. cd->cb_is_ref = TRUE;
  304. }
  305. if (name) {
  306. cd->L = L;
  307. cd->symbol = name;
  308. register_expression_function (name, lua_config_function_callback,
  309. cd);
  310. }
  311. rspamd_mempool_add_destructor (cfg->cfg_pool,
  312. (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
  313. cd);
  314. }
  315. return 1;
  316. }
  317. static gint
  318. lua_config_register_module_option (lua_State *L)
  319. {
  320. return 0;
  321. }
  322. void
  323. rspamd_lua_call_post_filters (struct rspamd_task *task)
  324. {
  325. struct lua_callback_data *cd;
  326. struct rspamd_task **ptask;
  327. GList *cur;
  328. cur = task->cfg->post_filters;
  329. while (cur) {
  330. cd = cur->data;
  331. if (cd->cb_is_ref) {
  332. lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
  333. }
  334. else {
  335. lua_getglobal (cd->L, cd->callback.name);
  336. }
  337. ptask = lua_newuserdata (cd->L, sizeof (struct rspamd_task *));
  338. rspamd_lua_setclass (cd->L, "rspamd{task}", -1);
  339. *ptask = task;
  340. if (lua_pcall (cd->L, 1, 0, 0) != 0) {
  341. msg_info ("call to %s failed: %s",
  342. cd->cb_is_ref ? "local function" :
  343. cd->callback.name,
  344. lua_tostring (cd->L, -1));
  345. }
  346. cur = g_list_next (cur);
  347. }
  348. }
  349. static gint
  350. lua_config_register_post_filter (lua_State *L)
  351. {
  352. struct rspamd_config *cfg = lua_check_config (L);
  353. struct lua_callback_data *cd;
  354. if (cfg) {
  355. cd =
  356. rspamd_mempool_alloc (cfg->cfg_pool,
  357. sizeof (struct lua_callback_data));
  358. if (lua_type (L, 2) == LUA_TSTRING) {
  359. cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool,
  360. luaL_checkstring (L, 2));
  361. cd->cb_is_ref = FALSE;
  362. }
  363. else {
  364. lua_pushvalue (L, 2);
  365. /* Get a reference */
  366. cd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX);
  367. cd->cb_is_ref = TRUE;
  368. }
  369. cd->L = L;
  370. cfg->post_filters = g_list_prepend (cfg->post_filters, cd);
  371. rspamd_mempool_add_destructor (cfg->cfg_pool,
  372. (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
  373. cd);
  374. }
  375. return 1;
  376. }
  377. void
  378. rspamd_lua_call_pre_filters (struct rspamd_task *task)
  379. {
  380. struct lua_callback_data *cd;
  381. struct rspamd_task **ptask;
  382. GList *cur;
  383. cur = task->cfg->pre_filters;
  384. while (cur) {
  385. cd = cur->data;
  386. if (cd->cb_is_ref) {
  387. lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
  388. }
  389. else {
  390. lua_getglobal (cd->L, cd->callback.name);
  391. }
  392. ptask = lua_newuserdata (cd->L, sizeof (struct rspamd_task *));
  393. rspamd_lua_setclass (cd->L, "rspamd{task}", -1);
  394. *ptask = task;
  395. if (lua_pcall (cd->L, 1, 0, 0) != 0) {
  396. msg_info ("call to %s failed: %s",
  397. cd->cb_is_ref ? "local function" :
  398. cd->callback.name,
  399. lua_tostring (cd->L, -1));
  400. }
  401. cur = g_list_next (cur);
  402. }
  403. }
  404. static gint
  405. lua_config_register_pre_filter (lua_State *L)
  406. {
  407. struct rspamd_config *cfg = lua_check_config (L);
  408. struct lua_callback_data *cd;
  409. if (cfg) {
  410. cd =
  411. rspamd_mempool_alloc (cfg->cfg_pool,
  412. sizeof (struct lua_callback_data));
  413. if (lua_type (L, 2) == LUA_TSTRING) {
  414. cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool,
  415. luaL_checkstring (L, 2));
  416. cd->cb_is_ref = FALSE;
  417. }
  418. else {
  419. lua_pushvalue (L, 2);
  420. /* Get a reference */
  421. cd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX);
  422. cd->cb_is_ref = TRUE;
  423. }
  424. cd->L = L;
  425. cfg->pre_filters = g_list_prepend (cfg->pre_filters, cd);
  426. rspamd_mempool_add_destructor (cfg->cfg_pool,
  427. (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
  428. cd);
  429. }
  430. return 1;
  431. }
  432. static gint
  433. lua_config_add_radix_map (lua_State *L)
  434. {
  435. struct rspamd_config *cfg = lua_check_config (L);
  436. const gchar *map_line, *description;
  437. radix_tree_t **r, ***ud;
  438. if (cfg) {
  439. map_line = luaL_checkstring (L, 2);
  440. description = lua_tostring (L, 3);
  441. r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (radix_tree_t *));
  442. *r = radix_tree_create ();
  443. if (!add_map (cfg, map_line, description, read_radix_list,
  444. fin_radix_list, (void **)r)) {
  445. msg_warn ("invalid radix map %s", map_line);
  446. radix_tree_free (*r);
  447. lua_pushnil (L);
  448. return 1;
  449. }
  450. ud = lua_newuserdata (L, sizeof (radix_tree_t *));
  451. *ud = r;
  452. rspamd_lua_setclass (L, "rspamd{radix}", -1);
  453. return 1;
  454. }
  455. lua_pushnil (L);
  456. return 1;
  457. }
  458. static gint
  459. lua_config_add_hash_map (lua_State *L)
  460. {
  461. struct rspamd_config *cfg = lua_check_config (L);
  462. const gchar *map_line, *description;
  463. GHashTable **r, ***ud;
  464. if (cfg) {
  465. map_line = luaL_checkstring (L, 2);
  466. description = lua_tostring (L, 3);
  467. r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (GHashTable *));
  468. *r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
  469. if (!add_map (cfg, map_line, description, read_host_list, fin_host_list,
  470. (void **)r)) {
  471. msg_warn ("invalid hash map %s", map_line);
  472. g_hash_table_destroy (*r);
  473. lua_pushnil (L);
  474. return 1;
  475. }
  476. rspamd_mempool_add_destructor (cfg->cfg_pool,
  477. (rspamd_mempool_destruct_t)g_hash_table_destroy,
  478. *r);
  479. ud = lua_newuserdata (L, sizeof (GHashTable *));
  480. *ud = r;
  481. rspamd_lua_setclass (L, "rspamd{hash_table}", -1);
  482. return 1;
  483. }
  484. lua_pushnil (L);
  485. return 1;
  486. }
  487. static gint
  488. lua_config_add_kv_map (lua_State *L)
  489. {
  490. struct rspamd_config *cfg = lua_check_config (L);
  491. const gchar *map_line, *description;
  492. GHashTable **r, ***ud;
  493. if (cfg) {
  494. map_line = luaL_checkstring (L, 2);
  495. description = lua_tostring (L, 3);
  496. r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (GHashTable *));
  497. *r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
  498. if (!add_map (cfg, map_line, description, read_kv_list, fin_kv_list,
  499. (void **)r)) {
  500. msg_warn ("invalid hash map %s", map_line);
  501. g_hash_table_destroy (*r);
  502. lua_pushnil (L);
  503. return 1;
  504. }
  505. rspamd_mempool_add_destructor (cfg->cfg_pool,
  506. (rspamd_mempool_destruct_t)g_hash_table_destroy,
  507. *r);
  508. ud = lua_newuserdata (L, sizeof (GHashTable *));
  509. *ud = r;
  510. rspamd_lua_setclass (L, "rspamd{hash_table}", -1);
  511. return 1;
  512. }
  513. lua_pushnil (L);
  514. return 1;
  515. }
  516. static gint
  517. lua_config_get_key (lua_State *L)
  518. {
  519. struct rspamd_config *cfg = lua_check_config (L);
  520. const gchar *name;
  521. size_t namelen;
  522. const ucl_object_t *val;
  523. name = luaL_checklstring(L, 2, &namelen);
  524. if (name && cfg) {
  525. val = ucl_object_find_keyl(cfg->rcl_obj, name, namelen);
  526. if (val != NULL) {
  527. ucl_object_push_lua (L, val, val->type != UCL_ARRAY);
  528. }
  529. else {
  530. lua_pushnil (L);
  531. }
  532. }
  533. else {
  534. lua_pushnil (L);
  535. }
  536. return 1;
  537. }
  538. static void
  539. lua_metric_symbol_callback (struct rspamd_task *task, gpointer ud)
  540. {
  541. struct lua_callback_data *cd = ud;
  542. struct rspamd_task **ptask;
  543. gint level = lua_gettop (cd->L), nresults;
  544. if (cd->cb_is_ref) {
  545. lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
  546. }
  547. else {
  548. lua_getglobal (cd->L, cd->callback.name);
  549. }
  550. ptask = lua_newuserdata (cd->L, sizeof (struct rspamd_task *));
  551. rspamd_lua_setclass (cd->L, "rspamd{task}", -1);
  552. *ptask = task;
  553. if (lua_pcall (cd->L, 1, LUA_MULTRET, 0) != 0) {
  554. msg_info ("call to (%s)%s failed: %s", cd->symbol,
  555. cd->cb_is_ref ? "local function" : cd->callback.name,
  556. lua_tostring (cd->L, -1));
  557. }
  558. nresults = lua_gettop (cd->L) - level;
  559. if (nresults >= 1) {
  560. /* Function returned boolean, so maybe we need to insert result? */
  561. gboolean res;
  562. GList *opts = NULL;
  563. gint i;
  564. gdouble flag = 1.0;
  565. if (lua_type (cd->L, level + 1) == LUA_TBOOLEAN) {
  566. res = lua_toboolean (cd->L, level + 1);
  567. if (res) {
  568. gint first_opt = 2;
  569. if (lua_type (cd->L, level + 2) == LUA_TNUMBER) {
  570. flag = lua_tonumber (cd->L, level + 2);
  571. /* Shift opt index */
  572. first_opt = 3;
  573. }
  574. for (i = lua_gettop (cd->L); i >= level + first_opt; i --) {
  575. if (lua_type (cd->L, i) == LUA_TSTRING) {
  576. const char *opt = lua_tostring (cd->L, i);
  577. opts = g_list_prepend (opts,
  578. rspamd_mempool_strdup (task->task_pool, opt));
  579. }
  580. }
  581. insert_result (task, cd->symbol, flag, opts);
  582. }
  583. }
  584. lua_pop (cd->L, nresults);
  585. }
  586. }
  587. static void
  588. rspamd_register_symbol_fromlua (lua_State *L,
  589. struct rspamd_config *cfg,
  590. const gchar *name,
  591. gint ref,
  592. gdouble weight,
  593. gint priority,
  594. enum rspamd_symbol_type type)
  595. {
  596. struct lua_callback_data *cd;
  597. cd = rspamd_mempool_alloc0 (cfg->cfg_pool,
  598. sizeof (struct lua_callback_data));
  599. cd->cb_is_ref = TRUE;
  600. cd->callback.ref = ref;
  601. cd->L = L;
  602. if (name) {
  603. cd->symbol = rspamd_mempool_strdup (cfg->cfg_pool, name);
  604. }
  605. register_symbol_common (&cfg->cache,
  606. name,
  607. weight,
  608. priority,
  609. lua_metric_symbol_callback,
  610. cd,
  611. type);
  612. rspamd_mempool_add_destructor (cfg->cfg_pool,
  613. (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
  614. cd);
  615. }
  616. static gint
  617. lua_config_register_symbol (lua_State * L)
  618. {
  619. struct rspamd_config *cfg = lua_check_config (L);
  620. gchar *name;
  621. double weight;
  622. if (cfg) {
  623. name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
  624. weight = luaL_checknumber (L, 3);
  625. if (lua_type (L, 4) == LUA_TSTRING) {
  626. lua_getglobal (L, luaL_checkstring (L, 4));
  627. }
  628. else {
  629. lua_pushvalue (L, 4);
  630. }
  631. if (name) {
  632. rspamd_register_symbol_fromlua (L,
  633. cfg,
  634. name,
  635. luaL_ref (L, LUA_REGISTRYINDEX),
  636. weight,
  637. 0,
  638. SYMBOL_TYPE_NORMAL);
  639. }
  640. }
  641. return 0;
  642. }
  643. static gint
  644. lua_config_register_symbols (lua_State *L)
  645. {
  646. struct rspamd_config *cfg = lua_check_config (L);
  647. gint i, top, idx;
  648. gchar *sym;
  649. gdouble weight = 1.0;
  650. if (lua_gettop (L) < 3) {
  651. msg_err ("not enough arguments to register a function");
  652. return 0;
  653. }
  654. if (cfg) {
  655. if (lua_type (L, 2) == LUA_TSTRING) {
  656. lua_getglobal (L, luaL_checkstring (L, 2));
  657. }
  658. else {
  659. lua_pushvalue (L, 2);
  660. }
  661. idx = luaL_ref (L, LUA_REGISTRYINDEX);
  662. if (lua_type (L, 3) == LUA_TNUMBER) {
  663. weight = lua_tonumber (L, 3);
  664. top = 4;
  665. }
  666. else {
  667. top = 3;
  668. }
  669. sym = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, top));
  670. rspamd_register_symbol_fromlua (L,
  671. cfg,
  672. sym,
  673. idx,
  674. weight,
  675. 0,
  676. SYMBOL_TYPE_NORMAL);
  677. for (i = top; i < lua_gettop (L); i++) {
  678. sym =
  679. rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L,
  680. i + 1));
  681. register_virtual_symbol (&cfg->cache, sym, weight);
  682. }
  683. }
  684. return 0;
  685. }
  686. static gint
  687. lua_config_register_virtual_symbol (lua_State * L)
  688. {
  689. struct rspamd_config *cfg = lua_check_config (L);
  690. gchar *name;
  691. double weight;
  692. if (cfg) {
  693. name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
  694. weight = luaL_checknumber (L, 3);
  695. if (name) {
  696. register_virtual_symbol (&cfg->cache, name, weight);
  697. }
  698. }
  699. return 0;
  700. }
  701. static gint
  702. lua_config_register_callback_symbol (lua_State * L)
  703. {
  704. struct rspamd_config *cfg = lua_check_config (L);
  705. gchar *name;
  706. double weight;
  707. if (cfg) {
  708. name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
  709. weight = luaL_checknumber (L, 3);
  710. if (lua_type (L, 4) == LUA_TSTRING) {
  711. lua_getglobal (L, luaL_checkstring (L, 4));
  712. }
  713. else {
  714. lua_pushvalue (L, 4);
  715. }
  716. if (name) {
  717. rspamd_register_symbol_fromlua (L,
  718. cfg,
  719. name,
  720. luaL_ref (L, LUA_REGISTRYINDEX),
  721. weight,
  722. 0,
  723. SYMBOL_TYPE_CALLBACK);
  724. }
  725. }
  726. return 0;
  727. }
  728. static gint
  729. lua_config_register_callback_symbol_priority (lua_State * L)
  730. {
  731. struct rspamd_config *cfg = lua_check_config (L);
  732. gchar *name;
  733. double weight;
  734. gint priority;
  735. if (cfg) {
  736. name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
  737. weight = luaL_checknumber (L, 3);
  738. priority = luaL_checknumber (L, 4);
  739. if (lua_type (L, 5) == LUA_TSTRING) {
  740. lua_getglobal (L, luaL_checkstring (L, 5));
  741. }
  742. else {
  743. lua_pushvalue (L, 5);
  744. }
  745. if (name) {
  746. rspamd_register_symbol_fromlua (L,
  747. cfg,
  748. name,
  749. luaL_ref (L, LUA_REGISTRYINDEX),
  750. weight,
  751. priority,
  752. SYMBOL_TYPE_CALLBACK);
  753. }
  754. }
  755. return 0;
  756. }
  757. static gint
  758. lua_config_newindex (lua_State *L)
  759. {
  760. struct rspamd_config *cfg = lua_check_config (L);
  761. const gchar *name;
  762. name = luaL_checkstring (L, 2);
  763. if (name != NULL && lua_gettop (L) > 2) {
  764. if (lua_type (L, 3) == LUA_TFUNCTION) {
  765. /* Normal symbol from just a function */
  766. lua_pushvalue (L, 3);
  767. rspamd_register_symbol_fromlua (L,
  768. cfg,
  769. name,
  770. luaL_ref (L, LUA_REGISTRYINDEX),
  771. 1.0,
  772. 0,
  773. SYMBOL_TYPE_NORMAL);
  774. }
  775. else if (lua_type (L, 3) == LUA_TTABLE) {
  776. gint type = SYMBOL_TYPE_NORMAL, priority = 0, idx;
  777. gdouble weight = 1.0;
  778. const char *type_str;
  779. /*
  780. * Table can have the following attributes:
  781. * "callback" - should be a callback function
  782. * "weight" - optional weight
  783. * "priority" - optional priority
  784. * "type" - optional type (normal, virtual, callback)
  785. */
  786. lua_pushstring (L, "callback");
  787. lua_gettable (L, -2);
  788. if (lua_type (L, -1) != LUA_TFUNCTION) {
  789. lua_pop (L, 1);
  790. msg_info ("cannot find callback definition for %s", name);
  791. return 0;
  792. }
  793. idx = luaL_ref (L, LUA_REGISTRYINDEX);
  794. /* Optional fields */
  795. lua_pushstring (L, "weight");
  796. lua_gettable (L, -2);
  797. if (lua_type (L, -1) == LUA_TNUMBER) {
  798. weight = lua_tonumber (L, -1);
  799. }
  800. lua_pop (L, 1);
  801. lua_pushstring (L, "priority");
  802. lua_gettable (L, -2);
  803. if (lua_type (L, -1) == LUA_TNUMBER) {
  804. priority = lua_tonumber (L, -1);
  805. }
  806. lua_pop (L, 1);
  807. lua_pushstring (L, "type");
  808. lua_gettable (L, -2);
  809. if (lua_type (L, -1) == LUA_TSTRING) {
  810. type_str = lua_tostring (L, -1);
  811. if (strcmp (type_str, "normal") == 0) {
  812. type = SYMBOL_TYPE_NORMAL;
  813. }
  814. else if (strcmp (type_str, "virtual") == 0) {
  815. type = SYMBOL_TYPE_VIRTUAL;
  816. }
  817. else if (strcmp (type_str, "callback") == 0) {
  818. type = SYMBOL_TYPE_CALLBACK;
  819. }
  820. else {
  821. msg_info ("unknown type: %s", type_str);
  822. }
  823. }
  824. lua_pop (L, 1);
  825. rspamd_register_symbol_fromlua (L,
  826. cfg,
  827. name,
  828. idx,
  829. weight,
  830. priority,
  831. type);
  832. }
  833. }
  834. return 0;
  835. }
  836. struct lua_map_callback_data {
  837. lua_State *L;
  838. gint ref;
  839. GString *data;
  840. };
  841. static gchar *
  842. lua_map_read (rspamd_mempool_t *pool, gchar *chunk, gint len,
  843. struct map_cb_data *data)
  844. {
  845. struct lua_map_callback_data *cbdata, *old;
  846. if (data->cur_data == NULL) {
  847. cbdata = g_slice_alloc0 (sizeof (*cbdata));
  848. old = (struct lua_map_callback_data *)data->prev_data;
  849. cbdata->L = old->L;
  850. cbdata->ref = old->ref;
  851. data->cur_data = cbdata;
  852. }
  853. else {
  854. cbdata = (struct lua_map_callback_data *)data->cur_data;
  855. }
  856. if (cbdata->data == NULL) {
  857. cbdata->data = g_string_new_len (chunk, len);
  858. }
  859. else {
  860. g_string_append_len (cbdata->data, chunk, len);
  861. }
  862. return NULL;
  863. }
  864. void
  865. lua_map_fin (rspamd_mempool_t * pool, struct map_cb_data *data)
  866. {
  867. struct lua_map_callback_data *cbdata, *old;
  868. if (data->prev_data) {
  869. /* Cleanup old data */
  870. old = (struct lua_map_callback_data *)data->prev_data;
  871. if (old->data) {
  872. g_string_free (old->data, TRUE);
  873. }
  874. g_slice_free1 (sizeof (*old), old);
  875. data->prev_data = NULL;
  876. }
  877. if (data->cur_data) {
  878. cbdata = (struct lua_map_callback_data *)data->cur_data;
  879. }
  880. else {
  881. msg_err ("no data read for map");
  882. return;
  883. }
  884. if (cbdata->data != NULL && cbdata->data->len != 0) {
  885. lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->ref);
  886. lua_pushlstring (cbdata->L, cbdata->data->str, cbdata->data->len);
  887. if (lua_pcall (cbdata->L, 1, 0, 0) != 0) {
  888. msg_info ("call to %s failed: %s", "local function",
  889. lua_tostring (cbdata->L, -1));
  890. }
  891. }
  892. }
  893. static gint
  894. lua_config_add_map (lua_State *L)
  895. {
  896. struct rspamd_config *cfg = lua_check_config (L);
  897. const gchar *map_line, *description;
  898. struct lua_map_callback_data *cbdata, **pcbdata;
  899. int cbidx;
  900. if (cfg) {
  901. map_line = luaL_checkstring (L, 2);
  902. if (lua_gettop (L) == 4) {
  903. description = lua_tostring (L, 3);
  904. cbidx = 4;
  905. }
  906. else {
  907. description = NULL;
  908. cbidx = 3;
  909. }
  910. if (lua_type (L, cbidx) == LUA_TFUNCTION) {
  911. cbdata = g_slice_alloc (sizeof (*cbdata));
  912. cbdata->L = L;
  913. cbdata->data = NULL;
  914. lua_pushvalue (L, cbidx);
  915. /* Get a reference */
  916. cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
  917. pcbdata = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (cbdata));
  918. *pcbdata = cbdata;
  919. if (!add_map (cfg, map_line, description, lua_map_read, lua_map_fin,
  920. (void **)pcbdata)) {
  921. msg_warn ("invalid hash map %s", map_line);
  922. lua_pushboolean (L, false);
  923. }
  924. else {
  925. lua_pushboolean (L, true);
  926. }
  927. }
  928. else {
  929. msg_warn ("invalid callback argument for map %s", map_line);
  930. lua_pushboolean (L, false);
  931. }
  932. }
  933. else {
  934. lua_pushboolean (L, false);
  935. }
  936. return 1;
  937. }
  938. /* Radix and hash table functions */
  939. static gint
  940. lua_radix_get_key (lua_State * L)
  941. {
  942. radix_tree_t *radix = lua_check_radix (L);
  943. guint32 key;
  944. if (radix) {
  945. key = luaL_checkint (L, 2);
  946. if (radix32tree_find (radix, key) != RADIX_NO_VALUE) {
  947. lua_pushboolean (L, 1);
  948. return 1;
  949. }
  950. }
  951. lua_pushboolean (L, 0);
  952. return 1;
  953. }
  954. static gint
  955. lua_hash_table_get_key (lua_State * L)
  956. {
  957. GHashTable *tbl = lua_check_hash_table (L);
  958. const gchar *key, *value;
  959. if (tbl) {
  960. key = luaL_checkstring (L, 2);
  961. if ((value = g_hash_table_lookup (tbl, key)) != NULL) {
  962. lua_pushstring (L, value);
  963. return 1;
  964. }
  965. }
  966. lua_pushnil (L);
  967. return 1;
  968. }
  969. /* Trie functions */
  970. static gint
  971. lua_trie_create (lua_State *L)
  972. {
  973. rspamd_trie_t *trie, **ptrie;
  974. gboolean icase = FALSE;
  975. if (lua_gettop (L) == 1) {
  976. icase = lua_toboolean (L, 1);
  977. }
  978. trie = rspamd_trie_create (icase);
  979. ptrie = lua_newuserdata (L, sizeof (rspamd_trie_t *));
  980. rspamd_lua_setclass (L, "rspamd{trie}", -1);
  981. *ptrie = trie;
  982. return 1;
  983. }
  984. static gint
  985. lua_trie_add_pattern (lua_State *L)
  986. {
  987. rspamd_trie_t *trie = lua_check_trie (L);
  988. const gchar *pattern;
  989. gint id;
  990. if (trie) {
  991. pattern = luaL_checkstring (L, 2);
  992. id = luaL_checknumber (L, 3);
  993. if (pattern != NULL) {
  994. rspamd_trie_insert (trie, pattern, id);
  995. lua_pushboolean (L, 1);
  996. }
  997. }
  998. lua_pushboolean (L, 0);
  999. return 1;
  1000. }
  1001. static gint
  1002. lua_trie_search_text (lua_State *L)
  1003. {
  1004. rspamd_trie_t *trie = lua_check_trie (L);
  1005. const gchar *text, *pos;
  1006. gint id, i = 1;
  1007. gsize len;
  1008. gboolean found = FALSE;
  1009. if (trie) {
  1010. text = luaL_checkstring (L, 2);
  1011. len = strlen (text);
  1012. if (text) {
  1013. lua_newtable (L);
  1014. pos = text;
  1015. while (pos < text + len &&
  1016. (pos = rspamd_trie_lookup (trie, pos, len, &id)) != NULL) {
  1017. lua_pushinteger (L, i);
  1018. lua_pushinteger (L, id);
  1019. lua_settable (L, -3);
  1020. i++;
  1021. found = TRUE;
  1022. break;
  1023. }
  1024. if (!found) {
  1025. lua_pushnil (L);
  1026. }
  1027. return 1;
  1028. }
  1029. }
  1030. lua_pushnil (L);
  1031. return 1;
  1032. }
  1033. static gint
  1034. lua_trie_search_task (lua_State *L)
  1035. {
  1036. rspamd_trie_t *trie = lua_check_trie (L);
  1037. struct rspamd_task *task;
  1038. struct mime_text_part *part;
  1039. GList *cur;
  1040. const gchar *pos, *end;
  1041. gint id, i = 1;
  1042. void *ud;
  1043. gboolean found = FALSE;
  1044. if (trie) {
  1045. ud = luaL_checkudata (L, 2, "rspamd{task}");
  1046. luaL_argcheck (L, ud != NULL, 1, "'task' expected");
  1047. task = ud ? *((struct rspamd_task **)ud) : NULL;
  1048. if (task) {
  1049. lua_newtable (L);
  1050. cur = task->text_parts;
  1051. while (cur) {
  1052. part = cur->data;
  1053. if (!part->is_empty && part->content != NULL) {
  1054. pos = (const gchar *)part->content->data;
  1055. end = pos + part->content->len;
  1056. while (pos < end &&
  1057. (pos =
  1058. rspamd_trie_lookup (trie, pos, part->content->len,
  1059. &id)) != NULL) {
  1060. lua_pushinteger (L, i);
  1061. lua_pushinteger (L, id);
  1062. lua_settable (L, -3);
  1063. i++;
  1064. found = TRUE;
  1065. break;
  1066. }
  1067. }
  1068. cur = g_list_next (cur);
  1069. }
  1070. if (!found) {
  1071. lua_pushnil (L);
  1072. }
  1073. return 1;
  1074. }
  1075. }
  1076. if (!found) {
  1077. lua_pushnil (L);
  1078. }
  1079. return 1;
  1080. }
  1081. /* Init functions */
  1082. void
  1083. luaopen_config (lua_State * L)
  1084. {
  1085. rspamd_lua_new_class (L, "rspamd{config}", configlib_m);
  1086. lua_pop (L, 1); /* remove metatable from stack */
  1087. }
  1088. void
  1089. luaopen_radix (lua_State * L)
  1090. {
  1091. rspamd_lua_new_class (L, "rspamd{radix}", radixlib_m);
  1092. lua_pop (L, 1); /* remove metatable from stack */
  1093. }
  1094. void
  1095. luaopen_hash_table (lua_State * L)
  1096. {
  1097. rspamd_lua_new_class (L, "rspamd{hash_table}", hashlib_m);
  1098. luaL_register (L, "rspamd_hash_table", null_reg);
  1099. lua_pop (L, 1); /* remove metatable from stack */
  1100. }
  1101. static gint
  1102. lua_load_trie (lua_State *L)
  1103. {
  1104. lua_newtable (L);
  1105. luaL_register (L, NULL, trielib_f);
  1106. return 1;
  1107. }
  1108. void
  1109. luaopen_trie (lua_State * L)
  1110. {
  1111. luaL_newmetatable (L, "rspamd{trie}");
  1112. lua_pushstring (L, "__index");
  1113. lua_pushvalue (L, -2);
  1114. lua_settable (L, -3);
  1115. lua_pushstring (L, "class");
  1116. lua_pushstring (L, "rspamd{trie}");
  1117. lua_rawset (L, -3);
  1118. luaL_register (L, NULL, trielib_m);
  1119. rspamd_lua_add_preload (L, "rspamd_trie", lua_load_trie);
  1120. lua_pop (L, 1); /* remove metatable from stack */
  1121. }