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 53KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746
  1. /*
  2. * Copyright 2024 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 "config.h"
  17. #include "util.h"
  18. #include "unix-std.h"
  19. #include "ottery.h"
  20. #include "cryptobox.h"
  21. #include "contrib/libev/ev.h"
  22. #ifdef HAVE_TERMIOS_H
  23. #include <termios.h>
  24. #endif
  25. #ifdef HAVE_READPASSPHRASE_H
  26. #include <readpassphrase.h>
  27. #endif
  28. /* libutil */
  29. #ifdef HAVE_LIBUTIL_H
  30. #include <libutil.h>
  31. #endif
  32. #ifdef __APPLE__
  33. #include <mach/mach_time.h>
  34. #include <mach/mach_init.h>
  35. #include <mach/thread_act.h>
  36. #include <mach/mach_port.h>
  37. #endif
  38. /* poll */
  39. #ifdef HAVE_POLL_H
  40. #include <poll.h>
  41. #endif
  42. #ifdef HAVE_SIGINFO_H
  43. #include <siginfo.h>
  44. #endif
  45. /* sys/wait */
  46. #ifdef HAVE_SYS_WAIT_H
  47. #include <sys/wait.h>
  48. #endif
  49. /* sys/resource.h */
  50. #ifdef HAVE_SYS_RESOURCE_H
  51. #include <sys/resource.h>
  52. #endif
  53. #ifdef HAVE_RDTSC
  54. #ifdef __x86_64__
  55. #include <x86intrin.h>
  56. #endif
  57. #endif
  58. #include <math.h> /* for pow */
  59. #include <glob.h> /* in fact, we require this file ultimately */
  60. #include "zlib.h"
  61. #include "contrib/uthash/utlist.h"
  62. #include "blas-config.h"
  63. /* Check log messages intensity once per minute */
  64. #define CHECK_TIME 60
  65. /* More than 2 log messages per second */
  66. #define BUF_INTENSITY 2
  67. /* Default connect timeout for sync sockets */
  68. #define CONNECT_TIMEOUT 3
  69. /*
  70. * Should be defined in a single point
  71. */
  72. const struct rspamd_controller_pbkdf pbkdf_list[] = {
  73. {.name = "PBKDF2-blake2b",
  74. .alias = "pbkdf2",
  75. .description = "standard CPU intensive \"slow\" KDF using blake2b hash function",
  76. .type = RSPAMD_CRYPTOBOX_PBKDF2,
  77. .id = RSPAMD_PBKDF_ID_V1,
  78. .complexity = 16000,
  79. .salt_len = 20,
  80. .key_len = rspamd_cryptobox_HASHBYTES / 2},
  81. {.name = "Catena-Butterfly",
  82. .alias = "catena",
  83. .description = "modern CPU and memory intensive KDF",
  84. .type = RSPAMD_CRYPTOBOX_CATENA,
  85. .id = RSPAMD_PBKDF_ID_V2,
  86. .complexity = 10,
  87. .salt_len = 20,
  88. .key_len = rspamd_cryptobox_HASHBYTES / 2}};
  89. int rspamd_socket_nonblocking(int fd)
  90. {
  91. int ofl;
  92. ofl = fcntl(fd, F_GETFL, 0);
  93. if (fcntl(fd, F_SETFL, ofl | O_NONBLOCK) == -1) {
  94. return -1;
  95. }
  96. return 0;
  97. }
  98. int rspamd_socket_blocking(int fd)
  99. {
  100. int ofl;
  101. ofl = fcntl(fd, F_GETFL, 0);
  102. if (fcntl(fd, F_SETFL, ofl & (~O_NONBLOCK)) == -1) {
  103. return -1;
  104. }
  105. return 0;
  106. }
  107. int rspamd_socket_poll(int fd, int timeout, short events)
  108. {
  109. int r;
  110. struct pollfd fds[1];
  111. fds->fd = fd;
  112. fds->events = events;
  113. fds->revents = 0;
  114. while ((r = poll(fds, 1, timeout)) < 0) {
  115. if (errno != EINTR) {
  116. break;
  117. }
  118. }
  119. return r;
  120. }
  121. int rspamd_socket_create(int af, int type, int protocol, gboolean async)
  122. {
  123. int fd;
  124. fd = socket(af, type, protocol);
  125. if (fd == -1) {
  126. return -1;
  127. }
  128. /* Set close on exec */
  129. if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
  130. close(fd);
  131. return -1;
  132. }
  133. if (async) {
  134. if (rspamd_socket_nonblocking(fd) == -1) {
  135. close(fd);
  136. return -1;
  137. }
  138. }
  139. return fd;
  140. }
  141. static int
  142. rspamd_inet_socket_create(int type, struct addrinfo *addr, gboolean is_server,
  143. gboolean async, GList **list)
  144. {
  145. int fd = -1, r, on = 1, s_error;
  146. struct addrinfo *cur;
  147. gpointer ptr;
  148. socklen_t optlen;
  149. cur = addr;
  150. while (cur) {
  151. /* Create socket */
  152. fd = rspamd_socket_create(cur->ai_family, type, cur->ai_protocol, TRUE);
  153. if (fd == -1) {
  154. goto out;
  155. }
  156. if (is_server) {
  157. (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on,
  158. sizeof(int));
  159. #ifdef HAVE_IPV6_V6ONLY
  160. if (cur->ai_family == AF_INET6) {
  161. setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &on,
  162. sizeof(int));
  163. }
  164. #endif
  165. r = bind(fd, cur->ai_addr, cur->ai_addrlen);
  166. }
  167. else {
  168. r = connect(fd, cur->ai_addr, cur->ai_addrlen);
  169. }
  170. if (r == -1) {
  171. if (errno != EINPROGRESS) {
  172. goto out;
  173. }
  174. if (!async) {
  175. /* Try to poll */
  176. if (rspamd_socket_poll(fd, CONNECT_TIMEOUT * 1000,
  177. POLLOUT) <= 0) {
  178. errno = ETIMEDOUT;
  179. goto out;
  180. }
  181. else {
  182. /* Make synced again */
  183. if (rspamd_socket_blocking(fd) < 0) {
  184. goto out;
  185. }
  186. }
  187. }
  188. }
  189. else {
  190. /* Still need to check SO_ERROR on socket */
  191. optlen = sizeof(s_error);
  192. if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) &s_error, &optlen) != -1) {
  193. if (s_error) {
  194. errno = s_error;
  195. goto out;
  196. }
  197. }
  198. }
  199. if (list == NULL) {
  200. /* Go out immediately */
  201. break;
  202. }
  203. else if (fd != -1) {
  204. ptr = GINT_TO_POINTER(fd);
  205. *list = g_list_prepend(*list, ptr);
  206. cur = cur->ai_next;
  207. continue;
  208. }
  209. out:
  210. if (fd != -1) {
  211. close(fd);
  212. }
  213. fd = -1;
  214. cur = cur->ai_next;
  215. }
  216. return (fd);
  217. }
  218. int rspamd_socket_tcp(struct addrinfo *addr, gboolean is_server, gboolean async)
  219. {
  220. return rspamd_inet_socket_create(SOCK_STREAM, addr, is_server, async, NULL);
  221. }
  222. int rspamd_socket_udp(struct addrinfo *addr, gboolean is_server, gboolean async)
  223. {
  224. return rspamd_inet_socket_create(SOCK_DGRAM, addr, is_server, async, NULL);
  225. }
  226. int rspamd_socket_unix(const char *path,
  227. struct sockaddr_un *addr,
  228. int type,
  229. gboolean is_server,
  230. gboolean async)
  231. {
  232. socklen_t optlen;
  233. int fd = -1, s_error, r, serrno, on = 1;
  234. struct stat st;
  235. if (path == NULL)
  236. return -1;
  237. addr->sun_family = AF_UNIX;
  238. rspamd_strlcpy(addr->sun_path, path, sizeof(addr->sun_path));
  239. #ifdef FREEBSD
  240. addr->sun_len = SUN_LEN(addr);
  241. #endif
  242. if (is_server) {
  243. /* Unlink socket if it exists already */
  244. if (lstat(addr->sun_path, &st) != -1) {
  245. if (S_ISSOCK(st.st_mode)) {
  246. if (unlink(addr->sun_path) == -1) {
  247. goto out;
  248. }
  249. }
  250. else {
  251. goto out;
  252. }
  253. }
  254. }
  255. fd = socket(PF_LOCAL, type, 0);
  256. if (fd == -1) {
  257. return -1;
  258. }
  259. if (rspamd_socket_nonblocking(fd) < 0) {
  260. goto out;
  261. }
  262. /* Set close on exec */
  263. if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
  264. goto out;
  265. }
  266. if (is_server) {
  267. (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on,
  268. sizeof(int));
  269. r = bind(fd, (struct sockaddr *) addr, SUN_LEN(addr));
  270. }
  271. else {
  272. r = connect(fd, (struct sockaddr *) addr, SUN_LEN(addr));
  273. }
  274. if (r == -1) {
  275. if (errno != EINPROGRESS) {
  276. goto out;
  277. }
  278. if (!async) {
  279. /* Try to poll */
  280. if (rspamd_socket_poll(fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
  281. errno = ETIMEDOUT;
  282. goto out;
  283. }
  284. else {
  285. /* Make synced again */
  286. if (rspamd_socket_blocking(fd) < 0) {
  287. goto out;
  288. }
  289. }
  290. }
  291. }
  292. else {
  293. /* Still need to check SO_ERROR on socket */
  294. optlen = sizeof(s_error);
  295. if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) &s_error, &optlen) != -1) {
  296. if (s_error) {
  297. errno = s_error;
  298. goto out;
  299. }
  300. }
  301. }
  302. return (fd);
  303. out:
  304. serrno = errno;
  305. if (fd != -1) {
  306. close(fd);
  307. }
  308. errno = serrno;
  309. return (-1);
  310. }
  311. static int
  312. rspamd_prefer_v4_hack(const struct addrinfo *a1, const struct addrinfo *a2)
  313. {
  314. return a1->ai_addr->sa_family - a2->ai_addr->sa_family;
  315. }
  316. /**
  317. * Make a universal socket
  318. * @param credits host, ip or path to unix socket
  319. * @param port port (used for network sockets)
  320. * @param async make this socket async
  321. * @param is_server make this socket as server socket
  322. * @param try_resolve try name resolution for a socket (BLOCKING)
  323. */
  324. int rspamd_socket(const char *credits, uint16_t port,
  325. int type, gboolean async, gboolean is_server, gboolean try_resolve)
  326. {
  327. struct sockaddr_un un;
  328. struct stat st;
  329. struct addrinfo hints, *res;
  330. int r;
  331. char portbuf[8];
  332. if (*credits == '/') {
  333. if (is_server) {
  334. return rspamd_socket_unix(credits, &un, type, is_server, async);
  335. }
  336. else {
  337. r = stat(credits, &st);
  338. if (r == -1) {
  339. /* Unix socket doesn't exists it must be created first */
  340. errno = ENOENT;
  341. return -1;
  342. }
  343. else {
  344. if ((st.st_mode & S_IFSOCK) == 0) {
  345. /* Path is not valid socket */
  346. errno = EINVAL;
  347. return -1;
  348. }
  349. else {
  350. return rspamd_socket_unix(credits,
  351. &un,
  352. type,
  353. is_server,
  354. async);
  355. }
  356. }
  357. }
  358. }
  359. else {
  360. /* TCP related part */
  361. memset(&hints, 0, sizeof(hints));
  362. hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
  363. hints.ai_socktype = type; /* Type of the socket */
  364. hints.ai_flags = is_server ? AI_PASSIVE : 0;
  365. hints.ai_protocol = 0; /* Any protocol */
  366. hints.ai_canonname = NULL;
  367. hints.ai_addr = NULL;
  368. hints.ai_next = NULL;
  369. if (!try_resolve) {
  370. hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
  371. }
  372. rspamd_snprintf(portbuf, sizeof(portbuf), "%d", (int) port);
  373. if ((r = getaddrinfo(credits, portbuf, &hints, &res)) == 0) {
  374. LL_SORT2(res, rspamd_prefer_v4_hack, ai_next);
  375. r = rspamd_inet_socket_create(type, res, is_server, async, NULL);
  376. freeaddrinfo(res);
  377. return r;
  378. }
  379. else {
  380. return -1;
  381. }
  382. }
  383. }
  384. gboolean
  385. rspamd_socketpair(int pair[2], int af)
  386. {
  387. int r = -1, serrno;
  388. #ifdef HAVE_SOCK_SEQPACKET
  389. if (af == SOCK_SEQPACKET) {
  390. r = socketpair(AF_LOCAL, SOCK_SEQPACKET, 0, pair);
  391. if (r == -1) {
  392. r = socketpair(AF_LOCAL, SOCK_DGRAM, 0, pair);
  393. }
  394. }
  395. #endif
  396. if (r == -1) {
  397. r = socketpair(AF_LOCAL, af, 0, pair);
  398. }
  399. if (r == -1) {
  400. return -1;
  401. }
  402. /* Set close on exec */
  403. if (fcntl(pair[0], F_SETFD, FD_CLOEXEC) == -1) {
  404. goto out;
  405. }
  406. if (fcntl(pair[1], F_SETFD, FD_CLOEXEC) == -1) {
  407. goto out;
  408. }
  409. return TRUE;
  410. out:
  411. serrno = errno;
  412. close(pair[0]);
  413. close(pair[1]);
  414. errno = serrno;
  415. return FALSE;
  416. }
  417. #ifdef HAVE_SA_SIGINFO
  418. void rspamd_signals_init(struct sigaction *signals, void (*sig_handler)(int,
  419. siginfo_t *,
  420. void *))
  421. #else
  422. void rspamd_signals_init(struct sigaction *signals, void (*sig_handler)(int))
  423. #endif
  424. {
  425. struct sigaction sigpipe_act;
  426. /* Setting up signal handlers */
  427. /* SIGUSR1 - reopen config file */
  428. /* SIGUSR2 - worker is ready for accept */
  429. sigemptyset(&signals->sa_mask);
  430. sigaddset(&signals->sa_mask, SIGTERM);
  431. sigaddset(&signals->sa_mask, SIGINT);
  432. sigaddset(&signals->sa_mask, SIGHUP);
  433. sigaddset(&signals->sa_mask, SIGCHLD);
  434. sigaddset(&signals->sa_mask, SIGUSR1);
  435. sigaddset(&signals->sa_mask, SIGUSR2);
  436. sigaddset(&signals->sa_mask, SIGALRM);
  437. #ifdef SIGPOLL
  438. sigaddset(&signals->sa_mask, SIGPOLL);
  439. #endif
  440. #ifdef SIGIO
  441. sigaddset(&signals->sa_mask, SIGIO);
  442. #endif
  443. #ifdef HAVE_SA_SIGINFO
  444. signals->sa_flags = SA_SIGINFO;
  445. signals->sa_handler = NULL;
  446. signals->sa_sigaction = sig_handler;
  447. #else
  448. signals->sa_handler = sig_handler;
  449. signals->sa_flags = 0;
  450. #endif
  451. sigaction(SIGTERM, signals, NULL);
  452. sigaction(SIGINT, signals, NULL);
  453. sigaction(SIGHUP, signals, NULL);
  454. sigaction(SIGCHLD, signals, NULL);
  455. sigaction(SIGUSR1, signals, NULL);
  456. sigaction(SIGUSR2, signals, NULL);
  457. sigaction(SIGALRM, signals, NULL);
  458. #ifdef SIGPOLL
  459. sigaction(SIGPOLL, signals, NULL);
  460. #endif
  461. #ifdef SIGIO
  462. sigaction(SIGIO, signals, NULL);
  463. #endif
  464. /* Ignore SIGPIPE as we handle write errors manually */
  465. sigemptyset(&sigpipe_act.sa_mask);
  466. sigaddset(&sigpipe_act.sa_mask, SIGPIPE);
  467. sigpipe_act.sa_handler = SIG_IGN;
  468. sigpipe_act.sa_flags = 0;
  469. sigaction(SIGPIPE, &sigpipe_act, NULL);
  470. }
  471. #ifndef HAVE_SETPROCTITLE
  472. #ifdef LINUX
  473. static char *title_buffer = NULL;
  474. static size_t title_buffer_size = 0;
  475. static char *title_progname, *title_progname_full;
  476. char **old_environ = NULL;
  477. static void
  478. rspamd_title_dtor(gpointer d)
  479. {
  480. /* Restore old environment */
  481. if (old_environ != NULL) {
  482. environ = old_environ;
  483. }
  484. char **env = (char **) d;
  485. unsigned int i;
  486. for (i = 0; env[i] != NULL; i++) {
  487. g_free(env[i]);
  488. }
  489. g_free(env);
  490. }
  491. #endif /* ifdef LINUX */
  492. #endif /* ifndef HAVE_SETPROCTITLE */
  493. int rspamd_init_title(rspamd_mempool_t *pool,
  494. int argc, char *argv[], char *envp[])
  495. {
  496. #if defined(LINUX) && !defined(HAVE_SETPROCTITLE)
  497. char *begin_of_buffer = 0, *end_of_buffer = 0;
  498. int i;
  499. for (i = 0; i < argc; ++i) {
  500. if (!begin_of_buffer) {
  501. begin_of_buffer = argv[i];
  502. }
  503. if (!end_of_buffer || end_of_buffer + 1 == argv[i]) {
  504. end_of_buffer = argv[i] + strlen(argv[i]);
  505. }
  506. }
  507. for (i = 0; envp[i]; ++i) {
  508. if (!begin_of_buffer) {
  509. begin_of_buffer = envp[i];
  510. }
  511. if (!end_of_buffer || end_of_buffer + 1 == envp[i]) {
  512. end_of_buffer = envp[i] + strlen(envp[i]);
  513. }
  514. }
  515. if (!end_of_buffer) {
  516. return 0;
  517. }
  518. char **new_environ = g_malloc((i + 1) * sizeof(envp[0]));
  519. for (i = 0; envp[i]; ++i) {
  520. new_environ[i] = g_strdup(envp[i]);
  521. }
  522. new_environ[i] = NULL;
  523. if (program_invocation_name) {
  524. title_progname_full = g_strdup(program_invocation_name);
  525. char *p = strrchr(title_progname_full, '/');
  526. if (p) {
  527. title_progname = p + 1;
  528. }
  529. else {
  530. title_progname = title_progname_full;
  531. }
  532. program_invocation_name = title_progname_full;
  533. program_invocation_short_name = title_progname;
  534. }
  535. old_environ = environ;
  536. environ = new_environ;
  537. title_buffer = begin_of_buffer;
  538. title_buffer_size = end_of_buffer - begin_of_buffer;
  539. rspamd_mempool_add_destructor(pool,
  540. rspamd_title_dtor,
  541. new_environ);
  542. #endif
  543. return 0;
  544. }
  545. int rspamd_setproctitle(const char *fmt, ...)
  546. {
  547. #ifdef HAVE_SETPROCTITLE
  548. if (fmt) {
  549. static char titlebuf[4096];
  550. va_list ap;
  551. va_start(ap, fmt);
  552. rspamd_vsnprintf(titlebuf, sizeof(titlebuf), fmt, ap);
  553. va_end(ap);
  554. setproctitle("%s", titlebuf);
  555. }
  556. #else
  557. #if defined(LINUX)
  558. if (!title_buffer || !title_buffer_size) {
  559. errno = ENOMEM;
  560. return -1;
  561. }
  562. memset(title_buffer, '\0', title_buffer_size);
  563. ssize_t written;
  564. if (fmt) {
  565. va_list ap;
  566. written = rspamd_snprintf(title_buffer,
  567. title_buffer_size,
  568. "%s: ",
  569. title_progname);
  570. if (written < 0 || (size_t) written >= title_buffer_size)
  571. return -1;
  572. va_start(ap, fmt);
  573. rspamd_vsnprintf(title_buffer + written,
  574. title_buffer_size - written,
  575. fmt,
  576. ap);
  577. va_end(ap);
  578. }
  579. else {
  580. written = rspamd_snprintf(title_buffer,
  581. title_buffer_size,
  582. "%s",
  583. title_progname);
  584. if (written < 0 || (size_t) written >= title_buffer_size)
  585. return -1;
  586. }
  587. written = strlen(title_buffer);
  588. memset(title_buffer + written, '\0', title_buffer_size - written);
  589. #elif defined(__APPLE__)
  590. /* OSX is broken, ignore this brain damaged system */
  591. #else
  592. /* Last resort (usually broken, but eh...) */
  593. GString *dest;
  594. va_list ap;
  595. dest = g_string_new("");
  596. va_start(ap, fmt);
  597. rspamd_vprintf_gstring(dest, fmt, ap);
  598. va_end(ap);
  599. g_set_prgname(dest->str);
  600. g_string_free(dest, TRUE);
  601. #endif /* defined(LINUX) */
  602. #endif /* HAVE_SETPROCTITLE */
  603. return 0;
  604. }
  605. #ifndef HAVE_PIDFILE
  606. static int _rspamd_pidfile_remove(rspamd_pidfh_t *pfh, int freeit);
  607. static int
  608. rspamd_pidfile_verify(rspamd_pidfh_t *pfh)
  609. {
  610. struct stat sb;
  611. if (pfh == NULL || pfh->pf_fd == -1)
  612. return (-1);
  613. /*
  614. * Check remembered descriptor.
  615. */
  616. if (fstat(pfh->pf_fd, &sb) == -1)
  617. return (errno);
  618. if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
  619. return -1;
  620. return 0;
  621. }
  622. static int
  623. rspamd_pidfile_read(const char *path, pid_t *pidptr)
  624. {
  625. char buf[16], *endptr;
  626. int error, fd, i;
  627. fd = open(path, O_RDONLY);
  628. if (fd == -1)
  629. return (errno);
  630. i = read(fd, buf, sizeof(buf) - 1);
  631. error = errno; /* Remember errno in case close() wants to change it. */
  632. close(fd);
  633. if (i == -1)
  634. return error;
  635. else if (i == 0)
  636. return EAGAIN;
  637. buf[i] = '\0';
  638. *pidptr = strtol(buf, &endptr, 10);
  639. if (endptr != &buf[i])
  640. return EINVAL;
  641. return 0;
  642. }
  643. rspamd_pidfh_t *
  644. rspamd_pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
  645. {
  646. rspamd_pidfh_t *pfh;
  647. struct stat sb;
  648. int error, fd, len, count;
  649. struct timespec rqtp;
  650. pfh = g_malloc(sizeof(*pfh));
  651. if (pfh == NULL)
  652. return NULL;
  653. if (path == NULL)
  654. len = snprintf(pfh->pf_path,
  655. sizeof(pfh->pf_path),
  656. "/var/run/%s.pid",
  657. g_get_prgname());
  658. else
  659. len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), "%s", path);
  660. if (len >= (int) sizeof(pfh->pf_path)) {
  661. g_free(pfh);
  662. errno = ENAMETOOLONG;
  663. return NULL;
  664. }
  665. /*
  666. * Open the PID file and obtain exclusive lock.
  667. * We truncate PID file here only to remove old PID immediately,
  668. * PID file will be truncated again in pidfile_write(), so
  669. * pidfile_write() can be called multiple times.
  670. */
  671. fd = open(pfh->pf_path, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
  672. rspamd_file_lock(fd, TRUE);
  673. if (fd == -1) {
  674. count = 0;
  675. rqtp.tv_sec = 0;
  676. rqtp.tv_nsec = 5000000;
  677. if (errno == EWOULDBLOCK && pidptr != NULL) {
  678. again:
  679. errno = rspamd_pidfile_read(pfh->pf_path, pidptr);
  680. if (errno == 0)
  681. errno = EEXIST;
  682. else if (errno == EAGAIN) {
  683. if (++count <= 3) {
  684. nanosleep(&rqtp, 0);
  685. goto again;
  686. }
  687. }
  688. }
  689. g_free(pfh);
  690. return NULL;
  691. }
  692. /*
  693. * Remember file information, so in pidfile_write() we are sure we write
  694. * to the proper descriptor.
  695. */
  696. if (fstat(fd, &sb) == -1) {
  697. error = errno;
  698. unlink(pfh->pf_path);
  699. close(fd);
  700. g_free(pfh);
  701. errno = error;
  702. return NULL;
  703. }
  704. pfh->pf_fd = fd;
  705. pfh->pf_dev = sb.st_dev;
  706. pfh->pf_ino = sb.st_ino;
  707. return pfh;
  708. }
  709. int rspamd_pidfile_write(rspamd_pidfh_t *pfh)
  710. {
  711. char pidstr[16];
  712. int error, fd;
  713. /*
  714. * Check remembered descriptor, so we don't overwrite some other
  715. * file if pidfile was closed and descriptor reused.
  716. */
  717. errno = rspamd_pidfile_verify(pfh);
  718. if (errno != 0) {
  719. /*
  720. * Don't close descriptor, because we are not sure if it's ours.
  721. */
  722. return -1;
  723. }
  724. fd = pfh->pf_fd;
  725. /*
  726. * Truncate PID file, so multiple calls of pidfile_write() are allowed.
  727. */
  728. if (ftruncate(fd, 0) == -1) {
  729. error = errno;
  730. _rspamd_pidfile_remove(pfh, 0);
  731. errno = error;
  732. return -1;
  733. }
  734. rspamd_snprintf(pidstr, sizeof(pidstr), "%P", getpid());
  735. if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t) strlen(pidstr)) {
  736. error = errno;
  737. _rspamd_pidfile_remove(pfh, 0);
  738. errno = error;
  739. return -1;
  740. }
  741. return 0;
  742. }
  743. int rspamd_pidfile_close(rspamd_pidfh_t *pfh)
  744. {
  745. int error;
  746. error = rspamd_pidfile_verify(pfh);
  747. if (error != 0) {
  748. errno = error;
  749. return -1;
  750. }
  751. if (close(pfh->pf_fd) == -1)
  752. error = errno;
  753. g_free(pfh);
  754. if (error != 0) {
  755. errno = error;
  756. return -1;
  757. }
  758. return 0;
  759. }
  760. static int
  761. _rspamd_pidfile_remove(rspamd_pidfh_t *pfh, int freeit)
  762. {
  763. int error;
  764. error = rspamd_pidfile_verify(pfh);
  765. if (error != 0) {
  766. errno = error;
  767. return -1;
  768. }
  769. if (unlink(pfh->pf_path) == -1)
  770. error = errno;
  771. if (!rspamd_file_unlock(pfh->pf_fd, FALSE)) {
  772. if (error == 0)
  773. error = errno;
  774. }
  775. if (close(pfh->pf_fd) == -1) {
  776. if (error == 0)
  777. error = errno;
  778. }
  779. if (freeit)
  780. g_free(pfh);
  781. else
  782. pfh->pf_fd = -1;
  783. if (error != 0) {
  784. errno = error;
  785. return -1;
  786. }
  787. return 0;
  788. }
  789. int rspamd_pidfile_remove(rspamd_pidfh_t *pfh)
  790. {
  791. return (_rspamd_pidfile_remove(pfh, 1));
  792. }
  793. #endif
  794. /* Replace %r with rcpt value and %f with from value, new string is allocated in pool */
  795. char *
  796. resolve_stat_filename(rspamd_mempool_t *pool,
  797. char *pattern,
  798. char *rcpt,
  799. char *from)
  800. {
  801. int need_to_format = 0, len = 0;
  802. int rcptlen, fromlen;
  803. char *c = pattern, *new, *s;
  804. if (rcpt) {
  805. rcptlen = strlen(rcpt);
  806. }
  807. else {
  808. rcptlen = 0;
  809. }
  810. if (from) {
  811. fromlen = strlen(from);
  812. }
  813. else {
  814. fromlen = 0;
  815. }
  816. /* Calculate length */
  817. while (*c++) {
  818. if (*c == '%' && *(c + 1) == 'r') {
  819. len += rcptlen;
  820. c += 2;
  821. need_to_format = 1;
  822. continue;
  823. }
  824. else if (*c == '%' && *(c + 1) == 'f') {
  825. len += fromlen;
  826. c += 2;
  827. need_to_format = 1;
  828. continue;
  829. }
  830. len++;
  831. }
  832. /* Do not allocate extra memory if we do not need to format string */
  833. if (!need_to_format) {
  834. return pattern;
  835. }
  836. /* Allocate new string */
  837. new = rspamd_mempool_alloc(pool, len);
  838. c = pattern;
  839. s = new;
  840. /* Format string */
  841. while (*c++) {
  842. if (*c == '%' && *(c + 1) == 'r') {
  843. c += 2;
  844. memcpy(s, rcpt, rcptlen);
  845. s += rcptlen;
  846. continue;
  847. }
  848. *s++ = *c;
  849. }
  850. *s = '\0';
  851. return new;
  852. }
  853. const char *
  854. rspamd_log_check_time(double start, double end, int resolution)
  855. {
  856. double diff;
  857. static char res[64];
  858. char fmt[32];
  859. diff = (end - start) * 1000.0;
  860. rspamd_snprintf(fmt, sizeof(fmt), "%%.%dfms", resolution);
  861. rspamd_snprintf(res, sizeof(res), fmt, diff);
  862. return (const char *) res;
  863. }
  864. #ifdef HAVE_FLOCK
  865. /* Flock version */
  866. gboolean
  867. rspamd_file_lock(int fd, gboolean async)
  868. {
  869. int flags;
  870. if (async) {
  871. flags = LOCK_EX | LOCK_NB;
  872. }
  873. else {
  874. flags = LOCK_EX;
  875. }
  876. if (flock(fd, flags) == -1) {
  877. return FALSE;
  878. }
  879. return TRUE;
  880. }
  881. gboolean
  882. rspamd_file_unlock(int fd, gboolean async)
  883. {
  884. int flags;
  885. if (async) {
  886. flags = LOCK_UN | LOCK_NB;
  887. }
  888. else {
  889. flags = LOCK_UN;
  890. }
  891. if (flock(fd, flags) == -1) {
  892. if (async && errno == EAGAIN) {
  893. return FALSE;
  894. }
  895. return FALSE;
  896. }
  897. return TRUE;
  898. }
  899. #else /* HAVE_FLOCK */
  900. /* Fctnl version */
  901. gboolean
  902. rspamd_file_lock(int fd, gboolean async)
  903. {
  904. struct flock fl = {
  905. .l_type = F_WRLCK,
  906. .l_whence = SEEK_SET,
  907. .l_start = 0,
  908. .l_len = 0};
  909. if (fcntl(fd, async ? F_SETLK : F_SETLKW, &fl) == -1) {
  910. if (async && (errno == EAGAIN || errno == EACCES)) {
  911. return FALSE;
  912. }
  913. return FALSE;
  914. }
  915. return TRUE;
  916. }
  917. gboolean
  918. rspamd_file_unlock(int fd, gboolean async)
  919. {
  920. struct flock fl = {
  921. .l_type = F_UNLCK,
  922. .l_whence = SEEK_SET,
  923. .l_start = 0,
  924. .l_len = 0};
  925. if (fcntl(fd, async ? F_SETLK : F_SETLKW, &fl) == -1) {
  926. if (async && (errno == EAGAIN || errno == EACCES)) {
  927. return FALSE;
  928. }
  929. return FALSE;
  930. }
  931. return TRUE;
  932. }
  933. #endif /* HAVE_FLOCK */
  934. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 22))
  935. void g_ptr_array_unref(GPtrArray *array)
  936. {
  937. g_ptr_array_free(array, TRUE);
  938. }
  939. gboolean
  940. g_int64_equal(gconstpointer v1, gconstpointer v2)
  941. {
  942. return *((const int64_t *) v1) == *((const int64_t *) v2);
  943. }
  944. unsigned int g_int64_hash(gconstpointer v)
  945. {
  946. uint64_t v64 = *(uint64_t *) v;
  947. return (unsigned int) (v ^ (v >> 32));
  948. }
  949. #endif
  950. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 14))
  951. void g_queue_clear(GQueue *queue)
  952. {
  953. g_return_if_fail(queue != NULL);
  954. g_list_free(queue->head);
  955. queue->head = queue->tail = NULL;
  956. queue->length = 0;
  957. }
  958. #endif
  959. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 30))
  960. GPtrArray *
  961. g_ptr_array_new_full(unsigned int reserved_size,
  962. GDestroyNotify element_free_func)
  963. {
  964. GPtrArray *array;
  965. array = g_ptr_array_sized_new(reserved_size);
  966. g_ptr_array_set_free_func(array, element_free_func);
  967. return array;
  968. }
  969. #endif
  970. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 32))
  971. void g_queue_free_full(GQueue *queue, GDestroyNotify free_func)
  972. {
  973. GList *cur;
  974. cur = queue->head;
  975. while (cur) {
  976. free_func(cur->data);
  977. cur = g_list_next(cur);
  978. }
  979. g_queue_free(queue);
  980. }
  981. #endif
  982. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 40))
  983. void g_ptr_array_insert(GPtrArray *array, int index_, gpointer data)
  984. {
  985. g_return_if_fail(array);
  986. g_return_if_fail(index_ >= -1);
  987. g_return_if_fail(index_ <= (int) array->len);
  988. g_ptr_array_set_size(array, array->len + 1);
  989. if (index_ < 0) {
  990. index_ = array->len;
  991. }
  992. if (index_ < array->len) {
  993. memmove(&(array->pdata[index_ + 1]), &(array->pdata[index_]),
  994. (array->len - index_) * sizeof(gpointer));
  995. }
  996. array->pdata[index_] = data;
  997. }
  998. #endif
  999. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 32))
  1000. const char *
  1001. g_environ_getenv(char **envp, const char *variable)
  1002. {
  1003. gsize len;
  1004. int i;
  1005. if (envp == NULL) {
  1006. return NULL;
  1007. }
  1008. len = strlen(variable);
  1009. for (i = 0; envp[i]; i++) {
  1010. if (strncmp(envp[i], variable, len) == 0 && envp[i][len] == '=') {
  1011. return envp[i] + len + 1;
  1012. }
  1013. }
  1014. return NULL;
  1015. }
  1016. #endif
  1017. int rspamd_fallocate(int fd, off_t offset, off_t len)
  1018. {
  1019. #if defined(HAVE_FALLOCATE)
  1020. return fallocate(fd, 0, offset, len);
  1021. #elif defined(HAVE_POSIX_FALLOCATE)
  1022. return posix_fallocate(fd, offset, len);
  1023. #else
  1024. /* Return 0 as nothing can be done on this system */
  1025. return 0;
  1026. #endif
  1027. }
  1028. /**
  1029. * Create new mutex
  1030. * @return mutex or NULL
  1031. */
  1032. inline rspamd_mutex_t *
  1033. rspamd_mutex_new(void)
  1034. {
  1035. rspamd_mutex_t *new;
  1036. new = g_malloc0(sizeof(rspamd_mutex_t));
  1037. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1038. g_mutex_init(&new->mtx);
  1039. #else
  1040. g_static_mutex_init(&new->mtx);
  1041. #endif
  1042. return new;
  1043. }
  1044. /**
  1045. * Lock mutex
  1046. * @param mtx
  1047. */
  1048. inline void
  1049. rspamd_mutex_lock(rspamd_mutex_t *mtx)
  1050. {
  1051. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1052. g_mutex_lock(&mtx->mtx);
  1053. #else
  1054. g_static_mutex_lock(&mtx->mtx);
  1055. #endif
  1056. }
  1057. /**
  1058. * Unlock mutex
  1059. * @param mtx
  1060. */
  1061. inline void
  1062. rspamd_mutex_unlock(rspamd_mutex_t *mtx)
  1063. {
  1064. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1065. g_mutex_unlock(&mtx->mtx);
  1066. #else
  1067. g_static_mutex_unlock(&mtx->mtx);
  1068. #endif
  1069. }
  1070. void rspamd_mutex_free(rspamd_mutex_t *mtx)
  1071. {
  1072. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  1073. g_mutex_clear(&mtx->mtx);
  1074. #endif
  1075. g_free(mtx);
  1076. }
  1077. struct rspamd_thread_data {
  1078. char *name;
  1079. int id;
  1080. GThreadFunc func;
  1081. gpointer data;
  1082. };
  1083. static gpointer
  1084. rspamd_thread_func(gpointer ud)
  1085. {
  1086. struct rspamd_thread_data *td = ud;
  1087. sigset_t s_mask;
  1088. /* Ignore signals in thread */
  1089. sigemptyset(&s_mask);
  1090. sigaddset(&s_mask, SIGINT);
  1091. sigaddset(&s_mask, SIGHUP);
  1092. sigaddset(&s_mask, SIGCHLD);
  1093. sigaddset(&s_mask, SIGUSR1);
  1094. sigaddset(&s_mask, SIGUSR2);
  1095. sigaddset(&s_mask, SIGALRM);
  1096. sigaddset(&s_mask, SIGPIPE);
  1097. pthread_sigmask(SIG_BLOCK, &s_mask, NULL);
  1098. ud = td->func(td->data);
  1099. g_free(td->name);
  1100. g_free(td);
  1101. return ud;
  1102. }
  1103. struct hash_copy_callback_data {
  1104. gpointer (*key_copy_func)(gconstpointer data, gpointer ud);
  1105. gpointer (*value_copy_func)(gconstpointer data, gpointer ud);
  1106. gpointer ud;
  1107. GHashTable *dst;
  1108. };
  1109. static void
  1110. copy_foreach_callback(gpointer key, gpointer value, gpointer ud)
  1111. {
  1112. struct hash_copy_callback_data *cb = ud;
  1113. gpointer nkey, nvalue;
  1114. nkey = cb->key_copy_func ? cb->key_copy_func(key, cb->ud) : (gpointer) key;
  1115. nvalue =
  1116. cb->value_copy_func ? cb->value_copy_func(value,
  1117. cb->ud)
  1118. : (gpointer) value;
  1119. g_hash_table_insert(cb->dst, nkey, nvalue);
  1120. }
  1121. /**
  1122. * Deep copy of one hash table to another
  1123. * @param src source hash
  1124. * @param dst destination hash
  1125. * @param key_copy_func function called to copy or modify keys (or NULL)
  1126. * @param value_copy_func function called to copy or modify values (or NULL)
  1127. * @param ud user data for copy functions
  1128. */
  1129. void rspamd_hash_table_copy(GHashTable *src, GHashTable *dst,
  1130. gpointer (*key_copy_func)(gconstpointer data, gpointer ud),
  1131. gpointer (*value_copy_func)(gconstpointer data, gpointer ud),
  1132. gpointer ud)
  1133. {
  1134. struct hash_copy_callback_data cb;
  1135. if (src != NULL && dst != NULL) {
  1136. cb.key_copy_func = key_copy_func;
  1137. cb.value_copy_func = value_copy_func;
  1138. cb.ud = ud;
  1139. cb.dst = dst;
  1140. g_hash_table_foreach(src, copy_foreach_callback, &cb);
  1141. }
  1142. }
  1143. static volatile sig_atomic_t saved_signo[NSIG];
  1144. static void
  1145. read_pass_tmp_sig_handler(int s)
  1146. {
  1147. saved_signo[s] = 1;
  1148. }
  1149. #ifndef _PATH_TTY
  1150. #define _PATH_TTY "/dev/tty"
  1151. #endif
  1152. int rspamd_read_passphrase_with_prompt(const char *prompt, char *buf, int size, bool echo, gpointer key)
  1153. {
  1154. #ifdef HAVE_READPASSPHRASE_H
  1155. int flags = echo ? RPP_ECHO_ON : RPP_ECHO_OFF;
  1156. if (readpassphrase(prompt, buf, size, flags | RPP_REQUIRE_TTY) == NULL) {
  1157. return 0;
  1158. }
  1159. return strlen(buf);
  1160. #else
  1161. struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
  1162. struct sigaction savetstp, savettin, savettou, savepipe;
  1163. struct termios term, oterm;
  1164. int input, output, i;
  1165. char *end, *p, ch;
  1166. restart:
  1167. if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) {
  1168. errno = ENOTTY;
  1169. return 0;
  1170. }
  1171. (void) fcntl(input, F_SETFD, FD_CLOEXEC);
  1172. /* Turn echo off */
  1173. if (tcgetattr(input, &oterm) != 0) {
  1174. close(input);
  1175. errno = ENOTTY;
  1176. return 0;
  1177. }
  1178. memcpy(&term, &oterm, sizeof(term));
  1179. if (!echo) {
  1180. term.c_lflag &= ~(ECHO | ECHONL);
  1181. }
  1182. if (tcsetattr(input, TCSAFLUSH, &term) == -1) {
  1183. errno = ENOTTY;
  1184. close(input);
  1185. return 0;
  1186. }
  1187. g_assert(write(output, prompt, sizeof("Enter passphrase: ") - 1) != -1);
  1188. /* Save the current sighandler */
  1189. for (i = 0; i < NSIG; i++) {
  1190. saved_signo[i] = 0;
  1191. }
  1192. sigemptyset(&sa.sa_mask);
  1193. sa.sa_flags = 0;
  1194. sa.sa_handler = read_pass_tmp_sig_handler;
  1195. (void) sigaction(SIGALRM, &sa, &savealrm);
  1196. (void) sigaction(SIGHUP, &sa, &savehup);
  1197. (void) sigaction(SIGINT, &sa, &saveint);
  1198. (void) sigaction(SIGPIPE, &sa, &savepipe);
  1199. (void) sigaction(SIGQUIT, &sa, &savequit);
  1200. (void) sigaction(SIGTERM, &sa, &saveterm);
  1201. (void) sigaction(SIGTSTP, &sa, &savetstp);
  1202. (void) sigaction(SIGTTIN, &sa, &savettin);
  1203. (void) sigaction(SIGTTOU, &sa, &savettou);
  1204. /* Now read a passphrase */
  1205. p = buf;
  1206. end = p + size - 1;
  1207. while (read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r') {
  1208. if (p < end) {
  1209. *p++ = ch;
  1210. }
  1211. }
  1212. *p = '\0';
  1213. g_assert(write(output, "\n", 1) == 1);
  1214. /* Restore terminal state */
  1215. if (memcmp(&term, &oterm, sizeof(term)) != 0) {
  1216. while (tcsetattr(input, TCSAFLUSH, &oterm) == -1 &&
  1217. errno == EINTR && !saved_signo[SIGTTOU])
  1218. ;
  1219. }
  1220. /* Restore signal handlers */
  1221. (void) sigaction(SIGALRM, &savealrm, NULL);
  1222. (void) sigaction(SIGHUP, &savehup, NULL);
  1223. (void) sigaction(SIGINT, &saveint, NULL);
  1224. (void) sigaction(SIGQUIT, &savequit, NULL);
  1225. (void) sigaction(SIGPIPE, &savepipe, NULL);
  1226. (void) sigaction(SIGTERM, &saveterm, NULL);
  1227. (void) sigaction(SIGTSTP, &savetstp, NULL);
  1228. (void) sigaction(SIGTTIN, &savettin, NULL);
  1229. (void) sigaction(SIGTTOU, &savettou, NULL);
  1230. close(input);
  1231. /* Send signals pending */
  1232. for (i = 0; i < NSIG; i++) {
  1233. if (saved_signo[i]) {
  1234. kill(getpid(), i);
  1235. switch (i) {
  1236. case SIGTSTP:
  1237. case SIGTTIN:
  1238. case SIGTTOU:
  1239. goto restart;
  1240. }
  1241. }
  1242. }
  1243. return (p - buf);
  1244. #endif
  1245. }
  1246. #ifdef HAVE_CLOCK_GETTIME
  1247. #ifdef CLOCK_MONOTONIC_COARSE
  1248. #define RSPAMD_FAST_MONOTONIC_CLOCK CLOCK_MONOTONIC_COARSE
  1249. #elif defined(CLOCK_MONOTONIC_FAST)
  1250. #define RSPAMD_FAST_MONOTONIC_CLOCK CLOCK_MONOTONIC_FAST
  1251. #else
  1252. #define RSPAMD_FAST_MONOTONIC_CLOCK CLOCK_MONOTONIC
  1253. #endif
  1254. #endif
  1255. double
  1256. rspamd_get_ticks(gboolean rdtsc_ok)
  1257. {
  1258. double res;
  1259. #ifdef HAVE_RDTSC
  1260. #ifdef __x86_64__
  1261. uint64_t r64;
  1262. if (rdtsc_ok) {
  1263. __builtin_ia32_lfence();
  1264. r64 = __rdtsc();
  1265. /* Preserve lower 52 bits */
  1266. res = r64 & ((1ULL << 53) - 1);
  1267. return res;
  1268. }
  1269. #endif
  1270. #endif
  1271. #ifdef HAVE_CLOCK_GETTIME
  1272. struct timespec ts;
  1273. int clk_id = RSPAMD_FAST_MONOTONIC_CLOCK;
  1274. clock_gettime(clk_id, &ts);
  1275. if (rdtsc_ok) {
  1276. res = (double) ts.tv_sec * 1e9 + ts.tv_nsec;
  1277. }
  1278. else {
  1279. res = (double) ts.tv_sec + ts.tv_nsec / 1000000000.;
  1280. }
  1281. #elif defined(__APPLE__)
  1282. if (rdtsc_ok) {
  1283. res = mach_absolute_time();
  1284. }
  1285. else {
  1286. res = mach_absolute_time() / 1000000000.;
  1287. }
  1288. #else
  1289. struct timeval tv;
  1290. (void) gettimeofday(&tv, NULL);
  1291. if (rdtsc_ok) {
  1292. res = (double) ts.tv_sec * 1e9 + tv.tv_usec * 1e3;
  1293. }
  1294. else {
  1295. res = (double) tv.tv_sec + tv.tv_usec / 1000000.;
  1296. }
  1297. #endif
  1298. return res;
  1299. }
  1300. double
  1301. rspamd_get_virtual_ticks(void)
  1302. {
  1303. double res;
  1304. #ifdef HAVE_CLOCK_GETTIME
  1305. struct timespec ts;
  1306. static clockid_t cid = (clockid_t) -1;
  1307. if (cid == (clockid_t) -1) {
  1308. #ifdef HAVE_CLOCK_GETCPUCLOCKID
  1309. if (clock_getcpuclockid(0, &cid) == -1) {
  1310. #endif
  1311. #ifdef CLOCK_PROCESS_CPUTIME_ID
  1312. cid = CLOCK_PROCESS_CPUTIME_ID;
  1313. #elif defined(CLOCK_PROF)
  1314. cid = CLOCK_PROF;
  1315. #else
  1316. cid = CLOCK_REALTIME;
  1317. #endif
  1318. #ifdef HAVE_CLOCK_GETCPUCLOCKID
  1319. }
  1320. #endif
  1321. }
  1322. clock_gettime(cid, &ts);
  1323. res = (double) ts.tv_sec + ts.tv_nsec / 1000000000.;
  1324. #elif defined(__APPLE__)
  1325. thread_port_t thread = mach_thread_self();
  1326. mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
  1327. thread_basic_info_data_t info;
  1328. if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count) != KERN_SUCCESS) {
  1329. return -1;
  1330. }
  1331. res = info.user_time.seconds + info.system_time.seconds;
  1332. res += ((double) (info.user_time.microseconds + info.system_time.microseconds)) / 1e6;
  1333. mach_port_deallocate(mach_task_self(), thread);
  1334. #elif defined(HAVE_RUSAGE_SELF)
  1335. struct rusage rusage;
  1336. if (getrusage(RUSAGE_SELF, &rusage) != -1) {
  1337. res = (double) rusage.ru_utime.tv_sec +
  1338. (double) rusage.ru_utime.tv_usec / 1000000.0;
  1339. }
  1340. #else
  1341. res = clock() / (double) CLOCKS_PER_SEC;
  1342. #endif
  1343. return res;
  1344. }
  1345. double
  1346. rspamd_get_calendar_ticks(void)
  1347. {
  1348. double res;
  1349. #ifdef HAVE_CLOCK_GETTIME
  1350. struct timespec ts;
  1351. clock_gettime(CLOCK_REALTIME, &ts);
  1352. res = ts_to_double(&ts);
  1353. #else
  1354. struct timeval tv;
  1355. if (gettimeofday(&tv, NULL) == 0) {
  1356. res = tv_to_double(&tv);
  1357. }
  1358. else {
  1359. res = time(NULL);
  1360. }
  1361. #endif
  1362. return res;
  1363. }
  1364. void rspamd_random_hex(char *buf, uint64_t len)
  1365. {
  1366. static const char hexdigests[16] = "0123456789abcdef";
  1367. int64_t i;
  1368. g_assert(len > 0);
  1369. ottery_rand_bytes((void *) buf, ceil(len / 2.0));
  1370. for (i = (int64_t) len - 1; i >= 0; i -= 2) {
  1371. buf[i] = hexdigests[buf[i / 2] & 0xf];
  1372. if (i > 0) {
  1373. buf[i - 1] = hexdigests[(buf[i / 2] >> 4) & 0xf];
  1374. }
  1375. }
  1376. }
  1377. int rspamd_shmem_mkstemp(char *pattern)
  1378. {
  1379. int fd = -1;
  1380. char *nbuf, *xpos;
  1381. gsize blen;
  1382. xpos = strchr(pattern, 'X');
  1383. if (xpos == NULL) {
  1384. errno = EINVAL;
  1385. return -1;
  1386. }
  1387. blen = strlen(pattern);
  1388. nbuf = g_malloc(blen + 1);
  1389. rspamd_strlcpy(nbuf, pattern, blen + 1);
  1390. xpos = nbuf + (xpos - pattern);
  1391. for (;;) {
  1392. rspamd_random_hex(xpos, blen - (xpos - nbuf));
  1393. fd = shm_open(nbuf, O_RDWR | O_EXCL | O_CREAT, 0600);
  1394. if (fd != -1) {
  1395. rspamd_strlcpy(pattern, nbuf, blen + 1);
  1396. break;
  1397. }
  1398. else if (errno != EEXIST) {
  1399. g_free(nbuf);
  1400. return -1;
  1401. }
  1402. }
  1403. g_free(nbuf);
  1404. return fd;
  1405. }
  1406. void rspamd_ptr_array_free_hard(gpointer p)
  1407. {
  1408. GPtrArray *ar = (GPtrArray *) p;
  1409. g_ptr_array_free(ar, TRUE);
  1410. }
  1411. void rspamd_array_free_hard(gpointer p)
  1412. {
  1413. GArray *ar = (GArray *) p;
  1414. g_array_free(ar, TRUE);
  1415. }
  1416. void rspamd_gstring_free_hard(gpointer p)
  1417. {
  1418. GString *ar = (GString *) p;
  1419. g_string_free(ar, TRUE);
  1420. }
  1421. void rspamd_gerror_free_maybe(gpointer p)
  1422. {
  1423. GError **err;
  1424. if (p) {
  1425. err = (GError **) p;
  1426. if (*err) {
  1427. g_error_free(*err);
  1428. }
  1429. }
  1430. }
  1431. /*
  1432. * Openblas creates threads that are not supported by
  1433. * jemalloc allocator (aside of being bloody stupid). So this hack
  1434. * is intended to set number of threads to one by default.
  1435. * FIXME: is it legit to do so in ctor?
  1436. */
  1437. #ifdef HAVE_OPENBLAS_SET_NUM_THREADS
  1438. extern void openblas_set_num_threads(int num_threads);
  1439. RSPAMD_CONSTRUCTOR(openblas_thread_fix_ctor)
  1440. {
  1441. openblas_set_num_threads(1);
  1442. }
  1443. #endif
  1444. #ifdef HAVE_BLI_THREAD_SET_NUM_THREADS
  1445. extern void bli_thread_set_num_threads(int num_threads);
  1446. RSPAMD_CONSTRUCTOR(blis_thread_fix_ctor)
  1447. {
  1448. bli_thread_set_num_threads(1);
  1449. }
  1450. #endif
  1451. uint64_t
  1452. rspamd_hash_seed(void)
  1453. {
  1454. #if 0
  1455. static uint64_t seed;
  1456. if (seed == 0) {
  1457. seed = ottery_rand_uint64 ();
  1458. }
  1459. #endif
  1460. /* Proved to be random, I promise! */
  1461. /*
  1462. * TODO: discover if it worth to use random seed on run
  1463. * with ordinary hash function or we need to switch to
  1464. * siphash1-3 or other slow cooker function...
  1465. */
  1466. return 0xabf9727ba290690bULL;
  1467. }
  1468. static inline double
  1469. rspamd_double_from_int64(uint64_t x)
  1470. {
  1471. const union {
  1472. uint64_t i;
  1473. double d;
  1474. } u = {
  1475. .i = G_GUINT64_CONSTANT(0x3FF) << 52 | x >> 12};
  1476. return u.d - 1.0;
  1477. }
  1478. double
  1479. rspamd_random_double(void)
  1480. {
  1481. uint64_t rnd_int;
  1482. rnd_int = ottery_rand_uint64();
  1483. return rspamd_double_from_int64(rnd_int);
  1484. }
  1485. static uint64_t *
  1486. rspamd_fast_random_seed(void)
  1487. {
  1488. static uint64_t seed;
  1489. if (G_UNLIKELY(seed == 0)) {
  1490. ottery_rand_bytes((void *) &seed, sizeof(seed));
  1491. }
  1492. return &seed;
  1493. }
  1494. /* wyrand */
  1495. inline uint64_t
  1496. rspamd_random_uint64_fast_seed(uint64_t *seed)
  1497. {
  1498. *seed += UINT64_C(0xa0761d6478bd642f);
  1499. #ifdef __SIZEOF_INT128__
  1500. #if defined(__aarch64__)
  1501. uint64_t lo, hi, p = *seed ^ UINT64_C(0xe7037ed1a0b428db), v = *seed;
  1502. lo = v * p;
  1503. __asm__("umulh %0, %1, %2"
  1504. : "=r"(hi)
  1505. : "r"(v), "r"(p));
  1506. return lo ^ hi;
  1507. #else
  1508. __uint128_t t = (__uint128_t) *seed * (*seed ^ UINT64_C(0xe7037ed1a0b428db));
  1509. return (t >> 64) ^ t;
  1510. #endif
  1511. #else
  1512. /* Implementation of 64x64->128-bit multiplication by four 32x32->64
  1513. * bit multiplication. */
  1514. uint64_t lo, hi, p = *seed ^ UINT64_C(0xe7037ed1a0b428db), v = *seed;
  1515. uint64_t hv = v >> 32, hp = p >> 32;
  1516. uint64_t lv = (uint32_t) v, lp = (uint32_t) p;
  1517. uint64_t rh = hv * hp;
  1518. uint64_t rm_0 = hv * lp;
  1519. uint64_t rm_1 = hp * lv;
  1520. uint64_t rl = lv * lp;
  1521. uint64_t t;
  1522. /* We could ignore a carry bit here if we did not care about the
  1523. same hash for 32-bit and 64-bit targets. */
  1524. t = rl + (rm_0 << 32);
  1525. lo = t + (rm_1 << 32);
  1526. hi = rh + (rm_0 >> 32) + (rm_1 >> 32);
  1527. return lo ^ hi;
  1528. #endif
  1529. }
  1530. double
  1531. rspamd_random_double_fast(void)
  1532. {
  1533. return rspamd_random_double_fast_seed(rspamd_fast_random_seed());
  1534. }
  1535. /* xoshiro256+ */
  1536. inline double
  1537. rspamd_random_double_fast_seed(uint64_t *seed)
  1538. {
  1539. return rspamd_double_from_int64(rspamd_random_uint64_fast_seed(seed));
  1540. }
  1541. uint64_t
  1542. rspamd_random_uint64_fast(void)
  1543. {
  1544. return rspamd_random_uint64_fast_seed(rspamd_fast_random_seed());
  1545. }
  1546. void rspamd_random_seed_fast(void)
  1547. {
  1548. (void) rspamd_fast_random_seed();
  1549. }
  1550. double
  1551. rspamd_time_jitter(double in, double jitter)
  1552. {
  1553. if (jitter == 0) {
  1554. jitter = in;
  1555. }
  1556. return in + jitter * rspamd_random_double();
  1557. }
  1558. gboolean
  1559. rspamd_constant_memcmp(const void *a, const void *b, gsize len)
  1560. {
  1561. gsize lena, lenb, i;
  1562. uint16_t d, r = 0, m;
  1563. uint16_t v;
  1564. const uint8_t *aa = (const uint8_t *) a,
  1565. *bb = (const uint8_t *) b;
  1566. if (len == 0) {
  1567. lena = strlen((const char *) a);
  1568. lenb = strlen((const char *) b);
  1569. if (lena != lenb) {
  1570. return FALSE;
  1571. }
  1572. len = lena;
  1573. }
  1574. for (i = 0; i < len; i++) {
  1575. v = ((uint16_t) (uint8_t) r) + 255;
  1576. m = v / 256 - 1;
  1577. d = (uint16_t) ((int) aa[i] - (int) bb[i]);
  1578. r |= (d & m);
  1579. }
  1580. return (((int32_t) (uint16_t) ((uint32_t) r + 0x8000) - 0x8000) == 0);
  1581. }
  1582. int rspamd_file_xopen(const char *fname, int oflags, unsigned int mode,
  1583. gboolean allow_symlink)
  1584. {
  1585. struct stat sb;
  1586. int fd, flags = oflags;
  1587. if (!(oflags & O_CREAT)) {
  1588. if (lstat(fname, &sb) == -1) {
  1589. if (errno != ENOENT) {
  1590. return (-1);
  1591. }
  1592. }
  1593. else if (!S_ISREG(sb.st_mode)) {
  1594. if (S_ISLNK(sb.st_mode)) {
  1595. if (!allow_symlink) {
  1596. return -1;
  1597. }
  1598. }
  1599. else {
  1600. return -1;
  1601. }
  1602. }
  1603. }
  1604. #ifdef HAVE_OCLOEXEC
  1605. flags |= O_CLOEXEC;
  1606. #endif
  1607. #ifdef HAVE_ONOFOLLOW
  1608. if (!allow_symlink) {
  1609. flags |= O_NOFOLLOW;
  1610. fd = open(fname, flags, mode);
  1611. }
  1612. else {
  1613. fd = open(fname, flags, mode);
  1614. }
  1615. #else
  1616. fd = open(fname, flags, mode);
  1617. #endif
  1618. #ifndef HAVE_OCLOEXEC
  1619. int serrno;
  1620. if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
  1621. serrno = errno;
  1622. close(fd);
  1623. errno = serrno;
  1624. return -1;
  1625. }
  1626. #endif
  1627. return (fd);
  1628. }
  1629. gpointer
  1630. rspamd_file_xmap(const char *fname, unsigned int mode, gsize *size,
  1631. gboolean allow_symlink)
  1632. {
  1633. int fd;
  1634. struct stat sb;
  1635. gpointer map;
  1636. g_assert(fname != NULL);
  1637. g_assert(size != NULL);
  1638. if (mode & PROT_WRITE) {
  1639. fd = rspamd_file_xopen(fname, O_RDWR, 0, allow_symlink);
  1640. }
  1641. else {
  1642. fd = rspamd_file_xopen(fname, O_RDONLY, 0, allow_symlink);
  1643. }
  1644. if (fd == -1) {
  1645. return NULL;
  1646. }
  1647. if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) {
  1648. close(fd);
  1649. *size = (gsize) -1;
  1650. return NULL;
  1651. }
  1652. if (sb.st_size == 0) {
  1653. close(fd);
  1654. *size = (gsize) 0;
  1655. return NULL;
  1656. }
  1657. map = mmap(NULL, sb.st_size, mode, MAP_SHARED, fd, 0);
  1658. close(fd);
  1659. if (map == MAP_FAILED) {
  1660. return NULL;
  1661. }
  1662. *size = sb.st_size;
  1663. return map;
  1664. }
  1665. gpointer
  1666. rspamd_shmem_xmap(const char *fname, unsigned int mode,
  1667. gsize *size)
  1668. {
  1669. int fd;
  1670. struct stat sb;
  1671. gpointer map;
  1672. g_assert(fname != NULL);
  1673. g_assert(size != NULL);
  1674. #ifdef HAVE_SANE_SHMEM
  1675. if (mode & PROT_WRITE) {
  1676. fd = shm_open(fname, O_RDWR, 0);
  1677. }
  1678. else {
  1679. fd = shm_open(fname, O_RDONLY, 0);
  1680. }
  1681. #else
  1682. if (mode & PROT_WRITE) {
  1683. fd = open(fname, O_RDWR, 0);
  1684. }
  1685. else {
  1686. fd = open(fname, O_RDONLY, 0);
  1687. }
  1688. #endif
  1689. if (fd == -1) {
  1690. return NULL;
  1691. }
  1692. if (fstat(fd, &sb) == -1) {
  1693. close(fd);
  1694. return NULL;
  1695. }
  1696. map = mmap(NULL, sb.st_size, mode, MAP_SHARED, fd, 0);
  1697. close(fd);
  1698. if (map == MAP_FAILED) {
  1699. return NULL;
  1700. }
  1701. *size = sb.st_size;
  1702. return map;
  1703. }
  1704. /*
  1705. * A(x - 0.5)^4 + B(x - 0.5)^3 + C(x - 0.5)^2 + D(x - 0.5)
  1706. * A = 32,
  1707. * B = -6
  1708. * C = -7
  1709. * D = 3
  1710. * y = 32(x - 0.5)^4 - 6(x - 0.5)^3 - 7(x - 0.5)^2 + 3(x - 0.5)
  1711. *
  1712. * New approach:
  1713. * y = ((x - bias)*2)^8
  1714. */
  1715. double
  1716. rspamd_normalize_probability(double x, double bias)
  1717. {
  1718. double xx;
  1719. xx = (x - bias) * 2.0;
  1720. return pow(xx, 8);
  1721. }
  1722. /*
  1723. * Calculations from musl libc
  1724. */
  1725. uint64_t
  1726. rspamd_tm_to_time(const struct tm *tm, glong tz)
  1727. {
  1728. uint64_t result;
  1729. gboolean is_leap = FALSE;
  1730. int leaps, y = tm->tm_year, cycles, rem, centuries;
  1731. glong offset = (tz / 100) * 3600 + (tz % 100) * 60;
  1732. /* How many seconds in each month from the beginning of the year */
  1733. static const int secs_through_month[] = {
  1734. 0, 31 * 86400, 59 * 86400, 90 * 86400,
  1735. 120 * 86400, 151 * 86400, 181 * 86400, 212 * 86400,
  1736. 243 * 86400, 273 * 86400, 304 * 86400, 334 * 86400};
  1737. /* Convert year */
  1738. if (tm->tm_year - 2ULL <= 136) {
  1739. leaps = (y - 68) / 4;
  1740. if (!((y - 68) & 3)) {
  1741. leaps--;
  1742. is_leap = 1;
  1743. }
  1744. result = 31536000 * (y - 70) + 86400 * leaps;
  1745. }
  1746. else {
  1747. cycles = (y - 100) / 400;
  1748. rem = (y - 100) % 400;
  1749. if (rem < 0) {
  1750. cycles--;
  1751. rem += 400;
  1752. }
  1753. if (!rem) {
  1754. is_leap = 1;
  1755. centuries = 0;
  1756. leaps = 0;
  1757. }
  1758. else {
  1759. if (rem >= 200) {
  1760. if (rem >= 300) {
  1761. centuries = 3;
  1762. rem -= 300;
  1763. }
  1764. else {
  1765. centuries = 2;
  1766. rem -= 200;
  1767. }
  1768. }
  1769. else {
  1770. if (rem >= 100) {
  1771. centuries = 1;
  1772. rem -= 100;
  1773. }
  1774. else {
  1775. centuries = 0;
  1776. }
  1777. }
  1778. if (!rem) {
  1779. is_leap = 1;
  1780. leaps = 0;
  1781. }
  1782. else {
  1783. leaps = rem / 4U;
  1784. rem %= 4U;
  1785. is_leap = !rem;
  1786. }
  1787. }
  1788. leaps += 97 * cycles + 24 * centuries - (int) is_leap;
  1789. result = (y - 100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
  1790. }
  1791. /* Now convert months to seconds */
  1792. result += secs_through_month[tm->tm_mon];
  1793. /* One more day */
  1794. if (is_leap && tm->tm_mon >= 2) {
  1795. result += 86400;
  1796. }
  1797. result += 86400LL * (tm->tm_mday - 1);
  1798. result += 3600LL * tm->tm_hour;
  1799. result += 60LL * tm->tm_min;
  1800. result += tm->tm_sec;
  1801. /* Now apply tz offset */
  1802. result -= offset;
  1803. return result;
  1804. }
  1805. void rspamd_gmtime(int64_t ts, struct tm *dest)
  1806. {
  1807. uint64_t days, secs, years;
  1808. int remdays, remsecs, remyears;
  1809. int leap_400_cycles, leap_100_cycles, leap_4_cycles;
  1810. int months;
  1811. int wday, yday, leap;
  1812. /* From March */
  1813. static const uint8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
  1814. static const uint64_t leap_epoch = 946684800ULL + 86400 * (31 + 29);
  1815. static const uint64_t days_per_400y = 365 * 400 + 97;
  1816. static const uint64_t days_per_100y = 365 * 100 + 24;
  1817. static const uint64_t days_per_4y = 365 * 4 + 1;
  1818. secs = ts - leap_epoch;
  1819. days = secs / 86400;
  1820. remsecs = secs % 86400;
  1821. if (remsecs < 0) {
  1822. remsecs += 86400;
  1823. days--;
  1824. }
  1825. wday = (3 + days) % 7;
  1826. if (wday < 0) {
  1827. wday += 7;
  1828. }
  1829. /* Deal with gregorian adjustments */
  1830. leap_400_cycles = days / days_per_400y;
  1831. remdays = days % days_per_400y;
  1832. if (remdays < 0) {
  1833. remdays += days_per_400y;
  1834. leap_400_cycles--;
  1835. }
  1836. leap_100_cycles = remdays / days_per_100y;
  1837. if (leap_100_cycles == 4) {
  1838. /* 400 years */
  1839. leap_100_cycles--;
  1840. }
  1841. remdays -= leap_100_cycles * days_per_100y;
  1842. leap_4_cycles = remdays / days_per_4y;
  1843. if (leap_4_cycles == 25) {
  1844. /* 100 years */
  1845. leap_4_cycles--;
  1846. }
  1847. remdays -= leap_4_cycles * days_per_4y;
  1848. remyears = remdays / 365;
  1849. if (remyears == 4) {
  1850. /* Ordinary leap year */
  1851. remyears--;
  1852. }
  1853. remdays -= remyears * 365;
  1854. leap = !remyears && (leap_4_cycles || !leap_100_cycles);
  1855. yday = remdays + 31 + 28 + leap;
  1856. if (yday >= 365 + leap) {
  1857. yday -= 365 + leap;
  1858. }
  1859. years = remyears + 4 * leap_4_cycles + 100 * leap_100_cycles +
  1860. 400ULL * leap_400_cycles;
  1861. for (months = 0; days_in_month[months] <= remdays; months++) {
  1862. remdays -= days_in_month[months];
  1863. }
  1864. if (months >= 10) {
  1865. months -= 12;
  1866. years++;
  1867. }
  1868. dest->tm_year = years + 100;
  1869. dest->tm_mon = months + 2;
  1870. dest->tm_mday = remdays + 1;
  1871. dest->tm_wday = wday;
  1872. dest->tm_yday = yday;
  1873. dest->tm_hour = remsecs / 3600;
  1874. dest->tm_min = remsecs / 60 % 60;
  1875. dest->tm_sec = remsecs % 60;
  1876. #if !defined(__sun)
  1877. dest->tm_gmtoff = 0;
  1878. dest->tm_zone = "GMT";
  1879. #endif
  1880. }
  1881. void rspamd_localtime(int64_t ts, struct tm *dest)
  1882. {
  1883. time_t t = ts;
  1884. localtime_r(&t, dest);
  1885. }
  1886. gboolean
  1887. rspamd_fstring_gzip(rspamd_fstring_t **in)
  1888. {
  1889. z_stream strm;
  1890. rspamd_fstring_t *buf = *in;
  1891. int ret;
  1892. unsigned tmp_remain;
  1893. unsigned char temp[BUFSIZ];
  1894. memset(&strm, 0, sizeof(strm));
  1895. ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
  1896. MAX_WBITS + 16, MAX_MEM_LEVEL - 1, Z_DEFAULT_STRATEGY);
  1897. if (ret != Z_OK) {
  1898. return FALSE;
  1899. }
  1900. if (buf->allocated < deflateBound(&strm, buf->len)) {
  1901. buf = rspamd_fstring_grow(buf, deflateBound(&strm, buf->len));
  1902. *in = buf;
  1903. }
  1904. strm.next_in = buf->str;
  1905. strm.avail_in = buf->len;
  1906. strm.next_out = temp;
  1907. strm.avail_out = sizeof(temp) > buf->allocated ? buf->allocated : sizeof(temp);
  1908. ret = deflate(&strm, Z_FINISH);
  1909. if (ret == Z_STREAM_ERROR) {
  1910. deflateEnd(&strm);
  1911. return FALSE;
  1912. }
  1913. /* Try to compress in-place */
  1914. tmp_remain = strm.next_out - temp;
  1915. if (tmp_remain <= (strm.avail_in ? buf->len - strm.avail_in : buf->allocated)) {
  1916. memcpy(buf->str, temp, tmp_remain);
  1917. strm.next_out = (unsigned char *) buf->str + tmp_remain;
  1918. tmp_remain = 0;
  1919. while (ret == Z_OK) {
  1920. strm.avail_out = strm.avail_in ? strm.next_in - strm.next_out : ((unsigned char *) buf->str + buf->allocated) - strm.next_out;
  1921. ret = deflate(&strm, Z_FINISH);
  1922. }
  1923. if (ret != Z_BUF_ERROR || strm.avail_in == 0) {
  1924. buf->len = strm.next_out - (unsigned char *) buf->str;
  1925. *in = buf;
  1926. deflateEnd(&strm);
  1927. return ret == Z_STREAM_END;
  1928. }
  1929. }
  1930. /*
  1931. * The case when input and output has caught each other, hold the remaining
  1932. * in a temporary buffer and compress it separately
  1933. */
  1934. unsigned char *hold = g_malloc(strm.avail_in);
  1935. memcpy(hold, strm.next_in, strm.avail_in);
  1936. strm.next_in = hold;
  1937. if (tmp_remain) {
  1938. memcpy(buf->str, temp, tmp_remain);
  1939. strm.next_out = (unsigned char *) buf->str + tmp_remain;
  1940. }
  1941. strm.avail_out = ((unsigned char *) buf->str + buf->allocated) - strm.next_out;
  1942. ret = deflate(&strm, Z_FINISH);
  1943. g_free(hold);
  1944. buf->len = strm.next_out - (unsigned char *) buf->str;
  1945. *in = buf;
  1946. deflateEnd(&strm);
  1947. return ret == Z_STREAM_END;
  1948. }
  1949. gboolean
  1950. rspamd_fstring_gunzip(rspamd_fstring_t **in)
  1951. {
  1952. z_stream strm;
  1953. rspamd_fstring_t *buf = *in, *out = rspamd_fstring_sized_new((*in)->len);
  1954. int ret;
  1955. memset(&strm, 0, sizeof(strm));
  1956. ret = inflateInit2(&strm, MAX_WBITS + 16);
  1957. if (ret != Z_OK) {
  1958. return FALSE;
  1959. }
  1960. strm.next_in = buf->str;
  1961. strm.avail_in = buf->len;
  1962. gsize total_out = 0;
  1963. do {
  1964. strm.next_out = out->str + total_out;
  1965. strm.avail_out = out->allocated - total_out;
  1966. ret = inflate(&strm, Z_NO_FLUSH);
  1967. if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
  1968. break;
  1969. }
  1970. gsize out_remain = strm.avail_out;
  1971. total_out = out->allocated - out_remain;
  1972. if (out_remain == 0 && ret != Z_STREAM_END) {
  1973. out = rspamd_fstring_grow(out, out->allocated * 2);
  1974. }
  1975. } while (ret != Z_STREAM_END);
  1976. if (ret == Z_STREAM_END) {
  1977. *in = out;
  1978. out->len = total_out;
  1979. rspamd_fstring_free(buf);
  1980. }
  1981. else {
  1982. /* Revert */
  1983. *in = buf;
  1984. rspamd_fstring_free(out);
  1985. }
  1986. inflateEnd(&strm);
  1987. return ret == Z_STREAM_END;
  1988. }
  1989. static gboolean
  1990. rspamd_glob_dir(const char *full_path, const char *pattern,
  1991. gboolean recursive, unsigned int rec_len,
  1992. GPtrArray *res, GError **err)
  1993. {
  1994. glob_t globbuf;
  1995. const char *path;
  1996. static char pathbuf[PATH_MAX]; /* Static to help recursion */
  1997. unsigned int i;
  1998. int rc;
  1999. static const unsigned int rec_lim = 16;
  2000. struct stat st;
  2001. if (rec_len > rec_lim) {
  2002. g_set_error(err, g_quark_from_static_string("glob"), EOVERFLOW,
  2003. "maximum nesting is reached: %d", rec_lim);
  2004. return FALSE;
  2005. }
  2006. memset(&globbuf, 0, sizeof(globbuf));
  2007. if ((rc = glob(full_path, 0, NULL, &globbuf)) != 0) {
  2008. if (rc != GLOB_NOMATCH) {
  2009. g_set_error(err, g_quark_from_static_string("glob"), errno,
  2010. "glob %s failed: %s", full_path, strerror(errno));
  2011. globfree(&globbuf);
  2012. return FALSE;
  2013. }
  2014. else {
  2015. globfree(&globbuf);
  2016. return TRUE;
  2017. }
  2018. }
  2019. for (i = 0; i < globbuf.gl_pathc; i++) {
  2020. path = globbuf.gl_pathv[i];
  2021. if (stat(path, &st) == -1) {
  2022. if (errno == EPERM || errno == EACCES || errno == ELOOP) {
  2023. /* Silently ignore */
  2024. continue;
  2025. }
  2026. g_set_error(err, g_quark_from_static_string("glob"), errno,
  2027. "stat %s failed: %s", path, strerror(errno));
  2028. globfree(&globbuf);
  2029. return FALSE;
  2030. }
  2031. if (S_ISREG(st.st_mode)) {
  2032. g_ptr_array_add(res, g_strdup(path));
  2033. }
  2034. else if (recursive && S_ISDIR(st.st_mode)) {
  2035. rspamd_snprintf(pathbuf, sizeof(pathbuf), "%s%c%s",
  2036. path, G_DIR_SEPARATOR, pattern);
  2037. if (!rspamd_glob_dir(full_path, pattern, recursive, rec_len + 1,
  2038. res, err)) {
  2039. globfree(&globbuf);
  2040. return FALSE;
  2041. }
  2042. }
  2043. }
  2044. globfree(&globbuf);
  2045. return TRUE;
  2046. }
  2047. GPtrArray *
  2048. rspamd_glob_path(const char *dir,
  2049. const char *pattern,
  2050. gboolean recursive,
  2051. GError **err)
  2052. {
  2053. char path[PATH_MAX];
  2054. GPtrArray *res;
  2055. res = g_ptr_array_new_full(32, (GDestroyNotify) g_free);
  2056. rspamd_snprintf(path, sizeof(path), "%s%c%s", dir, G_DIR_SEPARATOR, pattern);
  2057. if (!rspamd_glob_dir(path, pattern, recursive, 0, res, err)) {
  2058. g_ptr_array_free(res, TRUE);
  2059. return NULL;
  2060. }
  2061. return res;
  2062. }
  2063. double
  2064. rspamd_set_counter(struct rspamd_counter_data *cd, double value)
  2065. {
  2066. double cerr;
  2067. /* Cumulative moving average using per-process counter data */
  2068. if (cd->number == 0) {
  2069. cd->mean = 0;
  2070. cd->stddev = 0;
  2071. }
  2072. cd->mean += (value - cd->mean) / (double) (++cd->number);
  2073. cerr = (value - cd->mean) * (value - cd->mean);
  2074. cd->stddev += (cerr - cd->stddev) / (double) (cd->number);
  2075. return cd->mean;
  2076. }
  2077. float rspamd_set_counter_ema(struct rspamd_counter_data *cd,
  2078. float value,
  2079. float alpha)
  2080. {
  2081. float diff, incr;
  2082. /* Cumulative moving average using per-process counter data */
  2083. if (cd->number == 0) {
  2084. cd->mean = 0;
  2085. cd->stddev = 0;
  2086. }
  2087. diff = value - cd->mean;
  2088. incr = diff * alpha;
  2089. cd->mean += incr;
  2090. cd->stddev = (1.0f - alpha) * (cd->stddev + diff * incr);
  2091. cd->number++;
  2092. return cd->mean;
  2093. }
  2094. void rspamd_ptr_array_shuffle(GPtrArray *ar)
  2095. {
  2096. if (ar->len < 2) {
  2097. return;
  2098. }
  2099. unsigned int n = ar->len;
  2100. for (unsigned int i = 0; i < n - 1; i++) {
  2101. unsigned int j = i + rspamd_random_uint64_fast() % (n - i);
  2102. gpointer t = g_ptr_array_index(ar, j);
  2103. g_ptr_array_index(ar, j) = g_ptr_array_index(ar, i);
  2104. g_ptr_array_index(ar, i) = t;
  2105. }
  2106. }
  2107. float rspamd_sum_floats(float *ar, gsize *nelts)
  2108. {
  2109. float sum = 0.0f;
  2110. volatile float c = 0.0f; /* We don't want any optimisations around c */
  2111. gsize cnt = 0;
  2112. for (gsize i = 0; i < *nelts; i++) {
  2113. float elt = ar[i];
  2114. if (!isnan(elt)) {
  2115. cnt++;
  2116. float y = elt - c;
  2117. float t = sum + y;
  2118. c = (t - sum) - y;
  2119. sum = t;
  2120. }
  2121. }
  2122. *nelts = cnt;
  2123. return sum;
  2124. }
  2125. void rspamd_normalize_path_inplace(char *path, unsigned int len, gsize *nlen)
  2126. {
  2127. const char *p, *end, *slash = NULL, *dot = NULL;
  2128. char *o;
  2129. enum {
  2130. st_normal = 0,
  2131. st_got_dot,
  2132. st_got_dot_dot,
  2133. st_got_slash,
  2134. st_got_slash_slash,
  2135. } state = st_normal;
  2136. p = path;
  2137. end = path + len;
  2138. o = path;
  2139. while (p < end) {
  2140. switch (state) {
  2141. case st_normal:
  2142. if (G_UNLIKELY(*p == '/')) {
  2143. state = st_got_slash;
  2144. slash = p;
  2145. }
  2146. else if (G_UNLIKELY(*p == '.')) {
  2147. state = st_got_dot;
  2148. dot = p;
  2149. }
  2150. else {
  2151. *o++ = *p;
  2152. }
  2153. p++;
  2154. break;
  2155. case st_got_slash:
  2156. if (G_UNLIKELY(*p == '/')) {
  2157. /* Ignore double slash */
  2158. *o++ = *p;
  2159. state = st_got_slash_slash;
  2160. }
  2161. else if (G_UNLIKELY(*p == '.')) {
  2162. dot = p;
  2163. state = st_got_dot;
  2164. }
  2165. else {
  2166. *o++ = '/';
  2167. *o++ = *p;
  2168. slash = NULL;
  2169. dot = NULL;
  2170. state = st_normal;
  2171. }
  2172. p++;
  2173. break;
  2174. case st_got_slash_slash:
  2175. if (G_LIKELY(*p != '/')) {
  2176. slash = p - 1;
  2177. dot = NULL;
  2178. state = st_normal;
  2179. continue;
  2180. }
  2181. p++;
  2182. break;
  2183. case st_got_dot:
  2184. if (G_UNLIKELY(*p == '/')) {
  2185. /* Remove any /./ or ./ paths */
  2186. if (((o > path && *(o - 1) != '/') || (o == path)) && slash) {
  2187. /* Preserve one slash */
  2188. *o++ = '/';
  2189. }
  2190. slash = p;
  2191. dot = NULL;
  2192. /* Ignore last slash */
  2193. state = st_normal;
  2194. }
  2195. else if (*p == '.') {
  2196. /* Double dot character */
  2197. state = st_got_dot_dot;
  2198. }
  2199. else {
  2200. /* We have something like .some or /.some */
  2201. if (dot && p > dot) {
  2202. if (slash == dot - 1 && (o > path && *(o - 1) != '/')) {
  2203. /* /.blah */
  2204. memmove(o, slash, p - slash);
  2205. o += p - slash;
  2206. }
  2207. else {
  2208. memmove(o, dot, p - dot);
  2209. o += p - dot;
  2210. }
  2211. }
  2212. slash = NULL;
  2213. dot = NULL;
  2214. state = st_normal;
  2215. continue;
  2216. }
  2217. p++;
  2218. break;
  2219. case st_got_dot_dot:
  2220. if (*p == '/') {
  2221. /* We have something like /../ or ../ */
  2222. if (slash) {
  2223. /* We need to remove the last component from o if it is there */
  2224. if (o > path + 2 && *(o - 1) == '/') {
  2225. slash = rspamd_memrchr(path, '/', o - path - 2);
  2226. }
  2227. else if (o > path + 1) {
  2228. slash = rspamd_memrchr(path, '/', o - path - 1);
  2229. }
  2230. else {
  2231. slash = NULL;
  2232. }
  2233. if (slash) {
  2234. o = (char *) slash;
  2235. }
  2236. /* Otherwise we keep these dots */
  2237. slash = p;
  2238. state = st_got_slash;
  2239. }
  2240. else {
  2241. /* We have something like bla../, so we need to copy it as is */
  2242. if (o > path && dot && p > dot) {
  2243. memmove(o, dot, p - dot);
  2244. o += p - dot;
  2245. }
  2246. slash = NULL;
  2247. dot = NULL;
  2248. state = st_normal;
  2249. continue;
  2250. }
  2251. }
  2252. else {
  2253. /* We have something like ..bla or ... */
  2254. if (slash) {
  2255. *o++ = '/';
  2256. }
  2257. if (dot && p > dot) {
  2258. memmove(o, dot, p - dot);
  2259. o += p - dot;
  2260. }
  2261. slash = NULL;
  2262. dot = NULL;
  2263. state = st_normal;
  2264. continue;
  2265. }
  2266. p++;
  2267. break;
  2268. }
  2269. }
  2270. /* Leftover */
  2271. switch (state) {
  2272. case st_got_dot_dot:
  2273. /* Trailing .. */
  2274. if (slash) {
  2275. /* We need to remove the last component from o if it is there */
  2276. if (o > path + 2 && *(o - 1) == '/') {
  2277. slash = rspamd_memrchr(path, '/', o - path - 2);
  2278. }
  2279. else if (o > path + 1) {
  2280. slash = rspamd_memrchr(path, '/', o - path - 1);
  2281. }
  2282. else {
  2283. if (o == path) {
  2284. /* Corner case */
  2285. *o++ = '/';
  2286. }
  2287. slash = NULL;
  2288. }
  2289. if (slash) {
  2290. /* Remove last / */
  2291. o = (char *) slash;
  2292. }
  2293. }
  2294. else {
  2295. /* Corner case */
  2296. if (o == path) {
  2297. *o++ = '/';
  2298. }
  2299. else {
  2300. if (dot && p > dot) {
  2301. memmove(o, dot, p - dot);
  2302. o += p - dot;
  2303. }
  2304. }
  2305. }
  2306. break;
  2307. case st_got_dot:
  2308. if (slash) {
  2309. /* /. -> must be / */
  2310. *o++ = '/';
  2311. }
  2312. else {
  2313. if (o > path) {
  2314. *o++ = '.';
  2315. }
  2316. }
  2317. break;
  2318. case st_got_slash:
  2319. *o++ = '/';
  2320. break;
  2321. default:
  2322. #if 0
  2323. if (o > path + 1 && *(o - 1) == '/') {
  2324. o --;
  2325. }
  2326. #endif
  2327. break;
  2328. }
  2329. if (nlen) {
  2330. *nlen = (o - path);
  2331. }
  2332. }