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