1 /* $NetBSD: postscreen_misc.c,v 1.2 2017/02/14 01:16:47 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 50 /* System library. */ 51 52 #include <sys_defs.h> 53 54 /* Utility library. */ 55 56 #include <msg.h> 57 #include <vstring.h> 58 #include <iostuff.h> 59 #include <format_tv.h> 60 61 /* Global library. */ 62 63 #include <mail_params.h> 64 65 /* Application-specific. */ 66 67 #include <postscreen.h> 68 69 /* psc_format_delta_time - pretty-formatted delta time */ 70 71 char *psc_format_delta_time(VSTRING *buf, struct timeval tv, 72 DELTA_TIME *delta) 73 { 74 DELTA_TIME pdelay; 75 struct timeval now; 76 77 GETTIMEOFDAY(&now); 78 PSC_CALC_DELTA(pdelay, now, tv); 79 VSTRING_RESET(buf); 80 format_tv(buf, pdelay.dt_sec, pdelay.dt_usec, SIG_DIGS, var_delay_max_res); 81 *delta = pdelay; 82 return (STR(buf)); 83 } 84 85 /* psc_conclude - bring this session to a conclusion */ 86 87 void psc_conclude(PSC_STATE *state) 88 { 89 const char *myname = "psc_conclude"; 90 91 if (msg_verbose) 92 msg_info("flags for %s: %s", 93 myname, psc_print_state_flags(state->flags, myname)); 94 95 /* 96 * Handle clients that passed at least one test other than permanent 97 * whitelisting, and that didn't fail any test including permanent 98 * blacklisting. There may still be unfinished tests; those tests will 99 * need to be completed when the client returns in a later session. 100 */ 101 if (state->flags & PSC_STATE_MASK_ANY_FAIL) 102 state->flags &= ~PSC_STATE_MASK_ANY_PASS; 103 104 /* 105 * Log our final blessing when all unfinished tests were completed. 106 */ 107 if ((state->flags & PSC_STATE_MASK_ANY_PASS) != 0 108 && (state->flags & PSC_STATE_MASK_ANY_PASS) == 109 PSC_STATE_FLAGS_TODO_TO_PASS(state->flags & PSC_STATE_MASK_ANY_TODO)) 110 msg_info("PASS %s [%s]:%s", (state->flags & PSC_STATE_FLAG_NEW) == 0 111 || state->client_info->pass_new_count++ > 0 ? 112 "OLD" : "NEW", PSC_CLIENT_ADDR_PORT(state)); 113 114 /* 115 * Update the postscreen cache. This still supports a scenario where a 116 * client gets whitelisted in the course of multiple sessions, as long as 117 * that client does not "fail" any test. Don't try to optimize away cache 118 * updates; we want cached information to be up-to-date even if a test 119 * result is renewed during overlapping SMTP sessions, and even if 120 * 'postfix reload' happens in the middle of that. 121 */ 122 if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0 123 && psc_cache_map != 0) { 124 psc_print_tests(psc_temp, state); 125 psc_cache_update(psc_cache_map, state->smtp_client_addr, STR(psc_temp)); 126 } 127 128 /* 129 * Either hand off the socket to a real SMTP engine, or say bye-bye. 130 */ 131 if ((state->flags & PSC_STATE_FLAG_NOFORWARD) == 0) { 132 psc_send_socket(state); 133 } else { 134 if ((state->flags & PSC_STATE_FLAG_HANGUP) == 0) 135 (void) PSC_SEND_REPLY(state, state->final_reply); 136 msg_info("DISCONNECT [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); 137 psc_free_session_state(state); 138 } 139 } 140 141 /* psc_hangup_event - handle unexpected disconnect */ 142 143 void psc_hangup_event(PSC_STATE *state) 144 { 145 DELTA_TIME elapsed; 146 147 /* 148 * Sessions can break at any time, even after the client passes all tests 149 * (some MTAs including Postfix don't send QUIT when connection reuse is 150 * enabled). This must not be treated as a protocol test failure. 151 * 152 * Log the current test phase, and the elapsed time after the start of that 153 * phase. 154 */ 155 state->flags |= PSC_STATE_FLAG_HANGUP; 156 msg_info("HANGUP after %s from [%s]:%s in %s", 157 psc_format_delta_time(psc_temp, state->start_time, &elapsed), 158 PSC_CLIENT_ADDR_PORT(state), state->test_name); 159 state->flags |= PSC_STATE_FLAG_NOFORWARD; 160 psc_conclude(state); 161 } 162