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.25 (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 } 253 if (RcptLogFd >= 0) 254 { 255 int l = strlen(a->q_paddr); 256 257 a->q_paddr[l] = '\n'; 258 if (write(RcptLogFd, a->q_paddr, l + 1) < 0) 259 { 260 (void) close(RcptLogFd); 261 RcptLogFd = -1; 262 } 263 a->q_paddr[l] = '\0'; 264 } 265 } 266 267 /* 268 ** Alias the name and handle :include: specs. 269 */ 270 271 if (m == LocalMailer && !bitset(QDONTSEND, a->q_flags)) 272 { 273 if (strncmp(a->q_user, ":include:", 9) == 0) 274 { 275 a->q_flags |= QDONTSEND; 276 if (a->q_alias == NULL && !QueueRun && !ForceMail) 277 { 278 a->q_flags |= QBADADDR; 279 usrerr("Cannot mail directly to :include:s"); 280 } 281 else 282 { 283 message(Arpa_Info, "including file %s", &a->q_user[9]); 284 include(&a->q_user[9], " sending", a, sendq); 285 } 286 } 287 else 288 { 289 /* try aliasing */ 290 alias(a, sendq); 291 292 # ifdef USERDB 293 /* if not aliased, look it up in the user database */ 294 if (!bitset(QDONTSEND|QNOTREMOTE, a->q_flags)) 295 { 296 extern int udbexpand(); 297 298 if (udbexpand(a, sendq) == EX_TEMPFAIL) 299 { 300 a->q_flags |= QQUEUEUP; 301 if (CurEnv->e_message == NULL) 302 CurEnv->e_message = newstr("Deferred: user database error"); 303 # ifdef LOG 304 if (LogLevel > 3) 305 syslog(LOG_INFO, "%s: deferred: udbexpand", 306 CurEnv->e_id); 307 # endif 308 message(Arpa_Info, "queued (user database error)"); 309 return (a); 310 } 311 } 312 # endif 313 } 314 } 315 316 /* 317 ** If the user is local and still being sent, verify that 318 ** the address is good. If it is, try to forward. 319 ** If the address is already good, we have a forwarding 320 ** loop. This can be broken by just sending directly to 321 ** the user (which is probably correct anyway). 322 */ 323 324 if (bitset(QDONTSEND, a->q_flags) || m != LocalMailer) 325 return (a); 326 327 /* see if this is to a file */ 328 if (buf[0] == '/') 329 { 330 struct stat stb; 331 extern bool writable(); 332 333 p = rindex(buf, '/'); 334 /* check if writable or creatable */ 335 if (a->q_alias == NULL && !QueueRun && !ForceMail) 336 { 337 a->q_flags |= QDONTSEND|QBADADDR; 338 usrerr("Cannot mail directly to files"); 339 } 340 else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) : 341 (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC))) 342 { 343 a->q_flags |= QBADADDR; 344 giveresponse(EX_CANTCREAT, m, CurEnv); 345 } 346 return (a); 347 } 348 349 /* 350 ** If we have a level two config file, then pass the name through 351 ** Ruleset 5 before sending it off. Ruleset 5 has the right 352 ** to send rewrite it to another mailer. This gives us a hook 353 ** after local aliasing has been done. 354 */ 355 356 if (tTd(29, 5)) 357 { 358 printf("recipient: testing local? cl=%d, rr5=%x\n\t", 359 ConfigLevel, RewriteRules[5]); 360 printaddr(a, FALSE); 361 } 362 if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 && 363 RewriteRules[5] != NULL) 364 { 365 maplocaluser(a, sendq); 366 } 367 368 /* 369 ** If it didn't get rewritten to another mailer, go ahead 370 ** and deliver it. 371 */ 372 373 if (!bitset(QDONTSEND, a->q_flags)) 374 { 375 register struct passwd *pw; 376 extern struct passwd *finduser(); 377 378 /* warning -- finduser may trash buf */ 379 pw = finduser(buf); 380 if (pw == NULL) 381 { 382 a->q_flags |= QBADADDR; 383 giveresponse(EX_NOUSER, m, CurEnv); 384 } 385 else 386 { 387 char nbuf[MAXNAME]; 388 389 if (strcmp(a->q_user, pw->pw_name) != 0) 390 { 391 a->q_user = newstr(pw->pw_name); 392 (void) strcpy(buf, pw->pw_name); 393 } 394 a->q_home = newstr(pw->pw_dir); 395 a->q_uid = pw->pw_uid; 396 a->q_gid = pw->pw_gid; 397 a->q_flags |= QGOODUID; 398 buildfname(pw->pw_gecos, pw->pw_name, nbuf); 399 if (nbuf[0] != '\0') 400 a->q_fullname = newstr(nbuf); 401 if (!quoted) 402 forward(a, sendq); 403 } 404 } 405 return (a); 406 } 407 /* 408 ** FINDUSER -- find the password entry for a user. 409 ** 410 ** This looks a lot like getpwnam, except that it may want to 411 ** do some fancier pattern matching in /etc/passwd. 412 ** 413 ** This routine contains most of the time of many sendmail runs. 414 ** It deserves to be optimized. 415 ** 416 ** Parameters: 417 ** name -- the name to match against. 418 ** 419 ** Returns: 420 ** A pointer to a pw struct. 421 ** NULL if name is unknown or ambiguous. 422 ** 423 ** Side Effects: 424 ** may modify name. 425 */ 426 427 struct passwd * 428 finduser(name) 429 char *name; 430 { 431 register struct passwd *pw; 432 register char *p; 433 extern struct passwd *getpwent(); 434 extern struct passwd *getpwnam(); 435 436 /* map upper => lower case */ 437 for (p = name; *p != '\0'; p++) 438 { 439 if (isascii(*p) && isupper(*p)) 440 *p = tolower(*p); 441 } 442 443 /* look up this login name using fast path */ 444 if ((pw = getpwnam(name)) != NULL) 445 return (pw); 446 447 /* search for a matching full name instead */ 448 for (p = name; *p != '\0'; p++) 449 { 450 if (*p == (SpaceSub & 0177) || *p == '_') 451 *p = ' '; 452 } 453 (void) setpwent(); 454 while ((pw = getpwent()) != NULL) 455 { 456 char buf[MAXNAME]; 457 458 buildfname(pw->pw_gecos, pw->pw_name, buf); 459 if (index(buf, ' ') != NULL && !strcasecmp(buf, name)) 460 { 461 message(Arpa_Info, "sending to login name %s", pw->pw_name); 462 return (pw); 463 } 464 } 465 return (NULL); 466 } 467 /* 468 ** WRITABLE -- predicate returning if the file is writable. 469 ** 470 ** This routine must duplicate the algorithm in sys/fio.c. 471 ** Unfortunately, we cannot use the access call since we 472 ** won't necessarily be the real uid when we try to 473 ** actually open the file. 474 ** 475 ** Notice that ANY file with ANY execute bit is automatically 476 ** not writable. This is also enforced by mailfile. 477 ** 478 ** Parameters: 479 ** s -- pointer to a stat struct for the file. 480 ** 481 ** Returns: 482 ** TRUE -- if we will be able to write this file. 483 ** FALSE -- if we cannot write this file. 484 ** 485 ** Side Effects: 486 ** none. 487 */ 488 489 bool 490 writable(s) 491 register struct stat *s; 492 { 493 int euid, egid; 494 int bits; 495 496 if (bitset(0111, s->st_mode)) 497 return (FALSE); 498 euid = getruid(); 499 egid = getrgid(); 500 if (geteuid() == 0) 501 { 502 if (bitset(S_ISUID, s->st_mode)) 503 euid = s->st_uid; 504 if (bitset(S_ISGID, s->st_mode)) 505 egid = s->st_gid; 506 } 507 508 if (euid == 0) 509 return (TRUE); 510 bits = S_IWRITE; 511 if (euid != s->st_uid) 512 { 513 bits >>= 3; 514 if (egid != s->st_gid) 515 bits >>= 3; 516 } 517 return ((s->st_mode & bits) != 0); 518 } 519 /* 520 ** INCLUDE -- handle :include: specification. 521 ** 522 ** Parameters: 523 ** fname -- filename to include. 524 ** msg -- message to print in verbose mode. 525 ** ctladdr -- address template to use to fill in these 526 ** addresses -- effective user/group id are 527 ** the important things. 528 ** sendq -- a pointer to the head of the send queue 529 ** to put these addresses in. 530 ** 531 ** Returns: 532 ** none. 533 ** 534 ** Side Effects: 535 ** reads the :include: file and sends to everyone 536 ** listed in that file. 537 */ 538 539 include(fname, msg, ctladdr, sendq) 540 char *fname; 541 char *msg; 542 ADDRESS *ctladdr; 543 ADDRESS **sendq; 544 { 545 char buf[MAXLINE]; 546 register FILE *fp; 547 char *oldto = CurEnv->e_to; 548 char *oldfilename = FileName; 549 int oldlinenumber = LineNumber; 550 551 fp = fopen(fname, "r"); 552 if (fp == NULL) 553 { 554 usrerr("Cannot open %s", fname); 555 return; 556 } 557 if (getctladdr(ctladdr) == NULL) 558 { 559 struct stat st; 560 561 if (fstat(fileno(fp), &st) < 0) 562 syserr("Cannot fstat %s!", fname); 563 ctladdr->q_uid = st.st_uid; 564 ctladdr->q_gid = st.st_gid; 565 ctladdr->q_flags |= QGOODUID; 566 } 567 568 /* read the file -- each line is a comma-separated list. */ 569 FileName = fname; 570 LineNumber = 0; 571 while (fgets(buf, sizeof buf, fp) != NULL) 572 { 573 register char *p = index(buf, '\n'); 574 575 LineNumber++; 576 if (p != NULL) 577 *p = '\0'; 578 if (buf[0] == '\0' || buf[0] == '#') 579 continue; 580 CurEnv->e_to = oldto; 581 message(Arpa_Info, "%s to %s", msg, buf); 582 AliasLevel++; 583 sendtolist(buf, ctladdr, sendq); 584 AliasLevel--; 585 } 586 587 (void) fclose(fp); 588 FileName = oldfilename; 589 LineNumber = oldlinenumber; 590 } 591 /* 592 ** SENDTOARGV -- send to an argument vector. 593 ** 594 ** Parameters: 595 ** argv -- argument vector to send to. 596 ** 597 ** Returns: 598 ** none. 599 ** 600 ** Side Effects: 601 ** puts all addresses on the argument vector onto the 602 ** send queue. 603 */ 604 605 sendtoargv(argv) 606 register char **argv; 607 { 608 register char *p; 609 610 while ((p = *argv++) != NULL) 611 { 612 if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at")) 613 { 614 char nbuf[MAXNAME]; 615 616 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf) 617 usrerr("address overflow"); 618 else 619 { 620 (void) strcpy(nbuf, p); 621 (void) strcat(nbuf, "@"); 622 (void) strcat(nbuf, argv[1]); 623 p = newstr(nbuf); 624 argv += 2; 625 } 626 } 627 sendtolist(p, (ADDRESS *) NULL, &CurEnv->e_sendqueue); 628 } 629 } 630 /* 631 ** GETCTLADDR -- get controlling address from an address header. 632 ** 633 ** If none, get one corresponding to the effective userid. 634 ** 635 ** Parameters: 636 ** a -- the address to find the controller of. 637 ** 638 ** Returns: 639 ** the controlling address. 640 ** 641 ** Side Effects: 642 ** none. 643 */ 644 645 ADDRESS * 646 getctladdr(a) 647 register ADDRESS *a; 648 { 649 while (a != NULL && !bitset(QGOODUID, a->q_flags)) 650 a = a->q_alias; 651 return (a); 652 } 653