xref: /netbsd-src/external/ibm-public/postfix/dist/src/oqmgr/qmgr_message.c (revision 67b9b338a7386232ac596b5fd0cd5a9cc8a03c71)
1 /*	$NetBSD: qmgr_message.c,v 1.4 2022/10/08 16:12:46 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	qmgr_message 3
6 /* SUMMARY
7 /*	in-core message structures
8 /* SYNOPSIS
9 /*	#include "qmgr.h"
10 /*
11 /*	int	qmgr_message_count;
12 /*	int	qmgr_recipient_count;
13 /*	int	qmgr_vrfy_pend_count;
14 /*
15 /*	QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
16 /*	const char *class;
17 /*	const char *name;
18 /*	int	qflags;
19 /*	mode_t	mode;
20 /*
21 /*	QMGR_MESSAGE *qmgr_message_realloc(message)
22 /*	QMGR_MESSAGE *message;
23 /*
24 /*	void	qmgr_message_free(message)
25 /*	QMGR_MESSAGE *message;
26 /*
27 /*	void	qmgr_message_update_warn(message)
28 /*	QMGR_MESSAGE *message;
29 /*
30 /*	void	qmgr_message_kill_record(message, offset)
31 /*	QMGR_MESSAGE *message;
32 /*	long	offset;
33 /* DESCRIPTION
34 /*	This module performs en-gross operations on queue messages.
35 /*
36 /*	qmgr_message_count is a global counter for the total number
37 /*	of in-core message structures (i.e. the total size of the
38 /*	`active' message queue).
39 /*
40 /*	qmgr_recipient_count is a global counter for the total number
41 /*	of in-core recipient structures (i.e. the sum of all recipients
42 /*	in all in-core message structures).
43 /*
44 /*	qmgr_vrfy_pend_count is a global counter for the total
45 /*	number of in-core message structures that are associated
46 /*	with an address verification request. Requests that exceed
47 /*	the address_verify_pending_limit are deferred immediately.
48 /*	This is a backup mechanism for a more refined enforcement
49 /*	mechanism in the verify(8) daemon.
50 /*
51 /*	qmgr_message_alloc() creates an in-core message structure
52 /*	with sender and recipient information taken from the named queue
53 /*	file. A null result means the queue file could not be read or
54 /*	that the queue file contained incorrect information. A result
55 /*	QMGR_MESSAGE_LOCKED means delivery must be deferred. The number
56 /*	of recipients read from a queue file is limited by the global
57 /*	var_qmgr_rcpt_limit configuration parameter. When the limit
58 /*	is reached, the \fIrcpt_offset\fR structure member is set to
59 /*	the position where the read was terminated. Recipients are
60 /*	run through the resolver, and are assigned to destination
61 /*	queues. Recipients that cannot be assigned are deferred or
62 /*	bounced. Mail that has bounced twice is silently absorbed.
63 /*	A non-zero mode means change the queue file permissions.
64 /*
65 /*	qmgr_message_realloc() resumes reading recipients from the queue
66 /*	file, and updates the recipient list and \fIrcpt_offset\fR message
67 /*	structure members. A null result means that the file could not be
68 /*	read or that the file contained incorrect information.
69 /*
70 /*	qmgr_message_free() destroys an in-core message structure and makes
71 /*	the resources available for reuse. It is an error to destroy
72 /*	a message structure that is still referenced by queue entry structures.
73 /*
74 /*	qmgr_message_update_warn() takes a closed message, opens it, updates
75 /*	the warning field, and closes it again.
76 /*
77 /*	qmgr_message_kill_record() takes a closed message, opens it, updates
78 /*	the record type at the given offset to "killed", and closes the file.
79 /*	A killed envelope record is ignored. Killed records are not allowed
80 /*	inside the message content.
81 /* DIAGNOSTICS
82 /*	Warnings: malformed message file. Fatal errors: out of memory.
83 /* SEE ALSO
84 /*	envelope(3) message envelope parser
85 /* LICENSE
86 /* .ad
87 /* .fi
88 /*	The Secure Mailer license must be distributed with this software.
89 /* AUTHOR(S)
90 /*	Wietse Venema
91 /*	IBM T.J. Watson Research
92 /*	P.O. Box 704
93 /*	Yorktown Heights, NY 10598, USA
94 /*
95 /*	Wietse Venema
96 /*	Google, Inc.
97 /*	111 8th Avenue
98 /*	New York, NY 10011, USA
99 /*--*/
100 
101 /* System library. */
102 
103 #include <sys_defs.h>
104 #include <sys/stat.h>
105 #include <stdlib.h>
106 #include <stdio.h>			/* sscanf() */
107 #include <fcntl.h>
108 #include <errno.h>
109 #include <unistd.h>
110 #include <string.h>
111 #include <ctype.h>
112 
113 /* Utility library. */
114 
115 #include <msg.h>
116 #include <mymalloc.h>
117 #include <vstring.h>
118 #include <vstream.h>
119 #include <split_at.h>
120 #include <valid_hostname.h>
121 #include <argv.h>
122 #include <stringops.h>
123 #include <myflock.h>
124 
125 /* Global library. */
126 
127 #include <dict.h>
128 #include <mail_queue.h>
129 #include <mail_params.h>
130 #include <canon_addr.h>
131 #include <record.h>
132 #include <rec_type.h>
133 #include <sent.h>
134 #include <deliver_completed.h>
135 #include <opened.h>
136 #include <verp_sender.h>
137 #include <mail_proto.h>
138 #include <qmgr_user.h>
139 #include <split_addr.h>
140 #include <dsn_mask.h>
141 #include <rec_attr_map.h>
142 
143 /* Client stubs. */
144 
145 #include <rewrite_clnt.h>
146 #include <resolve_clnt.h>
147 
148 /* Application-specific. */
149 
150 #include "qmgr.h"
151 
152 int     qmgr_message_count;
153 int     qmgr_recipient_count;
154 int     qmgr_vrfy_pend_count;
155 
156 /* qmgr_message_create - create in-core message structure */
157 
qmgr_message_create(const char * queue_name,const char * queue_id,int qflags)158 static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
159 				           const char *queue_id, int qflags)
160 {
161     QMGR_MESSAGE *message;
162 
163     message = (QMGR_MESSAGE *) mymalloc(sizeof(QMGR_MESSAGE));
164     qmgr_message_count++;
165     message->flags = 0;
166     message->qflags = qflags;
167     message->tflags = 0;
168     message->tflags_offset = 0;
169     message->rflags = QMGR_READ_FLAG_DEFAULT;
170     message->fp = 0;
171     message->refcount = 0;
172     message->single_rcpt = 0;
173     message->arrival_time.tv_sec = message->arrival_time.tv_usec = 0;
174     message->create_time = 0;
175     GETTIMEOFDAY(&message->active_time);
176     message->data_offset = 0;
177     message->queue_id = mystrdup(queue_id);
178     message->queue_name = mystrdup(queue_name);
179     message->encoding = 0;
180     message->sender = 0;
181     message->dsn_envid = 0;
182     message->dsn_ret = 0;
183     message->smtputf8 = 0;
184     message->filter_xport = 0;
185     message->inspect_xport = 0;
186     message->redirect_addr = 0;
187     message->data_size = 0;
188     message->cont_length = 0;
189     message->warn_offset = 0;
190     message->warn_time = 0;
191     message->rcpt_offset = 0;
192     message->verp_delims = 0;
193     message->client_name = 0;
194     message->client_addr = 0;
195     message->client_port = 0;
196     message->client_proto = 0;
197     message->client_helo = 0;
198     message->sasl_method = 0;
199     message->sasl_username = 0;
200     message->sasl_sender = 0;
201     message->log_ident = 0;
202     message->rewrite_context = 0;
203     recipient_list_init(&message->rcpt_list, RCPT_LIST_INIT_QUEUE);
204     return (message);
205 }
206 
207 /* qmgr_message_close - close queue file */
208 
qmgr_message_close(QMGR_MESSAGE * message)209 static void qmgr_message_close(QMGR_MESSAGE *message)
210 {
211     vstream_fclose(message->fp);
212     message->fp = 0;
213 }
214 
215 /* qmgr_message_open - open queue file */
216 
qmgr_message_open(QMGR_MESSAGE * message)217 static int qmgr_message_open(QMGR_MESSAGE *message)
218 {
219 
220     /*
221      * Sanity check.
222      */
223     if (message->fp)
224 	msg_panic("%s: queue file is open", message->queue_id);
225 
226     /*
227      * Open this queue file. Skip files that we cannot open. Back off when
228      * the system appears to be running out of resources.
229      */
230     if ((message->fp = mail_queue_open(message->queue_name,
231 				       message->queue_id,
232 				       O_RDWR, 0)) == 0) {
233 	if (errno != ENOENT)
234 	    msg_fatal("open %s %s: %m", message->queue_name, message->queue_id);
235 	msg_warn("open %s %s: %m", message->queue_name, message->queue_id);
236 	return (-1);
237     }
238     return (0);
239 }
240 
241 /* qmgr_message_oldstyle_scan - support for Postfix < 1.0 queue files */
242 
qmgr_message_oldstyle_scan(QMGR_MESSAGE * message)243 static void qmgr_message_oldstyle_scan(QMGR_MESSAGE *message)
244 {
245     VSTRING *buf;
246     long    orig_offset, extra_offset;
247     int     rec_type;
248     char   *start;
249 
250     /*
251      * Initialize. No early returns or we have a memory leak.
252      */
253     buf = vstring_alloc(100);
254     if ((orig_offset = vstream_ftell(message->fp)) < 0)
255 	msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
256 
257     /*
258      * Rewind to the very beginning to make sure we see all records.
259      */
260     if (vstream_fseek(message->fp, 0, SEEK_SET) < 0)
261 	msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
262 
263     /*
264      * Scan through the old style queue file. Count the total number of
265      * recipients and find the data/extra sections offsets. Note that the new
266      * queue files require that data_size equals extra_offset - data_offset,
267      * so we set data_size to this as well and ignore the size record itself
268      * completely.
269      */
270     for (;;) {
271 	rec_type = rec_get(message->fp, buf, 0);
272 	if (rec_type <= 0)
273 	    /* Report missing end record later. */
274 	    break;
275 	start = vstring_str(buf);
276 	if (msg_verbose > 1)
277 	    msg_info("old-style scan record %c %s", rec_type, start);
278 	if (rec_type == REC_TYPE_END)
279 	    break;
280 	if (rec_type == REC_TYPE_MESG) {
281 	    if (message->data_offset == 0) {
282 		if ((message->data_offset = vstream_ftell(message->fp)) < 0)
283 		    msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
284 		if ((extra_offset = atol(start)) <= message->data_offset)
285 		    msg_fatal("bad extra offset %s file %s",
286 			      start, VSTREAM_PATH(message->fp));
287 		if (vstream_fseek(message->fp, extra_offset, SEEK_SET) < 0)
288 		    msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
289 		message->data_size = extra_offset - message->data_offset;
290 	    }
291 	    continue;
292 	}
293     }
294 
295     /*
296      * Clean up.
297      */
298     if (vstream_fseek(message->fp, orig_offset, SEEK_SET) < 0)
299 	msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
300     vstring_free(buf);
301 
302     /*
303      * Sanity checks. Verify that all required information was found,
304      * including the queue file end marker.
305      */
306     if (message->data_offset == 0 || rec_type != REC_TYPE_END)
307 	msg_fatal("%s: envelope records out of order", message->queue_id);
308 }
309 
310 /* qmgr_message_read - read envelope records */
311 
qmgr_message_read(QMGR_MESSAGE * message)312 static int qmgr_message_read(QMGR_MESSAGE *message)
313 {
314     VSTRING *buf;
315     int     rec_type;
316     long    curr_offset;
317     long    save_offset = message->rcpt_offset;	/* save a flag */
318     char   *start;
319     int     nrcpt = 0;
320     const char *error_text;
321     char   *name;
322     char   *value;
323     char   *orig_rcpt = 0;
324     int     count;
325     int     dsn_notify = 0;
326     char   *dsn_orcpt = 0;
327     int     n;
328     int     have_log_client_attr = 0;
329     static const char env_rec_types[] = REC_TYPE_ENVELOPE REC_TYPE_EXTRACT;
330     static const char extra_rec_type[] = {REC_TYPE_XTRA, 0};
331     const char *expected_rec_types;
332 
333     /*
334      * Initialize. No early returns or we have a memory leak.
335      */
336     buf = vstring_alloc(100);
337 
338     /*
339      * If we re-open this file, skip over on-file recipient records that we
340      * already looked at, and refill the in-core recipient address list.
341      */
342     if (message->rcpt_offset) {
343 	if (message->rcpt_list.len)
344 	    msg_panic("%s: recipient list not empty on recipient reload",
345 		      message->queue_id);
346 	if (vstream_fseek(message->fp, message->rcpt_offset, SEEK_SET) < 0)
347 	    msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
348 	message->rcpt_offset = 0;
349     }
350 
351     /*
352      * Read envelope records. XXX Rely on the front-end programs to enforce
353      * record size limits. Read up to var_qmgr_rcpt_limit recipients from the
354      * queue file, to protect against memory exhaustion. Recipient records
355      * may appear before or after the message content, so we keep reading
356      * from the queue file until we have enough recipients (rcpt_offset != 0)
357      * and until we know all the non-recipient information.
358      *
359      * When reading recipients from queue file, stop reading when we reach a
360      * per-message in-core recipient limit rather than a global in-core
361      * recipient limit. Use the global recipient limit only in order to stop
362      * opening queue files. The purpose is to achieve equal delay for
363      * messages with recipient counts up to var_qmgr_rcpt_limit recipients.
364      *
365      * If we would read recipients up to a global recipient limit, the average
366      * number of in-core recipients per message would asymptotically approach
367      * (global recipient limit)/(active queue size limit), which gives equal
368      * delay per recipient rather than equal delay per message.
369      *
370      * On the first open, we must examine all non-recipient records.
371      *
372      * Optimization: when we know that recipient records are not mixed with
373      * non-recipient records, as is typical with mailing list mail, then we
374      * can avoid having to examine all the queue file records before we can
375      * start deliveries. This avoids some file system thrashing with huge
376      * mailing lists.
377      */
378     for (;;) {
379 	expected_rec_types = env_rec_types;
380 	if ((curr_offset = vstream_ftell(message->fp)) < 0)
381 	    msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
382 	if (curr_offset == message->data_offset && curr_offset > 0) {
383 	    if (vstream_fseek(message->fp, message->data_size, SEEK_CUR) < 0)
384 		msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
385 	    curr_offset += message->data_size;
386 	    expected_rec_types = extra_rec_type;
387 	}
388 	rec_type = rec_get_raw(message->fp, buf, 0, REC_FLAG_NONE);
389 	start = vstring_str(buf);
390 	if (msg_verbose > 1)
391 	    msg_info("record %c %s", rec_type, start);
392 	if (rec_type == REC_TYPE_PTR) {
393 	    if ((rec_type = rec_goto(message->fp, start)) == REC_TYPE_ERROR)
394 		break;
395 	    /* Need to update curr_offset after pointer jump. */
396 	    continue;
397 	}
398 	if (rec_type <= 0) {
399 	    msg_warn("%s: message rejected: missing end record",
400 		     message->queue_id);
401 	    break;
402 	}
403 	if (strchr(expected_rec_types, rec_type) == 0) {
404 	    msg_warn("Unexpected record type '%c' at offset %ld",
405 		     rec_type, (long) curr_offset);
406 	    rec_type = REC_TYPE_ERROR;
407 	    break;
408 	}
409 	if (rec_type == REC_TYPE_END) {
410 	    message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
411 	    break;
412 	}
413 
414 	/*
415 	 * Map named attributes to pseudo record types, so that we don't have
416 	 * to pollute the queue file with records that are incompatible with
417 	 * past Postfix versions. Preferably, people should be able to back
418 	 * out from an upgrade without losing mail.
419 	 */
420 	if (rec_type == REC_TYPE_ATTR) {
421 	    if ((error_text = split_nameval(start, &name, &value)) != 0) {
422 		msg_warn("%s: bad attribute record: %s: %.200s",
423 			 message->queue_id, error_text, start);
424 		rec_type = REC_TYPE_ERROR;
425 		break;
426 	    }
427 	    if ((n = rec_attr_map(name)) != 0) {
428 		start = value;
429 		rec_type = n;
430 	    }
431 	}
432 
433 	/*
434 	 * Process recipient records.
435 	 */
436 	if (rec_type == REC_TYPE_RCPT) {
437 	    /* See also below for code setting orig_rcpt etc. */
438 #define FUDGE(x)	((x) * (var_qmgr_fudge / 100.0))
439 	    if (message->rcpt_offset == 0) {
440 		recipient_list_add(&message->rcpt_list, curr_offset,
441 				   dsn_orcpt ? dsn_orcpt : "",
442 				   dsn_notify ? dsn_notify : 0,
443 				   orig_rcpt ? orig_rcpt : "", start);
444 		if (dsn_orcpt) {
445 		    myfree(dsn_orcpt);
446 		    dsn_orcpt = 0;
447 		}
448 		if (orig_rcpt) {
449 		    myfree(orig_rcpt);
450 		    orig_rcpt = 0;
451 		}
452 		if (dsn_notify)
453 		    dsn_notify = 0;
454 		if (message->rcpt_list.len >= FUDGE(var_qmgr_rcpt_limit)) {
455 		    if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0)
456 			msg_fatal("vstream_ftell %s: %m",
457 				  VSTREAM_PATH(message->fp));
458 		    if (message->rflags & QMGR_READ_FLAG_SEEN_ALL_NON_RCPT)
459 			/* We already examined all non-recipient records. */
460 			break;
461 		    if (message->rflags & QMGR_READ_FLAG_MIXED_RCPT_OTHER)
462 			/* Examine all remaining non-recipient records. */
463 			continue;
464 		    /* Optimizations for "pure recipient" record sections. */
465 		    if (curr_offset > message->data_offset) {
466 			/* We already examined all non-recipient records. */
467 			message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
468 			break;
469 		    }
470 
471 		    /*
472 		     * Examine non-recipient records in the extracted
473 		     * segment. Note that this skips to the message start
474 		     * record, because the handler for that record changes
475 		     * the expectations for allowed record types.
476 		     */
477 		    if (vstream_fseek(message->fp, message->data_offset,
478 				      SEEK_SET) < 0)
479 			msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
480 		    continue;
481 		}
482 	    }
483 	    continue;
484 	}
485 	if (rec_type == REC_TYPE_DONE || rec_type == REC_TYPE_DRCP) {
486 	    if (message->rcpt_offset == 0) {
487 		if (dsn_orcpt) {
488 		    myfree(dsn_orcpt);
489 		    dsn_orcpt = 0;
490 		}
491 		if (orig_rcpt) {
492 		    myfree(orig_rcpt);
493 		    orig_rcpt = 0;
494 		}
495 		if (dsn_notify)
496 		    dsn_notify = 0;
497 	    }
498 	    continue;
499 	}
500 	if (rec_type == REC_TYPE_DSN_ORCPT) {
501 	    /* See also above for code clearing dsn_orcpt. */
502 	    if (dsn_orcpt != 0) {
503 		msg_warn("%s: ignoring out-of-order DSN original recipient address <%.200s>",
504 			 message->queue_id, dsn_orcpt);
505 		myfree(dsn_orcpt);
506 		dsn_orcpt = 0;
507 	    }
508 	    if (message->rcpt_offset == 0)
509 		dsn_orcpt = mystrdup(start);
510 	    continue;
511 	}
512 	if (rec_type == REC_TYPE_DSN_NOTIFY) {
513 	    /* See also above for code clearing dsn_notify. */
514 	    if (dsn_notify != 0) {
515 		msg_warn("%s: ignoring out-of-order DSN notify flags <%d>",
516 			 message->queue_id, dsn_notify);
517 		dsn_notify = 0;
518 	    }
519 	    if (message->rcpt_offset == 0) {
520 		if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_NOTIFY_OK(n))
521 		    msg_warn("%s: ignoring malformed DSN notify flags <%.200s>",
522 			     message->queue_id, start);
523 		else
524 		    dsn_notify = n;
525 		continue;
526 	    }
527 	}
528 	if (rec_type == REC_TYPE_ORCP) {
529 	    /* See also above for code clearing orig_rcpt. */
530 	    if (orig_rcpt != 0) {
531 		msg_warn("%s: ignoring out-of-order original recipient <%.200s>",
532 			 message->queue_id, orig_rcpt);
533 		myfree(orig_rcpt);
534 		orig_rcpt = 0;
535 	    }
536 	    if (message->rcpt_offset == 0)
537 		orig_rcpt = mystrdup(start);
538 	    continue;
539 	}
540 
541 	/*
542 	 * Process non-recipient records.
543 	 */
544 	if (message->rflags & QMGR_READ_FLAG_SEEN_ALL_NON_RCPT)
545 	    /* We already examined all non-recipient records. */
546 	    continue;
547 	if (rec_type == REC_TYPE_SIZE) {
548 	    if (message->data_offset == 0) {
549 		if ((count = sscanf(start, "%ld %ld %d %d %ld %d",
550 				 &message->data_size, &message->data_offset,
551 				    &nrcpt, &message->rflags,
552 				    &message->cont_length,
553 				    &message->smtputf8)) >= 3) {
554 		    /* Postfix >= 1.0 (a.k.a. 20010228). */
555 		    if (message->data_offset <= 0 || message->data_size <= 0) {
556 			msg_warn("%s: invalid size record: %.100s",
557 				 message->queue_id, start);
558 			rec_type = REC_TYPE_ERROR;
559 			break;
560 		    }
561 		    if (message->rflags & ~QMGR_READ_FLAG_USER) {
562 			msg_warn("%s: invalid flags in size record: %.100s",
563 				 message->queue_id, start);
564 			rec_type = REC_TYPE_ERROR;
565 			break;
566 		    }
567 		} else if (count == 1) {
568 		    /* Postfix < 1.0 (a.k.a. 20010228). */
569 		    qmgr_message_oldstyle_scan(message);
570 		} else {
571 		    /* Can't happen. */
572 		    msg_warn("%s: message rejected: weird size record",
573 			     message->queue_id);
574 		    rec_type = REC_TYPE_ERROR;
575 		    break;
576 		}
577 	    }
578 	    /* Postfix < 2.4 compatibility. */
579 	    if (message->cont_length == 0) {
580 		message->cont_length = message->data_size;
581 	    } else if (message->cont_length < 0) {
582 		msg_warn("%s: invalid size record: %.100s",
583 			 message->queue_id, start);
584 		rec_type = REC_TYPE_ERROR;
585 		break;
586 	    }
587 	    continue;
588 	}
589 	if (rec_type == REC_TYPE_TIME) {
590 	    if (message->arrival_time.tv_sec == 0)
591 		REC_TYPE_TIME_SCAN(start, message->arrival_time);
592 	    continue;
593 	}
594 	if (rec_type == REC_TYPE_CTIME) {
595 	    if (message->create_time == 0)
596 		message->create_time = atol(start);
597 	    continue;
598 	}
599 	if (rec_type == REC_TYPE_FILT) {
600 	    if (message->filter_xport != 0)
601 		myfree(message->filter_xport);
602 	    message->filter_xport = mystrdup(start);
603 	    continue;
604 	}
605 	if (rec_type == REC_TYPE_INSP) {
606 	    if (message->inspect_xport != 0)
607 		myfree(message->inspect_xport);
608 	    message->inspect_xport = mystrdup(start);
609 	    continue;
610 	}
611 	if (rec_type == REC_TYPE_RDR) {
612 	    if (message->redirect_addr != 0)
613 		myfree(message->redirect_addr);
614 	    message->redirect_addr = mystrdup(start);
615 	    continue;
616 	}
617 	if (rec_type == REC_TYPE_FROM) {
618 	    if (message->sender == 0) {
619 		message->sender = mystrdup(start);
620 		opened(message->queue_id, message->sender,
621 		       message->cont_length, nrcpt,
622 		       "queue %s", message->queue_name);
623 	    }
624 	    continue;
625 	}
626 	if (rec_type == REC_TYPE_DSN_ENVID) {
627 	    /* Allow Milter override. */
628 	    if (message->dsn_envid != 0)
629 		myfree(message->dsn_envid);
630 	    message->dsn_envid = mystrdup(start);
631 	}
632 	if (rec_type == REC_TYPE_DSN_RET) {
633 	    /* Allow Milter override. */
634 	    if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n))
635 		msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s",
636 			 message->queue_id, start);
637 	    else
638 		message->dsn_ret = n;
639 	}
640 	if (rec_type == REC_TYPE_ATTR) {
641 	    /* Allow extra segment to override envelope segment info. */
642 	    if (strcmp(name, MAIL_ATTR_ENCODING) == 0) {
643 		if (message->encoding != 0)
644 		    myfree(message->encoding);
645 		message->encoding = mystrdup(value);
646 	    }
647 
648 	    /*
649 	     * Backwards compatibility. Before Postfix 2.3, the logging
650 	     * attributes were called client_name, etc. Now they are called
651 	     * log_client_name. etc., and client_name is used for the actual
652 	     * client information. To support old queue files, we accept both
653 	     * names for the purpose of logging; the new name overrides the
654 	     * old one.
655 	     *
656 	     * XXX Do not use the "legacy" client_name etc. attribute values for
657 	     * initializing the logging attributes, when this file already
658 	     * contains the "modern" log_client_name etc. logging attributes.
659 	     * Otherwise, logging attributes that are not present in the
660 	     * queue file would be set with information from the real client.
661 	     */
662 	    else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_NAME) == 0) {
663 		if (have_log_client_attr == 0 && message->client_name == 0)
664 		    message->client_name = mystrdup(value);
665 	    } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_ADDR) == 0) {
666 		if (have_log_client_attr == 0 && message->client_addr == 0)
667 		    message->client_addr = mystrdup(value);
668 	    } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) {
669 		if (have_log_client_attr == 0 && message->client_port == 0)
670 		    message->client_port = mystrdup(value);
671 	    } else if (strcmp(name, MAIL_ATTR_ACT_PROTO_NAME) == 0) {
672 		if (have_log_client_attr == 0 && message->client_proto == 0)
673 		    message->client_proto = mystrdup(value);
674 	    } else if (strcmp(name, MAIL_ATTR_ACT_HELO_NAME) == 0) {
675 		if (have_log_client_attr == 0 && message->client_helo == 0)
676 		    message->client_helo = mystrdup(value);
677 	    }
678 	    /* Original client attributes. */
679 	    else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_NAME) == 0) {
680 		if (message->client_name != 0)
681 		    myfree(message->client_name);
682 		message->client_name = mystrdup(value);
683 		have_log_client_attr = 1;
684 	    } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_ADDR) == 0) {
685 		if (message->client_addr != 0)
686 		    myfree(message->client_addr);
687 		message->client_addr = mystrdup(value);
688 		have_log_client_attr = 1;
689 	    } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_PORT) == 0) {
690 		if (message->client_port != 0)
691 		    myfree(message->client_port);
692 		message->client_port = mystrdup(value);
693 		have_log_client_attr = 1;
694 	    } else if (strcmp(name, MAIL_ATTR_LOG_PROTO_NAME) == 0) {
695 		if (message->client_proto != 0)
696 		    myfree(message->client_proto);
697 		message->client_proto = mystrdup(value);
698 		have_log_client_attr = 1;
699 	    } else if (strcmp(name, MAIL_ATTR_LOG_HELO_NAME) == 0) {
700 		if (message->client_helo != 0)
701 		    myfree(message->client_helo);
702 		message->client_helo = mystrdup(value);
703 		have_log_client_attr = 1;
704 	    } else if (strcmp(name, MAIL_ATTR_SASL_METHOD) == 0) {
705 		if (message->sasl_method == 0)
706 		    message->sasl_method = mystrdup(value);
707 		else
708 		    msg_warn("%s: ignoring multiple %s attribute: %s",
709 			   message->queue_id, MAIL_ATTR_SASL_METHOD, value);
710 	    } else if (strcmp(name, MAIL_ATTR_SASL_USERNAME) == 0) {
711 		if (message->sasl_username == 0)
712 		    message->sasl_username = mystrdup(value);
713 		else
714 		    msg_warn("%s: ignoring multiple %s attribute: %s",
715 			 message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
716 	    } else if (strcmp(name, MAIL_ATTR_SASL_SENDER) == 0) {
717 		if (message->sasl_sender == 0)
718 		    message->sasl_sender = mystrdup(value);
719 		else
720 		    msg_warn("%s: ignoring multiple %s attribute: %s",
721 			   message->queue_id, MAIL_ATTR_SASL_SENDER, value);
722 	    } else if (strcmp(name, MAIL_ATTR_LOG_IDENT) == 0) {
723 		if (message->log_ident == 0)
724 		    message->log_ident = mystrdup(value);
725 		else
726 		    msg_warn("%s: ignoring multiple %s attribute: %s",
727 			     message->queue_id, MAIL_ATTR_LOG_IDENT, value);
728 	    } else if (strcmp(name, MAIL_ATTR_RWR_CONTEXT) == 0) {
729 		if (message->rewrite_context == 0)
730 		    message->rewrite_context = mystrdup(value);
731 		else
732 		    msg_warn("%s: ignoring multiple %s attribute: %s",
733 			   message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
734 	    }
735 
736 	    /*
737 	     * Optional tracing flags (verify, sendmail -v, sendmail -bv).
738 	     * This record is killed after a trace logfile report is sent and
739 	     * after the logfile is deleted.
740 	     */
741 	    else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
742 		if (message->tflags == 0) {
743 		    message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
744 		    if (message->tflags == DEL_REQ_FLAG_RECORD)
745 			message->tflags_offset = curr_offset;
746 		    else
747 			message->tflags_offset = 0;
748 		    if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
749 			qmgr_vrfy_pend_count++;
750 		}
751 	    }
752 	    continue;
753 	}
754 	if (rec_type == REC_TYPE_WARN) {
755 	    if (message->warn_offset == 0) {
756 		message->warn_offset = curr_offset;
757 		REC_TYPE_WARN_SCAN(start, message->warn_time);
758 	    }
759 	    continue;
760 	}
761 	if (rec_type == REC_TYPE_VERP) {
762 	    if (message->verp_delims == 0) {
763 		if (message->sender == 0 || message->sender[0] == 0) {
764 		    msg_warn("%s: ignoring VERP request for null sender",
765 			     message->queue_id);
766 		} else if (verp_delims_verify(start) != 0) {
767 		    msg_warn("%s: ignoring bad VERP request: \"%.100s\"",
768 			     message->queue_id, start);
769 		} else {
770 		    if (msg_verbose)
771 			msg_info("%s: enabling VERP for sender \"%.100s\"",
772 				 message->queue_id, message->sender);
773 		    message->single_rcpt = 1;
774 		    message->verp_delims = mystrdup(start);
775 		}
776 	    }
777 	    continue;
778 	}
779     }
780 
781     /*
782      * Grr.
783      */
784     if (dsn_orcpt != 0) {
785 	if (rec_type > 0)
786 	    msg_warn("%s: ignoring out-of-order DSN original recipient <%.200s>",
787 		     message->queue_id, dsn_orcpt);
788 	myfree(dsn_orcpt);
789     }
790     if (orig_rcpt != 0) {
791 	if (rec_type > 0)
792 	    msg_warn("%s: ignoring out-of-order original recipient <%.200s>",
793 		     message->queue_id, orig_rcpt);
794 	myfree(orig_rcpt);
795     }
796 
797     /*
798      * After sending a "delayed" warning, request sender notification when
799      * message delivery is completed. While "mail delayed" notifications are
800      * bad enough because they multiply the amount of email traffic, "delay
801      * cleared" notifications are even worse because they come in a sudden
802      * burst when the queue drains after a network outage.
803      */
804     if (var_dsn_delay_cleared && message->warn_time < 0)
805 	message->tflags |= DEL_REQ_FLAG_REC_DLY_SENT;
806 
807     /*
808      * Avoid clumsiness elsewhere in the program. When sending data across an
809      * IPC channel, sending an empty string is more convenient than sending a
810      * null pointer.
811      */
812     if (message->dsn_envid == 0)
813 	message->dsn_envid = mystrdup("");
814     if (message->encoding == 0)
815 	message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
816     if (message->client_name == 0)
817 	message->client_name = mystrdup("");
818     if (message->client_addr == 0)
819 	message->client_addr = mystrdup("");
820     if (message->client_port == 0)
821 	message->client_port = mystrdup("");
822     if (message->client_proto == 0)
823 	message->client_proto = mystrdup("");
824     if (message->client_helo == 0)
825 	message->client_helo = mystrdup("");
826     if (message->sasl_method == 0)
827 	message->sasl_method = mystrdup("");
828     if (message->sasl_username == 0)
829 	message->sasl_username = mystrdup("");
830     if (message->sasl_sender == 0)
831 	message->sasl_sender = mystrdup("");
832     if (message->log_ident == 0)
833 	message->log_ident = mystrdup("");
834     if (message->rewrite_context == 0)
835 	message->rewrite_context = mystrdup(MAIL_ATTR_RWR_LOCAL);
836     /* Postfix < 2.3 compatibility. */
837     if (message->create_time == 0)
838 	message->create_time = message->arrival_time.tv_sec;
839 
840     /*
841      * Clean up.
842      */
843     vstring_free(buf);
844 
845     /*
846      * Sanity checks. Verify that all required information was found,
847      * including the queue file end marker.
848      */
849     if (rec_type <= 0) {
850 	/* Already logged warning. */
851     } else if (message->arrival_time.tv_sec == 0) {
852 	msg_warn("%s: message rejected: missing arrival time record",
853 		 message->queue_id);
854     } else if (message->sender == 0) {
855 	msg_warn("%s: message rejected: missing sender record",
856 		 message->queue_id);
857     } else if (message->data_offset == 0) {
858 	msg_warn("%s: message rejected: missing size record",
859 		 message->queue_id);
860     } else {
861 	return (0);
862     }
863     message->rcpt_offset = save_offset;		/* restore flag */
864     return (-1);
865 }
866 
867 /* qmgr_message_update_warn - update the time of next delay warning */
868 
qmgr_message_update_warn(QMGR_MESSAGE * message)869 void    qmgr_message_update_warn(QMGR_MESSAGE *message)
870 {
871 
872     /*
873      * After the "mail delayed" warning, optionally send a "delay cleared"
874      * notification.
875      */
876     if (qmgr_message_open(message)
877 	|| vstream_fseek(message->fp, message->warn_offset, SEEK_SET) < 0
878 	|| rec_fprintf(message->fp, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
879 		       REC_TYPE_WARN_ARG(-1)) < 0
880 	|| vstream_fflush(message->fp))
881 	msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
882     qmgr_message_close(message);
883 }
884 
885 /* qmgr_message_kill_record - mark one message record as killed */
886 
qmgr_message_kill_record(QMGR_MESSAGE * message,long offset)887 void    qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
888 {
889     if (offset <= 0)
890 	msg_panic("qmgr_message_kill_record: bad offset 0x%lx", offset);
891     if (qmgr_message_open(message)
892 	|| rec_put_type(message->fp, REC_TYPE_KILL, offset) < 0
893 	|| vstream_fflush(message->fp))
894 	msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
895     qmgr_message_close(message);
896 }
897 
898 /* qmgr_message_sort_compare - compare recipient information */
899 
qmgr_message_sort_compare(const void * p1,const void * p2)900 static int qmgr_message_sort_compare(const void *p1, const void *p2)
901 {
902     RECIPIENT *rcpt1 = (RECIPIENT *) p1;
903     RECIPIENT *rcpt2 = (RECIPIENT *) p2;
904     QMGR_QUEUE *queue1;
905     QMGR_QUEUE *queue2;
906     char   *at1;
907     char   *at2;
908     int     result;
909 
910     /*
911      * Compare most significant to least significant recipient attributes.
912      * The comparison function must be transitive, so NULL values need to be
913      * assigned an ordinal (we set NULL last).
914      */
915 
916     queue1 = rcpt1->u.queue;
917     queue2 = rcpt2->u.queue;
918     if (queue1 != 0 && queue2 == 0)
919 	return (-1);
920     if (queue1 == 0 && queue2 != 0)
921 	return (1);
922     if (queue1 != 0 && queue2 != 0) {
923 
924 	/*
925 	 * Compare message transport.
926 	 */
927 	if ((result = strcmp(queue1->transport->name,
928 			     queue2->transport->name)) != 0)
929 	    return (result);
930 
931 	/*
932 	 * Compare queue name (nexthop or recipient@nexthop).
933 	 */
934 	if ((result = strcmp(queue1->name, queue2->name)) != 0)
935 	    return (result);
936     }
937 
938     /*
939      * Compare recipient domain.
940      */
941     at1 = strrchr(rcpt1->address, '@');
942     at2 = strrchr(rcpt2->address, '@');
943     if (at1 == 0 && at2 != 0)
944 	return (1);
945     if (at1 != 0 && at2 == 0)
946 	return (-1);
947     if (at1 != 0 && at2 != 0
948 	&& (result = strcasecmp_utf8(at1, at2)) != 0)
949 	return (result);
950 
951     /*
952      * Compare recipient address.
953      */
954     return (strcasecmp_utf8(rcpt1->address, rcpt2->address));
955 }
956 
957 /* qmgr_message_sort - sort message recipient addresses by domain */
958 
qmgr_message_sort(QMGR_MESSAGE * message)959 static void qmgr_message_sort(QMGR_MESSAGE *message)
960 {
961     qsort((void *) message->rcpt_list.info, message->rcpt_list.len,
962 	  sizeof(message->rcpt_list.info[0]), qmgr_message_sort_compare);
963     if (msg_verbose) {
964 	RECIPIENT_LIST list = message->rcpt_list;
965 	RECIPIENT *rcpt;
966 
967 	msg_info("start sorted recipient list");
968 	for (rcpt = list.info; rcpt < list.info + list.len; rcpt++)
969 	    msg_info("qmgr_message_sort: %s", rcpt->address);
970 	msg_info("end sorted recipient list");
971     }
972 }
973 
974 /* qmgr_resolve_one - resolve or skip one recipient */
975 
qmgr_resolve_one(QMGR_MESSAGE * message,RECIPIENT * recipient,const char * addr,RESOLVE_REPLY * reply)976 static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
977 			            const char *addr, RESOLVE_REPLY *reply)
978 {
979 #define QMGR_REDIRECT(rp, tp, np) do { \
980 	(rp)->flags = 0; \
981 	vstring_strcpy((rp)->transport, (tp)); \
982 	vstring_strcpy((rp)->nexthop, (np)); \
983     } while (0)
984 
985     if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) == 0)
986 	resolve_clnt_query_from(message->sender, addr, reply);
987     else
988 	resolve_clnt_verify_from(message->sender, addr, reply);
989     if (reply->flags & RESOLVE_FLAG_FAIL) {
990 	QMGR_REDIRECT(reply, MAIL_SERVICE_RETRY,
991 		      "4.3.0 address resolver failure");
992 	return (0);
993     } else if (reply->flags & RESOLVE_FLAG_ERROR) {
994 	QMGR_REDIRECT(reply, MAIL_SERVICE_ERROR,
995 		      "5.1.3 bad address syntax");
996 	return (0);
997     } else {
998 	return (0);
999     }
1000 }
1001 
1002 /* qmgr_message_resolve - resolve recipients */
1003 
qmgr_message_resolve(QMGR_MESSAGE * message)1004 static void qmgr_message_resolve(QMGR_MESSAGE *message)
1005 {
1006     static ARGV *defer_xport_argv;
1007     RECIPIENT_LIST list = message->rcpt_list;
1008     RECIPIENT *recipient;
1009     QMGR_TRANSPORT *transport = 0;
1010     QMGR_QUEUE *queue = 0;
1011     RESOLVE_REPLY reply;
1012     VSTRING *queue_name;
1013     char   *at;
1014     char  **cpp;
1015     char   *nexthop;
1016     ssize_t len;
1017     int     status;
1018     DSN     dsn;
1019     MSG_STATS stats;
1020     DSN    *saved_dsn;
1021 
1022 #define STREQ(x,y)	(strcmp(x,y) == 0)
1023 #define STR		vstring_str
1024 #define LEN		VSTRING_LEN
1025 
1026     resolve_clnt_init(&reply);
1027     queue_name = vstring_alloc(1);
1028     for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1029 
1030 	/*
1031 	 * Redirect overrides all else. But only once (per entire message).
1032 	 * For consistency with the remainder of Postfix, rewrite the address
1033 	 * to canonical form before resolving it.
1034 	 */
1035 	if (message->redirect_addr) {
1036 	    if (recipient > list.info) {
1037 		recipient->u.queue = 0;
1038 		continue;
1039 	    }
1040 	    message->rcpt_offset = 0;
1041 	    rewrite_clnt_internal(REWRITE_CANON, message->redirect_addr,
1042 				  reply.recipient);
1043 	    RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1044 	    if (qmgr_resolve_one(message, recipient,
1045 				 recipient->address, &reply) < 0)
1046 		continue;
1047 	    if (!STREQ(recipient->address, STR(reply.recipient)))
1048 		RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1049 	}
1050 
1051 	/*
1052 	 * Content filtering overrides the address resolver.
1053 	 *
1054 	 * XXX Bypass content_filter inspection for user-generated probes
1055 	 * (sendmail -bv). MTA-generated probes never have the "please filter
1056 	 * me" bits turned on, but we handle them here anyway for the sake of
1057 	 * future proofing.
1058 	 */
1059 #define FILTER_WITHOUT_NEXTHOP(filter, next) \
1060 	(((next) = split_at((filter), ':')) == 0 || *(next) == 0)
1061 
1062 #define RCPT_WITHOUT_DOMAIN(rcpt, next) \
1063 	((next = strrchr(rcpt, '@')) == 0 || *++(next) == 0)
1064 
1065 	else if (message->filter_xport
1066 		 && (message->tflags & DEL_REQ_TRACE_ONLY_MASK) == 0) {
1067 	    reply.flags = 0;
1068 	    vstring_strcpy(reply.transport, message->filter_xport);
1069 	    if (FILTER_WITHOUT_NEXTHOP(STR(reply.transport), nexthop)
1070 		&& *(nexthop = var_def_filter_nexthop) == 0
1071 		&& RCPT_WITHOUT_DOMAIN(recipient->address, nexthop))
1072 		nexthop = var_myhostname;
1073 	    vstring_strcpy(reply.nexthop, nexthop);
1074 	    vstring_strcpy(reply.recipient, recipient->address);
1075 	}
1076 
1077 	/*
1078 	 * Resolve the destination to (transport, nexthop, address). The
1079 	 * result address may differ from the one specified by the sender.
1080 	 */
1081 	else {
1082 	    if (qmgr_resolve_one(message, recipient,
1083 				 recipient->address, &reply) < 0)
1084 		continue;
1085 	    if (!STREQ(recipient->address, STR(reply.recipient)))
1086 		RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1087 	}
1088 
1089 	/*
1090 	 * Bounce null recipients. This should never happen, but is most
1091 	 * likely the result of a fault in a different program, so aborting
1092 	 * the queue manager process does not help.
1093 	 */
1094 	if (recipient->address[0] == 0) {
1095 	    QMGR_REDIRECT(&reply, MAIL_SERVICE_ERROR,
1096 			  "5.1.3 null recipient address");
1097 	}
1098 
1099 	/*
1100 	 * Redirect a forced-to-expire message without defer log to the retry
1101 	 * service, so that its defer log will contain an appropriate reason.
1102 	 * Do not redirect such a message to the error service, because if
1103 	 * that request fails, a defer log would be created with reason
1104 	 * "bounce or trace service failure" which would make no sense. Note
1105 	 * that if the bounce service fails to create a defer log, the
1106 	 * message will be returned as undeliverable anyway, because it is
1107 	 * expired.
1108 	 */
1109 	if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) {
1110 	    QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1111 			  "4.7.0 message is administratively expired");
1112 	}
1113 
1114 	/*
1115 	 * Discard mail to the local double bounce address here, so this
1116 	 * system can run without a local delivery agent. They'd still have
1117 	 * to configure something for mail directed to the local postmaster,
1118 	 * though, but that is an RFC requirement anyway.
1119 	 *
1120 	 * XXX This lookup should be done in the resolver, and the mail should
1121 	 * be directed to a general-purpose null delivery agent.
1122 	 */
1123 	if (reply.flags & RESOLVE_CLASS_LOCAL) {
1124 	    at = strrchr(STR(reply.recipient), '@');
1125 	    len = (at ? (at - STR(reply.recipient))
1126 		   : strlen(STR(reply.recipient)));
1127 	    if (strncasecmp_utf8(STR(reply.recipient),
1128 				 var_double_bounce_sender, len) == 0
1129 		&& !var_double_bounce_sender[len]) {
1130 		status = sent(message->tflags, message->queue_id,
1131 			      QMGR_MSG_STATS(&stats, message), recipient,
1132 			      "none", DSN_SIMPLE(&dsn, "2.0.0",
1133 			"undeliverable postmaster notification discarded"));
1134 		if (status == 0) {
1135 		    deliver_completed(message->fp, recipient->offset);
1136 #if 0
1137 		    /* It's the default verification probe sender address. */
1138 		    msg_warn("%s: undeliverable postmaster notification discarded",
1139 			     message->queue_id);
1140 #endif
1141 		} else
1142 		    message->flags |= status;
1143 		continue;
1144 	    }
1145 	}
1146 
1147 	/*
1148 	 * Optionally defer deliveries over specific transports, unless the
1149 	 * restriction is lifted temporarily.
1150 	 */
1151 	if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 0) {
1152 	    if (defer_xport_argv == 0)
1153 		defer_xport_argv = argv_split(var_defer_xports, CHARS_COMMA_SP);
1154 	    for (cpp = defer_xport_argv->argv; *cpp; cpp++)
1155 		if (strcmp(*cpp, STR(reply.transport)) == 0)
1156 		    break;
1157 	    if (*cpp) {
1158 		QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1159 			      "4.3.2 deferred transport");
1160 	    }
1161 	}
1162 
1163 	/*
1164 	 * Safety: defer excess address verification requests.
1165 	 */
1166 	if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0
1167 	    && qmgr_vrfy_pend_count > var_vrfy_pend_limit)
1168 	    QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1169 			  "4.3.2 Too many address verification requests");
1170 
1171 	/*
1172 	 * Look up or instantiate the proper transport.
1173 	 */
1174 	if (transport == 0 || !STREQ(transport->name, STR(reply.transport))) {
1175 	    if ((transport = qmgr_transport_find(STR(reply.transport))) == 0)
1176 		transport = qmgr_transport_create(STR(reply.transport));
1177 	    queue = 0;
1178 	}
1179 
1180 	/*
1181 	 * This message is being flushed. If need-be unthrottle the
1182 	 * transport.
1183 	 */
1184 	if ((message->qflags & QMGR_FLUSH_EACH) != 0
1185 	    && QMGR_TRANSPORT_THROTTLED(transport))
1186 	    qmgr_transport_unthrottle(transport);
1187 
1188 	/*
1189 	 * This transport is dead. Defer delivery to this recipient.
1190 	 */
1191 	if (QMGR_TRANSPORT_THROTTLED(transport)) {
1192 	    saved_dsn = transport->dsn;
1193 	    if ((transport = qmgr_error_transport(MAIL_SERVICE_RETRY)) != 0) {
1194 		nexthop = qmgr_error_nexthop(saved_dsn);
1195 		vstring_strcpy(reply.nexthop, nexthop);
1196 		myfree(nexthop);
1197 		queue = 0;
1198 	    } else {
1199 		qmgr_defer_recipient(message, recipient, saved_dsn);
1200 		continue;
1201 	    }
1202 	}
1203 
1204 	/*
1205 	 * The nexthop destination provides the default name for the
1206 	 * per-destination queue. When the delivery agent accepts only one
1207 	 * recipient per delivery, give each recipient its own queue, so that
1208 	 * deliveries to different recipients of the same message can happen
1209 	 * in parallel, and so that we can enforce per-recipient concurrency
1210 	 * limits and prevent one recipient from tying up all the delivery
1211 	 * agent resources. We use recipient@nexthop as queue name rather
1212 	 * than the actual recipient domain name, so that one recipient in
1213 	 * multiple equivalent domains cannot evade the per-recipient
1214 	 * concurrency limit. Split the address on the recipient delimiter if
1215 	 * one is defined, so that extended addresses don't get extra
1216 	 * delivery slots.
1217 	 *
1218 	 * Fold the result to lower case so that we don't have multiple queues
1219 	 * for the same name.
1220 	 *
1221 	 * Important! All recipients in a queue must have the same nexthop
1222 	 * value. It is OK to have multiple queues with the same nexthop
1223 	 * value, but only when those queues are named after recipients.
1224 	 *
1225 	 * The single-recipient code below was written for local(8) like
1226 	 * delivery agents, and assumes that all domains that deliver to the
1227 	 * same (transport + nexthop) are aliases for $nexthop. Delivery
1228 	 * concurrency is changed from per-domain into per-recipient, by
1229 	 * changing the queue name from nexthop into localpart@nexthop.
1230 	 *
1231 	 * XXX This assumption is incorrect when different destinations share
1232 	 * the same (transport + nexthop). In reality, such transports are
1233 	 * rarely configured to use single-recipient deliveries. The fix is
1234 	 * to decouple the per-destination recipient limit from the
1235 	 * per-destination concurrency.
1236 	 */
1237 	vstring_strcpy(queue_name, STR(reply.nexthop));
1238 	if (strcmp(transport->name, MAIL_SERVICE_ERROR) != 0
1239 	    && strcmp(transport->name, MAIL_SERVICE_RETRY) != 0
1240 	    && transport->recipient_limit == 1) {
1241 	    /* Copy the recipient localpart. */
1242 	    at = strrchr(STR(reply.recipient), '@');
1243 	    len = (at ? (at - STR(reply.recipient))
1244 		   : strlen(STR(reply.recipient)));
1245 	    vstring_strncpy(queue_name, STR(reply.recipient), len);
1246 	    /* Remove the address extension from the recipient localpart. */
1247 	    if (*var_rcpt_delim && split_addr(STR(queue_name), var_rcpt_delim))
1248 		vstring_truncate(queue_name, strlen(STR(queue_name)));
1249 	    /* Assume the recipient domain is equivalent to nexthop. */
1250 	    vstring_sprintf_append(queue_name, "@%s", STR(reply.nexthop));
1251 	}
1252 	lowercase(STR(queue_name));
1253 
1254 	/*
1255 	 * This transport is alive. Find or instantiate a queue for this
1256 	 * recipient.
1257 	 */
1258 	if (queue == 0 || !STREQ(queue->name, STR(queue_name))) {
1259 	    if ((queue = qmgr_queue_find(transport, STR(queue_name))) == 0)
1260 		queue = qmgr_queue_create(transport, STR(queue_name),
1261 					  STR(reply.nexthop));
1262 	}
1263 
1264 	/*
1265 	 * This message is being flushed. If need-be unthrottle the queue.
1266 	 */
1267 	if ((message->qflags & QMGR_FLUSH_EACH) != 0
1268 	    && QMGR_QUEUE_THROTTLED(queue))
1269 	    qmgr_queue_unthrottle(queue);
1270 
1271 	/*
1272 	 * This queue is dead. Defer delivery to this recipient.
1273 	 */
1274 	if (QMGR_QUEUE_THROTTLED(queue)) {
1275 	    saved_dsn = queue->dsn;
1276 	    if ((queue = qmgr_error_queue(MAIL_SERVICE_RETRY, saved_dsn)) == 0) {
1277 		qmgr_defer_recipient(message, recipient, saved_dsn);
1278 		continue;
1279 	    }
1280 	}
1281 
1282 	/*
1283 	 * This queue is alive. Bind this recipient to this queue instance.
1284 	 */
1285 	recipient->u.queue = queue;
1286     }
1287     resolve_clnt_free(&reply);
1288     vstring_free(queue_name);
1289 }
1290 
1291 /* qmgr_message_assign - assign recipients to specific delivery requests */
1292 
qmgr_message_assign(QMGR_MESSAGE * message)1293 static void qmgr_message_assign(QMGR_MESSAGE *message)
1294 {
1295     RECIPIENT_LIST list = message->rcpt_list;
1296     RECIPIENT *recipient;
1297     QMGR_ENTRY *entry = 0;
1298     QMGR_QUEUE *queue;
1299 
1300     /*
1301      * Try to bundle as many recipients in a delivery request as we can. When
1302      * the recipient resolves to the same site and transport as the previous
1303      * recipient, do not create a new queue entry, just move that recipient
1304      * to the recipient list of the existing queue entry. All this provided
1305      * that we do not exceed the transport-specific limit on the number of
1306      * recipients per transaction. Skip recipients with a dead transport or
1307      * destination.
1308      */
1309 #define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
1310 
1311     for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1312 	if ((queue = recipient->u.queue) != 0) {
1313 	    if (message->single_rcpt || entry == 0 || entry->queue != queue
1314 		|| !LIMIT_OK(entry->queue->transport->recipient_limit,
1315 			     entry->rcpt_list.len)) {
1316 		entry = qmgr_entry_create(queue, message);
1317 	    }
1318 	    recipient_list_add(&entry->rcpt_list, recipient->offset,
1319 			       recipient->dsn_orcpt, recipient->dsn_notify,
1320 			       recipient->orig_addr, recipient->address);
1321 	    qmgr_recipient_count++;
1322 	}
1323     }
1324     recipient_list_free(&message->rcpt_list);
1325     recipient_list_init(&message->rcpt_list, RCPT_LIST_INIT_QUEUE);
1326 }
1327 
1328 /* qmgr_message_free - release memory for in-core message structure */
1329 
qmgr_message_free(QMGR_MESSAGE * message)1330 void    qmgr_message_free(QMGR_MESSAGE *message)
1331 {
1332     if (message->refcount != 0)
1333 	msg_panic("qmgr_message_free: reference len: %d", message->refcount);
1334     if (message->fp)
1335 	msg_panic("qmgr_message_free: queue file is open");
1336     myfree(message->queue_id);
1337     myfree(message->queue_name);
1338     if (message->dsn_envid)
1339 	myfree(message->dsn_envid);
1340     if (message->encoding)
1341 	myfree(message->encoding);
1342     if (message->sender)
1343 	myfree(message->sender);
1344     if (message->verp_delims)
1345 	myfree(message->verp_delims);
1346     if (message->filter_xport)
1347 	myfree(message->filter_xport);
1348     if (message->inspect_xport)
1349 	myfree(message->inspect_xport);
1350     if (message->redirect_addr)
1351 	myfree(message->redirect_addr);
1352     if (message->client_name)
1353 	myfree(message->client_name);
1354     if (message->client_addr)
1355 	myfree(message->client_addr);
1356     if (message->client_port)
1357 	myfree(message->client_port);
1358     if (message->client_proto)
1359 	myfree(message->client_proto);
1360     if (message->client_helo)
1361 	myfree(message->client_helo);
1362     if (message->sasl_method)
1363 	myfree(message->sasl_method);
1364     if (message->sasl_username)
1365 	myfree(message->sasl_username);
1366     if (message->sasl_sender)
1367 	myfree(message->sasl_sender);
1368     if (message->log_ident)
1369 	myfree(message->log_ident);
1370     if (message->rewrite_context)
1371 	myfree(message->rewrite_context);
1372     recipient_list_free(&message->rcpt_list);
1373     qmgr_message_count--;
1374     if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
1375 	qmgr_vrfy_pend_count--;
1376     myfree((void *) message);
1377 }
1378 
1379 /* qmgr_message_alloc - create in-core message structure */
1380 
qmgr_message_alloc(const char * queue_name,const char * queue_id,int qflags,mode_t mode)1381 QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
1382 				         int qflags, mode_t mode)
1383 {
1384     const char *myname = "qmgr_message_alloc";
1385     QMGR_MESSAGE *message;
1386     struct stat st;
1387 
1388     if (msg_verbose)
1389 	msg_info("%s: %s %s", myname, queue_name, queue_id);
1390 
1391     /*
1392      * Create an in-core message structure.
1393      */
1394     message = qmgr_message_create(queue_name, queue_id, qflags);
1395 
1396     /*
1397      * Extract message envelope information: time of arrival, sender address,
1398      * recipient addresses. Skip files with malformed envelope information.
1399      */
1400 #define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
1401 
1402     if (qmgr_message_open(message) < 0) {
1403 	qmgr_message_free(message);
1404 	return (0);
1405     }
1406     if (myflock(vstream_fileno(message->fp), INTERNAL_LOCK, QMGR_LOCK_MODE) < 0) {
1407 	msg_info("%s: skipped, still being delivered", queue_id);
1408 	qmgr_message_close(message);
1409 	qmgr_message_free(message);
1410 	return (QMGR_MESSAGE_LOCKED);
1411     }
1412     if (qmgr_message_read(message) < 0) {
1413 	qmgr_message_close(message);
1414 	qmgr_message_free(message);
1415 	return (0);
1416     } else {
1417 
1418 	/*
1419 	 * We have validated the queue file content, so it is safe to modify
1420 	 * the file properties now.
1421 	 */
1422 	if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
1423 	    msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
1424 
1425 	/*
1426 	 * If this message is forced to expire, use the existing defer
1427 	 * logfile records and do not assign any deliveries, leaving the
1428 	 * refcount at zero. If this message is forced to expire, but no
1429 	 * defer logfile records are available, assign deliveries to the
1430 	 * retry transport so that the sender will still find out what
1431 	 * recipients are affected and why. Either way, do not assign normal
1432 	 * deliveries because that would be undesirable especially with mail
1433 	 * that was expired in the 'hold' queue.
1434 	 */
1435 	if ((message->qflags & QMGR_FORCE_EXPIRE) != 0
1436 	    && stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_DEFER,
1437 				    queue_id), &st) == 0 && st.st_size > 0) {
1438 	    /* Use this defer log; don't assign deliveries (refcount == 0). */
1439 	    message->flags = 1;			/* simplify downstream code */
1440 	    qmgr_message_close(message);
1441 	    return (message);
1442 	}
1443 
1444 	/*
1445 	 * Reset the defer log. This code should not be here, but we must
1446 	 * reset the defer log *after* acquiring the exclusive lock on the
1447 	 * queue file and *before* resolving new recipients. Since all those
1448 	 * operations are encapsulated so nicely by this routine, the defer
1449 	 * log reset has to be done here as well.
1450 	 *
1451 	 * Note: it is safe to remove the defer logfile from a previous queue
1452 	 * run of this queue file, because the defer log contains information
1453 	 * about recipients that still exist in this queue file.
1454 	 */
1455 	if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
1456 	    msg_fatal("%s: %s: remove %s %s: %m", myname,
1457 		      queue_id, MAIL_QUEUE_DEFER, queue_id);
1458 	qmgr_message_sort(message);
1459 	qmgr_message_resolve(message);
1460 	qmgr_message_sort(message);
1461 	qmgr_message_assign(message);
1462 	qmgr_message_close(message);
1463 	return (message);
1464     }
1465 }
1466 
1467 /* qmgr_message_realloc - refresh in-core message structure */
1468 
qmgr_message_realloc(QMGR_MESSAGE * message)1469 QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *message)
1470 {
1471     const char *myname = "qmgr_message_realloc";
1472 
1473     /*
1474      * Sanity checks.
1475      */
1476     if (message->rcpt_offset <= 0)
1477 	msg_panic("%s: invalid offset: %ld", myname, message->rcpt_offset);
1478     if (msg_verbose)
1479 	msg_info("%s: %s %s offset %ld", myname, message->queue_name,
1480 		 message->queue_id, message->rcpt_offset);
1481 
1482     /*
1483      * Extract recipient addresses. Skip files with malformed envelope
1484      * information.
1485      */
1486     if (qmgr_message_open(message) < 0)
1487 	return (0);
1488     if (qmgr_message_read(message) < 0) {
1489 	qmgr_message_close(message);
1490 	return (0);
1491     } else {
1492 	qmgr_message_sort(message);
1493 	qmgr_message_resolve(message);
1494 	qmgr_message_sort(message);
1495 	qmgr_message_assign(message);
1496 	qmgr_message_close(message);
1497 	return (message);
1498     }
1499 }
1500