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_cfg_file.c 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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 "symbols_cache.h"
  27. #ifdef HAVE_SYS_UTSNAME_H
  28. #include <sys/utsname.h>
  29. #endif
  30. /*
  31. * This is implementation of lua routines to handle config file params
  32. */
  33. /* Process a single item in 'metrics' table */
  34. static void
  35. lua_process_metric (lua_State *L, const gchar *name, struct config_file *cfg)
  36. {
  37. GList *metric_list;
  38. gchar *symbol, *old_desc;
  39. const gchar *desc;
  40. struct metric *metric;
  41. gdouble *score, *old_score;
  42. /* Get module opt structure */
  43. if ((metric = g_hash_table_lookup (cfg->metrics, name)) == NULL) {
  44. metric = check_metric_conf (cfg, metric);
  45. metric->name = memory_pool_strdup (cfg->cfg_pool, name);
  46. }
  47. /* Now iterate throught module table */
  48. for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
  49. /* key - -2, value - -1 */
  50. symbol = memory_pool_strdup (cfg->cfg_pool, luaL_checkstring (L, -2));
  51. if (symbol != NULL) {
  52. if (lua_istable (L, -1)) {
  53. /* We got a table, so extract individual attributes */
  54. lua_pushstring (L, "weight");
  55. lua_gettable (L, -2);
  56. if (lua_isnumber (L, -1)) {
  57. score = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
  58. *score = lua_tonumber (L, -1);
  59. }
  60. else {
  61. msg_warn ("cannot get weight of symbol: %s", symbol);
  62. continue;
  63. }
  64. lua_pop (L, 1);
  65. lua_pushstring (L, "description");
  66. lua_gettable (L, -2);
  67. if (lua_isstring (L, -1)) {
  68. desc = lua_tostring (L, -1);
  69. old_desc = g_hash_table_lookup (metric->descriptions, symbol);
  70. if (old_desc) {
  71. msg_info ("replacing description for symbol %s", symbol);
  72. g_hash_table_replace (metric->descriptions,
  73. symbol, memory_pool_strdup (cfg->cfg_pool, desc));
  74. }
  75. else {
  76. g_hash_table_insert (metric->descriptions,
  77. symbol, memory_pool_strdup (cfg->cfg_pool, desc));
  78. }
  79. }
  80. lua_pop (L, 1);
  81. }
  82. else if (lua_isnumber (L, -1)) {
  83. /* Just got weight */
  84. score = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
  85. *score = lua_tonumber (L, -1);
  86. }
  87. else {
  88. msg_warn ("cannot get weight of symbol: %s", symbol);
  89. continue;
  90. }
  91. /* Insert symbol */
  92. if ((old_score = g_hash_table_lookup (metric->symbols, symbol)) != NULL) {
  93. msg_info ("replacing weight for symbol %s: %.2f -> %.2f", symbol, *old_score, *score);
  94. g_hash_table_replace (metric->symbols, symbol, score);
  95. }
  96. else {
  97. g_hash_table_insert (metric->symbols, symbol, score);
  98. }
  99. if ((metric_list = g_hash_table_lookup (cfg->metrics_symbols, symbol)) == NULL) {
  100. metric_list = g_list_prepend (NULL, metric);
  101. memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_list_free, metric_list);
  102. g_hash_table_insert (cfg->metrics_symbols, symbol, metric_list);
  103. }
  104. else {
  105. /* Slow but keep start element of list in safe */
  106. if (!g_list_find (metric_list, metric)) {
  107. metric_list = g_list_append (metric_list, metric);
  108. }
  109. }
  110. }
  111. }
  112. }
  113. /* Do post load initialization based on lua */
  114. void
  115. lua_post_load_config (struct config_file *cfg)
  116. {
  117. lua_State *L = cfg->lua_state;
  118. const gchar *name, *val;
  119. gchar *sym;
  120. struct expression *expr, *old_expr;
  121. ucl_object_t *obj;
  122. gsize keylen;
  123. /* First check all module options that may be overriden in 'config' global */
  124. lua_getglobal (L, "config");
  125. if (lua_istable (L, -1)) {
  126. /* Iterate */
  127. for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
  128. /* 'key' is at index -2 and 'value' is at index -1 */
  129. /* Key must be a string and value must be a table */
  130. name = luaL_checklstring (L, -2, &keylen);
  131. if (name != NULL && lua_istable (L, -1)) {
  132. obj = lua_rcl_obj_get (L, -1);
  133. if (obj != NULL) {
  134. cfg->rcl_obj = ucl_object_insert_key_merged (cfg->rcl_obj, obj, name, keylen, true);
  135. }
  136. }
  137. }
  138. }
  139. /* Check metrics settings */
  140. lua_getglobal (L, "metrics");
  141. if (lua_istable (L, -1)) {
  142. /* Iterate */
  143. for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
  144. /* 'key' is at index -2 and 'value' is at index -1 */
  145. /* Key must be a string and value must be a table */
  146. name = luaL_checkstring (L, -2);
  147. if (name != NULL && lua_istable (L, -1)) {
  148. lua_process_metric (L, name, cfg);
  149. }
  150. }
  151. }
  152. /* Check composites */
  153. lua_getglobal (L, "composites");
  154. if (lua_istable (L, -1)) {
  155. /* Iterate */
  156. for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
  157. /* 'key' is at index -2 and 'value' is at index -1 */
  158. /* Key must be a string and value must be a table */
  159. name = luaL_checkstring (L, -2);
  160. if (name != NULL && lua_isstring (L, -1)) {
  161. val = lua_tostring (L, -1);
  162. sym = memory_pool_strdup(cfg->cfg_pool, name);
  163. if ((expr = parse_expression (cfg->cfg_pool, memory_pool_strdup(cfg->cfg_pool, val))) == NULL) {
  164. msg_err ("cannot parse composite expression: %s", val);
  165. continue;
  166. }
  167. /* Now check hash table for this composite */
  168. if ((old_expr = g_hash_table_lookup (cfg->composite_symbols, name)) != NULL) {
  169. msg_info ("replacing composite symbol %s", name);
  170. g_hash_table_replace (cfg->composite_symbols, sym, expr);
  171. }
  172. else {
  173. g_hash_table_insert (cfg->composite_symbols, sym, expr);
  174. register_virtual_symbol (&cfg->cache, sym, 1);
  175. }
  176. }
  177. }
  178. }
  179. }
  180. /* Handle lua dynamic config param */
  181. gboolean
  182. lua_handle_param (struct worker_task *task, gchar *mname, gchar *optname, enum lua_var_type expected_type, gpointer *res)
  183. {
  184. /* xxx: Adopt this for rcl */
  185. /* Option not found */
  186. *res = NULL;
  187. return FALSE;
  188. }
  189. #define FAKE_RES_VAR "rspamd_res"
  190. gboolean
  191. lua_check_condition (struct config_file *cfg, const gchar *condition)
  192. {
  193. lua_State *L = cfg->lua_state;
  194. gchar *hostbuf, *condbuf;
  195. gsize hostlen;
  196. gboolean res;
  197. #ifdef HAVE_SYS_UTSNAME_H
  198. struct utsname uts;
  199. #endif
  200. /* Set some globals for condition */
  201. /* XXX: think what other variables can be useful */
  202. hostlen = sysconf (_SC_HOST_NAME_MAX) + 1;
  203. hostbuf = alloca (hostlen);
  204. gethostname (hostbuf, hostlen);
  205. hostbuf[hostlen - 1] = '\0';
  206. /* Hostname */
  207. lua_pushstring (L, hostbuf);
  208. lua_setglobal (L, "hostname");
  209. /* Config file name */
  210. lua_pushstring (L, cfg->cfg_name);
  211. lua_setglobal (L, "cfg_name");
  212. /* Check for uname */
  213. #ifdef HAVE_SYS_UTSNAME_H
  214. uname (&uts);
  215. lua_pushstring (L, uts.sysname);
  216. lua_setglobal (L, "osname");
  217. lua_pushstring (L, uts.release);
  218. lua_setglobal (L, "osrelease");
  219. #else
  220. lua_pushstring (L, "unknown");
  221. lua_setglobal (L, "osname");
  222. lua_pushstring (L, "");
  223. lua_setglobal (L, "osrelease");
  224. #endif
  225. #ifdef HAVE_OPENSSL
  226. lua_pushboolean (L, TRUE);
  227. #else
  228. lua_pushboolean (L, FALSE);
  229. #endif
  230. lua_setglobal (L, "rspamd_supports_rsa");
  231. /* Rspamd paths */
  232. lua_newtable (L);
  233. lua_set_table_index (L, "confdir", RSPAMD_CONFDIR);
  234. lua_set_table_index (L, "rundir", RSPAMD_RUNDIR);
  235. lua_set_table_index (L, "dbdir", RSPAMD_DBDIR);
  236. lua_set_table_index (L, "logdir", RSPAMD_LOGDIR);
  237. lua_set_table_index (L, "pluginsdir", RSPAMD_PLUGINSDIR);
  238. lua_set_table_index (L, "prefix", RSPAMD_PREFIX);
  239. lua_setglobal (L, "rspamd_paths");
  240. /* Make fake string */
  241. hostlen = sizeof (FAKE_RES_VAR "=") + strlen (condition);
  242. condbuf = g_malloc (hostlen);
  243. rspamd_strlcpy (condbuf, FAKE_RES_VAR "=", sizeof (FAKE_RES_VAR "="));
  244. g_strlcat (condbuf, condition, hostlen);
  245. /* Evaluate condition */
  246. if (luaL_dostring (L, condbuf) != 0) {
  247. msg_err ("eval of '%s' failed: '%s'", condition, lua_tostring (L, -1));
  248. g_free (condbuf);
  249. return FALSE;
  250. }
  251. /* Get global variable res to get result */
  252. lua_getglobal (L, FAKE_RES_VAR);
  253. if (! lua_isboolean (L, -1)) {
  254. msg_err ("bad string evaluated: %s, type: %s", condbuf, lua_typename (L, lua_type (L, -1)));
  255. g_free (condbuf);
  256. return FALSE;
  257. }
  258. res = lua_toboolean (L, -1);
  259. g_free (condbuf);
  260. return res;
  261. }