make a bunch of #defines into 0/1 instead of ifdef/ifndef
[unix-history] / usr / src / usr.sbin / sendmail / src / deliver.c
index 255f10c..b7eb70e 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)deliver.c  8.149 (Berkeley) %G%";
+static char sccsid[] = "@(#)deliver.c  8.158 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -518,7 +518,7 @@ sendenvelope(e, mode)
        /* now run through the queue */
        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
        {
        /* now run through the queue */
        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
        {
-#ifdef XDEBUG
+#if XDEBUG
                char wbuf[MAXNAME + 20];
 
                (void) sprintf(wbuf, "sendall(%s)", q->q_paddr);
                char wbuf[MAXNAME + 20];
 
                (void) sprintf(wbuf, "sendall(%s)", q->q_paddr);
@@ -563,7 +563,7 @@ sendenvelope(e, mode)
                e->e_ntries++;
        }
 
                e->e_ntries++;
        }
 
-#ifdef XDEBUG
+#if XDEBUG
        checkfd012("end of sendenvelope");
 #endif
 
        checkfd012("end of sendenvelope");
 #endif
 
@@ -626,6 +626,7 @@ sendenvelope(e, mode)
 **             returns twice, once in parent and once in child.
 */
 
 **             returns twice, once in parent and once in child.
 */
 
+int
 dofork()
 {
        register int pid = -1;
 dofork()
 {
        register int pid = -1;
@@ -683,6 +684,7 @@ deliver(e, firstto)
        char buf[MAXNAME + 1];
        char rpathbuf[MAXNAME + 1];     /* translated return path */
        extern int checkcompat();
        char buf[MAXNAME + 1];
        char rpathbuf[MAXNAME + 1];     /* translated return path */
        extern int checkcompat();
+       extern void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int));
 
        errno = 0;
        if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
 
        errno = 0;
        if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
@@ -857,7 +859,7 @@ deliver(e, firstto)
                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                {
                        e->e_flags |= EF_NO_BODY_RETN;
                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                {
                        e->e_flags |= EF_NO_BODY_RETN;
-                       mci->mci_status = "5.2.3";
+                       to->q_status = "5.2.3";
                        usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
                        giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e);
                        continue;
                        usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
                        giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e);
                        continue;
@@ -913,7 +915,7 @@ deliver(e, firstto)
 
                if (strcmp(m->m_mailer, "[FILE]") == 0)
                {
 
                if (strcmp(m->m_mailer, "[FILE]") == 0)
                {
-                       rcode = mailfile(user, ctladdr, e);
+                       rcode = mailfile(user, ctladdr, SFF_CREAT, e);
                        giveresponse(rcode, m, NULL, ctladdr, xstart, e);
                        e->e_nsent++;
                        if (rcode == EX_OK)
                        giveresponse(rcode, m, NULL, ctladdr, xstart, e);
                        e->e_nsent++;
                        if (rcode == EX_OK)
@@ -999,7 +1001,7 @@ deliver(e, firstto)
        */
 
        /*XXX this seems a bit wierd */
        */
 
        /*XXX this seems a bit wierd */
-       if (ctladdr == NULL && m != ProgMailer &&
+       if (ctladdr == NULL && m != ProgMailer && m != FileMailer &&
            bitset(QGOODUID, e->e_from.q_flags))
                ctladdr = &e->e_from;
 
            bitset(QGOODUID, e->e_from.q_flags))
                ctladdr = &e->e_from;
 
@@ -1033,7 +1035,7 @@ deliver(e, firstto)
        SmtpPhase = NULL;
        mci = NULL;
 
        SmtpPhase = NULL;
        mci = NULL;
 
-#ifdef XDEBUG
+#if XDEBUG
        {
                char wbuf[MAXLINE];
 
        {
                char wbuf[MAXLINE];
 
@@ -1095,7 +1097,18 @@ deliver(e, firstto)
                        goto give_up;
                }
                if (pv[2] != NULL)
                        goto give_up;
                }
                if (pv[2] != NULL)
-                       port = atoi(pv[2]);
+               {
+                       port = htons(atoi(pv[2]));
+                       if (port == 0)
+                       {
+                               struct servent *sp = getservbyname(pv[2], "tcp");
+
+                               if (sp == NULL)
+                                       syserr("Service %s unknown", pv[2]);
+                               else
+                                       port = sp->s_port;
+                       }
+               }
 tryhost:
                while (*curhost != '\0')
                {
 tryhost:
                while (*curhost != '\0')
                {
@@ -1262,9 +1275,7 @@ tryhost:
                {
                        int i;
                        int saveerrno;
                {
                        int i;
                        int saveerrno;
-                       char **ep;
-                       char *env[MAXUSERENVIRON];
-                       extern char **environ;
+                       struct stat stb;
                        extern int DtableSize;
 
                        if (e->e_lockfp != NULL)
                        extern int DtableSize;
 
                        if (e->e_lockfp != NULL)
@@ -1275,23 +1286,24 @@ tryhost:
                        (void) setsignal(SIGHUP, SIG_IGN);
                        (void) setsignal(SIGTERM, SIG_DFL);
 
                        (void) setsignal(SIGHUP, SIG_IGN);
                        (void) setsignal(SIGTERM, SIG_DFL);
 
+                       if (m != FileMailer || stat(tochain->q_user, &stb) < 0)
+                               stb.st_mode = 0;
+
                        /* tweak niceness */
                        if (m->m_nice != 0)
                                nice(m->m_nice);
 
                        /* tweak niceness */
                        if (m->m_nice != 0)
                                nice(m->m_nice);
 
-                       /* reset user and group */
+                       /* reset group id */
                        if (bitnset(M_SPECIFIC_UID, m->m_flags))
                        if (bitnset(M_SPECIFIC_UID, m->m_flags))
-                       {
                                (void) setgid(m->m_gid);
                                (void) setgid(m->m_gid);
-                               (void) setuid(m->m_uid);
-                       }
-                       else if (ctladdr != NULL && ctladdr->q_uid != 0)
+                       else if (bitset(S_ISGID, stb.st_mode))
+                               (void) setgid(stb.st_gid);
+                       else if (ctladdr != NULL && ctladdr->q_gid != 0)
                        {
                                (void) initgroups(ctladdr->q_ruser?
                                        ctladdr->q_ruser: ctladdr->q_user,
                                        ctladdr->q_gid);
                                (void) setgid(ctladdr->q_gid);
                        {
                                (void) initgroups(ctladdr->q_ruser?
                                        ctladdr->q_ruser: ctladdr->q_user,
                                        ctladdr->q_gid);
                                (void) setgid(ctladdr->q_gid);
-                               (void) setuid(ctladdr->q_uid);
                        }
                        else
                        {
                        }
                        else
                        {
@@ -1300,6 +1312,17 @@ tryhost:
                                        (void) setgid(DefGid);
                                else
                                        (void) setgid(m->m_gid);
                                        (void) setgid(DefGid);
                                else
                                        (void) setgid(m->m_gid);
+                       }
+
+                       /* reset user id */
+                       if (bitnset(M_SPECIFIC_UID, m->m_flags))
+                               (void) setuid(m->m_uid);
+                       else if (bitset(S_ISUID, stb.st_mode))
+                               (void) setuid(stb.st_uid);
+                       else if (ctladdr != NULL && ctladdr->q_uid != 0)
+                               (void) setuid(ctladdr->q_uid);
+                       else
+                       {
                                if (m->m_uid == 0)
                                        (void) setuid(DefUid);
                                else
                                if (m->m_uid == 0)
                                        (void) setuid(DefUid);
                                else
@@ -1382,31 +1405,11 @@ tryhost:
                                        (void) fcntl(i, F_SETFD, j | 1);
                        }
 
                                        (void) fcntl(i, F_SETFD, j | 1);
                        }
 
-                       /*
-                       **  Set up the mailer environment
-                       **      _FORCE_MAIL_LOCAL_ is DG-UX equiv of -d flag.
-                       **      TZ is timezone information.
-                       **      SYSTYPE is Apollo software sys type (required).
-                       **      ISP is Apollo hardware system type (required).
-                       */
-
-                       i = 0;
-                       env[i++] = "AGENT=sendmail";
-                       env[i++] = "_FORCE_MAIL_LOCAL_=yes";
-                       for (ep = environ; *ep != NULL; ep++)
-                       {
-                               if (strncmp(*ep, "TZ=", 3) == 0 ||
-                                   strncmp(*ep, "ISP=", 4) == 0 ||
-                                   strncmp(*ep, "SYSTYPE=", 8) == 0)
-                                       env[i++] = *ep;
-                       }
-                       env[i] = NULL;
-
                        /* run disconnected from terminal */
                        (void) setsid();
 
                        /* try to execute the mailer */
                        /* run disconnected from terminal */
                        (void) setsid();
 
                        /* try to execute the mailer */
-                       execve(m->m_mailer, (ARGV_T) pv, (ARGV_T) env);
+                       execve(m->m_mailer, (ARGV_T) pv, (ARGV_T) UserEnviron);
                        saveerrno = errno;
                        syserr("Cannot exec %s", m->m_mailer);
                        if (bitnset(M_LOCALMAILER, m->m_flags) ||
                        saveerrno = errno;
                        syserr("Cannot exec %s", m->m_mailer);
                        if (bitnset(M_LOCALMAILER, m->m_flags) ||
@@ -1634,7 +1637,7 @@ tryhost:
        **  Restore state and return.
        */
 
        **  Restore state and return.
        */
 
-#ifdef XDEBUG
+#if XDEBUG
        {
                char wbuf[MAXLINE];
 
        {
                char wbuf[MAXLINE];
 
@@ -1668,6 +1671,7 @@ tryhost:
 **                     the message will be queued, as appropriate.
 */
 
 **                     the message will be queued, as appropriate.
 */
 
+void
 markfailure(e, q, mci, rcode)
        register ENVELOPE *e;
        register ADDRESS *q;
 markfailure(e, q, mci, rcode)
        register ENVELOPE *e;
        register ADDRESS *q;
@@ -1776,6 +1780,7 @@ markfailure(e, q, mci, rcode)
 **             none.
 */
 
 **             none.
 */
 
+int
 endmailer(mci, e, pv)
        register MCI *mci;
        register ENVELOPE *e;
 endmailer(mci, e, pv)
        register MCI *mci;
        register ENVELOPE *e;
@@ -1851,6 +1856,7 @@ endmailer(mci, e, pv)
 **             ExitStat may be set.
 */
 
 **             ExitStat may be set.
 */
 
+void
 giveresponse(stat, m, mci, ctladdr, xstart, e)
        int stat;
        register MAILER *m;
 giveresponse(stat, m, mci, ctladdr, xstart, e)
        int stat;
        register MAILER *m;
@@ -2002,10 +2008,11 @@ giveresponse(stat, m, mci, ctladdr, xstart, e)
 **             none
 */
 
 **             none
 */
 
+void
 logdelivery(m, mci, stat, ctladdr, xstart, e)
        MAILER *m;
        register MCI *mci;
 logdelivery(m, mci, stat, ctladdr, xstart, e)
        MAILER *m;
        register MCI *mci;
-       char *stat;
+       const char *stat;
        ADDRESS *ctladdr;
        time_t xstart;
        register ENVELOPE *e;
        ADDRESS *ctladdr;
        time_t xstart;
        register ENVELOPE *e;
@@ -2210,6 +2217,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
 **             outputs some text to fp.
 */
 
 **             outputs some text to fp.
 */
 
+void
 putfromline(mci, e)
        register MCI *mci;
        ENVELOPE *e;
 putfromline(mci, e)
        register MCI *mci;
        ENVELOPE *e;
@@ -2221,7 +2229,6 @@ putfromline(mci, e)
        if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
                return;
 
        if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
                return;
 
-# ifdef UGLYUUCP
        if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags))
        {
                char *bang;
        if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags))
        {
                char *bang;
@@ -2241,7 +2248,6 @@ putfromline(mci, e)
                        template = xbuf;
                }
        }
                        template = xbuf;
                }
        }
-# endif /* UGLYUUCP */
        expand(template, buf, sizeof buf, e);
        putxline(buf, mci, PXLF_NOTHINGSPECIAL);
 }
        expand(template, buf, sizeof buf, e);
        putxline(buf, mci, PXLF_NOTHINGSPECIAL);
 }
@@ -2266,6 +2272,7 @@ putfromline(mci, e)
 #define OS_CR          1       /* read a carriage return */
 #define OS_INLINE      2       /* putting rest of line */
 
 #define OS_CR          1       /* read a carriage return */
 #define OS_INLINE      2       /* putting rest of line */
 
+void
 putbody(mci, e, separator)
        register MCI *mci;
        register ENVELOPE *e;
 putbody(mci, e, separator)
        register MCI *mci;
        register ENVELOPE *e;
@@ -2310,6 +2317,7 @@ putbody(mci, e, separator)
        }
        rewind(e->e_dfp);
 
        }
        rewind(e->e_dfp);
 
+#if MIME8TO7
        if (bitset(MCIF_CVT8TO7, mci->mci_flags))
        {
                char *boundaries[MAXMIMENESTING + 1];
        if (bitset(MCIF_CVT8TO7, mci->mci_flags))
        {
                char *boundaries[MAXMIMENESTING + 1];
@@ -2334,6 +2342,7 @@ putbody(mci, e, separator)
                mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER);
        }
        else
                mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER);
        }
        else
+#endif
        {
                int ostate;
                register char *bp;
        {
                int ostate;
                register char *bp;
@@ -2536,6 +2545,8 @@ endofmessage:
 **             filename -- the name of the file to send to.
 **             ctladdr -- the controlling address header -- includes
 **                     the userid/groupid to be when sending.
 **             filename -- the name of the file to send to.
 **             ctladdr -- the controlling address header -- includes
 **                     the userid/groupid to be when sending.
+**             sfflags -- flags for opening.
+**             e -- the current envelope.
 **
 **     Returns:
 **             The exit code associated with the operation.
 **
 **     Returns:
 **             The exit code associated with the operation.
@@ -2544,9 +2555,11 @@ endofmessage:
 **             none.
 */
 
 **             none.
 */
 
-mailfile(filename, ctladdr, e)
+int
+mailfile(filename, ctladdr, sfflags, e)
        char *filename;
        ADDRESS *ctladdr;
        char *filename;
        ADDRESS *ctladdr;
+       int sfflags;
        register ENVELOPE *e;
 {
        register FILE *f;
        register ENVELOPE *e;
 {
        register FILE *f;
@@ -2588,6 +2601,8 @@ mailfile(filename, ctladdr, e)
                (void) setsignal(SIGHUP, SIG_DFL);
                (void) setsignal(SIGTERM, SIG_DFL);
                (void) umask(OldUmask);
                (void) setsignal(SIGHUP, SIG_DFL);
                (void) setsignal(SIGTERM, SIG_DFL);
                (void) umask(OldUmask);
+               e->e_to = filename;
+               ExitStat = EX_OK;
 
 #ifdef HASLSTAT
                if ((SafeFileEnv != NULL ? lstat(filename, &stb)
 
 #ifdef HASLSTAT
                if ((SafeFileEnv != NULL ? lstat(filename, &stb)
@@ -2609,7 +2624,7 @@ mailfile(filename, ctladdr, e)
                errno = 0;
                ExitStat = EX_OK;
 
                errno = 0;
                ExitStat = EX_OK;
 
-               if (ctladdr != NULL)
+               if (ctladdr != NULL || bitset(SFF_RUNASREALUID, sfflags))
                {
                        /* ignore setuid and setgid bits */
                        mode &= ~(S_ISGID|S_ISUID);
                {
                        /* ignore setuid and setgid bits */
                        mode &= ~(S_ISGID|S_ISUID);
@@ -2645,44 +2660,68 @@ mailfile(filename, ctladdr, e)
                if (chdir("/") < 0)
                        syserr("mailfile: cannot chdir(/)");
 
                if (chdir("/") < 0)
                        syserr("mailfile: cannot chdir(/)");
 
-               if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0)
+               /* select a new user to run as */
+               if (!bitset(SFF_RUNASREALUID, sfflags))
                {
                {
-                       if (ctladdr != NULL && ctladdr->q_uid != 0)
-                               (void) initgroups(ctladdr->q_ruser ?
-                                       ctladdr->q_ruser : ctladdr->q_user,
-                                       ctladdr->q_gid);
+                       if (bitset(S_ISUID, mode))
+                       {
+                               RealUserName = NULL;
+                               RealUid = stb.st_uid;
+                       }
+                       else if (ctladdr != NULL && ctladdr->q_uid != 0)
+                       {
+                               if (ctladdr->q_ruser != NULL)
+                                       RealUserName = ctladdr->q_ruser;
+                               else
+                                       RealUserName = ctladdr->q_user;
+                               RealUid = ctladdr->q_uid;
+                       }
+                       else if (FileMailer != NULL && FileMailer->m_uid != 0)
+                       {
+                               RealUserName = DefUser;
+                               RealUid = FileMailer->m_uid;
+                       }
+                       else
+                       {
+                               RealUserName = DefUser;
+                               RealUid = DefUid;
+                       }
+
+                       /* select a new group to run as */
+                       if (bitset(S_ISGID, mode))
+                               RealGid = stb.st_gid;
+                       else if (ctladdr != NULL && ctladdr->q_uid != 0)
+                               RealGid = ctladdr->q_gid;
                        else if (FileMailer != NULL && FileMailer->m_gid != 0)
                        else if (FileMailer != NULL && FileMailer->m_gid != 0)
-                               (void) initgroups(DefUser, FileMailer->m_gid);
+                               RealGid = FileMailer->m_gid;
                        else
                        else
-                               (void) initgroups(DefUser, DefGid);
+                               RealGid = DefGid;
                }
                }
-               if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0)
+
+               /* last ditch */
+               if (!bitset(SFF_ROOTOK, sfflags))
                {
                {
-                       if (ctladdr != NULL && ctladdr->q_uid != 0)
-                               (void) setuid(ctladdr->q_uid);
-                       else if (FileMailer != NULL && FileMailer->m_uid != 0)
-                               (void) setuid(FileMailer->m_uid);
-                       else
-                               (void) setuid(DefUid);
+                       if (RealUid == 0)
+                               RealUid = DefUid;
+                       if (RealGid == 0)
+                               RealGid = DefGid;
                }
                }
-               FileName = filename;
-               LineNumber = 0;
-               f = dfopen(filename, oflags, FileMode);
+
+               /* now set the group and user ids */
+               if (RealUserName != NULL)
+                       (void) initgroups(RealUserName, RealGid);
+               else
+                       (void) setgid(RealGid);
+               (void) setuid(RealUid);
+
+               sfflags |= SFF_NOPATHCHECK;
+               sfflags &= ~SFF_OPENASROOT;
+               f = safefopen(filename, oflags, FileMode, sfflags);
                if (f == NULL)
                {
                        message("554 cannot open: %s", errstring(errno));
                        exit(EX_CANTCREAT);
                }
                if (f == NULL)
                {
                        message("554 cannot open: %s", errstring(errno));
                        exit(EX_CANTCREAT);
                }
-               if (fstat(fileno(f), &fsb) < 0 ||
-                   (!bitset(O_CREAT, oflags) &&
-                    (stb.st_nlink != fsb.st_nlink ||
-                     stb.st_dev != fsb.st_dev ||
-                     stb.st_ino != fsb.st_ino ||
-                     stb.st_uid != fsb.st_uid)))
-               {
-                       message("554 cannot write: file changed after open");
-                       exit(EX_CANTCREAT);
-               }
 
                bzero(&mcibuf, sizeof mcibuf);
                mcibuf.mci_mailer = FileMailer;
 
                bzero(&mcibuf, sizeof mcibuf);
                mcibuf.mci_mailer = FileMailer;