1 /* 2 * Copyright (c) 1998-2003 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: alias.c,v 8.221 2013-11-22 20:51:54 ca Exp $") 17 18 #include <sm/sendmail.h> 19 20 #define SEPARATOR ':' 21 # define ALIAS_SPEC_SEPARATORS " ,/:" 22 23 static MAP *AliasFileMap = NULL; /* the actual aliases.files map */ 24 static int NAliasFileMaps; /* the number of entries in AliasFileMap */ 25 26 static char *aliaslookup __P((char *, int *, char *)); 27 28 /* 29 ** ALIAS -- Compute aliases. 30 ** 31 ** Scans the alias file for an alias for the given address. 32 ** If found, it arranges to deliver to the alias list instead. 33 ** Uses libdbm database if -DDBM. 34 ** 35 ** Parameters: 36 ** a -- address to alias. 37 ** sendq -- a pointer to the head of the send queue 38 ** to put the aliases in. 39 ** aliaslevel -- the current alias nesting depth. 40 ** e -- the current envelope. 41 ** 42 ** Returns: 43 ** none 44 ** 45 ** Side Effects: 46 ** Aliases found are expanded. 47 ** 48 ** Deficiencies: 49 ** It should complain about names that are aliased to 50 ** nothing. 51 */ 52 53 void 54 alias(a, sendq, aliaslevel, e) 55 register ADDRESS *a; 56 ADDRESS **sendq; 57 int aliaslevel; 58 register ENVELOPE *e; 59 { 60 register char *p; 61 char *owner; 62 auto int status = EX_OK; 63 char obuf[MAXNAME_I + 7]; 64 65 if (tTd(27, 1)) 66 sm_dprintf("alias(%s)\n", a->q_user); 67 68 /* don't realias already aliased names */ 69 if (!QS_IS_OK(a->q_state)) 70 return; 71 72 if (NoAlias) 73 return; 74 75 e->e_to = a->q_paddr; 76 77 /* 78 ** Look up this name. 79 ** 80 ** If the map was unavailable, we will queue this message 81 ** until the map becomes available; otherwise, we could 82 ** bounce messages inappropriately. 83 */ 84 85 #if _FFR_REDIRECTEMPTY 86 /* 87 ** envelope <> can't be sent to mailing lists, only owner- 88 ** send spam of this type to owner- of the list 89 ** ---- to stop spam from going to mailing lists! 90 */ 91 92 if (e->e_sender != NULL && *e->e_sender == '\0') 93 { 94 /* Look for owner of alias */ 95 (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user); 96 if (aliaslookup(obuf, &status, a->q_host) != NULL) 97 { 98 if (LogLevel > 8) 99 sm_syslog(LOG_WARNING, e->e_id, 100 "possible spam from <> to list: %s, redirected to %s\n", 101 a->q_user, obuf); 102 a->q_user = sm_rpool_strdup_x(e->e_rpool, obuf); 103 } 104 } 105 #endif /* _FFR_REDIRECTEMPTY */ 106 107 p = aliaslookup(a->q_user, &status, a->q_host); 108 if (status == EX_TEMPFAIL || status == EX_UNAVAILABLE) 109 { 110 a->q_state = QS_QUEUEUP; 111 if (e->e_message == NULL) 112 e->e_message = sm_rpool_strdup_x(e->e_rpool, 113 "alias database unavailable"); 114 115 /* XXX msg only per recipient? */ 116 if (a->q_message == NULL) 117 a->q_message = "alias database unavailable"; 118 return; 119 } 120 if (p == NULL) 121 return; 122 123 /* 124 ** Match on Alias. 125 ** Deliver to the target list. 126 */ 127 128 if (tTd(27, 1)) 129 sm_dprintf("%s (%s, %s) aliased to %s\n", 130 a->q_paddr, a->q_host, a->q_user, p); 131 if (bitset(EF_VRFYONLY, e->e_flags)) 132 { 133 a->q_state = QS_VERIFIED; 134 return; 135 } 136 message("aliased to %s", shortenstring(p, MAXSHORTSTR)); 137 if (LogLevel > 10) 138 sm_syslog(LOG_INFO, e->e_id, 139 "alias %.100s => %s", 140 a->q_paddr, shortenstring(p, MAXSHORTSTR)); 141 a->q_flags &= ~QSELFREF; 142 if (tTd(27, 5)) 143 { 144 sm_dprintf("alias: QS_EXPANDED "); 145 printaddr(sm_debug_file(), a, false); 146 } 147 a->q_state = QS_EXPANDED; 148 149 /* 150 ** Always deliver aliased items as the default user. 151 ** Setting q_gid to 0 forces deliver() to use DefUser 152 ** instead of the alias name for the call to initgroups(). 153 */ 154 155 a->q_uid = DefUid; 156 a->q_gid = 0; 157 a->q_fullname = NULL; 158 a->q_flags |= QGOODUID|QALIAS; 159 160 (void) sendtolist(p, a, sendq, aliaslevel + 1, e); 161 162 if (bitset(QSELFREF, a->q_flags) && QS_IS_EXPANDED(a->q_state)) 163 a->q_state = QS_OK; 164 165 /* 166 ** Look for owner of alias 167 */ 168 169 if (strncmp(a->q_user, "owner-", 6) == 0 || 170 strlen(a->q_user) > sizeof(obuf) - 7) 171 (void) sm_strlcpy(obuf, "owner-owner", sizeof(obuf)); 172 else 173 (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user); 174 owner = aliaslookup(obuf, &status, a->q_host); 175 if (owner == NULL) 176 return; 177 178 /* reflect owner into envelope sender */ 179 if (strpbrk(owner, ",:/|\"") != NULL) 180 owner = obuf; 181 a->q_owner = sm_rpool_strdup_x(e->e_rpool, owner); 182 183 /* announce delivery to this alias; NORECEIPT bit set later */ 184 if (e->e_xfp != NULL) 185 (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 186 "Message delivered to mailing list %s\n", 187 a->q_paddr); 188 e->e_flags |= EF_SENDRECEIPT; 189 a->q_flags |= QDELIVERED|QEXPANDED; 190 } 191 192 /* 193 ** ALIASLOOKUP -- look up a name in the alias file. 194 ** 195 ** Parameters: 196 ** name -- the name to look up [i] 197 ** pstat -- a pointer to a place to put the status. 198 ** av -- argument for %1 expansion. 199 ** 200 ** Returns: 201 ** the value of name. 202 ** NULL if unknown. 203 ** 204 ** Warnings: 205 ** The return value will be trashed across calls. 206 */ 207 208 static char * 209 aliaslookup(name, pstat, av) 210 char *name; 211 int *pstat; 212 char *av; 213 { 214 static MAP *map = NULL; 215 char *res; 216 #if _FFR_ALIAS_DETAIL 217 int i; 218 char *argv[4]; 219 #else 220 # define argv NULL 221 #endif 222 #if _FFR_8BITENVADDR 223 char buf[MAXNAME]; /* EAI:ok */ 224 #endif 225 226 if (map == NULL) 227 { 228 STAB *s = stab("aliases", ST_MAP, ST_FIND); 229 230 if (s == NULL) 231 return NULL; 232 map = &s->s_map; 233 } 234 DYNOPENMAP(map); 235 236 /* special case POstMastER -- always use lower case */ 237 if (SM_STRCASEEQ(name, "postmaster")) 238 name = "postmaster"; 239 #if _FFR_8BITENVADDR 240 (void) dequote_internal_chars(name, buf, sizeof(buf)); 241 /* check length? */ 242 name = buf; 243 #endif /* _FFR_8BITENVADDR */ 244 245 #if _FFR_ALIAS_DETAIL 246 i = 0; 247 argv[i++] = name; 248 argv[i++] = av; 249 250 /* XXX '+' is hardwired here as delimiter! */ 251 if (av != NULL && *av == '+') 252 argv[i++] = av + 1; 253 argv[i++] = NULL; 254 #endif /* _FFR_ALIAS_DETAIL */ 255 res = (*map->map_class->map_lookup)(map, name, argv, pstat); 256 #if _FFR_8BITENVADDR 257 /* map_lookup() does a map_rewrite(), so no quoting here */ 258 #endif 259 return res; 260 } 261 262 /* 263 ** SETALIAS -- set up an alias map 264 ** 265 ** Called when reading configuration file. 266 ** 267 ** Parameters: 268 ** spec -- the alias specification 269 ** 270 ** Returns: 271 ** none. 272 */ 273 274 void 275 setalias(spec) 276 char *spec; 277 { 278 register char *p; 279 register MAP *map; 280 char *class; 281 STAB *s; 282 283 if (tTd(27, 8)) 284 sm_dprintf("setalias(%s)\n", spec); 285 286 for (p = spec; p != NULL; ) 287 { 288 char buf[50]; 289 290 while (SM_ISSPACE(*p)) 291 p++; 292 if (*p == '\0') 293 break; 294 spec = p; 295 296 if (NAliasFileMaps >= MAXMAPSTACK) 297 { 298 syserr("Too many alias databases defined, %d max", 299 MAXMAPSTACK); 300 return; 301 } 302 if (AliasFileMap == NULL) 303 { 304 (void) sm_strlcpy(buf, "aliases.files sequence", 305 sizeof(buf)); 306 AliasFileMap = makemapentry(buf); 307 if (AliasFileMap == NULL) 308 { 309 syserr("setalias: cannot create aliases.files map"); 310 return; 311 } 312 } 313 (void) sm_snprintf(buf, sizeof(buf), "Alias%d", NAliasFileMaps); 314 s = stab(buf, ST_MAP, ST_ENTER); 315 map = &s->s_map; 316 memset(map, '\0', sizeof(*map)); 317 map->map_mname = s->s_name; 318 p = strpbrk(p, ALIAS_SPEC_SEPARATORS); 319 if (p != NULL && *p == SEPARATOR) 320 { 321 /* map name */ 322 *p++ = '\0'; 323 class = spec; 324 spec = p; 325 } 326 else 327 { 328 class = "implicit"; 329 map->map_mflags = MF_INCLNULL; 330 } 331 332 /* find end of spec */ 333 if (p != NULL) 334 { 335 bool quoted = false; 336 337 for (; *p != '\0'; p++) 338 { 339 /* 340 ** Don't break into a quoted string. 341 ** Needed for ldap maps which use 342 ** commas in their specifications. 343 */ 344 345 if (*p == '"') 346 quoted = !quoted; 347 else if (*p == ',' && !quoted) 348 break; 349 } 350 351 /* No more alias specifications follow */ 352 if (*p == '\0') 353 p = NULL; 354 } 355 if (p != NULL) 356 *p++ = '\0'; 357 358 if (tTd(27, 20)) 359 sm_dprintf(" map %s:%s %s\n", class, s->s_name, spec); 360 361 /* look up class */ 362 s = stab(class, ST_MAPCLASS, ST_FIND); 363 if (s == NULL) 364 { 365 syserr("setalias: unknown alias class %s", class); 366 } 367 else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags)) 368 { 369 syserr("setalias: map class %s can't handle aliases", 370 class); 371 } 372 else 373 { 374 map->map_class = &s->s_mapclass; 375 map->map_mflags |= MF_ALIAS; 376 if (map->map_class->map_parse(map, spec)) 377 { 378 map->map_mflags |= MF_VALID; 379 AliasFileMap->map_stack[NAliasFileMaps++] = map; 380 } 381 } 382 } 383 } 384 385 /* 386 ** ALIASWAIT -- wait for distinguished @:@ token to appear. 387 ** 388 ** This can decide to reopen the alias file 389 ** 390 ** Parameters: 391 ** map -- a pointer to the map descriptor for this alias file. 392 ** ext -- the filename extension (e.g., ".db") for the 393 ** database file. 394 ** isopen -- if set, the database is already open, and we 395 ** should check for validity; otherwise, we are 396 ** just checking to see if it should be created. 397 ** 398 ** Returns: 399 ** true -- if the database is open when we return. 400 ** false -- if the database is closed when we return. 401 */ 402 403 bool 404 aliaswait(map, ext, isopen) 405 MAP *map; 406 const char *ext; 407 bool isopen; 408 { 409 bool attimeout = false; 410 time_t mtime; 411 struct stat stb; 412 char buf[MAXPATHLEN]; 413 414 if (tTd(27, 3)) 415 sm_dprintf("aliaswait(%s:%s), open=%d, wait=%d\n", 416 map->map_class->map_cname, map->map_file, 417 isopen, bitset(MF_ALIASWAIT, map->map_mflags)); 418 if (bitset(MF_ALIASWAIT, map->map_mflags)) 419 return isopen; 420 map->map_mflags |= MF_ALIASWAIT; 421 422 if (isopen && SafeAlias > 0) 423 { 424 auto int st; 425 unsigned int sleeptime = 2; 426 unsigned int loopcount = 0; /* only used for debugging */ 427 time_t toolong = curtime() + SafeAlias; 428 429 while (isopen && 430 map->map_class->map_lookup(map, "@", NULL, &st) == NULL) 431 { 432 if (curtime() > toolong) 433 { 434 /* we timed out */ 435 attimeout = true; 436 break; 437 } 438 439 /* 440 ** Close and re-open the alias database in case 441 ** the one is mv'ed instead of cp'ed in. 442 */ 443 444 if (tTd(27, 2)) 445 { 446 loopcount++; 447 sm_dprintf("aliaswait: sleeping for %u seconds (loopcount = %u)\n", 448 sleeptime, loopcount); 449 } 450 451 map->map_mflags |= MF_CLOSING; 452 map->map_class->map_close(map); 453 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING|MF_CHKED_CHGD); 454 (void) sleep(sleeptime); 455 sleeptime *= 2; 456 if (sleeptime > 60) 457 sleeptime = 60; 458 isopen = map->map_class->map_open(map, O_RDONLY); 459 } 460 } 461 map->map_mflags &= ~MF_CHKED_CHGD; 462 463 /* see if we need to go into auto-rebuild mode */ 464 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 465 { 466 if (tTd(27, 3)) 467 sm_dprintf("aliaswait: not rebuildable\n"); 468 map->map_mflags &= ~MF_ALIASWAIT; 469 return isopen; 470 } 471 if (stat(map->map_file, &stb) < 0) 472 { 473 if (tTd(27, 3)) 474 sm_dprintf("aliaswait: no source file\n"); 475 map->map_mflags &= ~MF_ALIASWAIT; 476 return isopen; 477 } 478 mtime = stb.st_mtime; 479 if (sm_strlcpyn(buf, sizeof(buf), 2, 480 map->map_file, ext == NULL ? "" : ext) >= sizeof(buf)) 481 { 482 if (LogLevel > 3) 483 sm_syslog(LOG_INFO, NOQID, 484 "alias database %s%s name too long", 485 map->map_file, ext == NULL ? "" : ext); 486 message("alias database %s%s name too long", 487 map->map_file, ext == NULL ? "" : ext); 488 } 489 490 if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout) 491 { 492 if (LogLevel > 3) 493 sm_syslog(LOG_INFO, NOQID, 494 "alias database %s out of date", buf); 495 message("Warning: alias database %s out of date", buf); 496 } 497 map->map_mflags &= ~MF_ALIASWAIT; 498 return isopen; 499 } 500 /* 501 ** REBUILDALIASES -- rebuild the alias database. 502 ** 503 ** Parameters: 504 ** map -- the database to rebuild. 505 ** 506 ** Returns: 507 ** true if successful; false otherwise. 508 ** 509 ** Side Effects: 510 ** Reads the text version of the database, builds the map. 511 */ 512 513 bool 514 rebuildaliases(map) 515 register MAP *map; 516 { 517 SM_FILE_T *af; 518 bool nolock = false; 519 bool success = false; 520 long sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK; 521 sigfunc_t oldsigint, oldsigquit; 522 #ifdef SIGTSTP 523 sigfunc_t oldsigtstp; 524 #endif 525 526 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 527 return false; 528 529 if (!bitnset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail)) 530 sff |= SFF_NOWLINK; 531 if (!bitnset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail)) 532 sff |= SFF_NOGWFILES; 533 if (!bitnset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail)) 534 sff |= SFF_NOWWFILES; 535 536 /* try to lock the source file */ 537 if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL) 538 { 539 struct stat stb; 540 541 if ((errno != EACCES && errno != EROFS) || 542 (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL) 543 { 544 int saveerr = errno; 545 546 if (tTd(27, 1)) 547 sm_dprintf("Can't open %s: %s\n", 548 map->map_file, sm_errstring(saveerr)); 549 if (!bitset(MF_OPTIONAL, map->map_mflags)) 550 message("newaliases: cannot open %s: %s", 551 map->map_file, sm_errstring(saveerr)); 552 errno = 0; 553 return false; 554 } 555 nolock = true; 556 if (tTd(27, 1) || 557 fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &stb) < 0 || 558 bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode)) 559 message("warning: cannot lock %s: %s", 560 map->map_file, sm_errstring(errno)); 561 } 562 563 /* see if someone else is rebuilding the alias file */ 564 if (!nolock && 565 !lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), map->map_file, 566 NULL, LOCK_EX|LOCK_NB)) 567 { 568 /* yes, they are -- wait until done */ 569 message("Alias file %s is locked (maybe being rebuilt)", 570 map->map_file); 571 if (OpMode != MD_INITALIAS) 572 { 573 /* wait for other rebuild to complete */ 574 (void) lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), 575 map->map_file, NULL, LOCK_EX); 576 } 577 (void) sm_io_close(af, SM_TIME_DEFAULT); 578 errno = 0; 579 return false; 580 } 581 582 oldsigint = sm_signal(SIGINT, SIG_IGN); 583 oldsigquit = sm_signal(SIGQUIT, SIG_IGN); 584 #ifdef SIGTSTP 585 oldsigtstp = sm_signal(SIGTSTP, SIG_IGN); 586 #endif 587 588 if (map->map_class->map_open(map, O_RDWR)) 589 { 590 if (LogLevel > 7) 591 { 592 sm_syslog(LOG_NOTICE, NOQID, 593 "alias database %s rebuilt by %s", 594 map->map_file, username()); 595 } 596 map->map_mflags |= MF_OPEN|MF_WRITABLE; 597 map->map_pid = CurrentPid; 598 readaliases(map, af, true, true); 599 success = true; 600 } 601 else 602 { 603 if (tTd(27, 1)) 604 sm_dprintf("Can't create database for %s: %s\n", 605 map->map_file, sm_errstring(errno)); 606 syserr("Cannot create database for alias file %s", 607 map->map_file); 608 } 609 610 /* close the file, thus releasing locks */ 611 (void) sm_io_close(af, SM_TIME_DEFAULT); 612 613 /* add distinguished entries and close the database */ 614 if (bitset(MF_OPEN, map->map_mflags)) 615 { 616 #if _FFR_TESTS 617 if (tTd(78, 101)) 618 { 619 int sl; 620 621 sl = tTdlevel(78) - 100; 622 sm_dprintf("rebuildaliases: sleep=%d, file=%s\n", 623 sl, map->map_file); 624 sleep(sl); 625 sm_dprintf("rebuildaliases: done\n"); 626 } 627 #endif 628 map->map_mflags |= MF_CLOSING; 629 map->map_class->map_close(map); 630 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 631 } 632 633 /* restore the old signals */ 634 (void) sm_signal(SIGINT, oldsigint); 635 (void) sm_signal(SIGQUIT, oldsigquit); 636 #ifdef SIGTSTP 637 (void) sm_signal(SIGTSTP, oldsigtstp); 638 #endif 639 return success; 640 } 641 642 /* 643 ** CONTLINE -- handle potential continuation line 644 ** 645 ** Parameters: 646 ** fp -- file to read 647 ** line -- current line 648 ** 649 ** Returns: 650 ** pointer to end of current line if there is a continuation line 651 ** NULL otherwise 652 ** 653 ** Side Effects: 654 ** Modifies line if it is a continuation line 655 */ 656 657 static char *contline __P((SM_FILE_T *, char *)); 658 static char * 659 contline(fp, line) 660 SM_FILE_T *fp; 661 char *line; 662 { 663 char *p; 664 int c; 665 666 if ((p = strchr(line, '\n')) != NULL && p > line && p[-1] == '\\') 667 { 668 *p = '\0'; 669 *--p = '\0'; 670 return p; 671 } 672 673 c = sm_io_getc(fp, SM_TIME_DEFAULT); 674 if (!sm_io_eof(fp)) 675 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); 676 if (c == ' ' || c == '\t') 677 { 678 char *nlp; 679 680 p = line; 681 nlp = &p[strlen(p)]; 682 if (nlp > p && nlp[-1] == '\n') 683 *--nlp = '\0'; 684 return nlp; 685 } 686 return NULL; 687 } 688 689 /* 690 ** READALIASES -- read and process the alias file. 691 ** 692 ** This routine implements the part of initaliases that occurs 693 ** when we are not going to use the DBM stuff. 694 ** 695 ** Parameters: 696 ** map -- the alias database descriptor. 697 ** af -- file to read the aliases from. 698 ** announcestats -- announce statistics regarding number of 699 ** aliases, longest alias, etc. 700 ** logstats -- lot the same info. 701 ** 702 ** Returns: 703 ** none. 704 ** 705 ** Side Effects: 706 ** Reads aliasfile into the symbol table. 707 ** Optionally, builds the .dir & .pag files. 708 */ 709 710 void 711 readaliases(map, af, announcestats, logstats) 712 register MAP *map; 713 SM_FILE_T *af; 714 bool announcestats; 715 bool logstats; 716 { 717 register char *p; 718 char *rhs; 719 bool skipping; 720 long naliases, bytes, longest; 721 ADDRESS al, bl; 722 char lbuf[BUFSIZ]; 723 char *line; 724 #if _FFR_8BITENVADDR 725 char lhsbuf[MAXNAME]; /* EAI:ok */ 726 char rhsbuf[BUFSIZ]; 727 int len; 728 #endif 729 730 /* 731 ** Read and interpret lines 732 */ 733 734 FileName = map->map_file; 735 LineNumber = 0; 736 naliases = bytes = longest = 0; 737 skipping = false; 738 line = NULL; 739 740 while (sm_io_fgets(af, SM_TIME_DEFAULT, lbuf, sizeof(lbuf)) >= 0) 741 { 742 int lhssize, rhssize; 743 int c; 744 char *newp; 745 746 LineNumber++; 747 748 /* XXX what if line="a\\" ? */ 749 line = lbuf; 750 p = line; 751 while ((newp = contline(af, line)) != NULL) 752 { 753 p = newp; 754 if ((c = sm_io_fgets(af, SM_TIME_DEFAULT, p, 755 SPACELEFT(lbuf, p))) < 0) 756 { 757 break; 758 } 759 LineNumber++; 760 } 761 #if _FFR_8BITENVADDR 762 if (SMTP_UTF8 || EightBitAddrOK) 763 { 764 if (line != lbuf) 765 SM_FREE(line); 766 line = quote_internal_chars(lbuf, NULL, &len, NULL); 767 } 768 else 769 #endif 770 /* "else" in #if code above */ 771 line = lbuf; 772 773 p = strchr(line, '\n'); 774 if (p != NULL) 775 *p = '\0'; 776 else if (!sm_io_eof(af)) 777 { 778 int prev; 779 bool cl; 780 781 errno = 0; 782 syserr("554 5.3.0 alias line too long"); 783 784 prev = '\0'; 785 cl = false; 786 787 do { 788 /* flush to end of "virtual" line */ 789 while ((c = sm_io_getc(af, SM_TIME_DEFAULT)) != 790 SM_IO_EOF && c != '\n') 791 { 792 prev = c; 793 } 794 cl = ('\\' == prev && '\n' == c); 795 if (!cl) 796 { 797 c = sm_io_getc(af, SM_TIME_DEFAULT); 798 if (!sm_io_eof(af)) 799 (void) sm_io_ungetc(af, SM_TIME_DEFAULT, c); 800 cl = (c == ' ' || c == '\t'); 801 } 802 } while (cl); 803 804 continue; 805 } 806 807 switch (line[0]) 808 { 809 case '#': 810 case '\0': 811 skipping = false; 812 continue; 813 814 case ' ': 815 case '\t': 816 if (!skipping) 817 syserr("554 5.3.5 Non-continuation line starts with space"); 818 skipping = true; 819 continue; 820 } 821 skipping = false; 822 823 /* 824 ** Process the LHS 825 ** Find the colon separator, and parse the address. 826 ** It should resolve to a local name -- this will 827 ** be checked later (we want to optionally do 828 ** parsing of the RHS first to maximize error 829 ** detection). 830 */ 831 832 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 833 continue; 834 if (*p++ != ':') 835 { 836 syserr("554 5.3.5 missing colon"); 837 continue; 838 } 839 /* XXX line must be [i] */ 840 if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv, true) 841 == NULL) 842 { 843 syserr("554 5.3.5 %.40s... illegal alias name", line); 844 continue; 845 } 846 847 /* 848 ** Process the RHS. 849 ** 'al' is the internal form of the LHS address. 850 ** 'p' points to the text of the RHS. 851 */ 852 853 while (SM_ISSPACE(*p)) 854 p++; 855 rhs = p; 856 { 857 register char *nlp; 858 859 nlp = &p[strlen(p)]; 860 if (nlp > p && nlp[-1] == '\n') 861 *--nlp = '\0'; 862 863 if (CheckAliases) 864 { 865 /* do parsing & compression of addresses */ 866 while (*p != '\0') 867 { 868 auto char *delimptr; 869 870 while ((SM_ISSPACE(*p)) || *p == ',') 871 p++; 872 if (*p == '\0') 873 break; 874 /* XXX p must be [i] */ 875 if (parseaddr(p, &bl, RF_COPYNONE, ',', 876 &delimptr, CurEnv, true) 877 == NULL) 878 usrerr("553 5.3.5 %s... bad address", p); 879 p = delimptr; 880 } 881 } 882 else 883 { 884 p = nlp; 885 } 886 } while (0); 887 888 if (skipping) 889 continue; 890 891 if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags)) 892 { 893 syserr("554 5.3.5 %s... cannot alias non-local names", 894 al.q_paddr); 895 continue; 896 } 897 898 /* 899 ** Insert alias into symbol table or database file. 900 ** 901 ** Special case pOStmaStER -- always make it lower case. 902 */ 903 904 if (SM_STRCASEEQ(al.q_user, "postmaster")) 905 makelower_a(&al.q_user, CurEnv->e_rpool); 906 907 lhssize = strlen(al.q_user); 908 rhssize = strlen(rhs); 909 if (rhssize > 0) 910 { 911 /* is RHS empty (just spaces)? */ 912 p = rhs; 913 while (SM_ISSPACE(*p)) 914 p++; 915 } 916 if (rhssize == 0 || *p == '\0') 917 { 918 syserr("554 5.3.5 %.40s... missing value for alias", 919 line); 920 } 921 else 922 { 923 #if _FFR_8BITENVADDR 924 if (SMTP_UTF8 || EightBitAddrOK) 925 { 926 dequote_internal_chars(al.q_user, lhsbuf, sizeof(lhsbuf)); 927 dequote_internal_chars(rhs, rhsbuf, sizeof(rhsbuf)); 928 map->map_class->map_store(map, lhsbuf, rhsbuf); 929 } 930 else 931 #endif 932 /* "else" in #if code above */ 933 map->map_class->map_store(map, al.q_user, rhs); 934 935 /* statistics */ 936 naliases++; 937 bytes += lhssize + rhssize; 938 if (rhssize > longest) 939 longest = rhssize; 940 } 941 } 942 943 CurEnv->e_to = NULL; 944 FileName = NULL; 945 if (Verbose || announcestats) 946 message("%s: %ld aliases, longest %ld bytes, %ld bytes total", 947 map->map_file, naliases, longest, bytes); 948 if (LogLevel > 7 && logstats) 949 sm_syslog(LOG_INFO, NOQID, 950 "%s: %ld aliases, longest %ld bytes, %ld bytes total", 951 map->map_file, naliases, longest, bytes); 952 } 953 /* 954 ** FORWARD -- Try to forward mail 955 ** 956 ** This is similar but not identical to aliasing. 957 ** 958 ** Parameters: 959 ** user -- the name of the user who's mail we would like 960 ** to forward to. It must have been verified -- 961 ** i.e., the q_home field must have been filled in. 962 ** sendq -- a pointer to the head of the send queue to 963 ** put this user's aliases in. 964 ** aliaslevel -- the current alias nesting depth. 965 ** e -- the current envelope. 966 ** 967 ** Returns: 968 ** none. 969 ** 970 ** Side Effects: 971 ** New names are added to send queues. 972 */ 973 974 void 975 forward(user, sendq, aliaslevel, e) 976 ADDRESS *user; 977 ADDRESS **sendq; 978 int aliaslevel; 979 register ENVELOPE *e; 980 { 981 char *pp; 982 char *ep; 983 bool got_transient; 984 985 if (tTd(27, 1)) 986 sm_dprintf("forward(%s)\n", user->q_paddr); 987 988 if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) || 989 !QS_IS_OK(user->q_state)) 990 return; 991 if (ForwardPath != NULL && *ForwardPath == '\0') 992 return; 993 if (user->q_home == NULL) 994 { 995 syserr("554 5.3.0 forward: no home"); 996 user->q_home = "/no/such/directory"; 997 } 998 999 /* good address -- look for .forward file in home */ 1000 macdefine(&e->e_macro, A_PERM, 'z', user->q_home); 1001 macdefine(&e->e_macro, A_PERM, 'u', user->q_user); 1002 pp = user->q_host; 1003 #if _FFR_8BITENVADDR 1004 if (NULL != pp) 1005 { 1006 int len; 1007 1008 pp = quote_internal_chars(pp, NULL, &len, NULL); 1009 } 1010 #endif 1011 macdefine(&e->e_macro, A_PERM, 'h', pp); 1012 if (ForwardPath == NULL) 1013 ForwardPath = newstr("\201z/.forward"); 1014 1015 got_transient = false; 1016 for (pp = ForwardPath; pp != NULL; pp = ep) 1017 { 1018 int err; 1019 char buf[MAXPATHLEN]; 1020 struct stat st; 1021 1022 ep = strchr(pp, SEPARATOR); 1023 if (ep != NULL) 1024 *ep = '\0'; 1025 expand(pp, buf, sizeof(buf), e); 1026 if (ep != NULL) 1027 *ep++ = SEPARATOR; 1028 if (buf[0] == '\0') 1029 continue; 1030 if (tTd(27, 3)) 1031 sm_dprintf("forward: trying %s\n", buf); 1032 1033 err = include(buf, true, user, sendq, aliaslevel, e); 1034 if (err == 0) 1035 break; 1036 else if (transienterror(err)) 1037 { 1038 /* we may have to suspend this message */ 1039 got_transient = true; 1040 if (tTd(27, 2)) 1041 sm_dprintf("forward: transient error on %s\n", 1042 buf); 1043 if (LogLevel > 2) 1044 { 1045 char *curhost = CurHostName; 1046 1047 CurHostName = NULL; 1048 sm_syslog(LOG_ERR, e->e_id, 1049 "forward %s: transient error: %s", 1050 buf, sm_errstring(err)); 1051 CurHostName = curhost; 1052 } 1053 1054 } 1055 else 1056 { 1057 switch (err) 1058 { 1059 case ENOENT: 1060 break; 1061 1062 case E_SM_WWDIR: 1063 case E_SM_GWDIR: 1064 /* check if it even exists */ 1065 if (stat(buf, &st) < 0 && errno == ENOENT) 1066 { 1067 if (bitnset(DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH, 1068 DontBlameSendmail)) 1069 break; 1070 } 1071 /* FALLTHROUGH */ 1072 1073 #if _FFR_FORWARD_SYSERR 1074 case E_SM_NOSLINK: 1075 case E_SM_NOHLINK: 1076 case E_SM_REGONLY: 1077 case E_SM_ISEXEC: 1078 case E_SM_WWFILE: 1079 case E_SM_GWFILE: 1080 syserr("forward: %s: %s", buf, sm_errstring(err)); 1081 break; 1082 #endif /* _FFR_FORWARD_SYSERR */ 1083 1084 default: 1085 if (LogLevel > (RunAsUid == 0 ? 2 : 10)) 1086 sm_syslog(LOG_WARNING, e->e_id, 1087 "forward %s: %s", buf, 1088 sm_errstring(err)); 1089 if (Verbose) 1090 message("forward: %s: %s", 1091 buf, sm_errstring(err)); 1092 break; 1093 } 1094 } 1095 } 1096 if (pp == NULL && got_transient) 1097 { 1098 /* 1099 ** There was no successful .forward open and at least one 1100 ** transient open. We have to defer this address for 1101 ** further delivery. 1102 */ 1103 1104 message("transient .forward open error: message queued"); 1105 user->q_state = QS_QUEUEUP; 1106 return; 1107 } 1108 } 1109