1 /*- 2 * Copyright 2016-2017 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 17 #ifndef RSPAMD_MAIN_H 18 #define RSPAMD_MAIN_H 19 20 #include "config.h" 21 #include "libutil/fstring.h" 22 #include "libutil/mem_pool.h" 23 #include "libutil/util.h" 24 #include "libserver/logger.h" 25 #include "libserver/http/http_connection.h" 26 #include "libutil/upstream.h" 27 #include "libutil/radix.h" 28 #include "libserver/cfg_file.h" 29 #include "libserver/url.h" 30 #include "libserver/protocol.h" 31 #include "libserver/async_session.h" 32 #include "libserver/roll_history.h" 33 #include "libserver/task.h" 34 35 #include <openssl/ssl.h> 36 37 /* Default values */ 38 #define FIXED_CONFIG_FILE RSPAMD_CONFDIR "/rspamd.conf" 39 /* Time in seconds to exit for old worker */ 40 #define SOFT_SHUTDOWN_TIME 10 41 42 /* Spam subject */ 43 #define SPAM_SUBJECT "*** SPAM *** %s" 44 45 #ifdef CRLF 46 #undef CRLF 47 #undef CR 48 #undef LF 49 #endif 50 51 #define CRLF "\r\n" 52 #define CR '\r' 53 #define LF '\n' 54 55 #ifdef __cplusplus 56 extern "C" { 57 #endif 58 59 struct rspamd_main; 60 61 enum rspamd_worker_flags { 62 RSPAMD_WORKER_HAS_SOCKET = (1 << 0), 63 RSPAMD_WORKER_UNIQUE = (1 << 1), 64 RSPAMD_WORKER_THREADED = (1 << 2), 65 RSPAMD_WORKER_KILLABLE = (1 << 3), 66 RSPAMD_WORKER_ALWAYS_START = (1 << 4), 67 RSPAMD_WORKER_SCANNER = (1 << 5), 68 RSPAMD_WORKER_CONTROLLER = (1 << 6), 69 RSPAMD_WORKER_NO_TERMINATE_DELAY = (1 << 7), 70 RSPAMD_WORKER_OLD_CONFIG = (1 << 8), 71 }; 72 73 struct rspamd_worker_accept_event { 74 ev_io accept_ev; 75 ev_timer throttling_ev; 76 struct ev_loop *event_loop; 77 struct rspamd_worker_accept_event *prev, *next; 78 }; 79 80 typedef void (*rspamd_worker_term_cb) (EV_P_ ev_child *, struct rspamd_main *, 81 struct rspamd_worker *); 82 83 struct rspamd_worker_heartbeat { 84 ev_timer heartbeat_ev; /**< used by main for checking heartbeats and by workers to send heartbeats */ 85 ev_tstamp last_event; /**< last heartbeat received timestamp */ 86 gint64 nbeats; /**< positive for beats received, negative for beats missed */ 87 }; 88 89 enum rspamd_worker_state { 90 rspamd_worker_state_running = 0, 91 rspamd_worker_state_wanna_die, 92 rspamd_worker_state_terminating, 93 rspamd_worker_wait_connections, 94 rspamd_worker_wait_final_scripts, 95 rspamd_worker_wanna_die 96 }; 97 98 /** 99 * Worker process structure 100 */ 101 struct rspamd_worker { 102 pid_t pid; /**< pid of worker */ 103 pid_t ppid; /**< pid of parent */ 104 guint index; /**< index number */ 105 guint nconns; /**< current connections count */ 106 enum rspamd_worker_state state; /**< current worker state */ 107 gboolean cores_throttled; /**< set to true if cores throttling took place */ 108 gdouble start_time; /**< start time */ 109 struct rspamd_main *srv; /**< pointer to server structure */ 110 GQuark type; /**< process type */ 111 GHashTable *signal_events; /**< signal events */ 112 struct rspamd_worker_accept_event *accept_events; /**< socket events */ 113 struct rspamd_worker_conf *cf; /**< worker config data */ 114 gpointer ctx; /**< worker's specific data */ 115 gint flags; /**< worker's flags (enum rspamd_worker_flags) */ 116 gint control_pipe[2]; /**< control pipe. [0] is used by main process, 117 [1] is used by a worker */ 118 gint srv_pipe[2]; /**< used by workers to request something from the 119 main process. [0] - main, [1] - worker */ 120 ev_io srv_ev; /**< used by main for read workers' requests */ 121 struct rspamd_worker_heartbeat hb; /**< heartbeat data */ 122 gpointer control_data; /**< used by control protocol to handle commands */ 123 gpointer tmp_data; /**< used to avoid race condition to deal with control messages */ 124 ev_child cld_ev; /**< to allow reaping */ 125 rspamd_worker_term_cb term_handler; /**< custom term handler */ 126 GHashTable *control_events_pending; /**< control events pending indexed by ptr */ 127 }; 128 129 struct rspamd_abstract_worker_ctx { 130 guint64 magic; 131 /* Events base */ 132 struct ev_loop *event_loop; 133 /* DNS resolver */ 134 struct rspamd_dns_resolver *resolver; 135 /* Config */ 136 struct rspamd_config *cfg; 137 char data[]; 138 }; 139 140 struct rspamd_worker_signal_handler; 141 142 typedef gboolean (*rspamd_worker_signal_cb_t) ( 143 struct rspamd_worker_signal_handler *, void *ud); 144 145 struct rspamd_worker_signal_handler_elt { 146 rspamd_worker_signal_cb_t handler; 147 void *handler_data; 148 struct rspamd_worker_signal_handler_elt *next, *prev; 149 }; 150 151 struct rspamd_worker_signal_handler { 152 gint signo; 153 gboolean enabled; 154 ev_signal ev_sig; 155 struct ev_loop *event_loop; 156 struct rspamd_worker *worker; 157 struct rspamd_worker_signal_handler_elt *cb; 158 }; 159 160 /** 161 * Common structure representing C module context 162 */ 163 struct module_s; 164 165 struct module_ctx { 166 gint (*filter) (struct rspamd_task *task); /**< pointer to headers process function */ 167 struct module_s *mod; /**< module pointer */ 168 gboolean enabled; /**< true if module is enabled in configuration */ 169 }; 170 171 #ifndef WITH_HYPERSCAN 172 #define RSPAMD_FEATURE_HYPERSCAN "0" 173 #else 174 #define RSPAMD_FEATURE_HYPERSCAN "1" 175 #endif 176 #ifndef WITH_PCRE2 177 #define RSPAMD_FEATURE_PCRE2 "0" 178 #else 179 #define RSPAMD_FEATURE_PCRE2 "1" 180 #endif 181 #ifndef WITH_FANN 182 #define RSPAMD_FEATURE_FANN "0" 183 #else 184 #define RSPAMD_FEATURE_FANN "1" 185 #endif 186 #ifndef WITH_SNOWBALL 187 #define RSPAMD_FEATURE_SNOWBALL "0" 188 #else 189 #define RSPAMD_FEATURE_SNOWBALL "1" 190 #endif 191 192 #define RSPAMD_CUR_MODULE_VERSION 0x1 193 #define RSPAMD_CUR_WORKER_VERSION 0x2 194 195 #define RSPAMD_FEATURES \ 196 RSPAMD_FEATURE_HYPERSCAN RSPAMD_FEATURE_PCRE2 \ 197 RSPAMD_FEATURE_FANN RSPAMD_FEATURE_SNOWBALL 198 199 #define RSPAMD_MODULE_VER \ 200 RSPAMD_CUR_MODULE_VERSION, /* Module version */ \ 201 RSPAMD_VERSION_NUM, /* Rspamd version */ \ 202 RSPAMD_FEATURES /* Compilation features */ \ 203 204 #define RSPAMD_WORKER_VER \ 205 RSPAMD_CUR_WORKER_VERSION, /* Worker version */ \ 206 RSPAMD_VERSION_NUM, /* Rspamd version */ \ 207 RSPAMD_FEATURES /* Compilation features */ \ 208 /** 209 * Module 210 */ 211 typedef struct module_s { 212 const gchar *name; 213 214 int (*module_init_func) (struct rspamd_config *cfg, struct module_ctx **ctx); 215 216 int (*module_config_func) (struct rspamd_config *cfg, bool validate); 217 218 int (*module_reconfig_func) (struct rspamd_config *cfg); 219 220 int (*module_attach_controller_func) (struct module_ctx *ctx, 221 GHashTable *custom_commands); 222 223 guint module_version; 224 guint64 rspamd_version; 225 const gchar *rspamd_features; 226 guint ctx_offset; 227 } module_t; 228 229 enum rspamd_worker_socket_type { 230 RSPAMD_WORKER_SOCKET_NONE = 0, 231 RSPAMD_WORKER_SOCKET_TCP = (1 << 0), 232 RSPAMD_WORKER_SOCKET_UDP = (1 << 1), 233 }; 234 235 struct rspamd_worker_listen_socket { 236 const rspamd_inet_addr_t *addr; 237 gint fd; 238 enum rspamd_worker_socket_type type; 239 bool is_systemd; 240 }; 241 242 typedef struct worker_s { 243 const gchar *name; 244 245 gpointer (*worker_init_func) (struct rspamd_config *cfg); 246 247 void (*worker_start_func) (struct rspamd_worker *worker); 248 249 int flags; 250 int listen_type; 251 guint worker_version; 252 guint64 rspamd_version; 253 const gchar *rspamd_features; 254 } worker_t; 255 256 /** 257 * Check if loaded worker is compatible with rspamd 258 * @param cfg 259 * @param wrk 260 * @return 261 */ 262 gboolean rspamd_check_worker (struct rspamd_config *cfg, worker_t *wrk); 263 264 /** 265 * Check if loaded module is compatible with rspamd 266 * @param cfg 267 * @param wrk 268 * @return 269 */ 270 gboolean rspamd_check_module (struct rspamd_config *cfg, module_t *wrk); 271 272 struct pidfh; 273 struct rspamd_config; 274 struct tokenizer; 275 struct rspamd_stat_classifier; 276 struct rspamd_classifier_config; 277 struct rspamd_mime_part; 278 struct rspamd_dns_resolver; 279 struct rspamd_task; 280 struct rspamd_cryptobox_library_ctx; 281 282 /** 283 * Server statistics 284 */ 285 struct rspamd_stat { 286 guint messages_scanned; /**< total number of messages scanned */ 287 guint actions_stat[METRIC_ACTION_MAX]; /**< statistic for each action */ 288 guint connections_count; /**< total connections count */ 289 guint control_connections_count; /**< connections count to control interface */ 290 guint messages_learned; /**< messages learned */ 291 }; 292 293 /** 294 * Struct that determine main server object (for logging purposes) 295 */ 296 struct rspamd_main { 297 struct rspamd_config *cfg; /**< pointer to config structure */ 298 pid_t pid; /**< main pid */ 299 /* Pid file structure */ 300 rspamd_pidfh_t *pfh; /**< struct pidfh for pidfile */ 301 GQuark type; /**< process type */ 302 struct rspamd_stat *stat; /**< pointer to statistics */ 303 304 rspamd_mempool_t *server_pool; /**< server's memory pool */ 305 rspamd_mempool_mutex_t *start_mtx; /**< server is starting up */ 306 GHashTable *workers; /**< workers pool indexed by pid */ 307 GHashTable *spairs; /**< socket pairs requested by workers */ 308 rspamd_logger_t *logger; 309 uid_t workers_uid; /**< worker's uid running to */ 310 gid_t workers_gid; /**< worker's gid running to */ 311 gboolean is_privilleged; /**< true if run in privilleged mode */ 312 gboolean wanna_die; /**< no respawn of processes */ 313 gboolean cores_throttling; /**< turn off cores when limits are exceeded */ 314 struct roll_history *history; /**< rolling history */ 315 struct ev_loop *event_loop; 316 ev_signal term_ev, int_ev, hup_ev, usr1_ev; /**< signals */ 317 struct rspamd_http_context *http_ctx; 318 }; 319 320 /** 321 * Control session object 322 */ 323 struct controller_command; 324 struct controller_session; 325 326 typedef gboolean (*controller_func_t) (gchar **args, 327 struct controller_session *session); 328 329 struct controller_session { 330 struct rspamd_worker *worker; /**< pointer to worker structure (controller in fact) */ 331 gint sock; /**< socket descriptor */ 332 struct controller_command *cmd; /**< real command */ 333 struct rspamd_config *cfg; /**< pointer to config file */ 334 GList *parts; /**< extracted mime parts */ 335 struct rspamd_async_session *s; /**< async session object */ 336 struct rspamd_dns_resolver *resolver; /**< DNS resolver */ 337 struct ev_loop *ev_base; /**< Event base */ 338 }; 339 340 struct zstd_dictionary { 341 void *dict; 342 gsize size; 343 guint id; 344 }; 345 346 struct rspamd_external_libs_ctx { 347 void **local_addrs; 348 struct rspamd_cryptobox_library_ctx *crypto_ctx; 349 struct ottery_config *ottery_cfg; 350 SSL_CTX *ssl_ctx; 351 SSL_CTX *ssl_ctx_noverify; 352 struct zstd_dictionary *in_dict; 353 struct zstd_dictionary *out_dict; 354 void *out_zstream; 355 void *in_zstream; 356 ref_entry_t ref; 357 }; 358 359 360 /** 361 * Register custom controller function 362 */ 363 void register_custom_controller_command (const gchar *name, 364 controller_func_t handler, 365 gboolean privilleged, 366 gboolean require_message); 367 368 #ifdef __cplusplus 369 } 370 #endif 371 372 #endif