Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

8 лет назад
8 лет назад
8 лет назад
10 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
5 лет назад
9 лет назад
3 месяцев назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
3 месяцев назад
10 лет назад
10 лет назад
5 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
9 лет назад
3 месяцев назад
3 месяцев назад
3 месяцев назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
10 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
5 лет назад
9 лет назад
5 лет назад
9 лет назад
9 лет назад
5 лет назад
9 лет назад
5 лет назад
9 лет назад
9 лет назад
5 лет назад
9 лет назад
5 лет назад
9 лет назад
9 лет назад
5 лет назад
9 лет назад
5 лет назад
9 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
5 лет назад
5 лет назад
9 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
3 месяцев назад
10 лет назад
3 месяцев назад
10 лет назад
10 лет назад
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. }