1 /* $NetBSD: verify.c,v 1.1.1.3 2011/05/11 09:11:28 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* verify 8 6 /* SUMMARY 7 /* Postfix address verification server 8 /* SYNOPSIS 9 /* \fBverify\fR [generic Postfix daemon options] 10 /* DESCRIPTION 11 /* The \fBverify\fR(8) address verification server maintains a record 12 /* of what recipient addresses are known to be deliverable or 13 /* undeliverable. 14 /* 15 /* Addresses are verified by injecting probe messages into the 16 /* Postfix queue. Probe messages are run through all the routing 17 /* and rewriting machinery except for final delivery, and are 18 /* discarded rather than being deferred or bounced. 19 /* 20 /* Address verification relies on the answer from the nearest 21 /* MTA for the specified address, and will therefore not detect 22 /* all undeliverable addresses. 23 /* 24 /* The \fBverify\fR(8) server is designed to run under control 25 /* by the Postfix 26 /* master server. It maintains an optional persistent database. 27 /* To avoid being interrupted by "postfix stop" in the middle 28 /* of a database update, the process runs in a separate process 29 /* group. 30 /* 31 /* The \fBverify\fR(8) server implements the following requests: 32 /* .IP "\fBupdate\fI address status text\fR" 33 /* Update the status and text of the specified address. 34 /* .IP "\fBquery\fI address\fR" 35 /* Look up the \fIstatus\fR and \fItext\fR for the specified 36 /* \fIaddress\fR. 37 /* If the status is unknown, a probe is sent and an "in progress" 38 /* status is returned. 39 /* SECURITY 40 /* .ad 41 /* .fi 42 /* The address verification server is not security-sensitive. It does 43 /* not talk to the network, and it does not talk to local users. 44 /* The verify server can run chrooted at fixed low privilege. 45 /* 46 /* The address verification server can be coerced to store 47 /* unlimited amounts of garbage. Limiting the cache expiry 48 /* time 49 /* trades one problem (disk space exhaustion) for another 50 /* one (poor response time to client requests). 51 /* 52 /* With Postfix version 2.5 and later, the \fBverify\fR(8) 53 /* server no longer uses root privileges when opening the 54 /* \fBaddress_verify_map\fR cache file. The file should now 55 /* be stored under the Postfix-owned \fBdata_directory\fR. As 56 /* a migration aid, an attempt to open a cache file under a 57 /* non-Postfix directory is redirected to the Postfix-owned 58 /* \fBdata_directory\fR, and a warning is logged. 59 /* DIAGNOSTICS 60 /* Problems and transactions are logged to \fBsyslogd\fR(8). 61 /* BUGS 62 /* Address verification probe messages add additional traffic 63 /* to the mail queue. 64 /* Recipient verification may cause an increased load on 65 /* down-stream servers in the case of a dictionary attack or 66 /* a flood of backscatter bounces. 67 /* Sender address verification may cause your site to be 68 /* blacklisted by some providers. 69 /* 70 /* If the persistent database ever gets corrupted then the world 71 /* comes to an end and human intervention is needed. This violates 72 /* a basic Postfix principle. 73 /* CONFIGURATION PARAMETERS 74 /* .ad 75 /* .fi 76 /* Changes to \fBmain.cf\fR are not picked up automatically, 77 /* as \fBverify\fR(8) 78 /* processes are long-lived. Use the command "\fBpostfix reload\fR" after 79 /* a configuration change. 80 /* 81 /* The text below provides only a parameter summary. See 82 /* \fBpostconf\fR(5) for more details including examples. 83 /* CACHE CONTROLS 84 /* .ad 85 /* .fi 86 /* .IP "\fBaddress_verify_map (see 'postconf -d' output)\fR" 87 /* Lookup table for persistent address verification status 88 /* storage. 89 /* .IP "\fBaddress_verify_sender ($double_bounce_sender)\fR" 90 /* The sender address to use in address verification probes; prior 91 /* to Postfix 2.5 the default was "postmaster". 92 /* .IP "\fBaddress_verify_positive_expire_time (31d)\fR" 93 /* The time after which a successful probe expires from the address 94 /* verification cache. 95 /* .IP "\fBaddress_verify_positive_refresh_time (7d)\fR" 96 /* The time after which a successful address verification probe needs 97 /* to be refreshed. 98 /* .IP "\fBaddress_verify_negative_cache (yes)\fR" 99 /* Enable caching of failed address verification probe results. 100 /* .IP "\fBaddress_verify_negative_expire_time (3d)\fR" 101 /* The time after which a failed probe expires from the address 102 /* verification cache. 103 /* .IP "\fBaddress_verify_negative_refresh_time (3h)\fR" 104 /* The time after which a failed address verification probe needs to 105 /* be refreshed. 106 /* .PP 107 /* Available with Postfix 2.7 and later: 108 /* .IP "\fBaddress_verify_cache_cleanup_interval (12h)\fR" 109 /* The amount of time between \fBverify\fR(8) address verification 110 /* database cleanup runs. 111 /* PROBE MESSAGE ROUTING CONTROLS 112 /* .ad 113 /* .fi 114 /* By default, probe messages are delivered via the same route 115 /* as regular messages. The following parameters can be used to 116 /* override specific message routing mechanisms. 117 /* .IP "\fBaddress_verify_relayhost ($relayhost)\fR" 118 /* Overrides the relayhost parameter setting for address verification 119 /* probes. 120 /* .IP "\fBaddress_verify_transport_maps ($transport_maps)\fR" 121 /* Overrides the transport_maps parameter setting for address verification 122 /* probes. 123 /* .IP "\fBaddress_verify_local_transport ($local_transport)\fR" 124 /* Overrides the local_transport parameter setting for address 125 /* verification probes. 126 /* .IP "\fBaddress_verify_virtual_transport ($virtual_transport)\fR" 127 /* Overrides the virtual_transport parameter setting for address 128 /* verification probes. 129 /* .IP "\fBaddress_verify_relay_transport ($relay_transport)\fR" 130 /* Overrides the relay_transport parameter setting for address 131 /* verification probes. 132 /* .IP "\fBaddress_verify_default_transport ($default_transport)\fR" 133 /* Overrides the default_transport parameter setting for address 134 /* verification probes. 135 /* .PP 136 /* Available in Postfix 2.3 and later: 137 /* .IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR" 138 /* Overrides the sender_dependent_relayhost_maps parameter setting for address 139 /* verification probes. 140 /* .PP 141 /* Available in Postfix 2.7 and later: 142 /* .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR" 143 /* Overrides the sender_dependent_default_transport_maps parameter 144 /* setting for address verification probes. 145 /* MISCELLANEOUS CONTROLS 146 /* .ad 147 /* .fi 148 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 149 /* The default location of the Postfix main.cf and master.cf 150 /* configuration files. 151 /* .IP "\fBdaemon_timeout (18000s)\fR" 152 /* How much time a Postfix daemon process may take to handle a 153 /* request before it is terminated by a built-in watchdog timer. 154 /* .IP "\fBipc_timeout (3600s)\fR" 155 /* The time limit for sending or receiving information over an internal 156 /* communication channel. 157 /* .IP "\fBprocess_id (read-only)\fR" 158 /* The process ID of a Postfix command or daemon process. 159 /* .IP "\fBprocess_name (read-only)\fR" 160 /* The process name of a Postfix command or daemon process. 161 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" 162 /* The location of the Postfix top-level queue directory. 163 /* .IP "\fBsyslog_facility (mail)\fR" 164 /* The syslog facility of Postfix logging. 165 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" 166 /* The mail system name that is prepended to the process name in syslog 167 /* records, so that "smtpd" becomes, for example, "postfix/smtpd". 168 /* SEE ALSO 169 /* smtpd(8), Postfix SMTP server 170 /* cleanup(8), enqueue Postfix message 171 /* postconf(5), configuration parameters 172 /* syslogd(5), system logging 173 /* README FILES 174 /* .ad 175 /* .fi 176 /* Use "\fBpostconf readme_directory\fR" or 177 /* "\fBpostconf html_directory\fR" to locate this information. 178 /* .na 179 /* .nf 180 /* ADDRESS_VERIFICATION_README, address verification howto 181 /* LICENSE 182 /* .ad 183 /* .fi 184 /* The Secure Mailer license must be distributed with this software. 185 /* HISTORY 186 /* .ad 187 /* .fi 188 /* This service was introduced with Postfix version 2.1. 189 /* AUTHOR(S) 190 /* Wietse Venema 191 /* IBM T.J. Watson Research 192 /* P.O. Box 704 193 /* Yorktown Heights, NY 10598, USA 194 /*--*/ 195 196 /* System library. */ 197 198 #include <sys_defs.h> 199 #include <sys/stat.h> 200 #include <time.h> 201 #include <string.h> 202 #include <stdlib.h> 203 #include <unistd.h> 204 205 /* Utility library. */ 206 207 #include <msg.h> 208 #include <mymalloc.h> 209 #include <htable.h> 210 #include <dict_ht.h> 211 #include <dict_cache.h> 212 #include <split_at.h> 213 #include <stringops.h> 214 #include <set_eugid.h> 215 #include <events.h> 216 217 /* Global library. */ 218 219 #include <mail_conf.h> 220 #include <mail_params.h> 221 #include <mail_version.h> 222 #include <mail_proto.h> 223 #include <post_mail.h> 224 #include <data_redirect.h> 225 #include <verify_clnt.h> 226 227 /* Server skeleton. */ 228 229 #include <mail_server.h> 230 231 /* Application-specific. */ 232 233 /* 234 * Tunable parameters. 235 */ 236 char *var_verify_map; 237 int var_verify_pos_exp; 238 int var_verify_pos_try; 239 int var_verify_neg_exp; 240 int var_verify_neg_try; 241 int var_verify_scan_cache; 242 char *var_verify_sender; 243 244 /* 245 * State. 246 */ 247 static DICT_CACHE *verify_map; 248 249 /* 250 * Silly little macros. 251 */ 252 #define STR(x) vstring_str(x) 253 #define STREQ(x,y) (strcmp(x,y) == 0) 254 255 /* 256 * The address verification database consists of (address, data) tuples. The 257 * format of the data field is "status:probed:updated:text". The meaning of 258 * each field is: 259 * 260 * status: one of the four recipient status codes (OK, DEFER, BOUNCE or TODO). 261 * In the case of TODO, we have no information about the address, and the 262 * address is being probed. 263 * 264 * probed: if non-zero, the time the currently outstanding address probe was 265 * sent. If zero, there is no outstanding address probe. 266 * 267 * updated: if non-zero, the time the address probe result was received. If 268 * zero, we have no information about the address, and the address is being 269 * probed. 270 * 271 * text: descriptive text from delivery agents etc. 272 */ 273 274 /* 275 * Quick test to see status without parsing the whole entry. 276 */ 277 #define STATUS_FROM_RAW_ENTRY(e) atoi(e) 278 279 /* verify_make_entry - construct table entry */ 280 281 static void verify_make_entry(VSTRING *buf, int status, long probed, 282 long updated, const char *text) 283 { 284 vstring_sprintf(buf, "%d:%ld:%ld:%s", status, probed, updated, text); 285 } 286 287 /* verify_parse_entry - parse table entry */ 288 289 static int verify_parse_entry(char *buf, int *status, long *probed, 290 long *updated, char **text) 291 { 292 char *probed_text; 293 char *updated_text; 294 295 if ((probed_text = split_at(buf, ':')) != 0 296 && (updated_text = split_at(probed_text, ':')) != 0 297 && (*text = split_at(updated_text, ':')) != 0 298 && alldig(buf) 299 && alldig(probed_text) 300 && alldig(updated_text)) { 301 *probed = atol(probed_text); 302 *updated = atol(updated_text); 303 *status = atoi(buf); 304 305 /* 306 * Coverity 200604: the code incorrectly tested (probed || updated), 307 * so that the sanity check never detected all-zero time stamps. Such 308 * records are never written. If we read a record with all-zero time 309 * stamps, then something is badly broken. 310 */ 311 if ((*status == DEL_RCPT_STAT_OK 312 || *status == DEL_RCPT_STAT_DEFER 313 || *status == DEL_RCPT_STAT_BOUNCE 314 || *status == DEL_RCPT_STAT_TODO) 315 && (*probed || *updated)) 316 return (0); 317 } 318 msg_warn("bad address verify table entry: %.100s", buf); 319 return (-1); 320 } 321 322 /* verify_stat2name - status to name */ 323 324 static const char *verify_stat2name(int addr_status) 325 { 326 if (addr_status == DEL_RCPT_STAT_OK) 327 return ("deliverable"); 328 if (addr_status == DEL_RCPT_STAT_DEFER) 329 return ("undeliverable"); 330 if (addr_status == DEL_RCPT_STAT_BOUNCE) 331 return ("undeliverable"); 332 return (0); 333 } 334 335 /* verify_update_service - update address service */ 336 337 static void verify_update_service(VSTREAM *client_stream) 338 { 339 VSTRING *buf = vstring_alloc(10); 340 VSTRING *addr = vstring_alloc(10); 341 int addr_status; 342 VSTRING *text = vstring_alloc(10); 343 const char *status_name; 344 const char *raw_data; 345 long probed; 346 long updated; 347 348 if (attr_scan(client_stream, ATTR_FLAG_STRICT, 349 ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr, 350 ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, &addr_status, 351 ATTR_TYPE_STR, MAIL_ATTR_WHY, text, 352 ATTR_TYPE_END) == 3) { 353 /* FIX 200501 IPv6 patch did not neuter ":" in address literals. */ 354 translit(STR(addr), ":", "_"); 355 if ((status_name = verify_stat2name(addr_status)) == 0) { 356 msg_warn("bad recipient status %d for recipient %s", 357 addr_status, STR(addr)); 358 attr_print(client_stream, ATTR_FLAG_NONE, 359 ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_BAD, 360 ATTR_TYPE_END); 361 } else { 362 363 /* 364 * Robustness: don't allow a failed probe to clobber an OK 365 * address before it expires. The failed probe is ignored so that 366 * the address will be re-probed upon the next query. As long as 367 * some probes succeed the address will remain cached as OK. 368 */ 369 if (addr_status == DEL_RCPT_STAT_OK 370 || (raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0 371 || STATUS_FROM_RAW_ENTRY(raw_data) != DEL_RCPT_STAT_OK) { 372 probed = 0; 373 updated = (long) time((time_t *) 0); 374 verify_make_entry(buf, addr_status, probed, updated, STR(text)); 375 if (msg_verbose) 376 msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s", 377 STR(addr), addr_status, probed, updated, STR(text)); 378 dict_cache_update(verify_map, STR(addr), STR(buf)); 379 } 380 attr_print(client_stream, ATTR_FLAG_NONE, 381 ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK, 382 ATTR_TYPE_END); 383 } 384 } 385 vstring_free(buf); 386 vstring_free(addr); 387 vstring_free(text); 388 } 389 390 /* verify_post_mail_action - callback */ 391 392 static void verify_post_mail_action(VSTREAM *stream, void *unused_context) 393 { 394 395 /* 396 * Probe messages need no body content, because they are never delivered, 397 * deferred, or bounced. 398 */ 399 if (stream != 0) 400 post_mail_fclose(stream); 401 } 402 403 /* verify_query_service - query address status */ 404 405 static void verify_query_service(VSTREAM *client_stream) 406 { 407 VSTRING *addr = vstring_alloc(10); 408 VSTRING *get_buf = 0; 409 VSTRING *put_buf = 0; 410 const char *raw_data; 411 int addr_status; 412 long probed; 413 long updated; 414 char *text; 415 416 if (attr_scan(client_stream, ATTR_FLAG_STRICT, 417 ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr, 418 ATTR_TYPE_END) == 1) { 419 long now = (long) time((time_t *) 0); 420 421 /* 422 * Produce a default record when no usable record exists. 423 * 424 * If negative caching is disabled, purge an expired record from the 425 * database. 426 * 427 * XXX Assume that a probe is lost if no response is received in 1000 428 * seconds. If this number is too small the queue will slowly fill up 429 * with delayed probes. 430 * 431 * XXX Maintain a moving average for the probe turnaround time, and 432 * allow probe "retransmission" when a probe is outstanding for, say 433 * some minimal amount of time (1000 sec) plus several times the 434 * observed probe turnaround time. This causes probing to back off 435 * when the mail system becomes congested. 436 */ 437 #define POSITIVE_ENTRY_EXPIRED(addr_status, updated) \ 438 (addr_status == DEL_RCPT_STAT_OK && updated + var_verify_pos_exp < now) 439 #define NEGATIVE_ENTRY_EXPIRED(addr_status, updated) \ 440 (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_exp < now) 441 #define PROBE_TTL 1000 442 443 /* FIX 200501 IPv6 patch did not neuter ":" in address literals. */ 444 translit(STR(addr), ":", "_"); 445 if ((raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0 /* not found */ 446 || ((get_buf = vstring_alloc(10)), 447 vstring_strcpy(get_buf, raw_data), /* malformed */ 448 verify_parse_entry(STR(get_buf), &addr_status, &probed, 449 &updated, &text) < 0) 450 || (now - probed > PROBE_TTL /* safe to probe */ 451 && (POSITIVE_ENTRY_EXPIRED(addr_status, updated) 452 || NEGATIVE_ENTRY_EXPIRED(addr_status, updated)))) { 453 addr_status = DEL_RCPT_STAT_TODO; 454 probed = 0; 455 updated = 0; 456 text = "Address verification in progress"; 457 if (raw_data != 0 && var_verify_neg_cache == 0) 458 dict_cache_delete(verify_map, STR(addr)); 459 } 460 if (msg_verbose) 461 msg_info("GOT %s status=%d probed=%ld updated=%ld text=%s", 462 STR(addr), addr_status, probed, updated, text); 463 464 /* 465 * Respond to the client. 466 */ 467 attr_print(client_stream, ATTR_FLAG_NONE, 468 ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK, 469 ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status, 470 ATTR_TYPE_STR, MAIL_ATTR_WHY, text, 471 ATTR_TYPE_END); 472 473 /* 474 * Send a new probe when the information needs to be refreshed. 475 * 476 * XXX For an initial proof of concept implementation, use synchronous 477 * mail submission. This needs to be made async for high-volume 478 * sites, which makes it even more interesting to eliminate duplicate 479 * queries while a probe is being built. 480 * 481 * If negative caching is turned off, update the database only when 482 * refreshing an existing entry. 483 */ 484 #define POSITIVE_REFRESH_NEEDED(addr_status, updated) \ 485 (addr_status == DEL_RCPT_STAT_OK && updated + var_verify_pos_try < now) 486 #define NEGATIVE_REFRESH_NEEDED(addr_status, updated) \ 487 (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now) 488 489 if (now - probed > PROBE_TTL 490 && (POSITIVE_REFRESH_NEEDED(addr_status, updated) 491 || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) { 492 if (msg_verbose) 493 msg_info("PROBE %s status=%d probed=%ld updated=%ld", 494 STR(addr), addr_status, now, updated); 495 post_mail_fopen_async(strcmp(var_verify_sender, "<>") == 0 ? 496 "" : var_verify_sender, STR(addr), 497 INT_FILT_MASK_NONE, 498 DEL_REQ_FLAG_MTA_VRFY, 499 (VSTRING *) 0, 500 verify_post_mail_action, 501 (void *) 0); 502 if (updated != 0 || var_verify_neg_cache != 0) { 503 put_buf = vstring_alloc(10); 504 verify_make_entry(put_buf, addr_status, now, updated, text); 505 if (msg_verbose) 506 msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s", 507 STR(addr), addr_status, now, updated, text); 508 dict_cache_update(verify_map, STR(addr), STR(put_buf)); 509 } 510 } 511 } 512 vstring_free(addr); 513 if (get_buf) 514 vstring_free(get_buf); 515 if (put_buf) 516 vstring_free(put_buf); 517 } 518 519 /* verify_cache_validator - cache cleanup validator */ 520 521 static int verify_cache_validator(const char *addr, const char *raw_data, 522 char *context) 523 { 524 VSTRING *get_buf = (VSTRING *) context; 525 int addr_status; 526 long probed; 527 long updated; 528 char *text; 529 long now = (long) event_time(); 530 531 #define POS_OR_NEG_ENTRY_EXPIRED(stat, stamp) \ 532 (POSITIVE_ENTRY_EXPIRED((stat), (stamp)) \ 533 || NEGATIVE_ENTRY_EXPIRED((stat), (stamp))) 534 535 vstring_strcpy(get_buf, raw_data); 536 return (verify_parse_entry(STR(get_buf), &addr_status, /* syntax OK */ 537 &probed, &updated, &text) == 0 538 && (now - probed < PROBE_TTL /* probe in progress */ 539 || !POS_OR_NEG_ENTRY_EXPIRED(addr_status, updated))); 540 } 541 542 /* verify_service - perform service for client */ 543 544 static void verify_service(VSTREAM *client_stream, char *unused_service, 545 char **argv) 546 { 547 VSTRING *request = vstring_alloc(10); 548 549 /* 550 * Sanity check. This service takes no command-line arguments. 551 */ 552 if (argv[0]) 553 msg_fatal("unexpected command-line argument: %s", argv[0]); 554 555 /* 556 * This routine runs whenever a client connects to the socket dedicated 557 * to the address verification service. All connection-management stuff 558 * is handled by the common code in multi_server.c. 559 */ 560 if (attr_scan(client_stream, 561 ATTR_FLAG_MORE | ATTR_FLAG_STRICT, 562 ATTR_TYPE_STR, MAIL_ATTR_REQ, request, 563 ATTR_TYPE_END) == 1) { 564 if (STREQ(STR(request), VRFY_REQ_UPDATE)) { 565 verify_update_service(client_stream); 566 } else if (STREQ(STR(request), VRFY_REQ_QUERY)) { 567 verify_query_service(client_stream); 568 } else { 569 msg_warn("unrecognized request: \"%s\", ignored", STR(request)); 570 attr_print(client_stream, ATTR_FLAG_NONE, 571 ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_BAD, 572 ATTR_TYPE_END); 573 } 574 } 575 vstream_fflush(client_stream); 576 vstring_free(request); 577 } 578 579 /* verify_dump - dump some statistics */ 580 581 static void verify_dump(void) 582 { 583 584 /* 585 * Dump preliminary cache cleanup statistics when the process commits 586 * suicide while a cache cleanup run is in progress. We can't currently 587 * distinguish between "postfix reload" (we should restart) or "maximal 588 * idle time reached" (we could finish the cache cleanup first). 589 */ 590 dict_cache_close(verify_map); 591 verify_map = 0; 592 } 593 594 /* post_jail_init - post-jail initialization */ 595 596 static void post_jail_init(char *unused_name, char **unused_argv) 597 { 598 599 /* 600 * If the database is in volatile memory only, prevent automatic process 601 * suicide after a limited number of client requests or after a limited 602 * amount of idle time. 603 */ 604 if (*var_verify_map == 0) { 605 var_use_limit = 0; 606 var_idle_limit = 0; 607 } 608 609 /* 610 * Start the cache cleanup thread. 611 */ 612 if (var_verify_scan_cache > 0) { 613 int cache_flags; 614 615 cache_flags = DICT_CACHE_FLAG_STATISTICS; 616 if (msg_verbose) 617 cache_flags |= DICT_CACHE_FLAG_VERBOSE; 618 dict_cache_control(verify_map, 619 DICT_CACHE_CTL_FLAGS, cache_flags, 620 DICT_CACHE_CTL_INTERVAL, var_verify_scan_cache, 621 DICT_CACHE_CTL_VALIDATOR, verify_cache_validator, 622 DICT_CACHE_CTL_CONTEXT, (char *) vstring_alloc(100), 623 DICT_CACHE_CTL_END); 624 } 625 } 626 627 /* pre_jail_init - pre-jail initialization */ 628 629 static void pre_jail_init(char *unused_name, char **unused_argv) 630 { 631 mode_t saved_mask; 632 VSTRING *redirect; 633 634 /* 635 * Never, ever, get killed by a master signal, as that would corrupt the 636 * database when we're in the middle of an update. 637 */ 638 setsid(); 639 640 /* 641 * Security: don't create root-owned files that contain untrusted data. 642 * And don't create Postfix-owned files in root-owned directories, 643 * either. We want a correct relationship between (file/directory) 644 * ownership and (file/directory) content. 645 * 646 * XXX Non-root open can violate the principle of least surprise: Postfix 647 * can't open an *SQL config file for database read-write access, even 648 * though it can open that same control file for database read-only 649 * access. 650 * 651 * The solution is to query a map type and obtain its properties before 652 * opening it. A clean solution is to add a dict_info() API that is 653 * similar to dict_open() except it returns properties (dict flags) only. 654 * A pragmatic solution is to overload the existing API and have 655 * dict_open() return a dummy map when given a null map name. 656 * 657 * However, the proxymap daemon has been opening *SQL maps as non-root for 658 * years now without anyone complaining, let's not solve a problem that 659 * doesn't exist. 660 */ 661 SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid); 662 redirect = vstring_alloc(100); 663 664 /* 665 * Keep state in persistent (external) or volatile (internal) map. 666 * 667 * Start the cache cleanup thread after permanently dropping privileges. 668 */ 669 #define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE \ 670 | DICT_FLAG_OPEN_LOCK) 671 672 saved_mask = umask(022); 673 verify_map = 674 dict_cache_open(*var_verify_map ? 675 data_redirect_map(redirect, var_verify_map) : 676 "internal:verify", 677 O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS); 678 (void) umask(saved_mask); 679 680 /* 681 * Clean up and restore privilege. 682 */ 683 vstring_free(redirect); 684 RESTORE_SAVED_EUGID(); 685 } 686 687 MAIL_VERSION_STAMP_DECLARE; 688 689 /* main - pass control to the multi-threaded skeleton */ 690 691 int main(int argc, char **argv) 692 { 693 static const CONFIG_STR_TABLE str_table[] = { 694 VAR_VERIFY_MAP, DEF_VERIFY_MAP, &var_verify_map, 0, 0, 695 VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender, 0, 0, 696 0, 697 }; 698 static const CONFIG_TIME_TABLE time_table[] = { 699 VAR_VERIFY_POS_EXP, DEF_VERIFY_POS_EXP, &var_verify_pos_exp, 1, 0, 700 VAR_VERIFY_POS_TRY, DEF_VERIFY_POS_TRY, &var_verify_pos_try, 1, 0, 701 VAR_VERIFY_NEG_EXP, DEF_VERIFY_NEG_EXP, &var_verify_neg_exp, 1, 0, 702 VAR_VERIFY_NEG_TRY, DEF_VERIFY_NEG_TRY, &var_verify_neg_try, 1, 0, 703 VAR_VERIFY_SCAN_CACHE, DEF_VERIFY_SCAN_CACHE, &var_verify_scan_cache, 0, 0, 704 0, 705 }; 706 707 /* 708 * Fingerprint executables and core dumps. 709 */ 710 MAIL_VERSION_STAMP_ALLOCATE; 711 712 multi_server_main(argc, argv, verify_service, 713 MAIL_SERVER_STR_TABLE, str_table, 714 MAIL_SERVER_TIME_TABLE, time_table, 715 MAIL_SERVER_PRE_INIT, pre_jail_init, 716 MAIL_SERVER_POST_INIT, post_jail_init, 717 MAIL_SERVER_SOLITARY, 718 MAIL_SERVER_EXIT, verify_dump, 719 0); 720 } 721