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_dns_resolver.c 19KB

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