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