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