ShellBanner
System:Linux MiraNet 3.0.0-14-generic-pae #23-Ubuntu SMP Mon Nov 21 22:07:10 UTC 2011 i686
Software:Apache. PHP/5.3.6-13ubuntu3.10
ID:uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
Safe Mode:OFF
Open_Basedir:OFF
Freespace:24.65 GB of 70.42 GB (35.01%)
MySQL: ON MSSQL: OFF Oracle: OFF PostgreSQL: OFF Curl: OFF Sockets: ON Fetch: OFF Wget: ON Perl: ON
Disabled Functions: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

/ usr/ src/ courier-0.66.1/ courier/ - drwxrwxrwx

Directory:
Viewing file:     submit.C (51 KB)      -rw-rw-rw-
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 1998 - 2010 Double Precision, Inc.
** See COPYING for distribution information.
*/

#include    "courier.h"
#include    "localstatedir.h"
#include    "rw.h"
#include    "comcargs.h"
#include    "comtrack.h"
#include    "rfc822/rfc822.h"
#include    "rfc822/rfc2047.h"
#include    "rfc2045/rfc2045charset.h"
#include    "rfc1035/rfc1035.h"
#include    "rfc1035/rfc1035mxlist.h"
#include    "rfc1035/spf.h"
#include    "numlib/numlib.h"
#include    "dbobj.h"
#include    "afx.h"
#include    "aliases.h"
#include    "submit.h"
#include    "maxlongsize.h"
#include    "bofh.h"
#include    <string.h>
#include    <cstdlib>
#include    <ctype.h>
#include    <errno.h>
#include    <utime.h>
#include    <iostream>
#if    HAVE_LOCALE_H
#include    <locale.h>
#endif
#if    HAVE_SYS_TYPES_H
#include    <sys/types.h>
#endif
#if    HAVE_SYS_STAT_H
#include    <sys/stat.h>
#endif
#if    HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    <fcntl.h>
#include    <time.h>
#include    <poll.h>

#include    <algorithm>
#include    <functional>

#include    <ctype.h>

static time_t alarm_timeout;


time_t    submit_time;
static const char *expnname=0;
static const char *vrfyname=0;
static const char *receivedfrommta=0;
static const char *identinfo=0;
static const char *onlybcc=0;

const char *authname=0;

static const char *rfc3848_receivedwith=0;

const char *msgsource=0;
int suppressbackscatter=0;

const char *submitdelay=0;

static int nofilter;

int verpflag;
std::string security;
extern std::string mkmessageidheader();

static struct courier_args arginfo[]={
    {"expn", &expnname},
    {"vrfy", &vrfyname},
    {"bcc", &onlybcc},
    {"src", &msgsource},
    {"delay", &submitdelay},
    {"auth", &authname},
    {"rfc3848", &rfc3848_receivedwith},
    {0}
    } ;

// Strip off trailing periods in domain names.

static void stripdots(std::string &s)
{
    std::string::iterator b=s.begin(), e=s.end();

    while (b < e && e[-1] == '.')
        --e;

    s.erase(e, s.end());
}

static const char you_are_whitelisted[]=
    "412 You are whitelisted by this recipient, please try again later.";

static const char you_are_not_whitelisted[]=
    "412 You are not whitelisted by this recipient, please try again later.";

// A pointer to expninfo is supplied as a misc argument to the
// rewrite_address function, which passes it along to the handler of the
// rewritten address.
//
// expninfo is used by the handler function (showexpn, showvrfy, or ...)
// in order to find the original AliasSearch function to search for
// any aliases of this address.

struct expninfo {
    AliasSearch *asptr;
    int    flag;
    struct rw_transport *module;
    } ;

/////////////////////////////////////////////////////////////////////////////
//
// rewrite_address() rewrites an arbitrary address using a specified module's
// rewriting function.
//
// inaddress - address to rewrite
// module    - module whose rewrite function is used
// mode      - rewriting mode
// sender    - what to put in rw_info.sender
//
// handler   - function that will be called.  The first argument to the
//             function will be the rewritten address, the second argument
//             is the same address, but as rfc822token link list.  The third
//             argument will be an error message.  If NULL, the address was
//             rewritten succesfully.  The last argument will be the misc
//             pointer.
// misc      - miscellaneous pointer to pass to the handler function.
//
/////////////////////////////////////////////////////////////////////////////

static void rewrite_address(const char *inaddress, struct rw_transport *module,
    int mode,
    struct rfc822token *sender,
    void (*handler)(const char *inaddress,
        struct rfc822token *inaddresst, const char *errmsg, void *misc),
    void *misc)
{
struct    rw_info_rewrite    rwir;
struct    rw_info rwi;
struct    rfc822t *rfcp;
char    *address, *p, *errmsg;

    rfcp=rw_rewrite_tokenize(inaddress);

    rw_info_init(&rwi, rfcp->tokens, rw_err_func);

    rwi.mode=mode;
    rwi.sender=sender;
    rwi.udata=(void *)&rwir;
    rwir.buf=0;
    rwir.errmsg=0;

    rw_rewrite_module(module, &rwi, rw_rewrite_chksyn_print);

    address=((struct rw_info_rewrite *)rwi.udata)->buf;
    if (address)
    {
    char    *hostdomain=0;

        if ((p=strrchr(address, '@')) &&
            config_islocal(p+1, &hostdomain) && hostdomain == 0)
            locallower(address);
        if (hostdomain)    free(hostdomain);
        domainlower(address);
    }
    errmsg=((struct rw_info_rewrite *)rwi.udata)->errmsg;

    (*handler)( address, rwi.ptr, errmsg, misc);
    if (address)    free(address);
    if (errmsg)    free(errmsg);
    rfc822t_free(rfcp);
}

int checkfreespace(unsigned *availbytes)
{
static unsigned nsubmitters;
static unsigned min_inodes=0;
unsigned long checkblocks, nfreeblocks, checkinodes, nfreeinodes;
unsigned blksize;
unsigned dummy;

    if (min_inodes == 0)    // Calculate thresholds
    {
    const char *p=getenv("MAXSUBMITTERS");

        nsubmitters= p ? (unsigned)atoi(p):0;

        if (nsubmitters < 10)    nsubmitters=10;
        if (nsubmitters > 1000)    nsubmitters=1000;

        min_inodes=nsubmitters*5+100;
    }

    if (!availbytes)    availbytes= &dummy;

    *availbytes=65536;

    if (freespace( ".", &checkblocks, &nfreeblocks, &checkinodes, &nfreeinodes, &blksize))
    {
        return (0);
    }

    if (checkinodes && nfreeinodes < min_inodes)    return (-1);

    if (nfreeblocks < blksize * nsubmitters/65536 + 100)
        *availbytes=4096;
    else if (nfreeblocks < blksize * nsubmitters/4096 + 100)
        return (-1);
    return (0);

}

//////////////////////////////////////////////////////////////////////
//
// ExpnAliasHandler - subclasses AliasHandler.  The AliasHandler
// class is used by the AliasSearch class to output addresses found
// in the aliases.dat file.  AliasHandler is subclassed so that
// one alias is always buffered.  When an alias address is received,
// the previous one is printed on std::cout, as an RFC822 multiline
// response.  The final call to ExpnAliasHandler::Alias() std::flushes out
// the final address and prints it as an RFC822 final multiline
// response.
//
//////////////////////////////////////////////////////////////////////

class ExpnAliasHandler : public AliasHandler {
public:
    ExpnAliasHandler();
    ~ExpnAliasHandler();

    std::string prev_alias;
    void    Alias(const char *);
} ;

ExpnAliasHandler::ExpnAliasHandler()
{
}

ExpnAliasHandler::~ExpnAliasHandler()
{
}

void    ExpnAliasHandler::Alias(const char *p)
{
    if ( prev_alias.size() > 0)
        std::cout << "250" << ( p ? '-':' ') <<
            "<" << prev_alias << ">" << std::endl << std::flush;

    if (p)
        prev_alias=p;
}

////////////////////////////////////////////////////////////////////////////
//
// showexpn - expand aliases.  After rewriting an address, expand any aliases.
//
////////////////////////////////////////////////////////////////////////////

static void showexpn(const char *address, struct rfc822token *addresst,
    const char *errmsg, void *misc)
{
struct    expninfo *info = (struct expninfo *)misc;

    addresst=addresst;

    if (errmsg)
    {
        std::cout << errmsg << std::flush;
        info->flag=1;
        return;
    }

    ExpnAliasHandler expnh;
    int rc;

    rc=info->asptr->Search(address, expnh);

    if (rc < 0)
        std::cout << "400 <" << address <<
            "> - service temporarily unavailable."
             << std::endl << std::flush;
    else if (rc)
        std::cout << "500 <" << address << "> not found." << std::endl << std::flush;
                // No aliases
    else
        expnh.Alias(0);
                // Print last alias
    info->flag=0;
}

/////////////////////////////////////////////////////////////////////////////
//
// VRFY
//
// A pointer to rw_info_vrfy is passed to rw_searchdel as a misc pointer.
// The found_transport function is called when an output module is found
// for the address.  found_transport() saves the delivery information in
// the rw_info_vrfy structure
//
/////////////////////////////////////////////////////////////////////////////

struct rw_info_vrfy {
    struct rw_info_rewrite rwr;
    struct    rw_transport *module;
    char    *host;
    char    *addr;
    } ;

static void found_transport(struct rw_info *rwi,
        struct rw_transport *t,
        const struct rfc822token *host,
        const struct rfc822token *addr)
{
struct rw_info_vrfy *p=(struct rw_info_vrfy *)rwi->udata;

    p->module=t;
    if (!(p->host=rfc822_gettok(host)) ||
        !(p->addr=rfc822_gettok(addr)))
        clog_msg_errno();
}

static void showvrfy(const char *address, struct rfc822token *addresst,
    const char *errmsg, void *misc)
{
struct    expninfo *info = (struct expninfo *)misc;

    addresst=addresst;

    if (!address)
    {
        std::cout << errmsg << std::flush;
        info->flag=1;
        return;
    }

    // If there's an alias defined for this one, presume that this is
    // a good address.

    if (info->asptr->Found(address))
    {
        std::cout << "250 <" << address << ">" << std::endl << std::flush;
        return;
    }

    // Attempt to find an output module for this address.

struct    rfc822t *rfcp=rw_rewrite_tokenize(address);
struct    rw_info_vrfy riv;

    riv.rwr.buf=0;
    riv.rwr.errmsg=0;
    riv.module=0;
    riv.host=0;
    riv.addr=0;

struct    rw_info    rwi;

    rw_info_init(&rwi, rfcp->tokens, rw_err_func);
    rwi.udata= (void *)&riv;
    rwi.mode=RW_VERIFY;
    rw_searchdel(&rwi, &found_transport);
    rfc822t_free(rfcp);

    if (!riv.module && !riv.rwr.errmsg)
        rw_err_func(511, "Undeliverable address.", &rwi);


    if (!riv.module)    // Not found.
    {
        std::cout << riv.rwr.errmsg << std::flush;
        ((struct expninfo *)misc)->flag=1;
        free(riv.rwr.errmsg);
        return;
    }
    free(riv.host);
    free(riv.addr);
    std::cout << "250 <" << address << ">" << std::endl << std::flush;
}

class Input {

    char buffer[BUFSIZ];

    char *bufptr;
    size_t bufleft;

    SubmitFile *submitfile;

    int fillbuf();

public:

    Input();
    ~Input();

    void setSubmitFile(SubmitFile &f)
    {
        submitfile= &f;
    }

    int getinputline(std::string &linebuf);
    int getinputchar();
    int unputinputchar(char c);
};

Input::Input() : bufptr(NULL), bufleft(0), submitfile(NULL)
{
}

Input::~Input()
{
}

int Input::fillbuf()
{
    struct pollfd pfd;
    int n;

    std::cout.flush();
    std::cerr.flush();

    pfd.fd=0;
    pfd.events=POLLIN | POLLHUP | POLLERR;

    while (1)
    {
        n=poll(&pfd, 1, submitfile ? 300*1000:-1);

        if (n > 0)
            break;

        if (n == 0)
        {
            if (submitfile)
            {
                std::set<std::string>::iterator
                    b=submitfile->all_files.begin(),
                    e=submitfile->all_files.end();

                while (b != e)
                {
                    utime(b->c_str(), NULL);
                    ++b;
                }
            }
            continue;
        }
        if (errno != EINTR)
            return -1;
    }

    if (!(pfd.revents & POLLIN))
        return -1;

    if ((n=read(0, buffer, sizeof(buffer))) <= 0)
        return -1;

    bufptr=buffer;
    bufleft=n;
    return 0;
}

int Input::getinputline(std::string &linebuf)
{
    linebuf.clear();

    do
    {
        size_t i;

        for (i=0; i<bufleft; i++)
        {
            if (bufptr[i] == '\n')
            {
                linebuf.append(bufptr, i);
                ++i;
                bufptr += i;
                bufleft -= i;
                return 0;
            }
        }

        linebuf.append(bufptr, bufleft);
        bufleft=0;
    } while (fillbuf() == 0);

    if (linebuf.size())
        return 0;
    return -1;
}

int Input::getinputchar()
{
    if (!bufleft && fillbuf())
        return -1;

    --bufleft;
    return (unsigned char)*bufptr++;
}

int Input::unputinputchar(char c)
{
    ++bufleft;
    *--bufptr=c;
    return (unsigned char)c;
}

static void getrcpts(struct rw_info *rwi);

struct mailfrominfo {
    AliasSearch    *asptr;
    std::string    *envid;
    char    dsnformat;
    struct    rw_transport *module;
    int    flag;
    std::string    helohost;
    std::string    *receivedspfhelo;
    std::string    *receivedspfmailfrom;
    int    mailfrom_passed_spf;

    Input        *input;
    } ;

static void mailfromerr(int msgnum, const char *errtext, struct rw_info *rwi)
{
    rwi=rwi;

char    *errmsg=makeerrmsgtext(msgnum, errtext);

    std::cout << errmsg << std::flush;
    free(errmsg);
}

static void setmsgopts(struct mailfrominfo &mfi, std::string optstring)
{
    std::string::iterator q=optstring.begin();

    while (q != optstring.end())
    {
        char ch= *q++;

        std::string opts;

        if (q != optstring.end() && *q == '{')
        {
            std::string::iterator b= ++q;

            while (q != optstring.end())
            {
                if (*q == '}')
                {
                    opts=std::string(b, q);
                    ++q;
                    break;
                }
                ++q;
            }
        }

        switch (ch) {
        case 'f':
        case 'F':
            if (mfi.dsnformat == 0)
                mfi.dsnformat='F';
            break;
        case 'h':
        case 'H':
            if (mfi.dsnformat == 0)
                mfi.dsnformat='H';
            break;
        case 'V':
            verpflag=1;
            break;
        case 's':
        case 'S':
            if (opts.size() && security.size() == 0)
                security=opts;
            break;
        }
    }
}

static int ipcmp(const char *a, const char *b)
{
    if (strncasecmp(a, "::ffff:",7) == 0)
        a += 7;
    if (strncasecmp(b, "::ffff:",7) == 0)
        b += 7;

    return strcasecmp(a, b);
}

static int checka(const char *hostname)
{
    RFC1035_ADDR *addrs;
    unsigned        naddrs, n;
    int rc=rfc1035_a(&rfc1035_default_resolver, hostname, &addrs,
             &naddrs);
    const char *tcpremoteip=getenv("TCPREMOTEIP");

    if (rc > 0)
        return 1;

    if (rc < 0)
        return -1;

    for (n=0; n<naddrs; n++)
    {
        char    buf[RFC1035_NTOABUFSIZE];

        rfc1035_ntoa(&addrs[n], buf);
        if (ipcmp(buf, tcpremoteip) == 0)
        {
            free(addrs);
            return 0;
        }
    }

    free(addrs);
    return (-1);
}

static const char *my_spf_lookup(const char *checkname,
                 const char *mailfrom,
                 const char *tcpremoteip,
                 const char *helodomain,
                 std::string *hdrOut,
                 char *errmsg_buf,
                 size_t errmsg_buf_size)
{
    static const char * const keys[]={
        "sender",
        "remoteip",
        "remotehost",
        "helo",
        "receiver"};
    const char *values[5];
    char *q;
    char result=rfc1035_spf_lookup((values[0]=mailfrom),
                       (values[1]=tcpremoteip),
                       (values[2]=getenv("TCPREMOTEHOST")),
                       (values[3]=helodomain),
                       (values[4]=config_esmtphelo()),
                       errmsg_buf,
                       errmsg_buf_size);


    const char *str;
    size_t i;

    switch (result) {
    case SPF_NONE:
        str="none";
        break;
    case SPF_NEUTRAL:
        str="neutral";
        break;
    case SPF_PASS:
        str="pass";
        break;
    case SPF_FAIL:
        str="fail";
        break;
    case SPF_SOFTFAIL:
        str="softfail";
        break;
    case SPF_ERROR:
        str="error";
        break;
    default:
        str="unknown";
    }

    (*hdrOut)="Received-SPF: ";

    for (q=errmsg_buf; *q; q++)
        if (*q < ' ' || *q >= 127)
            *q='?';

    (*hdrOut) += str;
    (*hdrOut) += " (";
    (*hdrOut) += errmsg_buf;
    (*hdrOut) += ")\n  SPF=";
    (*hdrOut) += checkname;
    (*hdrOut) += ";\n";

    for (i=0; i<sizeof(values)/sizeof(values[0]); i++)
    {
        char *v=strdup(values[i] ? values[i]:"");

        for (q=v; q && *q; q++)
            if (*q < ' ' || *q >= 127)
                *q='?';
            else if (*q == ';')
                *q=' ';
        (*hdrOut) += "  ";
        (*hdrOut) += keys[i];
        (*hdrOut) += "=";
        (*hdrOut) += v ? v:strerror(errno);
        (*hdrOut) += ";\n";
    }
    return str;
}

static std::string get_spf_errmsg(const char *bofh_var,
                  const char *result,
                  const char *errmsg_txt,
                  const char *what)
{
    std::string errmsg;

    if (!bofh_checkspf_status(bofh_var, "off", result))
    {
        const char *p=getenv("BOFHSPFNOVERBOSE");

        errmsg += bofh_checkspf("BOFHSPFHARDERROR",
                    "fail,softfail", result)
            ? "517":"417";
        errmsg += " SPF ";
        errmsg += result;
        errmsg += " ";
        errmsg += what;
        errmsg += ": ";

        if (p && atoi(p))
            errmsg += "Rejected by the Sender Policy Framework.";
        else errmsg += errmsg_txt;
    }
    return errmsg;
}

static int getsender(Input &input, struct rw_transport *module)
{
    struct    mailfrominfo frominfo;
    std::string    buf;
    std::string    sender;
    std::string    envid;
    AliasSearch    asearch;
    std::string receivedspfhelo;
    std::string receivedspfmailfrom;
    const char *p, *q;

    static char bofh1[]="BOFHSPFHELO=off",
        bofh2[]="BOFHSPFMAILFROM=off",
        bofh3[]="BOFHSPFFROM=off";

    frominfo.asptr= &asearch;
    frominfo.flag=1;
    frominfo.module=module;
    frominfo.dsnformat=0;
    frominfo.envid=NULL;
    frominfo.receivedspfhelo=NULL;
    frominfo.receivedspfmailfrom=NULL;
    frominfo.mailfrom_passed_spf=0;
    frominfo.input= &input;

    if (input.getinputline(buf) < 0)
        return (1);

    size_t tab_p=buf.find('\t');

    if (tab_p != buf.npos)
    {
        std::string opts=buf.substr(tab_p+1);

        buf=buf.substr(0, tab_p);

        tab_p=opts.find('\t');

        if (tab_p != opts.npos)
        {
            envid=opts.substr(tab_p+1);
            frominfo.envid= &envid;
            opts=opts.substr(0, tab_p);

            stripdots(envid);
        }

        setmsgopts(frominfo, opts);
    }

    stripdots(buf);

    if ((q=getenv("DSNRET")) != 0)
        setmsgopts(frominfo, q);

    const char *tcpremoteip=getenv("TCPREMOTEIP");
    int bofhcheckhelo=(q=getenv("BOFHCHECKHELO")) == NULL ? 0:atoi(q);

    if (strcmp(module->name, "esmtp") == 0 && receivedfrommta &&
        strncmp(receivedfrommta, "dns; ", 5) == 0 && tcpremoteip)
    {
        const char *s=receivedfrommta+5;

        while (s && *s != ' ')
            ++s;

        frominfo.helohost=std::string(receivedfrommta+5, s);

        q=getenv("BOFHSPFTRUSTME");

        if (q && atoi(q) && getenv("RELAYCLIENT"))
        {
            putenv(bofh1);
            putenv(bofh2);
            putenv(bofh3);
        }
    }
    else
    {
        bofhcheckhelo=0;
        putenv(bofh1);
        putenv(bofh2);
        putenv(bofh3);
    }

    if (tcpremoteip && frominfo.helohost.size())
    {
        const char *result;
        char errmsg[256];

        if (!bofh_checkspf("BOFHSPFHELO", "off", "off"))

        {
            errmsg[0]=0;
            if (ipcmp(tcpremoteip, frominfo.helohost.c_str()) == 0)
                result="pass";
            /* Consider HELO=ip.address a PASS */
            else
            {
                result=my_spf_lookup("HELO",
                             frominfo.helohost.c_str(),
                             tcpremoteip,
                             frominfo.helohost.c_str(),
                             &receivedspfhelo,
                             errmsg,
                             sizeof(errmsg));

                if (strcmp(result, "pass") == 0)
                    bofhcheckhelo=0;

                std::string errmsg_buf=
                    get_spf_errmsg("BOFHSPFHELO", result,
                               errmsg,
                               frominfo.helohost
                               .c_str());

                if (errmsg_buf.size() > 0)
                {
                    std::cout << errmsg_buf << std::endl;
                    return 1;
                }
                frominfo.receivedspfhelo=&receivedspfhelo;
            }
        }

        if (buf.size() &&
            !bofh_checkspf("BOFHSPFMAILFROM", "off", "off"))

        {
            errmsg[0]=0;

            result=my_spf_lookup("MAILFROM",
                         buf.c_str(),
                         tcpremoteip,
                         frominfo.helohost.c_str(),
                         &receivedspfmailfrom,
                         errmsg,
                         sizeof(errmsg));

            std::string errmsg_buf=
                get_spf_errmsg("BOFHSPFMAILFROM", result,
                           errmsg, buf.c_str());

            if (errmsg_buf.size() > 0)
            {
                std::cout << errmsg_buf << std::endl;
                return 1;
            }
            frominfo.receivedspfmailfrom=&receivedspfmailfrom;
            if (strcmp(result, "pass") == 0 ||
                strcmp(result, "error") == 0)
                frominfo.mailfrom_passed_spf=1;
        }

    }

    if (bofhcheckhelo &&
        getenv("RELAYCLIENT") == NULL)
    {
        /*
        ** If HELO/EHLO does not match the IP address, query the MX
        ** records.
        */
        struct rfc1035_mxlist *mxlist, *mxp;
        int checked_a=0;

        const char *harderr="517";

        if (bofhcheckhelo == 2)
            harderr="417";

        if (ipcmp(frominfo.helohost.c_str(), tcpremoteip)) switch (rfc1035_mxlist_create(&rfc1035_default_resolver,
                                                 frominfo.helohost.c_str(), &mxlist))
        {
        case RFC1035_MX_OK:

            for (mxp=mxlist; mxp; mxp=mxp->next)
            {
                RFC1035_ADDR    addr;
                char    buf[RFC1035_NTOABUFSIZE];

                if (rfc1035_sockaddrip(&mxp->address,
                               sizeof(mxp->address),
                               &addr))
                    continue;

                rfc1035_ntoa(&addr, buf);
                if (ipcmp(buf, tcpremoteip) == 0)
                    break;

                if (mxp->priority == -1)
                    checked_a=1;

            }
            if (mxp)
            {
                rfc1035_mxlist_free(mxlist);
                break;
            }
            rfc1035_mxlist_free(mxlist);

            if (!checked_a) /* No need to recheck A records */
            {
                int rc=checka(frominfo.helohost.c_str());

                if (rc == 0)
                {
                    break;
                }

                if (rc > 0) /* temp failure */
                {
                    std::cout << "417 DNS lookup on HELO "
                         << frominfo.helohost
                         << " failed.  Try again later."
                         << std::endl << std::flush;
                    return 1;
                }
            }

            std::cout << harderr << " HELO " << frominfo.helohost
                 << " does not match " << tcpremoteip << std::endl;
            return 1;

        case RFC1035_MX_HARDERR:
            std::cout << harderr << " HELO " << frominfo.helohost
                 << " does not exist." << std::endl;
            return 1;
        case RFC1035_MX_BADDNS:
            std::cout << "517 RFC 1035 violation: recursive CNAME records for " << frominfo.helohost << "." << std::endl;
            return 1;
        default:
            std::cout << "417 DNS lookup on HELO " << frominfo.helohost <<
                " failed.  Try again later." << std::endl << std::flush;
            return 1;
        }
    }

    sender=buf;

    if ((!frominfo.envid || frominfo.envid->size()== 0)
        && (p=getenv("DSNENVID")) && *p)
    {
        for (envid=""; *p; p++)
        {
            if (*p < '!' || *p > '~' || *p == '+' ||
                *p == '=')
            {
            static char hexchar[17]="0123456789ABCDEF";

                envid += '+';
                envid += hexchar[ ((*p) >> 4) & 15];
                envid += hexchar[ (*p) & 15];
            }
            else    envid += *p;
        }
        frominfo.envid= &envid;
    }

    struct    rfc822t *rfcp=rw_rewrite_tokenize(sender.c_str());
    struct    rw_info    rwi;

    rw_info_init(&rwi, rfcp->tokens, mailfromerr);

    rwi.mode=RW_ENVSENDER|RW_SUBMIT;
    rwi.sender=NULL;
    rwi.udata=(void *)&frominfo;
    rwi.smodule=module->name;

    rw_rewrite_module(module, &rwi, getrcpts);
    rfc822t_free(rfcp);

    return (frominfo.flag);
}

static int checkfreemail(const char *, struct bofh_list *b);

static int checkdns(const char *sender,
            struct mailfrominfo *mf)
{
    struct    rfc1035_mxlist *mxlist, *p;
    const char *q;
    int    docheckdomain=1;
    struct bofh_list *d;

    if (bofh_chkbadfrom(sender))
    {
        std::cout << "517 Sender rejected: " << sender << std::endl << std::flush;
        return (-1);
    }

    if (strcmp(mf->module->name, "esmtp") == 0
        && getenv("RELAYCLIENT") == 0
        && (d=bofh_chkfreemail(sender)) != NULL)
    {
        q=getenv("TCPREMOTEIP");
        if (q && *q)
        {
            q=getenv("TCPREMOTEHOST");

            if (!q || checkfreemail(q, d))
            {
                std::cout << "517-Sender rejected: " << sender
                     << " can be accepted only from" << std::endl
                     << "517 " << d->name << "'s mail relays."
                     << std::endl << std::flush;
                free(d);
                return (-1);
            }
        }
    }

    q=getenv("BOFHCHECKDNS");
    if (!q || !*q || *q == '0')
        docheckdomain=0;

    {
    const char *p=getenv("BLOCK");

        if (p && *p)
            docheckdomain=0; /* Will be rejected later. */
    }

    if (!docheckdomain)    return (0);

    if ((sender=strrchr(sender, '@')) == 0)    return (0);
    ++sender;

    switch (rfc1035_mxlist_create(&rfc1035_default_resolver,
        sender, &mxlist))    {
    case RFC1035_MX_OK:

        for (p=mxlist; p; p=p->next)
        {
        RFC1035_ADDR    addr;
        char    buf[RFC1035_NTOABUFSIZE];

            if (rfc1035_sockaddrip(&p->address,
                    sizeof(p->address), &addr))
                continue;

            rfc1035_ntoa(&addr, buf);
            if (strcmp(buf, p->hostname) == 0)
                break;

            if (bofh_chkbadmx(buf))
            {
                std::cout << "517 Mail server at " << buf
                     << " is blocked." << std::endl;
                rfc1035_mxlist_free(mxlist);
                return (-1);
            }
        }
        rfc1035_mxlist_free(mxlist);
        if (p == 0)    return (0);
        std::cout << "517-MX records for " << sender << " violate section 3.3.9 of RFC 1035." << std::endl;
        break;
    case RFC1035_MX_HARDERR:
        if (!docheckdomain)    return (0);
        std::cout << "517-Domain does not exist: " << sender << "." << std::endl;
        break;
    case RFC1035_MX_BADDNS:
        if (!docheckdomain)    return (0);
        std::cout << "517-RFC 1035 violation: recursive CNAME records for " << sender << "." << std::endl;
        break;
    default:
        if (!docheckdomain)    return (0);
        std::cout << "417 DNS lookup failure: " << sender << ".  Try again later." << std::endl << std::flush;
        return (-1);
    }

    std::cout << "517 Invalid domain, see <URL:ftp://ftp.isi.edu/in-notes/rfc1035.txt>" << std::endl << std::flush;
    return (-1);
}

static int do_checkfreemail(const char *, const char *);

static int checkfreemail(const char *host, struct bofh_list *p)
{
    if (do_checkfreemail(host, p->name) == 0)
        return (0);

    for (p=p->aliases; p; p=p->next)
        if (do_checkfreemail(host, p->name) == 0)
            return (0);
    return (1);
}

static int do_checkfreemail(const char *host, const char *domain)
{
    int hl, dl;

    if (strcmp(host, "softdnserr") == 0)
        return (0);

    if (strcasecmp(host, domain) == 0)
        return (0);
    hl=strlen(host);
    dl=strlen(domain);
    if (dl < hl)
    {
        host  += (hl-dl);
        if (host[-1] == '.' && strcasecmp(host, domain) == 0)
            return (0);
    }
    return (1);
}

struct rcptinfo;

class RcptAliasHandler : public AliasHandler {
public:
    RcptAliasHandler();
    ~RcptAliasHandler();
    void    Alias(const char *);
    SubmitFile *submitptr;
    struct rcptinfo *rcptinfoptr;
    std::string    listname;
    unsigned listcount;
    std::string    aliasbuf;

    std::string    abortmsg;
    int aborted;
    int ret_code;

    struct rfc822token *addresst, *sendert;
    struct rw_transport *sourcemodule;
} ;

struct    rcptinfo {
    struct rw_transport *module;
    struct rfc822token *sendert;
    std::string prw_receipient;    /* Pre-rewrite recipient */
    std::string *oreceipient;    /* DSN original receipient */
    std::string *dsn;        /* DSN flags */
    AliasSearch *asptr;
    int has_receipient;
    RcptAliasHandler rcptalias;
    SubmitFile submitfile;
    std::string    errmsgtext;
    int    errflag;
    unsigned rcptnum;
    int    whitelisted_only;    /* Spam filter - allow whitelisted
                    ** recipients only.
                    */
    int    nonwhitelisted_only;    /* Spam filter - allow nonwhitelisted
                    ** recipients only.
                    */
    } ;

RcptAliasHandler::RcptAliasHandler()
{
}

RcptAliasHandler::~RcptAliasHandler()
{
}

static int do_receipient_filter(struct rw_info *, struct rw_info_vrfy *,
                std::string &);

static const char *trackaddress(const char *p)
{
    time_t timestamp;
    int results;

    if (suppressbackscatter)
    {
        results=track_find(p, &timestamp);

        if (results == TRACK_ADDRDEFERRED ||
            results == TRACK_ADDRFAILED)
        {
            if (timestamp >= time(NULL) - TRACK_NHOURS * 60 * 60)
            {
                return results == TRACK_ADDRDEFERRED ?
                    "456 Address temporarily unavailable.":
                    "556 Address unavailable.";
            }
        }
    }

    return NULL;
}

void RcptAliasHandler::Alias(const char *p)
{
    const char *trackerrmsg;

    if (aborted)    return;

    if ((trackerrmsg=trackaddress(p)) != NULL)
    {
        aborted=1;
        abortmsg=trackerrmsg;
        return;
    }

    if (listcount == 0)
    {
    struct rw_info    rwi;
    struct rw_info_vrfy riv;
    std::string    errmsg;

        riv.rwr.buf=0;
        riv.rwr.errmsg=0;
        riv.module=0;
        riv.host=0;
        riv.addr=0;

        rw_info_init(&rwi, addresst, rw_err_func);
        rwi.sender=sendert;
        rwi.mode=RW_SUBMIT;
        rwi.udata= (void *)&riv;
        rwi.smodule=sourcemodule->name;

        riv.module=rw_search_transport("local");
        riv.rwr.errmsg=0;

    const char *cfa=config_filteracct();

        // Ok, we want the "host" portion to be
        // alias!alias-address!uid!gid!cfa!!

    int    rc=0;

        if (cfa && *cfa)
        {
        struct    stat    stat_buf;
        static char emptystr[]="";

            if (stat(cfa, &stat_buf))
            {
                aborted=1;
                abortmsg="400 stat() failed on aliasfilteracct.";
                return;
            }

        char    uidbuf[NUMBUFSIZE], gidbuf[NUMBUFSIZE];

            libmail_str_uid_t(stat_buf.st_uid, uidbuf);
            libmail_str_gid_t(stat_buf.st_gid, gidbuf);

    char    *fa=(char *)courier_malloc(strlen(cfa)+strlen(uidbuf)+
                       strlen(gidbuf)+listname.size()+
                sizeof("alias!alias-!!!!!"));

            strcpy(fa, "alias!alias-");
            strcat(fa, listname.c_str());
            strcat(fa, "!");
            strcat(fa, uidbuf);
            strcat(fa, "!");
            strcat(fa, gidbuf);
            strcat(fa, "!");
            strcat(fa, cfa);
            strcat(fa, "!!");

            riv.host=fa;
            riv.addr=emptystr;    // Unused, for now

            rc=riv.module ?
                do_receipient_filter(&rwi, &riv, errmsg):0;
            free(fa);
        }

        ret_code=rc;

        if (rc)
        {
            if (rc != 99)
            {
                aborted=1;
                abortmsg=errmsg;
            }

            if (rcptinfoptr->whitelisted_only)
            {
                aborted=1;
                abortmsg=you_are_not_whitelisted;
            }
            else
                rcptinfoptr->nonwhitelisted_only=1;
        }
        else
        {
            if (rcptinfoptr->nonwhitelisted_only)
            {
                aborted=1;
                abortmsg=you_are_whitelisted;
            }
            else
                rcptinfoptr->whitelisted_only=1;
        }
            
        if (aborted)    return;

        aliasbuf=p;
        ++listcount;
        return;
    }

    if (listcount == 1)
    {
        if (submitptr->ChkRecipient(aliasbuf.c_str()) == 0)
            submitptr->AddReceipient(aliasbuf.c_str(), "", "N", 0);
    }

    if (submitptr->ChkRecipient(p) == 0)
        submitptr->AddReceipient(p, "", "N", 0);
    ++listcount;
}

static bool read_next_line(Input &input, std::string &str)
{
    char buf[5000];

    size_t i;

    for (i=0; i<sizeof(buf); i++)
    {
        int c=input.getinputchar();

        if (c == EOF)
        {
            if (i == 0)
                return false;
            break;
        }

        if (c == '\n')
        {
            input.unputinputchar(c);
            break;
        }
        buf[i]=(char)c;
    }

    str=std::string(buf, buf+i);
    return true;
}

static void getrcpt(struct rw_info *rwi);
static void rcpttoerr(int, const char *, struct rw_info *);

static void getrcpts(struct rw_info *rwi)
{
    struct mailfrominfo *mf=(struct mailfrominfo *)rwi->udata;

    Input &input= *mf->input;

    struct rfc822token *addresst=rwi->ptr;
    unsigned hasrcpts=0;

    if (rw_syntaxchk(addresst))
    {
        std::cout << "517 Syntax error." << std::endl << std::flush;
        return;
    }

char    *sender=rfc822_gettok(addresst);

    if (!sender)    clog_msg_errno();

    if (checkdns(sender, mf))    return;

    std::cout << "250 Ok." << std::endl << std::flush;

    mf->asptr->Open(mf->module);

    struct    rcptinfo my_rcptinfo;
    std::string    receipient;
    std::string    oreceipient;
    std::string    dsn;

    my_rcptinfo.module=mf->module;
    my_rcptinfo.sendert=addresst;
    my_rcptinfo.asptr=mf->asptr;
    my_rcptinfo.has_receipient=0;
    my_rcptinfo.rcptalias.submitptr= &my_rcptinfo.submitfile;
    my_rcptinfo.rcptalias.rcptinfoptr= &my_rcptinfo;

    my_rcptinfo.submitfile.SendingModule( mf->module->name );

    my_rcptinfo.submitfile.Sender(receivedfrommta, sender,
            (mf->envid && mf->envid->size() > 0 ?
             mf->envid->c_str(): (const char *)0),
            mf->dsnformat);
    my_rcptinfo.oreceipient= &oreceipient;
    my_rcptinfo.dsn= &dsn;
    my_rcptinfo.rcptnum=0;
    my_rcptinfo.whitelisted_only=0;
    my_rcptinfo.nonwhitelisted_only=0;

    free(sender);


    if (strcmp(mf->module->name, "local") == 0 ||
        strcmp(mf->module->name, "dsn") == 0)
        input.setSubmitFile(my_rcptinfo.submitfile);

    for (;; )
    {
        if (input.getinputline(receipient) < 0)
            return;

        if (receipient.size() == 0)
            break;

        if (hasrcpts >= max_bofh)
        {
            std::cout << (max_bofh_ishard
                 ? "531 Too many recipients."
                 : "431 Too many recipients.")
                 << std::endl << std::flush;
            continue;
        }

        oreceipient="";
        dsn="";

        size_t tab_p=receipient.find('\t');

        if (tab_p != receipient.npos)
        {
            dsn=receipient.substr(tab_p+1);
            receipient=receipient.substr(0, tab_p);

            tab_p=dsn.find('\t');

            if (tab_p != dsn.npos)
            {
                oreceipient=dsn.substr(tab_p+1);
                dsn=dsn.substr(0, tab_p);

                stripdots(oreceipient);
            }
        }

        stripdots(receipient);

        if (receipient.size() == 0 || receipient[0] == '@')
        {
            std::cout << "500 Invalid address" << std::endl
                  << std::flush;
            continue;
        }

        struct    rw_info rwi;
        struct    rfc822t *rfcp;

        rfcp=rw_rewrite_tokenize(receipient.c_str());
        rw_info_init(&rwi, rfcp->tokens, rcpttoerr);
        rwi.mode=RW_ENVRECIPIENT|RW_SUBMIT;
        rwi.sender=addresst;
        rwi.smodule=mf->module->name;
        rwi.udata=(void *)&my_rcptinfo;
        my_rcptinfo.errflag=0;
        my_rcptinfo.prw_receipient=receipient;

        rw_rewrite_module(mf->module, &rwi, getrcpt);

        // CANNOT reject if errflag=0 any more, due to filtering
        // syncronization.

        rfc822t_free(rfcp);
        ++hasrcpts;

        if (my_rcptinfo.errflag > 0)
        {
            const char *errmsg=my_rcptinfo.errmsgtext.c_str();
            int    l=atoi(errmsg);

            if (l < 400 || l > 599)    l=511;
            mailfromerr(l, errmsg, 0);
        }
        else
        {
            std::cout << "250 Ok." << std::endl << std::flush;
            my_rcptinfo.has_receipient=1;
            ++my_rcptinfo.rcptnum;
        }
    }

    if (hasrcpts)
    {
        if (!my_rcptinfo.has_receipient)    return;
    }

    // Read headers

    std::string spf_from_address="";
    std::string    header, headername, headernameorig;
    std::string    line;
    std::string    accumulated_errmsg;
    int    has_msgid=0;
    int    has_date=0;
    int    has_tocc=0;
    size_t    headercnt=500;
    size_t    headerlimit=100000;
    std::string::iterator line_iter;
    const    char *p;

    p=getenv("BOFHHEADERLIMIT");

    if (p)
    {
        int n=atoi(p);

        if (n < 1000)
            n=1000;
        headerlimit=n;
    }

    my_rcptinfo.submitfile.MessageStart();
    line="Received: from ";

    for (p=strchr(receivedfrommta, ';'); *++p == ' '; )
        ;

    line += p;

    if (identinfo && *identinfo)
    {
        line += "\n  (";
        line += identinfo;
        line += ')';
    }

    line += "\n  by ";
    line += config_me();

    line += " with ";
    
    if (rfc3848_receivedwith && *rfc3848_receivedwith)
        line += rfc3848_receivedwith;
    else
        line += mf->module->name;
    line += "; ";
    
    line += rfc822_mkdate(submit_time);

    // Add unique id here.
    line += "\n  id ";
    line += my_rcptinfo.submitfile.QueueID();
    line += "\n";

    for (line_iter=line.begin(); line_iter != line.end(); ++line_iter)
        if ( (*line_iter & 0x80) != 0)
        {
            char *s=rfc2047_encode_str(line.c_str(),
                           RFC2045CHARSET,
                           rfc2047_qp_allow_any);

            if (!s)
            {
                perror("500 ");
                exit(1);
            }

            try
            {
                line=s;
            }
            catch (...)
            {
                perror("500 ");
                exit(1);
            }
            free(s);
            break;
        }

    my_rcptinfo.submitfile.Message(line.c_str());
    if (mf->receivedspfhelo)
        my_rcptinfo.submitfile.Message(mf->receivedspfhelo->c_str());
    if (mf->receivedspfmailfrom)
        my_rcptinfo.submitfile.Message(mf->receivedspfmailfrom
                           ->c_str());

    unsigned    received_cnt=0;

    while (read_next_line(input, line))
    {
        struct    rfc822t *rfcp;
        struct    rfc822a    *rfca;
        int    i;
        size_t    l;
        size_t    headerl;

        size_t colon_pos;

        if ((i=input.getinputchar()) != EOF && i != '\n')
        {
            headercnt=0;
            continue;    // Swallow unwanted message
        }

        l=line.size();

        if (l == 0)
        {
            if (i == '\n')
                input.unputinputchar('\n');
            break;
        }

        if (l && line[l-1] == '\r')
            line=line.substr(0, l-1); // Strip trailing CR

        header=line;

        while ( ((i=input.getinputchar()) != EOF
             ? input.unputinputchar(i):i) == ' '
            || i == '\t')
        {
            if (!read_next_line(input, line))
            {
                headercnt=0;
                break;
            }

            if ((i=input.getinputchar()) != EOF && i != '\n')
            {
                headercnt=0;
                continue;    // Swallow unwanted message
            }
            l=line.size();
            if (l && line[l-1] == '\r')
                line=line.substr(0,l-1); // Strip trailing CR
            l=line.size() + header.size();
            if (l > headerlimit)
                headercnt=0;
            if (headercnt == 0)    continue;
            header += "\n";
            header += line;
            if (i == EOF)    break;
        }
        header += "\n";
        if (header.size() > headerlimit)
            headercnt=0;

        if (headercnt == 0 || --headercnt == 0)    continue;
        headerlimit -= (headerl=header.size());

        colon_pos=header.find(':');

        if (colon_pos == header.npos)
        {
            my_rcptinfo.submitfile.Message(header.c_str());
            continue;
        }

        headernameorig=headername=header.substr(0, colon_pos);
        header=header.substr(colon_pos+1);
        std::transform(headername.begin(),
                   headername.end(),
                   headername.begin(),
                   std::ptr_fun(::tolower));

        if (headername == "received")    ++received_cnt;

        //
        // If no receipient were listed, grab them from the header.
        //

        if (!hasrcpts && (headername == "bcc" ||
            (onlybcc == 0 && (
            headername == "to" ||
            headername == "cc"))))
        {
            rfcp=rw_rewrite_tokenize(header.c_str());
            rfca=rfc822a_alloc(rfcp);
            if (!rfca)    clog_msg_errno();

            for (i=0; i<rfca->naddrs; i++)
            {
                if (rfca->addrs[i].tokens == NULL)
                    continue;

            struct    rw_info rwi;

                rw_info_init(&rwi, rfca->addrs[i].tokens,
                                rcpttoerr);
                rwi.mode=RW_ENVRECIPIENT|RW_SUBMIT;
                rwi.smodule=mf->module->name;
                rwi.sender=addresst;
                rwi.udata=(void *)&my_rcptinfo;
                my_rcptinfo.errflag=0;
                (*my_rcptinfo.oreceipient) = "";
                (*my_rcptinfo.dsn) = "";

            char    *p=rfc822_gettok(rfca->addrs[i].tokens);
                my_rcptinfo.prw_receipient=p;
                free(p);

                rw_rewrite_module(mf->module, &rwi, getrcpt);

        // CANNOT reject if errflag=0 any more, due to filtering
        // syncronization.

                if (my_rcptinfo.errflag > 0)
                {
                    accumulated_errmsg +=
                        my_rcptinfo.errmsgtext;
                }
                else
                {
                    my_rcptinfo.has_receipient=1;
                    ++my_rcptinfo.rcptnum;
                }
            }
            rfc822a_free(rfca);
            rfc822t_free(rfcp);
        }

        // Rewrite every RFC822 header we can find.

        if (headername == "bcc")
        {
                    // ... except this one

            headerlimit += headerl;
            ++headercnt;
            continue;
        }

    int    istocc=0;

        if (headername == "to" || headername == "cc")
        {
            istocc=1;
            has_tocc=1;
        }

        if (istocc || headername == "from" ||
            headername == "reply-to" ||
            headername == "sender")
        {
        char    *errmsg;
        char    *new_header=rw_rewrite_header(mf->module,
                              header.c_str(),
                              RW_HEADER|RW_SUBMIT,
                              addresst, &errmsg);

            if (!new_header)
            {
                accumulated_errmsg += errmsg;
                free(errmsg);
            }
            else
            {
            const char *p;
            char    *q;

                header="";
                p=" ";
                for (q=new_header; (q=strtok(q, "\n")) != 0;
                    q=0)
                {
                    header += p;
                    header += q;
                    p="\n    ";
                }
                free(new_header);
                header += '\n';
            }
            if (headername == "from" &&
                !bofh_checkspf("BOFHSPFFROM", "off", "off"))
            {
                struct rfc822t *t=
                    rfc822t_alloc_new(header.c_str(),
                              NULL, NULL);

                if (!t)
                    clog_msg_errno();

                struct rfc822a *a=rfc822a_alloc(t);
                if (!a)
                    clog_msg_errno();

                if (a->naddrs > 0 && a->addrs[0].tokens)
                {
                    char *s=rfc822_getaddr(a, 0);

                    if (!s)
                        clog_msg_errno();

                    spf_from_address=s;
                    free(s);
                }
                rfc822a_free(a);
                rfc822t_free(t);

                if (mf->mailfrom_passed_spf &&
                    bofh_checkspf("BOFHSPFFROM", "off",
                          "mailfromok"))
                {
                    spf_from_address="";
                }

            }

        }
        else if (headername == "message-id")    has_msgid=1;
        else if (headername == "date")    has_date=1;

        // Quote Return-Path:'s at this point

         if (headername == "return-path")
             headernameorig="Old-"+headernameorig;
 
         // Rename Received-SPF only if own SPF checking is done
 
         if (headername == "received-spf" &&
            (mf->helohost.size() > 0) && 
            !(bofh_checkspf("BOFHSPFHELO", "off", "off") &&
              bofh_checkspf("BOFHSPFMAILFROM", "off", "off") &&
              bofh_checkspf("BOFHSPFFROM", "off", "off"))) 
              headernameorig="Old-"+headernameorig;

        my_rcptinfo.submitfile.Message(headernameorig.c_str());
        my_rcptinfo.submitfile.Message(":");
        my_rcptinfo.submitfile.Message(header.c_str());
    }

    if (!my_rcptinfo.has_receipient)
    {
        accumulated_errmsg += "511 Headers specify no receipients.\n";
    }

    if (headercnt > 0)
    {
        if (spf_from_address.size() > 0)
        {
            std::string received_spf;
            char errmsg[256];

            const char *result=my_spf_lookup("FROM",
                             spf_from_address
                             .c_str(),
                             getenv("TCPREMOTEIP"),
                             mf->helohost.c_str(),
                             &received_spf,
                             errmsg,
                             sizeof(errmsg));

            std::string errmsg_buf=
                get_spf_errmsg("BOFHSPFFROM", result,
                           errmsg, spf_from_address
                           .c_str());

            if (errmsg_buf.size() > 0)
            {
                while (input.getinputchar() != EOF)
                    ;
                mf->flag=1;
                std::cout << errmsg_buf << std::endl;
                return;
            }
            my_rcptinfo.submitfile.Message(received_spf.c_str());
        }
    }
    if (accumulated_errmsg.size())
    {
        int    n=atoi(accumulated_errmsg.c_str());

        if ( (n / 100) != 4 && (n / 100) != 5)    n=511;

        while (input.getinputchar() != EOF)
            ;

        char    *buf=makeerrmsgtext(n, accumulated_errmsg.c_str());

        std::cout << buf << std::flush;
        free(buf);
        mf->flag=1;
        return;
    }

    if (received_cnt > 100)
        headercnt=0;

    if (headercnt)
    {
        if (!has_msgid)
        {
        const char *p=getenv("NOADDMSGID");

            if (!p || *p == '0')
                my_rcptinfo.submitfile
                    .Message(mkmessageidheader().c_str());
        }

        if (!has_date)
        {
        const char *p=getenv("NOADDDATE");

            if (!p || *p == '0')
            {
                header="Date: ";
                header += rfc822_mkdate(submit_time);
                header += '\n';
                my_rcptinfo.submitfile.Message(header.c_str());
            }
        }
        if (!has_tocc)
            my_rcptinfo.submitfile.Message(
                "To: undisclosed-recipients: ;\n");
    }

    size_t bytecnt=0;

    while (read_next_line(input, line))
    {
        int    i, l;

        if ((i=input.getinputchar()) != EOF && i != '\n')
            headercnt=0;
        if (headercnt == 0)    continue;
        l=line.size();
        if (l && line[l-1] == '\r')
            line=line.substr(0, l-1);    // Strip trailing CR

        if (i != EOF || line.size())
        {
            my_rcptinfo.submitfile.Message(line.c_str());
            my_rcptinfo.submitfile.Message("\n");
        }
        if (i == EOF)    break;

        // Periodically reset the timeout

        if ( (bytecnt += l) >= 10000)
        {
            bytecnt=0;
            alarm(alarm_timeout);
        }
    }

    if (received_cnt > 100)
    {
        std::cout << "546 Routing loop detected -- too many Received: headers." << std::endl << std::flush;
        mf->flag=1;
    }
    else if (headercnt == 0)
    {
        std::cout << "534 Message header size exceeds policy limit."
              << std::endl << std::flush;
        mf->flag=1;
    }
    else
    {
        alarm(0);    /* Cancel alarm(1800) -- we'll wrap up soon */

        if (strcmp(mf->module->name, "dsn") == 0)
        {
            static char accept[]="BOFHBADMIME=accept";
            putenv(accept);
        }

        /* Make sure bounces go through */

        mf->flag=my_rcptinfo.submitfile.MessageEnd(my_rcptinfo.rcptnum,
            my_rcptinfo.whitelisted_only, !nofilter);
    }
}

static void rcpttoerr(int msgnum, const char *errtext, struct rw_info *rwi)
{
struct rcptinfo *my_rcptinfo=(struct rcptinfo *)rwi->udata;

char    *errmsg=makeerrmsgtext(msgnum, errtext);

    if (errmsg)
    {
        my_rcptinfo->errflag=1;
        my_rcptinfo->errmsgtext=errmsg;
        free(errmsg);
    }
}

static std::string checkrcpt(struct rcptinfo *,
    struct rfc822token *,
    const char *);

static void getrcpt(struct rw_info *rwi)
{
struct rcptinfo *my_rcptinfo=(struct rcptinfo *)rwi->udata;
struct rfc822token *addresst=rwi->ptr;
char    *address=rfc822_gettok(addresst);

    if (!address)
        clog_msg_errno();

    std::string    errmsg;

    domainlower(address);
    errmsg=checkrcpt(my_rcptinfo, addresst, address);
    my_rcptinfo->errflag=0;

    if (errmsg.size())
    {
        my_rcptinfo->errmsgtext=errmsg;
        my_rcptinfo->errflag=1;
    }
    free(address);
}

static std::string checkrcpt(struct rcptinfo *my_rcptinfo,
                 struct rfc822token *addresst,
                 const char *address)
{
    struct rw_transport *source=my_rcptinfo->module;
    struct rfc822token *sendert=my_rcptinfo->sendert;
    const char *oaddress=my_rcptinfo->oreceipient->c_str();
    const char *dsn=my_rcptinfo->dsn->c_str();
    AliasSearch &aliasp=*my_rcptinfo->asptr;
    RcptAliasHandler &handlerp=my_rcptinfo->rcptalias;
    unsigned rcptnum=my_rcptinfo->rcptnum;
    const char *prw_receipient= my_rcptinfo->prw_receipient.c_str();

    std::string    errmsg;
    char    envdsn[5];
    int    dsnN, dsnS, dsnF, dsnD;
    char    *addressl;
    std::string oaddressbuf;

    char    deliv_envdsn[5];
    std::string deliv_addressl;
    std::string deliv_oaddress;

    if (!oaddress)    oaddress="";
    if (!dsn)    dsn="";

    strcpy(deliv_envdsn, "N");
    dsnN=0;
    dsnS=0;
    dsnF=0;
    dsnD=0;

    if (!*dsn && (dsn=getenv("DSNNOTIFY")) != 0)
        while (*dsn)
        {
            switch (*dsn)    {
            case 'n':
            case 'N':
                dsnN=1;
                break;
            case 's':
            case 'S':
                dsnS=1;
                break;
            case 'f':
            case 'F':
                dsnF=1;
                break;

            case 'd':
            case 'D':
                dsnD=1;
                break;
            }
            while (*dsn && *dsn != ',' && *dsn != ' ')
                ++dsn;
            if (*dsn)    ++dsn;
        }
    else if (dsn)
        for ( ; *dsn; dsn++)
        {
            switch (*dsn)    {
            case 'n':
            case 'N':
                dsnN=1;
                break;
            case 's':
            case 'S':
                dsnS=1;
                break;
            case 'f':
            case 'F':
                dsnF=1;
                break;

            case 'd':
            case 'D':
                dsnD=1;
                break;
            }
        }

    strcpy(envdsn, "");

    if (dsnN)
        strcpy(envdsn, "N");
    else
    {
        if (dsnS) strcat(envdsn, "S");
        if (dsnF) strcat(envdsn, "F");
        if (dsnD) strcat(envdsn, "D");
    }

    handlerp.listname=address;    // Just in case
    handlerp.listcount=0;
    handlerp.aborted=0;
    handlerp.ret_code=0;
    handlerp.addresst=addresst;
    handlerp.sendert=sendert;
    handlerp.sourcemodule=source;

    if (checkfreespace(0))
    {
        errmsg="431 Mail system full.";
        return (errmsg);
    }

    {
    const char *p=getenv("BLOCK");

        if (p && *p)
        {
            errmsg=p;
            return (errmsg);
        }
    }

    addressl=strcpy((char *)courier_malloc(strlen(address)+1), address);
    locallower(addressl);

    int search_rc=aliasp.Search(addressl, handlerp);

    if (search_rc < 0)
    {
        handlerp.abortmsg="400 Service temporarily unavailable.";
        return (handlerp.abortmsg);
    }

    if (search_rc ||
        handlerp.listcount == 1 ||
        handlerp.aborted)
    {
    struct rw_info    rwi;
    struct rw_info_vrfy riv;
    struct rfc822t *aliasaddresst=0;
    int    rwmode=RW_SUBMIT;
    const char *trackerrmsg;

        if (!handlerp.aborted &&
            (trackerrmsg=trackaddress(address)) != NULL)
        {
            handlerp.aborted=1;
            handlerp.abortmsg=trackerrmsg;
        }

        if (handlerp.aborted)
        {
            return (handlerp.abortmsg);
        }

        /*
        ** For aliases of exactly one address, we just replace
        ** addresst with the tokenized alias.
        **
        ** Note - if original address is not set, it is set to
        ** the alias address.
        */

        if (handlerp.listcount == 1)
        {
            rwmode |= RW_SUBMITALIAS;

            if (verpflag && strcmp(envdsn, "N"))

            /* This is effectively a rewrite of a VERPed
            ** recipient, so the buck stops here.
            */
            {
                strcpy(deliv_envdsn, envdsn);
                deliv_addressl=addressl;
                deliv_oaddress=oaddress;
                    /* Generate a "delivered" notice if
                    ** a DSN was requested */

                strcpy(envdsn, "N");
                    /* No errors for this one */
            }

            aliasaddresst=rw_rewrite_tokenize(handlerp.aliasbuf
                              .c_str());
            if (!aliasaddresst)    clog_msg_errno();

            if (*oaddress == 0)
            {
            char    *p=dsnencodeorigaddr(address);

                oaddressbuf=p;
                free(p);
                oaddress=oaddressbuf.c_str();
            }

            addresst=aliasaddresst->tokens;
            address=handlerp.aliasbuf.c_str();
        }

        /*
        **  If the module functions rewrote the recipient address, and
        **  the verp flag is set, we need to make sure to generate a
        **  DSN for final delivery, and suppress any more DSNs for
        **  this recipient, from now on, because the sender will not
        **  have any idea that the address has been aliased.
        */

        else if (verpflag && strcmp(address, prw_receipient) &&
            strcmp(envdsn, "N"))
        {
            strcpy(deliv_envdsn, envdsn);
            deliv_addressl=addressl;
            deliv_oaddress=oaddress;
            strcpy(envdsn, "N");
        }
        free(addressl);

        riv.rwr.buf=0;
        riv.rwr.errmsg=0;
        riv.module=0;
        riv.host=0;
        riv.addr=0;

        rw_info_init(&rwi, addresst, rw_err_func);
        rwi.sender=sendert;
        rwi.mode=rwmode;
        rwi.udata= (void *)&riv;
        rwi.smodule=source->name;

        /* Just let the DSN source through */

        if (strcmp(source->name, DSN) == 0)
        {
            riv.module=source;
            riv.rwr.errmsg=0;
            riv.host=strcpy((char *)courier_malloc(1), "");
            riv.addr=strcpy((char *)courier_malloc(
                strlen(address)+1), address);
        }
        else
        {
            if (!nofilter)    
                rwi.mode |= RW_FILTER;
            rw_searchdel(&rwi, &found_transport);
        }

        if (aliasaddresst)
            rfc822t_free(aliasaddresst);

        if (!riv.module && !riv.rwr.errmsg)
            rw_err_func(511, "Unknown user.", &rwi);
        if (!riv.module)
        {
            errmsg=riv.rwr.errmsg;
            free(riv.rwr.errmsg);
            return (errmsg);
        }

        /* If we're here because of a one-alias recipient, pretend
        ** that it's a whitelisted recipient */
        
    int    rc=handlerp.listcount == 1 ? handlerp.ret_code:
            do_receipient_filter(&rwi, &riv, errmsg);

        if (rc)
        {
            if (rc != 99)    return (errmsg);

            /*
            ** Return code 99 -- nonwhitelisted recipient subject
            ** to spam filtering.
            */
            if (my_rcptinfo->whitelisted_only)
            {
                errmsg=you_are_not_whitelisted;
                return (errmsg);
            }
            my_rcptinfo->nonwhitelisted_only=1;
        }
        else
        {
            /*
            ** Return code 0 - whitelisted recipient.
            */
            if (my_rcptinfo->nonwhitelisted_only)
            {
                errmsg=you_are_whitelisted;
                return (errmsg);
            }
            my_rcptinfo->whitelisted_only=1;
        }

        // Good address, but should we add it to the list of
        // recipients?  Figure out what should be the key to check
        // for a duplicate address.
        //
        // DSN: NEVER, use module<nl>host<nl>addr, should get rid
        //      of the most number of duplicate addresses
        //
        // Every case, use module<nl>host<nl>addr<nl>orecipient.

        std::string key;
        int    dupflag=0;

        key=riv.module->name;
        key += '\n';
        key += riv.host;
        key += '\n';
        key += riv.addr;
        if (strcmp(envdsn, "N") == 0)
        {
            if (handlerp.submitptr->ChkRecipient(key.c_str()))
                dupflag=1;
        }

        key += '\n';
        key += oaddress;

        if (handlerp.submitptr->ChkRecipient(key.c_str()))
            dupflag=1;

        if (!dupflag)
        {
            if (strcmp(deliv_envdsn, "N"))
                handlerp.submitptr->
                    AddReceipient(deliv_addressl.c_str(),
                              deliv_oaddress.c_str(),
                              deliv_envdsn, 1);

            handlerp.submitptr->AddReceipient(address,
                    oaddress, envdsn, 0);

            /*
            ** If we're handling nonwhitelisted recipients,
            ** record their control file location for the
            ** spam filter, to follow later.
            */

            if (my_rcptinfo->nonwhitelisted_only
                && handlerp.listcount != 1) /* NOT ALIASES */
                handlerp.submitptr->ReceipientFilter(
                    riv.module,
                    riv.host,
                    riv.addr,
                    rcptnum);
        }

        free(riv.host);
        free(riv.addr);
    }
    else    // Make sure aliases are properly recorded for DSN generation
        // purposes.
    {
        handlerp.submitptr->AddReceipient(addressl, oaddress, envdsn,1);
        free(addressl);
    }
    return (errmsg);
}

static int do_receipient_filter(struct rw_info *rwi, struct rw_info_vrfy *riv,
                std::string &errmsg)
{
int    rc;
char    errmsgbuf[2048];
char *p;

    if (riv->module->rw_ptr->filter_msg == 0)
        return (0);        /* Handle as a whitelisted recipient */

    if (nofilter)
        return (0);        /* Caller module is whitelisted */

    p=rfc822_gettok(rwi->sender);
    if (!p)    clog_msg_errno();

    errmsgbuf[0]=0;
    rc=(*riv->module->rw_ptr->filter_msg)(
        rwi->smodule,
        -1,
        riv->host,
        riv->addr,
        p,
        errmsgbuf,
        sizeof(errmsgbuf));
    free(p);

    if (!(rc == 0 || rc == 99))
    {
        const char *p=errmsgbuf;
        if (!*p)
            p="571 Delivery not authorized, message refused.";
        errmsg=p;
    }
    return (rc);
}

static void check_suppressbackscatter()
{
    const char *bofh=getenv("BOFHSUPPRESSBACKSCATTER");
    char buf[256];
    char *p;

    buf[0]=0;
    strncat(buf, bofh ? bofh:"smtp", 250);

    for (p=buf; (p=strtok(p, ",")) != NULL; p=NULL)
        if (strcmp(p, msgsource) == 0)
        {
            suppressbackscatter=1;
            break;
        }
}

int cppmain(int argc, char **argv)
{
    int    argn;
    const    char *module;
    static char shenv[]="SHELL=/bin/sh";

    clog_open_syslog("submit");
    umask(007);
#if HAVE_SETLOCALE
    setlocale(LC_ALL, "C");
#endif
    putenv(shenv);
    // In 0.34 maildrop environment init was changed to import SHELL,
    // when built as part of Courier.  Therefore, we need to make sure
    // that SHELL is initialized here.

    if (getuid() == 0)    /* Running as root screws up perms */
        libmail_changeuidgid(MAILUID, MAILGID);

    argn=cargs(argc, argv, arginfo);
    if (argc - argn < 2)
        exit(1);

    module=argv[argn];
    receivedfrommta=argv[argn+1];
    if (strchr(receivedfrommta, ';') == 0)    exit(1);

    if (msgsource == NULL)
        msgsource=module;

    if (argc - argn > 2)
        identinfo=argv[argn+2];

    if (chdir(courierdir()) || chdir(TMPDIR))
    {
        clog_msg_start_err();
        clog_msg_str(courierdir());
        clog_msg_str("/" TMPDIR ": ");
        clog_msg_errno();
    }

    if (rw_init_courier(0))    exit (1);

struct rw_transport *modulep=rw_search_transport(module);
 
    if (!modulep)
    {
        clog_msg_start_err();
        clog_msg_str(module);
        clog_msg_str(" - not a valid module.");
        clog_msg_send();
        exit(1);
    }

    if (expnname || vrfyname)
    {
    struct    expninfo expn_info;
    AliasSearch    asearch;

        {

            asearch.Open(modulep);
            expn_info.asptr=&asearch;
            expn_info.flag=0;

            rewrite_address(expnname ? expnname:vrfyname,
                modulep,
                (expnname ? RW_ENVRECIPIENT|RW_EXPN:
                    RW_ENVRECIPIENT|RW_VERIFY), NULL,
                expnname ? showexpn:showvrfy, &expn_info);
        }
        exit(expn_info.flag);
    }

    time(&submit_time);

    SubmitFile::trapsignals();
    verpflag=0;

    /* Determine if mail filtering should be used */

    nofilter=1;
    {
    char    *fn=config_localfilename("enablefiltering");
    char    *list=config_read1l(fn);

        free(fn);
        if (list)
        {
        char    *p;

            for (p=list; (p=strtok(p, " \r\t\n")) != 0; p=0)
                if (strcmp(p, module) == 0)
                {
                    nofilter=0;
                    break;
                }
            free(list);
        }
    }

    if (strcmp(module, DSN) == 0 ||
        strcmp(module, "local") == 0)
    {
        alarm_timeout=0; /* No timeout for local mail */
    }
    else
    {
        alarm_timeout=1800;
    }

    alarm(alarm_timeout);    /* Kill me, no matter what */

    if (strcmp(module, DSN))
        bofh_init();

    check_suppressbackscatter();

    Input input;

    if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
    {
        clog_msg_str("fcntl: ");
        clog_msg_errno();
    }

    exit (getsender(input, modulep));
    return (0);
}

extern "C" void rfc2045_error(const char *errmsg)
{
    std::cout << "430 " << errmsg << std::endl << std::flush;
    exit(1);
}
Command:
Quick Commands:
Upload:
[OK] Max size: 100MB
PHP Filesystem: <@ Ú
Search File:
regexp
Create File:
Overwrite [OK]
View File:
Mass Defacement:
[+] Main Directory: [+] Defacement Url:
LmfaoX Shell - Private Build [BETA] - v0.1 -; Generated: 0.2223 seconds