4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.sbin / sendmail / src / recipient.c
index 832c870..39f6938 100644 (file)
@@ -7,14 +7,11 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)recipient.c        6.16 (Berkeley) %G%";
+static char sccsid[] = "@(#)recipient.c        8.1 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <pwd.h>
 # include "sendmail.h"
 # include "sendmail.h"
+# include <pwd.h>
 
 /*
 **  SENDTOLIST -- Designate a send list.
 
 /*
 **  SENDTOLIST -- Designate a send list.
@@ -36,6 +33,7 @@ static char sccsid[] = "@(#)recipient.c       6.16 (Berkeley) %G%";
 **                     expansion.
 **             sendq -- a pointer to the head of a queue to put
 **                     these people into.
 **                     expansion.
 **             sendq -- a pointer to the head of a queue to put
 **                     these people into.
+**             e -- the envelope in which to add these recipients.
 **             qflags -- special flags to set in the q_flags field.
 **
 **     Returns:
 **             qflags -- special flags to set in the q_flags field.
 **
 **     Returns:
@@ -84,14 +82,14 @@ sendto(list, copyf, ctladdr, qflags)
 
        for (p = list; *p != '\0'; )
        {
 
        for (p = list; *p != '\0'; )
        {
+               auto char *delimptr;
                register ADDRESS *a;
                register ADDRESS *a;
-               extern char *DelimChar;         /* defined in prescan */
 
                /* parse the address */
                while ((isascii(*p) && isspace(*p)) || *p == ',')
                        p++;
 
                /* parse the address */
                while ((isascii(*p) && isspace(*p)) || *p == ',')
                        p++;
-               a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, e);
-               p = DelimChar;
+               a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, &delimptr, e);
+               p = delimptr;
                if (a == NULL)
                        continue;
                a->q_next = al;
                if (a == NULL)
                        continue;
                a->q_next = al;
@@ -119,7 +117,6 @@ sendto(list, copyf, ctladdr, qflags)
        {
                register ADDRESS *a = al;
                extern ADDRESS *recipient();
        {
                register ADDRESS *a = al;
                extern ADDRESS *recipient();
-               extern ADDRESS *recipient();
 
                al = a->q_next;
                sibl = recipient(a);
 
                al = a->q_next;
                sibl = recipient(a);
@@ -199,8 +196,6 @@ addrref(a, r)
 **             none.
 */
 
 **             none.
 */
 
-extern ADDRESS *getctladdr();
-
 ADDRESS *
 ADDRESS *
 recipient(a, sendq, e)
 ADDRESS *
 ADDRESS *
 recipient(a, sendq, e)
@@ -215,7 +210,7 @@ recipient(a, sendq, e)
        bool quoted = FALSE;            /* set if the addr has a quote bit */
        int findusercount = 0;
        char buf[MAXNAME];              /* unquoted image of the user name */
        bool quoted = FALSE;            /* set if the addr has a quote bit */
        int findusercount = 0;
        char buf[MAXNAME];              /* unquoted image of the user name */
-       extern bool safefile();
+       extern int safefile();
 
        e->e_to = a->q_paddr;
        m = a->q_mailer;
 
        e->e_to = a->q_paddr;
        m = a->q_mailer;
@@ -238,11 +233,7 @@ recipient(a, sendq, e)
        */
 
        /* set the queue timeout */
        */
 
        /* set the queue timeout */
-       a->q_timeout = TimeOut;
-
-       /* map user & host to lower case if requested on non-aliases */
-       if (a->q_alias == NULL)
-               loweraddr(a);
+       a->q_timeout = TimeOuts.to_q_return;
 
        /* get unquoted user for file, program or user.name check */
        (void) strcpy(buf, a->q_user);
 
        /* get unquoted user for file, program or user.name check */
        (void) strcpy(buf, a->q_user);
@@ -254,9 +245,10 @@ recipient(a, sendq, e)
        stripquotes(buf);
 
        /* check for direct mailing to restricted mailers */
        stripquotes(buf);
 
        /* check for direct mailing to restricted mailers */
-       if (a->q_alias == NULL && m == ProgMailer)
+       if (a->q_alias == NULL && m == ProgMailer &&
+           !bitset(EF_QUEUERUN, e->e_flags))
        {
        {
-               a->q_flags |= QDONTSEND|QBADADDR;
+               a->q_flags |= QBADADDR;
                usrerr("550 Cannot mail directly to programs", m->m_name);
        }
 
                usrerr("550 Cannot mail directly to programs", m->m_name);
        }
 
@@ -271,8 +263,12 @@ recipient(a, sendq, e)
 
        for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
        {
 
        for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
        {
-               if (!ForceMail && sameaddr(q, a))
+               if (sameaddr(q, a))
                {
                {
+                       /* if this is a reinsertion, just go ahead */
+                       if (bitset(QVERIFIED, q->q_flags))
+                               break;
+
                        if (tTd(26, 1))
                        {
                                printf("%s in sendq: ", a->q_paddr);
                        if (tTd(26, 1))
                        {
                                printf("%s in sendq: ", a->q_paddr);
@@ -291,8 +287,13 @@ recipient(a, sendq, e)
        }
 
        /* add address on list */
        }
 
        /* add address on list */
-       *pq = a;
-       a->q_next = NULL;
+       if (*pq != a)
+       {
+               *pq = a;
+               a->q_next = NULL;
+       }
+
+       a->q_flags &= ~QVERIFIED;
 
        /*
        **  Alias the name and handle special mailer types.
 
        /*
        **  Alias the name and handle special mailer types.
@@ -302,21 +303,40 @@ recipient(a, sendq, e)
        if (tTd(29, 7))
                printf("at trylocaluser %s\n", a->q_user);
 
        if (tTd(29, 7))
                printf("at trylocaluser %s\n", a->q_user);
 
-       if (bitset(QDONTSEND, a->q_flags))
+       if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
                return (a);
 
        if (m == InclMailer)
        {
                a->q_flags |= QDONTSEND;
                return (a);
 
        if (m == InclMailer)
        {
                a->q_flags |= QDONTSEND;
-               if (a->q_alias == NULL)
+               if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
                {
                        a->q_flags |= QBADADDR;
                        usrerr("550 Cannot mail directly to :include:s");
                }
                else
                {
                {
                        a->q_flags |= QBADADDR;
                        usrerr("550 Cannot mail directly to :include:s");
                }
                else
                {
+                       int ret;
+
                        message("including file %s", a->q_user);
                        message("including file %s", a->q_user);
-                       (void) include(a->q_user, FALSE, a, sendq, e);
+                       ret = include(a->q_user, FALSE, a, sendq, e);
+                       if (transienterror(ret))
+                       {
+#ifdef LOG
+                               if (LogLevel > 2)
+                                       syslog(LOG_ERR, "%s: include %s: transient error: %e",
+                                               e->e_id, a->q_user, errstring(ret));
+#endif
+                               a->q_flags |= QQUEUEUP|QDONTSEND;
+                               usrerr("451 Cannot open %s: %s",
+                                       a->q_user, errstring(ret));
+                       }
+                       else if (ret != 0)
+                       {
+                               usrerr("550 Cannot open %s: %s",
+                                       a->q_user, errstring(ret));
+                               a->q_flags |= QBADADDR;
+                       }
                }
        }
        else if (m == FileMailer)
                }
        }
        else if (m == FileMailer)
@@ -326,16 +346,16 @@ recipient(a, sendq, e)
 
                p = strrchr(buf, '/');
                /* check if writable or creatable */
 
                p = strrchr(buf, '/');
                /* check if writable or creatable */
-               if (a->q_alias == NULL && !QueueRun)
+               if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
                {
                {
-                       a->q_flags |= QDONTSEND|QBADADDR;
+                       a->q_flags |= QBADADDR;
                        usrerr("550 Cannot mail directly to files");
                }
                else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
                        usrerr("550 Cannot mail directly to files");
                }
                else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
-                   (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC)))
+                   (*p = '\0', safefile(buf, getruid(), S_IWRITE|S_IEXEC) != 0))
                {
                        a->q_flags |= QBADADDR;
                {
                        a->q_flags |= QBADADDR;
-                       giveresponse(EX_CANTCREAT, m, e);
+                       giveresponse(EX_CANTCREAT, m, NULL, e);
                }
        }
 
                }
        }
 
@@ -351,21 +371,23 @@ recipient(a, sendq, e)
 
 # ifdef USERDB
        /* if not aliased, look it up in the user database */
 
 # ifdef USERDB
        /* if not aliased, look it up in the user database */
-       if (!bitset(QDONTSEND|QNOTREMOTE, a->q_flags))
+       if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags))
        {
                extern int udbexpand();
        {
                extern int udbexpand();
+               extern int errno;
 
                if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
                {
 
                if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
                {
-                       a->q_flags |= QQUEUEUP;
+                       a->q_flags |= QQUEUEUP|QDONTSEND;
                        if (e->e_message == NULL)
                                e->e_message = newstr("Deferred: user database error");
 # ifdef LOG
                        if (LogLevel > 8)
                        if (e->e_message == NULL)
                                e->e_message = newstr("Deferred: user database error");
 # ifdef LOG
                        if (LogLevel > 8)
-                               syslog(LOG_INFO, "%s: deferred: udbexpand",
-                                       e->e_id);
+                               syslog(LOG_INFO, "%s: deferred: udbexpand: %s",
+                                       e->e_id, errstring(errno));
 # endif
 # endif
-                       message("queued (user database error)");
+                       message("queued (user database error): %s",
+                               errstring(errno));
                        e->e_nrcpts++;
                        return (a);
                }
                        e->e_nrcpts++;
                        return (a);
                }
@@ -373,7 +395,7 @@ recipient(a, sendq, e)
 # endif
 
        /* if it was an alias or a UDB expansion, just return now */
 # endif
 
        /* if it was an alias or a UDB expansion, just return now */
-       if (bitset(QDONTSEND, a->q_flags))
+       if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))
                return (a);
 
        /*
                return (a);
 
        /*
@@ -400,7 +422,7 @@ recipient(a, sendq, e)
        **  and deliver it.
        */
 
        **  and deliver it.
        */
 
-       if (!bitset(QDONTSEND, a->q_flags))
+       if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags))
        {
                auto bool fuzzy;
                register struct passwd *pw;
        {
                auto bool fuzzy;
                register struct passwd *pw;
@@ -411,7 +433,7 @@ recipient(a, sendq, e)
                if (pw == NULL)
                {
                        a->q_flags |= QBADADDR;
                if (pw == NULL)
                {
                        a->q_flags |= QBADADDR;
-                       giveresponse(EX_NOUSER, m, e);
+                       giveresponse(EX_NOUSER, m, NULL, e);
                }
                else
                {
                }
                else
                {
@@ -423,6 +445,7 @@ recipient(a, sendq, e)
                                a->q_user = newstr(pw->pw_name);
                                if (findusercount++ > 3)
                                {
                                a->q_user = newstr(pw->pw_name);
                                if (findusercount++ > 3)
                                {
+                                       a->q_flags |= QBADADDR;
                                        usrerr("554 aliasing/forwarding loop for %s broken",
                                                pw->pw_name);
                                        return (a);
                                        usrerr("554 aliasing/forwarding loop for %s broken",
                                                pw->pw_name);
                                        return (a);
@@ -435,6 +458,7 @@ recipient(a, sendq, e)
                        a->q_home = newstr(pw->pw_dir);
                        a->q_uid = pw->pw_uid;
                        a->q_gid = pw->pw_gid;
                        a->q_home = newstr(pw->pw_dir);
                        a->q_uid = pw->pw_uid;
                        a->q_gid = pw->pw_gid;
+                       a->q_ruser = newstr(pw->pw_name);
                        a->q_flags |= QGOODUID;
                        buildfname(pw->pw_gecos, pw->pw_name, nbuf);
                        if (nbuf[0] != '\0')
                        a->q_flags |= QGOODUID;
                        buildfname(pw->pw_gecos, pw->pw_name, nbuf);
                        if (nbuf[0] != '\0')
@@ -485,12 +509,6 @@ finduser(name, fuzzyp)
        if (tTd(29, 4))
                printf("finduser(%s): ", name);
 
        if (tTd(29, 4))
                printf("finduser(%s): ", name);
 
-       /* map upper => lower case */
-       for (p = name; *p != '\0'; p++)
-       {
-               if (isascii(*p) && isupper(*p))
-                       *p = tolower(*p);
-       }
        *fuzzyp = FALSE;
 
        /* look up this login name using fast path */
        *fuzzyp = FALSE;
 
        /* look up this login name using fast path */
@@ -531,9 +549,12 @@ finduser(name, fuzzyp)
                        return (pw);
                }
        }
                        return (pw);
                }
        }
-#endif
        if (tTd(29, 4))
                printf("no fuzzy match found\n");
        if (tTd(29, 4))
                printf("no fuzzy match found\n");
+#else
+       if (tTd(29, 4))
+               printf("not found (fuzzy disabled)\n");
+#endif
        return (NULL);
 }
 \f/*
        return (NULL);
 }
 \f/*
@@ -626,6 +647,7 @@ include(fname, forwarding, ctladdr, sendq, e)
        int oldlinenumber = LineNumber;
        register EVENT *ev = NULL;
        int nincludes;
        int oldlinenumber = LineNumber;
        register EVENT *ev = NULL;
        int nincludes;
+       int ret;
        char buf[MAXLINE];
        static int includetimeout();
 
        char buf[MAXLINE];
        static int includetimeout();
 
@@ -647,13 +669,14 @@ include(fname, forwarding, ctladdr, sendq, e)
        ev = setevent((time_t) 60, includetimeout, 0);
 
        /* if forwarding, the input file must be marked safe */
        ev = setevent((time_t) 60, includetimeout, 0);
 
        /* if forwarding, the input file must be marked safe */
-       if (forwarding && !safefile(fname, ctladdr->q_uid, S_IREAD))
+       if (forwarding && (ret = safefile(fname, ctladdr->q_uid, S_IREAD)) != 0)
        {
                /* don't use this .forward file */
                clrevent(ev);
                if (tTd(27, 4))
        {
                /* don't use this .forward file */
                clrevent(ev);
                if (tTd(27, 4))
-                       printf("include: not safe (uid=%d)\n", ctladdr->q_uid);
-               return EPERM;
+                       printf("include: not safe (uid=%d): %s\n",
+                               ctladdr->q_uid, errstring(ret));
+               return ret;
        }
 
        fp = fopen(fname, "r");
        }
 
        fp = fopen(fname, "r");
@@ -662,7 +685,6 @@ include(fname, forwarding, ctladdr, sendq, e)
                int ret = errno;
 
                clrevent(ev);
                int ret = errno;
 
                clrevent(ev);
-               usrerr("550 Cannot open %s", fname);
                return ret;
        }
 
                return ret;
        }
 
@@ -688,7 +710,9 @@ include(fname, forwarding, ctladdr, sendq, e)
        if (bitset(EF_VRFYONLY, e->e_flags))
        {
                /* don't do any more now */
        if (bitset(EF_VRFYONLY, e->e_flags))
        {
                /* don't do any more now */
-               fclose(fp);
+               ctladdr->q_flags |= QVERIFIED;
+               e->e_nrcpts++;
+               xfclose(fp, "include", fname);
                return 0;
        }
 
                return 0;
        }
 
@@ -729,7 +753,7 @@ include(fname, forwarding, ctladdr, sendq, e)
                ctladdr->q_flags |= QDONTSEND;
        }
 
                ctladdr->q_flags |= QDONTSEND;
        }
 
-       (void) fclose(fp);
+       (void) xfclose(fp, "include", fname);
        FileName = oldfilename;
        LineNumber = oldlinenumber;
        return 0;
        FileName = oldfilename;
        LineNumber = oldlinenumber;
        return 0;
@@ -745,6 +769,7 @@ includetimeout()
 **
 **     Parameters:
 **             argv -- argument vector to send to.
 **
 **     Parameters:
 **             argv -- argument vector to send to.
+**             e -- the current envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -762,21 +787,6 @@ sendtoargv(argv, e)
 
        while ((p = *argv++) != NULL)
        {
 
        while ((p = *argv++) != NULL)
        {
-               if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at"))
-               {
-                       char nbuf[MAXNAME];
-
-                       if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
-                               usrerr("554 address overflow");
-                       else
-                       {
-                               (void) strcpy(nbuf, p);
-                               (void) strcat(nbuf, "@");
-                               (void) strcat(nbuf, argv[1]);
-                               p = newstr(nbuf);
-                               argv += 2;
-                       }
-               }
                sendto(p, 0, (ADDRESS *) NULL, 0);
        }
 }
                sendto(p, 0, (ADDRESS *) NULL, 0);
        }
 }