122704Sdist /* 268839Seric * Copyright (c) 1983, 1995 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*69713Seric static char sccsid[] = "@(#)envelope.c 8.65 (Berkeley) 05/27/95"; 1133729Sbostic #endif /* not lint */ 1222704Sdist 1358332Seric #include "sendmail.h" 149536Seric 159536Seric /* 169536Seric ** NEWENVELOPE -- allocate a new envelope 179536Seric ** 189536Seric ** Supports inheritance. 199536Seric ** 209536Seric ** Parameters: 219536Seric ** e -- the new envelope to fill in. 2258179Seric ** parent -- the envelope to be the parent of e. 239536Seric ** 249536Seric ** Returns: 259536Seric ** e. 269536Seric ** 279536Seric ** Side Effects: 289536Seric ** none. 299536Seric */ 309536Seric 319536Seric ENVELOPE * 3258179Seric newenvelope(e, parent) 339536Seric register ENVELOPE *e; 3458179Seric register ENVELOPE *parent; 359536Seric { 369536Seric extern putheader(), putbody(); 3725611Seric extern ENVELOPE BlankEnvelope; 389536Seric 3958179Seric if (e == parent && e->e_parent != NULL) 409536Seric parent = e->e_parent; 4125611Seric clearenvelope(e, TRUE); 4224944Seric if (e == CurEnv) 4324944Seric bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from); 4424944Seric else 4524944Seric bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); 469536Seric e->e_parent = parent; 479536Seric e->e_ctime = curtime(); 4856215Seric if (parent != NULL) 4956215Seric e->e_msgpriority = parent->e_msgsize; 509536Seric e->e_puthdr = putheader; 519536Seric e->e_putbody = putbody; 529536Seric if (CurEnv->e_xfp != NULL) 539536Seric (void) fflush(CurEnv->e_xfp); 549536Seric 559536Seric return (e); 569536Seric } 579536Seric /* 589536Seric ** DROPENVELOPE -- deallocate an envelope. 599536Seric ** 609536Seric ** Parameters: 619536Seric ** e -- the envelope to deallocate. 629536Seric ** 639536Seric ** Returns: 649536Seric ** none. 659536Seric ** 669536Seric ** Side Effects: 679536Seric ** housekeeping necessary to dispose of an envelope. 689536Seric ** Unlocks this queue file. 699536Seric */ 709536Seric 7160494Seric void 729536Seric dropenvelope(e) 739536Seric register ENVELOPE *e; 749536Seric { 759536Seric bool queueit = FALSE; 7668498Seric bool failure_return = FALSE; 7768498Seric bool success_return = FALSE; 789536Seric register ADDRESS *q; 7957943Seric char *id = e->e_id; 8063753Seric char buf[MAXLINE]; 819536Seric 829536Seric if (tTd(50, 1)) 839536Seric { 8468567Seric extern void printenvflags(); 8568567Seric 8658680Seric printf("dropenvelope %x: id=", e); 879536Seric xputs(e->e_id); 8868567Seric printf(", flags="); 8968567Seric printenvflags(e); 9063753Seric if (tTd(50, 10)) 9163753Seric { 9263753Seric printf("sendq="); 9363753Seric printaddr(e->e_sendqueue, TRUE); 9463753Seric } 959536Seric } 9657943Seric 9758680Seric /* we must have an id to remove disk files */ 9857943Seric if (id == NULL) 9958680Seric return; 10057943Seric 1019536Seric #ifdef LOG 10265089Seric if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) 10365089Seric logsender(e, NULL); 10458020Seric if (LogLevel > 84) 10565089Seric syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=0x%x, pid=%d", 10657943Seric id, e->e_flags, getpid()); 10756795Seric #endif /* LOG */ 10865089Seric e->e_flags &= ~EF_LOGSENDER; 1099536Seric 11063753Seric /* post statistics */ 11163753Seric poststats(StatFile); 11263753Seric 1139536Seric /* 1149536Seric ** Extract state information from dregs of send list. 1159536Seric */ 1169536Seric 11764743Seric e->e_flags &= ~EF_QUEUERUN; 1189536Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 1199536Seric { 1209536Seric if (bitset(QQUEUEUP, q->q_flags)) 1219536Seric queueit = TRUE; 12268498Seric 12368498Seric /* see if a notification is needed */ 12468564Seric if (bitset(QBADADDR, q->q_flags) && 12568498Seric bitset(QPINGONFAILURE, q->q_flags)) 12663839Seric { 12768498Seric failure_return = TRUE; 12868498Seric if (q->q_owner == NULL && !emptyaddr(&e->e_from)) 12963839Seric (void) sendtolist(e->e_from.q_paddr, NULL, 13068498Seric &e->e_errorqueue, 0, e); 13163839Seric } 13268603Seric else if (bitset(QPINGONSUCCESS, q->q_flags) && 13368603Seric ((bitset(QSENT, q->q_flags) && 13468603Seric bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) || 13568867Seric bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) 13668498Seric { 13768498Seric success_return = TRUE; 13868498Seric } 1399536Seric } 1409536Seric 14168559Seric if (e->e_class < 0) 14268559Seric e->e_flags |= EF_NO_BODY_RETN; 14368559Seric 1449536Seric /* 14563753Seric ** See if the message timed out. 14663753Seric */ 14763753Seric 14863753Seric if (!queueit) 14963753Seric /* nothing to do */ ; 15068498Seric else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) 15163753Seric { 15263839Seric (void) sprintf(buf, "Cannot send message for %s", 15368498Seric pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 15463839Seric if (e->e_message != NULL) 15563839Seric free(e->e_message); 15663839Seric e->e_message = newstr(buf); 15763839Seric message(buf); 15863839Seric e->e_flags |= EF_CLRQUEUE; 15968498Seric failure_return = TRUE; 16063787Seric fprintf(e->e_xfp, "Message could not be delivered for %s\n", 16168498Seric pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 16263787Seric fprintf(e->e_xfp, "Message will be deleted from queue\n"); 16363787Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 16463787Seric { 16563787Seric if (bitset(QQUEUEUP, q->q_flags)) 16668859Seric { 16763787Seric q->q_flags |= QBADADDR; 16868859Seric q->q_status = "4.4.7"; 16968859Seric } 17063787Seric } 17163753Seric } 17268498Seric else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && 17368498Seric curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass]) 17463753Seric { 17568498Seric bool delay_return = FALSE; 17668498Seric 17768498Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 17868498Seric { 17968498Seric if (bitset(QQUEUEUP, q->q_flags) && 18068498Seric bitset(QPINGONDELAY, q->q_flags)) 18168498Seric { 18268867Seric q->q_flags |= QDELAYED; 18368498Seric delay_return = TRUE; 18468498Seric } 18568498Seric } 18668498Seric if (delay_return && 18768498Seric !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && 18863753Seric e->e_class >= 0 && 18968498Seric strcmp(e->e_from.q_paddr, "<>") != 0 && 19068498Seric strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && 19168706Seric (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 || 19268498Seric strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0)) 19363753Seric { 19463753Seric (void) sprintf(buf, 19568498Seric "Warning: cannot send message for %s", 19668498Seric pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); 19763753Seric if (e->e_message != NULL) 19863753Seric free(e->e_message); 19963753Seric e->e_message = newstr(buf); 20063753Seric message(buf); 20163839Seric e->e_flags |= EF_WARNING; 20268498Seric failure_return = TRUE; 20363753Seric } 20463753Seric fprintf(e->e_xfp, 20563753Seric "Warning: message still undelivered after %s\n", 20668498Seric pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); 20763753Seric fprintf(e->e_xfp, "Will keep trying until message is %s old\n", 20868498Seric pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 20968498Seric } 21068498Seric 21168498Seric if (tTd(50, 2)) 21268498Seric printf("failure_return=%d success_return=%d queueit=%d\n", 21368498Seric failure_return, success_return, queueit); 21468498Seric 21568498Seric /* 21668498Seric ** If we had some fatal error, but no addresses are marked as 21768498Seric ** bad, mark them _all_ as bad. 21868498Seric */ 21968498Seric 22068498Seric if (bitset(EF_FATALERRS, e->e_flags) && !failure_return) 22168498Seric { 22268498Seric failure_return = TRUE; 22368019Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 22468019Seric { 22568498Seric if (!bitset(QDONTSEND, q->q_flags)) 22668498Seric q->q_flags |= QBADADDR; 22768019Seric } 22868019Seric } 22968019Seric 23068019Seric /* 2319536Seric ** Send back return receipts as requested. 2329536Seric */ 2339536Seric 23468498Seric /* 23566783Seric if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags) 23666783Seric && !bitset(PRIV_NORECEIPTS, PrivacyFlags)) 23768498Seric */ 23868498Seric if (e->e_receiptto == NULL) 23968498Seric e->e_receiptto = e->e_from.q_paddr; 24068498Seric if (success_return && !failure_return && 24168498Seric !bitset(PRIV_NORECEIPTS, PrivacyFlags) && 24268498Seric strcmp(e->e_receiptto, "<>") != 0) 2439536Seric { 24410844Seric auto ADDRESS *rlist = NULL; 2459536Seric 24668498Seric e->e_flags |= EF_SENDRECEIPT; 24768498Seric (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e); 24868559Seric (void) returntosender("Return receipt", rlist, FALSE, e); 2499536Seric } 25068498Seric e->e_flags &= ~EF_SENDRECEIPT; 2519536Seric 2529536Seric /* 2539536Seric ** Arrange to send error messages if there are fatal errors. 2549536Seric */ 2559536Seric 25668498Seric if (failure_return && e->e_errormode != EM_QUIET) 25768559Seric savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags)); 2589536Seric 2599536Seric /* 26063849Seric ** Arrange to send warning messages to postmaster as requested. 26163849Seric */ 26263849Seric 26368802Seric if ((failure_return || bitset(EF_PM_NOTIFY, e->e_flags)) && 26468802Seric PostMasterCopy != NULL && 26564363Seric !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0) 26663849Seric { 26763849Seric auto ADDRESS *rlist = NULL; 26863849Seric 26968498Seric (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e); 27063849Seric (void) returntosender(e->e_message, rlist, FALSE, e); 27163849Seric } 27263849Seric 27363849Seric /* 2749536Seric ** Instantiate or deinstantiate the queue. 2759536Seric */ 2769536Seric 2779536Seric if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || 2789536Seric bitset(EF_CLRQUEUE, e->e_flags)) 2799536Seric { 28064307Seric if (tTd(50, 1)) 28168567Seric { 28268567Seric extern void printenvflags(); 28368567Seric 28468567Seric printf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=", 28568567Seric e->e_id, queueit); 28668567Seric printenvflags(e); 28768567Seric } 28868564Seric xunlink(queuename(e, 'd')); 2899536Seric xunlink(queuename(e, 'q')); 29063839Seric 29163839Seric #ifdef LOG 29263839Seric if (LogLevel > 10) 29363839Seric syslog(LOG_INFO, "%s: done", id); 29463839Seric #endif 2959536Seric } 2969536Seric else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) 29710754Seric { 29810754Seric #ifdef QUEUE 29964307Seric queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE); 30056795Seric #else /* QUEUE */ 30158151Seric syserr("554 dropenvelope: queueup"); 30256795Seric #endif /* QUEUE */ 30310754Seric } 3049536Seric 3059536Seric /* now unlock the job */ 30610196Seric closexscript(e); 3079536Seric unlockqueue(e); 3089536Seric 3099536Seric /* make sure that this envelope is marked unused */ 31024944Seric if (e->e_dfp != NULL) 31168564Seric (void) xfclose(e->e_dfp, "dropenvelope df", e->e_id); 31210196Seric e->e_dfp = NULL; 31368564Seric e->e_id = NULL; 31468564Seric e->e_flags &= ~EF_HAS_DF; 3159536Seric } 3169536Seric /* 3179536Seric ** CLEARENVELOPE -- clear an envelope without unlocking 3189536Seric ** 3199536Seric ** This is normally used by a child process to get a clean 3209536Seric ** envelope without disturbing the parent. 3219536Seric ** 3229536Seric ** Parameters: 3239536Seric ** e -- the envelope to clear. 32425611Seric ** fullclear - if set, the current envelope is total 32525611Seric ** garbage and should be ignored; otherwise, 32625611Seric ** release any resources it may indicate. 3279536Seric ** 3289536Seric ** Returns: 3299536Seric ** none. 3309536Seric ** 3319536Seric ** Side Effects: 3329536Seric ** Closes files associated with the envelope. 3339536Seric ** Marks the envelope as unallocated. 3349536Seric */ 3359536Seric 33660494Seric void 33725611Seric clearenvelope(e, fullclear) 3389536Seric register ENVELOPE *e; 33925611Seric bool fullclear; 3409536Seric { 34125514Seric register HDR *bh; 34225514Seric register HDR **nhp; 34325514Seric extern ENVELOPE BlankEnvelope; 34425514Seric 34525611Seric if (!fullclear) 34625611Seric { 34725611Seric /* clear out any file information */ 34825611Seric if (e->e_xfp != NULL) 34958680Seric (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id); 35025611Seric if (e->e_dfp != NULL) 35168564Seric (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_id); 35258680Seric e->e_xfp = e->e_dfp = NULL; 35325611Seric } 3549536Seric 35524961Seric /* now clear out the data */ 35624965Seric STRUCTCOPY(BlankEnvelope, *e); 35759698Seric if (Verbose) 35859698Seric e->e_sendmode = SM_DELIVER; 35925514Seric bh = BlankEnvelope.e_header; 36025514Seric nhp = &e->e_header; 36125514Seric while (bh != NULL) 36225514Seric { 36325514Seric *nhp = (HDR *) xalloc(sizeof *bh); 36425514Seric bcopy((char *) bh, (char *) *nhp, sizeof *bh); 36525514Seric bh = bh->h_link; 36625514Seric nhp = &(*nhp)->h_link; 36725514Seric } 3689536Seric } 3699536Seric /* 3709536Seric ** INITSYS -- initialize instantiation of system 3719536Seric ** 3729536Seric ** In Daemon mode, this is done in the child. 3739536Seric ** 3749536Seric ** Parameters: 3759536Seric ** none. 3769536Seric ** 3779536Seric ** Returns: 3789536Seric ** none. 3799536Seric ** 3809536Seric ** Side Effects: 3819536Seric ** Initializes the system macros, some global variables, 3829536Seric ** etc. In particular, the current time in various 3839536Seric ** forms is set. 3849536Seric */ 3859536Seric 38660494Seric void 38755012Seric initsys(e) 38855012Seric register ENVELOPE *e; 3899536Seric { 39064768Seric char cbuf[5]; /* holds hop count */ 39164768Seric char pbuf[10]; /* holds pid */ 39222963Smiriam #ifdef TTYNAME 39359304Seric static char ybuf[60]; /* holds tty id */ 3949536Seric register char *p; 39556795Seric #endif /* TTYNAME */ 3969536Seric extern char *ttyname(); 39760494Seric extern void settime(); 3989536Seric extern char Version[]; 3999536Seric 4009536Seric /* 4019536Seric ** Give this envelope a reality. 4029536Seric ** I.e., an id, a transcript, and a creation time. 4039536Seric */ 4049536Seric 40555012Seric openxscript(e); 40655012Seric e->e_ctime = curtime(); 4079536Seric 4089536Seric /* 4099536Seric ** Set OutChannel to something useful if stdout isn't it. 4109536Seric ** This arranges that any extra stuff the mailer produces 4119536Seric ** gets sent back to the user on error (because it is 4129536Seric ** tucked away in the transcript). 4139536Seric */ 4149536Seric 41564760Seric if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && 41658737Seric e->e_xfp != NULL) 41755012Seric OutChannel = e->e_xfp; 4189536Seric 4199536Seric /* 4209536Seric ** Set up some basic system macros. 4219536Seric */ 4229536Seric 4239536Seric /* process id */ 4249536Seric (void) sprintf(pbuf, "%d", getpid()); 42564768Seric define('p', newstr(pbuf), e); 4269536Seric 4279536Seric /* hop count */ 42855012Seric (void) sprintf(cbuf, "%d", e->e_hopcount); 42964768Seric define('c', newstr(cbuf), e); 4309536Seric 4319536Seric /* time as integer, unix time, arpa time */ 43255012Seric settime(e); 4339536Seric 43417472Seric #ifdef TTYNAME 4359536Seric /* tty name */ 43655012Seric if (macvalue('y', e) == NULL) 4379536Seric { 4389536Seric p = ttyname(2); 4399536Seric if (p != NULL) 4409536Seric { 44156795Seric if (strrchr(p, '/') != NULL) 44256795Seric p = strrchr(p, '/') + 1; 4439536Seric (void) strcpy(ybuf, p); 44455012Seric define('y', ybuf, e); 4459536Seric } 4469536Seric } 44756795Seric #endif /* TTYNAME */ 4489536Seric } 4499536Seric /* 45011932Seric ** SETTIME -- set the current time. 45111932Seric ** 45211932Seric ** Parameters: 45311932Seric ** none. 45411932Seric ** 45511932Seric ** Returns: 45611932Seric ** none. 45711932Seric ** 45811932Seric ** Side Effects: 45911932Seric ** Sets the various time macros -- $a, $b, $d, $t. 46011932Seric */ 46111932Seric 46260494Seric void 46355012Seric settime(e) 46455012Seric register ENVELOPE *e; 46511932Seric { 46611932Seric register char *p; 46711932Seric auto time_t now; 46864768Seric char tbuf[20]; /* holds "current" time */ 46964768Seric char dbuf[30]; /* holds ctime(tbuf) */ 47011932Seric register struct tm *tm; 47111932Seric extern char *arpadate(); 47211932Seric extern struct tm *gmtime(); 47311932Seric 47411932Seric now = curtime(); 47511932Seric tm = gmtime(&now); 47657014Seric (void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900, 47757014Seric tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); 47864768Seric define('t', newstr(tbuf), e); 47911932Seric (void) strcpy(dbuf, ctime(&now)); 48058131Seric p = strchr(dbuf, '\n'); 48158131Seric if (p != NULL) 48258131Seric *p = '\0'; 48364768Seric define('d', newstr(dbuf), e); 48464086Seric p = arpadate(dbuf); 48564086Seric p = newstr(p); 48655012Seric if (macvalue('a', e) == NULL) 48755012Seric define('a', p, e); 48855012Seric define('b', p, e); 48911932Seric } 49011932Seric /* 4919536Seric ** OPENXSCRIPT -- Open transcript file 4929536Seric ** 4939536Seric ** Creates a transcript file for possible eventual mailing or 4949536Seric ** sending back. 4959536Seric ** 4969536Seric ** Parameters: 4979536Seric ** e -- the envelope to create the transcript in/for. 4989536Seric ** 4999536Seric ** Returns: 5009536Seric ** none 5019536Seric ** 5029536Seric ** Side Effects: 5039536Seric ** Creates the transcript file. 5049536Seric */ 5059536Seric 50658803Seric #ifndef O_APPEND 50758803Seric #define O_APPEND 0 50858803Seric #endif 50958803Seric 51060494Seric void 5119536Seric openxscript(e) 5129536Seric register ENVELOPE *e; 5139536Seric { 5149536Seric register char *p; 51540933Srick int fd; 5169536Seric 5179536Seric if (e->e_xfp != NULL) 5189536Seric return; 5199536Seric p = queuename(e, 'x'); 52058803Seric fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644); 52140933Srick if (fd < 0) 52263753Seric { 52363753Seric syserr("Can't create transcript file %s", p); 52463753Seric fd = open("/dev/null", O_WRONLY, 0644); 52563753Seric if (fd < 0) 52663753Seric syserr("!Can't open /dev/null"); 52763753Seric } 52868352Seric e->e_xfp = fdopen(fd, "a"); 52964724Seric if (e->e_xfp == NULL) 53064724Seric syserr("!Can't create transcript stream %s", p); 53168498Seric #ifdef HASSETVBUF 53268498Seric setvbuf(e->e_xfp, NULL, _IOLBF, 0); 53368498Seric #else 53468498Seric setlinebuf(e->e_xfp); 53568498Seric #endif 53664743Seric if (tTd(46, 9)) 53764743Seric { 53864743Seric printf("openxscript(%s):\n ", p); 53964743Seric dumpfd(fileno(e->e_xfp), TRUE, FALSE); 54064743Seric } 5419536Seric } 5429536Seric /* 54310196Seric ** CLOSEXSCRIPT -- close the transcript file. 54410196Seric ** 54510196Seric ** Parameters: 54610196Seric ** e -- the envelope containing the transcript to close. 54710196Seric ** 54810196Seric ** Returns: 54910196Seric ** none. 55010196Seric ** 55110196Seric ** Side Effects: 55210196Seric ** none. 55310196Seric */ 55410196Seric 55560494Seric void 55610196Seric closexscript(e) 55710196Seric register ENVELOPE *e; 55810196Seric { 55910196Seric if (e->e_xfp == NULL) 56010196Seric return; 56158680Seric (void) xfclose(e->e_xfp, "closexscript", e->e_id); 56210196Seric e->e_xfp = NULL; 56310196Seric } 56410196Seric /* 5659536Seric ** SETSENDER -- set the person who this message is from 5669536Seric ** 5679536Seric ** Under certain circumstances allow the user to say who 5689536Seric ** s/he is (using -f or -r). These are: 5699536Seric ** 1. The user's uid is zero (root). 5709536Seric ** 2. The user's login name is in an approved list (typically 5719536Seric ** from a network server). 5729536Seric ** 3. The address the user is trying to claim has a 5739536Seric ** "!" character in it (since #2 doesn't do it for 5749536Seric ** us if we are dialing out for UUCP). 5759536Seric ** A better check to replace #3 would be if the 5769536Seric ** effective uid is "UUCP" -- this would require me 5779536Seric ** to rewrite getpwent to "grab" uucp as it went by, 5789536Seric ** make getname more nasty, do another passwd file 5799536Seric ** scan, or compile the UID of "UUCP" into the code, 5809536Seric ** all of which are reprehensible. 5819536Seric ** 5829536Seric ** Assuming all of these fail, we figure out something 5839536Seric ** ourselves. 5849536Seric ** 5859536Seric ** Parameters: 5869536Seric ** from -- the person we would like to believe this message 5879536Seric ** is from, as specified on the command line. 58853182Seric ** e -- the envelope in which we would like the sender set. 58958333Seric ** delimptr -- if non-NULL, set to the location of the 59058333Seric ** trailing delimiter. 59158704Seric ** internal -- set if this address is coming from an internal 59258704Seric ** source such as an owner alias. 5939536Seric ** 5949536Seric ** Returns: 59558704Seric ** none. 5969536Seric ** 5979536Seric ** Side Effects: 5989536Seric ** sets sendmail's notion of who the from person is. 5999536Seric */ 6009536Seric 60160494Seric void 60258704Seric setsender(from, e, delimptr, internal) 6039536Seric char *from; 60453182Seric register ENVELOPE *e; 60558333Seric char **delimptr; 60658704Seric bool internal; 6079536Seric { 6089536Seric register char **pvp; 6099536Seric char *realname = NULL; 61018665Seric register struct passwd *pw; 61158727Seric char delimchar; 61264147Seric char *bp; 61364147Seric char buf[MAXNAME + 2]; 61416913Seric char pvpbuf[PSBUFSIZE]; 6159536Seric extern char *FullName; 6169536Seric 6179536Seric if (tTd(45, 1)) 61814786Seric printf("setsender(%s)\n", from == NULL ? "" : from); 6199536Seric 6209536Seric /* 6219536Seric ** Figure out the real user executing us. 6229536Seric ** Username can return errno != 0 on non-errors. 6239536Seric */ 6249536Seric 62565580Seric if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP || 62665983Seric OpMode == MD_ARPAFTP || OpMode == MD_DAEMON) 6279536Seric realname = from; 6289536Seric if (realname == NULL || realname[0] == '\0') 6299536Seric realname = username(); 6309536Seric 63159027Seric if (ConfigLevel < 2) 63259027Seric SuprErrs = TRUE; 63359027Seric 63458727Seric delimchar = internal ? '\0' : ' '; 63564793Seric e->e_from.q_flags = QBADADDR; 63658333Seric if (from == NULL || 63764284Seric parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, 63864793Seric delimchar, delimptr, e) == NULL || 63964793Seric bitset(QBADADDR, e->e_from.q_flags) || 64064793Seric e->e_from.q_mailer == ProgMailer || 64164793Seric e->e_from.q_mailer == FileMailer || 64264793Seric e->e_from.q_mailer == InclMailer) 6439536Seric { 64421750Seric /* log garbage addresses for traceback */ 64555173Seric # ifdef LOG 64658020Seric if (from != NULL && LogLevel > 2) 64721750Seric { 64858951Seric char *p; 64958951Seric char ebuf[MAXNAME * 2 + 2]; 65055173Seric 65158951Seric p = macvalue('_', e); 65258951Seric if (p == NULL) 65358951Seric { 65458951Seric char *host = RealHostName; 65558951Seric if (host == NULL) 65658951Seric host = MyHostName; 65758951Seric (void) sprintf(ebuf, "%s@%s", realname, host); 65858951Seric p = ebuf; 65958951Seric } 66055173Seric syslog(LOG_NOTICE, 66164793Seric "setsender: %s: invalid or unparseable, received from %s", 66265015Seric shortenstring(from, 83), p); 66355173Seric } 66456795Seric # endif /* LOG */ 66557589Seric if (from != NULL) 66664793Seric { 66764793Seric if (!bitset(QBADADDR, e->e_from.q_flags)) 66864793Seric { 66964793Seric /* it was a bogus mailer in the from addr */ 67068859Seric e->e_status = "5.1.7"; 67164793Seric usrerr("553 Invalid sender address"); 67264793Seric } 67357589Seric SuprErrs = TRUE; 67464793Seric } 67557589Seric if (from == realname || 67664284Seric parseaddr(from = newstr(realname), &e->e_from, 67764284Seric RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL) 67824944Seric { 67964793Seric char nbuf[100]; 68064793Seric 68157589Seric SuprErrs = TRUE; 68268529Seric expand("\201n", nbuf, sizeof nbuf, e); 68364793Seric if (parseaddr(from = newstr(nbuf), &e->e_from, 68464793Seric RF_COPYALL, ' ', NULL, e) == NULL && 68564793Seric parseaddr(from = "postmaster", &e->e_from, 68664793Seric RF_COPYALL, ' ', NULL, e) == NULL) 68758151Seric syserr("553 setsender: can't even parse postmaster!"); 68824944Seric } 6899536Seric } 6909536Seric else 6919536Seric FromFlag = TRUE; 69253182Seric e->e_from.q_flags |= QDONTSEND; 69357731Seric if (tTd(45, 5)) 69457731Seric { 69557731Seric printf("setsender: QDONTSEND "); 69657731Seric printaddr(&e->e_from, FALSE); 69757731Seric } 6989536Seric SuprErrs = FALSE; 6999536Seric 700*69713Seric # if USERDB 70168498Seric if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) 70268460Seric { 70353736Seric register char *p; 70453736Seric extern char *udbsender(); 70517472Seric 70668498Seric p = udbsender(e->e_from.q_user); 70768498Seric if (p != NULL) 70868498Seric from = p; 70968498Seric } 71068498Seric # endif /* USERDB */ 71168498Seric 71268498Seric if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) 71368498Seric { 71458704Seric if (!internal) 71558704Seric { 71668498Seric /* if the user already given fullname don't redefine */ 71758704Seric if (FullName == NULL) 71858704Seric FullName = macvalue('x', e); 71958704Seric if (FullName != NULL && FullName[0] == '\0') 72058704Seric FullName = NULL; 7219536Seric } 72253736Seric 72368693Seric if ((pw = sm_getpwnam(e->e_from.q_user)) != NULL) 72453736Seric { 72553736Seric /* 72653736Seric ** Process passwd file entry. 72753736Seric */ 72853736Seric 72953736Seric /* extract home directory */ 73065822Seric if (strcmp(pw->pw_dir, "/") == 0) 73165822Seric e->e_from.q_home = newstr(""); 73265822Seric else 73365822Seric e->e_from.q_home = newstr(pw->pw_dir); 73453736Seric define('z', e->e_from.q_home, e); 73553736Seric 73653736Seric /* extract user and group id */ 73753736Seric e->e_from.q_uid = pw->pw_uid; 73853736Seric e->e_from.q_gid = pw->pw_gid; 73965023Seric e->e_from.q_flags |= QGOODUID; 74053736Seric 74153736Seric /* extract full name from passwd file */ 74253736Seric if (FullName == NULL && pw->pw_gecos != NULL && 74358704Seric strcmp(pw->pw_name, e->e_from.q_user) == 0 && 74458704Seric !internal) 74553736Seric { 74665015Seric buildfname(pw->pw_gecos, e->e_from.q_user, buf); 74753736Seric if (buf[0] != '\0') 74853736Seric FullName = newstr(buf); 74953736Seric } 75053736Seric } 75158704Seric if (FullName != NULL && !internal) 75253182Seric define('x', FullName, e); 7539536Seric } 75465580Seric else if (!internal && OpMode != MD_DAEMON) 75511625Seric { 75653182Seric if (e->e_from.q_home == NULL) 75765822Seric { 75853182Seric e->e_from.q_home = getenv("HOME"); 75966049Seric if (e->e_from.q_home != NULL && 76066049Seric strcmp(e->e_from.q_home, "/") == 0) 76165822Seric e->e_from.q_home++; 76265822Seric } 76363787Seric e->e_from.q_uid = RealUid; 76463787Seric e->e_from.q_gid = RealGid; 76565023Seric e->e_from.q_flags |= QGOODUID; 76611625Seric } 76711625Seric 7689536Seric /* 7699536Seric ** Rewrite the from person to dispose of possible implicit 7709536Seric ** links in the net. 7719536Seric */ 7729536Seric 77368711Seric pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL); 7749536Seric if (pvp == NULL) 7759536Seric { 77658403Seric /* don't need to give error -- prescan did that already */ 77736233Skarels # ifdef LOG 77858020Seric if (LogLevel > 2) 77936233Skarels syslog(LOG_NOTICE, "cannot prescan from (%s)", from); 78036233Skarels # endif 7819536Seric finis(); 7829536Seric } 78368498Seric /* 78465071Seric (void) rewrite(pvp, 3, 0, e); 78565071Seric (void) rewrite(pvp, 1, 0, e); 78665071Seric (void) rewrite(pvp, 4, 0, e); 78768498Seric */ 78864147Seric bp = buf + 1; 78964147Seric cataddr(pvp, NULL, bp, sizeof buf - 2, '\0'); 79068498Seric if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags)) 79164147Seric { 79264147Seric /* heuristic: route-addr: add angle brackets */ 79364147Seric strcat(bp, ">"); 79464147Seric *--bp = '<'; 79564147Seric } 79664147Seric e->e_sender = newstr(bp); 79758704Seric define('f', e->e_sender, e); 7989536Seric 7999536Seric /* save the domain spec if this mailer wants it */ 80065584Seric if (e->e_from.q_mailer != NULL && 80153182Seric bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) 8029536Seric { 80368736Seric char **lastat; 8049536Seric extern char **copyplist(); 8059536Seric 80668736Seric /* get rid of any pesky angle brackets */ 80768736Seric (void) rewrite(pvp, 3, 0, e); 80868736Seric (void) rewrite(pvp, 1, 0, e); 80968736Seric (void) rewrite(pvp, 4, 0, e); 81068736Seric 81168736Seric /* strip off to the last "@" sign */ 81268736Seric for (lastat = NULL; *pvp != NULL; pvp++) 81368736Seric if (strcmp(*pvp, "@") == 0) 81468736Seric lastat = pvp; 81568736Seric if (lastat != NULL) 81668736Seric { 81768736Seric e->e_fromdomain = copyplist(lastat, TRUE); 81868736Seric if (tTd(45, 3)) 81968736Seric { 82068736Seric printf("Saving from domain: "); 82168736Seric printav(e->e_fromdomain); 82268736Seric } 82368736Seric } 8249536Seric } 8259536Seric } 82668567Seric /* 82768567Seric ** PRINTENVFLAGS -- print envelope flags for debugging 82868567Seric ** 82968567Seric ** Parameters: 83068567Seric ** e -- the envelope with the flags to be printed. 83168567Seric ** 83268567Seric ** Returns: 83368567Seric ** none. 83468567Seric */ 83568567Seric 83668567Seric struct eflags 83768567Seric { 83868567Seric char *ef_name; 83968567Seric u_long ef_bit; 84068567Seric }; 84168567Seric 84268567Seric struct eflags EnvelopeFlags[] = 84368567Seric { 84468567Seric "OLDSTYLE", EF_OLDSTYLE, 84568567Seric "INQUEUE", EF_INQUEUE, 84668567Seric "NO_BODY_RETN", EF_NO_BODY_RETN, 84768567Seric "CLRQUEUE", EF_CLRQUEUE, 84868567Seric "SENDRECEIPT", EF_SENDRECEIPT, 84968567Seric "FATALERRS", EF_FATALERRS, 85068567Seric "KEEPQUEUE", EF_KEEPQUEUE, 85168567Seric "RESPONSE", EF_RESPONSE, 85268567Seric "RESENT", EF_RESENT, 85368567Seric "VRFYONLY", EF_VRFYONLY, 85468567Seric "WARNING", EF_WARNING, 85568567Seric "QUEUERUN", EF_QUEUERUN, 85668567Seric "GLOBALERRS", EF_GLOBALERRS, 85768567Seric "PM_NOTIFY", EF_PM_NOTIFY, 85868567Seric "METOO", EF_METOO, 85968567Seric "LOGSENDER", EF_LOGSENDER, 86068567Seric "NORECEIPT", EF_NORECEIPT, 86168567Seric "HAS8BIT", EF_HAS8BIT, 86268567Seric "NL_NOT_EOL", EF_NL_NOT_EOL, 86368567Seric "CRLF_NOT_EOL", EF_CRLF_NOT_EOL, 86468567Seric "RET_PARAM", EF_RET_PARAM, 86568567Seric "HAS_DF", EF_HAS_DF, 86668567Seric NULL 86768567Seric }; 86868567Seric 86968567Seric void 87068567Seric printenvflags(e) 87168567Seric register ENVELOPE *e; 87268567Seric { 87368567Seric register struct eflags *ef; 87468567Seric bool first = TRUE; 87568567Seric 87668567Seric printf("%lx", e->e_flags); 87768567Seric for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++) 87868567Seric { 87968567Seric if (!bitset(ef->ef_bit, e->e_flags)) 88068567Seric continue; 88168567Seric if (first) 88268567Seric printf("<%s", ef->ef_name); 88368567Seric else 88468567Seric printf(",%s", ef->ef_name); 88568567Seric first = FALSE; 88668567Seric } 88768567Seric if (!first) 88868567Seric printf(">\n"); 88968567Seric } 890