1 #ifndef SMTP_SERVER_H
2 #define SMTP_SERVER_H
3 
4 #include "smtp-common.h"
5 #include "smtp-command.h"
6 #include "smtp-params.h"
7 
8 struct smtp_address;
9 struct smtp_reply;
10 struct smtp_command;
11 
12 struct smtp_server_helo_data;
13 
14 struct smtp_server_esmtp_param;
15 struct smtp_server_cmd_ehlo;
16 struct smtp_server_cmd_mail;
17 struct smtp_server_cmd_ctx;
18 struct smtp_server_command;
19 struct smtp_server_reply;
20 struct smtp_server_recipient;
21 struct smtp_server_transaction;
22 
23 struct smtp_server;
24 
25 /*
26  * Types
27  */
28 
29 enum smtp_server_state {
30 	SMTP_SERVER_STATE_GREETING = 0,
31 	SMTP_SERVER_STATE_XCLIENT,
32 	SMTP_SERVER_STATE_HELO,
33 	SMTP_SERVER_STATE_STARTTLS,
34 	SMTP_SERVER_STATE_AUTH,
35 	SMTP_SERVER_STATE_READY,
36 	SMTP_SERVER_STATE_MAIL_FROM,
37 	SMTP_SERVER_STATE_RCPT_TO,
38 	SMTP_SERVER_STATE_DATA,
39 };
40 extern const char *const smtp_server_state_names[];
41 
42 struct smtp_server_helo_data {
43 	const char *domain;
44 
45 	bool domain_valid:1;  /* Valid domain/literal specified */
46 	bool old_smtp:1;      /* Client sent HELO rather than EHLO */
47 };
48 
49 /*
50  * Recipient
51  */
52 
53 enum smtp_server_recipient_hook_type {
54 	/* approved: the server is about to approve this recipient by sending
55 	   a success reply to the RCPT command. */
56 	SMTP_SERVER_RECIPIENT_HOOK_APPROVED,
57 	/* data_replied: the DATA command is replied for this recipient */
58 	SMTP_SERVER_RECIPIENT_HOOK_DATA_REPLIED,
59 	/* destroy: recipient is about to be destroyed. */
60 	SMTP_SERVER_RECIPIENT_HOOK_DESTROY
61 };
62 
63 typedef void smtp_server_rcpt_func_t(struct smtp_server_recipient *rcpt,
64 				     void *context);
65 
66 struct smtp_server_recipient {
67 	pool_t pool;
68 	struct smtp_server_connection *conn;
69 	struct smtp_server_transaction *trans;
70 	struct event *event;
71 
72 	struct smtp_address *path;
73 	struct smtp_params_rcpt params;
74 
75 	/* The associated RCPT or DATA command (whichever applies). This is NULL
76 	   when no command is active. */
77 	struct smtp_server_cmd_ctx *cmd;
78 
79 	/* The index in the list of approved recipients */
80 	unsigned int index;
81 
82 	void *context;
83 
84 	bool replied:1;
85 	bool finished:1;
86 };
87 ARRAY_DEFINE_TYPE(smtp_server_recipient, struct smtp_server_recipient *);
88 
89 /* Returns the original recipient path if available. Otherwise, it returns the
90    final path. */
91 const struct smtp_address *
92 smtp_server_recipient_get_original(struct smtp_server_recipient *rcpt);
93 
94 struct smtp_server_reply *
95 smtp_server_recipient_get_reply(struct smtp_server_recipient *rcpt);
96 bool smtp_server_recipient_is_replied(struct smtp_server_recipient *rcpt);
97 void smtp_server_recipient_replyv(struct smtp_server_recipient *rcpt,
98 				  unsigned int status, const char *enh_code,
99 				  const char *fmt, va_list args)
100 				  ATTR_FORMAT(4, 0);
101 void smtp_server_recipient_reply(struct smtp_server_recipient *rcpt,
102 				 unsigned int status, const char *enh_code,
103 				 const char *fmt, ...) ATTR_FORMAT(4, 5);
104 void smtp_server_recipient_reply_forward(struct smtp_server_recipient *rcpt,
105 					 const struct smtp_reply *from);
106 
107 /* Hooks */
108 
109 void smtp_server_recipient_add_hook(struct smtp_server_recipient *rcpt,
110 				    enum smtp_server_recipient_hook_type type,
111 				    smtp_server_rcpt_func_t func,
112 				    void *context);
113 #define smtp_server_recipient_add_hook(_rcpt, _type, _func, _context) \
114 	smtp_server_recipient_add_hook((_rcpt), (_type) - \
115 		CALLBACK_TYPECHECK(_func, void (*)( \
116 			struct smtp_server_recipient *, typeof(_context))), \
117 		(smtp_server_rcpt_func_t *)(_func), (_context))
118 void smtp_server_recipient_remove_hook(
119 	struct smtp_server_recipient *rcpt,
120 	enum smtp_server_recipient_hook_type type,
121 	smtp_server_rcpt_func_t *func);
122 #define smtp_server_recipient_remove_hook(_rcpt, _type, _func) \
123 	smtp_server_recipient_remove_hook((_rcpt), (_type), \
124 		(smtp_server_rcpt_func_t *)(_func));
125 
126 /*
127  * Transaction
128  */
129 
130 enum smtp_server_trace_rcpt_to_address {
131 	/* Don't add recipient address to trace header. */
132 	SMTP_SERVER_TRACE_RCPT_TO_ADDRESS_NONE,
133 	/* Add final recipient address to trace header. */
134 	SMTP_SERVER_TRACE_RCPT_TO_ADDRESS_FINAL,
135 	/* Add original recipient address to trace header. */
136 	SMTP_SERVER_TRACE_RCPT_TO_ADDRESS_ORIGINAL,
137 };
138 
139 enum smtp_server_transaction_flags {
140 	SMTP_SERVER_TRANSACTION_FLAG_REPLY_PER_RCPT = BIT(0),
141 };
142 
143 struct smtp_server_transaction {
144 	pool_t pool;
145 	struct smtp_server_connection *conn;
146 	struct event *event;
147 	const char *id;
148 	struct timeval timestamp;
149 
150 	enum smtp_server_transaction_flags flags;
151 
152 	struct smtp_address *mail_from;
153 	struct smtp_params_mail params;
154 	ARRAY_TYPE(smtp_server_recipient) rcpt_to;
155 
156 	/* The associated DATA command. This is NULL until the last DATA/BDAT
157 	   command is issued.
158 	 */
159 	struct smtp_server_cmd_ctx *cmd;
160 
161 	void *context;
162 
163 	bool finished:1;
164 };
165 
166 struct smtp_server_recipient *
167 smtp_server_transaction_find_rcpt_duplicate(
168 	struct smtp_server_transaction *trans,
169 	struct smtp_server_recipient *rcpt);
170 
171 void smtp_server_transaction_fail_data(struct smtp_server_transaction *trans,
172 				       struct smtp_server_cmd_ctx *data_cmd,
173 				       unsigned int status,
174 				       const char *enh_code,
175 				       const char *fmt, va_list args)
176 				       ATTR_FORMAT(5, 0);
177 
178 void smtp_server_transaction_write_trace_record(
179 	string_t *str, struct smtp_server_transaction *trans,
180 	enum smtp_server_trace_rcpt_to_address rcpt_to_address);
181 
182 /*
183  * Callbacks
184  */
185 
186 struct smtp_server_cmd_helo {
187 	struct smtp_server_helo_data helo;
188 
189 	bool first:1;         /* This is the first */
190 	bool changed:1;       /* This EHLO/HELO/LHLO is the first or different
191 	                         from a previous one */
192 };
193 
194 struct smtp_server_cmd_mail {
195 	struct smtp_address *path;
196 	struct smtp_params_mail params;
197 
198 	struct timeval timestamp;
199 
200 	enum smtp_server_transaction_flags flags;
201 };
202 
203 struct smtp_server_cmd_auth {
204 	const char *sasl_mech;
205 	const char *initial_response;
206 };
207 
208 struct smtp_server_callbacks {
209 	/* Command callbacks:
210 
211 	   These are used to override/implement the behavior of the various core
212 	   SMTP commands. Commands are handled asynchronously, which means that
213 	   the command is not necessarily finished when the callback ends. A
214 	   command is finished either when 1 is returned or a reply is submitted
215 	   for it. When a callback returns 0, the command implementation is
216 	   waiting for an external event and when it returns -1 an error
217 	   occurred. When 1 is returned, a default success reply is set if no
218 	   reply was submitted. Not submitting an error reply when -1 is
219 	   returned causes an assert fail. Except for RCPT and DATA, all these
220 	   callbacks are optional to implement; appropriate default behavior is
221 	   provided.
222 
223 	   The SMTP server API takes care of transaction state checking.
224 	   However, until all previous commands are handled, a transaction
225 	   command cannot rely on the transaction state being final. Use
226 	   cmd->hook_next to get notified when all previous commands are
227 	   finished and the current command is next in line to reply.
228 
229 	   If the implementation does not need asynchronous behavior, set
230 	   max_pipelined_commands=1 and don't return 0 from any command handler.
231 	  */
232 
233 	/* HELO/EHLO/LHLO */
234 	int (*conn_cmd_helo)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
235 			     struct smtp_server_cmd_helo *data);
236 	/* STARTTLS */
237 	int (*conn_cmd_starttls)(void *conn_ctx,
238 				 struct smtp_server_cmd_ctx *cmd);
239 	/* AUTH */
240 	int (*conn_cmd_auth)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
241 			     struct smtp_server_cmd_auth *data);
242 	int (*conn_cmd_auth_continue)(void *conn_ctx,
243 				      struct smtp_server_cmd_ctx *cmd,
244 				      const char *response);
245 	/* MAIL */
246 	int (*conn_cmd_mail)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
247 			     struct smtp_server_cmd_mail *data);
248 	/* RCPT */
249 	int (*conn_cmd_rcpt)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
250 			     struct smtp_server_recipient *rcpt);
251 	/* RSET */
252 	int (*conn_cmd_rset)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd);
253 	/* DATA */
254 	int (*conn_cmd_data_begin)(void *conn_ctx,
255 				   struct smtp_server_cmd_ctx *cmd,
256 				   struct smtp_server_transaction *trans,
257 				   struct istream *data_input);
258 	int (*conn_cmd_data_continue)(void *conn_ctx,
259 				     struct smtp_server_cmd_ctx *cmd,
260 				     struct smtp_server_transaction *trans);
261 	/* VRFY */
262 	int (*conn_cmd_vrfy)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
263 			     const char *param);
264 	/* NOOP */
265 	int (*conn_cmd_noop)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd);
266 	/* QUIT */
267 	int (*conn_cmd_quit)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd);
268 	/* XCLIENT */
269 	void (*conn_cmd_xclient)(void *conn_ctx,
270 				 struct smtp_server_cmd_ctx *cmd,
271 				 struct smtp_proxy_data *data);
272 
273 	/* Command input callbacks:
274 
275 	   These can be used to do stuff before and after a pipelined group of
276 	   commands is read.
277 	 */
278 	void (*conn_cmd_input_pre)(void *context);
279 	void (*conn_cmd_input_post)(void *context);
280 
281 	/* Transaction events */
282 	void (*conn_trans_start)(void *context,
283 				 struct smtp_server_transaction *trans);
284 	void (*conn_trans_free)(void *context,
285 				struct smtp_server_transaction *trans);
286 
287 	/* Protocol state events */
288 	void (*conn_state_changed)(void *context,
289 				   enum smtp_server_state new_state,
290 				   const char *new_args) ATTR_NULL(3);
291 
292 	/* Proxy data */
293 	void (*conn_proxy_data_updated)(void *conn_ctx,
294 					const struct smtp_proxy_data *data);
295 
296 	/* Connection */
297 	int (*conn_start_tls)(void *conn_ctx,
298 			      struct istream **input, struct ostream **output);
299 	/* Connection is disconnected. This is always called before
300 	   conn_free(). */
301 	void (*conn_disconnect)(void *context, const char *reason);
302 	/* The last reference to connection is dropped, causing the connection
303 	   to be freed. */
304 	void (*conn_free)(void *context);
305 
306 	/* Security */
307 	bool (*conn_is_trusted)(void *context);
308 };
309 
310 /*
311  * Server
312  */
313 
314 enum smtp_server_workarounds {
315 	SMTP_SERVER_WORKAROUND_WHITESPACE_BEFORE_PATH   = BIT(0),
316 	SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH         = BIT(1)
317 };
318 
319 struct smtp_server_settings {
320 	/* The protocol we are serving */
321 	enum smtp_protocol protocol;
322 	/* Standard capabilities supported by the server */
323 	enum smtp_capability capabilities;
324 	/* Enabled workarounds for client protocol deviations */
325 	enum smtp_server_workarounds workarounds;
326 
327 	/* Our hostname as presented to the client */
328 	const char *hostname;
329 	/* The message sent in the SMTP server greeting */
330 	const char *login_greeting;
331 	/* The directory that - if it exists and is accessible - is used to
332 	   write raw protocol logs for debugging */
333 	const char *rawlog_dir;
334 
335 	/* SSL settings; if NULL, master_service_ssl_init() is used instead */
336 	const struct ssl_iostream_settings *ssl;
337 
338 	/* The maximum time in milliseconds a client is allowed to be idle
339 	   before it is disconnected. */
340 	unsigned int max_client_idle_time_msecs;
341 
342 	/* Maximum number of commands in pipeline per connection (default = 1)
343 	 */
344 	unsigned int max_pipelined_commands;
345 
346 	/* Maximum number of sequential bad commands */
347 	unsigned int max_bad_commands;
348 
349 	/* Maximum number of recipients in a transaction
350 	   (0 means unlimited, which is the default) */
351 	unsigned int max_recipients;
352 
353 	/* Command limits */
354 	struct smtp_command_limits command_limits;
355 
356 	/* Message size limit */
357 	uoff_t max_message_size;
358 
359 	/* Accept these additional custom MAIL parameters */
360 	const char *const *mail_param_extensions;
361 	/* Accept these additional custom RCPT parameters */
362 	const char *const *rcpt_param_extensions;
363 	/* Accept these additional custom XCLIENT fields */
364 	const char *const *xclient_extensions;
365 
366 	/* The kernel send/receive buffer sizes used for the connection sockets.
367 	   Configuring this is mainly useful for the test suite. The kernel
368 	   defaults are used when these settings are 0. */
369 	size_t socket_send_buffer_size;
370 	size_t socket_recv_buffer_size;
371 
372 	/* Event to use for the smtp server. */
373 	struct event *event_parent;
374 
375 	/* Enable logging debug messages */
376 	bool debug:1;
377 	/* Authentication is not required for this service */
378 	bool auth_optional:1;
379 	/* TLS security is required for this service */
380 	bool tls_required:1;
381 	/* The path provided to the MAIL command does not need to be valid. A
382 	   completely invalid path will parse as <>. Paths that can still be
383 	   fixed by splitting it on the last `@' yielding a usable localpart and
384 	   domain, will be parsed as such. There are limits though; when the
385 	   path is badly delimited or contains control characters, the MAIL
386 	   command will still fail. The unparsed broken address will be
387 	   available in the `raw' field of struct smtp_address for logging etc.
388 	 */
389 	bool mail_path_allow_broken:1;
390 	/* The path provided to the RCPT command does not need to have the
391 	   domain part. */
392 	bool rcpt_domain_optional:1;
393 	/* Don't include "(state=%s)" in the disconnection reason string. */
394 	bool no_state_in_reason:1;
395 };
396 
397 struct smtp_server_stats {
398 	unsigned int command_count, reply_count;
399 	uoff_t input, output;
400 };
401 
402 /*
403  * Server
404  */
405 
406 struct smtp_server *smtp_server_init(const struct smtp_server_settings *set);
407 void smtp_server_deinit(struct smtp_server **_server);
408 
409 void smtp_server_switch_ioloop(struct smtp_server *server);
410 
411 /*
412  * Connection
413  */
414 
415 /* Create connection. It is still inactive and needs to be started with
416    one of the functions below. */
417 struct smtp_server_connection *
418 smtp_server_connection_create(
419 	struct smtp_server *server, int fd_in, int fd_out,
420 	const struct ip_addr *remote_ip, in_port_t remote_port, bool ssl_start,
421 	const struct smtp_server_settings *set,
422 	const struct smtp_server_callbacks *callbacks, void *context)
423 	ATTR_NULL(4, 6, 8);
424 struct smtp_server_connection *
425 smtp_server_connection_create_from_streams(
426 	struct smtp_server *server,
427 	struct istream *input, struct ostream *output,
428 	const struct ip_addr *remote_ip, in_port_t remote_port,
429 	const struct smtp_server_settings *set,
430 	const struct smtp_server_callbacks *callbacks, void *context)
431 	ATTR_NULL(4, 6, 8);
432 
433 void smtp_server_connection_ref(struct smtp_server_connection *conn);
434 bool smtp_server_connection_unref(struct smtp_server_connection **_conn);
435 
436 /* Initialize the connection with state and data from login service */
437 void smtp_server_connection_login(struct smtp_server_connection *conn,
438 				  const char *username, const char *helo,
439 				  const unsigned char *pdata,
440 				  unsigned int pdata_len, bool ssl_secured);
441 
442 /* Start the connection. Establishes SSL layer immediately if instructed,
443    and sends the greeting once the connection is ready for commands. */
444 void smtp_server_connection_start(struct smtp_server_connection *conn);
445 /* Start the connection, but only establish SSL layer and send greeting;
446    handling command input is held off until smtp_server_connection_resume() is
447    called. */
448 void smtp_server_connection_start_pending(struct smtp_server_connection *conn);
449 /* Abort the connection prematurely (before it is started). */
450 void smtp_server_connection_abort(struct smtp_server_connection **_conn,
451 				  unsigned int status, const char *enh_code,
452 				  const char *reason);
453 
454 /* Halt connection command input and idle timeout entirely. */
455 void smtp_server_connection_halt(struct smtp_server_connection *conn);
456 /* Resume connection command input and idle timeout. */
457 void smtp_server_connection_resume(struct smtp_server_connection *conn);
458 
459 void smtp_server_connection_input_lock(struct smtp_server_connection *conn);
460 void smtp_server_connection_input_unlock(struct smtp_server_connection *conn);
461 
462 void smtp_server_connection_set_streams(struct smtp_server_connection *conn,
463 					struct istream *input,
464 					struct ostream *output);
465 void smtp_server_connection_set_ssl_streams(struct smtp_server_connection *conn,
466 					    struct istream *input,
467 					    struct ostream *output);
468 
469 void smtp_server_connection_close(struct smtp_server_connection **_conn,
470 				  const char *reason) ATTR_NULL(2);
471 void smtp_server_connection_terminate(struct smtp_server_connection **_conn,
472 				      const char *enh_code, const char *reason)
473 				      ATTR_NULL(3);
474 
475 bool smtp_server_connection_data_check_state(struct smtp_server_cmd_ctx *cmd);
476 void smtp_server_connection_data_chunk_init(struct smtp_server_cmd_ctx *cmd);
477 int smtp_server_connection_data_chunk_add(struct smtp_server_cmd_ctx *cmd,
478 					  struct istream *chunk,
479 					  uoff_t chunk_size, bool chunk_last,
480 					  bool client_input);
481 
482 enum smtp_server_state
483 smtp_server_connection_get_state(struct smtp_server_connection *conn,
484 				 const char **args_r) ATTR_NULL(2);
485 const char *
486 smtp_server_connection_get_security_string(struct smtp_server_connection *conn);
487 struct smtp_server_transaction *
488 smtp_server_connection_get_transaction(struct smtp_server_connection *conn);
489 const char *
490 smtp_server_connection_get_transaction_id(struct smtp_server_connection *conn);
491 const struct smtp_server_stats *
492 smtp_server_connection_get_stats(struct smtp_server_connection *conn);
493 void *smtp_server_connection_get_context(struct smtp_server_connection *conn)
494 					 ATTR_PURE;
495 enum smtp_protocol
496 smtp_server_connection_get_protocol(struct smtp_server_connection *conn)
497 				    ATTR_PURE;
498 const char *
499 smtp_server_connection_get_protocol_name(struct smtp_server_connection *conn);
500 struct smtp_server_helo_data *
501 smtp_server_connection_get_helo_data(struct smtp_server_connection *conn);
502 
503 void smtp_server_connection_get_proxy_data(struct smtp_server_connection *conn,
504 					   struct smtp_proxy_data *proxy_data);
505 void smtp_server_connection_set_proxy_data(
506 	struct smtp_server_connection *conn,
507 	const struct smtp_proxy_data *proxy_data);
508 
509 void smtp_server_connection_set_capabilities(
510 	struct smtp_server_connection *conn, enum smtp_capability capabilities);
511 void smtp_server_connection_add_extra_capability(
512 	struct smtp_server_connection *conn,
513 	const struct smtp_capability_extra *cap);
514 
515 void smtp_server_connection_register_mail_param(
516 	struct smtp_server_connection *conn, const char *param);
517 void smtp_server_connection_register_rcpt_param(
518 	struct smtp_server_connection *conn, const char *param);
519 
520 bool smtp_server_connection_is_ssl_secured(struct smtp_server_connection *conn);
521 bool smtp_server_connection_is_trusted(struct smtp_server_connection *conn);
522 
523 /*
524  * Command
525  */
526 
527 enum smtp_server_command_flags {
528 	SMTP_SERVER_CMD_FLAG_PRETLS  = BIT(0),
529 	SMTP_SERVER_CMD_FLAG_PREAUTH = BIT(1)
530 };
531 
532 enum smtp_server_command_hook_type {
533 	/* next: command is next to reply but has not submittted all replies
534 	   yet. */
535 	SMTP_SERVER_COMMAND_HOOK_NEXT,
536 	/* replied_one: command has submitted one reply. */
537 	SMTP_SERVER_COMMAND_HOOK_REPLIED_ONE,
538 	/* replied: command has submitted all replies. */
539 	SMTP_SERVER_COMMAND_HOOK_REPLIED,
540 	/* completed: server is about to send last replies for this command. */
541 	SMTP_SERVER_COMMAND_HOOK_COMPLETED,
542 	/* destroy: command is about to be destroyed. */
543 	SMTP_SERVER_COMMAND_HOOK_DESTROY
544 };
545 
546 /* Commands are handled asynchronously, which means that the command is not
547    necessary finished when the start function ends. A command is finished
548    when a reply is submitted for it. Several command hooks are available to
549    get notified about events in the command's life cycle.
550  */
551 
552 typedef void smtp_server_cmd_input_callback_t(struct smtp_server_cmd_ctx *cmd);
553 typedef void smtp_server_cmd_start_func_t(struct smtp_server_cmd_ctx *cmd,
554 					  const char *params);
555 typedef void smtp_server_cmd_func_t(struct smtp_server_cmd_ctx *cmd,
556 				    void *context);
557 
558 struct smtp_server_cmd_ctx {
559 	pool_t pool;
560 	struct event *event;
561 	const char *name;
562 
563 	struct smtp_server *server;
564 	struct smtp_server_connection *conn;
565 	struct smtp_server_command *cmd;
566 };
567 
568 /* Hooks:
569 
570  */
571 
572 void smtp_server_command_add_hook(struct smtp_server_command *cmd,
573 				  enum smtp_server_command_hook_type type,
574 				  smtp_server_cmd_func_t func,
575 				  void *context);
576 #define smtp_server_command_add_hook(_cmd, _type, _func, _context) \
577 	smtp_server_command_add_hook((_cmd), (_type) - \
578 		CALLBACK_TYPECHECK(_func, void (*)( \
579 			struct smtp_server_cmd_ctx *, typeof(_context))), \
580 		(smtp_server_cmd_func_t *)(_func), (_context))
581 void smtp_server_command_remove_hook(struct smtp_server_command *cmd,
582 				     enum smtp_server_command_hook_type type,
583 				     smtp_server_cmd_func_t *func);
584 #define smtp_server_command_remove_hook(_cmd, _type, _func) \
585 	smtp_server_command_remove_hook((_cmd), (_type), \
586 		(smtp_server_cmd_func_t *)(_func));
587 
588 /* The core SMTP commands are pre-registered. Special connection callbacks are
589    provided for the core SMTP commands. Only use this command registration API
590    when custom/extension SMTP commands are required.
591  */
592 void smtp_server_command_register(struct smtp_server *server, const char *name,
593 				  smtp_server_cmd_start_func_t *func,
594 				  enum smtp_server_command_flags);
595 void smtp_server_command_unregister(struct smtp_server *server,
596 				    const char *name);
597 
598 void smtp_server_command_set_reply_count(struct smtp_server_command *cmd,
599 					 unsigned int count);
600 unsigned int
601 smtp_server_command_get_reply_count(struct smtp_server_command *cmd);
602 
603 void smtp_server_command_fail(struct smtp_server_command *cmd,
604 			      unsigned int status, const char *enh_code,
605 			      const char *fmt, ...) ATTR_FORMAT(4, 5);
606 
607 struct smtp_server_reply *
608 smtp_server_command_get_reply(struct smtp_server_command *cmd,
609 			      unsigned int idx);
610 bool smtp_server_command_reply_status_equals(struct smtp_server_command *cmd,
611 					     unsigned int status);
612 bool smtp_server_command_is_replied(struct smtp_server_command *cmd);
613 bool smtp_server_command_reply_is_forwarded(struct smtp_server_command *cmd);
614 bool smtp_server_command_replied_success(struct smtp_server_command *cmd);
615 
616 void smtp_server_command_input_lock(struct smtp_server_cmd_ctx *cmd);
617 void smtp_server_command_input_unlock(struct smtp_server_cmd_ctx *cmd);
618 void smtp_server_command_input_capture(
619 	struct smtp_server_cmd_ctx *cmd,
620 	smtp_server_cmd_input_callback_t *callback);
621 
622 /* EHLO */
623 
624 struct smtp_server_reply *
625 smtp_server_cmd_ehlo_reply_create(struct smtp_server_cmd_ctx *cmd);
626 void smtp_server_cmd_ehlo_reply_default(struct smtp_server_cmd_ctx *cmd);
627 
628 /* AUTH */
629 
630 void smtp_server_cmd_auth_send_challenge(struct smtp_server_cmd_ctx *cmd,
631 					 const char *challenge);
632 void smtp_server_cmd_auth_success(struct smtp_server_cmd_ctx *cmd,
633 				  const char *username, const char *success_msg)
634 				  ATTR_NULL(3);
635 
636 /* MAIL */
637 
638 void smtp_server_cmd_mail_reply_success(struct smtp_server_cmd_ctx *cmd);
639 
640 /* RCPT */
641 
642 bool smtp_server_command_is_rcpt(struct smtp_server_cmd_ctx *cmd);
643 void smtp_server_cmd_rcpt_reply_success(struct smtp_server_cmd_ctx *cmd);
644 
645 /* RSET */
646 
647 void smtp_server_cmd_rset_reply_success(struct smtp_server_cmd_ctx *cmd);
648 
649 /* DATA */
650 
651 bool smtp_server_cmd_data_check_size(struct smtp_server_cmd_ctx *cmd);
652 
653 /* VRFY */
654 
655 void smtp_server_cmd_vrfy_reply_default(struct smtp_server_cmd_ctx *cmd);
656 
657 /* NOOP */
658 
659 void smtp_server_cmd_noop_reply_success(struct smtp_server_cmd_ctx *cmd);
660 
661 /*
662  * Reply
663  */
664 
665 struct smtp_server_reply *
666 smtp_server_reply_create_index(struct smtp_server_command *cmd,
667 			       unsigned int index, unsigned int status,
668 			       const char *enh_code) ATTR_NULL(3);
669 struct smtp_server_reply *
670 smtp_server_reply_create(struct smtp_server_command *cmd, unsigned int status,
671 			 const char *enh_code) ATTR_NULL(3);
672 struct smtp_server_reply *
673 smtp_server_reply_create_forward(struct smtp_server_command *cmd,
674 				 unsigned int index,
675 				 const struct smtp_reply *from);
676 
677 void smtp_server_reply_set_status(struct smtp_server_reply *reply,
678 				  unsigned int status, const char *enh_code)
679 				  ATTR_NULL(3);
680 unsigned int smtp_server_reply_get_status(struct smtp_server_reply *reply,
681 					  const char **enh_code_r) ATTR_NULL(3);
682 
683 void smtp_server_reply_add_text(struct smtp_server_reply *reply,
684 				const char *line);
685 void smtp_server_reply_prepend_text(struct smtp_server_reply *reply,
686 				    const char *text_prefix);
687 void smtp_server_reply_replace_path(struct smtp_server_reply *reply,
688 				    struct smtp_address *path, bool add);
689 
690 void smtp_server_reply_submit(struct smtp_server_reply *reply);
691 void smtp_server_reply_submit_duplicate(struct smtp_server_cmd_ctx *_cmd,
692 					unsigned int index,
693 					unsigned int from_index);
694 
695 /* Submit a reply for the command at the specified index (> 0 only if more than
696    a single reply is expected). */
697 void smtp_server_reply_indexv(struct smtp_server_cmd_ctx *_cmd,
698 			      unsigned int index, unsigned int status,
699 			      const char *enh_code,
700 			      const char *fmt, va_list args) ATTR_FORMAT(5, 0);
701 void smtp_server_reply_index(struct smtp_server_cmd_ctx *_cmd,
702 			     unsigned int index, unsigned int status,
703 			     const char *enh_code, const char *fmt, ...)
704 			     ATTR_FORMAT(5, 6);
705 /* Submit the reply for the specified command. */
706 void smtp_server_reply(struct smtp_server_cmd_ctx *_cmd, unsigned int status,
707 		       const char *enh_code, const char *fmt, ...)
708 		       ATTR_FORMAT(4, 5);
709 /* Forward a reply for the command at the specified index (> 0 only if more
710    than a single reply is expected). */
711 void smtp_server_reply_index_forward(struct smtp_server_cmd_ctx *cmd,
712 				     unsigned int index,
713 				     const struct smtp_reply *from);
714 /* Forward the reply for the specified command. */
715 void smtp_server_reply_forward(struct smtp_server_cmd_ctx *cmd,
716 			       const struct smtp_reply *from);
717 /* Submit the same message for all expected replies for this command. */
718 void smtp_server_reply_all(struct smtp_server_cmd_ctx *_cmd,
719 			   unsigned int status, const char *enh_code,
720 			   const char *fmt, ...) ATTR_FORMAT(4, 5);
721 /* Submit and send the same message for all expected replies for this command
722    early; i.e., no matter whether all command data is received completely. */
723 void smtp_server_reply_early(struct smtp_server_cmd_ctx *_cmd,
724 			     unsigned int status, const char *enh_code,
725 			     const char *fmt, ...) ATTR_FORMAT(4, 5);
726 
727 /* Reply the command with a 221 bye message */
728 void smtp_server_reply_quit(struct smtp_server_cmd_ctx *_cmd);
729 
730 bool smtp_server_reply_is_success(const struct smtp_server_reply *reply);
731 
732 /* EHLO */
733 
734 struct smtp_server_reply *
735 smtp_server_reply_create_ehlo(struct smtp_server_command *cmd);
736 void smtp_server_reply_ehlo_add(struct smtp_server_reply *reply,
737 				const char *keyword);
738 void smtp_server_reply_ehlo_add_param(struct smtp_server_reply *reply,
739 				      const char *keyword,
740 				      const char *param_fmt, ...)
741 				      ATTR_FORMAT(3, 4);
742 void smtp_server_reply_ehlo_add_params(struct smtp_server_reply *reply,
743 				       const char *keyword,
744 				       const char *const *params) ATTR_NULL(3);
745 
746 void smtp_server_reply_ehlo_add_8bitmime(struct smtp_server_reply *reply);
747 void smtp_server_reply_ehlo_add_binarymime(struct smtp_server_reply *reply);
748 void smtp_server_reply_ehlo_add_chunking(struct smtp_server_reply *reply);
749 void smtp_server_reply_ehlo_add_dsn(struct smtp_server_reply *reply);
750 void smtp_server_reply_ehlo_add_enhancedstatuscodes(
751 	struct smtp_server_reply *reply);
752 void smtp_server_reply_ehlo_add_pipelining(struct smtp_server_reply *reply);
753 void smtp_server_reply_ehlo_add_size(struct smtp_server_reply *reply);
754 void smtp_server_reply_ehlo_add_starttls(struct smtp_server_reply *reply);
755 void smtp_server_reply_ehlo_add_vrfy(struct smtp_server_reply *reply);
756 void smtp_server_reply_ehlo_add_xclient(struct smtp_server_reply *reply);
757 
758 #endif
759