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