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.

util.c 47KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  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 "config.h"
  25. #include "util.h"
  26. #include "cfg_file.h"
  27. #include "main.h"
  28. #include "statfile.h"
  29. #include "filter.h"
  30. #include "message.h"
  31. #ifdef HAVE_OPENSSL
  32. #include <openssl/rand.h>
  33. #include <openssl/err.h>
  34. #endif
  35. #ifdef HAVE_TERMIOS_H
  36. #include <termios.h>
  37. #endif
  38. #ifdef HAVE_READPASSPHRASE_H
  39. #include <readpassphrase.h>
  40. #endif
  41. /* Check log messages intensity once per minute */
  42. #define CHECK_TIME 60
  43. /* More than 2 log messages per second */
  44. #define BUF_INTENSITY 2
  45. /* Default connect timeout for sync sockets */
  46. #define CONNECT_TIMEOUT 3
  47. gint
  48. make_socket_nonblocking (gint fd)
  49. {
  50. gint ofl;
  51. ofl = fcntl (fd, F_GETFL, 0);
  52. if (fcntl (fd, F_SETFL, ofl | O_NONBLOCK) == -1) {
  53. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  54. return -1;
  55. }
  56. return 0;
  57. }
  58. gint
  59. make_socket_blocking (gint fd)
  60. {
  61. gint ofl;
  62. ofl = fcntl (fd, F_GETFL, 0);
  63. if (fcntl (fd, F_SETFL, ofl & (~O_NONBLOCK)) == -1) {
  64. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  65. return -1;
  66. }
  67. return 0;
  68. }
  69. gint
  70. poll_sync_socket (gint fd, gint timeout, short events)
  71. {
  72. gint r;
  73. struct pollfd fds[1];
  74. fds->fd = fd;
  75. fds->events = events;
  76. fds->revents = 0;
  77. while ((r = poll (fds, 1, timeout)) < 0) {
  78. if (errno != EINTR) {
  79. break;
  80. }
  81. }
  82. return r;
  83. }
  84. static gint
  85. make_inet_socket (gint type, struct addrinfo *addr, gboolean is_server, gboolean async, GList **list)
  86. {
  87. gint fd, r, optlen, on = 1, s_error;
  88. struct addrinfo *cur;
  89. cur = addr;
  90. while (cur) {
  91. /* Create socket */
  92. fd = socket (cur->ai_family, type, 0);
  93. if (fd == -1) {
  94. msg_warn ("socket failed: %d, '%s'", errno, strerror (errno));
  95. goto out;
  96. }
  97. if (make_socket_nonblocking (fd) < 0) {
  98. goto out;
  99. }
  100. /* Set close on exec */
  101. if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) {
  102. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  103. goto out;
  104. }
  105. if (is_server) {
  106. setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
  107. #ifdef HAVE_IPV6_V6ONLY
  108. if (cur->ai_family == AF_INET6) {
  109. setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, sizeof (gint));
  110. }
  111. #endif
  112. r = bind (fd, cur->ai_addr, cur->ai_addrlen);
  113. }
  114. else {
  115. r = connect (fd, cur->ai_addr, cur->ai_addrlen);
  116. }
  117. if (r == -1) {
  118. if (errno != EINPROGRESS) {
  119. msg_warn ("bind/connect failed: %d, '%s'", errno, strerror (errno));
  120. goto out;
  121. }
  122. if (!async) {
  123. /* Try to poll */
  124. if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
  125. errno = ETIMEDOUT;
  126. msg_warn ("bind/connect failed: timeout");
  127. goto out;
  128. }
  129. else {
  130. /* Make synced again */
  131. if (make_socket_blocking (fd) < 0) {
  132. goto out;
  133. }
  134. }
  135. }
  136. }
  137. else {
  138. /* Still need to check SO_ERROR on socket */
  139. optlen = sizeof (s_error);
  140. getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
  141. if (s_error) {
  142. errno = s_error;
  143. goto out;
  144. }
  145. }
  146. if (list == NULL) {
  147. /* Go out immediately */
  148. break;
  149. }
  150. else if (fd != -1) {
  151. *list = g_list_prepend (*list, GINT_TO_POINTER (fd));
  152. cur = cur->ai_next;
  153. continue;
  154. }
  155. out:
  156. if (fd != -1) {
  157. close (fd);
  158. }
  159. fd = -1;
  160. cur = cur->ai_next;
  161. }
  162. return (fd);
  163. }
  164. gint
  165. make_tcp_socket (struct addrinfo *addr, gboolean is_server, gboolean async)
  166. {
  167. return make_inet_socket (SOCK_STREAM, addr, is_server, async, NULL);
  168. }
  169. gint
  170. make_udp_socket (struct addrinfo *addr, gboolean is_server, gboolean async)
  171. {
  172. return make_inet_socket (SOCK_DGRAM, addr, is_server, async, NULL);
  173. }
  174. gint
  175. accept_from_socket (gint listen_sock, struct sockaddr *addr, socklen_t * len)
  176. {
  177. gint nfd;
  178. gint serrno;
  179. if ((nfd = accept (listen_sock, addr, len)) == -1) {
  180. if (errno == EAGAIN) {
  181. return 0;
  182. }
  183. msg_warn ("accept failed: %d, '%s'", errno, strerror (errno));
  184. return -1;
  185. }
  186. if (make_socket_nonblocking (nfd) < 0) {
  187. goto out;
  188. }
  189. /* Set close on exec */
  190. if (fcntl (nfd, F_SETFD, FD_CLOEXEC) == -1) {
  191. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  192. goto out;
  193. }
  194. return (nfd);
  195. out:
  196. serrno = errno;
  197. close (nfd);
  198. errno = serrno;
  199. return (-1);
  200. }
  201. gint
  202. make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboolean is_server, gboolean async)
  203. {
  204. gint fd = -1, s_error, r, optlen, serrno, on = 1;
  205. struct stat st;
  206. if (path == NULL)
  207. return -1;
  208. addr->sun_family = AF_UNIX;
  209. rspamd_strlcpy (addr->sun_path, path, sizeof (addr->sun_path));
  210. #ifdef FREEBSD
  211. addr->sun_len = SUN_LEN (addr);
  212. #endif
  213. if (is_server) {
  214. /* Unlink socket if it exists already */
  215. if (lstat (addr->sun_path, &st) != -1) {
  216. if (S_ISSOCK (st.st_mode)) {
  217. if (unlink (addr->sun_path) == -1) {
  218. msg_warn ("unlink %s failed: %d, '%s'", addr->sun_path, errno, strerror (errno));
  219. goto out;
  220. }
  221. }
  222. else {
  223. msg_warn ("%s is not a socket", addr->sun_path);
  224. goto out;
  225. }
  226. }
  227. }
  228. fd = socket (PF_LOCAL, type, 0);
  229. if (fd == -1) {
  230. msg_warn ("socket failed %s: %d, '%s'", addr->sun_path, errno, strerror (errno));
  231. return -1;
  232. }
  233. if (make_socket_nonblocking (fd) < 0) {
  234. goto out;
  235. }
  236. /* Set close on exec */
  237. if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) {
  238. msg_warn ("fcntl failed %s: %d, '%s'", addr->sun_path, errno, strerror (errno));
  239. goto out;
  240. }
  241. if (is_server) {
  242. setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
  243. r = bind (fd, (struct sockaddr *)addr, SUN_LEN (addr));
  244. }
  245. else {
  246. r = connect (fd, (struct sockaddr *)addr, SUN_LEN (addr));
  247. }
  248. if (r == -1) {
  249. if (errno != EINPROGRESS) {
  250. msg_warn ("bind/connect failed %s: %d, '%s'", addr->sun_path, errno, strerror (errno));
  251. goto out;
  252. }
  253. if (!async) {
  254. /* Try to poll */
  255. if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
  256. errno = ETIMEDOUT;
  257. msg_warn ("bind/connect failed %s: timeout", addr->sun_path);
  258. goto out;
  259. }
  260. else {
  261. /* Make synced again */
  262. if (make_socket_blocking (fd) < 0) {
  263. goto out;
  264. }
  265. }
  266. }
  267. }
  268. else {
  269. /* Still need to check SO_ERROR on socket */
  270. optlen = sizeof (s_error);
  271. getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
  272. if (s_error) {
  273. errno = s_error;
  274. goto out;
  275. }
  276. }
  277. return (fd);
  278. out:
  279. serrno = errno;
  280. if (fd != -1) {
  281. close (fd);
  282. }
  283. errno = serrno;
  284. return (-1);
  285. }
  286. /**
  287. * Make a universal socket
  288. * @param credits host, ip or path to unix socket
  289. * @param port port (used for network sockets)
  290. * @param async make this socket asynced
  291. * @param is_server make this socket as server socket
  292. * @param try_resolve try name resolution for a socket (BLOCKING)
  293. */
  294. gint
  295. make_universal_socket (const gchar *credits, guint16 port,
  296. gint type, gboolean async, gboolean is_server, gboolean try_resolve)
  297. {
  298. struct sockaddr_un un;
  299. struct stat st;
  300. struct addrinfo hints, *res;
  301. gint r;
  302. gchar portbuf[8];
  303. if (*credits == '/') {
  304. if (is_server) {
  305. return make_unix_socket (credits, &un, type, is_server, async);
  306. }
  307. else {
  308. r = stat (credits, &st);
  309. if (r == -1) {
  310. /* Unix socket doesn't exists it must be created first */
  311. errno = ENOENT;
  312. return -1;
  313. }
  314. else {
  315. if ((st.st_mode & S_IFSOCK) == 0) {
  316. /* Path is not valid socket */
  317. errno = EINVAL;
  318. return -1;
  319. }
  320. else {
  321. return make_unix_socket (credits, &un, type, is_server, async);
  322. }
  323. }
  324. }
  325. }
  326. else {
  327. /* TCP related part */
  328. memset (&hints, 0, sizeof (hints));
  329. hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
  330. hints.ai_socktype = type; /* Type of the socket */
  331. hints.ai_flags = is_server ? AI_PASSIVE : 0;
  332. hints.ai_protocol = 0; /* Any protocol */
  333. hints.ai_canonname = NULL;
  334. hints.ai_addr = NULL;
  335. hints.ai_next = NULL;
  336. if (!try_resolve) {
  337. hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
  338. }
  339. rspamd_snprintf (portbuf, sizeof (portbuf), "%d", (int)port);
  340. if ((r = getaddrinfo (credits, portbuf, &hints, &res)) == 0) {
  341. r = make_inet_socket (type, res, is_server, async, NULL);
  342. freeaddrinfo (res);
  343. return r;
  344. }
  345. else {
  346. msg_err ("address resolution for %s failed: %s", credits, gai_strerror (r));
  347. return FALSE;
  348. }
  349. }
  350. }
  351. /**
  352. * Make universal stream socket
  353. * @param credits host, ip or path to unix socket
  354. * @param port port (used for network sockets)
  355. * @param async make this socket asynced
  356. * @param is_server make this socket as server socket
  357. * @param try_resolve try name resolution for a socket (BLOCKING)
  358. */
  359. GList*
  360. make_universal_sockets_list (const gchar *credits, guint16 port,
  361. gint type, gboolean async, gboolean is_server, gboolean try_resolve)
  362. {
  363. struct sockaddr_un un;
  364. struct stat st;
  365. struct addrinfo hints, *res;
  366. gint r, fd, serrno;
  367. gchar portbuf[8], **strv, **cur;
  368. GList *result = NULL, *rcur;
  369. strv = g_strsplit_set (credits, ",", -1);
  370. if (strv == NULL) {
  371. msg_err ("invalid sockets credentials: %s", credits);
  372. return NULL;
  373. }
  374. cur = strv;
  375. while (*cur != NULL) {
  376. if (*credits == '/') {
  377. if (is_server) {
  378. fd = make_unix_socket (credits, &un, type, is_server, async);
  379. }
  380. else {
  381. r = stat (credits, &st);
  382. if (r == -1) {
  383. /* Unix socket doesn't exists it must be created first */
  384. errno = ENOENT;
  385. goto err;
  386. }
  387. else {
  388. if ((st.st_mode & S_IFSOCK) == 0) {
  389. /* Path is not valid socket */
  390. errno = EINVAL;
  391. goto err;
  392. }
  393. else {
  394. fd = make_unix_socket (credits, &un, type, is_server, async);
  395. }
  396. }
  397. }
  398. if (fd != -1) {
  399. result = g_list_prepend (result, GINT_TO_POINTER (fd));
  400. }
  401. else {
  402. goto err;
  403. }
  404. }
  405. else {
  406. /* TCP related part */
  407. memset (&hints, 0, sizeof (hints));
  408. hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
  409. hints.ai_socktype = type; /* Type of the socket */
  410. hints.ai_flags = is_server ? AI_PASSIVE : 0;
  411. hints.ai_protocol = 0; /* Any protocol */
  412. hints.ai_canonname = NULL;
  413. hints.ai_addr = NULL;
  414. hints.ai_next = NULL;
  415. if (!try_resolve) {
  416. hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
  417. }
  418. rspamd_snprintf (portbuf, sizeof (portbuf), "%d", (int)port);
  419. if ((r = getaddrinfo (credits, portbuf, &hints, &res)) == 0) {
  420. r = make_inet_socket (type, res, is_server, async, &result);
  421. freeaddrinfo (res);
  422. if (r == -1) {
  423. goto err;
  424. }
  425. }
  426. else {
  427. msg_err ("address resolution for %s failed: %s", credits, gai_strerror (r));
  428. goto err;
  429. }
  430. }
  431. cur ++;
  432. }
  433. g_strfreev (strv);
  434. return result;
  435. err:
  436. g_strfreev (strv);
  437. serrno = errno;
  438. rcur = result;
  439. while (rcur != NULL) {
  440. fd = GPOINTER_TO_INT (rcur->data);
  441. if (fd != -1) {
  442. close (fd);
  443. }
  444. rcur = g_list_next (rcur);
  445. }
  446. if (result != NULL) {
  447. g_list_free (result);
  448. }
  449. errno = serrno;
  450. return NULL;
  451. }
  452. gint
  453. make_socketpair (gint pair[2])
  454. {
  455. gint r;
  456. r = socketpair (AF_LOCAL, SOCK_STREAM, 0, pair);
  457. if (r == -1) {
  458. msg_warn ("socketpair failed: %d, '%s'", errno, strerror (errno), pair[0], pair[1]);
  459. return -1;
  460. }
  461. /* Set close on exec */
  462. if (fcntl (pair[0], F_SETFD, FD_CLOEXEC) == -1) {
  463. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  464. goto out;
  465. }
  466. if (fcntl (pair[1], F_SETFD, FD_CLOEXEC) == -1) {
  467. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  468. goto out;
  469. }
  470. return 0;
  471. out:
  472. close (pair[0]);
  473. close (pair[1]);
  474. return (-1);
  475. }
  476. gint
  477. write_pid (struct rspamd_main *main)
  478. {
  479. pid_t pid;
  480. if (main->cfg->pid_file == NULL) {
  481. return -1;
  482. }
  483. main->pfh = rspamd_pidfile_open (main->cfg->pid_file, 0644, &pid);
  484. if (main->pfh == NULL) {
  485. return -1;
  486. }
  487. if (main->is_privilleged) {
  488. /* Force root user as owner of pid file */
  489. #ifdef HAVE_PIDFILE_FILENO
  490. if (fchown (pidfile_fileno (main->pfh), 0, 0) == -1) {
  491. #else
  492. if (fchown (main->pfh->pf_fd, 0, 0) == -1) {
  493. #endif
  494. msg_err ("cannot chown of pidfile %s to 0:0 user", main->cfg->pid_file);
  495. }
  496. }
  497. rspamd_pidfile_write (main->pfh);
  498. return 0;
  499. }
  500. #ifdef HAVE_SA_SIGINFO
  501. void
  502. init_signals (struct sigaction *signals, void (*sig_handler)(gint, siginfo_t *, void *))
  503. #else
  504. void
  505. init_signals (struct sigaction *signals, void (*sig_handler)(gint))
  506. #endif
  507. {
  508. struct sigaction sigpipe_act;
  509. /* Setting up signal handlers */
  510. /* SIGUSR1 - reopen config file */
  511. /* SIGUSR2 - worker is ready for accept */
  512. sigemptyset (&signals->sa_mask);
  513. sigaddset (&signals->sa_mask, SIGTERM);
  514. sigaddset (&signals->sa_mask, SIGINT);
  515. sigaddset (&signals->sa_mask, SIGHUP);
  516. sigaddset (&signals->sa_mask, SIGCHLD);
  517. sigaddset (&signals->sa_mask, SIGUSR1);
  518. sigaddset (&signals->sa_mask, SIGUSR2);
  519. sigaddset (&signals->sa_mask, SIGALRM);
  520. #ifdef HAVE_SA_SIGINFO
  521. signals->sa_flags = SA_SIGINFO;
  522. signals->sa_handler = NULL;
  523. signals->sa_sigaction = sig_handler;
  524. #else
  525. signals->sa_handler = sig_handler;
  526. signals->sa_flags = 0;
  527. #endif
  528. sigaction (SIGTERM, signals, NULL);
  529. sigaction (SIGINT, signals, NULL);
  530. sigaction (SIGHUP, signals, NULL);
  531. sigaction (SIGCHLD, signals, NULL);
  532. sigaction (SIGUSR1, signals, NULL);
  533. sigaction (SIGUSR2, signals, NULL);
  534. sigaction (SIGALRM, signals, NULL);
  535. /* Ignore SIGPIPE as we handle write errors manually */
  536. sigemptyset (&sigpipe_act.sa_mask);
  537. sigaddset (&sigpipe_act.sa_mask, SIGPIPE);
  538. sigpipe_act.sa_handler = SIG_IGN;
  539. sigpipe_act.sa_flags = 0;
  540. sigaction (SIGPIPE, &sigpipe_act, NULL);
  541. }
  542. static void
  543. pass_signal_cb (gpointer key, gpointer value, gpointer ud)
  544. {
  545. struct rspamd_worker *cur = value;
  546. gint signo = GPOINTER_TO_INT (ud);
  547. kill (cur->pid, signo);
  548. }
  549. void
  550. pass_signal_worker (GHashTable * workers, gint signo)
  551. {
  552. g_hash_table_foreach (workers, pass_signal_cb, GINT_TO_POINTER (signo));
  553. }
  554. void
  555. convert_to_lowercase (gchar *str, guint size)
  556. {
  557. while (size--) {
  558. *str = g_ascii_tolower (*str);
  559. str++;
  560. }
  561. }
  562. #ifndef HAVE_SETPROCTITLE
  563. static gchar *title_buffer = 0;
  564. static size_t title_buffer_size = 0;
  565. static gchar *title_progname, *title_progname_full;
  566. gint
  567. setproctitle (const gchar *fmt, ...)
  568. {
  569. if (!title_buffer || !title_buffer_size) {
  570. errno = ENOMEM;
  571. return -1;
  572. }
  573. memset (title_buffer, '\0', title_buffer_size);
  574. ssize_t written;
  575. if (fmt) {
  576. ssize_t written2;
  577. va_list ap;
  578. written = snprintf (title_buffer, title_buffer_size, "%s: ", title_progname);
  579. if (written < 0 || (size_t) written >= title_buffer_size)
  580. return -1;
  581. va_start (ap, fmt);
  582. written2 = vsnprintf (title_buffer + written, title_buffer_size - written, fmt, ap);
  583. va_end (ap);
  584. if (written2 < 0 || (size_t) written2 >= title_buffer_size - written)
  585. return -1;
  586. }
  587. else {
  588. written = snprintf (title_buffer, title_buffer_size, "%s", title_progname);
  589. if (written < 0 || (size_t) written >= title_buffer_size)
  590. return -1;
  591. }
  592. written = strlen (title_buffer);
  593. memset (title_buffer + written, '\0', title_buffer_size - written);
  594. return 0;
  595. }
  596. /*
  597. It has to be _init function, because __attribute__((constructor))
  598. functions gets called without arguments.
  599. */
  600. gint
  601. init_title (gint argc, gchar *argv[], gchar *envp[])
  602. {
  603. #if defined(DARWIN) || defined(SOLARIS)
  604. /* XXX: try to handle these OSes too */
  605. return 0;
  606. #else
  607. gchar *begin_of_buffer = 0, *end_of_buffer = 0;
  608. gint i;
  609. for (i = 0; i < argc; ++i) {
  610. if (!begin_of_buffer)
  611. begin_of_buffer = argv[i];
  612. if (!end_of_buffer || end_of_buffer + 1 == argv[i])
  613. end_of_buffer = argv[i] + strlen (argv[i]);
  614. }
  615. for (i = 0; envp[i]; ++i) {
  616. if (!begin_of_buffer)
  617. begin_of_buffer = envp[i];
  618. if (!end_of_buffer || end_of_buffer + 1 == envp[i])
  619. end_of_buffer = envp[i] + strlen (envp[i]);
  620. }
  621. if (!end_of_buffer)
  622. return 0;
  623. gchar **new_environ = g_malloc ((i + 1) * sizeof (envp[0]));
  624. if (!new_environ)
  625. return 0;
  626. for (i = 0; envp[i]; ++i) {
  627. if (!(new_environ[i] = g_strdup (envp[i])))
  628. goto cleanup_enomem;
  629. }
  630. new_environ[i] = 0;
  631. if (program_invocation_name) {
  632. title_progname_full = g_strdup (program_invocation_name);
  633. if (!title_progname_full)
  634. goto cleanup_enomem;
  635. gchar *p = strrchr (title_progname_full, '/');
  636. if (p)
  637. title_progname = p + 1;
  638. else
  639. title_progname = title_progname_full;
  640. program_invocation_name = title_progname_full;
  641. program_invocation_short_name = title_progname;
  642. }
  643. environ = new_environ;
  644. title_buffer = begin_of_buffer;
  645. title_buffer_size = end_of_buffer - begin_of_buffer;
  646. return 0;
  647. cleanup_enomem:
  648. for (--i; i >= 0; --i) {
  649. g_free (new_environ[i]);
  650. }
  651. g_free (new_environ);
  652. return 0;
  653. #endif
  654. }
  655. #endif
  656. #ifndef HAVE_PIDFILE
  657. extern gchar *__progname;
  658. static gint _rspamd_pidfile_remove (rspamd_pidfh_t *pfh, gint freeit);
  659. static gint
  660. rspamd_pidfile_verify (rspamd_pidfh_t *pfh)
  661. {
  662. struct stat sb;
  663. if (pfh == NULL || pfh->pf_fd == -1)
  664. return (-1);
  665. /*
  666. * Check remembered descriptor.
  667. */
  668. if (fstat (pfh->pf_fd, &sb) == -1)
  669. return (errno);
  670. if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
  671. return -1;
  672. return 0;
  673. }
  674. static gint
  675. rspamd_pidfile_read (const gchar *path, pid_t * pidptr)
  676. {
  677. gchar buf[16], *endptr;
  678. gint error, fd, i;
  679. fd = open (path, O_RDONLY);
  680. if (fd == -1)
  681. return (errno);
  682. i = read (fd, buf, sizeof (buf) - 1);
  683. error = errno; /* Remember errno in case close() wants to change it. */
  684. close (fd);
  685. if (i == -1)
  686. return error;
  687. else if (i == 0)
  688. return EAGAIN;
  689. buf[i] = '\0';
  690. *pidptr = strtol (buf, &endptr, 10);
  691. if (endptr != &buf[i])
  692. return EINVAL;
  693. return 0;
  694. }
  695. rspamd_pidfh_t *
  696. rspamd_pidfile_open (const gchar *path, mode_t mode, pid_t * pidptr)
  697. {
  698. rspamd_pidfh_t *pfh;
  699. struct stat sb;
  700. gint error, fd, len, count;
  701. struct timespec rqtp;
  702. pfh = g_malloc (sizeof (*pfh));
  703. if (pfh == NULL)
  704. return NULL;
  705. if (path == NULL)
  706. len = snprintf (pfh->pf_path, sizeof (pfh->pf_path), "/var/run/%s.pid", g_get_prgname ());
  707. else
  708. len = snprintf (pfh->pf_path, sizeof (pfh->pf_path), "%s", path);
  709. if (len >= (gint)sizeof (pfh->pf_path)) {
  710. g_free (pfh);
  711. errno = ENAMETOOLONG;
  712. return NULL;
  713. }
  714. /*
  715. * Open the PID file and obtain exclusive lock.
  716. * We truncate PID file here only to remove old PID immediatelly,
  717. * PID file will be truncated again in pidfile_write(), so
  718. * pidfile_write() can be called multiple times.
  719. */
  720. fd = open (pfh->pf_path, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
  721. lock_file (fd, TRUE);
  722. if (fd == -1) {
  723. count = 0;
  724. rqtp.tv_sec = 0;
  725. rqtp.tv_nsec = 5000000;
  726. if (errno == EWOULDBLOCK && pidptr != NULL) {
  727. again:
  728. errno = rspamd_pidfile_read (pfh->pf_path, pidptr);
  729. if (errno == 0)
  730. errno = EEXIST;
  731. else if (errno == EAGAIN) {
  732. if (++count <= 3) {
  733. nanosleep (&rqtp, 0);
  734. goto again;
  735. }
  736. }
  737. }
  738. g_free (pfh);
  739. return NULL;
  740. }
  741. /*
  742. * Remember file information, so in pidfile_write() we are sure we write
  743. * to the proper descriptor.
  744. */
  745. if (fstat (fd, &sb) == -1) {
  746. error = errno;
  747. unlink (pfh->pf_path);
  748. close (fd);
  749. g_free (pfh);
  750. errno = error;
  751. return NULL;
  752. }
  753. pfh->pf_fd = fd;
  754. pfh->pf_dev = sb.st_dev;
  755. pfh->pf_ino = sb.st_ino;
  756. return pfh;
  757. }
  758. gint
  759. rspamd_pidfile_write (rspamd_pidfh_t *pfh)
  760. {
  761. gchar pidstr[16];
  762. gint error, fd;
  763. /*
  764. * Check remembered descriptor, so we don't overwrite some other
  765. * file if pidfile was closed and descriptor reused.
  766. */
  767. errno = rspamd_pidfile_verify (pfh);
  768. if (errno != 0) {
  769. /*
  770. * Don't close descriptor, because we are not sure if it's ours.
  771. */
  772. return -1;
  773. }
  774. fd = pfh->pf_fd;
  775. /*
  776. * Truncate PID file, so multiple calls of pidfile_write() are allowed.
  777. */
  778. if (ftruncate (fd, 0) == -1) {
  779. error = errno;
  780. _rspamd_pidfile_remove (pfh, 0);
  781. errno = error;
  782. return -1;
  783. }
  784. rspamd_snprintf (pidstr, sizeof (pidstr), "%P", getpid ());
  785. if (pwrite (fd, pidstr, strlen (pidstr), 0) != (ssize_t) strlen (pidstr)) {
  786. error = errno;
  787. _rspamd_pidfile_remove (pfh, 0);
  788. errno = error;
  789. return -1;
  790. }
  791. return 0;
  792. }
  793. gint
  794. rspamd_pidfile_close (rspamd_pidfh_t *pfh)
  795. {
  796. gint error;
  797. error = rspamd_pidfile_verify (pfh);
  798. if (error != 0) {
  799. errno = error;
  800. return -1;
  801. }
  802. if (close (pfh->pf_fd) == -1)
  803. error = errno;
  804. g_free (pfh);
  805. if (error != 0) {
  806. errno = error;
  807. return -1;
  808. }
  809. return 0;
  810. }
  811. static gint
  812. _rspamd_pidfile_remove (rspamd_pidfh_t *pfh, gint freeit)
  813. {
  814. gint error;
  815. error = rspamd_pidfile_verify (pfh);
  816. if (error != 0) {
  817. errno = error;
  818. return -1;
  819. }
  820. if (unlink (pfh->pf_path) == -1)
  821. error = errno;
  822. if (!unlock_file (pfh->pf_fd, FALSE)) {
  823. if (error == 0)
  824. error = errno;
  825. }
  826. if (close (pfh->pf_fd) == -1) {
  827. if (error == 0)
  828. error = errno;
  829. }
  830. if (freeit)
  831. g_free (pfh);
  832. else
  833. pfh->pf_fd = -1;
  834. if (error != 0) {
  835. errno = error;
  836. return -1;
  837. }
  838. return 0;
  839. }
  840. gint
  841. rspamd_pidfile_remove (rspamd_pidfh_t *pfh)
  842. {
  843. return (_rspamd_pidfile_remove (pfh, 1));
  844. }
  845. #endif
  846. /* Replace %r with rcpt value and %f with from value, new string is allocated in pool */
  847. gchar *
  848. resolve_stat_filename (memory_pool_t * pool, gchar *pattern, gchar *rcpt, gchar *from)
  849. {
  850. gint need_to_format = 0, len = 0;
  851. gint rcptlen, fromlen;
  852. gchar *c = pattern, *new, *s;
  853. if (rcpt) {
  854. rcptlen = strlen (rcpt);
  855. }
  856. else {
  857. rcptlen = 0;
  858. }
  859. if (from) {
  860. fromlen = strlen (from);
  861. }
  862. else {
  863. fromlen = 0;
  864. }
  865. /* Calculate length */
  866. while (*c++) {
  867. if (*c == '%' && *(c + 1) == 'r') {
  868. len += rcptlen;
  869. c += 2;
  870. need_to_format = 1;
  871. continue;
  872. }
  873. else if (*c == '%' && *(c + 1) == 'f') {
  874. len += fromlen;
  875. c += 2;
  876. need_to_format = 1;
  877. continue;
  878. }
  879. len++;
  880. }
  881. /* Do not allocate extra memory if we do not need to format string */
  882. if (!need_to_format) {
  883. return pattern;
  884. }
  885. /* Allocate new string */
  886. new = memory_pool_alloc (pool, len);
  887. c = pattern;
  888. s = new;
  889. /* Format string */
  890. while (*c++) {
  891. if (*c == '%' && *(c + 1) == 'r') {
  892. c += 2;
  893. memcpy (s, rcpt, rcptlen);
  894. s += rcptlen;
  895. continue;
  896. }
  897. else if (*c == '%' && *(c + 1) == 'r') {
  898. c += 2;
  899. memcpy (s, from, fromlen);
  900. s += fromlen;
  901. continue;
  902. }
  903. *s++ = *c;
  904. }
  905. *s = '\0';
  906. return new;
  907. }
  908. #ifdef HAVE_CLOCK_GETTIME
  909. const gchar *
  910. calculate_check_time (struct timeval *tv, struct timespec *begin, gint resolution, guint32 *scan_time)
  911. #else
  912. const gchar *
  913. calculate_check_time (struct timeval *begin, gint resolution, guint32 *scan_time)
  914. #endif
  915. {
  916. double vdiff, diff;
  917. static gchar res[64];
  918. static gchar fmt[sizeof ("%.10f ms real, %.10f ms virtual")];
  919. struct timeval tv_now;
  920. if (gettimeofday (&tv_now, NULL) == -1) {
  921. msg_warn ("gettimeofday failed: %s", strerror (errno));
  922. }
  923. #ifdef HAVE_CLOCK_GETTIME
  924. struct timespec ts;
  925. diff = (tv_now.tv_sec - tv->tv_sec) * 1000. + /* Seconds */
  926. (tv_now.tv_usec - tv->tv_usec) / 1000.; /* Microseconds */
  927. #ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID
  928. clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts);
  929. #elif defined(HAVE_CLOCK_VIRTUAL)
  930. clock_gettime (CLOCK_VIRTUAL, &ts);
  931. #else
  932. clock_gettime (CLOCK_REALTIME, &ts);
  933. #endif
  934. vdiff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */
  935. (ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */
  936. #else
  937. diff = (tv_now.tv_sec - begin->tv_sec) * 1000. + /* Seconds */
  938. (tv_now.tv_usec - begin->tv_usec) / 1000.; /* Microseconds */
  939. vdiff = diff;
  940. #endif
  941. *scan_time = diff;
  942. sprintf (fmt, "%%.%dfms real, %%.%dfms virtual", resolution, resolution);
  943. snprintf (res, sizeof (res), fmt, diff, vdiff);
  944. return (const gchar *)res;
  945. }
  946. #ifndef g_tolower
  947. # define g_tolower(x) (((x) >= 'A' && (x) <= 'Z') ? (x) - 'A' + 'a' : (x))
  948. #endif
  949. gboolean
  950. rspamd_strcase_equal (gconstpointer v, gconstpointer v2)
  951. {
  952. if (g_ascii_strcasecmp ((const gchar *)v, (const gchar *)v2) == 0) {
  953. return TRUE;
  954. }
  955. return FALSE;
  956. }
  957. guint
  958. rspamd_strcase_hash (gconstpointer key)
  959. {
  960. const gchar *p = key;
  961. gchar buf[256];
  962. guint h = 0, i = 0;
  963. while (*p != '\0') {
  964. buf[i] = g_ascii_tolower (*p);
  965. i++;
  966. p++;
  967. if (i == sizeof (buf)) {
  968. h ^= murmur32_hash (buf, i);
  969. i = 0;
  970. }
  971. }
  972. if (i > 0) {
  973. h ^= murmur32_hash (buf, i);
  974. }
  975. return h;
  976. }
  977. guint
  978. rspamd_str_hash (gconstpointer key)
  979. {
  980. gsize len;
  981. len = strlen ((const gchar *)key);
  982. return murmur32_hash (key, len);
  983. }
  984. gboolean
  985. rspamd_str_equal (gconstpointer v, gconstpointer v2)
  986. {
  987. return strcmp ((const gchar *)v, (const gchar *)v2) == 0;
  988. }
  989. gboolean
  990. fstr_strcase_equal (gconstpointer v, gconstpointer v2)
  991. {
  992. const f_str_t *f1 = v, *f2 = v2;
  993. if (f1->len == f2->len && g_ascii_strncasecmp (f1->begin, f2->begin, f1->len) == 0) {
  994. return TRUE;
  995. }
  996. return FALSE;
  997. }
  998. guint
  999. fstr_strcase_hash (gconstpointer key)
  1000. {
  1001. const f_str_t *f = key;
  1002. const gchar *p;
  1003. guint h = 0, i = 0;
  1004. gchar buf[256];
  1005. p = f->begin;
  1006. while (p - f->begin < (gint)f->len) {
  1007. buf[i] = g_ascii_tolower (*p);
  1008. i++;
  1009. p++;
  1010. if (i == sizeof (buf)) {
  1011. h ^= murmur32_hash (buf, i);
  1012. i = 0;
  1013. }
  1014. }
  1015. if (i > 0) {
  1016. h ^= murmur32_hash (buf, i);
  1017. }
  1018. return h;
  1019. }
  1020. void
  1021. gperf_profiler_init (struct config_file *cfg, const gchar *descr)
  1022. {
  1023. #if defined(WITH_GPERF_TOOLS)
  1024. gchar prof_path[PATH_MAX];
  1025. if (getenv ("CPUPROFILE")) {
  1026. /* disable inherited Profiler enabled in master process */
  1027. ProfilerStop ();
  1028. }
  1029. /* Try to create temp directory for gmon.out and chdir to it */
  1030. if (cfg->profile_path == NULL) {
  1031. cfg->profile_path = g_strdup_printf ("%s/rspamd-profile", cfg->temp_dir);
  1032. }
  1033. snprintf (prof_path, sizeof (prof_path), "%s-%s.%d", cfg->profile_path, descr, (gint)getpid ());
  1034. if (ProfilerStart (prof_path)) {
  1035. /* start ITIMER_PROF timer */
  1036. ProfilerRegisterThread ();
  1037. }
  1038. else {
  1039. msg_warn ("cannot start google perftools profiler");
  1040. }
  1041. #endif
  1042. }
  1043. #ifdef HAVE_FLOCK
  1044. /* Flock version */
  1045. gboolean
  1046. lock_file (gint fd, gboolean async)
  1047. {
  1048. gint flags;
  1049. if (async) {
  1050. flags = LOCK_EX | LOCK_NB;
  1051. }
  1052. else {
  1053. flags = LOCK_EX;
  1054. }
  1055. if (flock (fd, flags) == -1) {
  1056. if (async && errno == EAGAIN) {
  1057. return FALSE;
  1058. }
  1059. msg_warn ("lock on file failed: %s", strerror (errno));
  1060. return FALSE;
  1061. }
  1062. return TRUE;
  1063. }
  1064. gboolean
  1065. unlock_file (gint fd, gboolean async)
  1066. {
  1067. gint flags;
  1068. if (async) {
  1069. flags = LOCK_UN | LOCK_NB;
  1070. }
  1071. else {
  1072. flags = LOCK_UN;
  1073. }
  1074. if (flock (fd, flags) == -1) {
  1075. if (async && errno == EAGAIN) {
  1076. return FALSE;
  1077. }
  1078. msg_warn ("lock on file failed: %s", strerror (errno));
  1079. return FALSE;
  1080. }
  1081. return TRUE;
  1082. }
  1083. #else /* HAVE_FLOCK */
  1084. /* Fctnl version */
  1085. gboolean
  1086. lock_file (gint fd, gboolean async)
  1087. {
  1088. struct flock fl = {
  1089. .l_type = F_WRLCK,
  1090. .l_whence = SEEK_SET,
  1091. .l_start = 0,
  1092. .l_len = 0
  1093. };
  1094. if (fcntl (fd, async ? F_SETLK : F_SETLKW, &fl) == -1) {
  1095. if (async && (errno == EAGAIN || errno == EACCES)) {
  1096. return FALSE;
  1097. }
  1098. msg_warn ("lock on file failed: %s", strerror (errno));
  1099. return FALSE;
  1100. }
  1101. return TRUE;
  1102. }
  1103. gboolean
  1104. unlock_file (gint fd, gboolean async)
  1105. {
  1106. struct flock fl = {
  1107. .l_type = F_UNLCK,
  1108. .l_whence = SEEK_SET,
  1109. .l_start = 0,
  1110. .l_len = 0
  1111. };
  1112. if (fcntl (fd, async ? F_SETLK : F_SETLKW, &fl) == -1) {
  1113. if (async && (errno == EAGAIN || errno == EACCES)) {
  1114. return FALSE;
  1115. }
  1116. msg_warn ("lock on file failed: %s", strerror (errno));
  1117. return FALSE;
  1118. }
  1119. return TRUE;
  1120. }
  1121. #endif /* HAVE_FLOCK */
  1122. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 22))
  1123. void
  1124. g_ptr_array_unref (GPtrArray *array)
  1125. {
  1126. g_ptr_array_free (array, TRUE);
  1127. }
  1128. #endif
  1129. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 14))
  1130. void
  1131. g_queue_clear (GQueue *queue)
  1132. {
  1133. g_return_if_fail (queue != NULL);
  1134. g_list_free (queue->head);
  1135. queue->head = queue->tail = NULL;
  1136. queue->length = 0;
  1137. }
  1138. #endif
  1139. gsize
  1140. rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz)
  1141. {
  1142. gchar *d = dst;
  1143. const gchar *s = src;
  1144. gsize n = siz;
  1145. /* Copy as many bytes as will fit */
  1146. if (n != 0) {
  1147. while (--n != 0) {
  1148. if ((*d++ = *s++) == '\0') {
  1149. break;
  1150. }
  1151. }
  1152. }
  1153. if (n == 0 && siz != 0) {
  1154. *d = '\0';
  1155. }
  1156. return (s - src - 1); /* count does not include NUL */
  1157. }
  1158. gsize
  1159. rspamd_strlcpy_tolower (gchar *dst, const gchar *src, gsize siz)
  1160. {
  1161. gchar *d = dst;
  1162. const gchar *s = src;
  1163. gsize n = siz;
  1164. /* Copy as many bytes as will fit */
  1165. if (n != 0) {
  1166. while (--n != 0) {
  1167. if ((*d++ = g_ascii_tolower (*s++)) == '\0') {
  1168. break;
  1169. }
  1170. }
  1171. }
  1172. if (n == 0 && siz != 0) {
  1173. *d = '\0';
  1174. }
  1175. return (s - src - 1); /* count does not include NUL */
  1176. }
  1177. /* Compare two emails for building emails tree */
  1178. gint
  1179. compare_email_func (gconstpointer a, gconstpointer b)
  1180. {
  1181. const struct uri *u1 = a, *u2 = b;
  1182. gint r;
  1183. if (u1->hostlen != u2->hostlen || u1->hostlen == 0) {
  1184. return u1->hostlen - u2->hostlen;
  1185. }
  1186. else {
  1187. if ((r = g_ascii_strncasecmp (u1->host, u2->host, u1->hostlen)) == 0){
  1188. if (u1->userlen != u2->userlen || u1->userlen == 0) {
  1189. return u1->userlen - u2->userlen;
  1190. }
  1191. else {
  1192. return g_ascii_strncasecmp (u1->user, u2->user, u1->userlen);
  1193. }
  1194. }
  1195. else {
  1196. return r;
  1197. }
  1198. }
  1199. return 0;
  1200. }
  1201. gint
  1202. compare_url_func (gconstpointer a, gconstpointer b)
  1203. {
  1204. const struct uri *u1 = a, *u2 = b;
  1205. int r;
  1206. if (u1->hostlen != u2->hostlen || u1->hostlen == 0) {
  1207. return u1->hostlen - u2->hostlen;
  1208. }
  1209. else {
  1210. r = g_ascii_strncasecmp (u1->host, u2->host, u1->hostlen);
  1211. if (r == 0 && u1->is_phished != u2->is_phished) {
  1212. /* Always insert phished urls to the tree */
  1213. return -1;
  1214. }
  1215. }
  1216. return r;
  1217. }
  1218. /*
  1219. * Find the first occurrence of find in s, ignore case.
  1220. */
  1221. gchar *
  1222. rspamd_strncasestr (const gchar *s, const gchar *find, gint len)
  1223. {
  1224. gchar c, sc;
  1225. gsize mlen;
  1226. if ((c = *find++) != 0) {
  1227. c = g_ascii_tolower (c);
  1228. mlen = strlen (find);
  1229. do {
  1230. do {
  1231. if ((sc = *s++) == 0 || len -- == 0)
  1232. return (NULL);
  1233. } while (g_ascii_tolower (sc) != c);
  1234. } while (g_ascii_strncasecmp (s, find, mlen) != 0);
  1235. s--;
  1236. }
  1237. return ((gchar *)s);
  1238. }
  1239. /*
  1240. * Try to convert string of length to long
  1241. */
  1242. gboolean
  1243. rspamd_strtol (const gchar *s, gsize len, glong *value)
  1244. {
  1245. const gchar *p = s, *end = s + len;
  1246. gchar c;
  1247. glong v = 0;
  1248. const glong cutoff = G_MAXLONG / 10, cutlim = G_MAXLONG % 10;
  1249. gboolean neg;
  1250. /* Case negative values */
  1251. if (*p == '-') {
  1252. neg = TRUE;
  1253. p ++;
  1254. }
  1255. else {
  1256. neg = FALSE;
  1257. }
  1258. /* Some preparations for range errors */
  1259. while (p < end) {
  1260. c = *p;
  1261. if (c >= '0' && c <= '9') {
  1262. c -= '0';
  1263. if (v > cutoff || (v == cutoff && c > cutlim)) {
  1264. /* Range error */
  1265. *value = neg ? G_MINLONG : G_MAXLONG;
  1266. return FALSE;
  1267. }
  1268. else {
  1269. v *= 10;
  1270. v += c;
  1271. }
  1272. }
  1273. else {
  1274. return FALSE;
  1275. }
  1276. p ++;
  1277. }
  1278. *value = neg ? -(v) : v;
  1279. return TRUE;
  1280. }
  1281. /*
  1282. * Try to convert string of length to long
  1283. */
  1284. gboolean
  1285. rspamd_strtoul (const gchar *s, gsize len, gulong *value)
  1286. {
  1287. const gchar *p = s, *end = s + len;
  1288. gchar c;
  1289. gulong v = 0;
  1290. const gulong cutoff = G_MAXULONG / 10, cutlim = G_MAXULONG % 10;
  1291. /* Some preparations for range errors */
  1292. while (p < end) {
  1293. c = *p;
  1294. if (c >= '0' && c <= '9') {
  1295. c -= '0';
  1296. if (v > cutoff || (v == cutoff && (guint8)c > cutlim)) {
  1297. /* Range error */
  1298. *value = G_MAXULONG;
  1299. return FALSE;
  1300. }
  1301. else {
  1302. v *= 10;
  1303. v += c;
  1304. }
  1305. }
  1306. else {
  1307. return FALSE;
  1308. }
  1309. p ++;
  1310. }
  1311. *value = v;
  1312. return TRUE;
  1313. }
  1314. gint
  1315. rspamd_fallocate (gint fd, off_t offset, off_t len)
  1316. {
  1317. #if defined(HAVE_FALLOCATE)
  1318. return fallocate (fd, 0, offset, len);
  1319. #elif defined(HAVE_POSIX_FALLOCATE)
  1320. return posix_fallocate (fd, offset, len);
  1321. #else
  1322. /* Return 0 as nothing can be done on this system */
  1323. return 0;
  1324. #endif
  1325. }
  1326. /**
  1327. * Create new mutex
  1328. * @return mutex or NULL
  1329. */
  1330. inline rspamd_mutex_t*
  1331. rspamd_mutex_new (void)
  1332. {
  1333. rspamd_mutex_t *new;
  1334. new = g_slice_alloc (sizeof (rspamd_mutex_t));
  1335. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1336. g_mutex_init (&new->mtx);
  1337. #else
  1338. g_static_mutex_init (&new->mtx);
  1339. #endif
  1340. return new;
  1341. }
  1342. /**
  1343. * Lock mutex
  1344. * @param mtx
  1345. */
  1346. inline void
  1347. rspamd_mutex_lock (rspamd_mutex_t *mtx)
  1348. {
  1349. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1350. g_mutex_lock (&mtx->mtx);
  1351. #else
  1352. g_static_mutex_lock (&mtx->mtx);
  1353. #endif
  1354. }
  1355. /**
  1356. * Unlock mutex
  1357. * @param mtx
  1358. */
  1359. inline void
  1360. rspamd_mutex_unlock (rspamd_mutex_t *mtx)
  1361. {
  1362. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1363. g_mutex_unlock (&mtx->mtx);
  1364. #else
  1365. g_static_mutex_unlock (&mtx->mtx);
  1366. #endif
  1367. }
  1368. void
  1369. rspamd_mutex_free (rspamd_mutex_t *mtx)
  1370. {
  1371. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1372. g_mutex_clear (&mtx->mtx);
  1373. #endif
  1374. g_slice_free1 (sizeof (rspamd_mutex_t), mtx);
  1375. }
  1376. /**
  1377. * Create new rwlock
  1378. * @return
  1379. */
  1380. rspamd_rwlock_t*
  1381. rspamd_rwlock_new (void)
  1382. {
  1383. rspamd_rwlock_t *new;
  1384. new = g_malloc (sizeof (rspamd_rwlock_t));
  1385. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1386. g_rw_lock_init (&new->rwlock);
  1387. #else
  1388. g_static_rw_lock_init (&new->rwlock);
  1389. #endif
  1390. return new;
  1391. }
  1392. /**
  1393. * Lock rwlock for writing
  1394. * @param mtx
  1395. */
  1396. inline void
  1397. rspamd_rwlock_writer_lock (rspamd_rwlock_t *mtx)
  1398. {
  1399. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1400. g_rw_lock_writer_lock (&mtx->rwlock);
  1401. #else
  1402. g_static_rw_lock_writer_lock (&mtx->rwlock);
  1403. #endif
  1404. }
  1405. /**
  1406. * Lock rwlock for reading
  1407. * @param mtx
  1408. */
  1409. inline void
  1410. rspamd_rwlock_reader_lock (rspamd_rwlock_t *mtx)
  1411. {
  1412. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1413. g_rw_lock_reader_lock (&mtx->rwlock);
  1414. #else
  1415. g_static_rw_lock_reader_lock (&mtx->rwlock);
  1416. #endif
  1417. }
  1418. /**
  1419. * Unlock rwlock from writing
  1420. * @param mtx
  1421. */
  1422. inline void
  1423. rspamd_rwlock_writer_unlock (rspamd_rwlock_t *mtx)
  1424. {
  1425. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1426. g_rw_lock_writer_unlock (&mtx->rwlock);
  1427. #else
  1428. g_static_rw_lock_writer_unlock (&mtx->rwlock);
  1429. #endif
  1430. }
  1431. /**
  1432. * Unlock rwlock from reading
  1433. * @param mtx
  1434. */
  1435. inline void
  1436. rspamd_rwlock_reader_unlock (rspamd_rwlock_t *mtx)
  1437. {
  1438. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1439. g_rw_lock_reader_unlock (&mtx->rwlock);
  1440. #else
  1441. g_static_rw_lock_reader_unlock (&mtx->rwlock);
  1442. #endif
  1443. }
  1444. void
  1445. rspamd_rwlock_free (rspamd_rwlock_t *mtx)
  1446. {
  1447. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1448. g_rw_lock_clear (&mtx->rwlock);
  1449. #endif
  1450. g_slice_free1 (sizeof (rspamd_rwlock_t), mtx);
  1451. }
  1452. struct rspamd_thread_data {
  1453. gchar *name;
  1454. gint id;
  1455. GThreadFunc func;
  1456. gpointer data;
  1457. };
  1458. static gpointer
  1459. rspamd_thread_func (gpointer ud)
  1460. {
  1461. struct rspamd_thread_data *td = ud;
  1462. sigset_t s_mask;
  1463. /* Ignore signals in thread */
  1464. sigemptyset (&s_mask);
  1465. sigaddset (&s_mask, SIGTERM);
  1466. sigaddset (&s_mask, SIGINT);
  1467. sigaddset (&s_mask, SIGHUP);
  1468. sigaddset (&s_mask, SIGCHLD);
  1469. sigaddset (&s_mask, SIGUSR1);
  1470. sigaddset (&s_mask, SIGUSR2);
  1471. sigaddset (&s_mask, SIGALRM);
  1472. sigaddset (&s_mask, SIGPIPE);
  1473. sigprocmask (SIG_BLOCK, &s_mask, NULL);
  1474. ud = td->func (td->data);
  1475. g_free (td->name);
  1476. g_free (td);
  1477. return ud;
  1478. }
  1479. /**
  1480. * Create new named thread
  1481. * @param name name pattern
  1482. * @param func function to start
  1483. * @param data data to pass to function
  1484. * @param err error pointer
  1485. * @return new thread object that can be joined
  1486. */
  1487. GThread*
  1488. rspamd_create_thread (const gchar *name, GThreadFunc func, gpointer data, GError **err)
  1489. {
  1490. GThread *new;
  1491. struct rspamd_thread_data *td;
  1492. static gint32 id;
  1493. guint r;
  1494. r = strlen (name);
  1495. td = g_malloc (sizeof (struct rspamd_thread_data));
  1496. td->id = ++id;
  1497. td->name = g_malloc (r + sizeof ("4294967296"));
  1498. td->func = func;
  1499. td->data = data;
  1500. rspamd_snprintf (td->name, r + sizeof ("4294967296"), "%s-%d", name, id);
  1501. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1502. new = g_thread_try_new (td->name, rspamd_thread_func, td, err);
  1503. #else
  1504. new = g_thread_create (rspamd_thread_func, td, TRUE, err);
  1505. #endif
  1506. return new;
  1507. }
  1508. guint32
  1509. murmur32_hash (const guint8 *in, gsize len)
  1510. {
  1511. const guint32 c1 = 0xcc9e2d51;
  1512. const guint32 c2 = 0x1b873593;
  1513. const int nblocks = len / 4;
  1514. const guint32 *blocks = (const guint32 *)(in);
  1515. const guint8 *tail;
  1516. guint32 h = 0;
  1517. gint i;
  1518. guint32 k;
  1519. if (in == NULL || len == 0) {
  1520. return 0;
  1521. }
  1522. tail = (const guint8 *)(in + (nblocks * 4));
  1523. for (i = 0; i < nblocks; i++) {
  1524. k = blocks[i];
  1525. k *= c1;
  1526. k = (k << 15) | (k >> (32 - 15));
  1527. k *= c2;
  1528. h ^= k;
  1529. h = (h << 13) | (h >> (32 - 13));
  1530. h = (h * 5) + 0xe6546b64;
  1531. }
  1532. k = 0;
  1533. switch (len & 3) {
  1534. case 3:
  1535. k ^= tail[2] << 16;
  1536. case 2:
  1537. k ^= tail[1] << 8;
  1538. case 1:
  1539. k ^= tail[0];
  1540. k *= c1;
  1541. k = (k << 13) | (k >> (32 - 15));
  1542. k *= c2;
  1543. h ^= k;
  1544. };
  1545. h ^= len;
  1546. h ^= h >> 16;
  1547. h *= 0x85ebca6b;
  1548. h ^= h >> 13;
  1549. h *= 0xc2b2ae35;
  1550. h ^= h >> 16;
  1551. return h;
  1552. }
  1553. void
  1554. murmur128_hash (const guint8 *in, gsize len, guint64 out[])
  1555. {
  1556. const guint64 c1 = 0x87c37b91114253d5ULL;
  1557. const guint64 c2 = 0x4cf5ad432745937fULL;
  1558. const gint nblocks = len / 16;
  1559. const guint64 *blocks = (const guint64 *)(in);
  1560. const guint8 *tail;
  1561. guint64 h1 = 0;
  1562. guint64 h2 = 0;
  1563. int i;
  1564. guint64 k1, k2;
  1565. if (in == NULL || len == 0 || out == NULL) {
  1566. return;
  1567. }
  1568. tail = (const guint8 *)(in + (nblocks * 16));
  1569. for (i = 0; i < nblocks; i++) {
  1570. k1 = blocks[i*2+0];
  1571. k2 = blocks[i*2+1];
  1572. k1 *= c1;
  1573. k1 = (k1 << 31) | (k1 >> (64 - 31));
  1574. k1 *= c2;
  1575. h1 ^= k1;
  1576. h1 = (h1 << 27) | (h1 >> (64 - 27));
  1577. h1 += h2;
  1578. h1 = h1*5+0x52dce729;
  1579. k2 *= c2;
  1580. k2 = (k2 << 33) | (k2 >> (64 - 33));
  1581. k2 *= c1;
  1582. h2 ^= k2;
  1583. h2 = (h2 << 31) | (h2 >> (64 - 31));
  1584. h2 += h1;
  1585. h2 = h2*5+0x38495ab5;
  1586. }
  1587. k1 = k2 = 0;
  1588. switch (len & 15) {
  1589. case 15:
  1590. k2 ^= (guint64)(tail[14]) << 48;
  1591. case 14:
  1592. k2 ^= (guint64)(tail[13]) << 40;
  1593. case 13:
  1594. k2 ^= (guint64)(tail[12]) << 32;
  1595. case 12:
  1596. k2 ^= (guint64)(tail[11]) << 24;
  1597. case 11:
  1598. k2 ^= (guint64)(tail[10]) << 16;
  1599. case 10:
  1600. k2 ^= (guint64)(tail[ 9]) << 8;
  1601. case 9:
  1602. k2 ^= (guint64)(tail[ 8]) << 0;
  1603. k2 *= c2;
  1604. k2 = (k2 << 33) | (k2 >> (64 - 33));
  1605. k2 *= c1;
  1606. h2 ^= k2;
  1607. case 8:
  1608. k1 ^= (guint64)(tail[ 7]) << 56;
  1609. case 7:
  1610. k1 ^= (guint64)(tail[ 6]) << 48;
  1611. case 6:
  1612. k1 ^= (guint64)(tail[ 5]) << 40;
  1613. case 5:
  1614. k1 ^= (guint64)(tail[ 4]) << 32;
  1615. case 4:
  1616. k1 ^= (guint64)(tail[ 3]) << 24;
  1617. case 3:
  1618. k1 ^= (guint64)(tail[ 2]) << 16;
  1619. case 2:
  1620. k1 ^= (guint64)(tail[ 1]) << 8;
  1621. case 1:
  1622. k1 ^= (guint64)(tail[ 0]) << 0;
  1623. k1 *= c1;
  1624. k1 = (k1 << 31) | (k1 >> (64 - 31));
  1625. k1 *= c2;
  1626. h1 ^= k1;
  1627. };
  1628. //----------
  1629. // finalization
  1630. h1 ^= len;
  1631. h2 ^= len;
  1632. h1 += h2;
  1633. h2 += h1;
  1634. h1 ^= h1 >> 33;
  1635. h1 *= 0xff51afd7ed558ccdULL;
  1636. h1 ^= h1 >> 33;
  1637. h1 *= 0xc4ceb9fe1a85ec53ULL;
  1638. h1 ^= h1 >> 33;
  1639. h2 ^= h2 >> 33;
  1640. h2 *= 0xff51afd7ed558ccdULL;
  1641. h2 ^= h2 >> 33;
  1642. h2 *= 0xc4ceb9fe1a85ec53ULL;
  1643. h2 ^= h2 >> 33;
  1644. h1 += h2;
  1645. h2 += h1;
  1646. out[0] = h1;
  1647. out[1] = h2;
  1648. }
  1649. struct hash_copy_callback_data {
  1650. gpointer (*key_copy_func)(gconstpointer data, gpointer ud);
  1651. gpointer (*value_copy_func)(gconstpointer data, gpointer ud);
  1652. gpointer ud;
  1653. GHashTable *dst;
  1654. };
  1655. static void
  1656. copy_foreach_callback (gpointer key, gpointer value, gpointer ud)
  1657. {
  1658. struct hash_copy_callback_data *cb = ud;
  1659. gpointer nkey, nvalue;
  1660. nkey = cb->key_copy_func ? cb->key_copy_func (key, cb->ud) : (gpointer)key;
  1661. nvalue = cb->value_copy_func ? cb->value_copy_func (value, cb->ud) : (gpointer)value;
  1662. g_hash_table_insert (cb->dst, nkey, nvalue);
  1663. }
  1664. /**
  1665. * Deep copy of one hash table to another
  1666. * @param src source hash
  1667. * @param dst destination hash
  1668. * @param key_copy_func function called to copy or modify keys (or NULL)
  1669. * @param value_copy_func function called to copy or modify values (or NULL)
  1670. * @param ud user data for copy functions
  1671. */
  1672. void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst,
  1673. gpointer (*key_copy_func)(gconstpointer data, gpointer ud),
  1674. gpointer (*value_copy_func)(gconstpointer data, gpointer ud),
  1675. gpointer ud)
  1676. {
  1677. struct hash_copy_callback_data cb;
  1678. if (src != NULL && dst != NULL) {
  1679. cb.key_copy_func = key_copy_func;
  1680. cb.value_copy_func = value_copy_func;
  1681. cb.ud = ud;
  1682. cb.dst = dst;
  1683. g_hash_table_foreach (src, copy_foreach_callback, &cb);
  1684. }
  1685. }
  1686. /**
  1687. * Utility function to provide mem_pool copy for rspamd_hash_table_copy function
  1688. * @param data string to copy
  1689. * @param ud memory pool to use
  1690. * @return
  1691. */
  1692. gpointer
  1693. rspamd_str_pool_copy (gconstpointer data, gpointer ud)
  1694. {
  1695. memory_pool_t *pool = ud;
  1696. return data ? memory_pool_strdup (pool, data) : NULL;
  1697. }
  1698. gboolean
  1699. parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask)
  1700. {
  1701. const char *pos;
  1702. char ip_buf[INET_ADDRSTRLEN + 1], mask_buf[3] = { '\0', '\0', '\0' };
  1703. bzero (ip_buf, sizeof (ip_buf));
  1704. if ((pos = strchr (line, '/')) != NULL) {
  1705. rspamd_strlcpy (ip_buf, line, MIN ((gsize)(pos - line), sizeof (ip_buf)));
  1706. rspamd_strlcpy (mask_buf, pos + 1, sizeof (mask_buf));
  1707. }
  1708. else {
  1709. rspamd_strlcpy (ip_buf, line, sizeof (ip_buf));
  1710. }
  1711. if (!inet_aton (ip_buf, ina)) {
  1712. return FALSE;
  1713. }
  1714. if (mask_buf[0] != '\0') {
  1715. /* Also parse mask */
  1716. *mask = (mask_buf[0] - '0') * 10 + mask_buf[1] - '0';
  1717. if (*mask > 32) {
  1718. return FALSE;
  1719. }
  1720. }
  1721. else {
  1722. *mask = 32;
  1723. }
  1724. *mask = G_MAXUINT32 << (32 - *mask);
  1725. return TRUE;
  1726. }
  1727. static volatile sig_atomic_t saved_signo[NSIG];
  1728. static
  1729. void read_pass_tmp_sig_handler (int s)
  1730. {
  1731. saved_signo[s] = 1;
  1732. }
  1733. #ifndef _PATH_TTY
  1734. # define _PATH_TTY "/dev/tty"
  1735. #endif
  1736. gint
  1737. rspamd_read_passphrase (gchar *buf, gint size, gint rwflag, gpointer key)
  1738. {
  1739. #ifdef HAVE_PASSPHRASE_H
  1740. gint len = 0;
  1741. gchar pass[BUFSIZ];
  1742. if (readpassphrase ("Enter passphrase: ", buf, size, RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) {
  1743. return 0;
  1744. }
  1745. return strlen (buf);
  1746. #else
  1747. struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
  1748. struct sigaction savetstp, savettin, savettou, savepipe;
  1749. struct termios term, oterm;
  1750. gint input, output, i;
  1751. gchar *end, *p, ch;
  1752. restart:
  1753. if ((input = output = open (_PATH_TTY, O_RDWR)) == -1) {
  1754. errno = ENOTTY;
  1755. return 0;
  1756. }
  1757. if (fcntl (input, F_SETFD, FD_CLOEXEC) == -1) {
  1758. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  1759. }
  1760. /* Turn echo off */
  1761. if (tcgetattr (input, &oterm) != 0) {
  1762. errno = ENOTTY;
  1763. return 0;
  1764. }
  1765. memcpy(&term, &oterm, sizeof(term));
  1766. term.c_lflag &= ~(ECHO | ECHONL);
  1767. (void)tcsetattr(input, TCSAFLUSH, &term);
  1768. (void)write (output, "Enter passphrase: ", sizeof ("Enter passphrase: ") - 1);
  1769. /* Save the current sighandler */
  1770. for (i = 0; i < NSIG; i++) {
  1771. saved_signo[i] = 0;
  1772. }
  1773. sigemptyset(&sa.sa_mask);
  1774. sa.sa_flags = 0;
  1775. sa.sa_handler = read_pass_tmp_sig_handler;
  1776. (void)sigaction (SIGALRM, &sa, &savealrm);
  1777. (void)sigaction (SIGHUP, &sa, &savehup);
  1778. (void)sigaction (SIGINT, &sa, &saveint);
  1779. (void)sigaction (SIGPIPE, &sa, &savepipe);
  1780. (void)sigaction (SIGQUIT, &sa, &savequit);
  1781. (void)sigaction (SIGTERM, &sa, &saveterm);
  1782. (void)sigaction (SIGTSTP, &sa, &savetstp);
  1783. (void)sigaction (SIGTTIN, &sa, &savettin);
  1784. (void)sigaction (SIGTTOU, &sa, &savettou);
  1785. /* Now read a passphrase */
  1786. p = buf;
  1787. end = p + size - 1;
  1788. while (read (input, &ch, 1) == 1 && ch != '\n' && ch != '\r') {
  1789. if (p < end) {
  1790. *p++ = ch;
  1791. }
  1792. }
  1793. *p = '\0';
  1794. (void)write (output, "\n", 1);
  1795. /* Restore terminal state */
  1796. if (memcmp (&term, &oterm, sizeof (term)) != 0) {
  1797. while (tcsetattr (input, TCSAFLUSH, &oterm) == -1 &&
  1798. errno == EINTR && !saved_signo[SIGTTOU]);
  1799. }
  1800. /* Restore signal handlers */
  1801. (void)sigaction (SIGALRM, &savealrm, NULL);
  1802. (void)sigaction (SIGHUP, &savehup, NULL);
  1803. (void)sigaction (SIGINT, &saveint, NULL);
  1804. (void)sigaction (SIGQUIT, &savequit, NULL);
  1805. (void)sigaction (SIGPIPE, &savepipe, NULL);
  1806. (void)sigaction (SIGTERM, &saveterm, NULL);
  1807. (void)sigaction (SIGTSTP, &savetstp, NULL);
  1808. (void)sigaction (SIGTTIN, &savettin, NULL);
  1809. (void)sigaction (SIGTTOU, &savettou, NULL);
  1810. close (input);
  1811. /* Send signals pending */
  1812. for (i = 0; i < NSIG; i++) {
  1813. if (saved_signo[i]) {
  1814. kill(getpid(), i);
  1815. switch (i) {
  1816. case SIGTSTP:
  1817. case SIGTTIN:
  1818. case SIGTTOU:
  1819. goto restart;
  1820. }
  1821. }
  1822. }
  1823. return p - buf;
  1824. #endif
  1825. }
  1826. gboolean
  1827. rspamd_ip_is_valid (void *ptr, int af)
  1828. {
  1829. const struct in_addr ip4_any = { INADDR_ANY }, ip4_none = { INADDR_NONE };
  1830. const struct in6_addr ip6_any = IN6ADDR_ANY_INIT;
  1831. gboolean ret = FALSE;
  1832. if (G_LIKELY (af == AF_INET)) {
  1833. if (memcmp (ptr, &ip4_any, sizeof (struct in_addr)) != 0 &&
  1834. memcmp (ptr, &ip4_none, sizeof (struct in_addr)) != 0) {
  1835. ret = TRUE;
  1836. }
  1837. }
  1838. else if (G_UNLIKELY (af == AF_INET6)) {
  1839. if (memcmp (ptr, &ip6_any, sizeof (struct in6_addr)) != 0) {
  1840. ret = TRUE;
  1841. }
  1842. }
  1843. return ret;
  1844. }
  1845. /*
  1846. * GString ucl emitting functions
  1847. */
  1848. static int
  1849. rspamd_gstring_append_character (unsigned char c, size_t len, void *ud)
  1850. {
  1851. GString *buf = ud;
  1852. gsize old_len;
  1853. if (len == 1) {
  1854. g_string_append_c (buf, c);
  1855. }
  1856. else {
  1857. if (buf->allocated_len - buf->len <= len) {
  1858. old_len = buf->len;
  1859. g_string_set_size (buf, buf->len + len + 1);
  1860. buf->len = old_len;
  1861. }
  1862. memset (&buf->str[buf->len], c, len);
  1863. buf->len += len;
  1864. }
  1865. return 0;
  1866. }
  1867. static int
  1868. rspamd_gstring_append_len (const unsigned char *str, size_t len, void *ud)
  1869. {
  1870. GString *buf = ud;
  1871. g_string_append_len (buf, str, len);
  1872. return 0;
  1873. }
  1874. static int
  1875. rspamd_gstring_append_int (int64_t val, void *ud)
  1876. {
  1877. GString *buf = ud;
  1878. rspamd_printf_gstring (buf, "%L", (intmax_t)val);
  1879. return 0;
  1880. }
  1881. static int
  1882. rspamd_gstring_append_double (double val, void *ud)
  1883. {
  1884. GString *buf = ud;
  1885. const double delta = 0.0000001;
  1886. if (val == (double)(int)val) {
  1887. rspamd_printf_gstring (buf, "%.1f", val);
  1888. }
  1889. else if (fabs (val - (double)(int)val) < delta) {
  1890. /* Write at maximum precision */
  1891. rspamd_printf_gstring (buf, "%.*g", DBL_DIG, val);
  1892. }
  1893. else {
  1894. rspamd_printf_gstring (buf, "%f", val);
  1895. }
  1896. return 0;
  1897. }
  1898. void
  1899. rspamd_ucl_emit_gstring (ucl_object_t *obj, enum ucl_emitter emit_type, GString *target)
  1900. {
  1901. struct ucl_emitter_functions func = {
  1902. .ucl_emitter_append_character = rspamd_gstring_append_character,
  1903. .ucl_emitter_append_len = rspamd_gstring_append_len,
  1904. .ucl_emitter_append_int = rspamd_gstring_append_int,
  1905. .ucl_emitter_append_double = rspamd_gstring_append_double
  1906. };
  1907. func.ud = target;
  1908. ucl_object_emit_full (obj, emit_type, &func);
  1909. }
  1910. /*
  1911. * vi:ts=4
  1912. */