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