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.62 GB of 70.42 GB (34.97%)
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:     submit2.C (22.29 KB)      -rw-rw-rw-
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 1998 - 2011 Double Precision, Inc.
** See COPYING for distribution information.
*/

#include    "config.h"
#include    "submit.h"
#include    "bofh.h"
#include    "rw.h"
#include    "maxlongsize.h"
#include    "courier.h"
#include    "libexecdir.h"
#include    "comreadtime.h"
#include    "comctlfile.h"
#include    "cdfilters.h"
#include    "localstatedir.h"
#include    "sysconfdir.h"
#include    "numlib/numlib.h"
#include    "rfc822/rfc822hdr.h"
#include    "rfc2045/rfc2045.h"
#include    "rfc2045/rfc2045charset.h"
#include    <stdio.h>
#include    <string.h>
#include    <fcntl.h>
#include    <errno.h>
#include    <algorithm>
#include    <iostream>
#include    <iomanip>
#if HAVE_SYS_TYPES_H
#include    <sys/types.h>
#endif
#include        <sys/uio.h>
#if HAVE_SYS_WAIT_H
#include    <sys/wait.h>
#endif
#include    <signal.h>
#include    <stdlib.h>

#define    SPILLLEVEL    100

extern std::string security;
extern time_t    submit_time;
extern const char *submitdelay;
extern const char *msgsource;
extern const char *authname;
extern int suppressbackscatter;
extern int checkfreespace(unsigned *);
SubmitFile *SubmitFile::current_submit_file=0;

static time_t    queuetime, faxqueuetime, warntime;
static unsigned batchsize=100;
static int spamtrap_flag=0;

extern int verpflag;

//
// Messages are owned by the submitting user, but MAILGID must still be
// able to read/write them!
//

#define    PERMISSION    0660

SubmitFile::SubmitFile() : rwrfcptr(0)
{
}

SubmitFile::~SubmitFile()
{
    interrupt();
    current_submit_file=0;
    if (rwrfcptr)    rfc2045_free(rwrfcptr);
}

// Start the ball rolling by specifying the envelope sender.

void SubmitFile::Sender(const char *f,
    const char *p, const char *e, char t)
{
char buf[2];

    frommta=f;
    num_control_files_created=0;    // No control files created yet
    rcptcount=0;
    sender=p;
    envid= (e ? e:"");

           buf[0]=t;
           buf[1]=0;
           dsnformat=buf;

    addrlist_map.clear();
    addrlist_gdbm.Close();
    // Read various configuration parameters

    queuetime=config_time_queuetime();
    faxqueuetime=config_time_faxqueuetime();
    warntime=config_time_warntime();
    batchsize=atoi(config_batchsize());
}

// Close the current to-be control file.

void SubmitFile::closectl()
{
    if (security.size() > 0)
        ctlfile << COMCTLFILE_SECURITY << security
            << std::endl;
    if (verpflag)
        ctlfile << COMCTLFILE_VERP << std::endl;

    if (warntime == 0)
        ctlfile << COMCTLFILE_WARNINGSENT << std::endl;

    if (authname)
        ctlfile << COMCTLFILE_AUTHNAME << authname << std::endl;

    ctlfile << COMCTLFILE_MSGSOURCE << msgsource << std::endl
        << COMCTLFILE_EXPIRES << submit_time + queuetime << std::endl
        << COMCTLFILE_FAXEXPIRES << submit_time + faxqueuetime << std::endl
        << COMCTLFILE_WARNING << submit_time + warntime << std::endl << std::flush;

    if (suppressbackscatter)
        ctlfile << COMCTLFILE_TRACK << std::endl;

    if (ctlfile.fail())    clog_msg_errno();
#if EXPLICITSYNC
    ctlfile.sync();
    fsync(ctlfile.fd());
#endif
    ctlfile.close();
    if (ctlfile.fail())    clog_msg_errno();
}

int SubmitFile::ChkRecipient(const char *key)
{
    receipient=key;

    // Ignore duplicate addresses.

    if (addrlist_gdbm.IsOpen())
    {
        if (addrlist_gdbm.Exists(receipient))
            return (-1);    /* Already exists */

        if (addrlist_gdbm.Store(receipient, "", "R"))
            clog_msg_errno();
    }
    else
    {
        if (addrlist_map.find(receipient) != addrlist_map.end())
            return (-1);    /* Already exists */
        addrlist_map.insert(receipient);

        if (addrlist_map.size() > SPILLLEVEL)
        {
//
// Store the GDBM file in the name that's reserved for the first hard link
// link to the message file (which is never used).
//
            std::string gdbmname=namefile("D",1);

            if (addrlist_gdbm.Open(gdbmname.c_str(), "N"))
            {
                clog_msg_start_err();
                clog_msg_str(gdbmname.c_str());
                clog_msg_str(": ");
                clog_msg_errno();
            }

            std::set<std::string>::iterator b, e;

            for (b=addrlist_map.begin(),
                     e=addrlist_map.end(); b != e; ++b)
            {
                if (addrlist_gdbm.Store(*b, std::string(""),
                            "R"))
                    clog_msg_errno();
            }
            addrlist_map.clear();
        }
    }
    return (0);
}

void SubmitFile::AddReceipient(const char *r,
    const char *orig, const char *dsn, int delivered)
{
    // If # of receipients in the current control file exceeds the
    // defined batch size, close the current control file.

    if (rcptcount >= batchsize)
    {
        closectl();
//
// The first time we create another control file, rename the first
// control file to Cnnnn.1, which is a flag not to process Cnnnn.2, .3, etc...
//
// Cnnnn.2, .3, ... will be processed only after Cnnnn.1 is renamed to Cnnnn
//
        if (num_control_files_created == 1)
        {
            std::string p=name1stctlfile();
            std::string q=namefile("C", 1);

            if (rename(p.c_str(), q.c_str()))
            {
                clog_msg_start_err();
                clog_msg_str(p.c_str());
                clog_msg_str(" -> ");
                clog_msg_str(q.c_str());
                clog_msg_str(": ");
                clog_msg_errno();
            }
        }
    }

    // Open a new control file, if necessary.

    if (ctlfile.fd() < 0)
        openctl();
    ctlfile << COMCTLFILE_RECEIPIENT << r << std::endl
        << COMCTLFILE_ORECEIPIENT << (orig ? orig:"") << std::endl
        << COMCTLFILE_DSN << (dsn ? dsn:"") << std::endl;

    if (delivered)
    {
        ctlfile << COMCTLFILE_DELINFO << rcptcount << ' '
            << COMCTLFILE_DELINFO_REPLY
            << " 250 Ok - delivered to alias." << std::endl
            << COMCTLFILE_DELSUCCESS << rcptcount << ' '
                << submit_time << " r" << std::endl;
    }
    ctlfile << std::flush;
    ++rcptcount;
    if (bofh_chkspamtrap(r))
    {
        spamtrap_flag=1;
    }
}

//
//  Save original recipient list for recipient-specific filtering.
//

void SubmitFile::ReceipientFilter(struct rw_transport *rw,
        const char *host,
        const char *addr,
        unsigned rcptnum)
{

    if (rcptfilterlist_file.is_open())
    {
        rcptfilterlist_file
            << num_control_files_created - 1 << std::endl
            << rcptcount - 1 << std::endl
            << rw->name << std::endl
            << host << std::endl
            << addr << std::endl
            << rcptnum << std::endl;

        return;
    }

    rcptfilterlist.push_back(RcptFilterInfo());
    RcptFilterInfo &last_pos=rcptfilterlist.back();

    last_pos.num_control_file=num_control_files_created - 1;
    last_pos.num_receipient=rcptcount - 1;
    last_pos.driver=rw;
    last_pos.host=host;
    last_pos.address=addr;
    last_pos.rcptnum=rcptnum;

    if (rcptfilterlist.size() > SPILLLEVEL)
    {
        std::string filename=namefile("R", 0);

        rcptfilterlist_file.open(filename.c_str(),
                     std::ios::in | std::ios::out
                     | std::ios::trunc);
        if (!rcptfilterlist_file.is_open())
        {
            clog_msg_start_err();
            clog_msg_str(filename.c_str());
            clog_msg_str(": ");
            clog_msg_errno();
        }

        unlink(filename.c_str());    /* Immediately delete it */

        std::list<RcptFilterInfo>::iterator ab, ae;

        for (ab=rcptfilterlist.begin(),
                 ae=rcptfilterlist.end(); ab != ae; ++ab)
        {
            RcptFilterInfo &p= *ab;

            rcptfilterlist_file << p.num_control_file << std::endl
                << p.num_receipient << std::endl
                << p.driver->name << std::endl
                << p.host << std::endl
                << p.address << std::endl
                << p.rcptnum << std::endl;
        }
        rcptfilterlist.clear();
    }
}

void SubmitFile::openctl()
{
    std::string filename;

    ctlfile.close();
    if (num_control_files_created == 0)    // First recipient
    {
        for (;;)
        {
        const char *timeptr, *pidptr, *hostnameptr;

            getnewtmpfilenameargs(&timeptr, &pidptr,
                        &hostnameptr);

            filename=name1stctlfile();
            current_submit_file=this;

            int nfd=open(filename.c_str(),
                     O_WRONLY | O_TRUNC | O_CREAT | O_EXCL | O_APPEND,
                     PERMISSION);

            if (nfd >= 0)
              ctlfile.fd(nfd);

            if (nfd >= 0 || errno != EEXIST)
                break;
            current_submit_file=0;
            sleep(3);
        }
        ++num_control_files_created;

        if (ctlfile.fd() < 0)
        {
        //
        // One reason why we may not be able to create it
        // would be if the subdirectory, based on current time,
        // does not exist, so fork a tiny program to create it,
        // with the right permissions
        //

        pid_t p=fork();
        pid_t w;
        int wait_stat;

            if (p == -1)
            {
                clog_msg_start_err();
                clog_msg_str("fork: ");
                clog_msg_errno();
            }

            if (p == 0)
            {
                filename=std::string(filename.begin(),
                             std::find(filename.begin()
                                   , filename.end()
                                   , '/'));

                execl(LIBEXECDIR "/courier/submitmkdir",
                      "submitmkdir", filename.c_str(),
                      (char *)0);
                exit(0);
            }
            while ((w=wait(&wait_stat)) != p)
                if (w == -1 && errno == ECHILD)    break;

            int nfd=open(filename.c_str(),
                     O_WRONLY | O_TRUNC | O_CREAT | O_EXCL | O_APPEND,
                     PERMISSION);

            if (nfd >= 0)
              ctlfile.fd(nfd);
        }
    }
    else
    {
        ++num_control_files_created;
        filename=namefile("C", num_control_files_created);

        int nfd=open(filename.c_str(),
                 O_WRONLY | O_TRUNC | O_CREAT | O_EXCL | O_APPEND,
                 PERMISSION);

        if (nfd >= 0)
            ctlfile.fd(nfd);
    }
    if (ctlfile.fd() < 0)    clog_msg_errno();

struct    stat    stat_buf;
char    ino_buf[sizeof(ino_t)*2+1];

    if (fstat(ctlfile.fd(), &stat_buf) != 0)
        clog_msg_errno();

    rcptcount=0;
    if (num_control_files_created == 1)
    {
    char    time_buf[sizeof(time_t)*2+1];
    char    pid_buf[sizeof(time_t)*2+1];
    char    msgidbuf[sizeof(time_buf)+sizeof(pid_buf)];

        ctltimestamp=stat_buf.st_mtime;
        ctlpid=getpid();

        strcat(strcat(strcpy(msgidbuf,
            libmail_strh_time_t(ctltimestamp, time_buf)), "."),
            libmail_strh_pid_t(getpid(), pid_buf));

        basemsgid=msgidbuf;
        ctlinodenum=stat_buf.st_ino;
    }

    libmail_strh_ino_t( stat_buf.st_ino, ino_buf );

    ctlfile << COMCTLFILE_SENDER << sender << std::endl
        << COMCTLFILE_FROMMTA << frommta << std::endl
        << COMCTLFILE_ENVID << envid << std::endl
        << COMCTLFILE_DSNFORMAT << dsnformat << std::endl
        << COMCTLFILE_MSGID << ino_buf << '.' << basemsgid << std::endl;

    if (submitdelay)
        ctlfile << COMCTLFILE_SUBMITDELAY << submitdelay << std::endl;

    ctlfile << std::flush;
}

std::string SubmitFile::name1stctlfile()
{
    const char *timeptr, *pidptr, *hostnameptr;

    gettmpfilenameargs(&timeptr, &pidptr, &hostnameptr);

    std::string submit_filename_buf=timeptr;
    size_t l=submit_filename_buf.size();

    if (l > 4)
        submit_filename_buf=
            submit_filename_buf.substr(0, l-4);
    else
        submit_filename_buf="0";

    std::string n=submit_filename_buf + "/" + timeptr + "." + pidptr + "."
        + hostnameptr;

    all_files.insert(n);

    return n;
}

std::string SubmitFile::QueueID()
{
    char result[NUMBUFSIZE+1];

    libmail_strh_ino_t(ctlinodenum, result);

    return std::string(result) + "." + basemsgid;
}

std::string SubmitFile::namefile(const char *pfix, unsigned n)
{
char    buf[MAXLONGSIZE], *p;
const char *timeptr, *pidptr, *hostnameptr;

    gettmpfilenameargs(&timeptr, &pidptr, &hostnameptr);

    std::string submit_filename_buf=timeptr;

    size_t l=submit_filename_buf.size();

    if (l > 4)
        submit_filename_buf=
            submit_filename_buf.substr(0, l-4);
    else
        submit_filename_buf="0";

    submit_filename_buf = submit_filename_buf + "/" + pfix;

    p=buf+MAXLONGSIZE-1;

ino_t    inum=ctlinodenum;

    *p=0;
    do
    {
        *--p= '0' + (inum % 10);
        inum=inum/10;
    } while (inum);

    submit_filename_buf += p;

    if (n > 0)
    {
        p=buf+MAXLONGSIZE-1;
        *p=0;
        do
        {
            *--p= '0' + (n % 10);
            n=n/10;
        } while (n);
        submit_filename_buf = submit_filename_buf + "." + p;
    }

    all_files.insert(submit_filename_buf);
    return (submit_filename_buf);
}


// Process about to terminate.  Remove all possible files we might've
// created.

void SubmitFile::interrupt()
{
    if (!current_submit_file)    return;

    unlink(current_submit_file->name1stctlfile().c_str());
    if (current_submit_file->ctlinodenum == 0)    return;

unsigned    n;

    for (n=0; n<= 1 || n <= current_submit_file->num_control_files_created;
        n++)
        unlink(current_submit_file->namefile("D", n).c_str());

    n=current_submit_file->num_control_files_created;
    while ( n > 0)
    {
        unlink(current_submit_file->namefile("C", n).c_str());
        --n;
    }
}

//
// And now, process the message
//

void SubmitFile::MessageStart()
{
    bytecount=0;
    sizelimit=config_sizelimit();
    addrlist_map.clear();
    addrlist_gdbm.Close();
    if (ctlfile.fd() < 0)
        openctl();
    unlink(namefile("D", 1).c_str());    // Might be the GDBM file

    int nfd=open(namefile("D",0).c_str(),
             O_RDWR | O_CREAT | O_TRUNC, PERMISSION);
    if (nfd < 0)
    {
        clog_msg_start_err();
        clog_msg_str(namefile("D",0).c_str());
        clog_msg_str(": ");
        clog_msg_errno();
    }

    datfile.fd(nfd);

    rwrfcptr=rfc2045_alloc_ac();

    if (rwrfcptr == NULL)
        clog_msg_errno();
    diskfull=checkfreespace(&diskspacecheck);
}

void SubmitFile::Message(const char *p)
{
size_t    l=strlen(p);

    if (sizelimit && bytecount > sizelimit)    return;
    bytecount += l;
    if (sizelimit && bytecount > sizelimit)    return;

    if (diskfull)    return;
    datfile << p;
    if (l > diskspacecheck)
    {
        if (checkfreespace(&diskspacecheck))
        {
            diskfull=1;
            return;
        }
        diskspacecheck += l;
    }
    diskspacecheck -= l;

    if (datfile.fail())    clog_msg_errno();
    rfc2045_parse(rwrfcptr, p, strlen(p));
}

/* ------------ */

static int call_rfc2045_rewrite(struct rfc2045 *p, int fdin_arg, int fdout_arg,
                const char *appname)
{
    struct rfc2045src *src=rfc2045src_init_fd(fdin_arg);
    int rc;

    if (!src)
        return -1;

    rc=rfc2045_rewrite(p, src, fdout_arg, appname);
    rfc2045src_deinit(src);
    return rc;
}

int SubmitFile::MessageEnd(unsigned rcptnum, int iswhitelisted,
               int filter_enabled)
{
int    is8bit=0, dorewrite=0, rwmode=0;
const    char *mime=getenv("MIME");
unsigned    n;
struct    stat    stat_buf;

    if (sizelimit && bytecount > sizelimit)
    {
        std::cout << "523 Message length (" <<
            sizelimit << " bytes) exceeds administrative limit."
            << std::endl << std::flush;
        return (1);
    }

    if (diskfull)
    {
        std::cout << "431 Mail system full." << std::endl << std::flush;
        return (1);
    }

    if (spamtrap_flag)
    {
        std::cout << "550 Spam refused." << std::endl << std::flush;
        return (1);
    }

    if (rwrfcptr->rfcviolation & RFC2045_ERR2COMPLEX)
    {
                std::cout <<
                   "550 Message MIME complexity exceeds the policy maximum."
             << std::endl << std::flush;
        return (1);
    }

    datfile << std::flush;
    if (datfile.fail())    clog_msg_errno();

    ctlfile << std::flush;
    if (ctlfile.fail())    clog_msg_errno();

    /* Run global filters for this message */

    std::string dfile=namefile("D", 0);

    if (!mime || strcmp(mime, "none"))
    {
        if (mime && strcmp(mime, "7bit") == 0)
        {
            rwmode=RFC2045_RW_7BIT;
            is8bit=0;
        }
        if (mime && strcmp(mime, "8bit") == 0)
            rwmode=RFC2045_RW_8BIT;
        if (rfc2045_ac_check(rwrfcptr, rwmode))
            dorewrite=1;
    }
    else
        (void)rfc2045_ac_check(rwrfcptr, 0);

    if (rwrfcptr->has8bitchars)
        is8bit=1;

    unlink(namefile("D", 1).c_str());    // Might be the GDBM file
                    // if receipients read from headers.
    if (dorewrite)
    {
        int    fd1=dup(datfile.fd());
        int    fd2;

        if (fd1 < 0)    clog_msg_errno();
        datfile.close();
        if (datfile.fail())    clog_msg_errno();

        if ((fd2=open(namefile("D", 1).c_str(),
            O_RDWR|O_CREAT|O_TRUNC, PERMISSION)) < 0)
            clog_msg_errno();

        if (call_rfc2045_rewrite(rwrfcptr, fd1, fd2,
                     PACKAGE " " VERSION))
        {
            clog_msg_errno();
            std::cout << "431 Mail system full." << std::endl << std::flush;
            return (1);
        }
        close(fd1);

#if    EXPLICITSYNC
        fsync(fd2);
#endif
        fstat(fd2, &stat_buf);
        close(fd2);

        std::string p=namefile("D", 0);

        unlink(p.c_str());
        if (rename(namefile("D", 1).c_str(), p.c_str()) != 0)
            clog_msg_errno();
    }
    else
    {
        datfile.sync();
#if EXPLICITSYNC
        fsync(datfile.fd());
#endif
        fstat(datfile.fd(), &stat_buf);
        datfile.close();
        if (datfile.fail())    clog_msg_errno();
    }
    if (is8bit)
    {
        ctlfile << COMCTLFILE_8BIT << "\n" << std::flush;
        closectl();

        if (num_control_files_created > 1)
        {
            for (n=1; n < num_control_files_created; n++)
            {
                std::string p=namefile("C", n);

                int nfd=open(p.c_str(), O_WRONLY | O_APPEND);

                if (nfd < 0)    clog_msg_errno();
                ctlfile.fd(nfd);
                ctlfile << COMCTLFILE_8BIT << "\n" << std::flush;
                if (ctlfile.fail())    clog_msg_errno();
#if EXPLICITSYNC
                ctlfile.sync();
                fsync(ctlfile.fd());
#endif
                ctlfile.close();
                if (ctlfile.fail())    clog_msg_errno();
            }
        }
    }
    else
    {
        closectl();
    }

    SubmitFile *voidp=this;

    if (filter_enabled &&
        run_filter(dfile.c_str(), num_control_files_created,
               iswhitelisted,
               &SubmitFile::get_msgid_for_filtering, &voidp))
        return (1);

    std::string cfile=namefile("C", 0);

    for (n=2; n <= num_control_files_created; n++)
    {
        if (link(dfile.c_str(), namefile("D", n).c_str()) != 0)
            clog_msg_errno();
    }

    std::string okmsg("250 Ok. ");

    okmsg += basemsgid;

    int    hasxerror=datafilter(dfile.c_str(), rcptnum, okmsg.c_str());

    current_submit_file=0;
    if (num_control_files_created == 1)
    {
        if (rename(name1stctlfile().c_str(), cfile.c_str()) != 0)
            clog_msg_errno();
    }
    else
    {
        if (rename(namefile("C", 1).c_str(), cfile.c_str()) != 0)
            clog_msg_errno();
    }

    if (!hasxerror)
    {
#if EXPLICITDIRSYNC
        int p=cfile.ReverseFind('/');

        if (p >= 0)
        {
            std::string dir=cfile.substr(0, p);

            int fd=open(dir.c_str(), O_RDONLY);

            if (fd >= 0)
            {
                fsync(fd);
                close(fd);
            }
        }
#endif

        std::cout << okmsg << std::endl << std::flush;
    }

    trigger(TRIGGER_NEWMSG);
    return (0);
}

std::string SubmitFile::get_msgid_for_filtering(unsigned n, void *p)
{
    SubmitFile *objptr= *(SubmitFile **)p;
    std::string ctlname(TMPDIR "/");

    if (objptr->num_control_files_created == 1)
        ctlname += objptr->name1stctlfile();
    else
        ctlname += objptr->namefile("C", n+1);

    return (ctlname);
}

static void print_xerror(const char *address, const char *errbuf, int isfinal)
{
unsigned    c;
const char *p;
int    errcode=0;

    do
    {
        for (c=0; errbuf[c] && errbuf[c] != '\n'; c++)
            ;
        p=errbuf;
        errbuf += c;
        if (*errbuf)    ++errbuf;

        if (!errcode)
        {
            if (c > 3 && p[0] >= '2' && p[0] <= '5' &&
                p[1] >= '0' && p[1] <= '9' &&
                p[2] >= '0' && p[2] <= '9')
                errcode= (p[0] - '0') * 100 +
                    (p[1] - '0') * 10 + p[2] - '0';
            else
                errcode=450;
        }
        if (c > 4 &&  p[0] >= '2' && p[0] <= '5' &&
            p[1] >= '0' && p[1] <= '9' &&
            p[2] >= '0' && p[2] <= '9' &&
            (p[3] == ' ' || p[3] == '-'))
        {
            p += 4;
            c -= 4;
        }
        if (address)
        {
            std::cout << "558-" << errcode << "-"
                << address << ":" << std::endl;
            address=0;
        }
        std::cout << (( *errbuf == 0 && isfinal) ? "558 ":"558-")
            << errcode << (*errbuf == 0 ? " ":"-");
        std::cout.write(p, c);
        std::cout << std::endl;
    } while (*errbuf);
}

//
// SubmitFile::datafilter runs recipient-specific filters.  This function
// will generate a data extended error message if any recipient's filters
// reject the message.  Each rejection results in the control file being
// reopened and appended a delivery record for the failed recipients, so
// we don't actually try to deliver the message to this address (the addy
// is officially rejected).
//

int SubmitFile::datafilter(const char *datfilename, unsigned nrcpts,
                const char *okmsg)
{
int    fd=open(datfilename, O_RDONLY);
unsigned last_error=0;
int    flag=0;

    if (fd < 0)    clog_msg_errno();

    if (rcptfilterlist_file.is_open())
    {
        // List of receipients was large enough to be dumped into a
        // file.

        rcptfilterlist_file.seekg(0);
        if (rcptfilterlist_file.bad())
            clog_msg_errno();

        // Read recipient list from the dump file, and filter each
        // one.

        RcptFilterInfo r;
        struct rw_transport *rw;
        std::string buf;

        while (!std::getline(rcptfilterlist_file, buf).fail())
        {
            if (sscanf(buf.c_str(), "%u",
                   &r.num_control_file) != 1
                || std::getline(rcptfilterlist_file, buf).fail()
                || sscanf(buf.c_str(), "%u",
                      &r.num_receipient) != 1
                || std::getline(rcptfilterlist_file, buf).fail())
                clog_msg_errno();

            for (rw=rw_transport_first; rw; rw=rw->next)
                if (rw->name == buf)
                    break;
            if (!rw)    clog_msg_errno();
            r.driver=rw;
            if ( std::getline(rcptfilterlist_file, r.host).fail()
                 || std::getline(rcptfilterlist_file,
                         r.address).fail()
                 || std::getline(rcptfilterlist_file, buf).fail()
                 || sscanf(buf.c_str(), "%u",
                       &r.rcptnum) != 1)
                clog_msg_errno();

            do_datafilter(last_error, flag, fd,
                      r.driver,
                      r.host,
                      r.address,
                      r.rcptnum,

                      r.num_control_file,
                      r.num_receipient,

                      okmsg, nrcpts);
        }
        if ( rcptfilterlist_file.bad())
            clog_msg_errno();
        rcptfilterlist_file.close();
    }
    else
    {
        std::list<RcptFilterInfo>::iterator ab, ae;

        for (ab=rcptfilterlist.begin(),
                 ae=rcptfilterlist.end(); ab != ae; ++ab)
        {
            RcptFilterInfo &r= *ab;

            do_datafilter(last_error, flag, fd,
                      r.driver,
                      r.host,
                      r.address,
                      r.rcptnum,

                      r.num_control_file,
                      r.num_receipient,

                      okmsg, nrcpts);
        }
    }
    close(fd);
    while (last_error && last_error < nrcpts)
    {
        print_xerror(0, okmsg, ++last_error == nrcpts);
    }
    std::cout << std::flush;
    return (flag);
}

// This is where the dirty work of running a filter actually happens.
// We get here whether the list of recipients was small enough to fit
// into memory, or not.

void SubmitFile::do_datafilter( unsigned &last_error, int &flag, int fd,
                struct rw_transport *driver,
                std::string host,
                std::string address,
                unsigned rcptnum,

    unsigned num_control_file,
    unsigned num_receipient,

    const char *okmsg,
    unsigned nrcpts)
{
char    buf[2048];
int    ctf;
int    rc;

    if (driver->rw_ptr->filter_msg == 0)    return;

    buf[0]=0;

    if (lseek(fd, 0L, SEEK_SET) < 0)
        clog_msg_errno();

    // Call the driver's filter function.

    rc=driver->rw_ptr->filter_msg
        ? (*driver->rw_ptr->filter_msg)(sending_module, fd,
                        host.c_str(),
                        address.c_str(),
                        sender.c_str(),
                        buf, sizeof(buf)):0;
    if (rc == 0)    return;

    if (buf[0] == 0)    // Error but no msg, make one up
        strcpy(buf, "Access denied.");

    ctf=open ( (num_control_files_created == 1 ?
            name1stctlfile(): namefile( "C", num_control_file+1))
           .c_str(), O_WRONLY|O_APPEND);
    if (ctf < 0)    clog_msg_errno();

    /*
    ** Mark the recipient as delivered, so no more processing is
    ** done.
    */
    ctlfile_append_replyfd(ctf, num_receipient,
        buf, COMCTLFILE_DELSUCCESS, 0);
    close(ctf);

    /*
    ** We are now required to return an EXDATA extended error.  If there
    ** were any good recipients up until now, we need to return an OK
    ** message for those recipients.
    */

    while (last_error < rcptnum)
    {
        print_xerror(0, okmsg, 0);
        ++last_error;
    }

    print_xerror( address.c_str(), buf, rcptnum + 1 == nrcpts);
    ++last_error;
    flag=1;
}

static RETSIGTYPE sighandler(int signum)
{
    SubmitFile::interrupt();
    signal(SIGINT, SIG_DFL);
    kill(getpid(), SIGKILL);
#if    RETSIGTYPE != void
    return (0);
#endif
}

void SubmitFile::trapsignals()
{
    signal(SIGINT, sighandler);
    signal(SIGTERM, sighandler);
    signal(SIGHUP, sighandler);
    signal(SIGALRM, sighandler);
    if (atexit(SubmitFile::interrupt)) clog_msg_errno();
}
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.372 seconds