Coverage Report

Created: 2026-07-30 06:31

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