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