1 /* $NetBSD: postscreen_misc.c,v 1.4 2022/10/08 16:12:48 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* postscreen_misc 3 6 /* SUMMARY 7 /* postscreen misc routines 8 /* SYNOPSIS 9 /* #include <postscreen.h> 10 /* 11 /* char *psc_format_delta_time(buf, tv, delta) 12 /* VSTRING *buf; 13 /* struct timeval tv; 14 /* DELTA_TIME *delta; 15 /* 16 /* void psc_conclude(state) 17 /* PSC_STATE *state; 18 /* 19 /* void psc_hangup_event(state) 20 /* PSC_STATE *state; 21 /* DESCRIPTION 22 /* psc_format_delta_time() computes the time difference between 23 /* tv (past) and the present, formats the time difference with 24 /* sub-second resolution in a human-readable way, and returns 25 /* the integer time difference in seconds through the delta 26 /* argument. 27 /* 28 /* psc_conclude() logs when a client passes all necessary tests, 29 /* updates the postscreen cache for any testes that were passed, 30 /* and either forwards the connection to a real SMTP server or 31 /* replies with the text in state->error_reply and hangs up the 32 /* connection (by default, state->error_reply is set to a 33 /* default 421 reply). 34 /* 35 /* psc_hangup_event() cleans up after a client connection breaks 36 /* unexpectedly. If logs the test where the break happened, 37 /* and how much time as spent in that test before the connection 38 /* broke. 39 /* LICENSE 40 /* .ad 41 /* .fi 42 /* The Secure Mailer license must be distributed with this software. 43 /* AUTHOR(S) 44 /* Wietse Venema 45 /* IBM T.J. Watson Research 46 /* P.O. Box 704 47 /* Yorktown Heights, NY 10598, USA 48 /* 49 /* Wietse Venema 50 /* Google, Inc. 51 /* 111 8th Avenue 52 /* New York, NY 10011, USA 53 /*--*/ 54 55 /* System library. */ 56 57 #include <sys_defs.h> 58 59 /* Utility library. */ 60 61 #include <msg.h> 62 #include <vstring.h> 63 #include <iostuff.h> 64 #include <format_tv.h> 65 66 /* Global library. */ 67 68 #include <mail_params.h> 69 70 /* Application-specific. */ 71 72 #include <postscreen.h> 73 74 /* psc_format_delta_time - pretty-formatted delta time */ 75 76 char *psc_format_delta_time(VSTRING *buf, struct timeval tv, 77 DELTA_TIME *delta) 78 { 79 DELTA_TIME pdelay; 80 struct timeval now; 81 82 GETTIMEOFDAY(&now); 83 PSC_CALC_DELTA(pdelay, now, tv); 84 VSTRING_RESET(buf); 85 format_tv(buf, pdelay.dt_sec, pdelay.dt_usec, SIG_DIGS, var_delay_max_res); 86 *delta = pdelay; 87 return (STR(buf)); 88 } 89 90 /* psc_conclude - bring this session to a conclusion */ 91 92 void psc_conclude(PSC_STATE *state) 93 { 94 const char *myname = "psc_conclude"; 95 96 if (msg_verbose) 97 msg_info("flags for %s: %s", 98 myname, psc_print_state_flags(state->flags, myname)); 99 100 /* 101 * Handle clients that passed at least one test other than permanent 102 * allowlisting, and that didn't fail any test including permanent 103 * denylisting. There may still be unfinished tests; those tests will 104 * need to be completed when the client returns in a later session. 105 */ 106 if (state->flags & PSC_STATE_MASK_ANY_FAIL) 107 state->flags &= ~PSC_STATE_MASK_ANY_PASS; 108 109 /* 110 * Log our final blessing when all unfinished tests were completed. 111 */ 112 if ((state->flags & PSC_STATE_MASK_ANY_PASS) != 0 113 && (state->flags & PSC_STATE_MASK_ANY_PASS) == 114 PSC_STATE_FLAGS_TODO_TO_PASS(state->flags & PSC_STATE_MASK_ANY_TODO)) 115 msg_info("PASS %s [%s]:%s", (state->flags & PSC_STATE_FLAG_NEW) == 0 116 || state->client_info->pass_new_count++ > 0 ? 117 "OLD" : "NEW", PSC_CLIENT_ADDR_PORT(state)); 118 119 /* 120 * Update the postscreen cache. This still supports a scenario where a 121 * client gets allowlisted in the course of multiple sessions, as long as 122 * that client does not "fail" any test. Don't try to optimize away cache 123 * updates; we want cached information to be up-to-date even if a test 124 * result is renewed during overlapping SMTP sessions, and even if 125 * 'postfix reload' happens in the middle of that. 126 */ 127 if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0 128 && psc_cache_map != 0) { 129 psc_print_tests(psc_temp, state); 130 psc_cache_update(psc_cache_map, state->smtp_client_addr, STR(psc_temp)); 131 } 132 133 /* 134 * Either hand off the socket to a real SMTP engine, or say bye-bye. 135 */ 136 if ((state->flags & PSC_STATE_FLAG_NOFORWARD) == 0) { 137 psc_send_socket(state); 138 } else { 139 if ((state->flags & PSC_STATE_FLAG_HANGUP) == 0) 140 (void) PSC_SEND_REPLY(state, state->final_reply); 141 msg_info("DISCONNECT [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); 142 psc_free_session_state(state); 143 } 144 } 145 146 /* psc_hangup_event - handle unexpected disconnect */ 147 148 void psc_hangup_event(PSC_STATE *state) 149 { 150 DELTA_TIME elapsed; 151 152 /* 153 * Sessions can break at any time, even after the client passes all tests 154 * (some MTAs including Postfix don't send QUIT when connection reuse is 155 * enabled). This must not be treated as a protocol test failure. 156 * 157 * Log the current test phase, and the elapsed time after the start of that 158 * phase. 159 */ 160 state->flags |= PSC_STATE_FLAG_HANGUP; 161 msg_info("HANGUP after %s from [%s]:%s in %s", 162 psc_format_delta_time(psc_temp, state->start_time, &elapsed), 163 PSC_CLIENT_ADDR_PORT(state), state->test_name); 164 state->flags |= PSC_STATE_FLAG_NOFORWARD; 165 psc_conclude(state); 166 } 167