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.

10 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
13 years ago
9 years ago
9 years ago
9 years ago
9 years ago
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. }