📄 deliver.c
字号:
# if NETINET6
if (*mxhosts[hostnum] == '[')
{
endp = strchr(mxhosts[hostnum] + 1, ']');
if (endp != NULL)
endp = strpbrk(endp + 1, ":,");
}
else
endp = strpbrk(mxhosts[hostnum], ":,");
# else /* NETINET6 */
endp = strpbrk(mxhosts[hostnum], ":,");
# endif /* NETINET6 */
if (endp != NULL)
{
sep = *endp;
*endp = '\0';
}
if (*mxhosts[hostnum] == '\0')
{
syserr("deliver: null host name in signature");
hostnum++;
if (endp != NULL)
*endp = sep;
continue;
}
(void) strlcpy(hostbuf, mxhosts[hostnum],
sizeof hostbuf);
hostnum++;
if (endp != NULL)
*endp = sep;
/* see if we already know that this host is fried */
CurHostName = hostbuf;
mci = mci_get(hostbuf, m);
if (mci->mci_state != MCIS_CLOSED)
{
if (tTd(11, 1))
{
dprintf("openmailer: ");
mci_dump(mci, FALSE);
}
CurHostName = mci->mci_host;
message("Using cached %sSMTP connection to %s via %s...",
bitset(MCIF_ESMTP, mci->mci_flags) ? "E" : "",
hostbuf, m->m_name);
mci->mci_deliveries++;
break;
}
mci->mci_mailer = m;
if (mci->mci_exitstat != EX_OK)
{
if (mci->mci_exitstat == EX_TEMPFAIL)
goodmxfound = TRUE;
continue;
}
if (mci_lock_host(mci) != EX_OK)
{
mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
goodmxfound = TRUE;
continue;
}
/* try the connection */
sm_setproctitle(TRUE, e, "%s %s: %s",
qid_printname(e),
hostbuf, "user open");
# if NETUNIX
if (mux_path != NULL)
{
message("Connecting to %s via %s...",
mux_path, m->m_name);
i = makeconnection_ds(mux_path, mci);
}
else
# endif /* NETUNIX */
{
if (port == 0)
message("Connecting to %s via %s...",
hostbuf, m->m_name);
else
message("Connecting to %s port %d via %s...",
hostbuf, ntohs(port),
m->m_name);
i = makeconnection(hostbuf, port, mci, e);
}
mci->mci_lastuse = curtime();
mci->mci_deliveries = 0;
mci->mci_exitstat = i;
mci->mci_errno = errno;
# if NAMED_BIND
mci->mci_herrno = h_errno;
# endif /* NAMED_BIND */
if (i == EX_OK)
{
goodmxfound = TRUE;
mci->mci_state = MCIS_OPENING;
mci_cache(mci);
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d === CONNECT %s\n",
(int) getpid(), hostbuf);
break;
}
else
{
if (tTd(11, 1))
dprintf("openmailer: makeconnection => stat=%d, errno=%d\n",
i, errno);
if (i == EX_TEMPFAIL)
goodmxfound = TRUE;
mci_unlock_host(mci);
}
/* enter status of this host */
setstat(i);
/* should print some message here for -v mode */
}
if (mci == NULL)
{
syserr("deliver: no host name");
rcode = EX_SOFTWARE;
goto give_up;
}
mci->mci_pid = 0;
#else /* DAEMON */
syserr("554 5.3.5 openmailer: no IPC");
if (tTd(11, 1))
dprintf("openmailer: NULL\n");
rcode = EX_UNAVAILABLE;
goto give_up;
#endif /* DAEMON */
}
else
{
/* flush any expired connections */
(void) mci_scan(NULL);
mci = NULL;
#if SMTP
if (bitnset(M_LMTP, m->m_flags))
{
/* try to get a cached connection */
mci = mci_get(m->m_name, m);
if (mci->mci_host == NULL)
mci->mci_host = m->m_name;
CurHostName = mci->mci_host;
if (mci->mci_state != MCIS_CLOSED)
{
message("Using cached LMTP connection for %s...",
m->m_name);
mci->mci_deliveries++;
goto do_transfer;
}
}
#endif /* SMTP */
/* announce the connection to verbose listeners */
if (host == NULL || host[0] == '\0')
message("Connecting to %s...", m->m_name);
else
message("Connecting to %s via %s...", host, m->m_name);
if (TrafficLogFile != NULL)
{
char **av;
fprintf(TrafficLogFile, "%05d === EXEC", (int) getpid());
for (av = pv; *av != NULL; av++)
fprintf(TrafficLogFile, " %s", *av);
fprintf(TrafficLogFile, "\n");
}
#if XDEBUG
checkfd012("before creating mail pipe");
#endif /* XDEBUG */
/* create a pipe to shove the mail through */
if (pipe(mpvect) < 0)
{
syserr("%s... openmailer(%s): pipe (to mailer)",
shortenstring(e->e_to, MAXSHORTSTR), m->m_name);
if (tTd(11, 1))
dprintf("openmailer: NULL\n");
rcode = EX_OSERR;
goto give_up;
}
#if XDEBUG
/* make sure we didn't get one of the standard I/O files */
if (mpvect[0] < 3 || mpvect[1] < 3)
{
syserr("%s... openmailer(%s): bogus mpvect %d %d",
shortenstring(e->e_to, MAXSHORTSTR), m->m_name,
mpvect[0], mpvect[1]);
printopenfds(TRUE);
if (tTd(11, 1))
dprintf("openmailer: NULL\n");
rcode = EX_OSERR;
goto give_up;
}
/* make sure system call isn't dead meat */
checkfdopen(mpvect[0], "mpvect[0]");
checkfdopen(mpvect[1], "mpvect[1]");
if (mpvect[0] == mpvect[1] ||
(e->e_lockfp != NULL &&
(mpvect[0] == fileno(e->e_lockfp) ||
mpvect[1] == fileno(e->e_lockfp))))
{
if (e->e_lockfp == NULL)
syserr("%s... openmailer(%s): overlapping mpvect %d %d",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name, mpvect[0], mpvect[1]);
else
syserr("%s... openmailer(%s): overlapping mpvect %d %d, lockfp = %d",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name, mpvect[0], mpvect[1],
fileno(e->e_lockfp));
}
#endif /* XDEBUG */
/* create a return pipe */
if (pipe(rpvect) < 0)
{
syserr("%s... openmailer(%s): pipe (from mailer)",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name);
(void) close(mpvect[0]);
(void) close(mpvect[1]);
if (tTd(11, 1))
dprintf("openmailer: NULL\n");
rcode = EX_OSERR;
goto give_up;
}
#if XDEBUG
checkfdopen(rpvect[0], "rpvect[0]");
checkfdopen(rpvect[1], "rpvect[1]");
#endif /* XDEBUG */
/*
** Actually fork the mailer process.
** DOFORK is clever about retrying.
**
** Dispose of SIGCHLD signal catchers that may be laying
** around so that endmailer will get it.
*/
if (e->e_xfp != NULL)
(void) fflush(e->e_xfp); /* for debugging */
(void) fflush(stdout);
(void) setsignal(SIGCHLD, SIG_DFL);
DOFORK(FORK);
/* pid is set by DOFORK */
if (pid < 0)
{
/* failure */
syserr("%s... openmailer(%s): cannot fork",
shortenstring(e->e_to, MAXSHORTSTR), m->m_name);
(void) close(mpvect[0]);
(void) close(mpvect[1]);
(void) close(rpvect[0]);
(void) close(rpvect[1]);
if (tTd(11, 1))
dprintf("openmailer: NULL\n");
rcode = EX_OSERR;
goto give_up;
}
else if (pid == 0)
{
int i;
int save_errno;
int new_euid = NO_UID;
int new_ruid = NO_UID;
int new_gid = NO_GID;
struct stat stb;
extern int DtableSize;
if (e->e_lockfp != NULL)
(void) close(fileno(e->e_lockfp));
/* child -- set up input & exec mailer */
(void) setsignal(SIGINT, SIG_IGN);
(void) setsignal(SIGHUP, SIG_IGN);
(void) setsignal(SIGTERM, SIG_DFL);
if (m != FileMailer || stat(tochain->q_user, &stb) < 0)
stb.st_mode = 0;
# if HASSETUSERCONTEXT
/*
** Set user resources.
*/
if (contextaddr != NULL)
{
struct passwd *pwd;
if (contextaddr->q_ruser != NULL)
pwd = sm_getpwnam(contextaddr->q_ruser);
else
pwd = sm_getpwnam(contextaddr->q_user);
if (pwd != NULL)
(void) setusercontext(NULL,
pwd, pwd->pw_uid,
LOGIN_SETRESOURCES|LOGIN_SETPRIORITY);
}
# endif /* HASSETUSERCONTEXT */
/* tweak niceness */
if (m->m_nice != 0)
(void) nice(m->m_nice);
/* reset group id */
if (bitnset(M_SPECIFIC_UID, m->m_flags))
new_gid = m->m_gid;
else if (bitset(S_ISGID, stb.st_mode))
new_gid = stb.st_gid;
else if (ctladdr != NULL && ctladdr->q_gid != 0)
{
if (!DontInitGroups)
{
char *u = ctladdr->q_ruser;
if (u == NULL)
u = ctladdr->q_user;
if (initgroups(u, ctladdr->q_gid) == -1 && suidwarn)
{
syserr("openmailer: initgroups(%s, %d) failed",
u, ctladdr->q_gid);
exit(EX_TEMPFAIL);
}
}
else
{
GIDSET_T gidset[1];
gidset[0] = ctladdr->q_gid;
if (setgroups(1, gidset) == -1 && suidwarn)
{
syserr("openmailer: setgroups() failed");
exit(EX_TEMPFAIL);
}
}
new_gid = ctladdr->q_gid;
}
else
{
if (!DontInitGroups)
{
if (initgroups(DefUser, DefGid) == -1 && suidwarn)
{
syserr("openmailer: initgroups(%s, %d) failed",
DefUser, DefGid);
exit(EX_TEMPFAIL);
}
}
else
{
GIDSET_T gidset[1];
gidset[0] = DefGid;
if (setgroups(1, gidset) == -1 && suidwarn)
{
syserr("openmailer: setgroups() failed");
exit(EX_TEMPFAIL);
}
}
if (m->m_gid == 0)
new_gid = DefGid;
else
new_gid = m->m_gid;
}
if (new_gid != NO_GID)
{
if (RunAsUid != 0 &&
bitnset(M_SPECIFIC_UID, m->m_flags) &&
new_gid != getgid() &&
new_gid != getegid())
{
/* Only root can change the gid */
syserr("openmailer: insufficient privileges to change gid");
exit(EX_TEMPFAIL);
}
if (setgid(new_gid) < 0 && suidwarn)
{
syserr("openmailer: setgid(%ld) failed",
(long) new_gid);
exit(EX_TEMPFAIL);
}
}
/* change root to some "safe" directory */
if (m->m_rootdir != NULL)
{
expand(m->m_rootdir, buf, sizeof buf, e);
if (tTd(11, 20))
dprintf("openmailer: chroot %s\n",
buf);
if (chroot(buf) < 0)
{
syserr("openmailer: Cannot chroot(%s)",
buf);
exit(EX_TEMPFAIL);
}
if (chdir("/") < 0)
{
syserr("openmailer: cannot chdir(/)");
exit(EX_TEMPFAIL);
}
}
/* reset user id */
endpwent();
if (bitnset(M_SPECIFIC_UID, m->m_flags))
new_euid = m->m_uid;
else if (bitset(S_ISUID, stb.st_mode))
new_ruid = stb.st_uid;
else if (ctladdr != NULL && ctladdr->q_uid != 0)
new_ruid = ctladdr->q_uid;
else if (m->m_uid != 0)
new_ruid = m->m_uid;
else
new_ruid = DefUid;
if (new_euid != NO_UID)
{
if (RunAsUid != 0 && new_euid != RunAsUid)
{
/* Only root can change the uid */
syserr("openmailer: insufficient privileges to change uid");
exit(EX_TEMPFAIL);
}
vendor_set_uid(new_euid);
# if MAILER_SETUID_METHOD == USE_SETEUID
if (seteuid(new_euid) < 0 && suidwarn)
{
syserr("openmailer: seteuid(%ld) failed",
(long) new_euid);
exit(EX_TEMPFAIL);
}
# endif /* MAILER_SETUID_METHOD == USE_SETEUID */
# if MAILER_SETUID_METHOD == USE_SETREUID
if (setreuid(new_ruid, new_euid) < 0 && suidwarn)
{
syserr("openmailer: setreuid(%ld, %ld) failed",
(long) new_ruid, (long) new_euid);
exit(EX_TEMPFAIL);
}
# endif /* MAILER_SETUID_METHOD == USE_SETREUID */
# if MAILER_SETUID_METHOD == USE_SETUID
if (new_euid != geteuid() && setuid(new_euid) < 0 && suidwarn)
{
syserr("openmailer: setuid(%ld) failed",
(long) new_euid);
exit(EX_TEMPFAIL);
}
# endif /* MAILER_SETUID_METHOD == USE_SETUID */
}
else if (new_ruid != NO_UID)
{
vendor_set_uid(new_ruid);
if (setuid(new_ruid) < 0 && suidwarn)
{
syserr("openmailer: setuid(%ld) failed",
(long) new_ruid);
exit(EX_TEMPFAIL);
}
}
if (tTd(11, 2))
dprintf("openmailer: running as r/euid=%d/%d, r/egid=%d/%d\n",
(int) getuid(), (int) geteuid(),
(int) getgid(), (int) getegid());
/* move into some "safe" directory */
if (m->m_execdir != NULL)
{
char *q;
for (p = m->m_execdir; p != NULL; p = q)
{
q = strchr(p, ':');
if (q != NULL)
*q = '\0';
expand(p, buf, sizeof buf, e);
if (q != NULL)
*q++ = ':';
if (tTd(11, 20))
dprintf("openmailer: trydir %s\n",
buf);
if (buf[0] != '\0' && chdir(buf) >= 0)
break;
}
}
/* arrange to filter std & diag output of command */
(void) close(rpvect[0]);
if (dup2(rpvect[1], STDOUT_FILENO) < 0)
{
syserr("%s... openmailer(%s): cannot dup pipe %d for stdout",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name, rpvect[1]);
_exit(EX_OSERR);
}
(void) close(rpvect[1]);
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
{
syserr("%s... openmailer(%s): cannot dup stdout for stderr",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name);
_exit(EX_OSERR);
}
/* arrange to get standard input */
(void) close(mpvect[1]);
if (dup2(mpvect[0], STDIN_FILENO) < 0)
{
syserr("%s... openmailer(%s): cannot dup pipe %d for stdin",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name, mpvect[0]);
_exit(EX_OSERR);
}
(void) close(mpvect[0]);
/* arrange for all the files to be closed */
for (i = 3; i < DtableSize; i++)
{
register int j;
if ((j = fcntl(i, F_GETFD, 0)) != -1)
(void) fcntl(i, F_SETFD,
j | FD_CLOEXEC);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -