1/* $NetBSD$ */ 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 71char *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 87void 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 "OLD" : "NEW", PSC_CLIENT_ADDR_PORT(state)); 112 113 /* 114 * Update the postscreen cache. This still supports a scenario where a 115 * client gets whitelisted in the course of multiple sessions, as long as 116 * that client does not "fail" any test. 117 */ 118 if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0 119 && psc_cache_map != 0) { 120 psc_print_tests(psc_temp, state); 121 psc_cache_update(psc_cache_map, state->smtp_client_addr, STR(psc_temp)); 122 } 123 124 /* 125 * Either hand off the socket to a real SMTP engine, or say bye-bye. 126 */ 127 if ((state->flags & PSC_STATE_FLAG_NOFORWARD) == 0) { 128 psc_send_socket(state); 129 } else { 130 if ((state->flags & PSC_STATE_FLAG_HANGUP) == 0) 131 (void) PSC_SEND_REPLY(state, state->final_reply); 132 msg_info("DISCONNECT [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); 133 psc_free_session_state(state); 134 } 135} 136 137/* psc_hangup_event - handle unexpected disconnect */ 138 139void psc_hangup_event(PSC_STATE *state) 140{ 141 DELTA_TIME elapsed; 142 143 /* 144 * Sessions can break at any time, even after the client passes all tests 145 * (some MTAs including Postfix don't send QUIT when connection reuse is 146 * enabled). This must not be treated as a protocol test failure. 147 * 148 * Log the current test phase, and the elapsed time after the start of that 149 * phase. 150 */ 151 state->flags |= PSC_STATE_FLAG_HANGUP; 152 msg_info("HANGUP after %s from [%s]:%s in %s", 153 psc_format_delta_time(psc_temp, state->start_time, &elapsed), 154 PSC_CLIENT_ADDR_PORT(state), state->test_name); 155 state->flags |= PSC_STATE_FLAG_NOFORWARD; 156 psc_conclude(state); 157} 158