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.

logger.c 31KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. /*
  2. * Copyright 2023 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 "logger.h"
  18. #include "rspamd.h"
  19. #include "libserver/maps/map.h"
  20. #include "libserver/maps/map_helpers.h"
  21. #include "ottery.h"
  22. #include "unix-std.h"
  23. #include "logger_private.h"
  24. static rspamd_logger_t *default_logger = NULL;
  25. static rspamd_logger_t *emergency_logger = NULL;
  26. static struct rspamd_log_modules *log_modules = NULL;
  27. static const gchar lf_chr = '\n';
  28. guint rspamd_task_log_id = (guint) -1;
  29. RSPAMD_CONSTRUCTOR(rspamd_task_log_init)
  30. {
  31. rspamd_task_log_id = rspamd_logger_add_debug_module("task");
  32. }
  33. rspamd_logger_t *
  34. rspamd_log_default_logger(void)
  35. {
  36. return default_logger;
  37. }
  38. rspamd_logger_t *
  39. rspamd_log_emergency_logger(void)
  40. {
  41. return emergency_logger;
  42. }
  43. void rspamd_log_set_log_level(rspamd_logger_t *logger, gint level)
  44. {
  45. if (logger == NULL) {
  46. logger = default_logger;
  47. }
  48. logger->log_level = level;
  49. }
  50. gint rspamd_log_get_log_level(rspamd_logger_t *logger)
  51. {
  52. if (logger == NULL) {
  53. logger = default_logger;
  54. }
  55. return logger->log_level;
  56. }
  57. void rspamd_log_set_log_flags(rspamd_logger_t *logger, gint flags)
  58. {
  59. g_assert(logger != NULL);
  60. logger->flags = flags;
  61. }
  62. void rspamd_log_close(rspamd_logger_t *logger)
  63. {
  64. g_assert(logger != NULL);
  65. if (logger->closed) {
  66. return;
  67. }
  68. logger->closed = TRUE;
  69. if (logger->debug_ip) {
  70. rspamd_map_helper_destroy_radix(logger->debug_ip);
  71. }
  72. if (logger->pk) {
  73. rspamd_pubkey_unref(logger->pk);
  74. }
  75. if (logger->keypair) {
  76. rspamd_keypair_unref(logger->keypair);
  77. }
  78. logger->ops.dtor(logger, logger->ops.specific);
  79. /* TODO: Do we really need that ? */
  80. if (logger == default_logger) {
  81. default_logger = NULL;
  82. }
  83. if (logger == emergency_logger) {
  84. emergency_logger = NULL;
  85. }
  86. if (!logger->pool) {
  87. g_free(logger);
  88. }
  89. }
  90. bool rspamd_log_reopen(rspamd_logger_t *rspamd_log, struct rspamd_config *cfg,
  91. uid_t uid, gid_t gid)
  92. {
  93. void *nspec;
  94. GError *err = NULL;
  95. g_assert(rspamd_log != NULL);
  96. nspec = rspamd_log->ops.reload(rspamd_log, cfg, rspamd_log->ops.specific,
  97. uid, gid, &err);
  98. if (nspec != NULL) {
  99. rspamd_log->ops.specific = nspec;
  100. }
  101. else {
  102. }
  103. return nspec != NULL;
  104. }
  105. static void
  106. rspamd_emergency_logger_dtor(gpointer d)
  107. {
  108. rspamd_logger_t *logger = (rspamd_logger_t *) d;
  109. rspamd_log_close(logger);
  110. }
  111. rspamd_logger_t *
  112. rspamd_log_open_emergency(rspamd_mempool_t *pool, gint flags)
  113. {
  114. rspamd_logger_t *logger;
  115. GError *err = NULL;
  116. g_assert(default_logger == NULL);
  117. g_assert(emergency_logger == NULL);
  118. if (pool) {
  119. logger = rspamd_mempool_alloc0(pool, sizeof(rspamd_logger_t));
  120. logger->mtx = rspamd_mempool_get_mutex(pool);
  121. }
  122. else {
  123. logger = g_malloc0(sizeof(rspamd_logger_t));
  124. }
  125. logger->flags = flags;
  126. logger->pool = pool;
  127. logger->process_type = "main";
  128. logger->pid = getpid();
  129. const struct rspamd_logger_funcs *funcs = &console_log_funcs;
  130. memcpy(&logger->ops, funcs, sizeof(*funcs));
  131. logger->ops.specific = logger->ops.init(logger, NULL, -1, -1, &err);
  132. if (logger->ops.specific == NULL) {
  133. rspamd_fprintf(stderr, "fatal error: cannot init console logging: %e\n",
  134. err);
  135. g_error_free(err);
  136. exit(EXIT_FAILURE);
  137. }
  138. default_logger = logger;
  139. emergency_logger = logger;
  140. rspamd_mempool_add_destructor(pool, rspamd_emergency_logger_dtor,
  141. emergency_logger);
  142. return logger;
  143. }
  144. rspamd_logger_t *
  145. rspamd_log_open_specific(rspamd_mempool_t *pool,
  146. struct rspamd_config *cfg,
  147. const gchar *ptype,
  148. uid_t uid, gid_t gid)
  149. {
  150. rspamd_logger_t *logger;
  151. GError *err = NULL;
  152. if (pool) {
  153. logger = rspamd_mempool_alloc0(pool, sizeof(rspamd_logger_t));
  154. logger->mtx = rspamd_mempool_get_mutex(pool);
  155. }
  156. else {
  157. logger = g_malloc0(sizeof(rspamd_logger_t));
  158. }
  159. logger->pool = pool;
  160. if (cfg) {
  161. if (cfg->log_error_elts > 0 && pool) {
  162. logger->errlog = rspamd_mempool_alloc0_shared(pool,
  163. sizeof(*logger->errlog));
  164. logger->errlog->pool = pool;
  165. logger->errlog->max_elts = cfg->log_error_elts;
  166. logger->errlog->elt_len = cfg->log_error_elt_maxlen;
  167. logger->errlog->elts = rspamd_mempool_alloc0_shared(pool,
  168. sizeof(struct rspamd_logger_error_elt) * cfg->log_error_elts +
  169. cfg->log_error_elt_maxlen * cfg->log_error_elts);
  170. }
  171. logger->log_level = cfg->log_level;
  172. logger->flags = cfg->log_flags;
  173. if (!(logger->flags & RSPAMD_LOG_FLAG_ENFORCED)) {
  174. logger->log_level = cfg->log_level;
  175. }
  176. }
  177. const struct rspamd_logger_funcs *funcs = NULL;
  178. if (cfg) {
  179. switch (cfg->log_type) {
  180. case RSPAMD_LOG_CONSOLE:
  181. funcs = &console_log_funcs;
  182. break;
  183. case RSPAMD_LOG_SYSLOG:
  184. funcs = &syslog_log_funcs;
  185. break;
  186. case RSPAMD_LOG_FILE:
  187. funcs = &file_log_funcs;
  188. break;
  189. }
  190. }
  191. else {
  192. funcs = &console_log_funcs;
  193. }
  194. g_assert(funcs != NULL);
  195. memcpy(&logger->ops, funcs, sizeof(*funcs));
  196. logger->ops.specific = logger->ops.init(logger, cfg, uid, gid, &err);
  197. if (emergency_logger && logger->ops.specific == NULL) {
  198. rspamd_common_log_function(emergency_logger, G_LOG_LEVEL_CRITICAL,
  199. "logger", NULL, G_STRFUNC,
  200. "cannot open specific logger: %e", err);
  201. g_error_free(err);
  202. return NULL;
  203. }
  204. logger->pid = getpid();
  205. logger->process_type = ptype;
  206. logger->enabled = TRUE;
  207. /* Set up conditional logging */
  208. if (cfg) {
  209. if (cfg->debug_ip_map != NULL) {
  210. /* Try to add it as map first of all */
  211. if (logger->debug_ip) {
  212. rspamd_map_helper_destroy_radix(logger->debug_ip);
  213. }
  214. logger->debug_ip = NULL;
  215. rspamd_config_radix_from_ucl(cfg,
  216. cfg->debug_ip_map,
  217. "IP addresses for which debug logs are enabled",
  218. &logger->debug_ip,
  219. NULL,
  220. NULL, "debug ip");
  221. }
  222. if (cfg->log_encryption_key) {
  223. logger->pk = rspamd_pubkey_ref(cfg->log_encryption_key);
  224. logger->keypair = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX,
  225. RSPAMD_CRYPTOBOX_MODE_25519);
  226. rspamd_pubkey_calculate_nm(logger->pk, logger->keypair);
  227. }
  228. }
  229. default_logger = logger;
  230. return logger;
  231. }
  232. /**
  233. * Used after fork() for updating structure params
  234. */
  235. void rspamd_log_on_fork(GQuark ptype, struct rspamd_config *cfg,
  236. rspamd_logger_t *logger)
  237. {
  238. logger->pid = getpid();
  239. logger->process_type = g_quark_to_string(ptype);
  240. if (logger->ops.on_fork) {
  241. GError *err = NULL;
  242. bool ret = logger->ops.on_fork(logger, cfg, logger->ops.specific, &err);
  243. if (!ret && emergency_logger) {
  244. rspamd_common_log_function(emergency_logger, G_LOG_LEVEL_CRITICAL,
  245. "logger", NULL, G_STRFUNC,
  246. "cannot update logging on fork: %e", err);
  247. g_error_free(err);
  248. }
  249. }
  250. }
  251. inline gboolean
  252. rspamd_logger_need_log(rspamd_logger_t *rspamd_log, GLogLevelFlags log_level,
  253. gint module_id)
  254. {
  255. g_assert(rspamd_log != NULL);
  256. if ((log_level & RSPAMD_LOG_FORCED) ||
  257. (log_level & (RSPAMD_LOG_LEVEL_MASK & G_LOG_LEVEL_MASK)) <= rspamd_log->log_level) {
  258. return TRUE;
  259. }
  260. if (module_id != -1 && isset(log_modules->bitset, module_id)) {
  261. return TRUE;
  262. }
  263. return FALSE;
  264. }
  265. static gchar *
  266. rspamd_log_encrypt_message(const gchar *begin, const gchar *end, gsize *enc_len,
  267. rspamd_logger_t *rspamd_log)
  268. {
  269. guchar *out;
  270. gchar *b64;
  271. guchar *p, *nonce, *mac;
  272. const guchar *comp;
  273. guint len, inlen;
  274. g_assert(end > begin);
  275. /* base64 (pubkey | nonce | message) */
  276. inlen = rspamd_cryptobox_nonce_bytes(RSPAMD_CRYPTOBOX_MODE_25519) +
  277. rspamd_cryptobox_pk_bytes(RSPAMD_CRYPTOBOX_MODE_25519) +
  278. rspamd_cryptobox_mac_bytes(RSPAMD_CRYPTOBOX_MODE_25519) +
  279. (end - begin);
  280. out = g_malloc(inlen);
  281. p = out;
  282. comp = rspamd_pubkey_get_pk(rspamd_log->pk, &len);
  283. memcpy(p, comp, len);
  284. p += len;
  285. ottery_rand_bytes(p, rspamd_cryptobox_nonce_bytes(RSPAMD_CRYPTOBOX_MODE_25519));
  286. nonce = p;
  287. p += rspamd_cryptobox_nonce_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
  288. mac = p;
  289. p += rspamd_cryptobox_mac_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
  290. memcpy(p, begin, end - begin);
  291. comp = rspamd_pubkey_get_nm(rspamd_log->pk, rspamd_log->keypair);
  292. g_assert(comp != NULL);
  293. rspamd_cryptobox_encrypt_nm_inplace(p, end - begin, nonce, comp, mac,
  294. RSPAMD_CRYPTOBOX_MODE_25519);
  295. b64 = rspamd_encode_base64(out, inlen, 0, enc_len);
  296. g_free(out);
  297. return b64;
  298. }
  299. static void
  300. rspamd_log_write_ringbuffer(rspamd_logger_t *rspamd_log,
  301. const gchar *module, const gchar *id,
  302. const gchar *data, glong len)
  303. {
  304. uint32_t row_num;
  305. struct rspamd_logger_error_log *elog;
  306. struct rspamd_logger_error_elt *elt;
  307. if (!rspamd_log->errlog) {
  308. return;
  309. }
  310. elog = rspamd_log->errlog;
  311. g_atomic_int_compare_and_exchange(&elog->cur_row, elog->max_elts, 0);
  312. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  313. row_num = g_atomic_int_add(&elog->cur_row, 1);
  314. #else
  315. row_num = g_atomic_int_exchange_and_add(&elog->cur_row, 1);
  316. #endif
  317. if (row_num < elog->max_elts) {
  318. elt = (struct rspamd_logger_error_elt *) (((guchar *) elog->elts) +
  319. (sizeof(*elt) + elog->elt_len) * row_num);
  320. g_atomic_int_set(&elt->completed, 0);
  321. }
  322. else {
  323. /* Race condition */
  324. elog->cur_row = 0;
  325. return;
  326. }
  327. elt->pid = rspamd_log->pid;
  328. elt->ptype = g_quark_from_string(rspamd_log->process_type);
  329. elt->ts = rspamd_get_calendar_ticks();
  330. if (id) {
  331. rspamd_strlcpy(elt->id, id, sizeof(elt->id));
  332. }
  333. else {
  334. rspamd_strlcpy(elt->id, "", sizeof(elt->id));
  335. }
  336. if (module) {
  337. rspamd_strlcpy(elt->module, module, sizeof(elt->module));
  338. }
  339. else {
  340. rspamd_strlcpy(elt->module, "", sizeof(elt->module));
  341. }
  342. rspamd_strlcpy(elt->message, data, MIN(len + 1, elog->elt_len));
  343. g_atomic_int_set(&elt->completed, 1);
  344. }
  345. bool rspamd_common_logv(rspamd_logger_t *rspamd_log, gint level_flags,
  346. const gchar *module, const gchar *id, const gchar *function,
  347. const gchar *fmt, va_list args)
  348. {
  349. gchar *end;
  350. gint level = level_flags & (RSPAMD_LOG_LEVEL_MASK & G_LOG_LEVEL_MASK), mod_id;
  351. bool ret = false;
  352. gchar logbuf[RSPAMD_LOGBUF_SIZE], *log_line;
  353. gsize nescaped;
  354. if (G_UNLIKELY(rspamd_log == NULL)) {
  355. rspamd_log = default_logger;
  356. }
  357. log_line = logbuf;
  358. if (G_UNLIKELY(rspamd_log == NULL)) {
  359. /* Just fprintf message to stderr */
  360. if (level >= G_LOG_LEVEL_INFO) {
  361. end = rspamd_vsnprintf(logbuf, sizeof(logbuf), fmt, args);
  362. rspamd_fprintf(stderr, "%*s\n", (gint) (end - log_line),
  363. log_line);
  364. }
  365. }
  366. else {
  367. if (level == G_LOG_LEVEL_DEBUG) {
  368. mod_id = rspamd_logger_add_debug_module(module);
  369. }
  370. else {
  371. mod_id = -1;
  372. }
  373. if (rspamd_logger_need_log(rspamd_log, level_flags, mod_id)) {
  374. end = rspamd_vsnprintf(logbuf, sizeof(logbuf), fmt, args);
  375. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_RSPAMADM)) {
  376. if ((nescaped = rspamd_log_line_need_escape(logbuf, end - logbuf)) != 0) {
  377. gsize unescaped_len = end - logbuf;
  378. gchar *logbuf_escaped = g_alloca(unescaped_len + nescaped * 4);
  379. log_line = logbuf_escaped;
  380. end = rspamd_log_line_hex_escape(logbuf, unescaped_len,
  381. logbuf_escaped, unescaped_len + nescaped * 4);
  382. }
  383. }
  384. if ((level_flags & RSPAMD_LOG_ENCRYPTED) && rspamd_log->pk) {
  385. gchar *encrypted;
  386. gsize enc_len;
  387. encrypted = rspamd_log_encrypt_message(log_line, end, &enc_len,
  388. rspamd_log);
  389. ret = rspamd_log->ops.log(module, id,
  390. function,
  391. level_flags,
  392. encrypted,
  393. enc_len,
  394. rspamd_log,
  395. rspamd_log->ops.specific);
  396. g_free(encrypted);
  397. }
  398. else {
  399. ret = rspamd_log->ops.log(module, id,
  400. function,
  401. level_flags,
  402. log_line,
  403. end - log_line,
  404. rspamd_log,
  405. rspamd_log->ops.specific);
  406. }
  407. switch (level) {
  408. case G_LOG_LEVEL_CRITICAL:
  409. rspamd_log->log_cnt[0]++;
  410. rspamd_log_write_ringbuffer(rspamd_log, module, id, log_line,
  411. end - log_line);
  412. break;
  413. case G_LOG_LEVEL_WARNING:
  414. rspamd_log->log_cnt[1]++;
  415. break;
  416. case G_LOG_LEVEL_INFO:
  417. rspamd_log->log_cnt[2]++;
  418. break;
  419. case G_LOG_LEVEL_DEBUG:
  420. rspamd_log->log_cnt[3]++;
  421. break;
  422. default:
  423. break;
  424. }
  425. }
  426. }
  427. return ret;
  428. }
  429. /**
  430. * This log functions select real logger and write message if level is less or equal to configured log level
  431. */
  432. bool rspamd_common_log_function(rspamd_logger_t *rspamd_log,
  433. gint level_flags,
  434. const gchar *module, const gchar *id,
  435. const gchar *function,
  436. const gchar *fmt,
  437. ...)
  438. {
  439. va_list vp;
  440. va_start(vp, fmt);
  441. bool ret = rspamd_common_logv(rspamd_log, level_flags, module, id, function, fmt, vp);
  442. va_end(vp);
  443. return ret;
  444. }
  445. bool rspamd_default_logv(gint level_flags, const gchar *module, const gchar *id,
  446. const gchar *function,
  447. const gchar *fmt, va_list args)
  448. {
  449. return rspamd_common_logv(NULL, level_flags, module, id, function, fmt, args);
  450. }
  451. bool rspamd_default_log_function(gint level_flags,
  452. const gchar *module, const gchar *id,
  453. const gchar *function, const gchar *fmt, ...)
  454. {
  455. va_list vp;
  456. va_start(vp, fmt);
  457. bool ret = rspamd_default_logv(level_flags, module, id, function, fmt, vp);
  458. va_end(vp);
  459. return ret;
  460. }
  461. /**
  462. * Main file interface for logging
  463. */
  464. /**
  465. * Write log line depending on ip
  466. */
  467. bool rspamd_conditional_debug(rspamd_logger_t *rspamd_log,
  468. rspamd_inet_addr_t *addr, const gchar *module, const gchar *id,
  469. const gchar *function, const gchar *fmt, ...)
  470. {
  471. static gchar logbuf[LOGBUF_LEN];
  472. va_list vp;
  473. gchar *end;
  474. gint mod_id;
  475. if (rspamd_log == NULL) {
  476. rspamd_log = default_logger;
  477. }
  478. mod_id = rspamd_logger_add_debug_module(module);
  479. if (rspamd_logger_need_log(rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  480. rspamd_log->is_debug) {
  481. if (rspamd_log->debug_ip && addr != NULL) {
  482. if (rspamd_match_radix_map_addr(rspamd_log->debug_ip,
  483. addr) == NULL) {
  484. return false;
  485. }
  486. }
  487. va_start(vp, fmt);
  488. end = rspamd_vsnprintf(logbuf, sizeof(logbuf), fmt, vp);
  489. *end = '\0';
  490. va_end(vp);
  491. return rspamd_log->ops.log(module, id,
  492. function,
  493. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  494. logbuf,
  495. end - logbuf,
  496. rspamd_log,
  497. rspamd_log->ops.specific);
  498. }
  499. return false;
  500. }
  501. bool rspamd_conditional_debug_fast(rspamd_logger_t *rspamd_log,
  502. rspamd_inet_addr_t *addr,
  503. gint mod_id, const gchar *module, const gchar *id,
  504. const gchar *function, const gchar *fmt, ...)
  505. {
  506. static gchar logbuf[LOGBUF_LEN];
  507. va_list vp;
  508. gchar *end;
  509. if (rspamd_log == NULL) {
  510. rspamd_log = default_logger;
  511. }
  512. if (rspamd_logger_need_log(rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  513. rspamd_log->is_debug) {
  514. if (rspamd_log->debug_ip && addr != NULL) {
  515. if (rspamd_match_radix_map_addr(rspamd_log->debug_ip, addr) == NULL) {
  516. return false;
  517. }
  518. }
  519. va_start(vp, fmt);
  520. end = rspamd_vsnprintf(logbuf, sizeof(logbuf), fmt, vp);
  521. *end = '\0';
  522. va_end(vp);
  523. return rspamd_log->ops.log(module, id,
  524. function,
  525. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  526. logbuf,
  527. end - logbuf,
  528. rspamd_log,
  529. rspamd_log->ops.specific);
  530. }
  531. return false;
  532. }
  533. bool rspamd_conditional_debug_fast_num_id(rspamd_logger_t *rspamd_log,
  534. rspamd_inet_addr_t *addr,
  535. gint mod_id, const gchar *module, uint64_t id,
  536. const gchar *function, const gchar *fmt, ...)
  537. {
  538. static gchar logbuf[LOGBUF_LEN], idbuf[64];
  539. va_list vp;
  540. gchar *end;
  541. if (rspamd_log == NULL) {
  542. rspamd_log = default_logger;
  543. }
  544. if (rspamd_logger_need_log(rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  545. rspamd_log->is_debug) {
  546. if (rspamd_log->debug_ip && addr != NULL) {
  547. if (rspamd_match_radix_map_addr(rspamd_log->debug_ip, addr) == NULL) {
  548. return false;
  549. }
  550. }
  551. rspamd_snprintf(idbuf, sizeof(idbuf), "%XuL", id);
  552. va_start(vp, fmt);
  553. end = rspamd_vsnprintf(logbuf, sizeof(logbuf), fmt, vp);
  554. *end = '\0';
  555. va_end(vp);
  556. return rspamd_log->ops.log(module, idbuf,
  557. function,
  558. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  559. logbuf,
  560. end - logbuf,
  561. rspamd_log,
  562. rspamd_log->ops.specific);
  563. }
  564. return false;
  565. }
  566. /**
  567. * Wrapper for glib logger
  568. */
  569. void rspamd_glib_log_function(const gchar *log_domain,
  570. GLogLevelFlags log_level,
  571. const gchar *message,
  572. gpointer arg)
  573. {
  574. rspamd_logger_t *rspamd_log = (rspamd_logger_t *) arg;
  575. if (rspamd_log->enabled &&
  576. rspamd_logger_need_log(rspamd_log, log_level, -1)) {
  577. rspamd_log->ops.log("glib", NULL,
  578. NULL,
  579. log_level,
  580. message,
  581. strlen(message),
  582. rspamd_log,
  583. rspamd_log->ops.specific);
  584. }
  585. }
  586. void rspamd_glib_printerr_function(const gchar *message)
  587. {
  588. rspamd_common_log_function(NULL, G_LOG_LEVEL_CRITICAL, "glib",
  589. NULL, G_STRFUNC,
  590. "%s", message);
  591. }
  592. /**
  593. * Temporary turn on debugging
  594. */
  595. void rspamd_log_debug(rspamd_logger_t *rspamd_log)
  596. {
  597. rspamd_log->is_debug = TRUE;
  598. }
  599. /**
  600. * Turn off temporary debugging
  601. */
  602. void rspamd_log_nodebug(rspamd_logger_t *rspamd_log)
  603. {
  604. rspamd_log->is_debug = FALSE;
  605. }
  606. const uint64_t *
  607. rspamd_log_counters(rspamd_logger_t *logger)
  608. {
  609. if (logger) {
  610. return logger->log_cnt;
  611. }
  612. return NULL;
  613. }
  614. static gint
  615. rspamd_log_errlog_cmp(const ucl_object_t **o1, const ucl_object_t **o2)
  616. {
  617. const ucl_object_t *ts1, *ts2;
  618. ts1 = ucl_object_lookup(*o1, "ts");
  619. ts2 = ucl_object_lookup(*o2, "ts");
  620. if (ts1 && ts2) {
  621. gdouble t1 = ucl_object_todouble(ts1), t2 = ucl_object_todouble(ts2);
  622. if (t1 > t2) {
  623. return -1;
  624. }
  625. else if (t2 > t1) {
  626. return 1;
  627. }
  628. }
  629. return 0;
  630. }
  631. ucl_object_t *
  632. rspamd_log_errorbuf_export(const rspamd_logger_t *logger)
  633. {
  634. struct rspamd_logger_error_elt *cpy, *cur;
  635. ucl_object_t *top = ucl_object_typed_new(UCL_ARRAY);
  636. guint i;
  637. if (logger->errlog == NULL) {
  638. return top;
  639. }
  640. cpy = g_malloc0_n(logger->errlog->max_elts,
  641. sizeof(*cpy) + logger->errlog->elt_len);
  642. memcpy(cpy, logger->errlog->elts, logger->errlog->max_elts * (sizeof(*cpy) + logger->errlog->elt_len));
  643. for (i = 0; i < logger->errlog->max_elts; i++) {
  644. cur = (struct rspamd_logger_error_elt *) ((guchar *) cpy +
  645. i * ((sizeof(*cpy) + logger->errlog->elt_len)));
  646. if (cur->completed) {
  647. ucl_object_t *obj = ucl_object_typed_new(UCL_OBJECT);
  648. ucl_object_insert_key(obj, ucl_object_fromdouble(cur->ts),
  649. "ts", 0, false);
  650. ucl_object_insert_key(obj, ucl_object_fromint(cur->pid),
  651. "pid", 0, false);
  652. ucl_object_insert_key(obj,
  653. ucl_object_fromstring(g_quark_to_string(cur->ptype)),
  654. "type", 0, false);
  655. ucl_object_insert_key(obj, ucl_object_fromstring(cur->id),
  656. "id", 0, false);
  657. ucl_object_insert_key(obj, ucl_object_fromstring(cur->module),
  658. "module", 0, false);
  659. ucl_object_insert_key(obj, ucl_object_fromstring(cur->message),
  660. "message", 0, false);
  661. ucl_array_append(top, obj);
  662. }
  663. }
  664. ucl_object_array_sort(top, rspamd_log_errlog_cmp);
  665. g_free(cpy);
  666. return top;
  667. }
  668. static guint
  669. rspamd_logger_allocate_mod_bit(void)
  670. {
  671. if (log_modules->bitset_allocated * NBBY > log_modules->bitset_len + 1) {
  672. log_modules->bitset_len++;
  673. return log_modules->bitset_len - 1;
  674. }
  675. else {
  676. /* Need to expand */
  677. log_modules->bitset_allocated *= 2;
  678. log_modules->bitset = g_realloc(log_modules->bitset,
  679. log_modules->bitset_allocated);
  680. return rspamd_logger_allocate_mod_bit();
  681. }
  682. }
  683. RSPAMD_DESTRUCTOR(rspamd_debug_modules_dtor)
  684. {
  685. if (log_modules) {
  686. g_hash_table_unref(log_modules->modules);
  687. g_free(log_modules->bitset);
  688. g_free(log_modules);
  689. }
  690. }
  691. gint rspamd_logger_add_debug_module(const gchar *mname)
  692. {
  693. struct rspamd_log_module *m;
  694. if (mname == NULL) {
  695. return -1;
  696. }
  697. if (log_modules == NULL) {
  698. /*
  699. * This is usually called from constructors, so we call init check
  700. * each time to avoid dependency issues between ctors calls
  701. */
  702. log_modules = g_malloc0(sizeof(*log_modules));
  703. log_modules->modules = g_hash_table_new_full(rspamd_strcase_hash,
  704. rspamd_strcase_equal, g_free, g_free);
  705. log_modules->bitset_allocated = 16;
  706. log_modules->bitset_len = 0;
  707. log_modules->bitset = g_malloc0(log_modules->bitset_allocated);
  708. }
  709. if ((m = g_hash_table_lookup(log_modules->modules, mname)) == NULL) {
  710. m = g_malloc0(sizeof(*m));
  711. m->mname = g_strdup(mname);
  712. m->id = rspamd_logger_allocate_mod_bit();
  713. clrbit(log_modules->bitset, m->id);
  714. g_hash_table_insert(log_modules->modules, m->mname, m);
  715. }
  716. return m->id;
  717. }
  718. void rspamd_logger_configure_modules(GHashTable *mods_enabled)
  719. {
  720. GHashTableIter it;
  721. gpointer k, v;
  722. guint id;
  723. /* Clear all in bitset_allocated -> this are bytes not bits */
  724. memset(log_modules->bitset, 0, log_modules->bitset_allocated);
  725. /* On first iteration, we go through all modules enabled and add missing ones */
  726. g_hash_table_iter_init(&it, mods_enabled);
  727. while (g_hash_table_iter_next(&it, &k, &v)) {
  728. rspamd_logger_add_debug_module((const gchar *) k);
  729. }
  730. g_hash_table_iter_init(&it, mods_enabled);
  731. while (g_hash_table_iter_next(&it, &k, &v)) {
  732. id = rspamd_logger_add_debug_module((const gchar *) k);
  733. if (isclr(log_modules->bitset, id)) {
  734. msg_info("enable debugging for module %s (%d)", (const gchar *) k,
  735. id);
  736. setbit(log_modules->bitset, id);
  737. }
  738. }
  739. }
  740. struct rspamd_logger_funcs *
  741. rspamd_logger_set_log_function(rspamd_logger_t *logger,
  742. struct rspamd_logger_funcs *nfuncs)
  743. {
  744. /* TODO: write this */
  745. return NULL;
  746. }
  747. gchar *
  748. rspamd_log_line_hex_escape(const guchar *src, gsize srclen,
  749. gchar *dst, gsize dstlen)
  750. {
  751. static const gchar hexdigests[16] = "0123456789ABCDEF";
  752. gchar *d = dst;
  753. static uint32_t escape[] = {
  754. 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  755. /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
  756. 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
  757. /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
  758. 0x00000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
  759. /* ~}| {zyx wvut srqp onml kjih gfed cba` */
  760. 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
  761. /* Allow all 8bit characters (assuming they are valid utf8) */
  762. 0x00000000,
  763. 0x00000000,
  764. 0x00000000,
  765. 0x00000000,
  766. };
  767. while (srclen && dstlen) {
  768. if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
  769. if (dstlen >= 4) {
  770. *d++ = '\\';
  771. *d++ = 'x';
  772. *d++ = hexdigests[*src >> 4];
  773. *d++ = hexdigests[*src & 0xf];
  774. src++;
  775. dstlen -= 4;
  776. }
  777. else {
  778. /* Overflow */
  779. break;
  780. }
  781. }
  782. else {
  783. *d++ = *src++;
  784. dstlen--;
  785. }
  786. srclen--;
  787. }
  788. return d;
  789. }
  790. gsize rspamd_log_line_need_escape(const guchar *src, gsize srclen)
  791. {
  792. static uint32_t escape[] = {
  793. 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  794. /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
  795. 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
  796. /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
  797. 0x00000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
  798. /* ~}| {zyx wvut srqp onml kjih gfed cba` */
  799. 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
  800. /* Allow all 8bit characters (assuming they are valid utf8) */
  801. 0x00000000,
  802. 0x00000000,
  803. 0x00000000,
  804. 0x00000000,
  805. };
  806. gsize n = 0;
  807. while (srclen) {
  808. if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
  809. n++;
  810. }
  811. src++;
  812. srclen--;
  813. }
  814. return n;
  815. }
  816. const gchar *
  817. rspamd_get_log_severity_string(gint level_flags)
  818. {
  819. unsigned int bitnum;
  820. static const char *level_strs[G_LOG_LEVEL_USER_SHIFT] = {
  821. "", /* G_LOG_FLAG_RECURSION */
  822. "", /* G_LOG_FLAG_FATAL */
  823. "crit",
  824. "error",
  825. "warn",
  826. "notice",
  827. "info",
  828. "debug"};
  829. level_flags &= ((1u << G_LOG_LEVEL_USER_SHIFT) - 1u) & ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL);
  830. #ifdef __GNUC__
  831. /* We assume gcc >= 3 and clang >= 5 anyway */
  832. bitnum = __builtin_ffs(level_flags) - 1;
  833. #else
  834. bitnum = ffs(level_flags) - 1;
  835. #endif
  836. return level_strs[bitnum];
  837. }
  838. static inline void
  839. log_time(gdouble now, rspamd_logger_t *rspamd_log, gchar *timebuf,
  840. size_t len)
  841. {
  842. time_t sec = (time_t) now;
  843. gsize r;
  844. struct tm tms;
  845. rspamd_localtime(sec, &tms);
  846. r = strftime(timebuf, len, "%F %H:%M:%S", &tms);
  847. if (rspamd_log->flags & RSPAMD_LOG_FLAG_USEC) {
  848. gchar usec_buf[16];
  849. rspamd_snprintf(usec_buf, sizeof(usec_buf), "%.5f",
  850. now - (gdouble) sec);
  851. rspamd_snprintf(timebuf + r, len - r,
  852. "%s", usec_buf + 1);
  853. }
  854. }
  855. void rspamd_log_fill_iov(struct rspamd_logger_iov_ctx *iov_ctx,
  856. double ts,
  857. const gchar *module,
  858. const gchar *id,
  859. const gchar *function,
  860. gint level_flags,
  861. const gchar *message,
  862. gsize mlen,
  863. rspamd_logger_t *logger)
  864. {
  865. bool log_color = (logger->flags & RSPAMD_LOG_FLAG_COLOR);
  866. bool log_severity = (logger->flags & RSPAMD_LOG_FLAG_SEVERITY);
  867. bool log_rspamadm = (logger->flags & RSPAMD_LOG_FLAG_RSPAMADM);
  868. bool log_systemd = (logger->flags & RSPAMD_LOG_FLAG_SYSTEMD);
  869. bool log_json = (logger->flags & RSPAMD_LOG_FLAG_JSON);
  870. if (log_json) {
  871. /* Some sanity to avoid too many branches */
  872. log_color = false;
  873. log_severity = true;
  874. log_systemd = false;
  875. }
  876. glong r;
  877. static gchar timebuf[64], modulebuf[64];
  878. static gchar tmpbuf[256];
  879. if (!log_json && !log_systemd) {
  880. log_time(ts, logger, timebuf, sizeof(timebuf));
  881. }
  882. if (G_UNLIKELY(log_json)) {
  883. /* Perform JSON logging */
  884. guint slen = id ? strlen(id) : strlen("(NULL)");
  885. slen = MIN(RSPAMD_LOG_ID_LEN, slen);
  886. r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "{\"ts\": %f, "
  887. "\"pid\": %P, "
  888. "\"severity\": \"%s\", "
  889. "\"worker_type\": \"%s\", "
  890. "\"id\": \"%*.s\", "
  891. "\"module\": \"%s\", "
  892. "\"function\": \"%s\", "
  893. "\"message\": \"",
  894. ts,
  895. logger->pid,
  896. rspamd_get_log_severity_string(level_flags),
  897. logger->process_type,
  898. slen, id,
  899. module,
  900. function);
  901. iov_ctx->iov[0].iov_base = tmpbuf;
  902. iov_ctx->iov[0].iov_len = r;
  903. /* TODO: is it possible to have other 'bad' symbols here? */
  904. if (rspamd_memcspn(message, "\"\\\r\n\b\t\v", mlen) == mlen) {
  905. iov_ctx->iov[1].iov_base = (void *) message;
  906. iov_ctx->iov[1].iov_len = mlen;
  907. }
  908. else {
  909. /* We need to do JSON escaping of the quotes */
  910. const char *p, *end = message + mlen;
  911. long escaped_len;
  912. for (p = message, escaped_len = 0; p < end; p++, escaped_len++) {
  913. switch (*p) {
  914. case '\v':
  915. case '\0':
  916. escaped_len += 5;
  917. break;
  918. case '\\':
  919. case '"':
  920. case '\n':
  921. case '\r':
  922. case '\b':
  923. case '\t':
  924. escaped_len++;
  925. break;
  926. default:
  927. break;
  928. }
  929. }
  930. struct rspamd_logger_iov_thrash_stack *thrash_stack_elt = g_malloc(
  931. sizeof(struct rspamd_logger_iov_thrash_stack) +
  932. escaped_len);
  933. char *dst = ((char *) thrash_stack_elt) + sizeof(struct rspamd_logger_iov_thrash_stack);
  934. char *d;
  935. thrash_stack_elt->prev = iov_ctx->thrash_stack;
  936. iov_ctx->thrash_stack = thrash_stack_elt;
  937. for (p = message, d = dst; p < end; p++, d++) {
  938. switch (*p) {
  939. case '\n':
  940. *d++ = '\\';
  941. *d = 'n';
  942. break;
  943. case '\r':
  944. *d++ = '\\';
  945. *d = 'r';
  946. break;
  947. case '\b':
  948. *d++ = '\\';
  949. *d = 'b';
  950. break;
  951. case '\t':
  952. *d++ = '\\';
  953. *d = 't';
  954. break;
  955. case '\f':
  956. *d++ = '\\';
  957. *d = 'f';
  958. break;
  959. case '\0':
  960. *d++ = '\\';
  961. *d++ = 'u';
  962. *d++ = '0';
  963. *d++ = '0';
  964. *d++ = '0';
  965. *d = '0';
  966. break;
  967. case '\v':
  968. *d++ = '\\';
  969. *d++ = 'u';
  970. *d++ = '0';
  971. *d++ = '0';
  972. *d++ = '0';
  973. *d = 'B';
  974. break;
  975. case '\\':
  976. *d++ = '\\';
  977. *d = '\\';
  978. break;
  979. case '"':
  980. *d++ = '\\';
  981. *d = '"';
  982. break;
  983. default:
  984. *d = *p;
  985. break;
  986. }
  987. }
  988. iov_ctx->iov[1].iov_base = dst;
  989. iov_ctx->iov[1].iov_len = d - dst;
  990. }
  991. iov_ctx->iov[2].iov_base = (void *) "\"}\n";
  992. iov_ctx->iov[2].iov_len = sizeof("\"}\n") - 1;
  993. iov_ctx->niov = 3;
  994. }
  995. else if (G_LIKELY(!log_rspamadm)) {
  996. if (!log_systemd) {
  997. if (log_color) {
  998. if (level_flags & (G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE)) {
  999. /* White */
  1000. r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[0;37m");
  1001. }
  1002. else if (level_flags & G_LOG_LEVEL_WARNING) {
  1003. /* Magenta */
  1004. r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[0;32m");
  1005. }
  1006. else if (level_flags & G_LOG_LEVEL_CRITICAL) {
  1007. /* Red */
  1008. r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[1;31m");
  1009. }
  1010. else {
  1011. r = 0;
  1012. }
  1013. }
  1014. else {
  1015. r = 0;
  1016. }
  1017. if (log_severity) {
  1018. r += rspamd_snprintf(tmpbuf + r,
  1019. sizeof(tmpbuf) - r,
  1020. "%s [%s] #%P(%s) ",
  1021. timebuf,
  1022. rspamd_get_log_severity_string(level_flags),
  1023. logger->pid,
  1024. logger->process_type);
  1025. }
  1026. else {
  1027. r += rspamd_snprintf(tmpbuf + r,
  1028. sizeof(tmpbuf) - r,
  1029. "%s #%P(%s) ",
  1030. timebuf,
  1031. logger->pid,
  1032. logger->process_type);
  1033. }
  1034. }
  1035. else {
  1036. r = 0;
  1037. r += rspamd_snprintf(tmpbuf + r,
  1038. sizeof(tmpbuf) - r,
  1039. "(%s) ",
  1040. logger->process_type);
  1041. }
  1042. glong mremain, mr;
  1043. char *m;
  1044. modulebuf[0] = '\0';
  1045. mremain = sizeof(modulebuf);
  1046. m = modulebuf;
  1047. if (id != NULL) {
  1048. guint slen = strlen(id);
  1049. slen = MIN(RSPAMD_LOG_ID_LEN, slen);
  1050. mr = rspamd_snprintf(m, mremain, "<%*.s>; ", slen,
  1051. id);
  1052. m += mr;
  1053. mremain -= mr;
  1054. }
  1055. if (module != NULL) {
  1056. mr = rspamd_snprintf(m, mremain, "%s; ", module);
  1057. m += mr;
  1058. mremain -= mr;
  1059. }
  1060. if (function != NULL) {
  1061. mr = rspamd_snprintf(m, mremain, "%s: ", function);
  1062. m += mr;
  1063. mremain -= mr;
  1064. }
  1065. else {
  1066. mr = rspamd_snprintf(m, mremain, ": ");
  1067. m += mr;
  1068. mremain -= mr;
  1069. }
  1070. /* Ensure that we have a space at the end */
  1071. if (m > modulebuf && *(m - 1) != ' ') {
  1072. *(m - 1) = ' ';
  1073. }
  1074. /* Construct IOV for log line */
  1075. iov_ctx->iov[0].iov_base = tmpbuf;
  1076. iov_ctx->iov[0].iov_len = r;
  1077. iov_ctx->iov[1].iov_base = modulebuf;
  1078. iov_ctx->iov[1].iov_len = m - modulebuf;
  1079. iov_ctx->iov[2].iov_base = (void *) message;
  1080. iov_ctx->iov[2].iov_len = mlen;
  1081. iov_ctx->iov[3].iov_base = (void *) &lf_chr;
  1082. iov_ctx->iov[3].iov_len = 1;
  1083. iov_ctx->niov = 4;
  1084. if (log_color) {
  1085. iov_ctx->iov[4].iov_base = "\033[0m";
  1086. iov_ctx->iov[4].iov_len = sizeof("\033[0m") - 1;
  1087. iov_ctx->niov = 5;
  1088. }
  1089. }
  1090. else {
  1091. /* Rspamadm case */
  1092. int niov = 0;
  1093. if (logger->log_level == G_LOG_LEVEL_DEBUG) {
  1094. iov_ctx->iov[niov].iov_base = (void *) timebuf;
  1095. iov_ctx->iov[niov++].iov_len = strlen(timebuf);
  1096. iov_ctx->iov[niov].iov_base = (void *) " ";
  1097. iov_ctx->iov[niov++].iov_len = 1;
  1098. }
  1099. iov_ctx->iov[niov].iov_base = (void *) message;
  1100. iov_ctx->iov[niov++].iov_len = mlen;
  1101. iov_ctx->iov[niov].iov_base = (void *) &lf_chr;
  1102. iov_ctx->iov[niov++].iov_len = 1;
  1103. iov_ctx->niov = niov;
  1104. }
  1105. // this is kind of "after-the-fact" check, but it's mostly for debugging-only
  1106. g_assert(iov_ctx->niov <= G_N_ELEMENTS(iov_ctx->iov));
  1107. }
  1108. void rspamd_log_iov_free(struct rspamd_logger_iov_ctx *iov_ctx)
  1109. {
  1110. struct rspamd_logger_iov_thrash_stack *st = iov_ctx->thrash_stack;
  1111. while (st) {
  1112. struct rspamd_logger_iov_thrash_stack *nst = st->prev;
  1113. g_free(st);
  1114. st = nst;
  1115. }
  1116. }