122704Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 362525Sbostic * Copyright (c) 1988, 1993 462525Sbostic * The Regents of the University of California. All rights reserved. 533729Sbostic * 642826Sbostic * %sccs.include.redist.c% 733729Sbostic */ 822704Sdist 922704Sdist #ifndef lint 10*68498Seric static char sccsid[] = "@(#)envelope.c 8.51 (Berkeley) 03/07/95"; 1133729Sbostic #endif /* not lint */ 1222704Sdist 1358332Seric #include "sendmail.h" 149536Seric #include <pwd.h> 159536Seric 169536Seric /* 179536Seric ** NEWENVELOPE -- allocate a new envelope 189536Seric ** 199536Seric ** Supports inheritance. 209536Seric ** 219536Seric ** Parameters: 229536Seric ** e -- the new envelope to fill in. 2358179Seric ** parent -- the envelope to be the parent of e. 249536Seric ** 259536Seric ** Returns: 269536Seric ** e. 279536Seric ** 289536Seric ** Side Effects: 299536Seric ** none. 309536Seric */ 319536Seric 329536Seric ENVELOPE * 3358179Seric newenvelope(e, parent) 349536Seric register ENVELOPE *e; 3558179Seric register ENVELOPE *parent; 369536Seric { 379536Seric extern putheader(), putbody(); 3825611Seric extern ENVELOPE BlankEnvelope; 399536Seric 4058179Seric if (e == parent && e->e_parent != NULL) 419536Seric parent = e->e_parent; 4225611Seric clearenvelope(e, TRUE); 4324944Seric if (e == CurEnv) 4424944Seric bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from); 4524944Seric else 4624944Seric bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); 479536Seric e->e_parent = parent; 489536Seric e->e_ctime = curtime(); 4956215Seric if (parent != NULL) 5056215Seric e->e_msgpriority = parent->e_msgsize; 519536Seric e->e_puthdr = putheader; 529536Seric e->e_putbody = putbody; 539536Seric if (CurEnv->e_xfp != NULL) 549536Seric (void) fflush(CurEnv->e_xfp); 559536Seric 569536Seric return (e); 579536Seric } 589536Seric /* 599536Seric ** DROPENVELOPE -- deallocate an envelope. 609536Seric ** 619536Seric ** Parameters: 629536Seric ** e -- the envelope to deallocate. 639536Seric ** 649536Seric ** Returns: 659536Seric ** none. 669536Seric ** 679536Seric ** Side Effects: 689536Seric ** housekeeping necessary to dispose of an envelope. 699536Seric ** Unlocks this queue file. 709536Seric */ 719536Seric 7260494Seric void 739536Seric dropenvelope(e) 749536Seric register ENVELOPE *e; 759536Seric { 769536Seric bool queueit = FALSE; 77*68498Seric bool failure_return = FALSE; 78*68498Seric bool success_return = FALSE; 799536Seric register ADDRESS *q; 8057943Seric char *id = e->e_id; 81*68498Seric bool return_no, return_yes; 8263753Seric char buf[MAXLINE]; 839536Seric 849536Seric if (tTd(50, 1)) 859536Seric { 8658680Seric printf("dropenvelope %x: id=", e); 879536Seric xputs(e->e_id); 8865089Seric printf(", flags=0x%x\n", e->e_flags); 8963753Seric if (tTd(50, 10)) 9063753Seric { 9163753Seric printf("sendq="); 9263753Seric printaddr(e->e_sendqueue, TRUE); 9363753Seric } 949536Seric } 9557943Seric 9658680Seric /* we must have an id to remove disk files */ 9757943Seric if (id == NULL) 9858680Seric return; 9957943Seric 1009536Seric #ifdef LOG 10165089Seric if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) 10265089Seric logsender(e, NULL); 10358020Seric if (LogLevel > 84) 10465089Seric syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=0x%x, pid=%d", 10557943Seric id, e->e_flags, getpid()); 10656795Seric #endif /* LOG */ 10765089Seric e->e_flags &= ~EF_LOGSENDER; 1089536Seric 10963753Seric /* post statistics */ 11063753Seric poststats(StatFile); 11163753Seric 1129536Seric /* 1139536Seric ** Extract state information from dregs of send list. 1149536Seric */ 1159536Seric 11664743Seric e->e_flags &= ~EF_QUEUERUN; 117*68498Seric return_no = return_yes = FALSE; 1189536Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 1199536Seric { 1209536Seric if (bitset(QQUEUEUP, q->q_flags)) 1219536Seric queueit = TRUE; 122*68498Seric 123*68498Seric /* see if a notification is needed */ 124*68498Seric if (e->e_df != NULL && 125*68498Seric bitset(QBADADDR, q->q_flags) && 126*68498Seric bitset(QPINGONFAILURE, q->q_flags)) 12763839Seric { 128*68498Seric failure_return = TRUE; 129*68498Seric if (q->q_owner == NULL && !emptyaddr(&e->e_from)) 13063839Seric (void) sendtolist(e->e_from.q_paddr, NULL, 131*68498Seric &e->e_errorqueue, 0, e); 13263839Seric } 133*68498Seric else if (bitset(QSENT, q->q_flags) && 134*68498Seric bitnset(M_LOCALMAILER, q->q_mailer->m_flags) && 135*68498Seric bitset(QPINGONSUCCESS, q->q_flags)) 136*68498Seric { 137*68498Seric success_return = TRUE; 138*68498Seric } 139*68498Seric else if (bitset(QRELAYED, q->q_flags)) 140*68498Seric { 141*68498Seric success_return = TRUE; 142*68498Seric } 143*68498Seric else 144*68498Seric continue; 145*68498Seric 146*68498Seric /* common code for error returns and return receipts */ 147*68498Seric 148*68498Seric /* test for returning the body */ 149*68498Seric if (bitset(QHAS_RET_PARAM, q->q_flags)) 150*68498Seric { 151*68498Seric if (bitset(QRET_HDRS, q->q_flags)) 152*68498Seric return_no = TRUE; 153*68498Seric else 154*68498Seric return_yes = TRUE; 155*68498Seric } 1569536Seric } 157*68498Seric if (return_no && !return_yes) 158*68498Seric e->e_flags |= EF_NORETURN; 1599536Seric 1609536Seric /* 16163753Seric ** See if the message timed out. 16263753Seric */ 16363753Seric 16463753Seric if (!queueit) 16563753Seric /* nothing to do */ ; 166*68498Seric else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) 16763753Seric { 16863839Seric (void) sprintf(buf, "Cannot send message for %s", 169*68498Seric pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 17063839Seric if (e->e_message != NULL) 17163839Seric free(e->e_message); 17263839Seric e->e_message = newstr(buf); 17363839Seric message(buf); 17463839Seric e->e_flags |= EF_CLRQUEUE; 175*68498Seric failure_return = TRUE; 17663787Seric fprintf(e->e_xfp, "Message could not be delivered for %s\n", 177*68498Seric pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 17863787Seric fprintf(e->e_xfp, "Message will be deleted from queue\n"); 17963787Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 18063787Seric { 18163787Seric if (bitset(QQUEUEUP, q->q_flags)) 18263787Seric q->q_flags |= QBADADDR; 18363787Seric } 18463753Seric } 185*68498Seric else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && 186*68498Seric curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass]) 18763753Seric { 188*68498Seric bool delay_return = FALSE; 189*68498Seric 190*68498Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 191*68498Seric { 192*68498Seric if (bitset(QQUEUEUP, q->q_flags) && 193*68498Seric bitset(QPINGONDELAY, q->q_flags)) 194*68498Seric { 195*68498Seric q->q_flags |= QREPORT; 196*68498Seric delay_return = TRUE; 197*68498Seric } 198*68498Seric } 199*68498Seric if (delay_return && 200*68498Seric !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && 20163753Seric e->e_class >= 0 && 202*68498Seric strcmp(e->e_from.q_paddr, "<>") != 0 && 203*68498Seric strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && 204*68498Seric (strlen(e->e_from.q_paddr) <= 8 || 205*68498Seric strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0)) 20663753Seric { 20763753Seric (void) sprintf(buf, 208*68498Seric "Warning: cannot send message for %s", 209*68498Seric pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); 21063753Seric if (e->e_message != NULL) 21163753Seric free(e->e_message); 21263753Seric e->e_message = newstr(buf); 21363753Seric message(buf); 21463839Seric e->e_flags |= EF_WARNING; 215*68498Seric failure_return = TRUE; 21663753Seric } 21763753Seric fprintf(e->e_xfp, 21863753Seric "Warning: message still undelivered after %s\n", 219*68498Seric pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); 22063753Seric fprintf(e->e_xfp, "Will keep trying until message is %s old\n", 221*68498Seric pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 222*68498Seric } 223*68498Seric 224*68498Seric if (tTd(50, 2)) 225*68498Seric printf("failure_return=%d success_return=%d queueit=%d\n", 226*68498Seric failure_return, success_return, queueit); 227*68498Seric 228*68498Seric /* 229*68498Seric ** If we had some fatal error, but no addresses are marked as 230*68498Seric ** bad, mark them _all_ as bad. 231*68498Seric */ 232*68498Seric 233*68498Seric if (bitset(EF_FATALERRS, e->e_flags) && !failure_return) 234*68498Seric { 235*68498Seric failure_return = TRUE; 23668019Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 23768019Seric { 238*68498Seric if (!bitset(QDONTSEND, q->q_flags)) 239*68498Seric q->q_flags |= QBADADDR; 24068019Seric } 24168019Seric } 24268019Seric 24368019Seric /* 2449536Seric ** Send back return receipts as requested. 2459536Seric */ 2469536Seric 247*68498Seric /* 24866783Seric if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags) 24966783Seric && !bitset(PRIV_NORECEIPTS, PrivacyFlags)) 250*68498Seric */ 251*68498Seric if (e->e_receiptto == NULL) 252*68498Seric e->e_receiptto = e->e_from.q_paddr; 253*68498Seric if (success_return && !failure_return && 254*68498Seric !bitset(PRIV_NORECEIPTS, PrivacyFlags) && 255*68498Seric strcmp(e->e_receiptto, "<>") != 0) 2569536Seric { 25710844Seric auto ADDRESS *rlist = NULL; 2589536Seric 259*68498Seric e->e_flags |= EF_SENDRECEIPT; 260*68498Seric (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e); 261*68498Seric (void) returntosender("Return receipt", rlist, return_yes, e); 2629536Seric } 263*68498Seric e->e_flags &= ~EF_SENDRECEIPT; 2649536Seric 2659536Seric /* 2669536Seric ** Arrange to send error messages if there are fatal errors. 2679536Seric */ 2689536Seric 269*68498Seric if (failure_return && e->e_errormode != EM_QUIET) 270*68498Seric savemail(e, return_yes || (!return_no && e->e_class >= 0)); 2719536Seric 2729536Seric /* 27363849Seric ** Arrange to send warning messages to postmaster as requested. 27463849Seric */ 27563849Seric 27663849Seric if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL && 27764363Seric !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0) 27863849Seric { 27963849Seric auto ADDRESS *rlist = NULL; 28063849Seric 281*68498Seric (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e); 28263849Seric (void) returntosender(e->e_message, rlist, FALSE, e); 28363849Seric } 28463849Seric 28563849Seric /* 2869536Seric ** Instantiate or deinstantiate the queue. 2879536Seric */ 2889536Seric 2899536Seric if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || 2909536Seric bitset(EF_CLRQUEUE, e->e_flags)) 2919536Seric { 29264307Seric if (tTd(50, 1)) 293*68498Seric printf("\n===== Dropping [dq]f%s (queueit=%d, e_flags=%x) =====\n\n", 294*68498Seric e->e_id, queueit, e->e_flags); 29523497Seric if (e->e_df != NULL) 29623497Seric xunlink(e->e_df); 2979536Seric xunlink(queuename(e, 'q')); 29863839Seric 29963839Seric #ifdef LOG 30063839Seric if (LogLevel > 10) 30163839Seric syslog(LOG_INFO, "%s: done", id); 30263839Seric #endif 3039536Seric } 3049536Seric else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) 30510754Seric { 30610754Seric #ifdef QUEUE 30764307Seric queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE); 30856795Seric #else /* QUEUE */ 30958151Seric syserr("554 dropenvelope: queueup"); 31056795Seric #endif /* QUEUE */ 31110754Seric } 3129536Seric 3139536Seric /* now unlock the job */ 31410196Seric closexscript(e); 3159536Seric unlockqueue(e); 3169536Seric 3179536Seric /* make sure that this envelope is marked unused */ 31824944Seric if (e->e_dfp != NULL) 31958680Seric (void) xfclose(e->e_dfp, "dropenvelope", e->e_df); 32010196Seric e->e_dfp = NULL; 32158680Seric e->e_id = e->e_df = NULL; 3229536Seric } 3239536Seric /* 3249536Seric ** CLEARENVELOPE -- clear an envelope without unlocking 3259536Seric ** 3269536Seric ** This is normally used by a child process to get a clean 3279536Seric ** envelope without disturbing the parent. 3289536Seric ** 3299536Seric ** Parameters: 3309536Seric ** e -- the envelope to clear. 33125611Seric ** fullclear - if set, the current envelope is total 33225611Seric ** garbage and should be ignored; otherwise, 33325611Seric ** release any resources it may indicate. 3349536Seric ** 3359536Seric ** Returns: 3369536Seric ** none. 3379536Seric ** 3389536Seric ** Side Effects: 3399536Seric ** Closes files associated with the envelope. 3409536Seric ** Marks the envelope as unallocated. 3419536Seric */ 3429536Seric 34360494Seric void 34425611Seric clearenvelope(e, fullclear) 3459536Seric register ENVELOPE *e; 34625611Seric bool fullclear; 3479536Seric { 34825514Seric register HDR *bh; 34925514Seric register HDR **nhp; 35025514Seric extern ENVELOPE BlankEnvelope; 35125514Seric 35225611Seric if (!fullclear) 35325611Seric { 35425611Seric /* clear out any file information */ 35525611Seric if (e->e_xfp != NULL) 35658680Seric (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id); 35725611Seric if (e->e_dfp != NULL) 35858680Seric (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df); 35958680Seric e->e_xfp = e->e_dfp = NULL; 36025611Seric } 3619536Seric 36224961Seric /* now clear out the data */ 36324965Seric STRUCTCOPY(BlankEnvelope, *e); 36459698Seric if (Verbose) 36559698Seric e->e_sendmode = SM_DELIVER; 36625514Seric bh = BlankEnvelope.e_header; 36725514Seric nhp = &e->e_header; 36825514Seric while (bh != NULL) 36925514Seric { 37025514Seric *nhp = (HDR *) xalloc(sizeof *bh); 37125514Seric bcopy((char *) bh, (char *) *nhp, sizeof *bh); 37225514Seric bh = bh->h_link; 37325514Seric nhp = &(*nhp)->h_link; 37425514Seric } 3759536Seric } 3769536Seric /* 3779536Seric ** INITSYS -- initialize instantiation of system 3789536Seric ** 3799536Seric ** In Daemon mode, this is done in the child. 3809536Seric ** 3819536Seric ** Parameters: 3829536Seric ** none. 3839536Seric ** 3849536Seric ** Returns: 3859536Seric ** none. 3869536Seric ** 3879536Seric ** Side Effects: 3889536Seric ** Initializes the system macros, some global variables, 3899536Seric ** etc. In particular, the current time in various 3909536Seric ** forms is set. 3919536Seric */ 3929536Seric 39360494Seric void 39455012Seric initsys(e) 39555012Seric register ENVELOPE *e; 3969536Seric { 39764768Seric char cbuf[5]; /* holds hop count */ 39864768Seric char pbuf[10]; /* holds pid */ 39922963Smiriam #ifdef TTYNAME 40059304Seric static char ybuf[60]; /* holds tty id */ 4019536Seric register char *p; 40256795Seric #endif /* TTYNAME */ 4039536Seric extern char *ttyname(); 40460494Seric extern void settime(); 4059536Seric extern char Version[]; 4069536Seric 4079536Seric /* 4089536Seric ** Give this envelope a reality. 4099536Seric ** I.e., an id, a transcript, and a creation time. 4109536Seric */ 4119536Seric 41255012Seric openxscript(e); 41355012Seric e->e_ctime = curtime(); 4149536Seric 4159536Seric /* 4169536Seric ** Set OutChannel to something useful if stdout isn't it. 4179536Seric ** This arranges that any extra stuff the mailer produces 4189536Seric ** gets sent back to the user on error (because it is 4199536Seric ** tucked away in the transcript). 4209536Seric */ 4219536Seric 42264760Seric if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && 42358737Seric e->e_xfp != NULL) 42455012Seric OutChannel = e->e_xfp; 4259536Seric 4269536Seric /* 4279536Seric ** Set up some basic system macros. 4289536Seric */ 4299536Seric 4309536Seric /* process id */ 4319536Seric (void) sprintf(pbuf, "%d", getpid()); 43264768Seric define('p', newstr(pbuf), e); 4339536Seric 4349536Seric /* hop count */ 43555012Seric (void) sprintf(cbuf, "%d", e->e_hopcount); 43664768Seric define('c', newstr(cbuf), e); 4379536Seric 4389536Seric /* time as integer, unix time, arpa time */ 43955012Seric settime(e); 4409536Seric 44117472Seric #ifdef TTYNAME 4429536Seric /* tty name */ 44355012Seric if (macvalue('y', e) == NULL) 4449536Seric { 4459536Seric p = ttyname(2); 4469536Seric if (p != NULL) 4479536Seric { 44856795Seric if (strrchr(p, '/') != NULL) 44956795Seric p = strrchr(p, '/') + 1; 4509536Seric (void) strcpy(ybuf, p); 45155012Seric define('y', ybuf, e); 4529536Seric } 4539536Seric } 45456795Seric #endif /* TTYNAME */ 4559536Seric } 4569536Seric /* 45711932Seric ** SETTIME -- set the current time. 45811932Seric ** 45911932Seric ** Parameters: 46011932Seric ** none. 46111932Seric ** 46211932Seric ** Returns: 46311932Seric ** none. 46411932Seric ** 46511932Seric ** Side Effects: 46611932Seric ** Sets the various time macros -- $a, $b, $d, $t. 46711932Seric */ 46811932Seric 46960494Seric void 47055012Seric settime(e) 47155012Seric register ENVELOPE *e; 47211932Seric { 47311932Seric register char *p; 47411932Seric auto time_t now; 47564768Seric char tbuf[20]; /* holds "current" time */ 47664768Seric char dbuf[30]; /* holds ctime(tbuf) */ 47711932Seric register struct tm *tm; 47811932Seric extern char *arpadate(); 47911932Seric extern struct tm *gmtime(); 48011932Seric 48111932Seric now = curtime(); 48211932Seric tm = gmtime(&now); 48357014Seric (void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900, 48457014Seric tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); 48564768Seric define('t', newstr(tbuf), e); 48611932Seric (void) strcpy(dbuf, ctime(&now)); 48758131Seric p = strchr(dbuf, '\n'); 48858131Seric if (p != NULL) 48958131Seric *p = '\0'; 49064768Seric define('d', newstr(dbuf), e); 49164086Seric p = arpadate(dbuf); 49264086Seric p = newstr(p); 49355012Seric if (macvalue('a', e) == NULL) 49455012Seric define('a', p, e); 49555012Seric define('b', p, e); 49611932Seric } 49711932Seric /* 4989536Seric ** OPENXSCRIPT -- Open transcript file 4999536Seric ** 5009536Seric ** Creates a transcript file for possible eventual mailing or 5019536Seric ** sending back. 5029536Seric ** 5039536Seric ** Parameters: 5049536Seric ** e -- the envelope to create the transcript in/for. 5059536Seric ** 5069536Seric ** Returns: 5079536Seric ** none 5089536Seric ** 5099536Seric ** Side Effects: 5109536Seric ** Creates the transcript file. 5119536Seric */ 5129536Seric 51358803Seric #ifndef O_APPEND 51458803Seric #define O_APPEND 0 51558803Seric #endif 51658803Seric 51760494Seric void 5189536Seric openxscript(e) 5199536Seric register ENVELOPE *e; 5209536Seric { 5219536Seric register char *p; 52240933Srick int fd; 5239536Seric 5249536Seric if (e->e_xfp != NULL) 5259536Seric return; 5269536Seric p = queuename(e, 'x'); 52758803Seric fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644); 52840933Srick if (fd < 0) 52963753Seric { 53063753Seric syserr("Can't create transcript file %s", p); 53163753Seric fd = open("/dev/null", O_WRONLY, 0644); 53263753Seric if (fd < 0) 53363753Seric syserr("!Can't open /dev/null"); 53463753Seric } 53568352Seric e->e_xfp = fdopen(fd, "a"); 53664724Seric if (e->e_xfp == NULL) 53764724Seric syserr("!Can't create transcript stream %s", p); 538*68498Seric #ifdef HASSETVBUF 539*68498Seric setvbuf(e->e_xfp, NULL, _IOLBF, 0); 540*68498Seric #else 541*68498Seric setlinebuf(e->e_xfp); 542*68498Seric #endif 54364743Seric if (tTd(46, 9)) 54464743Seric { 54564743Seric printf("openxscript(%s):\n ", p); 54664743Seric dumpfd(fileno(e->e_xfp), TRUE, FALSE); 54764743Seric } 5489536Seric } 5499536Seric /* 55010196Seric ** CLOSEXSCRIPT -- close the transcript file. 55110196Seric ** 55210196Seric ** Parameters: 55310196Seric ** e -- the envelope containing the transcript to close. 55410196Seric ** 55510196Seric ** Returns: 55610196Seric ** none. 55710196Seric ** 55810196Seric ** Side Effects: 55910196Seric ** none. 56010196Seric */ 56110196Seric 56260494Seric void 56310196Seric closexscript(e) 56410196Seric register ENVELOPE *e; 56510196Seric { 56610196Seric if (e->e_xfp == NULL) 56710196Seric return; 56858680Seric (void) xfclose(e->e_xfp, "closexscript", e->e_id); 56910196Seric e->e_xfp = NULL; 57010196Seric } 57110196Seric /* 5729536Seric ** SETSENDER -- set the person who this message is from 5739536Seric ** 5749536Seric ** Under certain circumstances allow the user to say who 5759536Seric ** s/he is (using -f or -r). These are: 5769536Seric ** 1. The user's uid is zero (root). 5779536Seric ** 2. The user's login name is in an approved list (typically 5789536Seric ** from a network server). 5799536Seric ** 3. The address the user is trying to claim has a 5809536Seric ** "!" character in it (since #2 doesn't do it for 5819536Seric ** us if we are dialing out for UUCP). 5829536Seric ** A better check to replace #3 would be if the 5839536Seric ** effective uid is "UUCP" -- this would require me 5849536Seric ** to rewrite getpwent to "grab" uucp as it went by, 5859536Seric ** make getname more nasty, do another passwd file 5869536Seric ** scan, or compile the UID of "UUCP" into the code, 5879536Seric ** all of which are reprehensible. 5889536Seric ** 5899536Seric ** Assuming all of these fail, we figure out something 5909536Seric ** ourselves. 5919536Seric ** 5929536Seric ** Parameters: 5939536Seric ** from -- the person we would like to believe this message 5949536Seric ** is from, as specified on the command line. 59553182Seric ** e -- the envelope in which we would like the sender set. 59658333Seric ** delimptr -- if non-NULL, set to the location of the 59758333Seric ** trailing delimiter. 59858704Seric ** internal -- set if this address is coming from an internal 59958704Seric ** source such as an owner alias. 6009536Seric ** 6019536Seric ** Returns: 60258704Seric ** none. 6039536Seric ** 6049536Seric ** Side Effects: 6059536Seric ** sets sendmail's notion of who the from person is. 6069536Seric */ 6079536Seric 60860494Seric void 60958704Seric setsender(from, e, delimptr, internal) 6109536Seric char *from; 61153182Seric register ENVELOPE *e; 61258333Seric char **delimptr; 61358704Seric bool internal; 6149536Seric { 6159536Seric register char **pvp; 6169536Seric char *realname = NULL; 61718665Seric register struct passwd *pw; 61858727Seric char delimchar; 61964147Seric char *bp; 62064147Seric char buf[MAXNAME + 2]; 62116913Seric char pvpbuf[PSBUFSIZE]; 62218665Seric extern struct passwd *getpwnam(); 6239536Seric extern char *FullName; 6249536Seric 6259536Seric if (tTd(45, 1)) 62614786Seric printf("setsender(%s)\n", from == NULL ? "" : from); 6279536Seric 6289536Seric /* 6299536Seric ** Figure out the real user executing us. 6309536Seric ** Username can return errno != 0 on non-errors. 6319536Seric */ 6329536Seric 63365580Seric if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP || 63465983Seric OpMode == MD_ARPAFTP || OpMode == MD_DAEMON) 6359536Seric realname = from; 6369536Seric if (realname == NULL || realname[0] == '\0') 6379536Seric realname = username(); 6389536Seric 63959027Seric if (ConfigLevel < 2) 64059027Seric SuprErrs = TRUE; 64159027Seric 64258727Seric delimchar = internal ? '\0' : ' '; 64364793Seric e->e_from.q_flags = QBADADDR; 64458333Seric if (from == NULL || 64564284Seric parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, 64664793Seric delimchar, delimptr, e) == NULL || 64764793Seric bitset(QBADADDR, e->e_from.q_flags) || 64864793Seric e->e_from.q_mailer == ProgMailer || 64964793Seric e->e_from.q_mailer == FileMailer || 65064793Seric e->e_from.q_mailer == InclMailer) 6519536Seric { 65221750Seric /* log garbage addresses for traceback */ 65355173Seric # ifdef LOG 65458020Seric if (from != NULL && LogLevel > 2) 65521750Seric { 65658951Seric char *p; 65758951Seric char ebuf[MAXNAME * 2 + 2]; 65855173Seric 65958951Seric p = macvalue('_', e); 66058951Seric if (p == NULL) 66158951Seric { 66258951Seric char *host = RealHostName; 66358951Seric if (host == NULL) 66458951Seric host = MyHostName; 66558951Seric (void) sprintf(ebuf, "%s@%s", realname, host); 66658951Seric p = ebuf; 66758951Seric } 66855173Seric syslog(LOG_NOTICE, 66964793Seric "setsender: %s: invalid or unparseable, received from %s", 67065015Seric shortenstring(from, 83), p); 67155173Seric } 67256795Seric # endif /* LOG */ 67357589Seric if (from != NULL) 67464793Seric { 67564793Seric if (!bitset(QBADADDR, e->e_from.q_flags)) 67664793Seric { 67764793Seric /* it was a bogus mailer in the from addr */ 67864793Seric usrerr("553 Invalid sender address"); 67964793Seric } 68057589Seric SuprErrs = TRUE; 68164793Seric } 68257589Seric if (from == realname || 68364284Seric parseaddr(from = newstr(realname), &e->e_from, 68464284Seric RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL) 68524944Seric { 68664793Seric char nbuf[100]; 68764793Seric 68857589Seric SuprErrs = TRUE; 68964808Seric expand("\201n", nbuf, &nbuf[sizeof nbuf], e); 69064793Seric if (parseaddr(from = newstr(nbuf), &e->e_from, 69164793Seric RF_COPYALL, ' ', NULL, e) == NULL && 69264793Seric parseaddr(from = "postmaster", &e->e_from, 69364793Seric RF_COPYALL, ' ', NULL, e) == NULL) 69458151Seric syserr("553 setsender: can't even parse postmaster!"); 69524944Seric } 6969536Seric } 6979536Seric else 6989536Seric FromFlag = TRUE; 69953182Seric e->e_from.q_flags |= QDONTSEND; 70057731Seric if (tTd(45, 5)) 70157731Seric { 70257731Seric printf("setsender: QDONTSEND "); 70357731Seric printaddr(&e->e_from, FALSE); 70457731Seric } 7059536Seric SuprErrs = FALSE; 7069536Seric 707*68498Seric # ifdef USERDB 708*68498Seric if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) 70968460Seric { 71053736Seric register char *p; 71153736Seric extern char *udbsender(); 71217472Seric 713*68498Seric p = udbsender(e->e_from.q_user); 714*68498Seric if (p != NULL) 715*68498Seric from = p; 716*68498Seric } 717*68498Seric # endif /* USERDB */ 718*68498Seric 719*68498Seric if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) 720*68498Seric { 72158704Seric if (!internal) 72258704Seric { 723*68498Seric /* if the user already given fullname don't redefine */ 72458704Seric if (FullName == NULL) 72558704Seric FullName = macvalue('x', e); 72658704Seric if (FullName != NULL && FullName[0] == '\0') 72758704Seric FullName = NULL; 7289536Seric } 72953736Seric 73053736Seric if ((pw = getpwnam(e->e_from.q_user)) != NULL) 73153736Seric { 73253736Seric /* 73353736Seric ** Process passwd file entry. 73453736Seric */ 73553736Seric 73653736Seric /* extract home directory */ 73765822Seric if (strcmp(pw->pw_dir, "/") == 0) 73865822Seric e->e_from.q_home = newstr(""); 73965822Seric else 74065822Seric e->e_from.q_home = newstr(pw->pw_dir); 74153736Seric define('z', e->e_from.q_home, e); 74253736Seric 74353736Seric /* extract user and group id */ 74453736Seric e->e_from.q_uid = pw->pw_uid; 74553736Seric e->e_from.q_gid = pw->pw_gid; 74665023Seric e->e_from.q_flags |= QGOODUID; 74753736Seric 74853736Seric /* extract full name from passwd file */ 74953736Seric if (FullName == NULL && pw->pw_gecos != NULL && 75058704Seric strcmp(pw->pw_name, e->e_from.q_user) == 0 && 75158704Seric !internal) 75253736Seric { 75365015Seric buildfname(pw->pw_gecos, e->e_from.q_user, buf); 75453736Seric if (buf[0] != '\0') 75553736Seric FullName = newstr(buf); 75653736Seric } 75753736Seric } 75858704Seric if (FullName != NULL && !internal) 75953182Seric define('x', FullName, e); 7609536Seric } 76165580Seric else if (!internal && OpMode != MD_DAEMON) 76211625Seric { 76353182Seric if (e->e_from.q_home == NULL) 76465822Seric { 76553182Seric e->e_from.q_home = getenv("HOME"); 76666049Seric if (e->e_from.q_home != NULL && 76766049Seric strcmp(e->e_from.q_home, "/") == 0) 76865822Seric e->e_from.q_home++; 76965822Seric } 77063787Seric e->e_from.q_uid = RealUid; 77163787Seric e->e_from.q_gid = RealGid; 77265023Seric e->e_from.q_flags |= QGOODUID; 77311625Seric } 77411625Seric 7759536Seric /* 7769536Seric ** Rewrite the from person to dispose of possible implicit 7779536Seric ** links in the net. 7789536Seric */ 7799536Seric 780*68498Seric pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL); 7819536Seric if (pvp == NULL) 7829536Seric { 78358403Seric /* don't need to give error -- prescan did that already */ 78436233Skarels # ifdef LOG 78558020Seric if (LogLevel > 2) 78636233Skarels syslog(LOG_NOTICE, "cannot prescan from (%s)", from); 78736233Skarels # endif 7889536Seric finis(); 7899536Seric } 790*68498Seric /* 79165071Seric (void) rewrite(pvp, 3, 0, e); 79265071Seric (void) rewrite(pvp, 1, 0, e); 79365071Seric (void) rewrite(pvp, 4, 0, e); 794*68498Seric */ 79564147Seric bp = buf + 1; 79664147Seric cataddr(pvp, NULL, bp, sizeof buf - 2, '\0'); 797*68498Seric if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags)) 79864147Seric { 79964147Seric /* heuristic: route-addr: add angle brackets */ 80064147Seric strcat(bp, ">"); 80164147Seric *--bp = '<'; 80264147Seric } 80364147Seric e->e_sender = newstr(bp); 80458704Seric define('f', e->e_sender, e); 8059536Seric 8069536Seric /* save the domain spec if this mailer wants it */ 80765584Seric if (e->e_from.q_mailer != NULL && 80853182Seric bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) 8099536Seric { 8109536Seric extern char **copyplist(); 8119536Seric 8129536Seric while (*pvp != NULL && strcmp(*pvp, "@") != 0) 8139536Seric pvp++; 8149536Seric if (*pvp != NULL) 81553182Seric e->e_fromdomain = copyplist(pvp, TRUE); 8169536Seric } 8179536Seric } 818