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