1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 # include "sendmail.h" 10 # include <pwd.h> 11 12 #ifndef lint 13 static char sccsid[] = "@(#)alias.c 8.39 (Berkeley) 03/14/95"; 14 #endif /* not lint */ 15 16 17 MAP *AliasDB[MAXALIASDB + 1]; /* actual database list */ 18 int NAliasDBs; /* number of alias databases */ 19 /* 20 ** ALIAS -- Compute aliases. 21 ** 22 ** Scans the alias file for an alias for the given address. 23 ** If found, it arranges to deliver to the alias list instead. 24 ** Uses libdbm database if -DDBM. 25 ** 26 ** Parameters: 27 ** a -- address to alias. 28 ** sendq -- a pointer to the head of the send queue 29 ** to put the aliases in. 30 ** aliaslevel -- the current alias nesting depth. 31 ** e -- the current envelope. 32 ** 33 ** Returns: 34 ** none 35 ** 36 ** Side Effects: 37 ** Aliases found are expanded. 38 ** 39 ** Deficiencies: 40 ** It should complain about names that are aliased to 41 ** nothing. 42 */ 43 44 void 45 alias(a, sendq, aliaslevel, e) 46 register ADDRESS *a; 47 ADDRESS **sendq; 48 int aliaslevel; 49 register ENVELOPE *e; 50 { 51 register char *p; 52 int naliases; 53 char *owner; 54 char obuf[MAXNAME + 6]; 55 extern char *aliaslookup(); 56 57 if (tTd(27, 1)) 58 printf("alias(%s)\n", a->q_user); 59 60 /* don't realias already aliased names */ 61 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags)) 62 return; 63 64 if (NoAlias) 65 return; 66 67 e->e_to = a->q_paddr; 68 69 /* 70 ** Look up this name 71 */ 72 73 p = aliaslookup(a->q_user, e); 74 if (p == NULL) 75 return; 76 77 /* 78 ** Match on Alias. 79 ** Deliver to the target list. 80 */ 81 82 if (tTd(27, 1)) 83 printf("%s (%s, %s) aliased to %s\n", 84 a->q_paddr, a->q_host, a->q_user, p); 85 if (bitset(EF_VRFYONLY, e->e_flags)) 86 { 87 a->q_flags |= QVERIFIED; 88 e->e_nrcpts++; 89 return; 90 } 91 message("aliased to %s", p); 92 #ifdef LOG 93 if (LogLevel > 9) 94 syslog(LOG_INFO, "%s: alias %s => %s", 95 e->e_id == NULL ? "NOQUEUE" : e->e_id, 96 a->q_paddr, p); 97 #endif 98 a->q_flags &= ~QSELFREF; 99 if (tTd(27, 5)) 100 { 101 printf("alias: QDONTSEND "); 102 printaddr(a, FALSE); 103 } 104 a->q_flags |= QDONTSEND; 105 naliases = sendtolist(p, a, sendq, aliaslevel + 1, e); 106 if (bitset(QSELFREF, a->q_flags)) 107 a->q_flags &= ~QDONTSEND; 108 109 /* 110 ** Look for owner of alias 111 */ 112 113 (void) strcpy(obuf, "owner-"); 114 if (strncmp(a->q_user, "owner-", 6) == 0) 115 (void) strcat(obuf, "owner"); 116 else 117 (void) strcat(obuf, a->q_user); 118 if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) 119 makelower(obuf); 120 owner = aliaslookup(obuf, e); 121 if (owner == NULL) 122 return; 123 124 /* reflect owner into envelope sender */ 125 if (strpbrk(owner, ",:/|\"") != NULL) 126 owner = obuf; 127 a->q_owner = newstr(owner); 128 129 /* announce delivery to this alias; NORECEIPT bit set later */ 130 if (e->e_xfp != NULL) 131 fprintf(e->e_xfp, "Message delivered to mailing list %s\n", 132 a->q_paddr); 133 e->e_flags |= EF_SENDRECEIPT; 134 a->q_flags |= QREPORT; 135 } 136 /* 137 ** ALIASLOOKUP -- look up a name in the alias file. 138 ** 139 ** Parameters: 140 ** name -- the name to look up. 141 ** 142 ** Returns: 143 ** the value of name. 144 ** NULL if unknown. 145 ** 146 ** Side Effects: 147 ** none. 148 ** 149 ** Warnings: 150 ** The return value will be trashed across calls. 151 */ 152 153 char * 154 aliaslookup(name, e) 155 char *name; 156 ENVELOPE *e; 157 { 158 register int dbno; 159 register MAP *map; 160 register char *p; 161 162 for (dbno = 0; dbno < NAliasDBs; dbno++) 163 { 164 auto int stat; 165 166 map = AliasDB[dbno]; 167 if (!bitset(MF_OPEN, map->map_mflags)) 168 continue; 169 p = (*map->map_class->map_lookup)(map, name, NULL, &stat); 170 if (p != NULL) 171 return p; 172 } 173 return NULL; 174 } 175 /* 176 ** SETALIAS -- set up an alias map 177 ** 178 ** Called when reading configuration file. 179 ** 180 ** Parameters: 181 ** spec -- the alias specification 182 ** 183 ** Returns: 184 ** none. 185 */ 186 187 void 188 setalias(spec) 189 char *spec; 190 { 191 register char *p; 192 register MAP *map; 193 char *class; 194 STAB *s; 195 static bool first_unqual = TRUE; 196 197 if (tTd(27, 8)) 198 printf("setalias(%s)\n", spec); 199 200 for (p = spec; p != NULL; ) 201 { 202 while (isspace(*p)) 203 p++; 204 if (*p == '\0') 205 break; 206 spec = p; 207 208 /* 209 ** Treat simple filename specially -- this is the file name 210 ** for the files implementation, not necessarily in order. 211 */ 212 213 if (spec[0] == '/' && first_unqual) 214 { 215 s = stab("aliases.files", ST_MAP, ST_ENTER); 216 map = &s->s_map; 217 first_unqual = FALSE; 218 } 219 else 220 { 221 char aname[50]; 222 223 if (NAliasDBs >= MAXALIASDB) 224 { 225 syserr("Too many alias databases defined, %d max", 226 MAXALIASDB); 227 return; 228 } 229 (void) sprintf(aname, "Alias%d", NAliasDBs); 230 s = stab(aname, ST_MAP, ST_ENTER); 231 map = &s->s_map; 232 AliasDB[NAliasDBs] = map; 233 } 234 bzero(map, sizeof *map); 235 map->map_mname = s->s_name; 236 237 p = strpbrk(p, " ,/:"); 238 if (p != NULL && *p == ':') 239 { 240 /* map name */ 241 *p++ = '\0'; 242 class = spec; 243 spec = p; 244 } 245 else 246 { 247 class = "implicit"; 248 map->map_mflags = MF_OPTIONAL|MF_INCLNULL; 249 } 250 251 /* find end of spec */ 252 if (p != NULL) 253 p = strchr(p, ','); 254 if (p != NULL) 255 *p++ = '\0'; 256 257 if (tTd(27, 20)) 258 printf(" map %s:%s %s\n", class, s->s_name, spec); 259 260 /* look up class */ 261 s = stab(class, ST_MAPCLASS, ST_FIND); 262 if (s == NULL) 263 { 264 if (tTd(27, 1)) 265 printf("Unknown alias class %s\n", class); 266 } 267 else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags)) 268 { 269 syserr("setalias: map class %s can't handle aliases", 270 class); 271 } 272 else 273 { 274 map->map_class = &s->s_mapclass; 275 if (map->map_class->map_parse(map, spec)) 276 { 277 map->map_mflags |= MF_VALID|MF_ALIAS; 278 if (AliasDB[NAliasDBs] == map) 279 NAliasDBs++; 280 } 281 } 282 } 283 } 284 /* 285 ** ALIASWAIT -- wait for distinguished @:@ token to appear. 286 ** 287 ** This can decide to reopen or rebuild the alias file 288 ** 289 ** Parameters: 290 ** map -- a pointer to the map descriptor for this alias file. 291 ** ext -- the filename extension (e.g., ".db") for the 292 ** database file. 293 ** isopen -- if set, the database is already open, and we 294 ** should check for validity; otherwise, we are 295 ** just checking to see if it should be created. 296 ** 297 ** Returns: 298 ** TRUE -- if the database is open when we return. 299 ** FALSE -- if the database is closed when we return. 300 */ 301 302 bool 303 aliaswait(map, ext, isopen) 304 MAP *map; 305 char *ext; 306 int isopen; 307 { 308 bool attimeout = FALSE; 309 time_t mtime; 310 struct stat stb; 311 char buf[MAXNAME + 1]; 312 313 if (tTd(27, 3)) 314 printf("aliaswait(%s:%s)\n", 315 map->map_class->map_cname, map->map_file); 316 if (bitset(MF_ALIASWAIT, map->map_mflags)) 317 return isopen; 318 map->map_mflags |= MF_ALIASWAIT; 319 320 if (SafeAlias > 0) 321 { 322 auto int st; 323 time_t toolong = curtime() + SafeAlias; 324 unsigned int sleeptime = 2; 325 326 while (isopen && 327 map->map_class->map_lookup(map, "@", NULL, &st) == NULL) 328 { 329 if (curtime() > toolong) 330 { 331 /* we timed out */ 332 attimeout = TRUE; 333 break; 334 } 335 336 /* 337 ** Close and re-open the alias database in case 338 ** the one is mv'ed instead of cp'ed in. 339 */ 340 341 if (tTd(27, 2)) 342 printf("aliaswait: sleeping for %d seconds\n", 343 sleeptime); 344 345 map->map_class->map_close(map); 346 sleep(sleeptime); 347 sleeptime *= 2; 348 if (sleeptime > 60) 349 sleeptime = 60; 350 isopen = map->map_class->map_open(map, O_RDONLY); 351 } 352 } 353 354 /* see if we need to go into auto-rebuild mode */ 355 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 356 { 357 if (tTd(27, 3)) 358 printf("aliaswait: not rebuildable\n"); 359 map->map_mflags &= ~MF_ALIASWAIT; 360 return isopen; 361 } 362 if (stat(map->map_file, &stb) < 0) 363 { 364 if (tTd(27, 3)) 365 printf("aliaswait: no source file\n"); 366 map->map_mflags &= ~MF_ALIASWAIT; 367 return isopen; 368 } 369 mtime = stb.st_mtime; 370 (void) strcpy(buf, map->map_file); 371 if (ext != NULL) 372 (void) strcat(buf, ext); 373 if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout) 374 { 375 /* database is out of date */ 376 if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 377 { 378 bool oldSuprErrs; 379 380 message("auto-rebuilding alias database %s", buf); 381 oldSuprErrs = SuprErrs; 382 SuprErrs = TRUE; 383 if (isopen) 384 map->map_class->map_close(map); 385 rebuildaliases(map, TRUE); 386 isopen = map->map_class->map_open(map, O_RDONLY); 387 SuprErrs = oldSuprErrs; 388 } 389 else 390 { 391 #ifdef LOG 392 if (LogLevel > 3) 393 syslog(LOG_INFO, "alias database %s out of date", 394 buf); 395 #endif /* LOG */ 396 message("Warning: alias database %s out of date", buf); 397 } 398 } 399 map->map_mflags &= ~MF_ALIASWAIT; 400 return isopen; 401 } 402 /* 403 ** REBUILDALIASES -- rebuild the alias database. 404 ** 405 ** Parameters: 406 ** map -- the database to rebuild. 407 ** automatic -- set if this was automatically generated. 408 ** 409 ** Returns: 410 ** none. 411 ** 412 ** Side Effects: 413 ** Reads the text version of the database, builds the 414 ** DBM or DB version. 415 */ 416 417 void 418 rebuildaliases(map, automatic) 419 register MAP *map; 420 bool automatic; 421 { 422 FILE *af; 423 bool nolock = FALSE; 424 sigfunc_t oldsigint, oldsigquit; 425 #ifdef SIGTSTP 426 sigfunc_t oldsigtstp; 427 #endif 428 429 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 430 return; 431 432 /* try to lock the source file */ 433 if ((af = fopen(map->map_file, "r+")) == NULL) 434 { 435 if ((errno != EACCES && errno != EROFS) || automatic || 436 (af = fopen(map->map_file, "r")) == NULL) 437 { 438 int saveerr = errno; 439 440 if (tTd(27, 1)) 441 printf("Can't open %s: %s\n", 442 map->map_file, errstring(saveerr)); 443 if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags)) 444 message("newaliases: cannot open %s: %s", 445 map->map_file, errstring(saveerr)); 446 errno = 0; 447 return; 448 } 449 nolock = TRUE; 450 message("warning: cannot lock %s: %s", 451 map->map_file, errstring(errno)); 452 } 453 454 /* see if someone else is rebuilding the alias file */ 455 if (!nolock && 456 !lockfile(fileno(af), map->map_file, NULL, LOCK_EX|LOCK_NB)) 457 { 458 /* yes, they are -- wait until done */ 459 message("Alias file %s is already being rebuilt", 460 map->map_file); 461 if (OpMode != MD_INITALIAS) 462 { 463 /* wait for other rebuild to complete */ 464 (void) lockfile(fileno(af), map->map_file, NULL, 465 LOCK_EX); 466 } 467 (void) xfclose(af, "rebuildaliases1", map->map_file); 468 errno = 0; 469 return; 470 } 471 472 /* avoid denial-of-service attacks */ 473 resetlimits(); 474 oldsigint = setsignal(SIGINT, SIG_IGN); 475 oldsigquit = setsignal(SIGQUIT, SIG_IGN); 476 #ifdef SIGTSTP 477 oldsigtstp = setsignal(SIGTSTP, SIG_IGN); 478 #endif 479 480 if (map->map_class->map_open(map, O_RDWR)) 481 { 482 #ifdef LOG 483 if (LogLevel > 7) 484 { 485 syslog(LOG_NOTICE, "alias database %s %srebuilt by %s", 486 map->map_file, automatic ? "auto" : "", 487 username()); 488 } 489 #endif /* LOG */ 490 map->map_mflags |= MF_OPEN|MF_WRITABLE; 491 readaliases(map, af, !automatic, TRUE); 492 } 493 else 494 { 495 if (tTd(27, 1)) 496 printf("Can't create database for %s: %s\n", 497 map->map_file, errstring(errno)); 498 if (!automatic) 499 syserr("Cannot create database for alias file %s", 500 map->map_file); 501 } 502 503 /* close the file, thus releasing locks */ 504 xfclose(af, "rebuildaliases2", map->map_file); 505 506 /* add distinguished entries and close the database */ 507 if (bitset(MF_OPEN, map->map_mflags)) 508 map->map_class->map_close(map); 509 510 /* restore the old signals */ 511 (void) setsignal(SIGINT, oldsigint); 512 (void) setsignal(SIGQUIT, oldsigquit); 513 #ifdef SIGTSTP 514 (void) setsignal(SIGTSTP, oldsigtstp); 515 #endif 516 } 517 /* 518 ** READALIASES -- read and process the alias file. 519 ** 520 ** This routine implements the part of initaliases that occurs 521 ** when we are not going to use the DBM stuff. 522 ** 523 ** Parameters: 524 ** map -- the alias database descriptor. 525 ** af -- file to read the aliases from. 526 ** announcestats -- anounce statistics regarding number of 527 ** aliases, longest alias, etc. 528 ** logstats -- lot the same info. 529 ** 530 ** Returns: 531 ** none. 532 ** 533 ** Side Effects: 534 ** Reads aliasfile into the symbol table. 535 ** Optionally, builds the .dir & .pag files. 536 */ 537 538 void 539 readaliases(map, af, announcestats, logstats) 540 register MAP *map; 541 FILE *af; 542 bool announcestats; 543 bool logstats; 544 { 545 register char *p; 546 char *rhs; 547 bool skipping; 548 long naliases, bytes, longest; 549 ADDRESS al, bl; 550 char line[BUFSIZ]; 551 552 /* 553 ** Read and interpret lines 554 */ 555 556 FileName = map->map_file; 557 LineNumber = 0; 558 naliases = bytes = longest = 0; 559 skipping = FALSE; 560 while (fgets(line, sizeof (line), af) != NULL) 561 { 562 int lhssize, rhssize; 563 564 LineNumber++; 565 p = strchr(line, '\n'); 566 if (p != NULL) 567 *p = '\0'; 568 switch (line[0]) 569 { 570 case '#': 571 case '\0': 572 skipping = FALSE; 573 continue; 574 575 case ' ': 576 case '\t': 577 if (!skipping) 578 syserr("554 Non-continuation line starts with space"); 579 skipping = TRUE; 580 continue; 581 } 582 skipping = FALSE; 583 584 /* 585 ** Process the LHS 586 ** Find the colon separator, and parse the address. 587 ** It should resolve to a local name -- this will 588 ** be checked later (we want to optionally do 589 ** parsing of the RHS first to maximize error 590 ** detection). 591 */ 592 593 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 594 continue; 595 if (*p++ != ':') 596 { 597 syserr("554 missing colon"); 598 continue; 599 } 600 if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv) == NULL) 601 { 602 syserr("554 %.40s... illegal alias name", line); 603 continue; 604 } 605 606 /* 607 ** Process the RHS. 608 ** 'al' is the internal form of the LHS address. 609 ** 'p' points to the text of the RHS. 610 */ 611 612 while (isascii(*p) && isspace(*p)) 613 p++; 614 rhs = p; 615 for (;;) 616 { 617 register char c; 618 register char *nlp; 619 620 nlp = &p[strlen(p)]; 621 if (nlp[-1] == '\n') 622 *--nlp = '\0'; 623 624 if (CheckAliases) 625 { 626 /* do parsing & compression of addresses */ 627 while (*p != '\0') 628 { 629 auto char *delimptr; 630 631 while ((isascii(*p) && isspace(*p)) || 632 *p == ',') 633 p++; 634 if (*p == '\0') 635 break; 636 if (parseaddr(p, &bl, RF_COPYNONE, ',', 637 &delimptr, CurEnv) == NULL) 638 usrerr("553 %s... bad address", p); 639 p = delimptr; 640 } 641 } 642 else 643 { 644 p = nlp; 645 } 646 647 /* see if there should be a continuation line */ 648 c = fgetc(af); 649 if (!feof(af)) 650 (void) ungetc(c, af); 651 if (c != ' ' && c != '\t') 652 break; 653 654 /* read continuation line */ 655 if (fgets(p, sizeof line - (p - line), af) == NULL) 656 break; 657 LineNumber++; 658 659 /* check for line overflow */ 660 if (strchr(p, '\n') == NULL) 661 { 662 usrerr("554 alias too long"); 663 break; 664 } 665 } 666 if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags)) 667 { 668 syserr("554 %s... cannot alias non-local names", 669 al.q_paddr); 670 continue; 671 } 672 673 /* 674 ** Insert alias into symbol table or DBM file 675 */ 676 677 if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 678 makelower(al.q_user); 679 680 lhssize = strlen(al.q_user); 681 rhssize = strlen(rhs); 682 map->map_class->map_store(map, al.q_user, rhs); 683 684 if (al.q_paddr != NULL) 685 free(al.q_paddr); 686 if (al.q_host != NULL) 687 free(al.q_host); 688 if (al.q_user != NULL) 689 free(al.q_user); 690 691 /* statistics */ 692 naliases++; 693 bytes += lhssize + rhssize; 694 if (rhssize > longest) 695 longest = rhssize; 696 } 697 698 CurEnv->e_to = NULL; 699 FileName = NULL; 700 if (Verbose || announcestats) 701 message("%s: %d aliases, longest %d bytes, %d bytes total", 702 map->map_file, naliases, longest, bytes); 703 # ifdef LOG 704 if (LogLevel > 7 && logstats) 705 syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total", 706 map->map_file, naliases, longest, bytes); 707 # endif /* LOG */ 708 } 709 /* 710 ** FORWARD -- Try to forward mail 711 ** 712 ** This is similar but not identical to aliasing. 713 ** 714 ** Parameters: 715 ** user -- the name of the user who's mail we would like 716 ** to forward to. It must have been verified -- 717 ** i.e., the q_home field must have been filled 718 ** in. 719 ** sendq -- a pointer to the head of the send queue to 720 ** put this user's aliases in. 721 ** aliaslevel -- the current alias nesting depth. 722 ** e -- the current envelope. 723 ** 724 ** Returns: 725 ** none. 726 ** 727 ** Side Effects: 728 ** New names are added to send queues. 729 */ 730 731 void 732 forward(user, sendq, aliaslevel, e) 733 ADDRESS *user; 734 ADDRESS **sendq; 735 int aliaslevel; 736 register ENVELOPE *e; 737 { 738 char *pp; 739 char *ep; 740 741 if (tTd(27, 1)) 742 printf("forward(%s)\n", user->q_paddr); 743 744 if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) || 745 bitset(QBADADDR, user->q_flags)) 746 return; 747 if (user->q_home == NULL) 748 { 749 syserr("554 forward: no home"); 750 user->q_home = "/nosuchdirectory"; 751 } 752 753 /* good address -- look for .forward file in home */ 754 define('z', user->q_home, e); 755 define('u', user->q_user, e); 756 define('h', user->q_host, e); 757 if (ForwardPath == NULL) 758 ForwardPath = newstr("\201z/.forward"); 759 760 for (pp = ForwardPath; pp != NULL; pp = ep) 761 { 762 int err; 763 char buf[MAXPATHLEN+1]; 764 extern int include(); 765 766 ep = strchr(pp, ':'); 767 if (ep != NULL) 768 *ep = '\0'; 769 expand(pp, buf, sizeof buf, e); 770 if (ep != NULL) 771 *ep++ = ':'; 772 if (tTd(27, 3)) 773 printf("forward: trying %s\n", buf); 774 775 err = include(buf, TRUE, user, sendq, aliaslevel, e); 776 if (err == 0) 777 break; 778 else if (transienterror(err)) 779 { 780 /* we have to suspend this message */ 781 if (tTd(27, 2)) 782 printf("forward: transient error on %s\n", buf); 783 #ifdef LOG 784 if (LogLevel > 2) 785 syslog(LOG_ERR, "%s: forward %s: transient error: %s", 786 e->e_id == NULL ? "NOQUEUE" : e->e_id, 787 buf, errstring(err)); 788 #endif 789 message("%s: %s: message queued", buf, errstring(err)); 790 user->q_flags |= QQUEUEUP; 791 return; 792 } 793 } 794 } 795