Coverage Report

Created: 2023-10-10 06:32

/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