Postfix3.3.1
qmgr_message.c
[詳解]
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 
153 
154 /* qmgr_message_create - create in-core message structure */
155 
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));
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;
202  return (message);
203 }
204 
205 /* qmgr_message_close - close queue file */
206 
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 
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 
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 
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) {
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));
446  /* We already examined all non-recipient records. */
447  break;
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. */
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  */
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)
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)
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)
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 
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
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 
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 
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 
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 
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) {
972  "4.3.0 address resolver failure");
973  return (0);
974  } else if (reply->flags & RESOLVE_FLAG_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 
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;
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) {
1077  "5.1.3 null recipient address");
1078  }
1079 
1080  /*
1081  * Discard mail to the local double bounce address here, so this
1082  * system can run without a local delivery agent. They'd still have
1083  * to configure something for mail directed to the local postmaster,
1084  * though, but that is an RFC requirement anyway.
1085  *
1086  * XXX This lookup should be done in the resolver, and the mail should
1087  * be directed to a general-purpose null delivery agent.
1088  */
1089  if (reply.flags & RESOLVE_CLASS_LOCAL) {
1090  at = strrchr(STR(reply.recipient), '@');
1091  len = (at ? (at - STR(reply.recipient))
1092  : strlen(STR(reply.recipient)));
1093  if (strncasecmp_utf8(STR(reply.recipient),
1094  var_double_bounce_sender, len) == 0
1095  && !var_double_bounce_sender[len]) {
1096  status = sent(message->tflags, message->queue_id,
1097  QMGR_MSG_STATS(&stats, message), recipient,
1098  "none", DSN_SIMPLE(&dsn, "2.0.0",
1099  "undeliverable postmaster notification discarded"));
1100  if (status == 0) {
1101  deliver_completed(message->fp, recipient->offset);
1102 #if 0
1103  /* It's the default verification probe sender address. */
1104  msg_warn("%s: undeliverable postmaster notification discarded",
1105  message->queue_id);
1106 #endif
1107  } else
1108  message->flags |= status;
1109  continue;
1110  }
1111  }
1112 
1113  /*
1114  * Optionally defer deliveries over specific transports, unless the
1115  * restriction is lifted temporarily.
1116  */
1117  if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 0) {
1118  if (defer_xport_argv == 0)
1119  defer_xport_argv = argv_split(var_defer_xports, CHARS_COMMA_SP);
1120  for (cpp = defer_xport_argv->argv; *cpp; cpp++)
1121  if (strcmp(*cpp, STR(reply.transport)) == 0)
1122  break;
1123  if (*cpp) {
1125  "4.3.2 deferred transport");
1126  }
1127  }
1128 
1129  /*
1130  * Safety: defer excess address verification requests.
1131  */
1132  if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0
1135  "4.3.2 Too many address verification requests");
1136 
1137  /*
1138  * Look up or instantiate the proper transport.
1139  */
1140  if (transport == 0 || !STREQ(transport->name, STR(reply.transport))) {
1141  if ((transport = qmgr_transport_find(STR(reply.transport))) == 0)
1142  transport = qmgr_transport_create(STR(reply.transport));
1143  queue = 0;
1144  }
1145 
1146  /*
1147  * This message is being flushed. If need-be unthrottle the
1148  * transport.
1149  */
1150  if ((message->qflags & QMGR_FLUSH_EACH) != 0
1151  && QMGR_TRANSPORT_THROTTLED(transport))
1152  qmgr_transport_unthrottle(transport);
1153 
1154  /*
1155  * This transport is dead. Defer delivery to this recipient.
1156  */
1157  if (QMGR_TRANSPORT_THROTTLED(transport)) {
1158  saved_dsn = transport->dsn;
1159  if ((transport = qmgr_error_transport(MAIL_SERVICE_RETRY)) != 0) {
1160  nexthop = qmgr_error_nexthop(saved_dsn);
1161  vstring_strcpy(reply.nexthop, nexthop);
1162  myfree(nexthop);
1163  queue = 0;
1164  } else {
1165  qmgr_defer_recipient(message, recipient, saved_dsn);
1166  continue;
1167  }
1168  }
1169 
1170  /*
1171  * The nexthop destination provides the default name for the
1172  * per-destination queue. When the delivery agent accepts only one
1173  * recipient per delivery, give each recipient its own queue, so that
1174  * deliveries to different recipients of the same message can happen
1175  * in parallel, and so that we can enforce per-recipient concurrency
1176  * limits and prevent one recipient from tying up all the delivery
1177  * agent resources. We use recipient@nexthop as queue name rather
1178  * than the actual recipient domain name, so that one recipient in
1179  * multiple equivalent domains cannot evade the per-recipient
1180  * concurrency limit. Split the address on the recipient delimiter if
1181  * one is defined, so that extended addresses don't get extra
1182  * delivery slots.
1183  *
1184  * Fold the result to lower case so that we don't have multiple queues
1185  * for the same name.
1186  *
1187  * Important! All recipients in a queue must have the same nexthop
1188  * value. It is OK to have multiple queues with the same nexthop
1189  * value, but only when those queues are named after recipients.
1190  *
1191  * The single-recipient code below was written for local(8) like
1192  * delivery agents, and assumes that all domains that deliver to the
1193  * same (transport + nexthop) are aliases for $nexthop. Delivery
1194  * concurrency is changed from per-domain into per-recipient, by
1195  * changing the queue name from nexthop into localpart@nexthop.
1196  *
1197  * XXX This assumption is incorrect when different destinations share
1198  * the same (transport + nexthop). In reality, such transports are
1199  * rarely configured to use single-recipient deliveries. The fix is
1200  * to decouple the per-destination recipient limit from the
1201  * per-destination concurrency.
1202  */
1203  vstring_strcpy(queue_name, STR(reply.nexthop));
1204  if (strcmp(transport->name, MAIL_SERVICE_ERROR) != 0
1205  && strcmp(transport->name, MAIL_SERVICE_RETRY) != 0
1206  && transport->recipient_limit == 1) {
1207  /* Copy the recipient localpart. */
1208  at = strrchr(STR(reply.recipient), '@');
1209  len = (at ? (at - STR(reply.recipient))
1210  : strlen(STR(reply.recipient)));
1211  vstring_strncpy(queue_name, STR(reply.recipient), len);
1212  /* Remove the address extension from the recipient localpart. */
1213  if (*var_rcpt_delim && split_addr(STR(queue_name), var_rcpt_delim))
1214  vstring_truncate(queue_name, strlen(STR(queue_name)));
1215  /* Assume the recipient domain is equivalent to nexthop. */
1216  vstring_sprintf_append(queue_name, "@%s", STR(reply.nexthop));
1217  }
1218  lowercase(STR(queue_name));
1219 
1220  /*
1221  * This transport is alive. Find or instantiate a queue for this
1222  * recipient.
1223  */
1224  if (queue == 0 || !STREQ(queue->name, STR(queue_name))) {
1225  if ((queue = qmgr_queue_find(transport, STR(queue_name))) == 0)
1226  queue = qmgr_queue_create(transport, STR(queue_name),
1227  STR(reply.nexthop));
1228  }
1229 
1230  /*
1231  * This message is being flushed. If need-be unthrottle the queue.
1232  */
1233  if ((message->qflags & QMGR_FLUSH_EACH) != 0
1234  && QMGR_QUEUE_THROTTLED(queue))
1235  qmgr_queue_unthrottle(queue);
1236 
1237  /*
1238  * This queue is dead. Defer delivery to this recipient.
1239  */
1240  if (QMGR_QUEUE_THROTTLED(queue)) {
1241  saved_dsn = queue->dsn;
1242  if ((queue = qmgr_error_queue(MAIL_SERVICE_RETRY, saved_dsn)) == 0) {
1243  qmgr_defer_recipient(message, recipient, saved_dsn);
1244  continue;
1245  }
1246  }
1247 
1248  /*
1249  * This queue is alive. Bind this recipient to this queue instance.
1250  */
1251  recipient->u.queue = queue;
1252  }
1253  resolve_clnt_free(&reply);
1254  vstring_free(queue_name);
1255 }
1256 
1257 /* qmgr_message_assign - assign recipients to specific delivery requests */
1258 
1259 static void qmgr_message_assign(QMGR_MESSAGE *message)
1260 {
1261  RECIPIENT_LIST list = message->rcpt_list;
1262  RECIPIENT *recipient;
1263  QMGR_ENTRY *entry = 0;
1264  QMGR_QUEUE *queue;
1265 
1266  /*
1267  * Try to bundle as many recipients in a delivery request as we can. When
1268  * the recipient resolves to the same site and transport as the previous
1269  * recipient, do not create a new queue entry, just move that recipient
1270  * to the recipient list of the existing queue entry. All this provided
1271  * that we do not exceed the transport-specific limit on the number of
1272  * recipients per transaction. Skip recipients with a dead transport or
1273  * destination.
1274  */
1275 #define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
1276 
1277  for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1278  if ((queue = recipient->u.queue) != 0) {
1279  if (message->single_rcpt || entry == 0 || entry->queue != queue
1280  || !LIMIT_OK(entry->queue->transport->recipient_limit,
1281  entry->rcpt_list.len)) {
1282  entry = qmgr_entry_create(queue, message);
1283  }
1284  recipient_list_add(&entry->rcpt_list, recipient->offset,
1285  recipient->dsn_orcpt, recipient->dsn_notify,
1286  recipient->orig_addr, recipient->address);
1288  }
1289  }
1290  recipient_list_free(&message->rcpt_list);
1292 }
1293 
1294 /* qmgr_message_free - release memory for in-core message structure */
1295 
1297 {
1298  if (message->refcount != 0)
1299  msg_panic("qmgr_message_free: reference len: %d", message->refcount);
1300  if (message->fp)
1301  msg_panic("qmgr_message_free: queue file is open");
1302  myfree(message->queue_id);
1303  myfree(message->queue_name);
1304  if (message->dsn_envid)
1305  myfree(message->dsn_envid);
1306  if (message->encoding)
1307  myfree(message->encoding);
1308  if (message->sender)
1309  myfree(message->sender);
1310  if (message->verp_delims)
1311  myfree(message->verp_delims);
1312  if (message->filter_xport)
1313  myfree(message->filter_xport);
1314  if (message->inspect_xport)
1315  myfree(message->inspect_xport);
1316  if (message->redirect_addr)
1317  myfree(message->redirect_addr);
1318  if (message->client_name)
1319  myfree(message->client_name);
1320  if (message->client_addr)
1321  myfree(message->client_addr);
1322  if (message->client_port)
1323  myfree(message->client_port);
1324  if (message->client_proto)
1325  myfree(message->client_proto);
1326  if (message->client_helo)
1327  myfree(message->client_helo);
1328  if (message->sasl_method)
1329  myfree(message->sasl_method);
1330  if (message->sasl_username)
1331  myfree(message->sasl_username);
1332  if (message->sasl_sender)
1333  myfree(message->sasl_sender);
1334  if (message->log_ident)
1335  myfree(message->log_ident);
1336  if (message->rewrite_context)
1337  myfree(message->rewrite_context);
1338  recipient_list_free(&message->rcpt_list);
1340  if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
1342  myfree((void *) message);
1343 }
1344 
1345 /* qmgr_message_alloc - create in-core message structure */
1346 
1347 QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
1348  int qflags, mode_t mode)
1349 {
1350  const char *myname = "qmgr_message_alloc";
1351  QMGR_MESSAGE *message;
1352 
1353  if (msg_verbose)
1354  msg_info("%s: %s %s", myname, queue_name, queue_id);
1355 
1356  /*
1357  * Create an in-core message structure.
1358  */
1359  message = qmgr_message_create(queue_name, queue_id, qflags);
1360 
1361  /*
1362  * Extract message envelope information: time of arrival, sender address,
1363  * recipient addresses. Skip files with malformed envelope information.
1364  */
1365 #define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
1366 
1367  if (qmgr_message_open(message) < 0) {
1368  qmgr_message_free(message);
1369  return (0);
1370  }
1371  if (myflock(vstream_fileno(message->fp), INTERNAL_LOCK, QMGR_LOCK_MODE) < 0) {
1372  msg_info("%s: skipped, still being delivered", queue_id);
1373  qmgr_message_close(message);
1374  qmgr_message_free(message);
1375  return (QMGR_MESSAGE_LOCKED);
1376  }
1377  if (qmgr_message_read(message) < 0) {
1378  qmgr_message_close(message);
1379  qmgr_message_free(message);
1380  return (0);
1381  } else {
1382 
1383  /*
1384  * We have validated the queue file content, so it is safe to modify
1385  * the file properties now.
1386  */
1387  if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
1388  msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
1389 
1390  /*
1391  * Reset the defer log. This code should not be here, but we must
1392  * reset the defer log *after* acquiring the exclusive lock on the
1393  * queue file and *before* resolving new recipients. Since all those
1394  * operations are encapsulated so nicely by this routine, the defer
1395  * log reset has to be done here as well.
1396  *
1397  * Note: it is safe to remove the defer logfile from a previous queue
1398  * run of this queue file, because the defer log contains information
1399  * about recipients that still exist in this queue file.
1400  */
1401  if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
1402  msg_fatal("%s: %s: remove %s %s: %m", myname,
1403  queue_id, MAIL_QUEUE_DEFER, queue_id);
1404  qmgr_message_sort(message);
1405  qmgr_message_resolve(message);
1406  qmgr_message_sort(message);
1407  qmgr_message_assign(message);
1408  qmgr_message_close(message);
1409  return (message);
1410  }
1411 }
1412 
1413 /* qmgr_message_realloc - refresh in-core message structure */
1414 
1416 {
1417  const char *myname = "qmgr_message_realloc";
1418 
1419  /*
1420  * Sanity checks.
1421  */
1422  if (message->rcpt_offset <= 0)
1423  msg_panic("%s: invalid offset: %ld", myname, message->rcpt_offset);
1424  if (msg_verbose)
1425  msg_info("%s: %s %s offset %ld", myname, message->queue_name,
1426  message->queue_id, message->rcpt_offset);
1427 
1428  /*
1429  * Extract recipient addresses. Skip files with malformed envelope
1430  * information.
1431  */
1432  if (qmgr_message_open(message) < 0)
1433  return (0);
1434  if (qmgr_message_read(message) < 0) {
1435  qmgr_message_close(message);
1436  return (0);
1437  } else {
1438  qmgr_message_sort(message);
1439  qmgr_message_resolve(message);
1440  qmgr_message_sort(message);
1441  qmgr_message_assign(message);
1442  qmgr_message_close(message);
1443  return (message);
1444  }
1445 }
#define LIMIT_OK(limit, count)
int msg_verbose
Definition: msg.c:177
#define REC_TYPE_FILT
Definition: rec_type.h:42
void qmgr_message_free(QMGR_MESSAGE *message)
const char * orig_addr
QMGR_QUEUE * qmgr_error_queue(const char *, DSN *)
Definition: qmgr_error.c:85
#define MAIL_ATTR_ACT_HELO_NAME
Definition: mail_proto.h:219
#define RESOLVE_FLAG_FAIL
Definition: resolve_clnt.h:28
int rec_put_type(VSTREAM *stream, int type, off_t offset)
Definition: record.c:175
void myfree(void *ptr)
Definition: mymalloc.c:207
#define QMGR_READ_FLAG_MIXED_RCPT_OTHER
Definition: qmgr_user.h:25
int qmgr_message_count
Definition: qmgr_message.c:150
int var_vrfy_pend_limit
Definition: qmgr.c:437
#define MAIL_ATTR_TRACE_FLAGS
Definition: mail_proto.h:149
char * queue_id
Definition: qmgr.h:298
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define MAIL_ATTR_ENCODING
Definition: mail_proto.h:202
int smtputf8
Definition: qmgr.h:303
char * client_addr
Definition: qmgr.h:312
#define MAIL_SERVICE_ERROR
Definition: mail_proto.h:52
char * var_defer_xports
Definition: qmgr.c:421
const char * address
#define DSN_SIMPLE(dsn, _status, _reason)
Definition: dsn.h:41
QMGR_QUEUE * queue
Definition: qmgr.h:266
Definition: argv.h:17
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
char * client_helo
Definition: qmgr.h:315
#define vstring_str(vp)
Definition: vstring.h:71
off_t vstream_ftell(VSTREAM *stream)
Definition: vstream.c:1157
long data_size
Definition: qmgr.h:308
QMGR_TRANSPORT * qmgr_transport_create(const char *)
struct timeval active_time
Definition: qmgr.h:293
void deliver_completed(VSTREAM *stream, long offset)
VSTRING * rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *result)
Definition: rewrite_clnt.c:175
int rec_goto(VSTREAM *stream, const char *buf)
Definition: record.c:326
#define REC_TYPE_VERP
Definition: rec_type.h:68
char * sasl_sender
Definition: qmgr.h:318
#define REC_TYPE_SIZE
Definition: rec_type.h:37
QMGR_TRANSPORT * qmgr_error_transport(const char *)
Definition: qmgr_error.c:65
#define REC_FLAG_NONE
Definition: record.h:45
char * redirect_addr
Definition: qmgr.h:307
char ** argv
Definition: argv.h:20
int qmgr_recipient_count
Definition: qmgr_message.c:151
#define MAIL_ATTR_RWR_CONTEXT
Definition: mail_proto.h:163
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
Definition: vstring.c:415
QMGR_MESSAGE * qmgr_message_alloc(const char *queue_name, const char *queue_id, int qflags, mode_t mode)
void resolve_clnt_free(RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:287
#define split_addr
Definition: split_addr.h:20
#define MAIL_ATTR_RWR_LOCAL
Definition: mail_proto.h:166
#define MAIL_ATTR_ACT_CLIENT_ADDR
Definition: mail_proto.h:216
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
#define QMGR_TRANSPORT_THROTTLED(t)
Definition: qmgr.h:181
#define REC_TYPE_DSN_ENVID
Definition: rec_type.h:71
QMGR_QUEUE * qmgr_queue_create(QMGR_TRANSPORT *, const char *, const char *)
Definition: qmgr_queue.c:407
#define MAIL_ATTR_SASL_METHOD
Definition: mail_proto.h:156
#define REC_TYPE_FROM
Definition: rec_type.h:43
#define FILTER_WITHOUT_NEXTHOP(filter, next)
#define REC_TYPE_END
Definition: rec_type.h:77
#define strcasecmp_utf8(s1, s2)
Definition: stringops.h:75
#define DSN_RET_OK(v)
Definition: dsn_mask.h:24
int alldig(const char *string)
Definition: alldig.c:38
QMGR_MESSAGE * qmgr_message_realloc(QMGR_MESSAGE *message)
char * log_ident
Definition: qmgr.h:319
#define MAIL_ATTR_LOG_HELO_NAME
Definition: mail_proto.h:210
const char * split_nameval(char *buf, char **name, char **value)
Definition: split_nameval.c:61
#define REC_TYPE_DSN_NOTIFY
Definition: rec_type.h:73
#define MAIL_ATTR_LOG_PROTO_NAME
Definition: mail_proto.h:211
#define DEL_REQ_TRACE_FLAGS(f)
#define QMGR_FLUSH_EACH
Definition: qmgr.h:401
char * client_port
Definition: qmgr.h:313
#define REC_TYPE_KILL
Definition: rec_type.h:50
#define QMGR_READ_FLAG_SEEN_ALL_NON_RCPT
Definition: qmgr.h:327
int var_qmgr_rcpt_limit
Definition: qmgr.c:416
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
#define QMGR_LOCK_MODE
long cont_length
Definition: qmgr.h:309
char * var_rcpt_delim
Definition: mail_params.c:274
long warn_offset
Definition: qmgr.h:294
#define RESOLVE_CLASS_LOCAL
Definition: resolve_clnt.h:30
int rflags
Definition: qmgr.h:287
void qmgr_queue_unthrottle(QMGR_QUEUE *)
Definition: qmgr_queue.c:198
#define REC_TYPE_RDR
Definition: rec_type.h:52
#define REC_TYPE_DSN_RET
Definition: rec_type.h:70
int rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags)
Definition: record.c:236
long tflags_offset
Definition: qmgr.h:286
#define REC_TYPE_DRCP
Definition: rec_type.h:47
int flags
Definition: qmgr.h:283
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
struct timeval arrival_time
Definition: qmgr.h:291
#define MAIL_ATTR_ACT_CLIENT_PORT
Definition: mail_proto.h:217
#define MAIL_ATTR_ENC_NONE
Definition: mail_proto.h:205
char * queue_name
Definition: qmgr.h:297
#define RESOLVE_FLAG_ERROR
Definition: resolve_clnt.h:27
#define REC_TYPE_INSP
Definition: rec_type.h:41
QMGR_TRANSPORT * qmgr_transport_find(const char *)
#define REC_TYPE_DSN_ORCPT
Definition: rec_type.h:72
void resolve_clnt_init(RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:147
#define RCPT_WITHOUT_DOMAIN(rcpt, next)
char * name
Definition: qmgr.h:200
char * var_double_bounce_sender
Definition: mail_params.c:262
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
void opened(const char *queue_id, const char *sender, long size, int nrcpt, const char *fmt,...)
Definition: opened.c:64
char * rewrite_context
Definition: qmgr.h:320
#define REC_TYPE_RCPT
Definition: rec_type.h:45
#define STR
VSTREAM * mail_queue_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
Definition: mail_queue.c:424
#define MAIL_ATTR_SASL_SENDER
Definition: mail_proto.h:158
#define REC_TYPE_MESG
Definition: rec_type.h:56
QMGR_QUEUE * qmgr_queue_find(QMGR_TRANSPORT *, const char *)
Definition: qmgr_queue.c:439
#define REC_TYPE_PTR
Definition: rec_type.h:67
QMGR_ENTRY * qmgr_entry_create(QMGR_QUEUE *, QMGR_MESSAGE *)
Definition: qmgr_entry.c:304
void msg_warn(const char *fmt,...)
Definition: msg.c:215
char * sender
Definition: qmgr.h:300
#define MAIL_ATTR_ACT_CLIENT_NAME
Definition: mail_proto.h:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int myflock(int fd, int lock_style, int operation)
Definition: myflock.c:87
int recipient_limit
Definition: qmgr.h:158
#define RCPT_LIST_INIT_QUEUE
time_t warn_time
Definition: qmgr.h:295
long rcpt_offset
Definition: qmgr.h:310
#define FUDGE(x)
#define REC_TYPE_WARN_ARG(tv)
Definition: rec_type.h:141
#define MAIL_ATTR_LOG_IDENT
Definition: mail_proto.h:162
#define MAIL_ATTR_LOG_CLIENT_ADDR
Definition: mail_proto.h:208
#define REC_TYPE_WARN
Definition: rec_type.h:48
char * lowercase(char *string)
Definition: lowercase.c:34
int rec_attr_map(const char *attr_name)
Definition: rec_attr_map.c:39
char * name
Definition: qmgr.h:155
RECIPIENT_LIST rcpt_list
Definition: qmgr.h:321
#define REC_TYPE_WARN_SCAN(cp, tv)
Definition: rec_type.h:142
const char * verp_delims_verify(const char *delims)
Definition: verp_sender.c:104
int qflags
Definition: qmgr.h:284
char * dsn_envid
Definition: qmgr.h:301
#define QMGR_MSG_STATS(stats, message)
Definition: qmgr.h:341
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
char * sasl_username
Definition: qmgr.h:317
#define QMGR_FLUSH_DFXP
Definition: qmgr.h:400
#define STREQ(x, y)
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
Definition: vstream.c:1093
#define REC_TYPE_WARN_FORMAT
Definition: rec_type.h:140
VSTRING * recipient
Definition: resolve_clnt.h:46
#define CHARS_COMMA_SP
Definition: sys_defs.h:1761
void qmgr_defer_recipient(QMGR_MESSAGE *, RECIPIENT *, DSN *)
Definition: qmgr_defer.c:147
QMGR_TRANSPORT * transport
Definition: qmgr.h:208
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
void qmgr_transport_unthrottle(QMGR_TRANSPORT *)
char * var_def_filter_nexthop
Definition: qmgr.c:433
#define MAIL_SERVICE_RETRY
Definition: mail_proto.h:53
int mail_queue_remove(const char *queue_name, const char *queue_id)
Definition: mail_queue.c:274
void recipient_list_init(RECIPIENT_LIST *list, int variant)
ARGV * argv_split(const char *, const char *)
Definition: argv_split.c:63
void qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
Definition: qmgr_message.c:868
DSN * dsn
Definition: qmgr.h:162
#define MAIL_ATTR_SASL_USERNAME
Definition: mail_proto.h:157
char * sasl_method
Definition: qmgr.h:316
#define REWRITE_CANON
Definition: rewrite_clnt.h:28
#define QMGR_READ_FLAG_DEFAULT
Definition: qmgr_user.h:41
#define MAIL_QUEUE_DEFER
Definition: mail_queue.h:34
#define RECIPIENT_UPDATE(ptr, new)
char * client_proto
Definition: qmgr.h:314
#define QMGR_READ_FLAG_USER
Definition: qmgr_user.h:33
long data_offset
Definition: qmgr.h:296
const char * dsn_orcpt
Definition: dsn.h:17
#define resolve_clnt_verify_from(f, a, r)
Definition: resolve_clnt.h:58
#define strncasecmp_utf8(s1, s2, l)
Definition: stringops.h:77
time_t create_time
Definition: qmgr.h:292
int qmgr_vrfy_pend_count
Definition: qmgr_message.c:152
#define MAIL_ATTR_LOG_CLIENT_NAME
Definition: mail_proto.h:207
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
void recipient_list_free(RECIPIENT_LIST *list)
#define DSN_NOTIFY_OK(v)
Definition: dsn_mask.h:63
char * filter_xport
Definition: qmgr.h:305
RECIPIENT * info
char * client_name
Definition: qmgr.h:311
int single_rcpt
Definition: qmgr.h:290
char * qmgr_error_nexthop(DSN *)
Definition: qmgr_error.c:115
VSTRING * nexthop
Definition: resolve_clnt.h:45
char * inspect_xport
Definition: qmgr.h:306
void qmgr_message_update_warn(QMGR_MESSAGE *message)
Definition: qmgr_message.c:850
#define QMGR_REDIRECT(rp, tp, np)
VSTRING * transport
Definition: resolve_clnt.h:44
#define REC_TYPE_ATTR
Definition: rec_type.h:49
#define vstream_fileno(vp)
Definition: vstream.h:115
VSTREAM * fp
Definition: qmgr.h:288
#define resolve_clnt_query_from(f, a, r)
Definition: resolve_clnt.h:56
union RECIPIENT::@1 u
struct QMGR_QUEUE * queue
RECIPIENT_LIST rcpt_list
Definition: qmgr.h:265
int tflags
Definition: qmgr.h:285
#define QMGR_MESSAGE_LOCKED
Definition: qmgr.h:329
#define REC_TYPE_ERROR
Definition: rec_type.h:24
#define REC_TYPE_TIME
Definition: rec_type.h:38
#define MAIL_ATTR_ACT_PROTO_NAME
Definition: mail_proto.h:220
char * var_myhostname
Definition: mail_params.c:223
#define REC_TYPE_CTIME
Definition: rec_type.h:39
int sent(int flags, const char *id, MSG_STATS *stats, RECIPIENT *recipient, const char *relay, DSN *dsn)
Definition: sent.c:95
char * verp_delims
Definition: qmgr.h:304
#define REC_TYPE_DONE
Definition: rec_type.h:44
#define rec_get(fp, buf, limit)
Definition: record.h:56
void recipient_list_add(RECIPIENT_LIST *list, long offset, const char *dsn_orcpt, int dsn_notify, const char *orig_rcpt, const char *rcpt)
#define REC_TYPE_ORCP
Definition: rec_type.h:46
int rec_fprintf(VSTREAM *stream, int type, const char *format,...)
Definition: record.c:391
VSTRING * vstring_strncpy(VSTRING *vp, const char *src, ssize_t len)
Definition: vstring.c:445
#define REC_TYPE_TIME_SCAN(cp, tv)
Definition: rec_type.h:150
#define DEL_REQ_FLAG_REC_DLY_SENT
DSN * dsn
Definition: qmgr.h:212
int dsn_ret
Definition: qmgr.h:302
#define DEL_REQ_FLAG_MTA_VRFY
int var_dsn_delay_cleared
Definition: qmgr.c:436
#define MAIL_ATTR_LOG_CLIENT_PORT
Definition: mail_proto.h:209
int refcount
Definition: qmgr.h:289
#define QMGR_QUEUE_THROTTLED(q)
Definition: qmgr.h:245
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
char * encoding
Definition: qmgr.h:299
#define DEL_REQ_TRACE_ONLY_MASK
#define DEL_REQ_FLAG_RECORD
void msg_info(const char *fmt,...)
Definition: msg.c:199