1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)recipient.c 5.26 (Berkeley) 12/20/91"; 11 #endif /* not lint */ 12 13 # include <sys/types.h> 14 # include <sys/stat.h> 15 # include <sys/file.h> 16 # include <pwd.h> 17 # include "sendmail.h" 18 19 /* 20 ** SENDTOLIST -- Designate a send list. 21 ** 22 ** The parameter is a comma-separated list of people to send to. 23 ** This routine arranges to send to all of them. 24 ** 25 ** Parameters: 26 ** list -- the send list. 27 ** ctladdr -- the address template for the person to 28 ** send to -- effective uid/gid are important. 29 ** This is typically the alias that caused this 30 ** expansion. 31 ** sendq -- a pointer to the head of a queue to put 32 ** these people into. 33 ** 34 ** Returns: 35 ** none 36 ** 37 ** Side Effects: 38 ** none. 39 */ 40 41 # define MAXRCRSN 10 42 43 sendtolist(list, ctladdr, sendq) 44 char *list; 45 ADDRESS *ctladdr; 46 ADDRESS **sendq; 47 { 48 register char *p; 49 register ADDRESS *al; /* list of addresses to send to */ 50 bool firstone; /* set on first address sent */ 51 bool selfref; /* set if this list includes ctladdr */ 52 char delimiter; /* the address delimiter */ 53 54 if (tTd(25, 1)) 55 { 56 printf("sendto: %s\n ctladdr=", list); 57 printaddr(ctladdr, FALSE); 58 } 59 60 /* heuristic to determine old versus new style addresses */ 61 if (ctladdr == NULL && 62 (index(list, ',') != NULL || index(list, ';') != NULL || 63 index(list, '<') != NULL || index(list, '(') != NULL)) 64 CurEnv->e_flags &= ~EF_OLDSTYLE; 65 delimiter = ' '; 66 if (!bitset(EF_OLDSTYLE, CurEnv->e_flags) || ctladdr != NULL) 67 delimiter = ','; 68 69 firstone = TRUE; 70 selfref = FALSE; 71 al = NULL; 72 73 for (p = list; *p != '\0'; ) 74 { 75 register ADDRESS *a; 76 extern char *DelimChar; /* defined in prescan */ 77 78 /* parse the address */ 79 while (isspace(*p) || *p == ',') 80 p++; 81 a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter); 82 p = DelimChar; 83 if (a == NULL) 84 continue; 85 a->q_next = al; 86 a->q_alias = ctladdr; 87 88 /* see if this should be marked as a primary address */ 89 if (ctladdr == NULL || 90 (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags))) 91 a->q_flags |= QPRIMARY; 92 93 /* put on send queue or suppress self-reference */ 94 if (ctladdr != NULL && sameaddr(ctladdr, a)) 95 selfref = TRUE; 96 else 97 al = a; 98 firstone = FALSE; 99 } 100 101 /* if this alias doesn't include itself, delete ctladdr */ 102 if (!selfref && ctladdr != NULL) 103 ctladdr->q_flags |= QDONTSEND; 104 105 /* arrange to send to everyone on the local send list */ 106 while (al != NULL) 107 { 108 register ADDRESS *a = al; 109 extern ADDRESS *recipient(); 110 111 al = a->q_next; 112 setctladdr(a); 113 a = recipient(a, sendq); 114 115 /* arrange to inherit full name */ 116 if (a->q_fullname == NULL && ctladdr != NULL) 117 a->q_fullname = ctladdr->q_fullname; 118 } 119 120 CurEnv->e_to = NULL; 121 } 122 /* 123 ** RECIPIENT -- Designate a message recipient 124 ** 125 ** Saves the named person for future mailing. 126 ** 127 ** Parameters: 128 ** a -- the (preparsed) address header for the recipient. 129 ** sendq -- a pointer to the head of a queue to put the 130 ** recipient in. Duplicate supression is done 131 ** in this queue. 132 ** 133 ** Returns: 134 ** The actual address in the queue. This will be "a" if 135 ** the address is not a duplicate, else the original address. 136 ** 137 ** Side Effects: 138 ** none. 139 */ 140 141 extern ADDRESS *getctladdr(); 142 extern char *RcptLogFile; 143 144 ADDRESS * 145 recipient(a, sendq) 146 register ADDRESS *a; 147 register ADDRESS **sendq; 148 { 149 register ADDRESS *q; 150 ADDRESS **pq; 151 register struct mailer *m; 152 register char *p; 153 bool quoted = FALSE; /* set if the addr has a quote bit */ 154 char buf[MAXNAME]; /* unquoted image of the user name */ 155 extern bool safefile(); 156 157 CurEnv->e_to = a->q_paddr; 158 m = a->q_mailer; 159 errno = 0; 160 if (tTd(26, 1)) 161 { 162 printf("\nrecipient: "); 163 printaddr(a, FALSE); 164 } 165 166 /* break aliasing loops */ 167 if (AliasLevel > MAXRCRSN) 168 { 169 usrerr("aliasing/forwarding loop broken"); 170 return (a); 171 } 172 173 /* 174 ** Finish setting up address structure. 175 */ 176 177 /* set the queue timeout */ 178 a->q_timeout = TimeOut; 179 180 /* map user & host to lower case if requested on non-aliases */ 181 if (a->q_alias == NULL) 182 loweraddr(a); 183 184 /* get unquoted user for file, program or user.name check */ 185 (void) strcpy(buf, a->q_user); 186 for (p = buf; *p != '\0' && !quoted; p++) 187 { 188 if (!isascii(*p) && (*p & 0377) != (SpaceSub & 0377)) 189 quoted = TRUE; 190 } 191 stripquotes(buf, TRUE); 192 193 /* do sickly crude mapping for program mailing, etc. */ 194 if (m == LocalMailer && buf[0] == '|') 195 { 196 a->q_mailer = m = ProgMailer; 197 a->q_user++; 198 if (a->q_alias == NULL && !QueueRun && !ForceMail) 199 { 200 a->q_flags |= QDONTSEND|QBADADDR; 201 usrerr("Cannot mail directly to programs"); 202 } 203 } 204 205 /* 206 ** Look up this person in the recipient list. 207 ** If they are there already, return, otherwise continue. 208 ** If the list is empty, just add it. Notice the cute 209 ** hack to make from addresses suppress things correctly: 210 ** the QDONTSEND bit will be set in the send list. 211 ** [Please note: the emphasis is on "hack."] 212 */ 213 214 for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) 215 { 216 if (!ForceMail && sameaddr(q, a)) 217 { 218 if (tTd(26, 1)) 219 { 220 printf("%s in sendq: ", a->q_paddr); 221 printaddr(q, FALSE); 222 } 223 if (!bitset(QDONTSEND, a->q_flags)) 224 message(Arpa_Info, "duplicate suppressed"); 225 if (!bitset(QPRIMARY, q->q_flags)) 226 q->q_flags |= a->q_flags; 227 return (q); 228 } 229 } 230 231 /* add address on list */ 232 *pq = a; 233 a->q_next = NULL; 234 CurEnv->e_nrcpts++; 235 236 if (a->q_alias == NULL && RcptLogFile != NULL && 237 !bitset(QDONTSEND, a->q_flags)) 238 { 239 static int RcptLogFd = -1; 240 241 /* 242 ** Log the incoming recipient name before aliasing, 243 ** expanding, forwarding, rewriting, and all that jazz. 244 ** We'll use this to track down out-of-date aliases, 245 ** host names, and so forth. 246 */ 247 248 if (RcptLogFd < 0) 249 { 250 /* try to open the log file */ 251 RcptLogFd = open(RcptLogFile, O_WRONLY|O_APPEND|O_CREAT, 0666); 252 if (RcptLogFd >= 0) 253 (void) fcntl(RcptLogFd, F_SETFD, 1); 254 } 255 if (RcptLogFd >= 0) 256 { 257 int l = strlen(a->q_paddr); 258 259 a->q_paddr[l] = '\n'; 260 if (write(RcptLogFd, a->q_paddr, l + 1) < 0) 261 { 262 (void) close(RcptLogFd); 263 RcptLogFd = -1; 264 } 265 a->q_paddr[l] = '\0'; 266 } 267 } 268 269 /* 270 ** Alias the name and handle :include: specs. 271 */ 272 273 if (m == LocalMailer && !bitset(QDONTSEND, a->q_flags)) 274 { 275 if (strncmp(a->q_user, ":include:", 9) == 0) 276 { 277 a->q_flags |= QDONTSEND; 278 if (a->q_alias == NULL && !QueueRun && !ForceMail) 279 { 280 a->q_flags |= QBADADDR; 281 usrerr("Cannot mail directly to :include:s"); 282 } 283 else 284 { 285 message(Arpa_Info, "including file %s", &a->q_user[9]); 286 include(&a->q_user[9], " sending", a, sendq); 287 } 288 } 289 else 290 { 291 /* try aliasing */ 292 alias(a, sendq); 293 294 # ifdef USERDB 295 /* if not aliased, look it up in the user database */ 296 if (!bitset(QDONTSEND|QNOTREMOTE, a->q_flags)) 297 { 298 extern int udbexpand(); 299 300 if (udbexpand(a, sendq) == EX_TEMPFAIL) 301 { 302 a->q_flags |= QQUEUEUP; 303 if (CurEnv->e_message == NULL) 304 CurEnv->e_message = newstr("Deferred: user database error"); 305 # ifdef LOG 306 if (LogLevel > 3) 307 syslog(LOG_INFO, "%s: deferred: udbexpand", 308 CurEnv->e_id); 309 # endif 310 message(Arpa_Info, "queued (user database error)"); 311 return (a); 312 } 313 } 314 # endif 315 } 316 } 317 318 /* 319 ** If the user is local and still being sent, verify that 320 ** the address is good. If it is, try to forward. 321 ** If the address is already good, we have a forwarding 322 ** loop. This can be broken by just sending directly to 323 ** the user (which is probably correct anyway). 324 */ 325 326 if (bitset(QDONTSEND, a->q_flags) || m != LocalMailer) 327 return (a); 328 329 /* see if this is to a file */ 330 if (buf[0] == '/') 331 { 332 struct stat stb; 333 extern bool writable(); 334 335 p = rindex(buf, '/'); 336 /* check if writable or creatable */ 337 if (a->q_alias == NULL && !QueueRun && !ForceMail) 338 { 339 a->q_flags |= QDONTSEND|QBADADDR; 340 usrerr("Cannot mail directly to files"); 341 } 342 else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) : 343 (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC))) 344 { 345 a->q_flags |= QBADADDR; 346 giveresponse(EX_CANTCREAT, m, CurEnv); 347 } 348 return (a); 349 } 350 351 /* 352 ** If we have a level two config file, then pass the name through 353 ** Ruleset 5 before sending it off. Ruleset 5 has the right 354 ** to send rewrite it to another mailer. This gives us a hook 355 ** after local aliasing has been done. 356 */ 357 358 if (tTd(29, 5)) 359 { 360 printf("recipient: testing local? cl=%d, rr5=%x\n\t", 361 ConfigLevel, RewriteRules[5]); 362 printaddr(a, FALSE); 363 } 364 if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 && 365 RewriteRules[5] != NULL) 366 { 367 maplocaluser(a, sendq); 368 } 369 370 /* 371 ** If it didn't get rewritten to another mailer, go ahead 372 ** and deliver it. 373 */ 374 375 if (!bitset(QDONTSEND, a->q_flags)) 376 { 377 register struct passwd *pw; 378 extern struct passwd *finduser(); 379 380 /* warning -- finduser may trash buf */ 381 pw = finduser(buf); 382 if (pw == NULL) 383 { 384 a->q_flags |= QBADADDR; 385 giveresponse(EX_NOUSER, m, CurEnv); 386 } 387 else 388 { 389 char nbuf[MAXNAME]; 390 391 if (strcmp(a->q_user, pw->pw_name) != 0) 392 { 393 a->q_user = newstr(pw->pw_name); 394 (void) strcpy(buf, pw->pw_name); 395 } 396 a->q_home = newstr(pw->pw_dir); 397 a->q_uid = pw->pw_uid; 398 a->q_gid = pw->pw_gid; 399 a->q_flags |= QGOODUID; 400 buildfname(pw->pw_gecos, pw->pw_name, nbuf); 401 if (nbuf[0] != '\0') 402 a->q_fullname = newstr(nbuf); 403 if (!quoted) 404 forward(a, sendq); 405 } 406 } 407 return (a); 408 } 409 /* 410 ** FINDUSER -- find the password entry for a user. 411 ** 412 ** This looks a lot like getpwnam, except that it may want to 413 ** do some fancier pattern matching in /etc/passwd. 414 ** 415 ** This routine contains most of the time of many sendmail runs. 416 ** It deserves to be optimized. 417 ** 418 ** Parameters: 419 ** name -- the name to match against. 420 ** 421 ** Returns: 422 ** A pointer to a pw struct. 423 ** NULL if name is unknown or ambiguous. 424 ** 425 ** Side Effects: 426 ** may modify name. 427 */ 428 429 struct passwd * 430 finduser(name) 431 char *name; 432 { 433 register struct passwd *pw; 434 register char *p; 435 extern struct passwd *getpwent(); 436 extern struct passwd *getpwnam(); 437 438 /* map upper => lower case */ 439 for (p = name; *p != '\0'; p++) 440 { 441 if (isascii(*p) && isupper(*p)) 442 *p = tolower(*p); 443 } 444 445 /* look up this login name using fast path */ 446 if ((pw = getpwnam(name)) != NULL) 447 return (pw); 448 449 /* search for a matching full name instead */ 450 for (p = name; *p != '\0'; p++) 451 { 452 if (*p == (SpaceSub & 0177) || *p == '_') 453 *p = ' '; 454 } 455 (void) setpwent(); 456 while ((pw = getpwent()) != NULL) 457 { 458 char buf[MAXNAME]; 459 460 buildfname(pw->pw_gecos, pw->pw_name, buf); 461 if (index(buf, ' ') != NULL && !strcasecmp(buf, name)) 462 { 463 message(Arpa_Info, "sending to login name %s", pw->pw_name); 464 return (pw); 465 } 466 } 467 return (NULL); 468 } 469 /* 470 ** WRITABLE -- predicate returning if the file is writable. 471 ** 472 ** This routine must duplicate the algorithm in sys/fio.c. 473 ** Unfortunately, we cannot use the access call since we 474 ** won't necessarily be the real uid when we try to 475 ** actually open the file. 476 ** 477 ** Notice that ANY file with ANY execute bit is automatically 478 ** not writable. This is also enforced by mailfile. 479 ** 480 ** Parameters: 481 ** s -- pointer to a stat struct for the file. 482 ** 483 ** Returns: 484 ** TRUE -- if we will be able to write this file. 485 ** FALSE -- if we cannot write this file. 486 ** 487 ** Side Effects: 488 ** none. 489 */ 490 491 bool 492 writable(s) 493 register struct stat *s; 494 { 495 int euid, egid; 496 int bits; 497 498 if (bitset(0111, s->st_mode)) 499 return (FALSE); 500 euid = getruid(); 501 egid = getrgid(); 502 if (geteuid() == 0) 503 { 504 if (bitset(S_ISUID, s->st_mode)) 505 euid = s->st_uid; 506 if (bitset(S_ISGID, s->st_mode)) 507 egid = s->st_gid; 508 } 509 510 if (euid == 0) 511 return (TRUE); 512 bits = S_IWRITE; 513 if (euid != s->st_uid) 514 { 515 bits >>= 3; 516 if (egid != s->st_gid) 517 bits >>= 3; 518 } 519 return ((s->st_mode & bits) != 0); 520 } 521 /* 522 ** INCLUDE -- handle :include: specification. 523 ** 524 ** Parameters: 525 ** fname -- filename to include. 526 ** msg -- message to print in verbose mode. 527 ** ctladdr -- address template to use to fill in these 528 ** addresses -- effective user/group id are 529 ** the important things. 530 ** sendq -- a pointer to the head of the send queue 531 ** to put these addresses in. 532 ** 533 ** Returns: 534 ** none. 535 ** 536 ** Side Effects: 537 ** reads the :include: file and sends to everyone 538 ** listed in that file. 539 */ 540 541 include(fname, msg, ctladdr, sendq) 542 char *fname; 543 char *msg; 544 ADDRESS *ctladdr; 545 ADDRESS **sendq; 546 { 547 char buf[MAXLINE]; 548 register FILE *fp; 549 char *oldto = CurEnv->e_to; 550 char *oldfilename = FileName; 551 int oldlinenumber = LineNumber; 552 553 fp = fopen(fname, "r"); 554 if (fp == NULL) 555 { 556 usrerr("Cannot open %s", fname); 557 return; 558 } 559 if (getctladdr(ctladdr) == NULL) 560 { 561 struct stat st; 562 563 if (fstat(fileno(fp), &st) < 0) 564 syserr("Cannot fstat %s!", fname); 565 ctladdr->q_uid = st.st_uid; 566 ctladdr->q_gid = st.st_gid; 567 ctladdr->q_flags |= QGOODUID; 568 } 569 570 /* read the file -- each line is a comma-separated list. */ 571 FileName = fname; 572 LineNumber = 0; 573 while (fgets(buf, sizeof buf, fp) != NULL) 574 { 575 register char *p = index(buf, '\n'); 576 577 LineNumber++; 578 if (p != NULL) 579 *p = '\0'; 580 if (buf[0] == '\0' || buf[0] == '#') 581 continue; 582 CurEnv->e_to = oldto; 583 message(Arpa_Info, "%s to %s", msg, buf); 584 AliasLevel++; 585 sendtolist(buf, ctladdr, sendq); 586 AliasLevel--; 587 } 588 589 (void) fclose(fp); 590 FileName = oldfilename; 591 LineNumber = oldlinenumber; 592 } 593 /* 594 ** SENDTOARGV -- send to an argument vector. 595 ** 596 ** Parameters: 597 ** argv -- argument vector to send to. 598 ** 599 ** Returns: 600 ** none. 601 ** 602 ** Side Effects: 603 ** puts all addresses on the argument vector onto the 604 ** send queue. 605 */ 606 607 sendtoargv(argv) 608 register char **argv; 609 { 610 register char *p; 611 612 while ((p = *argv++) != NULL) 613 { 614 if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at")) 615 { 616 char nbuf[MAXNAME]; 617 618 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf) 619 usrerr("address overflow"); 620 else 621 { 622 (void) strcpy(nbuf, p); 623 (void) strcat(nbuf, "@"); 624 (void) strcat(nbuf, argv[1]); 625 p = newstr(nbuf); 626 argv += 2; 627 } 628 } 629 sendtolist(p, (ADDRESS *) NULL, &CurEnv->e_sendqueue); 630 } 631 } 632 /* 633 ** GETCTLADDR -- get controlling address from an address header. 634 ** 635 ** If none, get one corresponding to the effective userid. 636 ** 637 ** Parameters: 638 ** a -- the address to find the controller of. 639 ** 640 ** Returns: 641 ** the controlling address. 642 ** 643 ** Side Effects: 644 ** none. 645 */ 646 647 ADDRESS * 648 getctladdr(a) 649 register ADDRESS *a; 650 { 651 while (a != NULL && !bitset(QGOODUID, a->q_flags)) 652 a = a->q_alias; 653 return (a); 654 } 655