Postfix3.3.1
postscreen_state.c
[詳解]
1 /*++
2 /* NAME
3 /* postscreen_state 3
4 /* SUMMARY
5 /* postscreen session state and queue length management
6 /* SYNOPSIS
7 /* #include <postscreen.h>
8 /*
9 /* PSC_STATE *psc_new_session_state(stream, client_addr, client_port,
10 /* server_addr, server_port)
11 /* VSTREAM *stream;
12 /* const char *client_addr;
13 /* const char *client_port;
14 /* const char *server_addr;
15 /* const char *server_port;
16 /*
17 /* void psc_free_session_state(state)
18 /* PSC_STATE *state;
19 /*
20 /* char *psc_print_state_flags(flags, context)
21 /* int flags;
22 /* const char *context;
23 /*
24 /* void PSC_ADD_SERVER_STATE(state, server_fd)
25 /* PSC_STATE *state;
26 /* int server_fd;
27 /*
28 /* void PSC_DEL_CLIENT_STATE(state)
29 /* PSC_STATE *state;
30 /*
31 /* void PSC_DROP_SESSION_STATE(state, final_reply)
32 /* PSC_STATE *state;
33 /* const char *final_reply;
34 /*
35 /* void PSC_ENFORCE_SESSION_STATE(state, rcpt_reply)
36 /* PSC_STATE *state;
37 /* const char *rcpt_reply;
38 /*
39 /* void PSC_PASS_SESSION_STATE(state, testname, pass_flag)
40 /* PSC_STATE *state;
41 /* const char *testname;
42 /* int pass_flag;
43 /*
44 /* void PSC_FAIL_SESSION_STATE(state, fail_flag)
45 /* PSC_STATE *state;
46 /* int fail_flag;
47 /*
48 /* void PSC_UNFAIL_SESSION_STATE(state, fail_flag)
49 /* PSC_STATE *state;
50 /* int fail_flag;
51 /* DESCRIPTION
52 /* This module maintains per-client session state, and two
53 /* global file descriptor counters:
54 /* .IP psc_check_queue_length
55 /* The total number of remote SMTP client sockets.
56 /* .IP psc_post_queue_length
57 /* The total number of server file descriptors that are currently
58 /* in use for client file descriptor passing. This number
59 /* equals the number of client file descriptors in transit.
60 /* .PP
61 /* psc_new_session_state() creates a new session state object
62 /* for the specified client stream, and increments the
63 /* psc_check_queue_length counter. The flags and per-test time
64 /* stamps are initialized with PSC_INIT_TESTS(), or for concurrent
65 /* sessions, with PSC_INIT_TEST_FLAGS_ONLY(). The addr and
66 /* port arguments are null-terminated strings with the remote
67 /* SMTP client endpoint. The _reply members are set to
68 /* polite "try again" SMTP replies. The protocol member is set
69 /* to "SMTP".
70 /*
71 /* The psc_stress variable is set to non-zero when
72 /* psc_check_queue_length passes over a high-water mark.
73 /*
74 /* psc_free_session_state() destroys the specified session state
75 /* object, closes the applicable I/O channels, and decrements
76 /* the applicable file descriptor counters: psc_check_queue_length
77 /* and psc_post_queue_length.
78 /*
79 /* The psc_stress variable is reset to zero when psc_check_queue_length
80 /* passes under a low-water mark.
81 /*
82 /* psc_print_state_flags() converts per-session flags into
83 /* human-readable form. The context is for error reporting.
84 /* The result is overwritten upon each call.
85 /*
86 /* PSC_ADD_SERVER_STATE() updates the specified session state
87 /* object with the specified server file descriptor, and
88 /* increments the global psc_post_queue_length file descriptor
89 /* counter.
90 /*
91 /* PSC_DEL_CLIENT_STATE() updates the specified session state
92 /* object, closes the client stream, and decrements the global
93 /* psc_check_queue_length file descriptor counter.
94 /*
95 /* PSC_DROP_SESSION_STATE() updates the specified session state
96 /* object and closes the client stream after sending the
97 /* specified SMTP reply.
98 /*
99 /* PSC_ENFORCE_SESSION_STATE() updates the specified session
100 /* state object. It arranges that the built-in SMTP engine
101 /* logs sender/recipient information and rejects all RCPT TO
102 /* commands with the specified SMTP reply.
103 /*
104 /* PSC_PASS_SESSION_STATE() sets the specified "pass" flag.
105 /* The testname is used for debug logging.
106 /*
107 /* PSC_FAIL_SESSION_STATE() sets the specified "fail" flag.
108 /*
109 /* PSC_UNFAIL_SESSION_STATE() unsets the specified "fail" flag.
110 /* LICENSE
111 /* .ad
112 /* .fi
113 /* The Secure Mailer license must be distributed with this software.
114 /* AUTHOR(S)
115 /* Wietse Venema
116 /* IBM T.J. Watson Research
117 /* P.O. Box 704
118 /* Yorktown Heights, NY 10598, USA
119 /*
120 /* Wietse Venema
121 /* Google, Inc.
122 /* 111 8th Avenue
123 /* New York, NY 10011, USA
124 /*--*/
125 
126 /* System library. */
127 
128 #include <sys_defs.h>
129 
130 /* Utility library. */
131 
132 #include <msg.h>
133 #include <mymalloc.h>
134 #include <name_mask.h>
135 #include <htable.h>
136 
137 /* Global library. */
138 
139 #include <mail_proto.h>
140 
141 /* Master server protocols. */
142 
143 #include <mail_server.h>
144 
145 /* Application-specific. */
146 
147 #include <postscreen.h>
148 
149 /* psc_new_session_state - fill in connection state for event processing */
150 
152  const char *client_addr,
153  const char *client_port,
154  const char *server_addr,
155  const char *server_port)
156 {
157  PSC_STATE *state;
158 
159  state = (PSC_STATE *) mymalloc(sizeof(*state));
160  if ((state->smtp_client_stream = stream) != 0)
162  state->smtp_server_fd = (-1);
163  state->smtp_client_addr = mystrdup(client_addr);
164  state->smtp_client_port = mystrdup(client_port);
165  state->smtp_server_addr = mystrdup(server_addr);
166  state->smtp_server_port = mystrdup(server_port);
167  state->send_buf = vstring_alloc(100);
168  state->test_name = "TEST NAME HERE";
169  state->dnsbl_reply = 0;
170  state->final_reply = "421 4.3.2 Service currently unavailable\r\n";
171  state->rcpt_reply = "450 4.3.2 Service currently unavailable\r\n";
172  state->command_count = 0;
173  state->protocol = MAIL_PROTO_SMTP;
174  state->helo_name = 0;
175  state->sender = 0;
176  state->cmd_buffer = 0;
177  state->read_state = 0;
178  state->ehlo_discard_mask = 0; /* XXX Should be ~0 */
179  state->expand_buf = 0;
180  state->where = PSC_SMTPD_CMD_CONNECT;
181 
182  /*
183  * Update the stress level.
184  */
185  if (psc_stress == 0
187  psc_stress = 1;
188  msg_info("entering STRESS mode with %d connections",
190  }
191 
192  /*
193  * Update the per-client session count.
194  */
195  if ((state->client_info = (PSC_CLIENT_INFO *)
196  htable_find(psc_client_concurrency, client_addr)) == 0) {
197  state->client_info = (PSC_CLIENT_INFO *)
198  mymalloc(sizeof(state->client_info[0]));
199  (void) htable_enter(psc_client_concurrency, client_addr,
200  (void *) state->client_info);
201  PSC_INIT_TESTS(state);
202  state->client_info->concurrency = 1;
203  state->client_info->pass_new_count = 0;
204  } else {
206  state->client_info->concurrency += 1;
207  }
208 
209  return (state);
210 }
211 
212 /* psc_free_session_state - destroy connection state including connections */
213 
215 {
216  const char *myname = "psc_free_session_state";
217  HTABLE_INFO *ht;
218 
219  /*
220  * Update the per-client session count.
221  */
223  state->smtp_client_addr)) == 0)
224  msg_panic("%s: unknown client address: %s",
225  myname, state->smtp_client_addr);
226  if (--(state->client_info->concurrency) == 0)
228 
229  if (state->smtp_client_stream != 0) {
232  }
233  if (state->smtp_server_fd >= 0) {
234  close(state->smtp_server_fd);
236  }
237  if (state->send_buf != 0)
238  state->send_buf = vstring_free(state->send_buf);
239  myfree(state->smtp_client_addr);
240  myfree(state->smtp_client_port);
241  myfree(state->smtp_server_addr);
242  myfree(state->smtp_server_port);
243  if (state->dnsbl_reply)
244  vstring_free(state->dnsbl_reply);
245  if (state->helo_name)
246  myfree(state->helo_name);
247  if (state->sender)
248  myfree(state->sender);
249  if (state->cmd_buffer)
250  vstring_free(state->cmd_buffer);
251  if (state->expand_buf)
252  vstring_free(state->expand_buf);
253  myfree((void *) state);
254 
256  msg_panic("bad queue length: check_queue=%d, post_queue=%d",
258 
259  /*
260  * Update the stress level.
261  */
262  if (psc_stress != 0
264  psc_stress = 0;
265  msg_info("leaving STRESS mode with %d connections",
267  }
268 }
269 
270 /* psc_print_state_flags - format state flags */
271 
272 const char *psc_print_state_flags(int flags, const char *context)
273 {
274  static const NAME_MASK flags_mask[] = {
275  "NOFORWARD", PSC_STATE_FLAG_NOFORWARD,
276  "USING_TLS", PSC_STATE_FLAG_USING_TLS,
277  "NEW", PSC_STATE_FLAG_NEW,
278  "BLIST_FAIL", PSC_STATE_FLAG_BLIST_FAIL,
279  "HANGUP", PSC_STATE_FLAG_HANGUP,
280  /* unused */
281  "WLIST_FAIL", PSC_STATE_FLAG_WLIST_FAIL,
282 
283  "PREGR_FAIL", PSC_STATE_FLAG_PREGR_FAIL,
284  "PREGR_PASS", PSC_STATE_FLAG_PREGR_PASS,
285  "PREGR_TODO", PSC_STATE_FLAG_PREGR_TODO,
286  "PREGR_DONE", PSC_STATE_FLAG_PREGR_DONE,
287 
288  "DNSBL_FAIL", PSC_STATE_FLAG_DNSBL_FAIL,
289  "DNSBL_PASS", PSC_STATE_FLAG_DNSBL_PASS,
290  "DNSBL_TODO", PSC_STATE_FLAG_DNSBL_TODO,
291  "DNSBL_DONE", PSC_STATE_FLAG_DNSBL_DONE,
292 
293  "PIPEL_FAIL", PSC_STATE_FLAG_PIPEL_FAIL,
294  "PIPEL_PASS", PSC_STATE_FLAG_PIPEL_PASS,
295  "PIPEL_TODO", PSC_STATE_FLAG_PIPEL_TODO,
296  "PIPEL_SKIP", PSC_STATE_FLAG_PIPEL_SKIP,
297 
298  "NSMTP_FAIL", PSC_STATE_FLAG_NSMTP_FAIL,
299  "NSMTP_PASS", PSC_STATE_FLAG_NSMTP_PASS,
300  "NSMTP_TODO", PSC_STATE_FLAG_NSMTP_TODO,
301  "NSMTP_SKIP", PSC_STATE_FLAG_NSMTP_SKIP,
302 
303  "BARLF_FAIL", PSC_STATE_FLAG_BARLF_FAIL,
304  "BARLF_PASS", PSC_STATE_FLAG_BARLF_PASS,
305  "BARLF_TODO", PSC_STATE_FLAG_BARLF_TODO,
306  "BARLF_SKIP", PSC_STATE_FLAG_BARLF_SKIP,
307  0,
308  };
309 
310  return (str_name_mask_opt((VSTRING *) 0, context, flags_mask, flags,
312 }
PSC_CLIENT_INFO * client_info
Definition: postscreen.h:83
VSTRING * cmd_buffer
Definition: postscreen.h:94
#define PSC_STATE_FLAG_NEW
Definition: postscreen.h:115
void myfree(void *ptr)
Definition: mymalloc.c:207
int command_count
Definition: postscreen.h:90
#define PSC_STATE_FLAG_DNSBL_TODO
Definition: postscreen.h:193
HTABLE_INFO * htable_locate(HTABLE *table, const char *key)
Definition: htable.c:242
const char * rcpt_reply
Definition: postscreen.h:89
#define PSC_STATE_FLAG_NSMTP_TODO
Definition: postscreen.h:203
char * mystrdup(const char *str)
Definition: mymalloc.c:225
char * helo_name
Definition: postscreen.h:92
int ehlo_discard_mask
Definition: postscreen.h:97
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
char * sender
Definition: postscreen.h:93
#define PSC_STATE_FLAG_PIPEL_SKIP
Definition: postscreen.h:199
const char * test_name
Definition: postscreen.h:82
char * smtp_client_port
Definition: postscreen.h:75
#define PSC_STATE_FLAG_DNSBL_DONE
Definition: postscreen.h:194
#define PSC_STATE_FLAG_PIPEL_PASS
Definition: postscreen.h:197
#define PSC_SMTPD_CMD_CONNECT
Definition: postscreen.h:290
const char * psc_print_state_flags(int flags, const char *context)
int psc_check_queue_length
Definition: postscreen.c:527
#define PSC_INIT_TEST_FLAGS_ONLY(dst)
Definition: postscreen.h:495
#define PSC_STATE_FLAG_HANGUP
Definition: postscreen.h:117
#define PSC_STATE_FLAG_WLIST_FAIL
Definition: postscreen.h:119
const char * str_name_mask_opt(VSTRING *buf, const char *context, const NAME_MASK *table, int mask, int flags)
Definition: name_mask.c:265
const char * final_reply
Definition: postscreen.h:78
#define PSC_STATE_FLAG_BLIST_FAIL
Definition: postscreen.h:116
const char * where
Definition: postscreen.h:99
char * smtp_client_addr
Definition: postscreen.h:74
#define PSC_STATE_FLAG_DNSBL_FAIL
Definition: postscreen.h:191
VSTRING * dnsbl_reply
Definition: postscreen.h:84
#define PSC_STATE_FLAG_NSMTP_PASS
Definition: postscreen.h:202
#define PSC_INIT_TESTS(dst)
Definition: postscreen.h:487
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define PSC_STATE_FLAG_BARLF_SKIP
Definition: postscreen.h:209
char * smtp_server_addr
Definition: postscreen.h:76
void * htable_find(HTABLE *table, const char *key)
Definition: htable.c:227
#define MAIL_PROTO_SMTP
Definition: mail_proto.h:30
#define PSC_STATE_FLAG_PREGR_PASS
Definition: postscreen.h:187
void event_server_disconnect(VSTREAM *stream)
Definition: event_server.c:335
#define PSC_STATE_FLAG_PREGR_DONE
Definition: postscreen.h:189
void psc_free_session_state(PSC_STATE *state)
#define PSC_STATE_FLAG_NOFORWARD
Definition: postscreen.h:112
int psc_stress
Definition: postscreen.c:543
int smtp_server_fd
Definition: postscreen.h:73
#define PSC_STATE_FLAG_BARLF_FAIL
Definition: postscreen.h:206
VSTRING * send_buf
Definition: postscreen.h:79
int psc_hiwat_check_queue_length
Definition: postscreen.c:545
#define PSC_STATE_FLAG_USING_TLS
Definition: postscreen.h:113
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
#define NAME_MASK_NUMBER
Definition: name_mask.h:32
#define PSC_STATE_FLAG_PREGR_FAIL
Definition: postscreen.h:186
const char * protocol
Definition: postscreen.h:91
#define PSC_STATE_FLAG_BARLF_PASS
Definition: postscreen.h:207
VSTRING * expand_buf
Definition: postscreen.h:98
PSC_STATE * psc_new_session_state(VSTREAM *stream, const char *client_addr, const char *client_port, const char *server_addr, const char *server_port)
#define PSC_STATE_FLAG_DNSBL_PASS
Definition: postscreen.h:192
#define PSC_STATE_FLAG_PIPEL_TODO
Definition: postscreen.h:198
HTABLE * psc_client_concurrency
Definition: postscreen.c:547
#define PSC_STATE_FLAG_PIPEL_FAIL
Definition: postscreen.h:196
#define NAME_MASK_PIPE
Definition: name_mask.h:31
#define PSC_STATE_FLAG_NSMTP_SKIP
Definition: postscreen.h:204
void htable_delete(HTABLE *table, const char *key, void(*free_fn)(void *))
Definition: htable.c:257
int psc_lowat_check_queue_length
Definition: postscreen.c:544
int psc_post_queue_length
Definition: postscreen.c:528
char * smtp_server_port
Definition: postscreen.h:77
int read_state
Definition: postscreen.h:95
#define PSC_STATE_FLAG_BARLF_TODO
Definition: postscreen.h:208
VSTREAM * smtp_client_stream
Definition: postscreen.h:72
#define PSC_STATE_FLAG_PREGR_TODO
Definition: postscreen.h:188
#define PSC_STATE_FLAG_NSMTP_FAIL
Definition: postscreen.h:201
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
Definition: htable.c:212
void msg_info(const char *fmt,...)
Definition: msg.c:199