1 /* $NetBSD: postscreen.h,v 1.1.1.1 2011/03/02 19:32:26 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* postscreen 3h 6 /* SUMMARY 7 /* postscreen internal interfaces 8 /* SYNOPSIS 9 /* #include <postscreen.h> 10 /* DESCRIPTION 11 /* .nf 12 13 /* 14 * System library. 15 */ 16 17 /* 18 * Utility library. 19 */ 20 #include <dict_cache.h> 21 #include <vstream.h> 22 #include <vstring.h> 23 #include <events.h> 24 #include <htable.h> 25 26 /* 27 * Global library. 28 */ 29 #include <addr_match_list.h> 30 #include <string_list.h> 31 #include <maps.h> 32 33 /* 34 * Preliminary stuff, to be fixed. 35 */ 36 #define PSC_READ_BUF_SIZE 1024 37 38 /* 39 * Per-session state. 40 */ 41 typedef struct { 42 int flags; /* see below */ 43 /* Socket state. */ 44 VSTREAM *smtp_client_stream; /* remote SMTP client */ 45 int smtp_server_fd; /* real SMTP server */ 46 char *smtp_client_addr; /* client address */ 47 char *smtp_client_port; /* client port */ 48 int client_concurrency; /* per-client */ 49 const char *final_reply; /* cause for hanging up */ 50 VSTRING *send_buf; /* pending output */ 51 /* Test context. */ 52 struct timeval start_time; /* start of current test */ 53 const char *test_name; /* name of current test */ 54 /* Before-handshake tests. */ 55 time_t pregr_stamp; /* pregreet expiration time */ 56 time_t dnsbl_stamp; /* dnsbl expiration time */ 57 VSTRING *dnsbl_reply; /* dnsbl reject text */ 58 int dnsbl_index; /* dnsbl request index */ 59 time_t penal_stamp; /* penalty expiration time */ 60 /* Built-in SMTP protocol engine. */ 61 time_t pipel_stamp; /* pipelining expiration time */ 62 time_t nsmtp_stamp; /* non-smtp command expiration time */ 63 time_t barlf_stamp; /* bare newline expiration time */ 64 const char *rcpt_reply; /* how to reject recipients */ 65 int command_count; /* error + junk command count */ 66 const char *protocol; /* SMTP or ESMTP */ 67 char *helo_name; /* SMTP helo/ehlo */ 68 char *sender; /* MAIL FROM */ 69 VSTRING *cmd_buffer; /* command read buffer */ 70 int read_state; /* command read state machine */ 71 /* smtpd(8) compatibility */ 72 int ehlo_discard_mask; /* EHLO filter */ 73 VSTRING *expand_buf; /* macro expansion */ 74 } PSC_STATE; 75 76 #define PSC_TIME_STAMP_NEW (0) /* test was never passed */ 77 #define PSC_TIME_STAMP_DISABLED (1) /* never passed but disabled */ 78 #define PSC_TIME_STAMP_INVALID (-1) /* must not be cached */ 79 80 #define PSC_STATE_FLAG_NOFORWARD (1<<0) /* don't forward this session */ 81 #define PSC_STATE_FLAG_USING_TLS (1<<1) /* using the TLS proxy */ 82 #define PSC_STATE_FLAG_UNUSED2 (1<<2) /* use me! */ 83 #define PSC_STATE_FLAG_NEW (1<<3) /* some test was never passed */ 84 #define PSC_STATE_FLAG_BLIST_FAIL (1<<4) /* blacklisted */ 85 #define PSC_STATE_FLAG_HANGUP (1<<5) /* NOT a test failure */ 86 #define PSC_STATE_FLAG_CACHE_EXPIRED (1<<6) /* cache retention expired */ 87 88 /* 89 * Important: every MUMBLE_TODO flag must have a MUMBLE_PASS flag, such that 90 * MUMBLE_PASS == PSC_STATE_FLAGS_TODO_TO_PASS(MUMBLE_TODO). 91 * 92 * MUMBLE_TODO flags must not be cleared once raised. The _TODO_TO_PASS and 93 * _TODO_TO_DONE macros depend on this to decide that a group of tests is 94 * passed or completed. 95 * 96 * MUMBLE_DONE flags are used for "early" tests that have final results. 97 * 98 * MUMBLE_SKIP flags are used for "deep" tests where the client messed up. 99 * These flags look like MUMBLE_DONE but they are different. Deep tests can 100 * tentatively pass, but can still fail later in a session. The "ignore" 101 * action introduces an additional complication. MUMBLE_PASS indicates 102 * either that a deep test passed tentatively, or that the test failed but 103 * the result was ignored. MUMBLE_FAIL, on the other hand, is always final. 104 * We use MUMBLE_SKIP to indicate that a decision was either "fail" or 105 * forced "pass". 106 */ 107 #define PSC_STATE_FLAGS_TODO_TO_PASS(todo_flags) ((todo_flags) >> 1) 108 #define PSC_STATE_FLAGS_TODO_TO_DONE(todo_flags) ((todo_flags) << 1) 109 110 #define PSC_STATE_FLAG_PENAL_UPDATE (1<<6) /* save new penalty */ 111 #define PSC_STATE_FLAG_PENAL_FAIL (1<<7) /* penalty is active */ 112 113 #define PSC_STATE_FLAG_PREGR_FAIL (1<<8) /* failed pregreet test */ 114 #define PSC_STATE_FLAG_PREGR_PASS (1<<9) /* passed pregreet test */ 115 #define PSC_STATE_FLAG_PREGR_TODO (1<<10) /* pregreet test expired */ 116 #define PSC_STATE_FLAG_PREGR_DONE (1<<11) /* decision is final */ 117 118 #define PSC_STATE_FLAG_DNSBL_FAIL (1<<12) /* failed DNSBL test */ 119 #define PSC_STATE_FLAG_DNSBL_PASS (1<<13) /* passed DNSBL test */ 120 #define PSC_STATE_FLAG_DNSBL_TODO (1<<14) /* DNSBL test expired */ 121 #define PSC_STATE_FLAG_DNSBL_DONE (1<<15) /* decision is final */ 122 123 /* Room here for one more after-handshake test. */ 124 125 #define PSC_STATE_FLAG_PIPEL_FAIL (1<<20) /* failed pipelining test */ 126 #define PSC_STATE_FLAG_PIPEL_PASS (1<<21) /* passed pipelining test */ 127 #define PSC_STATE_FLAG_PIPEL_TODO (1<<22) /* pipelining test expired */ 128 #define PSC_STATE_FLAG_PIPEL_SKIP (1<<23) /* action is already logged */ 129 130 #define PSC_STATE_FLAG_NSMTP_FAIL (1<<24) /* failed non-SMTP test */ 131 #define PSC_STATE_FLAG_NSMTP_PASS (1<<25) /* passed non-SMTP test */ 132 #define PSC_STATE_FLAG_NSMTP_TODO (1<<26) /* non-SMTP test expired */ 133 #define PSC_STATE_FLAG_NSMTP_SKIP (1<<27) /* action is already logged */ 134 135 #define PSC_STATE_FLAG_BARLF_FAIL (1<<28) /* failed bare newline test */ 136 #define PSC_STATE_FLAG_BARLF_PASS (1<<29) /* passed bare newline test */ 137 #define PSC_STATE_FLAG_BARLF_TODO (1<<30) /* bare newline test expired */ 138 #define PSC_STATE_FLAG_BARLF_SKIP (1<<31) /* action is already logged */ 139 140 /* 141 * Aggregates for individual tests. 142 */ 143 #define PSC_STATE_MASK_PREGR_TODO_FAIL \ 144 (PSC_STATE_FLAG_PREGR_TODO | PSC_STATE_FLAG_PREGR_FAIL) 145 #define PSC_STATE_MASK_DNSBL_TODO_FAIL \ 146 (PSC_STATE_FLAG_DNSBL_TODO | PSC_STATE_FLAG_DNSBL_FAIL) 147 #define PSC_STATE_MASK_PIPEL_TODO_FAIL \ 148 (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_PIPEL_FAIL) 149 #define PSC_STATE_MASK_NSMTP_TODO_FAIL \ 150 (PSC_STATE_FLAG_NSMTP_TODO | PSC_STATE_FLAG_NSMTP_FAIL) 151 #define PSC_STATE_MASK_BARLF_TODO_FAIL \ 152 (PSC_STATE_FLAG_BARLF_TODO | PSC_STATE_FLAG_BARLF_FAIL) 153 154 #define PSC_STATE_MASK_PIPEL_TODO_SKIP \ 155 (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_PIPEL_SKIP) 156 #define PSC_STATE_MASK_NSMTP_TODO_SKIP \ 157 (PSC_STATE_FLAG_NSMTP_TODO | PSC_STATE_FLAG_NSMTP_SKIP) 158 #define PSC_STATE_MASK_BARLF_TODO_SKIP \ 159 (PSC_STATE_FLAG_BARLF_TODO | PSC_STATE_FLAG_BARLF_SKIP) 160 161 #define PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL \ 162 (PSC_STATE_MASK_PIPEL_TODO_FAIL | PSC_STATE_FLAG_PIPEL_PASS) 163 #define PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL \ 164 (PSC_STATE_MASK_NSMTP_TODO_FAIL | PSC_STATE_FLAG_NSMTP_PASS) 165 #define PSC_STATE_MASK_BARLF_TODO_PASS_FAIL \ 166 (PSC_STATE_MASK_BARLF_TODO_FAIL | PSC_STATE_FLAG_BARLF_PASS) 167 168 /* 169 * Separate aggregates for early tests and deep tests. 170 */ 171 #define PSC_STATE_MASK_EARLY_DONE \ 172 (PSC_STATE_FLAG_PREGR_DONE | PSC_STATE_FLAG_DNSBL_DONE) 173 #define PSC_STATE_MASK_EARLY_TODO \ 174 (PSC_STATE_FLAG_PREGR_TODO | PSC_STATE_FLAG_DNSBL_TODO) 175 #define PSC_STATE_MASK_EARLY_PASS \ 176 (PSC_STATE_FLAG_PREGR_PASS | PSC_STATE_FLAG_DNSBL_PASS) 177 #define PSC_STATE_MASK_EARLY_FAIL \ 178 (PSC_STATE_FLAG_PREGR_FAIL | PSC_STATE_FLAG_DNSBL_FAIL) 179 180 #define PSC_STATE_MASK_SMTPD_TODO \ 181 (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_NSMTP_TODO | \ 182 PSC_STATE_FLAG_BARLF_TODO) 183 #define PSC_STATE_MASK_SMTPD_PASS \ 184 (PSC_STATE_FLAG_PIPEL_PASS | PSC_STATE_FLAG_NSMTP_PASS | \ 185 PSC_STATE_FLAG_BARLF_PASS) 186 #define PSC_STATE_MASK_SMTPD_FAIL \ 187 (PSC_STATE_FLAG_PIPEL_FAIL | PSC_STATE_FLAG_NSMTP_FAIL | \ 188 PSC_STATE_FLAG_BARLF_FAIL) 189 190 /* 191 * Super-aggregates for all tests combined. 192 */ 193 #define PSC_STATE_MASK_ANY_FAIL \ 194 (PSC_STATE_FLAG_BLIST_FAIL | PSC_STATE_FLAG_PENAL_FAIL | \ 195 PSC_STATE_MASK_EARLY_FAIL | PSC_STATE_MASK_SMTPD_FAIL) 196 197 #define PSC_STATE_MASK_ANY_PASS \ 198 (PSC_STATE_MASK_EARLY_PASS | PSC_STATE_MASK_SMTPD_PASS) 199 200 #define PSC_STATE_MASK_ANY_TODO \ 201 (PSC_STATE_MASK_EARLY_TODO | PSC_STATE_MASK_SMTPD_TODO) 202 203 #define PSC_STATE_MASK_ANY_TODO_FAIL \ 204 (PSC_STATE_MASK_ANY_TODO | PSC_STATE_MASK_ANY_FAIL) 205 206 #define PSC_STATE_MASK_ANY_UPDATE \ 207 (PSC_STATE_MASK_ANY_PASS | PSC_STATE_FLAG_PENAL_UPDATE) 208 209 /* 210 * See log_adhoc.c for discussion. 211 */ 212 typedef struct { 213 int dt_sec; /* make sure it's signed */ 214 int dt_usec; /* make sure it's signed */ 215 } DELTA_TIME; 216 217 #define PSC_CALC_DELTA(x, y, z) \ 218 do { \ 219 (x).dt_sec = (y).tv_sec - (z).tv_sec; \ 220 (x).dt_usec = (y).tv_usec - (z).tv_usec; \ 221 while ((x).dt_usec < 0) { \ 222 (x).dt_usec += 1000000; \ 223 (x).dt_sec -= 1; \ 224 } \ 225 while ((x).dt_usec >= 1000000) { \ 226 (x).dt_usec -= 1000000; \ 227 (x).dt_sec += 1; \ 228 } \ 229 if ((x).dt_sec < 0) \ 230 (x).dt_sec = (x).dt_usec = 0; \ 231 } while (0) 232 233 #define SIG_DIGS 2 234 235 /* 236 * Event management. 237 */ 238 239 /* PSC_READ_EVENT_REQUEST - prepare for transition to next state */ 240 241 #define PSC_READ_EVENT_REQUEST(fd, action, context, timeout) do { \ 242 if (msg_verbose > 1) \ 243 msg_info("%s: read-request fd=%d", myname, (fd)); \ 244 event_enable_read((fd), (action), (context)); \ 245 event_request_timer((action), (context), (timeout)); \ 246 } while (0) 247 248 #define PSC_READ_EVENT_REQUEST2(fd, read_act, time_act, context, timeout) do { \ 249 if (msg_verbose > 1) \ 250 msg_info("%s: read-request fd=%d", myname, (fd)); \ 251 event_enable_read((fd), (read_act), (context)); \ 252 event_request_timer((time_act), (context), (timeout)); \ 253 } while (0) 254 255 /* PSC_CLEAR_EVENT_REQUEST - complete state transition */ 256 257 #define PSC_CLEAR_EVENT_REQUEST(fd, time_act, context) do { \ 258 if (msg_verbose > 1) \ 259 msg_info("%s: clear-request fd=%d", myname, (fd)); \ 260 event_disable_readwrite(fd); \ 261 event_cancel_timer((time_act), (context)); \ 262 } while (0) 263 264 /* 265 * Failure enforcement policies. 266 */ 267 #define PSC_NAME_ACT_DROP "drop" 268 #define PSC_NAME_ACT_ENFORCE "enforce" 269 #define PSC_NAME_ACT_IGNORE "ignore" 270 #define PSC_NAME_ACT_CONT "continue" 271 272 #define PSC_ACT_DROP 1 273 #define PSC_ACT_ENFORCE 2 274 #define PSC_ACT_IGNORE 3 275 276 /* 277 * Global variables. 278 */ 279 extern int psc_check_queue_length; /* connections being checked */ 280 extern int psc_post_queue_length; /* being sent to real SMTPD */ 281 extern DICT_CACHE *psc_cache_map; /* cache table handle */ 282 extern VSTRING *psc_temp; /* scratchpad */ 283 extern char *psc_smtpd_service_name; /* path to real SMTPD */ 284 extern int psc_pregr_action; /* PSC_ACT_DROP etc. */ 285 extern int psc_dnsbl_action; /* PSC_ACT_DROP etc. */ 286 extern int psc_pipel_action; /* PSC_ACT_DROP etc. */ 287 extern int psc_nsmtp_action; /* PSC_ACT_DROP etc. */ 288 extern int psc_barlf_action; /* PSC_ACT_DROP etc. */ 289 extern int psc_min_ttl; /* Update with new tests! */ 290 extern int psc_max_ttl; /* Update with new tests! */ 291 extern STRING_LIST *psc_forbid_cmds; /* CONNECT GET POST */ 292 extern int psc_stress_greet_wait; /* stressed greet wait */ 293 extern int psc_normal_greet_wait; /* stressed greet wait */ 294 extern int psc_stress_cmd_time_limit; /* stressed command limit */ 295 extern int psc_normal_cmd_time_limit; /* normal command time limit */ 296 extern int psc_stress; /* stress level */ 297 extern int psc_lowat_check_queue_length;/* stress low-water mark */ 298 extern int psc_hiwat_check_queue_length;/* stress high-water mark */ 299 extern DICT *psc_dnsbl_reply; /* DNSBL name mapper */ 300 extern HTABLE *psc_client_concurrency; /* per-client concurrency */ 301 302 #define PSC_EFF_GREET_WAIT \ 303 (psc_stress ? psc_stress_greet_wait : psc_normal_greet_wait) 304 #define PSC_EFF_CMD_TIME_LIMIT \ 305 (psc_stress ? psc_stress_cmd_time_limit : psc_normal_cmd_time_limit) 306 307 /* 308 * String plumbing macros. 309 */ 310 #define PSC_STRING_UPDATE(str, text) do { \ 311 if (str) myfree(str); \ 312 (str) = ((text) ? mystrdup(text) : 0); \ 313 } while (0) 314 315 #define PSC_STRING_RESET(str) do { \ 316 if (str) { \ 317 myfree(str); \ 318 (str) = 0; \ 319 } \ 320 } while (0) 321 322 /* 323 * SLMs. 324 */ 325 #define STR(x) vstring_str(x) 326 #define LEN(x) VSTRING_LEN(x) 327 328 /* 329 * postscreen_state.c 330 */ 331 #define PSC_CLIENT_ADDR_PORT(state) \ 332 (state)->smtp_client_addr, (state)->smtp_client_port 333 334 #define PSC_PASS_SESSION_STATE(state, what, bits) do { \ 335 if (msg_verbose) \ 336 msg_info("PASS %s [%s]:%s", (what), PSC_CLIENT_ADDR_PORT(state)); \ 337 (state)->flags |= (bits); \ 338 } while (0) 339 #define PSC_FAIL_SESSION_STATE(state, bits) do { \ 340 if (msg_verbose) \ 341 msg_info("FAIL [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \ 342 (state)->flags |= (bits); \ 343 } while (0) 344 #define PSC_SKIP_SESSION_STATE(state, what, bits) do { \ 345 if (msg_verbose) \ 346 msg_info("SKIP %s [%s]:%s", (what), PSC_CLIENT_ADDR_PORT(state)); \ 347 (state)->flags |= (bits); \ 348 } while (0) 349 #define PSC_DROP_SESSION_STATE(state, reply) do { \ 350 if (msg_verbose) \ 351 msg_info("DROP [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \ 352 (state)->flags |= PSC_STATE_FLAG_NOFORWARD; \ 353 (state)->final_reply = (reply); \ 354 psc_conclude(state); \ 355 } while (0) 356 #define PSC_ENFORCE_SESSION_STATE(state, reply) do { \ 357 if (msg_verbose) \ 358 msg_info("ENFORCE [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \ 359 (state)->rcpt_reply = (reply); \ 360 (state)->flags |= PSC_STATE_FLAG_NOFORWARD; \ 361 } while (0) 362 #define PSC_UNPASS_SESSION_STATE(state, bits) do { \ 363 if (msg_verbose) \ 364 msg_info("UNPASS [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \ 365 (state)->flags &= ~(bits); \ 366 } while (0) 367 #define PSC_UNFAIL_SESSION_STATE(state, bits) do { \ 368 if (msg_verbose) \ 369 msg_info("UNFAIL [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \ 370 (state)->flags &= ~(bits); \ 371 } while (0) 372 #define PSC_ADD_SERVER_STATE(state, fd) do { \ 373 (state)->smtp_server_fd = (fd); \ 374 psc_post_queue_length++; \ 375 } while (0) 376 #define PSC_DEL_CLIENT_STATE(state) do { \ 377 event_server_disconnect((state)->smtp_client_stream); \ 378 (state)->smtp_client_stream = 0; \ 379 psc_check_queue_length--; \ 380 } while (0) 381 extern PSC_STATE *psc_new_session_state(VSTREAM *, const char *, const char *); 382 extern void psc_free_session_state(PSC_STATE *); 383 extern const char *psc_print_state_flags(int, const char *); 384 385 /* 386 * postscreen_dict.c 387 */ 388 extern int psc_addr_match_list_match(ADDR_MATCH_LIST *, const char *); 389 extern const char *psc_cache_lookup(DICT_CACHE *, const char *); 390 extern void psc_cache_update(DICT_CACHE *, const char *, const char *); 391 const char *psc_dict_get(DICT *, const char *); 392 const char *psc_maps_find(MAPS *, const char *, int); 393 394 /* 395 * postscreen_dnsbl.c 396 */ 397 extern void psc_dnsbl_init(void); 398 extern int psc_dnsbl_retrieve(const char *, const char **, int); 399 extern int psc_dnsbl_request(const char *, void (*) (int, char *), char *); 400 401 /* 402 * postscreen_tests.c 403 */ 404 #define PSC_INIT_TESTS(dst) do { \ 405 (dst)->flags = 0; \ 406 (dst)->pregr_stamp = PSC_TIME_STAMP_INVALID; \ 407 (dst)->dnsbl_stamp = PSC_TIME_STAMP_INVALID; \ 408 (dst)->pipel_stamp = PSC_TIME_STAMP_INVALID; \ 409 (dst)->barlf_stamp = PSC_TIME_STAMP_INVALID; \ 410 (dst)->penal_stamp = PSC_TIME_STAMP_INVALID; \ 411 } while (0) 412 #define PSC_BEGIN_TESTS(state, name) do { \ 413 (state)->test_name = (name); \ 414 GETTIMEOFDAY(&(state)->start_time); \ 415 } while (0) 416 extern void psc_new_tests(PSC_STATE *); 417 extern void psc_parse_tests(PSC_STATE *, const char *, time_t); 418 extern char *psc_print_tests(VSTRING *, PSC_STATE *); 419 extern char *psc_print_grey_key(VSTRING *, const char *, const char *, 420 const char *, const char *); 421 422 #define PSC_MIN(x, y) ((x) < (y) ? (x) : (y)) 423 #define PSC_MAX(x, y) ((x) > (y) ? (x) : (y)) 424 425 /* 426 * postscreen_early.c 427 */ 428 extern void psc_early_tests(PSC_STATE *); 429 extern void psc_early_init(void); 430 431 /* 432 * postscreen_smtpd.c 433 */ 434 extern void psc_smtpd_tests(PSC_STATE *); 435 extern void psc_smtpd_init(void); 436 extern void psc_smtpd_pre_jail_init(void); 437 438 /* 439 * postscreen_misc.c 440 */ 441 extern char *psc_format_delta_time(VSTRING *, struct timeval, DELTA_TIME *); 442 extern void psc_conclude(PSC_STATE *); 443 extern void psc_hangup_event(PSC_STATE *); 444 445 /* 446 * postscreen_send.c 447 */ 448 #define PSC_SEND_REPLY psc_send_reply /* legacy macro */ 449 extern int psc_send_reply(PSC_STATE *, const char *); 450 extern void psc_send_socket(PSC_STATE *); 451 452 /* 453 * postscreen_starttls.c 454 */ 455 extern void psc_starttls_open(PSC_STATE *, EVENT_NOTIFY_FN); 456 457 /* 458 * postscreen_expand.c 459 */ 460 extern VSTRING *psc_expand_filter; 461 extern void psc_expand_init(void); 462 extern const char *psc_expand_lookup(const char *, int, char *); 463 464 /* 465 * postscreen_access.c 466 */ 467 #define PSC_ACL_ACT_WHITELIST 1 468 #define PSC_ACL_ACT_DUNNO 0 469 #define PSC_ACL_ACT_BLACKLIST (-1) 470 #define PSC_ACL_ACT_ERROR (-2) 471 472 extern void psc_acl_pre_jail_init(void); 473 extern ARGV *psc_acl_parse(const char *, const char *); 474 extern int psc_acl_eval(PSC_STATE *, ARGV *, const char *); 475 476 /* LICENSE 477 /* .ad 478 /* .fi 479 /* The Secure Mailer license must be distributed with this software. 480 /* AUTHOR(S) 481 /* Wietse Venema 482 /* IBM T.J. Watson Research 483 /* P.O. Box 704 484 /* Yorktown Heights, NY 10598, USA 485 /*--*/ 486