GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../mda.c Lines: 0 476 0.0 %
Date: 2017-11-07 Branches: 0 193 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mda.c,v 1.127 2017/07/31 16:45:03 gilles Exp $	*/
2
3
/*
4
 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
5
 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6
 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
7
 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
#include <sys/types.h>
23
#include <sys/queue.h>
24
#include <sys/tree.h>
25
#include <sys/socket.h>
26
27
#include <ctype.h>
28
#include <err.h>
29
#include <errno.h>
30
#include <event.h>
31
#include <imsg.h>
32
#include <inttypes.h>
33
#include <pwd.h>
34
#include <signal.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <time.h>
39
#include <unistd.h>
40
#include <limits.h>
41
#include <vis.h>
42
43
#include "smtpd.h"
44
#include "log.h"
45
46
#define MDA_HIWAT		65536
47
48
struct mda_envelope {
49
	TAILQ_ENTRY(mda_envelope)	 entry;
50
	uint64_t			 id;
51
	time_t				 creation;
52
	char				*sender;
53
	char				*dest;
54
	char				*rcpt;
55
	enum action_type		 method;
56
	char				*user;
57
	char				*buffer;
58
};
59
60
#define USER_WAITINFO	0x01
61
#define USER_RUNNABLE	0x02
62
#define USER_ONHOLD	0x04
63
#define USER_HOLDQ	0x08
64
65
struct mda_user {
66
	uint64_t			id;
67
	TAILQ_ENTRY(mda_user)		entry;
68
	TAILQ_ENTRY(mda_user)		entry_runnable;
69
	char				name[LOGIN_NAME_MAX];
70
	char				usertable[PATH_MAX];
71
	size_t				evpcount;
72
	TAILQ_HEAD(, mda_envelope)	envelopes;
73
	int				flags;
74
	size_t				running;
75
	struct userinfo			userinfo;
76
};
77
78
struct mda_session {
79
	uint64_t		 id;
80
	struct mda_user		*user;
81
	struct mda_envelope	*evp;
82
	struct io		*io;
83
	FILE			*datafp;
84
};
85
86
static void mda_io(struct io *, int, void *);
87
static int mda_check_loop(FILE *, struct mda_envelope *);
88
static int mda_getlastline(int, char *, size_t);
89
static void mda_done(struct mda_session *);
90
static void mda_fail(struct mda_user *, int, const char *,
91
    enum enhanced_status_code);
92
static void mda_drain(void);
93
static void mda_log(const struct mda_envelope *, const char *, const char *);
94
static void mda_queue_ok(uint64_t);
95
static void mda_queue_tempfail(uint64_t, const char *,
96
    enum enhanced_status_code);
97
static void mda_queue_permfail(uint64_t, const char *, enum enhanced_status_code);
98
static void mda_queue_loop(uint64_t);
99
static struct mda_user *mda_user(const struct envelope *);
100
static void mda_user_free(struct mda_user *);
101
static const char *mda_user_to_text(const struct mda_user *);
102
static struct mda_envelope *mda_envelope(const struct envelope *);
103
static void mda_envelope_free(struct mda_envelope *);
104
static struct mda_session * mda_session(struct mda_user *);
105
106
static struct tree	sessions;
107
static struct tree	users;
108
109
static TAILQ_HEAD(, mda_user)	runnable;
110
111
void
112
mda_imsg(struct mproc *p, struct imsg *imsg)
113
{
114
	struct mda_session	*s;
115
	struct mda_user		*u;
116
	struct mda_envelope	*e;
117
	struct envelope		 evp;
118
	struct userinfo		*userinfo;
119
	struct deliver		 deliver;
120
	struct msg		 m;
121
	const void		*data;
122
	const char		*error, *parent_error;
123
	uint64_t		 reqid;
124
	time_t			 now;
125
	size_t			 sz;
126
	char			 out[256], buf[LINE_MAX];
127
	int			 n;
128
	enum lka_resp_status	status;
129
130
	if (p->proc == PROC_LKA) {
131
		switch (imsg->hdr.type) {
132
		case IMSG_MDA_LOOKUP_USERINFO:
133
			m_msg(&m, imsg);
134
			m_get_id(&m, &reqid);
135
			m_get_int(&m, (int *)&status);
136
			if (status == LKA_OK)
137
				m_get_data(&m, &data, &sz);
138
			m_end(&m);
139
140
			u = tree_xget(&users, reqid);
141
142
			if (status == LKA_TEMPFAIL)
143
				mda_fail(u, 0,
144
				    "Temporary failure in user lookup",
145
				    ESC_OTHER_ADDRESS_STATUS);
146
			else if (status == LKA_PERMFAIL)
147
				mda_fail(u, 1,
148
				    "Permanent failure in user lookup",
149
				    ESC_DESTINATION_MAILBOX_HAS_MOVED);
150
			else {
151
				if (sz != sizeof(u->userinfo))
152
					fatalx("mda: userinfo size mismatch");
153
				memmove(&u->userinfo, data, sz);
154
				u->flags &= ~USER_WAITINFO;
155
				u->flags |= USER_RUNNABLE;
156
				TAILQ_INSERT_TAIL(&runnable, u, entry_runnable);
157
				mda_drain();
158
			}
159
			return;
160
		}
161
	}
162
163
	if (p->proc == PROC_QUEUE) {
164
		switch (imsg->hdr.type) {
165
166
		case IMSG_QUEUE_DELIVER:
167
			m_msg(&m, imsg);
168
			m_get_envelope(&m, &evp);
169
			m_end(&m);
170
171
			u = mda_user(&evp);
172
173
			if (u->evpcount >= env->sc_mda_task_hiwat) {
174
				if (!(u->flags & USER_ONHOLD)) {
175
					log_debug("debug: mda: hiwat reached for "
176
					    "user \"%s\": holding envelopes",
177
					    mda_user_to_text(u));
178
					u->flags |= USER_ONHOLD;
179
				}
180
			}
181
182
			if (u->flags & USER_ONHOLD) {
183
				u->flags |= USER_HOLDQ;
184
				m_create(p_queue, IMSG_MDA_DELIVERY_HOLD,
185
				    0, 0, -1);
186
				m_add_evpid(p_queue, evp.id);
187
				m_add_id(p_queue, u->id);
188
				m_close(p_queue);
189
				return;
190
			}
191
192
			e = mda_envelope(&evp);
193
			TAILQ_INSERT_TAIL(&u->envelopes, e, entry);
194
			u->evpcount += 1;
195
			stat_increment("mda.pending", 1);
196
197
			if (!(u->flags & USER_RUNNABLE) &&
198
			    !(u->flags & USER_WAITINFO)) {
199
				u->flags |= USER_RUNNABLE;
200
				TAILQ_INSERT_TAIL(&runnable, u, entry_runnable);
201
			}
202
203
			mda_drain();
204
			return;
205
206
		case IMSG_MDA_OPEN_MESSAGE:
207
			m_msg(&m, imsg);
208
			m_get_id(&m, &reqid);
209
			m_end(&m);
210
211
			s = tree_xget(&sessions, reqid);
212
			e = s->evp;
213
214
			if (imsg->fd == -1) {
215
				log_debug("debug: mda: cannot get message fd");
216
				mda_queue_tempfail(e->id,
217
				    "Cannot get message fd",
218
				    ESC_OTHER_MAIL_SYSTEM_STATUS);
219
				mda_log(e, "TempFail", "Cannot get message fd");
220
				mda_done(s);
221
				return;
222
			}
223
224
			log_debug("debug: mda: got message fd %d "
225
			    "for session %016"PRIx64 " evpid %016"PRIx64,
226
			    imsg->fd, s->id, e->id);
227
228
			if ((s->datafp = fdopen(imsg->fd, "r")) == NULL) {
229
				log_warn("warn: mda: fdopen");
230
				close(imsg->fd);
231
				mda_queue_tempfail(e->id, "fdopen failed",
232
				    ESC_OTHER_MAIL_SYSTEM_STATUS);
233
				mda_log(e, "TempFail", "fdopen failed");
234
				mda_done(s);
235
				return;
236
			}
237
238
			/* check delivery loop */
239
			if (mda_check_loop(s->datafp, e)) {
240
				log_debug("debug: mda: loop detected");
241
				mda_queue_loop(e->id);
242
				mda_log(e, "PermFail", "Loop detected");
243
				mda_done(s);
244
				return;
245
			}
246
247
			n = 0;
248
			/*
249
			 * prepend "From " separator ... for
250
			 * A_MDA and A_FILENAME backends only
251
			 */
252
			if (e->method == A_MDA || e->method == A_FILENAME) {
253
				time(&now);
254
				if (e->sender[0])
255
					n = io_printf(s->io, "From %s %s",
256
					    e->sender, ctime(&now));
257
				else
258
					n = io_printf(s->io,
259
					    "From MAILER-DAEMON@%s %s",
260
					    env->sc_hostname, ctime(&now));
261
			}
262
			if (n != -1) {
263
				/* start queueing delivery headers */
264
				if (e->sender[0])
265
					/*
266
					 * XXX: remove existing Return-Path,
267
					 * if any
268
					 */
269
					n = io_printf(s->io,
270
					    "Return-Path: %s\n"
271
					    "Delivered-To: %s\n",
272
					    e->sender,
273
					    e->rcpt ? e->rcpt : e->dest);
274
				else
275
					n = io_printf(s->io,
276
					    "Delivered-To: %s\n",
277
					    e->rcpt ? e->rcpt : e->dest);
278
			}
279
			if (n == -1) {
280
				log_warn("warn: mda: "
281
				    "fail to write delivery info");
282
				mda_queue_tempfail(e->id, "Out of memory",
283
				    ESC_OTHER_MAIL_SYSTEM_STATUS);
284
				mda_log(e, "TempFail", "Out of memory");
285
				mda_done(s);
286
				return;
287
			}
288
289
			/* request parent to fork a helper process */
290
			userinfo = &s->user->userinfo;
291
			memset(&deliver, 0, sizeof deliver);
292
			switch (e->method) {
293
			case A_MDA:
294
				deliver.mode = A_MDA;
295
				deliver.userinfo = *userinfo;
296
				(void)strlcpy(deliver.user, userinfo->username,
297
				    sizeof(deliver.user));
298
				if (strlcpy(deliver.to, e->buffer,
299
					sizeof(deliver.to))
300
				    >= sizeof(deliver.to)) {
301
					mda_queue_tempfail(e->id,
302
					    "mda command too long",
303
					    ESC_OTHER_MAIL_SYSTEM_STATUS);
304
					mda_log(e, "TempFail",
305
					    "mda command too long");
306
					mda_done(s);
307
					return;
308
				}
309
				break;
310
311
			case A_MBOX:
312
				/*
313
				 * MBOX is a special case as we MUST
314
				 * deliver as root, just override the uid.
315
				 */
316
				deliver.mode = A_MBOX;
317
				deliver.userinfo = *userinfo;
318
				deliver.userinfo.uid = 0;
319
				(void)strlcpy(deliver.user, "root",
320
				    sizeof(deliver.user));
321
				(void)strlcpy(deliver.from, e->sender,
322
				    sizeof(deliver.from));
323
				(void)strlcpy(deliver.to, userinfo->username,
324
				    sizeof(deliver.to));
325
				break;
326
327
			case A_MAILDIR:
328
				deliver.mode = A_MAILDIR;
329
				deliver.userinfo = *userinfo;
330
				(void)strlcpy(deliver.user, userinfo->username,
331
				    sizeof(deliver.user));
332
				(void)strlcpy(deliver.dest, e->dest,
333
				    sizeof(deliver.dest));
334
				if (strlcpy(deliver.to, e->buffer,
335
					sizeof(deliver.to))
336
				    >= sizeof(deliver.to)) {
337
					log_warn("warn: mda: "
338
					    "deliver buffer too large");
339
					mda_queue_tempfail(e->id,
340
					    "Maildir path too long",
341
					    ESC_OTHER_MAIL_SYSTEM_STATUS);
342
					mda_log(e, "TempFail",
343
					    "Maildir path too long");
344
					mda_done(s);
345
					return;
346
				}
347
				break;
348
349
			case A_FILENAME:
350
				deliver.mode = A_FILENAME;
351
				deliver.userinfo = *userinfo;
352
				(void)strlcpy(deliver.user, userinfo->username,
353
				    sizeof deliver.user);
354
				if (strlcpy(deliver.to, e->buffer,
355
					sizeof(deliver.to))
356
				    >= sizeof(deliver.to)) {
357
					log_warn("warn: mda: "
358
					    "deliver buffer too large");
359
					mda_queue_tempfail(e->id,
360
					    "filename path too long",
361
					    ESC_OTHER_MAIL_SYSTEM_STATUS);
362
					mda_log(e, "TempFail",
363
					    "filename path too long");
364
					mda_done(s);
365
					return;
366
				}
367
				break;
368
369
			case A_LMTP:
370
				deliver.mode = A_LMTP;
371
				deliver.userinfo = *userinfo;
372
				(void)strlcpy(deliver.user, e->user,
373
				    sizeof(deliver.user));
374
				(void)strlcpy(deliver.from, e->sender,
375
				    sizeof(deliver.from));
376
				(void)strlcpy(deliver.dest, e->dest,
377
				    sizeof(deliver.dest));
378
				if (strlcpy(deliver.to, e->buffer,
379
					sizeof(deliver.to))
380
				    >= sizeof(deliver.to)) {
381
					log_warn("warn: mda: "
382
					    "deliver buffer too large");
383
					mda_queue_tempfail(e->id,
384
					    "socket path too long",
385
					    ESC_OTHER_MAIL_SYSTEM_STATUS);
386
					mda_log(e, "TempFail",
387
					    "socket path too long");
388
					mda_done(s);
389
					return;
390
				}
391
				break;
392
393
			default:
394
				errx(1, "mda: unknown delivery method: %d",
395
				    e->method);
396
			}
397
398
			log_debug("debug: mda: querying mda fd "
399
			    "for session %016"PRIx64 " evpid %016"PRIx64,
400
			    s->id, s->evp->id);
401
402
			m_create(p_parent, IMSG_MDA_FORK, 0, 0, -1);
403
			m_add_id(p_parent, reqid);
404
			m_add_data(p_parent, &deliver, sizeof(deliver));
405
			m_close(p_parent);
406
			return;
407
		}
408
	}
409
410
	if (p->proc == PROC_PARENT) {
411
		switch (imsg->hdr.type) {
412
		case IMSG_MDA_FORK:
413
			m_msg(&m, imsg);
414
			m_get_id(&m, &reqid);
415
			m_end(&m);
416
417
			s = tree_xget(&sessions, reqid);
418
			e = s->evp;
419
			if (imsg->fd == -1) {
420
				log_warn("warn: mda: fail to retrieve mda fd");
421
				mda_queue_tempfail(e->id, "Cannot get mda fd",
422
				    ESC_OTHER_MAIL_SYSTEM_STATUS);
423
				mda_log(e, "TempFail", "Cannot get mda fd");
424
				mda_done(s);
425
				return;
426
			}
427
428
			log_debug("debug: mda: got mda fd %d "
429
			    "for session %016"PRIx64 " evpid %016"PRIx64,
430
			    imsg->fd, s->id, s->evp->id);
431
432
			io_set_nonblocking(imsg->fd);
433
			io_set_fd(s->io, imsg->fd);
434
			io_set_write(s->io);
435
			return;
436
437
		case IMSG_MDA_DONE:
438
			m_msg(&m, imsg);
439
			m_get_id(&m, &reqid);
440
			m_get_string(&m, &parent_error);
441
			m_end(&m);
442
443
			s = tree_xget(&sessions, reqid);
444
			e = s->evp;
445
			/*
446
			 * Grab last line of mda stdout/stderr if available.
447
			 */
448
			out[0] = '\0';
449
			if (imsg->fd != -1)
450
				mda_getlastline(imsg->fd, out, sizeof(out));
451
			/*
452
			 * Choose between parent's description of error and
453
			 * child's output, the latter having preference over
454
			 * the former.
455
			 */
456
			error = NULL;
457
			if (strcmp(parent_error, "exited okay") == 0) {
458
				if (s->datafp || (s->io && io_queued(s->io)))
459
					error = "mda exited prematurely";
460
			} else
461
				error = out[0] ? out : parent_error;
462
463
			/* update queue entry */
464
			if (error) {
465
				mda_queue_tempfail(e->id, error,
466
				    ESC_OTHER_MAIL_SYSTEM_STATUS);
467
				(void)snprintf(buf, sizeof buf,
468
				    "Error (%s)", error);
469
				mda_log(e, "TempFail", buf);
470
			}
471
			else {
472
				mda_queue_ok(e->id);
473
				mda_log(e, "Ok", "Delivered");
474
			}
475
			mda_done(s);
476
			return;
477
		}
478
	}
479
480
	errx(1, "mda_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
481
}
482
483
void
484
mda_postfork()
485
{
486
}
487
488
void
489
mda_postprivdrop()
490
{
491
	tree_init(&sessions);
492
	tree_init(&users);
493
	TAILQ_INIT(&runnable);
494
}
495
496
static void
497
mda_io(struct io *io, int evt, void *arg)
498
{
499
	struct mda_session	*s = arg;
500
	char			*ln = NULL;
501
	size_t			 sz = 0;
502
	ssize_t			 len;
503
504
	log_trace(TRACE_IO, "mda: %p: %s %s", s, io_strevent(evt),
505
	    io_strio(io));
506
507
	switch (evt) {
508
	case IO_LOWAT:
509
510
	/* done */
511
	done:
512
		if (s->datafp == NULL) {
513
			log_debug("debug: mda: all data sent for session"
514
			    " %016"PRIx64 " evpid %016"PRIx64,
515
			    s->id, s->evp->id);
516
			io_free(io);
517
			s->io = NULL;
518
			return;
519
		}
520
521
		while (io_queued(s->io) < MDA_HIWAT) {
522
			if ((len = getline(&ln, &sz, s->datafp)) == -1)
523
				break;
524
			if (io_write(s->io, ln, len) == -1) {
525
				m_create(p_parent, IMSG_MDA_KILL,
526
				    0, 0, -1);
527
				m_add_id(p_parent, s->id);
528
				m_add_string(p_parent, "Out of memory");
529
				m_close(p_parent);
530
				io_pause(io, IO_OUT);
531
				free(ln);
532
				return;
533
			}
534
		}
535
536
		free(ln);
537
		ln = NULL;
538
		if (ferror(s->datafp)) {
539
			log_debug("debug: mda: ferror on session %016"PRIx64,
540
			    s->id);
541
			m_create(p_parent, IMSG_MDA_KILL, 0, 0, -1);
542
			m_add_id(p_parent, s->id);
543
			m_add_string(p_parent, "Error reading body");
544
			m_close(p_parent);
545
			io_pause(io, IO_OUT);
546
			return;
547
		}
548
549
		if (feof(s->datafp)) {
550
			log_debug("debug: mda: end-of-file for session"
551
			    " %016"PRIx64 " evpid %016"PRIx64,
552
			    s->id, s->evp->id);
553
			fclose(s->datafp);
554
			s->datafp = NULL;
555
			if (io_queued(s->io) == 0)
556
				goto done;
557
		}
558
		return;
559
560
	case IO_TIMEOUT:
561
		log_debug("debug: mda: timeout on session %016"PRIx64, s->id);
562
		io_pause(io, IO_OUT);
563
		return;
564
565
	case IO_ERROR:
566
		log_debug("debug: mda: io error on session %016"PRIx64": %s",
567
		    s->id, io_error(io));
568
		io_pause(io, IO_OUT);
569
		return;
570
571
	case IO_DISCONNECTED:
572
		log_debug("debug: mda: io disconnected on session %016"PRIx64,
573
		    s->id);
574
		io_pause(io, IO_OUT);
575
		return;
576
577
	default:
578
		log_debug("debug: mda: unexpected event on session %016"PRIx64,
579
		    s->id);
580
		io_pause(io, IO_OUT);
581
		return;
582
	}
583
}
584
585
static int
586
mda_check_loop(FILE *fp, struct mda_envelope *e)
587
{
588
	char		*buf = NULL;
589
	size_t		 sz = 0;
590
	ssize_t		 len;
591
	int		 ret = 0;
592
593
	while ((len = getline(&buf, &sz, fp)) != -1) {
594
		if (buf[len - 1] == '\n')
595
			buf[len - 1] = '\0';
596
597
		if (strchr(buf, ':') == NULL && !isspace((unsigned char)*buf))
598
			break;
599
600
		if (strncasecmp("Delivered-To: ", buf, 14) == 0) {
601
			if (strcasecmp(buf + 14, e->dest) == 0) {
602
				ret = 1;
603
				break;
604
			}
605
		}
606
	}
607
608
	free(buf);
609
	fseek(fp, SEEK_SET, 0);
610
	return (ret);
611
}
612
613
static int
614
mda_getlastline(int fd, char *dst, size_t dstsz)
615
{
616
	FILE	*fp;
617
	char	*ln = NULL;
618
	size_t	 sz = 0;
619
	ssize_t	 len;
620
	int	 out = 0;
621
622
	if (lseek(fd, 0, SEEK_SET) < 0) {
623
		log_warn("warn: mda: lseek");
624
		close(fd);
625
		return (-1);
626
	}
627
	fp = fdopen(fd, "r");
628
	if (fp == NULL) {
629
		log_warn("warn: mda: fdopen");
630
		close(fd);
631
		return (-1);
632
	}
633
	while ((len = getline(&ln, &sz, fp)) != -1) {
634
		if (ln[len - 1] == '\n')
635
			ln[len - 1] = '\0';
636
		out = 1;
637
	}
638
	fclose(fp);
639
640
	if (out) {
641
		(void)strlcpy(dst, "\"", dstsz);
642
		(void)strnvis(dst + 1, ln, dstsz - 2, VIS_SAFE | VIS_CSTYLE);
643
		(void)strlcat(dst, "\"", dstsz);
644
	}
645
646
	free(ln);
647
	return (0);
648
}
649
650
static void
651
mda_fail(struct mda_user *user, int permfail, const char *error,
652
    enum enhanced_status_code code)
653
{
654
	struct mda_envelope	*e;
655
656
	while ((e = TAILQ_FIRST(&user->envelopes))) {
657
		TAILQ_REMOVE(&user->envelopes, e, entry);
658
		if (permfail) {
659
			mda_log(e, "PermFail", error);
660
			mda_queue_permfail(e->id, error, code);
661
		}
662
		else {
663
			mda_log(e, "TempFail", error);
664
			mda_queue_tempfail(e->id, error, code);
665
		}
666
		mda_envelope_free(e);
667
	}
668
669
	mda_user_free(user);
670
}
671
672
static void
673
mda_drain(void)
674
{
675
	struct mda_user		*u;
676
677
	while ((u = (TAILQ_FIRST(&runnable)))) {
678
679
		TAILQ_REMOVE(&runnable, u, entry_runnable);
680
681
		if (u->evpcount == 0 && u->running == 0) {
682
			log_debug("debug: mda: all done for user \"%s\"",
683
			    mda_user_to_text(u));
684
			mda_user_free(u);
685
			continue;
686
		}
687
688
		if (u->evpcount == 0) {
689
			log_debug("debug: mda: no more envelope for \"%s\"",
690
			    mda_user_to_text(u));
691
			u->flags &= ~USER_RUNNABLE;
692
			continue;
693
		}
694
695
		if (u->running >= env->sc_mda_max_user_session) {
696
			log_debug("debug: mda: "
697
			    "maximum number of session reached for user \"%s\"",
698
			    mda_user_to_text(u));
699
			u->flags &= ~USER_RUNNABLE;
700
			continue;
701
		}
702
703
		if (tree_count(&sessions) >= env->sc_mda_max_session) {
704
			log_debug("debug: mda: "
705
			    "maximum number of session reached");
706
			TAILQ_INSERT_HEAD(&runnable, u, entry_runnable);
707
			return;
708
		}
709
710
		mda_session(u);
711
712
		if (u->evpcount == env->sc_mda_task_lowat) {
713
			if (u->flags & USER_ONHOLD) {
714
				log_debug("debug: mda: down to lowat for user "
715
				    "\"%s\": releasing",
716
				    mda_user_to_text(u));
717
				u->flags &= ~USER_ONHOLD;
718
			}
719
			if (u->flags & USER_HOLDQ) {
720
				m_create(p_queue, IMSG_MDA_HOLDQ_RELEASE,
721
				    0, 0, -1);
722
				m_add_id(p_queue, u->id);
723
				m_add_int(p_queue, env->sc_mda_task_release);
724
				m_close(p_queue);
725
			}
726
		}
727
728
		/* re-add the user at the tail of the queue */
729
		TAILQ_INSERT_TAIL(&runnable, u, entry_runnable);
730
	}
731
}
732
733
static void
734
mda_done(struct mda_session *s)
735
{
736
	log_debug("debug: mda: session %016" PRIx64 " done", s->id);
737
738
	tree_xpop(&sessions, s->id);
739
740
	mda_envelope_free(s->evp);
741
742
	s->user->running--;
743
	if (!(s->user->flags & USER_RUNNABLE)) {
744
		log_debug("debug: mda: user \"%s\" becomes runnable",
745
		    s->user->name);
746
		TAILQ_INSERT_TAIL(&runnable, s->user, entry_runnable);
747
		s->user->flags |= USER_RUNNABLE;
748
	}
749
750
	if (s->datafp)
751
		fclose(s->datafp);
752
	if (s->io)
753
		io_free(s->io);
754
755
	free(s);
756
757
	stat_decrement("mda.running", 1);
758
759
	mda_drain();
760
}
761
762
static void
763
mda_log(const struct mda_envelope *evp, const char *prefix, const char *status)
764
{
765
	char rcpt[LINE_MAX];
766
	const char *method;
767
768
	rcpt[0] = '\0';
769
	if (evp->rcpt)
770
		(void)snprintf(rcpt, sizeof rcpt, "rcpt=<%s>, ", evp->rcpt);
771
772
	if (evp->method == A_MAILDIR)
773
		method = "maildir";
774
	else if (evp->method == A_MBOX)
775
		method = "mbox";
776
	else if (evp->method == A_FILENAME)
777
		method = "file";
778
	else if (evp->method == A_MDA)
779
		method = "mda";
780
	else if (evp->method == A_LMTP)
781
		method = "lmtp";
782
	else
783
		method = "???";
784
785
	log_info("%016"PRIx64" mda event=delivery evpid=%016" PRIx64 " from=<%s> to=<%s> "
786
	    "%suser=%s method=%s delay=%s result=%s stat=%s",
787
	    (uint64_t)0,
788
	    evp->id,
789
	    evp->sender ? evp->sender : "",
790
	    evp->dest,
791
	    rcpt,
792
	    evp->user,
793
	    method,
794
	    duration_to_text(time(NULL) - evp->creation),
795
	    prefix,
796
	    status);
797
}
798
799
static void
800
mda_queue_ok(uint64_t evpid)
801
{
802
	m_create(p_queue, IMSG_MDA_DELIVERY_OK, 0, 0, -1);
803
	m_add_evpid(p_queue, evpid);
804
	m_close(p_queue);
805
}
806
807
static void
808
mda_queue_tempfail(uint64_t evpid, const char *reason,
809
    enum enhanced_status_code code)
810
{
811
	m_create(p_queue, IMSG_MDA_DELIVERY_TEMPFAIL, 0, 0, -1);
812
	m_add_evpid(p_queue, evpid);
813
	m_add_string(p_queue, reason);
814
	m_add_int(p_queue, (int)code);
815
	m_close(p_queue);
816
}
817
818
static void
819
mda_queue_permfail(uint64_t evpid, const char *reason,
820
    enum enhanced_status_code code)
821
{
822
	m_create(p_queue, IMSG_MDA_DELIVERY_PERMFAIL, 0, 0, -1);
823
	m_add_evpid(p_queue, evpid);
824
	m_add_string(p_queue, reason);
825
	m_add_int(p_queue, (int)code);
826
	m_close(p_queue);
827
}
828
829
static void
830
mda_queue_loop(uint64_t evpid)
831
{
832
	m_create(p_queue, IMSG_MDA_DELIVERY_LOOP, 0, 0, -1);
833
	m_add_evpid(p_queue, evpid);
834
	m_close(p_queue);
835
}
836
837
static struct mda_user *
838
mda_user(const struct envelope *evp)
839
{
840
	struct mda_user	*u;
841
	void		*i;
842
843
	i = NULL;
844
	while (tree_iter(&users, &i, NULL, (void**)(&u))) {
845
		if (!strcmp(evp->agent.mda.username, u->name) &&
846
		    !strcmp(evp->agent.mda.usertable, u->usertable))
847
			return (u);
848
	}
849
850
	u = xcalloc(1, sizeof *u, "mda_user");
851
	u->id = generate_uid();
852
	TAILQ_INIT(&u->envelopes);
853
	(void)strlcpy(u->name, evp->agent.mda.username, sizeof(u->name));
854
	(void)strlcpy(u->usertable, evp->agent.mda.usertable,
855
	    sizeof(u->usertable));
856
857
	tree_xset(&users, u->id, u);
858
859
	m_create(p_lka, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1);
860
	m_add_id(p_lka, u->id);
861
	m_add_string(p_lka, evp->agent.mda.usertable);
862
	if (evp->agent.mda.delivery_user[0])
863
		m_add_string(p_lka, evp->agent.mda.delivery_user);
864
	else
865
		m_add_string(p_lka, evp->agent.mda.username);
866
	m_close(p_lka);
867
	u->flags |= USER_WAITINFO;
868
869
	stat_increment("mda.user", 1);
870
871
	if (evp->agent.mda.delivery_user[0])
872
		log_debug("mda: new user %016" PRIx64
873
		    " for \"%s\" delivering as \"%s\"",
874
		    u->id, mda_user_to_text(u), evp->agent.mda.delivery_user);
875
	else
876
		log_debug("mda: new user %016" PRIx64
877
		    " for \"%s\"", u->id, mda_user_to_text(u));
878
879
	return (u);
880
}
881
882
static void
883
mda_user_free(struct mda_user *u)
884
{
885
	tree_xpop(&users, u->id);
886
887
	if (u->flags & USER_HOLDQ) {
888
		m_create(p_queue, IMSG_MDA_HOLDQ_RELEASE, 0, 0, -1);
889
		m_add_id(p_queue, u->id);
890
		m_add_int(p_queue, 0);
891
		m_close(p_queue);
892
	}
893
894
	free(u);
895
	stat_decrement("mda.user", 1);
896
}
897
898
static const char *
899
mda_user_to_text(const struct mda_user *u)
900
{
901
	static char buf[1024];
902
903
	(void)snprintf(buf, sizeof(buf), "%s:%s", u->usertable, u->name);
904
905
	return (buf);
906
}
907
908
static struct mda_envelope *
909
mda_envelope(const struct envelope *evp)
910
{
911
	struct mda_envelope	*e;
912
	char			 buf[LINE_MAX];
913
914
	e = xcalloc(1, sizeof *e, "mda_envelope");
915
	e->id = evp->id;
916
	e->creation = evp->creation;
917
	buf[0] = '\0';
918
	if (evp->sender.user[0] && evp->sender.domain[0])
919
		(void)snprintf(buf, sizeof buf, "%s@%s",
920
		    evp->sender.user, evp->sender.domain);
921
	e->sender = xstrdup(buf, "mda_envelope:sender");
922
	(void)snprintf(buf, sizeof buf, "%s@%s", evp->dest.user,
923
	    evp->dest.domain);
924
	e->dest = xstrdup(buf, "mda_envelope:dest");
925
	(void)snprintf(buf, sizeof buf, "%s@%s", evp->rcpt.user,
926
	    evp->rcpt.domain);
927
	if (strcmp(buf, e->dest))
928
		e->rcpt = xstrdup(buf, "mda_envelope:rcpt");
929
	e->method = evp->agent.mda.method;
930
	e->buffer = xstrdup(evp->agent.mda.buffer, "mda_envelope:buffer");
931
	e->user = xstrdup(evp->agent.mda.username, "mda_envelope:user");
932
933
	stat_increment("mda.envelope", 1);
934
935
	return (e);
936
}
937
938
static void
939
mda_envelope_free(struct mda_envelope *e)
940
{
941
	free(e->sender);
942
	free(e->dest);
943
	free(e->rcpt);
944
	free(e->user);
945
	free(e->buffer);
946
	free(e);
947
948
	stat_decrement("mda.envelope", 1);
949
}
950
951
static struct mda_session *
952
mda_session(struct mda_user * u)
953
{
954
	struct mda_session *s;
955
956
	s = xcalloc(1, sizeof *s, "mda_session");
957
	s->id = generate_uid();
958
	s->user = u;
959
	s->io = io_new();
960
	io_set_callback(s->io, mda_io, s);
961
962
	tree_xset(&sessions, s->id, s);
963
964
	s->evp = TAILQ_FIRST(&u->envelopes);
965
	TAILQ_REMOVE(&u->envelopes, s->evp, entry);
966
	u->evpcount--;
967
	u->running++;
968
969
	stat_decrement("mda.pending", 1);
970
	stat_increment("mda.running", 1);
971
972
	log_debug("debug: mda: new session %016" PRIx64
973
	    " for user \"%s\" evpid %016" PRIx64, s->id,
974
	    mda_user_to_text(u), s->evp->id);
975
976
	m_create(p_queue, IMSG_MDA_OPEN_MESSAGE, 0, 0, -1);
977
	m_add_id(p_queue, s->id);
978
	m_add_msgid(p_queue, evpid_to_msgid(s->evp->id));
979
	m_close(p_queue);
980
981
	return (s);
982
}