Coverage Report

Created: 2025-08-26 07:01

/src/dovecot/src/lib-smtp/smtp-server-connection.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "llist.h"
5
#include "array.h"
6
#include "str.h"
7
#include "guid.h"
8
#include "base64.h"
9
#include "ioloop.h"
10
#include "istream.h"
11
#include "ostream.h"
12
#include "iostream.h"
13
#include "connection.h"
14
#include "iostream-rawlog.h"
15
#include "iostream-ssl.h"
16
#include "settings.h"
17
#include "master-service.h"
18
#include "master-service-ssl.h"
19
20
#include "smtp-syntax.h"
21
#include "smtp-reply-parser.h"
22
#include "smtp-command-parser.h"
23
#include "smtp-server-private.h"
24
#include "ssl-settings.h"
25
26
const char *const smtp_server_state_names[] = {
27
  "GREETING",
28
  "XCLIENT",
29
  "HELO",
30
  "STARTTLS",
31
  "AUTH",
32
  "READY",
33
  "MAIL FROM",
34
  "RCPT TO",
35
  "DATA"
36
};
37
38
/*
39
 * Connection
40
 */
41
42
static void smtp_server_connection_input(struct connection *_conn);
43
static int smtp_server_connection_output(struct smtp_server_connection *conn);
44
static void
45
smtp_server_connection_disconnect(struct smtp_server_connection *conn,
46
          const char *reason) ATTR_NULL(2);
47
48
static void
49
smtp_server_connection_update_stats(struct smtp_server_connection *conn)
50
6.47k
{
51
6.47k
  if (conn->conn.input != NULL)
52
6.47k
    conn->stats.input = conn->conn.input->v_offset;
53
6.47k
  if (conn->conn.output != NULL)
54
6.47k
    conn->stats.output = conn->conn.output->offset;
55
6.47k
  connection_update_counters(&conn->conn);
56
6.47k
}
57
58
const struct smtp_server_stats *
59
smtp_server_connection_get_stats(struct smtp_server_connection *conn)
60
0
{
61
0
  smtp_server_connection_update_stats(conn);
62
0
  return &conn->stats;
63
0
}
64
65
static bool
66
smtp_server_connection_check_pipeline(struct smtp_server_connection *conn)
67
160k
{
68
160k
  unsigned int pipeline = conn->command_queue_count;
69
70
160k
  if (conn->command_queue_tail != NULL) {
71
120k
    i_assert(pipeline > 0);
72
120k
    if (conn->command_queue_tail->state ==
73
120k
        SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY)
74
3.23k
      pipeline--;
75
120k
  }
76
77
160k
  if (pipeline >= conn->set.max_pipelined_commands) {
78
4.26k
    e_debug(conn->event, "Command pipeline is full "
79
4.26k
      "(pipelined commands %u > limit %u)",
80
4.26k
      pipeline, conn->set.max_pipelined_commands);
81
4.26k
    return FALSE;
82
4.26k
  }
83
155k
  return TRUE;
84
160k
}
85
86
void smtp_server_connection_input_halt(struct smtp_server_connection *conn)
87
73.2k
{
88
73.2k
  connection_input_halt(&conn->conn);
89
73.2k
}
90
91
void smtp_server_connection_input_resume(struct smtp_server_connection *conn)
92
68.3k
{
93
68.3k
  struct smtp_server_command *cmd;
94
68.3k
  bool cmd_locked = FALSE;
95
96
68.3k
  if (conn->conn.io == NULL) {
97
    /* Only resume when we actually can */
98
50.4k
    if (conn->input_locked || conn->input_broken ||
99
50.4k
      conn->disconnected)
100
8.18k
      return;
101
42.2k
    if (!smtp_server_connection_check_pipeline(conn))
102
608
      return;
103
104
    /* Is queued command still blocking input? */
105
41.6k
    cmd = conn->command_queue_head;
106
145k
    while (cmd != NULL) {
107
103k
      if (cmd->input_locked || cmd->pipeline_blocked) {
108
0
        cmd_locked = TRUE;
109
0
        break;
110
0
      }
111
103k
      cmd = cmd->next;
112
103k
    }
113
41.6k
    if (cmd_locked)
114
0
      return;
115
116
    /* Restore input handler */
117
41.6k
    connection_input_resume(&conn->conn);
118
41.6k
  }
119
120
59.5k
  if (conn->conn.io != NULL &&
121
59.5k
    i_stream_have_bytes_left(conn->conn.input)) {
122
59.5k
    io_set_pending(conn->conn.io);
123
59.5k
  }
124
59.5k
}
125
126
void smtp_server_connection_input_lock(struct smtp_server_connection *conn)
127
20.2k
{
128
20.2k
  conn->input_locked = TRUE;
129
20.2k
  smtp_server_connection_input_halt(conn);
130
20.2k
}
131
132
void smtp_server_connection_input_unlock(struct smtp_server_connection *conn)
133
20.2k
{
134
20.2k
  conn->input_locked = FALSE;
135
20.2k
  smtp_server_connection_input_resume(conn);
136
20.2k
}
137
138
#undef smtp_server_connection_input_capture
139
void smtp_server_connection_input_capture(
140
  struct smtp_server_connection *conn,
141
  smtp_server_input_callback_t *callback, void *context)
142
11.7k
{
143
11.7k
  i_assert(!conn->input_broken && !conn->disconnected);
144
11.7k
  connection_input_halt(&conn->conn);
145
11.7k
  i_stream_set_input_pending(conn->conn.input, TRUE);
146
11.7k
  conn->conn.io = io_add_istream(conn->conn.input, *callback, context);
147
11.7k
}
148
149
static void
150
smtp_server_connection_update_rawlog(struct smtp_server_connection *conn)
151
6.47k
{
152
6.47k
  struct stat st;
153
154
6.47k
  if (conn->set.rawlog_dir == NULL)
155
6.47k
    return;
156
157
0
  if (!conn->rawlog_checked) {
158
0
    conn->rawlog_checked = TRUE;
159
0
    if (stat(conn->set.rawlog_dir, &st) == 0)
160
0
      conn->rawlog_enabled = TRUE;
161
0
  }
162
0
  if (conn->rawlog_enabled) {
163
0
    iostream_rawlog_create(conn->set.rawlog_dir,
164
0
               &conn->conn.input, &conn->conn.output);
165
0
  }
166
0
}
167
168
static void
169
smtp_server_connection_streams_changed(struct smtp_server_connection *conn)
170
0
{
171
0
  smtp_server_connection_update_rawlog(conn);
172
0
  smtp_command_parser_set_stream(conn->smtp_parser, conn->conn.input);
173
174
0
  o_stream_set_flush_callback(conn->conn.output,
175
0
    smtp_server_connection_output, conn);
176
0
  o_stream_set_flush_pending(conn->conn.output, TRUE);
177
0
}
178
179
void smtp_server_connection_set_streams(struct smtp_server_connection *conn,
180
          struct istream *input,
181
          struct ostream *output)
182
0
{
183
0
  struct istream *old_input = conn->conn.input;
184
0
  struct ostream *old_output = conn->conn.output;
185
186
0
  i_assert(conn->created_from_streams);
187
188
0
  conn->conn.input = input;
189
0
  i_stream_ref(conn->conn.input);
190
191
0
  conn->conn.output = output;
192
0
  o_stream_ref(conn->conn.output);
193
0
  o_stream_set_no_error_handling(conn->conn.output, TRUE);
194
195
0
  i_stream_unref(&old_input);
196
0
  o_stream_unref(&old_output);
197
198
0
  smtp_server_connection_streams_changed(conn);
199
0
}
200
201
void smtp_server_connection_set_ssl_streams(struct smtp_server_connection *conn,
202
              struct istream *input,
203
              struct ostream *output)
204
0
{
205
0
  conn->ssl_secured = TRUE;
206
0
  conn->set.capabilities &= ENUM_NEGATE(SMTP_CAPABILITY_STARTTLS);
207
208
0
  smtp_server_connection_set_streams(conn, input, output);
209
0
}
210
211
static void
212
smtp_server_connection_idle_timeout(struct smtp_server_connection *conn)
213
0
{
214
0
  smtp_server_connection_terminate(
215
0
    &conn, "4.4.2", "Disconnected for inactivity");
216
0
}
217
218
void smtp_server_connection_timeout_stop(struct smtp_server_connection *conn)
219
123k
{
220
123k
  if (conn->to_idle != NULL) {
221
40.8k
    e_debug(conn->event, "Timeout stop");
222
223
40.8k
    timeout_remove(&conn->to_idle);
224
40.8k
  }
225
123k
}
226
227
void smtp_server_connection_timeout_start(struct smtp_server_connection *conn)
228
47.7k
{
229
47.7k
  if (conn->disconnected)
230
767
    return;
231
232
47.0k
  if (conn->to_idle == NULL &&
233
47.0k
    conn->set.max_client_idle_time_msecs > 0) {
234
40.8k
    e_debug(conn->event, "Timeout start");
235
236
40.8k
    conn->to_idle = timeout_add(
237
40.8k
      conn->set.max_client_idle_time_msecs,
238
40.8k
      smtp_server_connection_idle_timeout, conn);
239
40.8k
  }
240
47.0k
}
241
242
void smtp_server_connection_timeout_reset(struct smtp_server_connection *conn)
243
86.0k
{
244
86.0k
  if (conn->to_idle != NULL)
245
60.0k
    timeout_reset(conn->to_idle);
246
86.0k
}
247
248
static void
249
smtp_server_connection_timeout_update(struct smtp_server_connection *conn)
250
144k
{
251
144k
  struct smtp_server_command *cmd = conn->command_queue_head;
252
253
144k
  if (cmd == NULL) {
254
35.8k
    smtp_server_connection_timeout_start(conn);
255
35.8k
    return;
256
35.8k
  }
257
258
108k
  switch (cmd->state) {
259
0
  case SMTP_SERVER_COMMAND_STATE_NEW:
260
0
    smtp_server_connection_timeout_start(conn);
261
0
    break;
262
177
  case SMTP_SERVER_COMMAND_STATE_PROCESSING:
263
177
    if (cmd->input_captured) {
264
      /* Command updates timeout internally */
265
177
      return;
266
177
    }
267
0
    smtp_server_connection_timeout_stop(conn);
268
0
    break;
269
942
  case SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY:
270
108k
  case SMTP_SERVER_COMMAND_STATE_READY_TO_REPLY:
271
108k
    smtp_server_connection_timeout_stop(conn);
272
108k
    break;
273
0
  case SMTP_SERVER_COMMAND_STATE_FINISHED:
274
0
  case SMTP_SERVER_COMMAND_STATE_ABORTED:
275
0
    i_unreached();
276
108k
  }
277
108k
}
278
279
static void smtp_server_connection_ready(struct smtp_server_connection *conn)
280
6.47k
{
281
6.47k
  conn->raw_input = conn->conn.input;
282
6.47k
  conn->raw_output = conn->conn.output;
283
284
6.47k
  conn->connect_succeeded = TRUE;
285
286
6.47k
  smtp_server_connection_update_rawlog(conn);
287
288
6.47k
  conn->smtp_parser = smtp_command_parser_init(conn->conn.input,
289
6.47k
                 &conn->set.command_limits);
290
6.47k
  o_stream_set_flush_callback(conn->conn.output,
291
6.47k
            smtp_server_connection_output, conn);
292
293
6.47k
  o_stream_cork(conn->conn.output);
294
6.47k
  if (conn->set.no_greeting) {
295
    /* Don't send greeting or login reply. */
296
6.47k
  } else if (conn->authenticated) {
297
    /* RFC 4954, Section 4:
298
       Should the client successfully complete the exchange, the
299
       SMTP server issues a 235 reply. */
300
0
    smtp_server_connection_send_line(
301
0
      conn, "235 2.7.0 Logged in.");
302
6.47k
  } else {
303
6.47k
    smtp_server_connection_send_line(
304
6.47k
      conn, "220 %s %s", conn->set.hostname,
305
6.47k
      conn->set.login_greeting);
306
6.47k
  }
307
6.47k
  if (!conn->corked)
308
6.47k
    o_stream_uncork(conn->conn.output);
309
6.47k
}
310
311
static void smtp_server_connection_destroy(struct connection *_conn)
312
3.97k
{
313
3.97k
  struct smtp_server_connection *conn =
314
3.97k
    (struct smtp_server_connection *)_conn;
315
316
3.97k
  smtp_server_connection_disconnect(conn, NULL);
317
3.97k
  smtp_server_connection_unref(&conn);
318
3.97k
}
319
320
static bool
321
smtp_server_connection_handle_command(struct smtp_server_connection *conn,
322
              const char *cmd_name,
323
              const char *cmd_params)
324
108k
{
325
108k
  struct smtp_server_connection *tmp_conn = conn;
326
108k
  struct smtp_server_command *cmd;
327
108k
  bool finished;
328
329
108k
  cmd = smtp_server_command_new(tmp_conn, cmd_name);
330
331
108k
  smtp_server_command_ref(cmd);
332
333
108k
  smtp_server_connection_ref(tmp_conn);
334
108k
  smtp_server_command_execute(cmd, cmd_params);
335
108k
  if (!smtp_server_connection_unref(&tmp_conn)) {
336
    /* The command start callback managed to get this connection
337
       destroyed */
338
0
    smtp_server_command_unref(&cmd);
339
0
    return FALSE;
340
0
  }
341
342
108k
  if (conn->command_queue_head == cmd)
343
23.3k
    (void)smtp_server_command_next_to_reply(&cmd);
344
345
108k
  smtp_server_connection_timeout_update(conn);
346
347
108k
  finished = !cmd->input_locked;
348
108k
  return (!smtp_server_command_unref(&cmd) || finished);
349
108k
}
350
351
static int
352
smtp_server_connection_sni_callback(const char *name, const char **error_r,
353
            void *context)
354
0
{
355
0
  struct smtp_server_connection *conn = context;
356
0
  struct ssl_iostream_context *ssl_ctx;
357
0
  const struct ssl_settings *ssl_set;
358
0
  const struct ssl_server_settings *ssl_server_set;
359
360
0
  event_add_str(conn->event, "local_name", name);
361
0
  i_free(conn->local_name);
362
0
  conn->local_name = i_strdup(name);
363
0
  if (ssl_server_settings_get(conn->event, &ssl_set, &ssl_server_set,
364
0
            error_r) < 0)
365
0
    return -1;
366
0
  if (conn->local_name != NULL && *conn->local_name != '\0')
367
0
    conn->set.hostname = conn->local_name;
368
0
  if (conn->callbacks->conn_tls_sni_callback != NULL &&
369
0
      conn->callbacks->conn_tls_sni_callback(conn->context, name,
370
0
               error_r) < 0) {
371
0
    settings_free(ssl_set);
372
0
    settings_free(ssl_server_set);
373
0
    return -1;
374
0
  }
375
376
0
  ssl_server_settings_to_iostream_set(ssl_set, ssl_server_set,
377
0
              &conn->set.ssl);
378
379
0
  int ret;
380
0
  if ((ret = ssl_iostream_server_context_cache_get(conn->set.ssl, &ssl_ctx,
381
0
               error_r)) < 0) {
382
0
    settings_free(ssl_set);
383
0
    settings_free(ssl_server_set);
384
0
    return -1;
385
0
  }
386
0
  settings_free(ssl_set);
387
0
  settings_free(ssl_server_set);
388
0
  if (ret == 1) {
389
0
    const char *application_protocol = smtp_protocol_name(conn->set.protocol);
390
0
    const char *const names[] = {
391
0
      application_protocol,
392
0
      NULL
393
0
    };
394
0
    ssl_iostream_context_set_application_protocols(ssl_ctx, names);
395
0
  }
396
0
  ssl_iostream_change_context(conn->ssl_iostream, ssl_ctx);
397
0
  ssl_iostream_context_unref(&ssl_ctx);
398
0
  return 0;
399
0
}
400
401
int smtp_server_connection_ssl_init(struct smtp_server_connection *conn)
402
0
{
403
0
  struct ssl_iostream_context *ssl_ctx;
404
0
  const char *error;
405
0
  int ret;
406
407
0
  e_debug(conn->event, "Starting SSL handshake");
408
409
0
  if (conn->raw_input != conn->conn.input) {
410
    /* Recreate rawlog after STARTTLS */
411
0
    i_stream_ref(conn->raw_input);
412
0
    o_stream_ref(conn->raw_output);
413
0
    i_stream_destroy(&conn->conn.input);
414
0
    o_stream_destroy(&conn->conn.output);
415
0
    conn->conn.input = conn->raw_input;
416
0
    conn->conn.output = conn->raw_output;
417
0
  }
418
419
0
  smtp_server_connection_input_halt(conn);
420
0
  if (conn->set.ssl == NULL) {
421
0
    const struct ssl_iostream_server_autocreate_parameters parameters = {
422
0
      .event_parent = conn->event,
423
0
    };
424
0
    ret = io_stream_autocreate_ssl_server(&parameters,
425
0
      &conn->conn.input, &conn->conn.output,
426
0
      &conn->ssl_iostream, &error);
427
0
  } else if (ssl_iostream_server_context_cache_get(conn->set.ssl,
428
0
               &ssl_ctx, &error) < 0)
429
0
    ret = -1;
430
0
  else {
431
0
    ret = io_stream_create_ssl_server(ssl_ctx, conn->event,
432
0
      &conn->conn.input, &conn->conn.output,
433
0
      &conn->ssl_iostream, &error);
434
0
    ssl_iostream_context_unref(&ssl_ctx);
435
0
  }
436
0
  if (ret < 0) {
437
0
    e_error(conn->event,
438
0
      "Couldn't initialize SSL server for %s: %s",
439
0
      conn->conn.name, error);
440
0
    return -1;
441
0
  }
442
0
  ssl_iostream_set_sni_callback(
443
0
    conn->ssl_iostream, smtp_server_connection_sni_callback, conn);
444
0
  smtp_server_connection_input_resume(conn);
445
446
0
  if (ssl_iostream_handshake(conn->ssl_iostream) < 0) {
447
0
    e_error(conn->event, "SSL handshake failed: %s",
448
0
      ssl_iostream_get_last_error(conn->ssl_iostream));
449
0
    return -1;
450
0
  }
451
452
0
  conn->ssl_secured = TRUE;
453
0
  conn->set.capabilities &= ENUM_NEGATE(SMTP_CAPABILITY_STARTTLS);
454
455
0
  if (conn->connect_succeeded)
456
0
    smtp_server_connection_streams_changed(conn);
457
0
  else if (conn->ssl_start &&
458
0
     ssl_iostream_is_handshaked(conn->ssl_iostream))
459
0
    smtp_server_connection_ready(conn);
460
461
0
  return 0;
462
0
}
463
464
static void
465
smtp_server_connection_handle_input(struct smtp_server_connection *conn)
466
28.0k
{
467
28.0k
  struct smtp_server_command *pending_command;
468
28.0k
  enum smtp_command_parse_error error_code;
469
28.0k
  const char *cmd_name, *cmd_params, *error;
470
28.0k
  int ret;
471
472
  /* Check whether we are continuing a command */
473
28.0k
  pending_command = NULL;
474
28.0k
  if (conn->command_queue_tail != NULL) {
475
267
    pending_command =
476
267
      ((conn->command_queue_tail->state ==
477
267
        SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY) ?
478
162
       conn->command_queue_tail : NULL);
479
267
  }
480
481
28.0k
  smtp_server_connection_timeout_reset(conn);
482
483
  /* Parse commands */
484
28.0k
  ret = 1;
485
57.5k
  while (!conn->closing && !conn->input_locked && ret != 0) {
486
129k
    while ((ret = smtp_command_parse_next(
487
129k
      conn->smtp_parser, &cmd_name, &cmd_params,
488
129k
      &error_code, &error)) > 0) {
489
490
108k
      if (pending_command != NULL) {
491
        /* Previous command is now fully read and ready
492
           to reply */
493
2.64k
        smtp_server_command_ready_to_reply(pending_command);
494
2.64k
        pending_command = NULL;
495
2.64k
      }
496
497
108k
      e_debug(conn->event, "Received new command: %s %s",
498
108k
        cmd_name, cmd_params);
499
500
108k
      conn->stats.command_count++;
501
502
      /* Handle command (cmd may be destroyed after this) */
503
108k
      if (!smtp_server_connection_handle_command(conn,
504
108k
        cmd_name, cmd_params))
505
4.51k
        return;
506
507
103k
      if (conn->disconnected)
508
222
        return;
509
      /* Last command locked the input; stop trying to read
510
         more. */
511
103k
      if (conn->input_locked)
512
13.7k
        break;
513
      /* Client indicated it will close after this command;
514
         stop trying to read more. */
515
89.8k
      if (conn->closing)
516
0
        break;
517
518
89.8k
      if (!smtp_server_connection_check_pipeline(conn)) {
519
3.64k
        smtp_server_connection_input_halt(conn);
520
3.64k
        return;
521
3.64k
      }
522
523
86.2k
      if (conn->command_queue_tail != NULL) {
524
86.2k
        pending_command =
525
86.2k
          ((conn->command_queue_tail->state ==
526
86.2k
            SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY) ?
527
2.86k
           conn->command_queue_tail : NULL);
528
86.2k
      }
529
86.2k
    }
530
531
35.1k
    if (ret < 0 && conn->conn.input->eof) {
532
5.58k
      const char *error =
533
5.58k
        i_stream_get_disconnect_reason(conn->conn.input);
534
5.58k
      e_debug(conn->event, "Remote closed connection: %s",
535
5.58k
        error);
536
537
5.58k
      if (conn->command_queue_head == NULL ||
538
5.58k
          conn->command_queue_head->state <
539
3.99k
          SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY) {
540
        /* No pending commands or unfinished
541
           command; close */
542
1.59k
        smtp_server_connection_close(&conn, error);
543
3.99k
      } else {
544
        /* A command is still processing;
545
           only drop input io for now */
546
3.99k
        conn->input_broken = TRUE;
547
3.99k
        smtp_server_connection_input_halt(conn);
548
3.99k
      }
549
5.58k
      return;
550
5.58k
    }
551
552
29.5k
    if (ret < 0) {
553
15.5k
      struct smtp_server_command *cmd;
554
555
15.5k
      e_debug(conn->event,
556
15.5k
        "Client sent invalid command: %s", error);
557
558
15.5k
      switch (error_code) {
559
0
      case SMTP_COMMAND_PARSE_ERROR_BROKEN_COMMAND:
560
0
        conn->input_broken = TRUE;
561
        /* fall through */
562
15.1k
      case SMTP_COMMAND_PARSE_ERROR_BAD_COMMAND:
563
15.1k
        cmd = smtp_server_command_new_invalid(conn);
564
15.1k
        smtp_server_command_fail(
565
15.1k
          cmd, 500, "5.5.2",
566
15.1k
          "Invalid command syntax");
567
15.1k
        break;
568
414
      case SMTP_COMMAND_PARSE_ERROR_LINE_TOO_LONG:
569
414
        cmd = smtp_server_command_new_invalid(conn);
570
414
        smtp_server_command_fail(
571
414
          cmd, 500, "5.5.2", "Line too long");
572
414
        break;
573
0
      case SMTP_COMMAND_PARSE_ERROR_DATA_TOO_LARGE:
574
        /* Command data size exceeds the absolute limit;
575
           i.e. beyond which we don't even want to skip
576
           data anymore. The command error is usually
577
           already submitted by the application and sent
578
           to the client. */
579
0
        smtp_server_connection_close(&conn,
580
0
          "Command data size exceeds absolute limit");
581
0
        return;
582
0
      case SMTP_COMMAND_PARSE_ERROR_BROKEN_STREAM:
583
0
        smtp_server_connection_close(&conn, error);
584
0
        return;
585
0
      default:
586
0
        i_unreached();
587
15.5k
      }
588
15.5k
    }
589
590
29.5k
    if (conn->disconnected)
591
91
      return;
592
29.4k
    if (conn->input_broken || conn->closing) {
593
0
      smtp_server_connection_input_halt(conn);
594
0
      return;
595
0
    }
596
597
29.4k
    if (ret == 0 && pending_command != NULL &&
598
29.4k
        !smtp_command_parser_pending_data(conn->smtp_parser)) {
599
      /* Previous command is now fully read and ready to
600
         reply */
601
16
      smtp_server_command_ready_to_reply(pending_command);
602
16
    }
603
29.4k
  }
604
28.0k
}
605
606
static void smtp_server_connection_input(struct connection *_conn)
607
28.0k
{
608
28.0k
  struct smtp_server_connection *conn =
609
28.0k
    (struct smtp_server_connection *)_conn;
610
28.0k
  int ret;
611
612
28.0k
  i_assert(!conn->input_broken);
613
614
28.0k
  if (conn->handling_input)
615
0
    return;
616
617
28.0k
  smtp_server_connection_timeout_reset(conn);
618
619
28.0k
  if (conn->ssl_start && conn->ssl_iostream == NULL) {
620
0
    if (smtp_server_connection_ssl_init(conn) < 0) {
621
0
      smtp_server_connection_close(&conn,
622
0
        "SSL Initialization failed");
623
0
      return;
624
0
    }
625
0
  }
626
28.0k
  i_assert(!conn->halted);
627
628
  /* If connection is established over secure line, wait for TLS
629
     handshake to finish. */
630
28.0k
  if (conn->ssl_iostream != NULL &&
631
28.0k
      !ssl_iostream_is_handshaked(conn->ssl_iostream)) {
632
    /* Finish SSL negotiating by reading from input stream. */
633
0
    while ((ret = i_stream_read(conn->conn.input)) > 0 ||
634
0
           ret == -2) {
635
0
      if (ssl_iostream_is_handshaked(conn->ssl_iostream))
636
0
        break;
637
0
    }
638
0
    if (ret == -1) {
639
0
      int stream_errno = conn->conn.input->stream_errno;
640
641
      /* Failed somehow. */
642
0
      i_assert(ret != -2);
643
0
      const char *error = t_strdup_printf(
644
0
        "SSL handshaking with %s failed: "
645
0
        "read(%s) failed: %s",
646
0
        _conn->name,
647
0
        i_stream_get_name(conn->conn.input),
648
0
        (stream_errno != 0 ?
649
0
         i_stream_get_error(conn->conn.input) : "EOF"));
650
0
      e_error(conn->event, "%s", error);
651
0
      smtp_server_connection_close(&conn, error);
652
0
      return;
653
0
    }
654
0
    if (!ssl_iostream_is_handshaked(conn->ssl_iostream)) {
655
      /* Not finished. */
656
0
      i_assert(ret == 0);
657
0
      return;
658
0
    }
659
0
    if (conn->halted) {
660
0
      smtp_server_connection_input_lock(conn);
661
0
      return;
662
0
    }
663
0
  }
664
665
28.0k
  if (!conn->connect_succeeded &&
666
28.0k
      (conn->ssl_iostream == NULL ||
667
0
       ssl_iostream_is_handshaked(conn->ssl_iostream)))
668
0
    smtp_server_connection_ready(conn);
669
670
28.0k
  if (!smtp_server_connection_check_pipeline(conn)) {
671
16
    smtp_server_connection_input_halt(conn);
672
16
    return;
673
16
  }
674
675
28.0k
  smtp_server_connection_ref(conn);
676
28.0k
  conn->handling_input = TRUE;
677
28.0k
  if (conn->callbacks != NULL &&
678
28.0k
      conn->callbacks->conn_cmd_input_pre != NULL)
679
0
    conn->callbacks->conn_cmd_input_pre(conn->context);
680
28.0k
  smtp_server_connection_handle_input(conn);
681
28.0k
  if (conn->callbacks != NULL &&
682
28.0k
      conn->callbacks->conn_cmd_input_post != NULL)
683
0
    conn->callbacks->conn_cmd_input_post(conn->context);
684
28.0k
  conn->handling_input = FALSE;
685
686
  /* Handle output errors from immediate replies sent to client
687
     (normal replies are exclusively sent in output handler). */
688
28.0k
  if (conn->conn.output != NULL && conn->conn.output->closed)
689
0
                smtp_server_connection_handle_output_error(conn);
690
28.0k
  smtp_server_connection_unref(&conn);
691
28.0k
}
692
693
bool smtp_server_connection_pending_command_data(
694
  struct smtp_server_connection *conn)
695
123k
{
696
123k
  if (conn->smtp_parser == NULL)
697
0
    return FALSE;
698
123k
  return smtp_command_parser_pending_data(conn->smtp_parser);
699
123k
}
700
701
/*
702
 * Command reply handling
703
 */
704
705
void smtp_server_connection_handle_output_error(
706
  struct smtp_server_connection *conn)
707
0
{
708
0
  smtp_server_connection_close(&conn,
709
0
    o_stream_get_disconnect_reason(conn->conn.output));
710
0
}
711
712
static bool
713
smtp_server_connection_next_reply(struct smtp_server_connection *conn)
714
149k
{
715
149k
  struct smtp_server_command *cmd;
716
717
149k
  cmd = conn->command_queue_head;
718
149k
  if (cmd == NULL) {
719
    /* No commands pending */
720
28.5k
    e_debug(conn->event, "No more commands pending");
721
28.5k
    return FALSE;
722
28.5k
  }
723
724
121k
  return smtp_server_command_send_replies(cmd);
725
149k
}
726
727
void smtp_server_connection_cork(struct smtp_server_connection *conn)
728
0
{
729
0
  conn->corked = TRUE;
730
0
  if (conn->conn.output != NULL)
731
0
    o_stream_cork(conn->conn.output);
732
0
}
733
734
void smtp_server_connection_uncork(struct smtp_server_connection *conn)
735
0
{
736
0
  conn->corked = FALSE;
737
0
  if (conn->conn.output != NULL) {
738
0
    if (o_stream_uncork_flush(conn->conn.output) < 0) {
739
0
      smtp_server_connection_handle_output_error(conn);
740
0
      return;
741
0
    }
742
0
    smtp_server_connection_trigger_output(conn);
743
0
  }
744
0
}
745
746
static void
747
smtp_server_connection_send_replies(struct smtp_server_connection *conn)
748
29.7k
{
749
  /* Send more replies until no more replies remain, the output
750
     blocks again, or the connection is closed */
751
149k
  while (!conn->disconnected && smtp_server_connection_next_reply(conn));
752
753
29.7k
  smtp_server_connection_timeout_update(conn);
754
755
  /* Accept more commands if possible */
756
29.7k
  smtp_server_connection_input_resume(conn);
757
29.7k
}
758
759
int smtp_server_connection_flush(struct smtp_server_connection *conn)
760
29.7k
{
761
29.7k
  struct ostream *output = conn->conn.output;
762
29.7k
  int ret;
763
764
29.7k
  if ((ret = o_stream_flush(output)) <= 0) {
765
0
    if (ret < 0)
766
0
      smtp_server_connection_handle_output_error(conn);
767
0
    return ret;
768
0
  }
769
29.7k
  return 1;
770
29.7k
}
771
772
static int smtp_server_connection_output(struct smtp_server_connection *conn)
773
29.7k
{
774
29.7k
  int ret;
775
776
29.7k
  e_debug(conn->event, "Sending replies");
777
778
29.7k
  smtp_server_connection_ref(conn);
779
29.7k
  o_stream_cork(conn->conn.output);
780
29.7k
  ret = smtp_server_connection_flush(conn);
781
29.7k
  if (ret > 0) {
782
29.7k
    smtp_server_connection_timeout_reset(conn);
783
29.7k
    smtp_server_connection_send_replies(conn);
784
29.7k
  }
785
29.7k
  if (ret >= 0 && !conn->corked && conn->conn.output != NULL)
786
29.2k
    ret = o_stream_uncork_flush(conn->conn.output);
787
29.7k
  if (conn->conn.output != NULL && conn->conn.output->closed) {
788
0
    smtp_server_connection_handle_output_error(conn);
789
0
    ret = -1;
790
0
  }
791
29.7k
  smtp_server_connection_unref(&conn);
792
29.7k
  return ret;
793
29.7k
}
794
795
void smtp_server_connection_trigger_output(struct smtp_server_connection *conn)
796
243k
{
797
243k
  if (conn->conn.output != NULL) {
798
243k
    e_debug(conn->event, "Trigger output");
799
243k
    o_stream_set_flush_pending(conn->conn.output, TRUE);
800
243k
  }
801
243k
}
802
803
/*
804
 *
805
 */
806
807
static struct connection_settings smtp_server_connection_set = {
808
  .input_max_size = SIZE_MAX,
809
  .output_max_size = SIZE_MAX,
810
  .client = FALSE,
811
  .log_connection_id = TRUE,
812
};
813
814
static const struct connection_vfuncs smtp_server_connection_vfuncs = {
815
  .destroy = smtp_server_connection_destroy,
816
  .input = smtp_server_connection_input,
817
};
818
819
struct connection_list *smtp_server_connection_list_init(void)
820
6.47k
{
821
6.47k
  return connection_list_init(&smtp_server_connection_set,
822
6.47k
            &smtp_server_connection_vfuncs);
823
6.47k
}
824
825
static struct event *
826
smtp_server_connection_event_create(struct smtp_server *server,
827
            const struct smtp_server_settings *set)
828
6.47k
{
829
6.47k
  struct event *conn_event;
830
831
6.47k
  if (set != NULL && set->event_parent != NULL) {
832
0
    conn_event = event_create(set->event_parent);
833
0
    smtp_server_event_init(server, conn_event);
834
0
  } else
835
6.47k
    conn_event = event_create(server->event);
836
6.47k
  event_set_append_log_prefix(conn_event, t_strdup_printf(
837
6.47k
    "%s-server: ", smtp_protocol_name(server->set.protocol)));
838
6.47k
  event_set_forced_debug(conn_event, (set != NULL && set->debug));
839
840
6.47k
  return conn_event;
841
6.47k
}
842
843
static void
844
smtp_server_connection_update_event(struct smtp_server_connection *conn)
845
6.47k
{
846
6.47k
  event_add_str(conn->event, "connection_id", conn->session_id);
847
6.47k
  event_add_str(conn->event, "session", conn->session_id);
848
6.47k
}
849
850
static void
851
smtp_server_connection_init_session(struct smtp_server_connection *conn)
852
6.47k
{
853
6.47k
  guid_128_t guid;
854
6.47k
  string_t *session_id;
855
856
6.47k
  session_id = t_str_new(30);
857
6.47k
  guid_128_generate(guid);
858
6.47k
  base64_encode(guid, sizeof(guid), session_id);
859
860
  /* drop trailing "==" */
861
6.47k
  i_assert(str_c(session_id)[str_len(session_id)-2] == '=');
862
6.47k
  str_truncate(session_id, str_len(session_id)-2);
863
864
6.47k
  conn->session_id = i_strdup(str_c(session_id));
865
6.47k
}
866
867
static struct smtp_server_connection * ATTR_NULL(5, 6)
868
smtp_server_connection_alloc(struct smtp_server *server,
869
           const struct smtp_server_settings *set,
870
           int fd_in, int fd_out,
871
           const struct smtp_server_callbacks *callbacks,
872
           void *context)
873
6.47k
{
874
6.47k
  struct smtp_server_connection *conn;
875
6.47k
  pool_t pool;
876
877
6.47k
  pool = pool_alloconly_create("smtp server", 2048);
878
6.47k
  conn = p_new(pool, struct smtp_server_connection, 1);
879
6.47k
  conn->pool = pool;
880
6.47k
  conn->refcount = 1;
881
6.47k
  conn->server = server;
882
6.47k
  conn->callbacks = callbacks;
883
6.47k
  conn->context = context;
884
885
  /* Merge settings with global server settings */
886
6.47k
  conn->set = server->set;
887
6.47k
  if (set != NULL) {
888
0
    conn->set.protocol = server->set.protocol;
889
0
    if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
890
0
      conn->set.rawlog_dir = p_strdup(pool, set->rawlog_dir);
891
892
0
    if (set->ssl != NULL) {
893
0
      conn->set.ssl = set->ssl;
894
0
      pool_ref(conn->set.ssl->pool);
895
0
    }
896
897
0
    if (set->hostname != NULL && *set->hostname != '\0')
898
0
      conn->set.hostname = p_strdup(pool, set->hostname);
899
0
    if (set->login_greeting != NULL &&
900
0
      *set->login_greeting != '\0') {
901
0
      conn->set.login_greeting =
902
0
        p_strdup(pool, set->login_greeting);
903
0
    }
904
0
    if (set->capabilities != 0)
905
0
      conn->set.capabilities = set->capabilities;
906
0
    conn->set.workarounds |= set->workarounds;
907
908
0
    if (set->max_client_idle_time_msecs > 0) {
909
0
      conn->set.max_client_idle_time_msecs =
910
0
        set->max_client_idle_time_msecs;
911
0
    }
912
0
    if (set->max_pipelined_commands > 0) {
913
0
      conn->set.max_pipelined_commands =
914
0
        set->max_pipelined_commands;
915
0
    }
916
0
    if (set->max_bad_commands > 0) {
917
0
      conn->set.max_bad_commands = set->max_bad_commands;
918
0
    }
919
0
    if (set->max_recipients > 0)
920
0
      conn->set.max_recipients = set->max_recipients;
921
0
    smtp_command_limits_merge(&conn->set.command_limits,
922
0
            &set->command_limits);
923
924
0
    conn->set.max_message_size = set->max_message_size;
925
0
    if (set->max_message_size == 0 ||
926
0
        set->max_message_size == UOFF_T_MAX) {
927
0
      conn->set.command_limits.max_data_size = UOFF_T_MAX;
928
0
    } else if (conn->set.command_limits.max_data_size != 0) {
929
      /* Explicit limit given */
930
0
    } else if (set->max_message_size >
931
0
      (UOFF_T_MAX - SMTP_SERVER_DEFAULT_MAX_SIZE_EXCESS_LIMIT)) {
932
      /* Very high limit */
933
0
      conn->set.command_limits.max_data_size = UOFF_T_MAX;
934
0
    } else {
935
      /* Absolute maximum before connection is closed in DATA
936
         command */
937
0
      conn->set.command_limits.max_data_size =
938
0
        set->max_message_size +
939
0
          SMTP_SERVER_DEFAULT_MAX_SIZE_EXCESS_LIMIT;
940
0
    }
941
942
0
    if (set->mail_param_extensions != NULL) {
943
0
      conn->set.mail_param_extensions =
944
0
        p_strarray_dup(pool, set->mail_param_extensions);
945
0
    }
946
0
    if (set->rcpt_param_extensions != NULL) {
947
0
      conn->set.rcpt_param_extensions =
948
0
        p_strarray_dup(pool, set->rcpt_param_extensions);
949
0
    }
950
0
    if (set->xclient_extensions != NULL) {
951
0
      conn->set.xclient_extensions =
952
0
        p_strarray_dup(pool, set->xclient_extensions);
953
0
    }
954
955
0
    if (set->socket_send_buffer_size > 0) {
956
0
      conn->set.socket_send_buffer_size =
957
0
        set->socket_send_buffer_size;
958
0
    }
959
0
    if (set->socket_recv_buffer_size > 0) {
960
0
      conn->set.socket_recv_buffer_size =
961
0
        set->socket_recv_buffer_size;
962
0
    }
963
964
0
    conn->set.tls_required =
965
0
      conn->set.tls_required || set->tls_required;
966
0
    conn->set.auth_optional =
967
0
      conn->set.auth_optional || set->auth_optional;
968
0
    conn->set.mail_path_allow_broken =
969
0
      conn->set.mail_path_allow_broken ||
970
0
        set->mail_path_allow_broken;
971
0
    conn->set.rcpt_domain_optional =
972
0
      conn->set.rcpt_domain_optional ||
973
0
        set->rcpt_domain_optional;
974
0
    conn->set.no_greeting =
975
0
      conn->set.no_greeting || set->no_greeting;
976
0
    conn->set.debug = conn->set.debug || set->debug;
977
0
  }
978
979
6.47k
  if (set != NULL && set->mail_param_extensions != NULL) {
980
0
    const char *const *extp;
981
982
0
    p_array_init(&conn->mail_param_extensions, pool,
983
0
           str_array_length(set->mail_param_extensions) + 8);
984
0
    for (extp = set->mail_param_extensions; *extp != NULL; extp++) {
985
0
      const char *ext = p_strdup(pool, *extp);
986
0
      array_push_back(&conn->mail_param_extensions, &ext);
987
0
    }
988
0
    array_append_zero(&conn->mail_param_extensions);
989
0
  }
990
6.47k
  if (set != NULL && set->rcpt_param_extensions != NULL) {
991
0
    const char *const *extp;
992
993
0
    p_array_init(&conn->rcpt_param_extensions, pool,
994
0
           str_array_length(set->rcpt_param_extensions) + 8);
995
0
    for (extp = set->rcpt_param_extensions; *extp != NULL; extp++) {
996
0
      const char *ext = p_strdup(pool, *extp);
997
0
      array_push_back(&conn->rcpt_param_extensions, &ext);
998
0
    }
999
0
    array_append_zero(&conn->rcpt_param_extensions);
1000
0
  }
1001
1002
6.47k
  net_set_nonblock(fd_in, TRUE);
1003
6.47k
  if (fd_in != fd_out)
1004
0
    net_set_nonblock(fd_out, TRUE);
1005
6.47k
  (void)net_set_tcp_nodelay(fd_out, TRUE);
1006
1007
6.47k
  set = &conn->set;
1008
6.47k
  if (set->socket_send_buffer_size > 0 &&
1009
6.47k
      net_set_send_buffer_size(fd_out,
1010
0
                   set->socket_send_buffer_size) < 0) {
1011
0
    e_error(conn->event,
1012
0
      "net_set_send_buffer_size(%zu) failed: %m",
1013
0
      set->socket_send_buffer_size);
1014
0
  }
1015
6.47k
  if (set->socket_recv_buffer_size > 0 &&
1016
6.47k
      net_set_recv_buffer_size(fd_in,
1017
0
             set->socket_recv_buffer_size) < 0) {
1018
0
    e_error(conn->event,
1019
0
      "net_set_recv_buffer_size(%zu) failed: %m",
1020
0
      set->socket_recv_buffer_size);
1021
0
  }
1022
1023
6.47k
  smtp_server_connection_init_session(conn);
1024
1025
6.47k
  return conn;
1026
6.47k
}
1027
1028
static void smtp_server_connection_created(struct smtp_server_connection *conn)
1029
6.47k
{
1030
6.47k
  conn->raw_input = conn->conn.input;
1031
6.47k
  conn->raw_output = conn->conn.output;
1032
1033
  /* Halt input until started */
1034
6.47k
  smtp_server_connection_halt(conn);
1035
1036
6.47k
  e_debug(conn->event, "Connection created");
1037
6.47k
}
1038
1039
struct smtp_server_connection *
1040
smtp_server_connection_create(
1041
  struct smtp_server *server, int fd_in, int fd_out,
1042
  const struct ip_addr *remote_ip, in_port_t remote_port,
1043
  bool ssl_start, const struct smtp_server_settings *set,
1044
  const struct smtp_server_callbacks *callbacks, void *context)
1045
6.47k
{
1046
6.47k
  struct smtp_server_connection *conn;
1047
6.47k
  struct event *conn_event;
1048
1049
6.47k
  conn = smtp_server_connection_alloc(server, set, fd_in, fd_out,
1050
6.47k
              callbacks, context);
1051
6.47k
  conn_event = smtp_server_connection_event_create(server, set);
1052
6.47k
  conn->conn.event_parent = conn_event;
1053
6.47k
  connection_init_server_ip(server->conn_list, &conn->conn, NULL,
1054
6.47k
          fd_in, fd_out, remote_ip, remote_port);
1055
6.47k
  conn->event = conn->conn.event;
1056
6.47k
  smtp_server_connection_update_event(conn);
1057
6.47k
  event_unref(&conn_event);
1058
1059
6.47k
  conn->ssl_start = ssl_start;
1060
6.47k
  if (ssl_start)
1061
0
    conn->set.capabilities &= ENUM_NEGATE(SMTP_CAPABILITY_STARTTLS);
1062
1063
6.47k
  smtp_server_connection_created(conn);
1064
1065
6.47k
  return conn;
1066
6.47k
}
1067
1068
struct smtp_server_connection *
1069
smtp_server_connection_create_from_streams(
1070
  struct smtp_server *server,
1071
  struct istream *input, struct ostream *output,
1072
  const struct ip_addr *remote_ip, in_port_t remote_port,
1073
  const struct smtp_server_settings *set,
1074
  const struct smtp_server_callbacks *callbacks, void *context)
1075
0
{
1076
0
  struct smtp_server_connection *conn;
1077
0
  struct event *conn_event;
1078
0
  int fd_in, fd_out;
1079
1080
0
  fd_in = i_stream_get_fd(input);
1081
0
  fd_out = o_stream_get_fd(output);
1082
0
  i_assert(fd_in >= 0);
1083
0
  i_assert(fd_out >= 0);
1084
1085
0
  conn = smtp_server_connection_alloc(server, set, fd_in, fd_out,
1086
0
              callbacks, context);
1087
0
  if (remote_ip != NULL && remote_ip->family != 0)
1088
0
    conn->conn.remote_ip = *remote_ip;
1089
0
  if (remote_port != 0)
1090
0
    conn->conn.remote_port = remote_port;
1091
0
  conn_event = smtp_server_connection_event_create(server, set);
1092
0
  conn->conn.event_parent = conn_event;
1093
0
  connection_init_from_streams(server->conn_list, &conn->conn, NULL,
1094
0
             input, output);
1095
0
  conn->created_from_streams = TRUE;
1096
0
  conn->event = conn->conn.event;
1097
0
  smtp_server_connection_update_event(conn);
1098
0
  event_unref(&conn_event);
1099
1100
0
  smtp_server_connection_created(conn);
1101
1102
0
  return conn;
1103
0
}
1104
1105
void smtp_server_connection_ref(struct smtp_server_connection *conn)
1106
302k
{
1107
302k
  conn->refcount++;
1108
302k
}
1109
1110
static const char *
1111
smtp_server_connection_get_disconnect_reason(
1112
  struct smtp_server_connection *conn)
1113
3.97k
{
1114
3.97k
  const char *err;
1115
1116
3.97k
  if (conn->ssl_iostream != NULL &&
1117
3.97k
      !ssl_iostream_is_handshaked(conn->ssl_iostream)) {
1118
0
    err = ssl_iostream_get_last_error(conn->ssl_iostream);
1119
0
    if (err != NULL) {
1120
0
      return t_strdup_printf(
1121
0
        "TLS handshaking failed: %s", err);
1122
0
    }
1123
0
  }
1124
1125
3.97k
  return io_stream_get_disconnect_reason(conn->conn.input,
1126
3.97k
                 conn->conn.output);
1127
3.97k
}
1128
1129
static void
1130
smtp_server_connection_disconnect(struct smtp_server_connection *conn,
1131
          const char *reason)
1132
12.9k
{
1133
12.9k
  struct smtp_server_command *cmd, *cmd_next;
1134
1135
12.9k
  if (conn->disconnected)
1136
6.47k
    return;
1137
6.47k
  conn->disconnected = TRUE;
1138
1139
6.47k
  if (reason == NULL)
1140
3.97k
    reason = smtp_server_connection_get_disconnect_reason(conn);
1141
2.49k
  else
1142
2.49k
    reason = t_str_oneline(reason);
1143
1144
6.47k
  cmd = conn->command_queue_head;
1145
6.47k
  if (cmd != NULL && cmd->reg != NULL) {
1146
    /* Unfinished command - include it in the reason string */
1147
1.06k
    reason = t_strdup_printf("%s (unfinished %s command)",
1148
1.06k
      reason, cmd->reg->name);
1149
1.06k
  }
1150
6.47k
  if (!conn->set.no_state_in_reason) {
1151
6.47k
    reason = t_strdup_printf("%s (state=%s)", reason,
1152
6.47k
      smtp_server_state_names[conn->state.state]);
1153
6.47k
  }
1154
1155
6.47k
  e_debug(conn->event, "Disconnected: %s", reason);
1156
1157
  /* Preserve statistics */
1158
6.47k
  smtp_server_connection_update_stats(conn);
1159
1160
  /* Drop transaction */
1161
6.47k
  smtp_server_connection_reset_state(conn);
1162
1163
  /* Clear command queue */
1164
6.47k
  cmd = conn->command_queue_head;
1165
10.2k
  while (cmd != NULL) {
1166
3.78k
    cmd_next = cmd->next;
1167
3.78k
    smtp_server_command_abort(&cmd);
1168
3.78k
    cmd = cmd_next;
1169
3.78k
  }
1170
1171
6.47k
  smtp_server_connection_timeout_stop(conn);
1172
6.47k
  if (conn->conn.output != NULL)
1173
6.47k
    o_stream_uncork(conn->conn.output);
1174
6.47k
  if (conn->smtp_parser != NULL)
1175
6.47k
    smtp_command_parser_deinit(&conn->smtp_parser);
1176
6.47k
  ssl_iostream_destroy(&conn->ssl_iostream);
1177
6.47k
  settings_free(conn->set.ssl);
1178
1179
6.47k
  if (conn->callbacks != NULL &&
1180
6.47k
      conn->callbacks->conn_disconnect != NULL) {
1181
    /* The callback may close the fd, so remove IO before that */
1182
0
    io_remove(&conn->conn.io);
1183
0
    conn->callbacks->conn_disconnect(conn->context, reason);
1184
0
  }
1185
1186
6.47k
  if (!conn->created_from_streams)
1187
6.47k
    connection_disconnect(&conn->conn);
1188
0
  else {
1189
0
    conn->conn.fd_in = conn->conn.fd_out = -1;
1190
0
    io_remove(&conn->conn.io);
1191
0
    i_stream_unref(&conn->conn.input);
1192
0
    o_stream_unref(&conn->conn.output);
1193
0
  }
1194
6.47k
}
1195
1196
bool smtp_server_connection_unref(struct smtp_server_connection **_conn)
1197
309k
{
1198
309k
  struct smtp_server_connection *conn = *_conn;
1199
1200
309k
  *_conn = NULL;
1201
1202
309k
  i_assert(conn->refcount > 0);
1203
309k
  if (--conn->refcount > 0)
1204
302k
    return TRUE;
1205
1206
6.47k
  smtp_server_connection_disconnect(conn, NULL);
1207
1208
6.47k
  e_debug(conn->event, "Connection destroy");
1209
1210
6.47k
  connection_deinit(&conn->conn);
1211
1212
6.47k
  if (conn->callbacks != NULL && conn->callbacks->conn_free != NULL)
1213
6.47k
    conn->callbacks->conn_free(conn->context);
1214
1215
6.47k
  i_free(conn->proxy_helo);
1216
6.47k
  i_free(conn->helo_domain);
1217
6.47k
  i_free(conn->username);
1218
6.47k
  i_free(conn->session_id);
1219
6.47k
  i_free(conn->client_transport);
1220
6.47k
  i_free(conn->local_name);
1221
6.47k
  event_unref(&conn->next_trans_event);
1222
6.47k
  pool_unref(&conn->pool);
1223
6.47k
  return FALSE;
1224
309k
}
1225
1226
void smtp_server_connection_send_line(struct smtp_server_connection *conn,
1227
              const char *fmt, ...)
1228
6.47k
{
1229
6.47k
  va_list args;
1230
1231
6.47k
  va_start(args, fmt);
1232
1233
6.47k
  T_BEGIN {
1234
6.47k
    string_t *str;
1235
1236
6.47k
    str = t_str_new(256);
1237
6.47k
    str_vprintfa(str, fmt, args);
1238
1239
6.47k
    e_debug(conn->event, "Sent: %s", str_c(str));
1240
1241
6.47k
    str_append(str, "\r\n");
1242
6.47k
    o_stream_nsend(conn->conn.output, str_data(str), str_len(str));
1243
6.47k
  } T_END;
1244
6.47k
  va_end(args);
1245
6.47k
}
1246
1247
void smtp_server_connection_reply_lines(struct smtp_server_connection *conn,
1248
                unsigned int status,
1249
          const char *enh_code,
1250
          const char *const *text_lines)
1251
250
{
1252
250
  struct smtp_reply reply;
1253
1254
250
  i_zero(&reply);
1255
250
  reply.status = status;
1256
250
  reply.text_lines = text_lines;
1257
1258
250
  if (!smtp_reply_parse_enhanced_code(
1259
250
    enh_code, &reply.enhanced_code, NULL))
1260
0
    reply.enhanced_code = SMTP_REPLY_ENH_CODE(status / 100, 0, 0);
1261
1262
250
  T_BEGIN {
1263
250
    string_t *str;
1264
1265
250
    e_debug(conn->event, "Sent: %s", smtp_reply_log(&reply));
1266
1267
250
    str = t_str_new(256);
1268
250
    smtp_reply_write(str, &reply);
1269
250
    o_stream_nsend(conn->conn.output, str_data(str), str_len(str));
1270
250
  } T_END;
1271
250
}
1272
1273
void smtp_server_connection_reply_immediate(
1274
  struct smtp_server_connection *conn,
1275
  unsigned int status, const char *fmt, ...)
1276
1.94k
{
1277
1.94k
  va_list args;
1278
1279
1.94k
  va_start(args, fmt);
1280
1.94k
  T_BEGIN {
1281
1.94k
    string_t *str;
1282
1283
1.94k
    str = t_str_new(256);
1284
1.94k
    str_printfa(str, "%03u ", status);
1285
1.94k
    str_vprintfa(str, fmt, args);
1286
1287
1.94k
    e_debug(conn->event, "Sent: %s", str_c(str));
1288
1289
1.94k
    str_append(str, "\r\n");
1290
1.94k
    o_stream_nsend(conn->conn.output, str_data(str), str_len(str));
1291
1.94k
  } T_END;
1292
1.94k
  va_end(args);
1293
1294
  /* Send immediately */
1295
1.94k
  if (o_stream_is_corked(conn->conn.output)) {
1296
1.87k
    o_stream_uncork(conn->conn.output);
1297
1.87k
    o_stream_cork(conn->conn.output);
1298
1.87k
  }
1299
1.94k
}
1300
1301
void smtp_server_connection_login(struct smtp_server_connection *conn,
1302
          const char *username, const char *helo,
1303
          const unsigned char *pdata,
1304
          unsigned int pdata_len, bool ssl_secured)
1305
0
{
1306
0
  i_assert(!conn->started);
1307
1308
0
  conn->set.capabilities &= ENUM_NEGATE(SMTP_CAPABILITY_STARTTLS);
1309
0
  i_free(conn->username);
1310
0
  conn->username = i_strdup(username);
1311
0
  if (helo != NULL && *helo != '\0') {
1312
0
    i_free(conn->helo_domain);
1313
0
    conn->helo_domain = i_strdup(helo);
1314
0
    conn->helo.domain = conn->helo_domain;
1315
0
    conn->helo.domain_valid = TRUE;
1316
0
  }
1317
0
  conn->authenticated = TRUE;
1318
0
  conn->ssl_secured = ssl_secured;
1319
1320
0
  if (pdata_len > 0) {
1321
0
    if (!i_stream_add_data(conn->conn.input, pdata, pdata_len))
1322
0
      i_panic("Couldn't add client input to stream");
1323
0
  }
1324
0
}
1325
1326
void smtp_server_connection_start_pending(struct smtp_server_connection *conn)
1327
6.47k
{
1328
6.47k
  i_assert(!conn->started);
1329
6.47k
  conn->started = TRUE;
1330
1331
6.47k
  e_debug(conn->event, "Connection started");
1332
1333
6.47k
  if (!conn->ssl_start)
1334
6.47k
    smtp_server_connection_ready(conn);
1335
0
  else if (conn->ssl_iostream == NULL)
1336
0
    smtp_server_connection_input_unlock(conn);
1337
6.47k
}
1338
1339
void smtp_server_connection_start(struct smtp_server_connection *conn)
1340
6.47k
{
1341
6.47k
  smtp_server_connection_start_pending(conn);
1342
6.47k
  smtp_server_connection_resume(conn);
1343
6.47k
}
1344
1345
void smtp_server_connection_abort(struct smtp_server_connection **_conn,
1346
          unsigned int status, const char *enh_code,
1347
          const char *reason)
1348
0
{
1349
0
  struct smtp_server_connection *conn = *_conn;
1350
0
  const char **reason_lines;
1351
1352
0
  if (conn == NULL)
1353
0
    return;
1354
0
  *_conn = NULL;
1355
1356
0
  i_assert(!conn->started);
1357
0
  conn->started = TRUE;
1358
1359
0
  if (conn->authenticated) {
1360
0
    reason_lines = t_strsplit_spaces(reason, "\r\n");
1361
0
    smtp_server_connection_reply_lines(
1362
0
      conn, status, enh_code, reason_lines);
1363
0
    smtp_server_connection_terminate(
1364
0
      &conn, "4.3.2", "Shutting down due to fatal error");
1365
0
  } else {
1366
0
    smtp_server_connection_terminate(&conn, enh_code, reason);
1367
0
  }
1368
0
}
1369
1370
void smtp_server_connection_halt(struct smtp_server_connection *conn)
1371
6.47k
{
1372
6.47k
  conn->halted = TRUE;
1373
6.47k
  smtp_server_connection_timeout_stop(conn);
1374
6.47k
  if (conn->ssl_start &&
1375
6.47k
      (conn->ssl_iostream == NULL ||
1376
0
       !ssl_iostream_is_handshaked(conn->ssl_iostream)))
1377
0
    return;
1378
1379
6.47k
  smtp_server_connection_input_lock(conn);
1380
6.47k
}
1381
1382
void smtp_server_connection_resume(struct smtp_server_connection *conn)
1383
6.47k
{
1384
6.47k
  smtp_server_connection_input_unlock(conn);
1385
6.47k
  smtp_server_connection_timeout_update(conn);
1386
6.47k
  conn->halted = FALSE;
1387
6.47k
}
1388
1389
void smtp_server_connection_close(struct smtp_server_connection **_conn,
1390
          const char *reason)
1391
2.49k
{
1392
2.49k
  struct smtp_server_connection *conn = *_conn;
1393
1394
2.49k
  *_conn = NULL;
1395
1396
2.49k
  if (conn->closed)
1397
0
    return;
1398
2.49k
  conn->closed = TRUE;
1399
1400
2.49k
  smtp_server_connection_disconnect(conn, reason);
1401
2.49k
  smtp_server_connection_unref(&conn);
1402
2.49k
}
1403
1404
void smtp_server_connection_terminate(struct smtp_server_connection **_conn,
1405
              const char *enh_code, const char *reason)
1406
250
{
1407
250
  smtp_server_connection_terminate_full(_conn, enh_code, reason, reason);
1408
250
}
1409
1410
void smtp_server_connection_terminate_full(
1411
  struct smtp_server_connection **_conn, const char *enh_code,
1412
  const char *reply_reason, const char *log_reason)
1413
250
{
1414
250
  struct smtp_server_connection *conn = *_conn;
1415
250
  const char **reason_lines;
1416
1417
250
  *_conn = NULL;
1418
1419
250
  if (conn->closed)
1420
0
    return;
1421
1422
250
  i_assert(enh_code[0] == '4' && enh_code[1] == '.');
1423
1424
250
  T_BEGIN {
1425
    /* Add hostname prefix */
1426
250
    reason_lines = t_strsplit_spaces(reply_reason, "\r\n");
1427
250
    reason_lines[0] = t_strconcat(conn->set.hostname, " ",
1428
250
                reason_lines[0], NULL);
1429
1430
250
    smtp_server_connection_reply_lines(conn, 421, enh_code,
1431
250
               reason_lines);
1432
1433
250
    smtp_server_connection_close(&conn, log_reason);
1434
250
  } T_END;
1435
250
}
1436
1437
struct smtp_server_helo_data *
1438
smtp_server_connection_get_helo_data(struct smtp_server_connection *conn)
1439
0
{
1440
0
  return &conn->helo;
1441
0
}
1442
1443
enum smtp_server_state
1444
smtp_server_connection_get_state(struct smtp_server_connection *conn,
1445
         const char **args_r)
1446
0
{
1447
0
  if (args_r != NULL)
1448
0
    *args_r = conn->state.args;
1449
0
  return conn->state.state;
1450
0
}
1451
1452
void smtp_server_connection_set_state(struct smtp_server_connection *conn,
1453
              enum smtp_server_state state,
1454
              const char *args)
1455
61.6k
{
1456
61.6k
  bool changed = FALSE;
1457
1458
61.6k
  if (conn->state.state != state) {
1459
34.9k
    conn->state.state = state;
1460
34.9k
    changed = TRUE;
1461
34.9k
  }
1462
61.6k
  if (null_strcmp(args, conn->state.args) != 0) {
1463
15.1k
    i_free(conn->state.args);
1464
15.1k
    conn->state.args = i_strdup(args);
1465
15.1k
    changed = TRUE;
1466
15.1k
  }
1467
1468
61.6k
  if (changed && conn->callbacks != NULL &&
1469
61.6k
      conn->callbacks->conn_state_changed != NULL)
1470
0
    conn->callbacks->conn_state_changed(conn->context, state, args);
1471
61.6k
}
1472
1473
const char *
1474
smtp_server_connection_get_security_string(struct smtp_server_connection *conn)
1475
0
{
1476
0
  if (conn->ssl_iostream == NULL)
1477
0
    return NULL;
1478
0
  return ssl_iostream_get_security_string(conn->ssl_iostream);
1479
0
}
1480
1481
void smtp_server_connection_reset_state(struct smtp_server_connection *conn)
1482
21.8k
{
1483
21.8k
  e_debug(conn->event, "Connection state reset");
1484
1485
21.8k
  i_free(conn->state.args);
1486
1487
21.8k
  if (conn->state.trans != NULL)
1488
5.08k
    smtp_server_transaction_free(&conn->state.trans);
1489
1490
  /* RFC 3030, Section 2:
1491
     The RSET command, when issued after the first BDAT and before the
1492
     BDAT LAST, clears all segments sent during that transaction and
1493
     resets the session.
1494
   */
1495
21.8k
  i_stream_destroy(&conn->state.data_input);
1496
21.8k
  i_stream_destroy(&conn->state.data_chain_input);
1497
21.8k
  conn->state.data_chain = NULL;
1498
1499
  /* Reset state */
1500
21.8k
  i_zero(&conn->state);
1501
21.8k
  smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_READY, NULL);
1502
21.8k
}
1503
1504
void smtp_server_connection_clear(struct smtp_server_connection *conn)
1505
0
{
1506
0
  e_debug(conn->event, "Connection clear");
1507
1508
0
  i_free(conn->helo_domain);
1509
0
  i_zero(&conn->helo);
1510
0
  smtp_server_connection_reset_state(conn);
1511
0
}
1512
1513
void smtp_server_connection_set_capabilities(
1514
  struct smtp_server_connection *conn, enum smtp_capability capabilities)
1515
0
{
1516
0
  conn->set.capabilities = capabilities;
1517
0
}
1518
1519
void smtp_server_connection_set_greeting(struct smtp_server_connection *conn,
1520
           const char *greeting)
1521
0
{
1522
0
  conn->set.login_greeting = p_strdup(conn->pool, greeting);
1523
0
}
1524
1525
void smtp_server_connection_add_extra_capability(
1526
  struct smtp_server_connection *conn,
1527
  const struct smtp_capability_extra *cap)
1528
0
{
1529
0
  const struct smtp_capability_extra *cap_idx;
1530
0
  struct smtp_capability_extra cap_new;
1531
0
  unsigned int insert_idx;
1532
0
  pool_t pool = conn->pool;
1533
1534
  /* Avoid committing protocol errors */
1535
0
  i_assert(smtp_ehlo_keyword_is_valid(cap->name));
1536
0
  i_assert(smtp_ehlo_params_are_valid(cap->params));
1537
1538
  /* Cannot override standard capabilities */
1539
0
  i_assert(smtp_capability_find_by_name(cap->name)
1540
0
     == SMTP_CAPABILITY_NONE);
1541
1542
0
  if (!array_is_created(&conn->extra_capabilities))
1543
0
    p_array_init(&conn->extra_capabilities, pool, 4);
1544
1545
  /* Keep array sorted */
1546
0
  insert_idx = array_count(&conn->extra_capabilities);
1547
0
  array_foreach(&conn->extra_capabilities, cap_idx) {
1548
0
    int cmp = strcasecmp(cap_idx->name, cap->name);
1549
1550
    /* Prohibit duplicates */
1551
0
    i_assert(cmp != 0);
1552
1553
0
    if (cmp > 0) {
1554
0
      insert_idx = array_foreach_idx(
1555
0
        &conn->extra_capabilities, cap_idx);
1556
0
      break;
1557
0
    }
1558
0
  }
1559
1560
0
  i_zero(&cap_new);
1561
0
  cap_new.name = p_strdup(pool, cap->name);
1562
0
  if (cap->params != NULL)
1563
0
    cap_new.params = p_strarray_dup(pool, cap->params);
1564
1565
0
  array_insert(&conn->extra_capabilities, insert_idx, &cap_new, 1);
1566
0
}
1567
1568
void *smtp_server_connection_get_context(struct smtp_server_connection *conn)
1569
0
{
1570
0
  return conn->context;
1571
0
}
1572
1573
bool smtp_server_connection_is_ssl_secured(struct smtp_server_connection *conn)
1574
0
{
1575
0
  return conn->ssl_secured;
1576
0
}
1577
1578
bool smtp_server_connection_is_trusted(struct smtp_server_connection *conn)
1579
7.22k
{
1580
7.22k
  if (conn->callbacks == NULL || conn->callbacks->conn_is_trusted == NULL)
1581
7.22k
    return FALSE;
1582
0
  return conn->callbacks->conn_is_trusted(conn->context);
1583
7.22k
}
1584
1585
bool smtp_server_connection_is_started(struct smtp_server_connection *conn)
1586
0
{
1587
0
  return conn->started;
1588
0
}
1589
1590
enum smtp_protocol
1591
smtp_server_connection_get_protocol(struct smtp_server_connection *conn)
1592
0
{
1593
0
  return conn->set.protocol;
1594
0
}
1595
1596
const char *
1597
smtp_server_connection_get_protocol_name(struct smtp_server_connection *conn)
1598
0
{
1599
0
  string_t *pname = t_str_new(16);
1600
1601
0
  switch (conn->set.protocol) {
1602
0
  case SMTP_PROTOCOL_SMTP:
1603
0
    if (conn->helo.old_smtp)
1604
0
      str_append(pname, "SMTP");
1605
0
    else
1606
0
      str_append(pname, "ESMTP");
1607
0
    break;
1608
0
  case SMTP_PROTOCOL_LMTP:
1609
0
    str_append(pname, "LMTP");
1610
0
    break;
1611
0
  default:
1612
0
    i_unreached();
1613
0
  }
1614
0
  if (conn->ssl_secured)
1615
0
    str_append_c(pname, 'S');
1616
0
  if (conn->authenticated)
1617
0
    str_append_c(pname, 'A');
1618
0
  return str_c(pname);
1619
0
}
1620
1621
struct smtp_server_transaction *
1622
smtp_server_connection_get_transaction(struct smtp_server_connection *conn)
1623
0
{
1624
0
  return conn->state.trans;
1625
0
}
1626
1627
const char *
1628
smtp_server_connection_get_transaction_id(struct smtp_server_connection *conn)
1629
0
{
1630
0
  if (conn->state.trans == NULL)
1631
0
    return NULL;
1632
0
  return conn->state.trans->id;
1633
0
}
1634
1635
void smtp_server_connection_get_proxy_data(struct smtp_server_connection *conn,
1636
             struct smtp_proxy_data *proxy_data)
1637
0
{
1638
0
  i_zero(proxy_data);
1639
0
  proxy_data->source_ip = conn->conn.remote_ip;
1640
0
  proxy_data->source_port = conn->conn.remote_port;
1641
0
  if (conn->proxy_helo != NULL)
1642
0
    proxy_data->helo = conn->proxy_helo;
1643
0
  else if (conn->helo.domain_valid)
1644
0
    proxy_data->helo = conn->helo.domain;
1645
0
  proxy_data->login = conn->username;
1646
0
  proxy_data->session = conn->session_id;
1647
0
  proxy_data->client_transport = conn->client_transport;
1648
0
  proxy_data->local_name = conn->local_name;
1649
1650
0
  if (conn->proxy_proto != SMTP_PROXY_PROTOCOL_UNKNOWN)
1651
0
    proxy_data->proto = conn->proxy_proto;
1652
0
  else if (conn->set.protocol == SMTP_PROTOCOL_LMTP)
1653
0
    proxy_data->proto = SMTP_PROXY_PROTOCOL_LMTP;
1654
0
  else if (conn->helo.old_smtp)
1655
0
    proxy_data->proto = SMTP_PROXY_PROTOCOL_SMTP;
1656
0
  else
1657
0
    proxy_data->proto = SMTP_PROXY_PROTOCOL_ESMTP;
1658
1659
0
  proxy_data->ttl_plus_1 = conn->proxy_ttl_plus_1;
1660
0
  proxy_data->timeout_secs = conn->proxy_timeout_secs;
1661
0
}
1662
1663
void smtp_server_connection_set_proxy_data(
1664
  struct smtp_server_connection *conn,
1665
  const struct smtp_proxy_data *proxy_data)
1666
0
{
1667
0
  if (proxy_data->source_ip.family != 0)
1668
0
    conn->conn.remote_ip = proxy_data->source_ip;
1669
0
  if (proxy_data->source_port != 0)
1670
0
    conn->conn.remote_port = proxy_data->source_port;
1671
0
  if (proxy_data->helo != NULL) {
1672
0
    i_free(conn->helo_domain);
1673
0
    conn->helo_domain = i_strdup(proxy_data->helo);
1674
0
    conn->helo.domain = conn->helo_domain;
1675
0
    conn->helo.domain_valid = TRUE;
1676
0
    if (conn->helo.domain_valid) {
1677
0
      i_free(conn->proxy_helo);
1678
0
      conn->proxy_helo = i_strdup(proxy_data->helo);
1679
0
    }
1680
0
  }
1681
0
  if (proxy_data->login != NULL) {
1682
0
    i_free(conn->username);
1683
0
    conn->username = i_strdup(proxy_data->login);
1684
0
  }
1685
0
  if (proxy_data->proto != SMTP_PROXY_PROTOCOL_UNKNOWN)
1686
0
    conn->proxy_proto = proxy_data->proto;
1687
0
  if (proxy_data->session != NULL &&
1688
0
      strcmp(proxy_data->session, conn->session_id) != 0) {
1689
0
    e_debug(conn->event, "Updated session ID from %s to %s",
1690
0
            conn->session_id, proxy_data->session);
1691
0
    i_free(conn->session_id);
1692
0
    conn->session_id = i_strdup(proxy_data->session);
1693
0
  }
1694
0
  if (proxy_data->client_transport != NULL) {
1695
0
    i_free(conn->client_transport);
1696
0
    conn->client_transport = i_strdup(proxy_data->client_transport);
1697
0
  }
1698
0
  if (proxy_data->local_name != NULL) {
1699
0
    i_free(conn->local_name);
1700
0
    conn->local_name = i_strdup(proxy_data->local_name);
1701
0
  }
1702
0
  if (proxy_data->ttl_plus_1 > 0)
1703
0
    conn->proxy_ttl_plus_1 = proxy_data->ttl_plus_1;
1704
0
  if (conn->proxy_timeout_secs > 0)
1705
0
    conn->proxy_timeout_secs = proxy_data->timeout_secs;
1706
1707
0
  connection_update_properties(&conn->conn);
1708
0
  smtp_server_connection_update_event(conn);
1709
1710
0
  if (conn->callbacks != NULL &&
1711
0
      conn->callbacks->conn_proxy_data_updated != NULL) {
1712
0
    struct smtp_proxy_data full_data;
1713
1714
0
    smtp_server_connection_get_proxy_data(conn, &full_data);
1715
1716
0
    conn->callbacks->
1717
0
      conn_proxy_data_updated(conn->context, &full_data);
1718
0
  }
1719
0
}
1720
1721
void smtp_server_connection_register_mail_param(
1722
  struct smtp_server_connection *conn, const char *param)
1723
0
{
1724
0
  param = p_strdup(conn->pool, param);
1725
1726
0
  if (!array_is_created(&conn->mail_param_extensions)) {
1727
0
    p_array_init(&conn->mail_param_extensions, conn->pool, 8);
1728
0
    array_push_back(&conn->mail_param_extensions, &param);
1729
0
  } else {
1730
0
    unsigned int count = array_count(&conn->mail_param_extensions);
1731
1732
0
    i_assert(count > 0);
1733
0
    array_idx_set(&conn->mail_param_extensions,
1734
0
            count - 1, &param);
1735
0
  }
1736
0
  array_append_zero(&conn->mail_param_extensions);
1737
0
}
1738
1739
void smtp_server_connection_register_rcpt_param(
1740
  struct smtp_server_connection *conn, const char *param)
1741
0
{
1742
0
  param = p_strdup(conn->pool, param);
1743
1744
0
  if (!array_is_created(&conn->rcpt_param_extensions)) {
1745
0
    p_array_init(&conn->rcpt_param_extensions, conn->pool, 8);
1746
0
    array_push_back(&conn->rcpt_param_extensions, &param);
1747
0
  } else {
1748
0
    unsigned int count = array_count(&conn->rcpt_param_extensions);
1749
1750
0
    i_assert(count > 0);
1751
0
    array_idx_set(&conn->rcpt_param_extensions,
1752
0
            count - 1, &param);
1753
0
  }
1754
0
  array_append_zero(&conn->rcpt_param_extensions);
1755
0
}
1756
1757
void smtp_server_connection_switch_ioloop(struct smtp_server_connection *conn)
1758
0
{
1759
0
  if (conn->to_idle != NULL)
1760
0
    conn->to_idle = io_loop_move_timeout(&conn->to_idle);
1761
0
  connection_switch_ioloop(&conn->conn);
1762
0
}
1763
1764
struct event_reason *
1765
smtp_server_connection_reason_begin(struct smtp_server_connection *conn,
1766
            const char *name)
1767
27.5k
{
1768
27.5k
  if (conn->set.reason_code_module == NULL)
1769
27.5k
    return NULL;
1770
0
  const char *reason_code =
1771
0
    event_reason_code(conn->set.reason_code_module, name);
1772
0
  return event_reason_begin(reason_code);
1773
27.5k
}
1774
1775
const char *
1776
smtp_server_connection_get_server_name(struct smtp_server_connection *conn)
1777
0
{
1778
0
  if (conn->ssl_iostream == NULL)
1779
0
    return NULL;
1780
0
  return ssl_iostream_get_server_name(conn->ssl_iostream);
1781
0
}