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.

configtest.c 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 "rspamadm.h"
  18. #include "cfg_file.h"
  19. #include "cfg_rcl.h"
  20. #include "rspamd.h"
  21. #include "lua/lua_common.h"
  22. static gboolean quiet = FALSE;
  23. static char *config = NULL;
  24. static gboolean strict = FALSE;
  25. static gboolean skip_template = FALSE;
  26. extern struct rspamd_main *rspamd_main;
  27. /* Defined in modules.c */
  28. extern module_t *modules[];
  29. extern worker_t *workers[];
  30. static void rspamadm_configtest(int argc, char **argv,
  31. const struct rspamadm_command *cmd);
  32. static const char *rspamadm_configtest_help(gboolean full_help,
  33. const struct rspamadm_command *cmd);
  34. struct rspamadm_command configtest_command = {
  35. .name = "configtest",
  36. .flags = 0,
  37. .help = rspamadm_configtest_help,
  38. .run = rspamadm_configtest,
  39. .lua_subrs = NULL,
  40. };
  41. static GOptionEntry entries[] = {
  42. {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
  43. "Suppress output", NULL},
  44. {"config", 'c', 0, G_OPTION_ARG_STRING, &config,
  45. "Config file to test", NULL},
  46. {"strict", 's', 0, G_OPTION_ARG_NONE, &strict,
  47. "Stop on any error in config", NULL},
  48. {"skip-template", 'T', 0, G_OPTION_ARG_NONE, &skip_template,
  49. "Do not apply Jinja templates", NULL},
  50. {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}};
  51. static const char *
  52. rspamadm_configtest_help(gboolean full_help, const struct rspamadm_command *cmd)
  53. {
  54. const char *help_str;
  55. if (full_help) {
  56. help_str = "Perform configuration file test\n\n"
  57. "Usage: rspamadm configtest [-q -c <config_name>]\n"
  58. "Where options are:\n\n"
  59. "-q: quiet output\n"
  60. "-c: config file to test\n"
  61. "--help: shows available options and commands";
  62. }
  63. else {
  64. help_str = "Perform configuration file test";
  65. }
  66. return help_str;
  67. }
  68. static void
  69. config_logger(rspamd_mempool_t *pool, gpointer ud)
  70. {
  71. }
  72. static void
  73. rspamadm_configtest(int argc, char **argv, const struct rspamadm_command *cmd)
  74. {
  75. GOptionContext *context;
  76. GError *error = NULL;
  77. const char *confdir;
  78. struct rspamd_config *cfg = rspamd_main->cfg;
  79. gboolean ret = TRUE;
  80. worker_t **pworker;
  81. const uint64_t *log_cnt;
  82. context = g_option_context_new(
  83. "configtest - perform configuration file test");
  84. g_option_context_set_summary(context,
  85. "Summary:\n Rspamd administration utility version " RVERSION
  86. "\n Release id: " RID);
  87. g_option_context_add_main_entries(context, entries, NULL);
  88. if (!g_option_context_parse(context, &argc, &argv, &error)) {
  89. fprintf(stderr, "option parsing failed: %s\n", error->message);
  90. g_error_free(error);
  91. g_option_context_free(context);
  92. exit(EXIT_FAILURE);
  93. }
  94. g_option_context_free(context);
  95. if (config == NULL) {
  96. static char fbuf[PATH_MAX];
  97. if ((confdir = g_hash_table_lookup(ucl_vars, "CONFDIR")) == NULL) {
  98. confdir = RSPAMD_CONFDIR;
  99. }
  100. rspamd_snprintf(fbuf, sizeof(fbuf), "%s%c%s",
  101. confdir, G_DIR_SEPARATOR,
  102. "rspamd.conf");
  103. config = fbuf;
  104. }
  105. pworker = &workers[0];
  106. while (*pworker) {
  107. /* Init string quarks */
  108. (void) g_quark_from_static_string((*pworker)->name);
  109. pworker++;
  110. }
  111. cfg->compiled_modules = modules;
  112. cfg->compiled_workers = workers;
  113. cfg->cfg_name = config;
  114. if (!rspamd_config_read(cfg, cfg->cfg_name, config_logger, rspamd_main,
  115. ucl_vars, skip_template, lua_env)) {
  116. ret = FALSE;
  117. }
  118. else {
  119. /* Do post-load actions */
  120. rspamd_lua_post_load_config(cfg);
  121. if (!rspamd_init_filters(rspamd_main->cfg, false, strict)) {
  122. ret = FALSE;
  123. }
  124. if (ret) {
  125. ret = rspamd_config_post_load(cfg, RSPAMD_CONFIG_INIT_SYMCACHE);
  126. }
  127. if (ret && !rspamd_symcache_validate(cfg->cache,
  128. cfg,
  129. FALSE)) {
  130. ret = FALSE;
  131. }
  132. if (ret) {
  133. if (rspamd_lua_require_function(cfg->lua_state, "lua_cfg_utils", "check_configuration_errors")) {
  134. GError *err = NULL;
  135. if (!rspamd_lua_universal_pcall(cfg->lua_state, -1, G_STRLOC, 1, "", &err)) {
  136. msg_err_config("call to lua function failed: %s",
  137. lua_tostring(cfg->lua_state, -1));
  138. lua_pop(cfg->lua_state, 2);
  139. ret = FALSE;
  140. }
  141. else {
  142. ret = lua_toboolean(cfg->lua_state, -1);
  143. lua_pop(cfg->lua_state, 2);
  144. }
  145. }
  146. }
  147. }
  148. if (strict && ret) {
  149. log_cnt = rspamd_log_counters(rspamd_main->logger);
  150. if (log_cnt && log_cnt[0] > 0) {
  151. if (!quiet) {
  152. rspamd_printf("%L errors found\n", log_cnt[0]);
  153. }
  154. ret = FALSE;
  155. }
  156. }
  157. if (!quiet) {
  158. rspamd_printf("syntax %s\n", ret ? "OK" : "BAD");
  159. }
  160. if (!ret) {
  161. exit(EXIT_FAILURE);
  162. }
  163. }