diff options
Diffstat (limited to 'contrib/sendmail/src/envelope.c')
-rw-r--r-- | contrib/sendmail/src/envelope.c | 1293 |
1 files changed, 0 insertions, 1293 deletions
diff --git a/contrib/sendmail/src/envelope.c b/contrib/sendmail/src/envelope.c deleted file mode 100644 index 20b0ba2..0000000 --- a/contrib/sendmail/src/envelope.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers. - * All rights reserved. - * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the sendmail distribution. - * - */ - -#include <sendmail.h> - -SM_RCSID("@(#)$Id: envelope.c,v 8.304 2007/04/18 17:15:49 ca Exp $") - -/* -** CLRSESSENVELOPE -- clear session oriented data in an envelope -** -** Parameters: -** e -- the envelope to clear. -** -** Returns: -** none. -*/ - -void -clrsessenvelope(e) - ENVELOPE *e; -{ -#if SASL - macdefine(&e->e_macro, A_PERM, macid("{auth_type}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{auth_authen}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{auth_author}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{auth_ssf}"), ""); -#endif /* SASL */ -#if STARTTLS - macdefine(&e->e_macro, A_PERM, macid("{cert_issuer}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{cert_subject}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{cipher_bits}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{cipher}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{tls_version}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{verify}"), ""); -# if _FFR_TLS_1 - macdefine(&e->e_macro, A_PERM, macid("{alg_bits}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{cn_issuer}"), ""); - macdefine(&e->e_macro, A_PERM, macid("{cn_subject}"), ""); -# endif /* _FFR_TLS_1 */ -#endif /* STARTTLS */ -} - -/* -** NEWENVELOPE -- fill in a new envelope -** -** Supports inheritance. -** -** Parameters: -** e -- the new envelope to fill in. -** parent -- the envelope to be the parent of e. -** rpool -- either NULL, or a pointer to a resource pool -** from which envelope memory is allocated, and -** to which envelope resources are attached. -** -** Returns: -** e. -** -** Side Effects: -** none. -*/ - -ENVELOPE * -newenvelope(e, parent, rpool) - register ENVELOPE *e; - register ENVELOPE *parent; - SM_RPOOL_T *rpool; -{ - int sendmode, dm; - - /* - ** This code used to read: - ** if (e == parent && e->e_parent != NULL) - ** parent = e->e_parent; - ** So if e == parent && e->e_parent == NULL then we would - ** set e->e_parent = e, which creates a loop in the e_parent chain. - ** This meant macvalue() could go into an infinite loop. - */ - - dm = DM_NOTSET; - if (parent != NULL) - { - char *str; - - sendmode = parent->e_sendmode; - str = macvalue(macid("{deliveryMode}"), parent); - if (str != NULL) - dm = (int) str[0]; - } - else - sendmode = DM_NOTSET; - - if (e == parent) - parent = e->e_parent; - clearenvelope(e, true, rpool); - if (e == CurEnv) - memmove((char *) &e->e_from, - (char *) &NullAddress, - sizeof(e->e_from)); - else - memmove((char *) &e->e_from, - (char *) &CurEnv->e_from, - sizeof(e->e_from)); - e->e_parent = parent; - assign_queueid(e); - e->e_ctime = curtime(); -#if _FFR_SESSID - e->e_sessid = e->e_id; -#endif /* _FFR_SESSID */ - if (parent != NULL) - { - e->e_msgpriority = parent->e_msgsize; -#if _FFR_SESSID - if (parent->e_sessid != NULL) - e->e_sessid = sm_rpool_strdup_x(rpool, - parent->e_sessid); -#endif /* _FFR_SESSID */ - - if (parent->e_quarmsg == NULL) - { - e->e_quarmsg = NULL; - macdefine(&e->e_macro, A_PERM, - macid("{quarantine}"), ""); - } - else - { - e->e_quarmsg = sm_rpool_strdup_x(rpool, - parent->e_quarmsg); - macdefine(&e->e_macro, A_PERM, - macid("{quarantine}"), e->e_quarmsg); - } - } - e->e_puthdr = putheader; - e->e_putbody = putbody; - if (CurEnv->e_xfp != NULL) - (void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT); - if (sendmode != DM_NOTSET) - e->e_sendmode = sendmode; - if (dm != DM_NOTSET) - set_delivery_mode(dm, e); - - return e; -} - -/* values for msg_timeout, see also IS_* below for usage (bit layout) */ -#define MSG_T_O 0x01 /* normal timeout */ -#define MSG_T_O_NOW 0x02 /* NOW timeout */ -#define MSG_NOT_BY 0x04 /* Deliver-By time exceeded, mode R */ -#define MSG_WARN 0x10 /* normal queue warning */ -#define MSG_WARN_BY 0x20 /* Deliver-By time exceeded, mode N */ - -#define IS_MSG_ERR(x) (((x) & 0x0f) != 0) /* return an error */ - -/* immediate return */ -#define IS_IMM_RET(x) (((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0) -#define IS_MSG_WARN(x) (((x) & 0xf0) != 0) /* return a warning */ - -/* -** DROPENVELOPE -- deallocate an envelope. -** -** Parameters: -** e -- the envelope to deallocate. -** fulldrop -- if set, do return receipts. -** split -- if true, split by recipient if message is queued up -** -** Returns: -** none. -** -** Side Effects: -** housekeeping necessary to dispose of an envelope. -** Unlocks this queue file. -*/ - -void -dropenvelope(e, fulldrop, split) - register ENVELOPE *e; - bool fulldrop; - bool split; -{ - bool panic = false; - bool queueit = false; - int msg_timeout = 0; - bool failure_return = false; - bool delay_return = false; - bool success_return = false; - bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags); - bool done = false; - register ADDRESS *q; - char *id = e->e_id; - time_t now; - char buf[MAXLINE]; - - if (tTd(50, 1)) - { - sm_dprintf("dropenvelope %p: id=", e); - xputs(sm_debug_file(), e->e_id); - sm_dprintf(", flags="); - printenvflags(e); - if (tTd(50, 10)) - { - sm_dprintf("sendq="); - printaddr(sm_debug_file(), e->e_sendqueue, true); - } - } - - if (LogLevel > 84) - sm_syslog(LOG_DEBUG, id, - "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d", - e->e_flags, OpMode, (int) CurrentPid); - - /* we must have an id to remove disk files */ - if (id == NULL) - return; - - /* if verify-only mode, we can skip most of this */ - if (OpMode == MD_VERIFY) - goto simpledrop; - - if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) - logsender(e, NULL); - e->e_flags &= ~EF_LOGSENDER; - - /* post statistics */ - poststats(StatFile); - - /* - ** Extract state information from dregs of send list. - */ - - now = curtime(); - if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) - msg_timeout = MSG_T_O; - if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 && - now >= e->e_ctime + e->e_deliver_by && - !bitset(EF_RESPONSE, e->e_flags)) - { - msg_timeout = MSG_NOT_BY; - e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; - } - else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW && - !bitset(EF_RESPONSE, e->e_flags)) - { - msg_timeout = MSG_T_O_NOW; - e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; - } - - e->e_flags &= ~EF_QUEUERUN; - for (q = e->e_sendqueue; q != NULL; q = q->q_next) - { - if (QS_IS_UNDELIVERED(q->q_state)) - queueit = true; - - /* see if a notification is needed */ - if (bitset(QPINGONFAILURE, q->q_flags) && - ((IS_MSG_ERR(msg_timeout) && - QS_IS_UNDELIVERED(q->q_state)) || - QS_IS_BADADDR(q->q_state) || - IS_IMM_RET(msg_timeout))) - { - failure_return = true; - if (!done && q->q_owner == NULL && - !emptyaddr(&e->e_from)) - { - (void) sendtolist(e->e_from.q_paddr, NULLADDR, - &e->e_errorqueue, 0, e); - done = true; - } - } - else if ((bitset(QPINGONSUCCESS, q->q_flags) && - ((QS_IS_SENT(q->q_state) && - bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) || - bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) || - bitset(QBYTRACE, q->q_flags) || - bitset(QBYNRELAY, q->q_flags)) - { - success_return = true; - } - } - - if (e->e_class < 0) - e->e_flags |= EF_NO_BODY_RETN; - - /* - ** See if the message timed out. - */ - - if (!queueit) - /* EMPTY */ - /* nothing to do */ ; - else if (IS_MSG_ERR(msg_timeout)) - { - if (failure_return) - { - if (msg_timeout == MSG_NOT_BY) - { - (void) sm_snprintf(buf, sizeof(buf), - "delivery time expired %lds", - e->e_deliver_by); - } - else - { - (void) sm_snprintf(buf, sizeof(buf), - "Cannot send message for %s", - pintvl(TimeOuts.to_q_return[e->e_timeoutclass], - false)); - } - - /* don't free, allocated from e_rpool */ - e->e_message = sm_rpool_strdup_x(e->e_rpool, buf); - message(buf); - e->e_flags |= EF_CLRQUEUE; - } - if (msg_timeout == MSG_NOT_BY) - { - (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, - "Delivery time (%lds) expired\n", - e->e_deliver_by); - } - else - (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, - "Message could not be delivered for %s\n", - pintvl(TimeOuts.to_q_return[e->e_timeoutclass], - false)); - (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, - "Message will be deleted from queue\n"); - for (q = e->e_sendqueue; q != NULL; q = q->q_next) - { - if (QS_IS_UNDELIVERED(q->q_state)) - { - q->q_state = QS_BADADDR; - if (msg_timeout == MSG_NOT_BY) - q->q_status = "5.4.7"; - else - q->q_status = "4.4.7"; - } - } - } - else - { - if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && - now >= e->e_ctime + - TimeOuts.to_q_warning[e->e_timeoutclass]) - msg_timeout = MSG_WARN; - else if (IS_DLVR_NOTIFY(e) && - e->e_deliver_by > 0 && - now >= e->e_ctime + e->e_deliver_by) - msg_timeout = MSG_WARN_BY; - - if (IS_MSG_WARN(msg_timeout)) - { - if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && - e->e_class >= 0 && - e->e_from.q_paddr != NULL && - strcmp(e->e_from.q_paddr, "<>") != 0 && - sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && - (strlen(e->e_from.q_paddr) <= 8 || - sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], - "-request") != 0)) - { - for (q = e->e_sendqueue; q != NULL; - q = q->q_next) - { - if (QS_IS_UNDELIVERED(q->q_state) -#if _FFR_NODELAYDSN_ON_HOLD - && !bitnset(M_HOLD, - q->q_mailer->m_flags) -#endif /* _FFR_NODELAYDSN_ON_HOLD */ - ) - { - if (msg_timeout == - MSG_WARN_BY && - (bitset(QPINGONDELAY, - q->q_flags) || - !bitset(QHASNOTIFY, - q->q_flags)) - ) - { - q->q_flags |= QBYNDELAY; - delay_return = true; - } - if (bitset(QPINGONDELAY, - q->q_flags)) - { - q->q_flags |= QDELAYED; - delay_return = true; - } - } - } - } - if (delay_return) - { - if (msg_timeout == MSG_WARN_BY) - { - (void) sm_snprintf(buf, sizeof(buf), - "Warning: Delivery time (%lds) exceeded", - e->e_deliver_by); - } - else - (void) sm_snprintf(buf, sizeof(buf), - "Warning: could not send message for past %s", - pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], - false)); - - /* don't free, allocated from e_rpool */ - e->e_message = sm_rpool_strdup_x(e->e_rpool, - buf); - message(buf); - e->e_flags |= EF_WARNING; - } - if (msg_timeout == MSG_WARN_BY) - { - (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, - "Warning: Delivery time (%lds) exceeded\n", - e->e_deliver_by); - } - else - (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, - "Warning: message still undelivered after %s\n", - pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], - false)); - (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, - "Will keep trying until message is %s old\n", - pintvl(TimeOuts.to_q_return[e->e_timeoutclass], - false)); - } - } - - if (tTd(50, 2)) - sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n", - failure_return, delay_return, success_return, queueit); - - /* - ** If we had some fatal error, but no addresses are marked as - ** bad, mark them _all_ as bad. - */ - - if (bitset(EF_FATALERRS, e->e_flags) && !failure_return) - { - for (q = e->e_sendqueue; q != NULL; q = q->q_next) - { - if ((QS_IS_OK(q->q_state) || - QS_IS_VERIFIED(q->q_state)) && - bitset(QPINGONFAILURE, q->q_flags)) - { - failure_return = true; - q->q_state = QS_BADADDR; - } - } - } - - /* - ** Send back return receipts as requested. - */ - - if (success_return && !failure_return && !delay_return && fulldrop && - !bitset(PRIV_NORECEIPTS, PrivacyFlags) && - strcmp(e->e_from.q_paddr, "<>") != 0) - { - auto ADDRESS *rlist = NULL; - - if (tTd(50, 8)) - sm_dprintf("dropenvelope(%s): sending return receipt\n", - id); - e->e_flags |= EF_SENDRECEIPT; - (void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e); - (void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e); - } - e->e_flags &= ~EF_SENDRECEIPT; - - /* - ** Arrange to send error messages if there are fatal errors. - */ - - if ((failure_return || delay_return) && e->e_errormode != EM_QUIET) - { - if (tTd(50, 8)) - sm_dprintf("dropenvelope(%s): saving mail\n", id); - panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags)); - } - - /* - ** Arrange to send warning messages to postmaster as requested. - */ - - if ((failure_return || pmnotify) && - PostMasterCopy != NULL && - !bitset(EF_RESPONSE, e->e_flags) && - e->e_class >= 0) - { - auto ADDRESS *rlist = NULL; - char pcopy[MAXNAME]; - - if (failure_return) - { - expand(PostMasterCopy, pcopy, sizeof(pcopy), e); - - if (tTd(50, 8)) - sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n", - id, pcopy); - (void) sendtolist(pcopy, NULLADDR, &rlist, 0, e); - } - if (pmnotify) - (void) sendtolist("postmaster", NULLADDR, - &rlist, 0, e); - (void) returntosender(e->e_message, rlist, - RTSF_PM_BOUNCE|RTSF_NO_BODY, e); - } - - /* - ** Instantiate or deinstantiate the queue. - */ - -simpledrop: - if (tTd(50, 8)) - sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n", - id, queueit); - if (!queueit || bitset(EF_CLRQUEUE, e->e_flags)) - { - if (tTd(50, 1)) - { - sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=", - e->e_id, queueit); - printenvflags(e); - } - if (!panic) - { - if (e->e_dfp != NULL) - { - (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); - e->e_dfp = NULL; - } - (void) xunlink(queuename(e, DATAFL_LETTER)); - } - if (panic && QueueMode == QM_LOST) - { - /* - ** leave the Qf file behind as - ** the delivery attempt failed. - */ - - /* EMPTY */ - } - else - if (xunlink(queuename(e, ANYQFL_LETTER)) == 0) - { - /* add to available space in filesystem */ - updfs(e, -1, panic ? 0 : -1, "dropenvelope"); - } - - if (e->e_ntries > 0 && LogLevel > 9) - sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d", - pintvl(curtime() - e->e_ctime, true), - e->e_ntries); - } - else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) - { - if (!split) - queueup(e, false, true); - else - { - ENVELOPE *oldsib; - ENVELOPE *ee; - - /* - ** Save old sibling and set it to NULL to avoid - ** queueing up the same envelopes again. - ** This requires that envelopes in that list have - ** been take care of before (or at some other place). - */ - - oldsib = e->e_sibling; - e->e_sibling = NULL; - if (!split_by_recipient(e) && - bitset(EF_FATALERRS, e->e_flags)) - { - syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d", - e->e_id, queuename(e, DATAFL_LETTER), - (int) geteuid()); - } - for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) - queueup(ee, false, true); - queueup(e, false, true); - - /* clean up */ - for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) - { - /* now unlock the job */ - if (tTd(50, 8)) - sm_dprintf("dropenvelope(%s): unlocking job\n", - ee->e_id); - closexscript(ee); - unlockqueue(ee); - - /* this envelope is marked unused */ - if (ee->e_dfp != NULL) - { - (void) sm_io_close(ee->e_dfp, - SM_TIME_DEFAULT); - ee->e_dfp = NULL; - } - ee->e_id = NULL; - ee->e_flags &= ~EF_HAS_DF; - } - e->e_sibling = oldsib; - } - } - - /* now unlock the job */ - if (tTd(50, 8)) - sm_dprintf("dropenvelope(%s): unlocking job\n", id); - closexscript(e); - unlockqueue(e); - - /* make sure that this envelope is marked unused */ - if (e->e_dfp != NULL) - { - (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); - e->e_dfp = NULL; - } - e->e_id = NULL; - e->e_flags &= ~EF_HAS_DF; -} -/* -** CLEARENVELOPE -- clear an envelope without unlocking -** -** This is normally used by a child process to get a clean -** envelope without disturbing the parent. -** -** Parameters: -** e -- the envelope to clear. -** fullclear - if set, the current envelope is total -** garbage and should be ignored; otherwise, -** release any resources it may indicate. -** rpool -- either NULL, or a pointer to a resource pool -** from which envelope memory is allocated, and -** to which envelope resources are attached. -** -** Returns: -** none. -** -** Side Effects: -** Closes files associated with the envelope. -** Marks the envelope as unallocated. -*/ - -void -clearenvelope(e, fullclear, rpool) - register ENVELOPE *e; - bool fullclear; - SM_RPOOL_T *rpool; -{ - register HDR *bh; - register HDR **nhp; - extern ENVELOPE BlankEnvelope; - char **p; - - if (!fullclear) - { - /* clear out any file information */ - if (e->e_xfp != NULL) - (void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT); - if (e->e_dfp != NULL) - (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); - e->e_xfp = e->e_dfp = NULL; - } - - /* - ** Copy BlankEnvelope into *e. - ** It is not safe to simply copy pointers to strings; - ** the strings themselves must be copied (or set to NULL). - ** The problem is that when we assign a new string value to - ** a member of BlankEnvelope, we free the old string. - ** We did not need to do this copying in sendmail 8.11 :-( - ** and it is a potential performance hit. Reference counted - ** strings are one way out. - */ - - *e = BlankEnvelope; - e->e_message = NULL; - e->e_qfletter = '\0'; - e->e_quarmsg = NULL; - macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), ""); - - /* - ** Copy the macro table. - ** We might be able to avoid this by zeroing the macro table - ** and always searching BlankEnvelope.e_macro after e->e_macro - ** in macvalue(). - */ - - for (p = &e->e_macro.mac_table[0]; - p <= &e->e_macro.mac_table[MAXMACROID]; - ++p) - { - if (*p != NULL) - *p = sm_rpool_strdup_x(rpool, *p); - } - - /* - ** XXX There are many strings in the envelope structure - ** XXX that we are not attempting to copy here. - ** XXX Investigate this further. - */ - - e->e_rpool = rpool; - e->e_macro.mac_rpool = rpool; - if (Verbose) - set_delivery_mode(SM_DELIVER, e); - bh = BlankEnvelope.e_header; - nhp = &e->e_header; - while (bh != NULL) - { - *nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof(*bh)); - memmove((char *) *nhp, (char *) bh, sizeof(*bh)); - bh = bh->h_link; - nhp = &(*nhp)->h_link; - } -} -/* -** INITSYS -- initialize instantiation of system -** -** In Daemon mode, this is done in the child. -** -** Parameters: -** e -- the envelope to use. -** -** Returns: -** none. -** -** Side Effects: -** Initializes the system macros, some global variables, -** etc. In particular, the current time in various -** forms is set. -*/ - -void -initsys(e) - register ENVELOPE *e; -{ - char buf[10]; -#ifdef TTYNAME - static char ybuf[60]; /* holds tty id */ - register char *p; - extern char *ttyname(); -#endif /* TTYNAME */ - - /* - ** Give this envelope a reality. - ** I.e., an id, a transcript, and a creation time. - ** We don't select the queue until all of the recipients are known. - */ - - openxscript(e); - e->e_ctime = curtime(); - e->e_qfletter = '\0'; - - /* - ** Set OutChannel to something useful if stdout isn't it. - ** This arranges that any extra stuff the mailer produces - ** gets sent back to the user on error (because it is - ** tucked away in the transcript). - */ - - if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && - e->e_xfp != NULL) - OutChannel = e->e_xfp; - - /* - ** Set up some basic system macros. - */ - - /* process id */ - (void) sm_snprintf(buf, sizeof(buf), "%d", (int) CurrentPid); - macdefine(&e->e_macro, A_TEMP, 'p', buf); - - /* hop count */ - (void) sm_snprintf(buf, sizeof(buf), "%d", e->e_hopcount); - macdefine(&e->e_macro, A_TEMP, 'c', buf); - - /* time as integer, unix time, arpa time */ - settime(e); - - /* Load average */ - sm_getla(); - -#ifdef TTYNAME - /* tty name */ - if (macvalue('y', e) == NULL) - { - p = ttyname(2); - if (p != NULL) - { - if (strrchr(p, '/') != NULL) - p = strrchr(p, '/') + 1; - (void) sm_strlcpy(ybuf, sizeof(ybuf), p); - macdefine(&e->e_macro, A_PERM, 'y', ybuf); - } - } -#endif /* TTYNAME */ -} -/* -** SETTIME -- set the current time. -** -** Parameters: -** e -- the envelope in which the macros should be set. -** -** Returns: -** none. -** -** Side Effects: -** Sets the various time macros -- $a, $b, $d, $t. -*/ - -void -settime(e) - register ENVELOPE *e; -{ - register char *p; - auto time_t now; - char buf[30]; - register struct tm *tm; - - now = curtime(); - (void) sm_snprintf(buf, sizeof(buf), "%ld", (long) now); - macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf); - tm = gmtime(&now); - (void) sm_snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min); - macdefine(&e->e_macro, A_TEMP, 't', buf); - (void) sm_strlcpy(buf, ctime(&now), sizeof(buf)); - p = strchr(buf, '\n'); - if (p != NULL) - *p = '\0'; - macdefine(&e->e_macro, A_TEMP, 'd', buf); - macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf)); - if (macvalue('a', e) == NULL) - macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e)); -} -/* -** OPENXSCRIPT -- Open transcript file -** -** Creates a transcript file for possible eventual mailing or -** sending back. -** -** Parameters: -** e -- the envelope to create the transcript in/for. -** -** Returns: -** none -** -** Side Effects: -** Creates the transcript file. -*/ - -#ifndef O_APPEND -# define O_APPEND 0 -#endif /* ! O_APPEND */ - -void -openxscript(e) - register ENVELOPE *e; -{ - register char *p; - - if (e->e_xfp != NULL) - return; - -#if 0 - if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags)) - syserr("openxscript: job not locked"); -#endif /* 0 */ - - p = queuename(e, XSCRPT_LETTER); - e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize, - SFF_NOTEXCL|SFF_OPENASROOT); - - if (e->e_xfp == NULL) - { - syserr("Can't create transcript file %s", p); - e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, - SM_PATH_DEVNULL, SM_IO_RDWR, NULL); - if (e->e_xfp == NULL) - syserr("!Can't open %s", SM_PATH_DEVNULL); - } - (void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0); - if (tTd(46, 9)) - { - sm_dprintf("openxscript(%s):\n ", p); - dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true, - false); - } -} -/* -** CLOSEXSCRIPT -- close the transcript file. -** -** Parameters: -** e -- the envelope containing the transcript to close. -** -** Returns: -** none. -** -** Side Effects: -** none. -*/ - -void -closexscript(e) - register ENVELOPE *e; -{ - if (e->e_xfp == NULL) - return; -#if 0 - if (e->e_lockfp == NULL) - syserr("closexscript: job not locked"); -#endif /* 0 */ - (void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT); - e->e_xfp = NULL; -} -/* -** SETSENDER -- set the person who this message is from -** -** Under certain circumstances allow the user to say who -** s/he is (using -f or -r). These are: -** 1. The user's uid is zero (root). -** 2. The user's login name is in an approved list (typically -** from a network server). -** 3. The address the user is trying to claim has a -** "!" character in it (since #2 doesn't do it for -** us if we are dialing out for UUCP). -** A better check to replace #3 would be if the -** effective uid is "UUCP" -- this would require me -** to rewrite getpwent to "grab" uucp as it went by, -** make getname more nasty, do another passwd file -** scan, or compile the UID of "UUCP" into the code, -** all of which are reprehensible. -** -** Assuming all of these fail, we figure out something -** ourselves. -** -** Parameters: -** from -- the person we would like to believe this message -** is from, as specified on the command line. -** e -- the envelope in which we would like the sender set. -** delimptr -- if non-NULL, set to the location of the -** trailing delimiter. -** delimchar -- the character that will delimit the sender -** address. -** internal -- set if this address is coming from an internal -** source such as an owner alias. -** -** Returns: -** none. -** -** Side Effects: -** sets sendmail's notion of who the from person is. -*/ - -void -setsender(from, e, delimptr, delimchar, internal) - char *from; - register ENVELOPE *e; - char **delimptr; - int delimchar; - bool internal; -{ - register char **pvp; - char *realname = NULL; - char *bp; - char buf[MAXNAME + 2]; - char pvpbuf[PSBUFSIZE]; - extern char *FullName; - - if (tTd(45, 1)) - sm_dprintf("setsender(%s)\n", from == NULL ? "" : from); - - /* may be set from earlier calls */ - macdefine(&e->e_macro, A_PERM, 'x', ""); - - /* - ** Figure out the real user executing us. - ** Username can return errno != 0 on non-errors. - */ - - if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP || - OpMode == MD_ARPAFTP || OpMode == MD_DAEMON) - realname = from; - if (realname == NULL || realname[0] == '\0') - realname = username(); - - if (ConfigLevel < 2) - SuprErrs = true; - - macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s"); - - /* preset state for then clause in case from == NULL */ - e->e_from.q_state = QS_BADADDR; - e->e_from.q_flags = 0; - if (from == NULL || - parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, - delimchar, delimptr, e, false) == NULL || - QS_IS_BADADDR(e->e_from.q_state) || - e->e_from.q_mailer == ProgMailer || - e->e_from.q_mailer == FileMailer || - e->e_from.q_mailer == InclMailer) - { - /* log garbage addresses for traceback */ - if (from != NULL && LogLevel > 2) - { - char *p; - char ebuf[MAXNAME * 2 + 2]; - - p = macvalue('_', e); - if (p == NULL) - { - char *host = RealHostName; - - if (host == NULL) - host = MyHostName; - (void) sm_snprintf(ebuf, sizeof(ebuf), - "%.*s@%.*s", MAXNAME, - realname, MAXNAME, host); - p = ebuf; - } - sm_syslog(LOG_NOTICE, e->e_id, - "setsender: %s: invalid or unparsable, received from %s", - shortenstring(from, 83), p); - } - if (from != NULL) - { - if (!QS_IS_BADADDR(e->e_from.q_state)) - { - /* it was a bogus mailer in the from addr */ - e->e_status = "5.1.7"; - usrerrenh(e->e_status, - "553 Invalid sender address"); - } - SuprErrs = true; - } - if (from == realname || - parseaddr(from = realname, - &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ', - NULL, e, false) == NULL) - { - char nbuf[100]; - - SuprErrs = true; - expand("\201n", nbuf, sizeof(nbuf), e); - from = sm_rpool_strdup_x(e->e_rpool, nbuf); - if (parseaddr(from, &e->e_from, RF_COPYALL, ' ', - NULL, e, false) == NULL && - parseaddr(from = "postmaster", &e->e_from, - RF_COPYALL, ' ', NULL, e, false) == NULL) - syserr("553 5.3.0 setsender: can't even parse postmaster!"); - } - } - else - FromFlag = true; - e->e_from.q_state = QS_SENDER; - if (tTd(45, 5)) - { - sm_dprintf("setsender: QS_SENDER "); - printaddr(sm_debug_file(), &e->e_from, false); - } - SuprErrs = false; - -#if USERDB - if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) - { - register char *p; - - p = udbsender(e->e_from.q_user, e->e_rpool); - if (p != NULL) - from = p; - } -#endif /* USERDB */ - - if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) - { - SM_MBDB_T user; - - if (!internal) - { - /* if the user already given fullname don't redefine */ - if (FullName == NULL) - FullName = macvalue('x', e); - if (FullName != NULL) - { - if (FullName[0] == '\0') - FullName = NULL; - else - FullName = newstr(FullName); - } - } - - if (e->e_from.q_user[0] != '\0' && - sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK) - { - /* - ** Process passwd file entry. - */ - - /* extract home directory */ - if (*user.mbdb_homedir == '\0') - e->e_from.q_home = NULL; - else if (strcmp(user.mbdb_homedir, "/") == 0) - e->e_from.q_home = ""; - else - e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool, - user.mbdb_homedir); - macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home); - - /* extract user and group id */ - if (user.mbdb_uid != SM_NO_UID) - { - e->e_from.q_uid = user.mbdb_uid; - e->e_from.q_gid = user.mbdb_gid; - e->e_from.q_flags |= QGOODUID; - } - - /* extract full name from passwd file */ - if (FullName == NULL && !internal && - user.mbdb_fullname[0] != '\0' && - strcmp(user.mbdb_name, e->e_from.q_user) == 0) - { - FullName = newstr(user.mbdb_fullname); - } - } - else - { - e->e_from.q_home = NULL; - } - if (FullName != NULL && !internal) - macdefine(&e->e_macro, A_TEMP, 'x', FullName); - } - else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP) - { - if (e->e_from.q_home == NULL) - { - e->e_from.q_home = getenv("HOME"); - if (e->e_from.q_home != NULL) - { - if (*e->e_from.q_home == '\0') - e->e_from.q_home = NULL; - else if (strcmp(e->e_from.q_home, "/") == 0) - e->e_from.q_home++; - } - } - e->e_from.q_uid = RealUid; - e->e_from.q_gid = RealGid; - e->e_from.q_flags |= QGOODUID; - } - - /* - ** Rewrite the from person to dispose of possible implicit - ** links in the net. - */ - - pvp = prescan(from, delimchar, pvpbuf, sizeof(pvpbuf), NULL, - IntTokenTab, false); - if (pvp == NULL) - { - /* don't need to give error -- prescan did that already */ - if (LogLevel > 2) - sm_syslog(LOG_NOTICE, e->e_id, - "cannot prescan from (%s)", - shortenstring(from, MAXSHORTSTR)); - finis(true, true, ExitStat); - } - (void) REWRITE(pvp, 3, e); - (void) REWRITE(pvp, 1, e); - (void) REWRITE(pvp, 4, e); - macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); - bp = buf + 1; - cataddr(pvp, NULL, bp, sizeof(buf) - 2, '\0', false); - if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags)) - { - /* heuristic: route-addr: add angle brackets */ - (void) sm_strlcat(bp, ">", sizeof(buf) - 1); - *--bp = '<'; - } - e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp); - macdefine(&e->e_macro, A_PERM, 'f', e->e_sender); - - /* save the domain spec if this mailer wants it */ - if (e->e_from.q_mailer != NULL && - bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) - { - char **lastat; - - /* get rid of any pesky angle brackets */ - macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s"); - (void) REWRITE(pvp, 3, e); - (void) REWRITE(pvp, 1, e); - (void) REWRITE(pvp, 4, e); - macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); - - /* strip off to the last "@" sign */ - for (lastat = NULL; *pvp != NULL; pvp++) - { - if (strcmp(*pvp, "@") == 0) - lastat = pvp; - } - if (lastat != NULL) - { - e->e_fromdomain = copyplist(lastat, true, e->e_rpool); - if (tTd(45, 3)) - { - sm_dprintf("Saving from domain: "); - printav(sm_debug_file(), e->e_fromdomain); - } - } - } -} -/* -** PRINTENVFLAGS -- print envelope flags for debugging -** -** Parameters: -** e -- the envelope with the flags to be printed. -** -** Returns: -** none. -*/ - -struct eflags -{ - char *ef_name; - unsigned long ef_bit; -}; - -static struct eflags EnvelopeFlags[] = -{ - { "OLDSTYLE", EF_OLDSTYLE }, - { "INQUEUE", EF_INQUEUE }, - { "NO_BODY_RETN", EF_NO_BODY_RETN }, - { "CLRQUEUE", EF_CLRQUEUE }, - { "SENDRECEIPT", EF_SENDRECEIPT }, - { "FATALERRS", EF_FATALERRS }, - { "DELETE_BCC", EF_DELETE_BCC }, - { "RESPONSE", EF_RESPONSE }, - { "RESENT", EF_RESENT }, - { "VRFYONLY", EF_VRFYONLY }, - { "WARNING", EF_WARNING }, - { "QUEUERUN", EF_QUEUERUN }, - { "GLOBALERRS", EF_GLOBALERRS }, - { "PM_NOTIFY", EF_PM_NOTIFY }, - { "METOO", EF_METOO }, - { "LOGSENDER", EF_LOGSENDER }, - { "NORECEIPT", EF_NORECEIPT }, - { "HAS8BIT", EF_HAS8BIT }, - { "NL_NOT_EOL", EF_NL_NOT_EOL }, - { "CRLF_NOT_EOL", EF_CRLF_NOT_EOL }, - { "RET_PARAM", EF_RET_PARAM }, - { "HAS_DF", EF_HAS_DF }, - { "IS_MIME", EF_IS_MIME }, - { "DONT_MIME", EF_DONT_MIME }, - { "DISCARD", EF_DISCARD }, - { "TOOBIG", EF_TOOBIG }, - { "SPLIT", EF_SPLIT }, - { "UNSAFE", EF_UNSAFE }, - { NULL, 0 } -}; - -void -printenvflags(e) - register ENVELOPE *e; -{ - register struct eflags *ef; - bool first = true; - - sm_dprintf("%lx", e->e_flags); - for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++) - { - if (!bitset(ef->ef_bit, e->e_flags)) - continue; - if (first) - sm_dprintf("<%s", ef->ef_name); - else - sm_dprintf(",%s", ef->ef_name); - first = false; - } - if (!first) - sm_dprintf(">\n"); -} |