1 #ifndef SMTP_SERVER_PRIVATE_H
2 #define SMTP_SERVER_PRIVATE_H
3
4 #include "connection.h"
5
6 #include "smtp-server.h"
7
8 #define SMTP_SERVER_COMMAND_POOL_MAX (8 * 1024)
9
10 #define SMTP_SERVER_DEFAULT_MAX_COMMAND_LINE (4 * 1024)
11 #define SMTP_SERVER_DEFAULT_MAX_BAD_COMMANDS 10
12 #define SMTP_SERVER_DEFAULT_MAX_SIZE_EXCESS_LIMIT (1024*1024)
13
14 #define SMTP_SERVER_DEFAULT_CAPABILITIES \
15 (SMTP_CAPABILITY_SIZE | SMTP_CAPABILITY_ENHANCEDSTATUSCODES | \
16 SMTP_CAPABILITY_8BITMIME | SMTP_CAPABILITY_CHUNKING)
17
18 struct smtp_server_cmd_hook;
19 struct smtp_server_reply;
20 struct smtp_server_command;
21 struct smtp_server_connection;
22
23 ARRAY_DEFINE_TYPE(smtp_server_reply, struct smtp_server_reply);
24 ARRAY_DEFINE_TYPE(smtp_server_cmd_hook, struct smtp_server_cmd_hook);
25
26 enum smtp_server_command_state {
27 /* New command; callback to command start handler executing. */
28 SMTP_SERVER_COMMAND_STATE_NEW = 0,
29 /* This command is being processed; command data is fully read, but no
30 reply is yet submitted */
31 SMTP_SERVER_COMMAND_STATE_PROCESSING,
32 /* A reply is submitted for this command. If not all command data was
33 read by the handler, it is first skipped on the input. If this is a
34 multi-reply command (LMTP->DATA), not all replies may be submitted
35 yet. */
36 SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY,
37 /* Request is ready for sending reply; a reply is submitted and the
38 command payload is fully read. If this is a multi-reply command
39 (LMTP->DATA), not all replies may be submitted yet. In that case the
40 command state goes back to PROCESSING once the all submitted replies
41 are sent. */
42 SMTP_SERVER_COMMAND_STATE_READY_TO_REPLY,
43 /* The reply for the command is sent */
44 SMTP_SERVER_COMMAND_STATE_FINISHED,
45 /* Request is aborted; still lingering due to references */
46 SMTP_SERVER_COMMAND_STATE_ABORTED
47 };
48
49 struct smtp_server_command_hook {
50 enum smtp_server_command_hook_type type;
51 struct smtp_server_command_hook *prev, *next;
52
53 smtp_server_cmd_func_t *func;
54 void *context;
55 };
56
57 struct smtp_server_recipient_hook {
58 enum smtp_server_recipient_hook_type type;
59 struct smtp_server_recipient_hook *prev, *next;
60
61 smtp_server_rcpt_func_t *func;
62 void *context;
63 };
64
65 struct smtp_server_reply_content {
66 unsigned int status;
67 const char *enhanced_code;
68 const char *status_prefix;
69
70 string_t *text;
71 size_t last_line;
72 };
73
74 struct smtp_server_reply {
75 struct smtp_server_command *command;
76 unsigned int index;
77 struct event *event;
78
79 /* Replies may share content */
80 struct smtp_server_reply_content *content;
81
82 bool submitted:1;
83 bool sent:1;
84 bool forwarded:1;
85 };
86
87 struct smtp_server_command_reg {
88 const char *name;
89 enum smtp_server_command_flags flags;
90 smtp_server_cmd_start_func_t *func;
91 };
92
93 struct smtp_server_command {
94 struct smtp_server_cmd_ctx context;
95 const struct smtp_server_command_reg *reg;
96 int refcount;
97
98 enum smtp_server_command_state state;
99
100 struct smtp_server_command *prev, *next;
101
102 struct smtp_server_command_hook *hooks_head, *hooks_tail;
103 void *data;
104
105 ARRAY_TYPE(smtp_server_reply) replies;
106 unsigned int replies_expected;
107 unsigned int replies_submitted;
108
109 bool input_locked:1;
110 bool input_captured:1;
111 bool reply_early:1;
112 bool destroying:1;
113 };
114
115 struct smtp_server_recipient_private {
116 struct smtp_server_recipient rcpt;
117 int refcount;
118
119 struct smtp_server_recipient_hook *hooks_head, *hooks_tail;
120
121 bool destroying:1;
122 };
123
124 struct smtp_server_state_data {
125 enum smtp_server_state state;
126 char *args;
127 time_t timestamp;
128
129 unsigned int pending_mail_cmds;
130 unsigned int pending_rcpt_cmds, denied_rcpt_cmds;
131 unsigned int pending_data_cmds;
132
133 struct smtp_server_transaction *trans;
134 struct istream *data_input, *data_chain_input;
135 struct istream_chain *data_chain;
136 unsigned int data_chunks;
137 uoff_t data_size;
138
139 bool data_failed:1;
140 };
141
142 struct smtp_server_connection {
143 struct connection conn;
144 struct smtp_server *server;
145 pool_t pool;
146 int refcount;
147 struct event *event, *next_trans_event;
148
149 struct smtp_server_settings set;
150
151 ARRAY(struct smtp_capability_extra) extra_capabilities;
152 ARRAY_TYPE(const_string) mail_param_extensions; /* NULL-terminated */
153 ARRAY_TYPE(const_string) rcpt_param_extensions; /* NULL-terminated */
154
155 const struct smtp_server_callbacks *callbacks;
156 void *context;
157
158 enum smtp_proxy_protocol proxy_proto;
159 unsigned int proxy_ttl_plus_1;
160 unsigned int proxy_timeout_secs;
161 char *proxy_helo;
162
163 struct smtp_server_helo_data helo, *pending_helo;
164 char *helo_domain, *username;
165
166 struct timeout *to_idle;
167 struct istream *raw_input;
168 struct ostream *raw_output;
169 struct ssl_iostream_context *ssl_ctx;
170 struct ssl_iostream *ssl_iostream;
171 struct smtp_command_parser *smtp_parser;
172
173 struct smtp_server_command *command_queue_head, *command_queue_tail;
174 unsigned int command_queue_count;
175 unsigned int bad_counter;
176
177 struct smtp_server_state_data state;
178
179 struct smtp_server_stats stats;
180
181 bool started:1;
182 bool halted:1;
183 bool ssl_start:1;
184 bool ssl_secured:1;
185 bool authenticated:1;
186 bool created_from_streams:1;
187 bool corked:1;
188 bool disconnected:1;
189 bool closing:1;
190 bool closed:1;
191 bool input_broken:1;
192 bool input_locked:1;
193 bool handling_input:1;
194 bool rawlog_checked:1;
195 bool rawlog_enabled:1;
196 };
197
198 struct smtp_server {
199 pool_t pool;
200
201 struct smtp_server_settings set;
202
203 struct event *event;
204 struct ssl_iostream_context *ssl_ctx;
205
206 ARRAY(struct smtp_server_command_reg) commands_reg;
207
208 struct connection_list *conn_list;
209
210 bool commands_unsorted:1;
211 };
212
213 bool smtp_server_connection_pending_command_data(
214 struct smtp_server_connection *conn);
215
216 /*
217 * Reply
218 */
219
220 void smtp_server_reply_free(struct smtp_server_command *cmd);
221
222 int smtp_server_reply_send(struct smtp_server_reply *resp);
223
224 const char *
225 smtp_server_reply_get_one_line(const struct smtp_server_reply *reply);
226 const char *
227 smtp_server_reply_get_message(const struct smtp_server_reply *reply);
228
229 void smtp_server_reply_add_to_event(const struct smtp_server_reply *reply,
230 struct event_passthrough *e);
231
232 /*
233 * Command
234 */
235
236 void smtp_server_commands_init(struct smtp_server *server);
237
238 void smtp_server_command_debug(struct smtp_server_cmd_ctx *cmd,
239 const char *format, ...) ATTR_FORMAT(2, 3);
240
241 struct smtp_server_command *
242 smtp_server_command_new_invalid(struct smtp_server_connection *conn);
243 struct smtp_server_command *
244 smtp_server_command_new(struct smtp_server_connection *conn, const char *name);
245
246 void smtp_server_command_execute(struct smtp_server_command *cmd,
247 const char *params);
248
249 void smtp_server_command_ref(struct smtp_server_command *cmd);
250 bool smtp_server_command_unref(struct smtp_server_command **_cmd);
251 void smtp_server_command_abort(struct smtp_server_command **_cmd);
252
253 bool smtp_server_command_call_hooks(struct smtp_server_command **_cmd,
254 enum smtp_server_command_hook_type type,
255 bool remove);
256 void smtp_server_command_remove_hooks(struct smtp_server_command *cmd,
257 enum smtp_server_command_hook_type type);
258
259 void smtp_server_command_submit_reply(struct smtp_server_command *cmd);
260
261 int smtp_server_connection_flush(struct smtp_server_connection *conn);
262
263 void smtp_server_command_ready_to_reply(struct smtp_server_command *cmd);
264 void smtp_server_command_finished(struct smtp_server_command *cmd);
265
266 bool smtp_server_command_next_to_reply(struct smtp_server_command **_cmd);
267 bool smtp_server_command_completed(struct smtp_server_command **_cmd);
268
269 static inline bool
smtp_server_command_is_complete(struct smtp_server_command * cmd)270 smtp_server_command_is_complete(struct smtp_server_command *cmd)
271 {
272 struct smtp_server_connection *conn = cmd->context.conn;
273
274 return (conn->input_broken || (cmd->next != NULL) || cmd->reply_early ||
275 !smtp_server_connection_pending_command_data(conn));
276 }
277
278 void smtp_server_cmd_ehlo(struct smtp_server_cmd_ctx *cmd, const char *params);
279 void smtp_server_cmd_helo(struct smtp_server_cmd_ctx *cmd, const char *params);
280 void smtp_server_cmd_xclient(struct smtp_server_cmd_ctx *cmd,
281 const char *params);
282
283 void smtp_server_cmd_starttls(struct smtp_server_cmd_ctx *cmd,
284 const char *params);
285 void smtp_server_cmd_auth(struct smtp_server_cmd_ctx *cmd, const char *params);
286
287 void smtp_server_cmd_mail(struct smtp_server_cmd_ctx *cmd, const char *params);
288 void smtp_server_cmd_rcpt(struct smtp_server_cmd_ctx *cmd, const char *params);
289 void smtp_server_cmd_data(struct smtp_server_cmd_ctx *cmd, const char *params);
290 void smtp_server_cmd_bdat(struct smtp_server_cmd_ctx *cmd, const char *params);
291 void smtp_server_cmd_rset(struct smtp_server_cmd_ctx *cmd, const char *params);
292
293 void smtp_server_cmd_noop(struct smtp_server_cmd_ctx *cmd, const char *params);
294 void smtp_server_cmd_vrfy(struct smtp_server_cmd_ctx *cmd, const char *params);
295
296 void smtp_server_cmd_quit(struct smtp_server_cmd_ctx *cmd, const char *params);
297
298 /*
299 * Connection
300 */
301
302 typedef void smtp_server_input_callback_t(void *context);
303
304 void smtp_server_connection_debug(struct smtp_server_connection *conn,
305 const char *format, ...) ATTR_FORMAT(2, 3);
306
307 struct connection_list *smtp_server_connection_list_init(void);
308
309 void smtp_server_connection_switch_ioloop(struct smtp_server_connection *conn);
310
311 void smtp_server_connection_handle_output_error(
312 struct smtp_server_connection *conn);
313 void smtp_server_connection_trigger_output(struct smtp_server_connection *conn);
314 bool smtp_server_connection_pending_payload(struct smtp_server_connection *conn);
315
316 void smtp_server_connection_cork(struct smtp_server_connection *conn);
317 void smtp_server_connection_uncork(struct smtp_server_connection *conn);
318
319 void smtp_server_connection_input_halt(struct smtp_server_connection *conn);
320 void smtp_server_connection_input_resume(struct smtp_server_connection *conn);
321 void smtp_server_connection_input_capture(
322 struct smtp_server_connection *conn,
323 smtp_server_input_callback_t *callback, void *context);
324 #define smtp_server_connection_input_capture(conn, callback, context) \
325 smtp_server_connection_input_capture(conn - \
326 CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
327 (smtp_server_input_callback_t *)callback, context)
328
329 void smtp_server_connection_timeout_stop(struct smtp_server_connection *conn);
330 void smtp_server_connection_timeout_start(struct smtp_server_connection *conn);
331 void smtp_server_connection_timeout_reset(struct smtp_server_connection *conn);
332
333 void smtp_server_connection_send_line(struct smtp_server_connection *conn,
334 const char *fmt, ...) ATTR_FORMAT(2, 3);
335 void smtp_server_connection_reply_lines(struct smtp_server_connection *conn,
336 unsigned int status,
337 const char *enh_code,
338 const char *const *text_lines);
339 void smtp_server_connection_reply_immediate(
340 struct smtp_server_connection *conn, unsigned int status,
341 const char *fmt, ...) ATTR_FORMAT(3, 4);
342
343 void smtp_server_connection_reset_state(struct smtp_server_connection *conn);
344 void smtp_server_connection_set_state(struct smtp_server_connection *conn,
345 enum smtp_server_state state,
346 const char *args) ATTR_NULL(3);
347
348 int smtp_server_connection_ssl_init(struct smtp_server_connection *conn);
349
350 void smtp_server_connection_clear(struct smtp_server_connection *conn);
351
352 struct smtp_server_transaction *
353 smtp_server_connection_get_transaction(struct smtp_server_connection *conn);
354
355 /*
356 * Recipient
357 */
358
359 struct smtp_server_recipient *
360 smtp_server_recipient_create(struct smtp_server_cmd_ctx *cmd,
361 const struct smtp_address *rcpt_to,
362 const struct smtp_params_rcpt *params);
363 void smtp_server_recipient_ref(struct smtp_server_recipient *rcpt);
364 bool smtp_server_recipient_unref(struct smtp_server_recipient **_rcpt);
365 void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt);
366
367 bool smtp_server_recipient_approved(struct smtp_server_recipient **_rcpt);
368 void smtp_server_recipient_denied(struct smtp_server_recipient *rcpt,
369 const struct smtp_server_reply *reply);
370
371 void smtp_server_recipient_data_command(struct smtp_server_recipient *rcpt,
372 struct smtp_server_cmd_ctx *cmd);
373 void smtp_server_recipient_data_replied(struct smtp_server_recipient *rcpt);
374
375 void smtp_server_recipient_reset(struct smtp_server_recipient *rcpt);
376 void smtp_server_recipient_finished(struct smtp_server_recipient *rcpt,
377 const struct smtp_server_reply *reply);
378
379 bool smtp_server_recipient_call_hooks(
380 struct smtp_server_recipient **_rcpt,
381 enum smtp_server_recipient_hook_type type);
382
383 /*
384 * Transaction
385 */
386
387 struct smtp_server_transaction *
388 smtp_server_transaction_create(struct smtp_server_connection *conn,
389 const struct smtp_server_cmd_mail *mail_data);
390 void smtp_server_transaction_free(struct smtp_server_transaction **_trans);
391
392 void smtp_server_transaction_add_rcpt(struct smtp_server_transaction *trans,
393 struct smtp_server_recipient *rcpt);
394 bool smtp_server_transaction_has_rcpt(struct smtp_server_transaction *trans);
395 unsigned int
396 smtp_server_transaction_rcpt_count(struct smtp_server_transaction *trans);
397
398 void smtp_server_transaction_data_command(struct smtp_server_transaction *trans,
399 struct smtp_server_cmd_ctx *cmd);
400
401 void smtp_server_transaction_received(struct smtp_server_transaction *trans,
402 uoff_t data_size);
403
404 void smtp_server_transaction_reset(struct smtp_server_transaction *trans);
405 void smtp_server_transaction_finished(struct smtp_server_transaction *trans,
406 struct smtp_server_cmd_ctx *cmd);
407
408 /*
409 * Server
410 */
411
412 void smtp_server_event_init(struct smtp_server *server, struct event *event);
413 int smtp_server_init_ssl_ctx(struct smtp_server *server, const char **error_r);
414
415 #endif
416