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