Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

lua_dns_resolver.c 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "lua_common.h"
  17. #include "lua_thread_pool.h"
  18. #include "utlist.h"
  19. /***
  20. * @module rspamd_resolver
  21. * This module allows to resolve DNS names from LUA code. All resolving is executed
  22. * asynchronously. Here is an example of name resolution:
  23. * @example
  24. local function symbol_callback(task)
  25. local host = 'example.com'
  26. local function dns_cb(resolver, to_resolve, results, err, _, authenticated)
  27. if not results then
  28. rspamd_logger.infox('DNS resolving of %1 failed: %2', host, err)
  29. return
  30. end
  31. for _,r in ipairs(results) do
  32. -- r is of type rspamd{ip} here, but it can be converted to string
  33. rspamd_logger.infox('Resolved %1 to %2', host, tostring(r))
  34. end
  35. end
  36. task:get_resolver():resolve_a({task = task, name = host, callback = dns_cb})
  37. end
  38. */
  39. static const gchar *M = "rspamd lua dns resolver";
  40. /* Lua bindings */
  41. LUA_FUNCTION_DEF (dns_resolver, init);
  42. LUA_FUNCTION_DEF (dns_resolver, resolve_a);
  43. LUA_FUNCTION_DEF (dns_resolver, resolve_ptr);
  44. LUA_FUNCTION_DEF (dns_resolver, resolve_txt);
  45. LUA_FUNCTION_DEF (dns_resolver, resolve_mx);
  46. LUA_FUNCTION_DEF (dns_resolver, resolve_ns);
  47. LUA_FUNCTION_DEF (dns_resolver, resolve);
  48. LUA_FUNCTION_DEF (dns_resolver, idna_convert_utf8);
  49. void lua_push_dns_reply (lua_State *L, const struct rdns_reply *reply);
  50. static const struct luaL_reg dns_resolverlib_f[] = {
  51. LUA_INTERFACE_DEF (dns_resolver, init),
  52. {NULL, NULL}
  53. };
  54. static const struct luaL_reg dns_resolverlib_m[] = {
  55. LUA_INTERFACE_DEF (dns_resolver, resolve_a),
  56. LUA_INTERFACE_DEF (dns_resolver, resolve_ptr),
  57. LUA_INTERFACE_DEF (dns_resolver, resolve_txt),
  58. LUA_INTERFACE_DEF (dns_resolver, resolve_mx),
  59. LUA_INTERFACE_DEF (dns_resolver, resolve_ns),
  60. LUA_INTERFACE_DEF (dns_resolver, resolve),
  61. LUA_INTERFACE_DEF (dns_resolver, idna_convert_utf8),
  62. {"__tostring", rspamd_lua_class_tostring},
  63. {NULL, NULL}
  64. };
  65. struct rspamd_dns_resolver *
  66. lua_check_dns_resolver (lua_State * L, gint pos)
  67. {
  68. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{resolver}");
  69. luaL_argcheck (L, ud != NULL, pos, "'resolver' expected");
  70. return ud ? *((struct rspamd_dns_resolver **)ud) : NULL;
  71. }
  72. struct lua_dns_cbdata {
  73. struct rspamd_task *task;
  74. rspamd_mempool_t *pool;
  75. struct rspamd_dns_resolver *resolver;
  76. gint cbref;
  77. gchar *to_resolve;
  78. gchar *user_str;
  79. struct rspamd_symcache_dynamic_item *item;
  80. struct rspamd_async_session *s;
  81. };
  82. static int
  83. lua_dns_get_type (lua_State *L, int argno)
  84. {
  85. int type = RDNS_REQUEST_A;
  86. const gchar *strtype;
  87. if (lua_type (L, argno) != LUA_TSTRING) {
  88. lua_pushvalue (L, argno);
  89. lua_gettable (L, lua_upvalueindex (1));
  90. type = lua_tonumber (L, -1);
  91. lua_pop (L, 1);
  92. if (type == 0) {
  93. rspamd_lua_typerror (L, argno, "dns_request_type");
  94. }
  95. }
  96. else {
  97. strtype = lua_tostring (L, argno);
  98. type = rdns_type_fromstr (strtype);
  99. }
  100. return type;
  101. }
  102. static void
  103. lua_dns_resolver_callback (struct rdns_reply *reply, gpointer arg)
  104. {
  105. struct lua_dns_cbdata *cd = arg;
  106. struct rspamd_dns_resolver **presolver;
  107. lua_State *L;
  108. struct lua_callback_state cbs;
  109. rspamd_mempool_t *pool;
  110. gint err_idx;
  111. pool = cd->pool;
  112. lua_thread_pool_prepare_callback (cd->resolver->cfg->lua_thread_pool, &cbs);
  113. L = cbs.L;
  114. lua_pushcfunction (L, &rspamd_lua_traceback);
  115. err_idx = lua_gettop (L);
  116. lua_rawgeti (L, LUA_REGISTRYINDEX, cd->cbref);
  117. presolver = lua_newuserdata (L, sizeof (gpointer));
  118. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  119. *presolver = cd->resolver;
  120. lua_pushstring (L, cd->to_resolve);
  121. lua_push_dns_reply (L, reply);
  122. /*
  123. * 1 - resolver
  124. * 2 - to_resolve
  125. * 3 - entries | nil
  126. * 4 - error | nil
  127. * 5 - user_str
  128. * 6 - reply->flags & RDNS_AUTH
  129. * 7 - server
  130. */
  131. if (reply->code != RDNS_RC_NOERROR) {
  132. lua_pushnil (L);
  133. lua_pushstring (L, rdns_strerror (reply->code));
  134. }
  135. if (cd->user_str != NULL) {
  136. lua_pushstring (L, cd->user_str);
  137. }
  138. else {
  139. lua_pushnil (L);
  140. }
  141. lua_pushboolean (L, reply->flags & RDNS_AUTH);
  142. const gchar *servname = rdns_request_get_server (reply->request);
  143. if (servname) {
  144. lua_pushstring (L, servname);
  145. }
  146. else {
  147. lua_pushnil (L);
  148. }
  149. if (cd->item) {
  150. /* We also need to restore the item in case there are some chains */
  151. rspamd_symcache_set_cur_item (cd->task, cd->item);
  152. }
  153. if (lua_pcall (L, 7, 0, err_idx) != 0) {
  154. msg_err_pool_check ("call to dns callback failed: %s",
  155. lua_tostring (L, -1));
  156. }
  157. lua_settop (L, err_idx - 1);
  158. /* Unref function */
  159. luaL_unref (L, LUA_REGISTRYINDEX, cd->cbref);
  160. lua_thread_pool_restore_callback (&cbs);
  161. if (cd->item) {
  162. rspamd_symcache_item_async_dec_check (cd->task, cd->item, M);
  163. }
  164. if (!cd->pool) {
  165. g_free (cd->to_resolve);
  166. g_free (cd->user_str);
  167. g_free (cd);
  168. }
  169. }
  170. void
  171. lua_push_dns_reply (lua_State *L, const struct rdns_reply *reply)
  172. {
  173. gint i = 0, naddrs = 0;
  174. struct rdns_reply_entry *elt;
  175. rspamd_inet_addr_t *addr;
  176. if (reply->code == RDNS_RC_NOERROR) {
  177. LL_FOREACH (reply->entries, elt) {
  178. naddrs ++;
  179. }
  180. lua_createtable (L, naddrs, 0);
  181. LL_FOREACH (reply->entries, elt)
  182. {
  183. if (!rdns_request_has_type(reply->request, elt->type)) {
  184. /* Unrequested type has been returned, ignore it */
  185. continue;
  186. }
  187. switch (elt->type) {
  188. case RDNS_REQUEST_A:
  189. addr = rspamd_inet_address_new (AF_INET, &elt->content.a.addr);
  190. rspamd_lua_ip_push (L, addr);
  191. rspamd_inet_address_free (addr);
  192. lua_rawseti (L, -2, ++i);
  193. break;
  194. case RDNS_REQUEST_AAAA:
  195. addr = rspamd_inet_address_new (AF_INET6, &elt->content.aaa.addr);
  196. rspamd_lua_ip_push (L, addr);
  197. rspamd_inet_address_free (addr);
  198. lua_rawseti (L, -2, ++i);
  199. break;
  200. case RDNS_REQUEST_NS:
  201. lua_pushstring (L, elt->content.ns.name);
  202. lua_rawseti (L, -2, ++i);
  203. break;
  204. case RDNS_REQUEST_PTR:
  205. lua_pushstring (L, elt->content.ptr.name);
  206. lua_rawseti (L, -2, ++i);
  207. break;
  208. case RDNS_REQUEST_TXT:
  209. case RDNS_REQUEST_SPF:
  210. lua_pushstring (L, elt->content.txt.data);
  211. lua_rawseti (L, -2, ++i);
  212. break;
  213. case RDNS_REQUEST_MX:
  214. /* mx['name'], mx['priority'] */
  215. lua_createtable (L, 0, 2);
  216. rspamd_lua_table_set (L, "name", elt->content.mx.name);
  217. lua_pushstring (L, "priority");
  218. lua_pushinteger (L, elt->content.mx.priority);
  219. lua_settable (L, -3);
  220. lua_rawseti (L, -2, ++i);
  221. break;
  222. case RDNS_REQUEST_SOA:
  223. lua_createtable (L, 0, 7);
  224. rspamd_lua_table_set (L, "ns", elt->content.soa.mname);
  225. rspamd_lua_table_set (L, "contact", elt->content.soa.admin);
  226. lua_pushstring (L, "serial");
  227. lua_pushinteger (L, elt->content.soa.serial);
  228. lua_settable (L, -3);
  229. lua_pushstring (L, "refresh");
  230. lua_pushinteger (L, elt->content.soa.refresh);
  231. lua_settable (L, -3);
  232. lua_pushstring (L, "retry");
  233. lua_pushinteger (L, elt->content.soa.retry);
  234. lua_settable (L, -3);
  235. lua_pushstring (L, "expiry");
  236. lua_pushinteger (L, elt->content.soa.expire);
  237. lua_settable (L, -3);
  238. /* Negative TTL */
  239. lua_pushstring (L, "nx");
  240. lua_pushinteger (L, elt->content.soa.minimum);
  241. lua_settable (L, -3);
  242. lua_rawseti (L, -2, ++i);
  243. break;
  244. case RDNS_REQUEST_CNAME:
  245. lua_pushstring (L, elt->content.cname.name);
  246. lua_rawseti (L, -2, ++i);
  247. break;
  248. default:
  249. continue;
  250. }
  251. }
  252. lua_pushnil (L);
  253. }
  254. }
  255. /***
  256. * @function rspamd_resolver.init(ev_base, config)
  257. * @param {event_base} ev_base event base used for asynchronous events
  258. * @param {rspamd_config} config rspamd configuration parameters
  259. * @return {rspamd_resolver} new resolver object associated with the specified base
  260. */
  261. static int
  262. lua_dns_resolver_init (lua_State *L)
  263. {
  264. struct rspamd_dns_resolver *resolver, **presolver;
  265. struct rspamd_config *cfg, **pcfg;
  266. struct ev_loop *base, **pbase;
  267. /* Check args */
  268. pbase = rspamd_lua_check_udata (L, 1, "rspamd{ev_base}");
  269. luaL_argcheck (L, pbase != NULL, 1, "'ev_base' expected");
  270. base = pbase ? *(pbase) : NULL;
  271. pcfg = rspamd_lua_check_udata (L, 2, "rspamd{config}");
  272. luaL_argcheck (L, pcfg != NULL, 2, "'config' expected");
  273. cfg = pcfg ? *(pcfg) : NULL;
  274. if (base != NULL && cfg != NULL) {
  275. resolver = rspamd_dns_resolver_init (NULL, base, cfg);
  276. if (resolver) {
  277. presolver = lua_newuserdata (L, sizeof (gpointer));
  278. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  279. *presolver = resolver;
  280. }
  281. else {
  282. lua_pushnil (L);
  283. }
  284. }
  285. else {
  286. lua_pushnil (L);
  287. }
  288. return 1;
  289. }
  290. static int
  291. lua_dns_resolver_resolve_common (lua_State *L,
  292. struct rspamd_dns_resolver *resolver,
  293. enum rdns_request_type type,
  294. int first)
  295. {
  296. LUA_TRACE_POINT;
  297. struct rspamd_async_session *session = NULL;
  298. rspamd_mempool_t *pool = NULL;
  299. const gchar *to_resolve = NULL, *user_str = NULL;
  300. struct lua_dns_cbdata *cbdata;
  301. gint cbref = -1, ret;
  302. struct rspamd_task *task = NULL;
  303. GError *err = NULL;
  304. gboolean forced = FALSE;
  305. struct rspamd_symcache_dynamic_item *item = NULL;
  306. /* Check arguments */
  307. if (!rspamd_lua_parse_table_arguments (L, first, &err,
  308. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  309. "session=U{session};mempool=U{mempool};*name=S;*callback=F;"
  310. "option=S;task=U{task};forced=B",
  311. &session, &pool, &to_resolve, &cbref, &user_str, &task, &forced)) {
  312. if (err) {
  313. ret = luaL_error (L, "invalid arguments: %s", err->message);
  314. g_error_free (err);
  315. return ret;
  316. }
  317. return luaL_error (L, "invalid arguments");
  318. }
  319. if (task) {
  320. pool = task->task_pool;
  321. session = task->s;
  322. item = rspamd_symcache_get_cur_item (task);
  323. }
  324. if (to_resolve != NULL) {
  325. if (pool != NULL) {
  326. cbdata = rspamd_mempool_alloc0 (pool, sizeof (struct lua_dns_cbdata));
  327. cbdata->user_str = rspamd_mempool_strdup (pool, user_str);
  328. if (type != RDNS_REQUEST_PTR) {
  329. cbdata->to_resolve = rspamd_mempool_strdup (pool, to_resolve);
  330. }
  331. else {
  332. char *ptr_str;
  333. ptr_str = rdns_generate_ptr_from_str (to_resolve);
  334. if (ptr_str == NULL) {
  335. msg_err_task_check ("wrong resolve string to PTR request: %s",
  336. to_resolve);
  337. goto err;
  338. }
  339. cbdata->to_resolve = rspamd_mempool_strdup (pool, ptr_str);
  340. to_resolve = cbdata->to_resolve;
  341. free (ptr_str);
  342. }
  343. }
  344. else {
  345. cbdata = g_malloc0 (sizeof (struct lua_dns_cbdata));
  346. cbdata->user_str = user_str ? g_strdup (user_str) : NULL;
  347. if (type != RDNS_REQUEST_PTR) {
  348. cbdata->to_resolve = g_strdup (to_resolve);
  349. }
  350. else {
  351. char *ptr_str;
  352. ptr_str = rdns_generate_ptr_from_str (to_resolve);
  353. if (ptr_str == NULL) {
  354. msg_err_task_check ("wrong resolve string to PTR request: %s",
  355. to_resolve);
  356. goto err;
  357. }
  358. cbdata->to_resolve = g_strdup (ptr_str);
  359. free (ptr_str);
  360. }
  361. }
  362. cbdata->resolver = resolver;
  363. cbdata->cbref = cbref;
  364. cbdata->task = task;
  365. cbdata->pool = pool;
  366. if (task == NULL) {
  367. if (rspamd_dns_resolver_request (resolver,
  368. session,
  369. pool,
  370. lua_dns_resolver_callback,
  371. cbdata,
  372. type,
  373. to_resolve)) {
  374. lua_pushboolean (L, TRUE);
  375. if (session) {
  376. cbdata->s = session;
  377. }
  378. }
  379. else {
  380. goto err;
  381. }
  382. }
  383. else {
  384. /* Fail-safety as this function can, in theory, call
  385. * lua_dns_resolver_callback without switching to the event loop
  386. */
  387. if (item) {
  388. rspamd_symcache_item_async_inc (task, item, M);
  389. }
  390. if (forced) {
  391. ret = rspamd_dns_resolver_request_task_forced (task,
  392. lua_dns_resolver_callback,
  393. cbdata,
  394. type,
  395. to_resolve);
  396. } else {
  397. ret = rspamd_dns_resolver_request_task (task,
  398. lua_dns_resolver_callback,
  399. cbdata,
  400. type,
  401. to_resolve);
  402. }
  403. if (ret) {
  404. cbdata->s = session;
  405. if (item) {
  406. cbdata->item = item;
  407. rspamd_symcache_item_async_inc (task, item, M);
  408. }
  409. /* callback was set up */
  410. lua_pushboolean (L, TRUE);
  411. }
  412. else {
  413. if (item) {
  414. rspamd_symcache_item_async_dec_check (task, item, M);
  415. }
  416. goto err;
  417. }
  418. if (item) {
  419. rspamd_symcache_item_async_dec_check (task, item, M);
  420. }
  421. }
  422. }
  423. else {
  424. return luaL_error (L, "invalid arguments to lua_resolve");
  425. }
  426. return 1;
  427. err:
  428. /* Callback is not called in this case */
  429. if (cbdata->cbref != -1) {
  430. luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cbref);
  431. }
  432. if (!pool) {
  433. /* Free resources */
  434. g_free (cbdata->to_resolve);
  435. g_free (cbdata->user_str);
  436. g_free (cbdata);
  437. }
  438. lua_pushnil (L);
  439. return 1;
  440. }
  441. /***
  442. * @method resolver:resolve_a(table)
  443. * Resolve A record for a specified host.
  444. * Table elements:
  445. * * `task` - task element (preferred, required to track dependencies) -or-
  446. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  447. * * `mempool` - pool memory pool for storing intermediate data
  448. * * `name` - host name to resolve
  449. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  450. * * `forced` - true if needed to override normal limit for DNS requests
  451. * @return {boolean} `true` if DNS request has been scheduled
  452. */
  453. static int
  454. lua_dns_resolver_resolve_a (lua_State *L)
  455. {
  456. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  457. if (dns_resolver) {
  458. return lua_dns_resolver_resolve_common (L,
  459. dns_resolver,
  460. RDNS_REQUEST_A,
  461. 2);
  462. }
  463. else {
  464. lua_pushnil (L);
  465. }
  466. return 1;
  467. }
  468. /***
  469. * @method resolver:resolve_ptr(table)
  470. * Resolve PTR record for a specified host.
  471. * Table elements:
  472. * * `task` - task element (preferred, required to track dependencies) -or-
  473. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  474. * * `mempool` - pool memory pool for storing intermediate data
  475. * * `name` - host name to resolve
  476. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  477. * * `forced` - true if needed to override normal limit for DNS requests
  478. * @return {boolean} `true` if DNS request has been scheduled
  479. */
  480. static int
  481. lua_dns_resolver_resolve_ptr (lua_State *L)
  482. {
  483. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  484. if (dns_resolver) {
  485. return lua_dns_resolver_resolve_common (L,
  486. dns_resolver,
  487. RDNS_REQUEST_PTR,
  488. 2);
  489. }
  490. else {
  491. lua_pushnil (L);
  492. }
  493. return 1;
  494. }
  495. /***
  496. * @method resolver:resolve_txt(table)
  497. * Resolve TXT record for a specified host.
  498. * Table elements:
  499. * * `task` - task element (preferred, required to track dependencies) -or-
  500. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  501. * * `mempool` - pool memory pool for storing intermediate data
  502. * * `name` - host name to resolve
  503. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  504. * * `forced` - true if needed to override normal limit for DNS requests
  505. * @return {boolean} `true` if DNS request has been scheduled
  506. */
  507. static int
  508. lua_dns_resolver_resolve_txt (lua_State *L)
  509. {
  510. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  511. if (dns_resolver) {
  512. return lua_dns_resolver_resolve_common (L,
  513. dns_resolver,
  514. RDNS_REQUEST_TXT,
  515. 2);
  516. }
  517. else {
  518. lua_pushnil (L);
  519. }
  520. return 1;
  521. }
  522. /***
  523. * @method resolver:resolve_mx(table)
  524. * Resolve MX record for a specified host.
  525. * Table elements:
  526. * * `task` - task element (preferred, required to track dependencies) -or-
  527. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  528. * * `mempool` - pool memory pool for storing intermediate data
  529. * * `name` - host name to resolve
  530. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  531. * * `forced` - true if needed to override normal limit for DNS requests
  532. * @return {boolean} `true` if DNS request has been scheduled
  533. */
  534. static int
  535. lua_dns_resolver_resolve_mx (lua_State *L)
  536. {
  537. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  538. if (dns_resolver) {
  539. return lua_dns_resolver_resolve_common (L,
  540. dns_resolver,
  541. RDNS_REQUEST_MX,
  542. 2);
  543. }
  544. else {
  545. lua_pushnil (L);
  546. }
  547. return 1;
  548. }
  549. /***
  550. * @method resolver:resolve_ns(table)
  551. * Resolve NS records for a specified host.
  552. * Table elements:
  553. * * `task` - task element (preferred, required to track dependencies) -or-
  554. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  555. * * `mempool` - pool memory pool for storing intermediate data
  556. * * `name` - host name to resolve
  557. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  558. * * `forced` - true if needed to override normal limit for DNS requests
  559. * @return {boolean} `true` if DNS request has been scheduled
  560. */
  561. static int
  562. lua_dns_resolver_resolve_ns (lua_State *L)
  563. {
  564. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  565. if (dns_resolver) {
  566. return lua_dns_resolver_resolve_common (L,
  567. dns_resolver,
  568. RDNS_REQUEST_NS,
  569. 2);
  570. }
  571. else {
  572. lua_pushnil (L);
  573. }
  574. return 1;
  575. }
  576. /* XXX: broken currently */
  577. static int
  578. lua_dns_resolver_resolve (lua_State *L)
  579. {
  580. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  581. int type;
  582. type = lua_dns_get_type (L, 2);
  583. if (dns_resolver && type != 0) {
  584. return lua_dns_resolver_resolve_common (L, dns_resolver, type, 3);
  585. }
  586. else {
  587. lua_pushnil (L);
  588. }
  589. return 1;
  590. }
  591. /***
  592. * @method resolver:idna_convert_utf8(hostname[, pool])
  593. * Converts domain name from IDN (in utf8 format) to punycode
  594. * @return {string} new name converted
  595. */
  596. static int
  597. lua_dns_resolver_idna_convert_utf8 (lua_State *L)
  598. {
  599. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  600. gsize hlen;
  601. guint conv_len = 0;
  602. const gchar *hname = luaL_checklstring (L, 2, &hlen);
  603. gchar *converted;
  604. rspamd_mempool_t *pool = rspamd_lua_check_udata_maybe (L, 3, "rspamd{mempool}");
  605. if (dns_resolver && hname) {
  606. if (!rspamd_str_has_8bit (hname, hlen)) {
  607. /* No 8 bit, no reasons to call idna */
  608. lua_pushlstring (L, hname, hlen);
  609. }
  610. else {
  611. converted = rspamd_dns_resolver_idna_convert_utf8 (dns_resolver, pool,
  612. hname, hlen, &conv_len);
  613. if (converted == NULL) {
  614. lua_pushnil (L);
  615. }
  616. else {
  617. lua_pushlstring (L, converted, conv_len);
  618. if (pool == NULL) {
  619. g_free (converted);
  620. }
  621. }
  622. }
  623. }
  624. else {
  625. return luaL_error (L, "invalid arguments");
  626. }
  627. return 1;
  628. }
  629. static gint
  630. lua_load_dns_resolver (lua_State *L)
  631. {
  632. lua_newtable (L);
  633. luaL_register (L, NULL, dns_resolverlib_f);
  634. return 1;
  635. }
  636. void
  637. luaopen_dns_resolver (lua_State * L)
  638. {
  639. rspamd_lua_new_class (L, "rspamd{resolver}", dns_resolverlib_m);
  640. {
  641. LUA_ENUM (L, DNS_A, RDNS_REQUEST_A);
  642. LUA_ENUM (L, DNS_PTR, RDNS_REQUEST_PTR);
  643. LUA_ENUM (L, DNS_MX, RDNS_REQUEST_MX);
  644. LUA_ENUM (L, DNS_TXT, RDNS_REQUEST_TXT);
  645. LUA_ENUM (L, DNS_SRV, RDNS_REQUEST_SRV);
  646. LUA_ENUM (L, DNS_SPF, RDNS_REQUEST_SPF);
  647. LUA_ENUM (L, DNS_AAAA, RDNS_REQUEST_AAAA);
  648. LUA_ENUM (L, DNS_SOA, RDNS_REQUEST_SOA);
  649. LUA_ENUM (L, DNS_CNAME, RDNS_REQUEST_CNAME);
  650. }
  651. lua_pop (L, 1);
  652. rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
  653. }