xref: /netbsd-src/external/ibm-public/postfix/dist/src/postscreen/postscreen_misc.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: postscreen_misc.c,v 1.1.1.1 2011/03/02 19:32:26 tron 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 		 "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 
139 void    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