Archive for June 5th, 2009

5
Jun

Sendmail filter

   Posted by: admin    in Mẹo vặt của hiếu râu

/* ————————————————————
 *      “FilterRules” feature to log any message through this MTA
 *      (c) /Invisible VR Corp. 2001
 *
 *      ABSTRACT
 *      This routine sends every message which match the FilterRules.
 *
 *      IMPLEMENTATION
 *      The FilterRules code is compiled into the sendmail binary.
 *      To check whether a message was already filtered it writes
 *      log in /var/log/filter.log
 *
 *      CONFIGURATION
 *      The FilterRules is configuerd in /etc/sendmail.fil as:
 *      <Sender> <Recipient> <Subject> <SendTo>
 *
 *      ———-/etc/sendmail.fil example:————-
 *      a@a.com         b@b.com         *                       c@c.com
 *      *               *               This|is|the|Rules       d@d.com
 *      *               e@e.com         *                       d@d.com
 *      *               *               *                       f@f.com
 *      *               *               Love|letter|for|you     #!virusbox@antivirus.com
 *      *               *               *                       *
 *      —————— END ————————–
 *      That means :
 *              1/ If From a@a.com To b@b.com then send the
 *                 message to c@c.com
 *              2/ If the subject content “This is the Rules” then
 *                 send the message to d@d.com
 *              3/ If the recipient is e@e.com then send the
 *                 message to d@d.com
 *              4/ Send all message to f@f.com
 *              5/ If the subject content “Love letter for you” then
 *                 - Drop(!) the message and send a copy to virusbox@antivirus.com
 *                 - Ignore(#) other rules. It scans from the bottom to top.
 *              6/ Enable Log function, It writes activities log
 *                 to /var/log/filter.log
 *
 *
 *
 *
 *      COMPATIBILITY
 *      FilterRules is tested with sendmail-8.8.5 and sendmail-8.11.2
 *      under Linux RedHat 7.1
 *
 *      AUTHOR
 *      Hieu Nguyen Trung - hieu@vpnvietnam.com
 *
 *      LICENSE/WARRANTY
 *      The software is provided “AS IS” without warranties of any kind,
 *      either expressed or implied, including, but not limited to the
 *      implied warranties of merchantability and fitness for a particular
 *      purpose. The entire risc of the software is with you. In no event
 *      we will be liable for any damages, including any lost profits,
 *      lost savings or other incidental damages arising out of the use
 *      or inability to use the software, even if we have been advised
 *      of the possibility of such damages, or for any claim by another party.
 *
 *      INSTALLATION
 *      This source fragment must be included into the source-file:
 *      …/sendmail-8.x.y/src/srvrsmtp.c
 *      at the following position
 *
 *      the sendmail binary must be remaked and reinstalled at
 *      its proper position (normally /usr/sbin/sendmail).
 * —————————————————————
 */

 

/* Insert [-My Filter Code-] before these lines
 *
 *      SmtpPhase = “delivery”;
 *      (void) bftruncate(e->e_xfp);
 *
 */
// —————- My Filter Code———————
        my_filter(e);

        if (clearlist)
        for (a = e->e_sendqueue; a != NULL; a = a->q_next)
        {
            /* make this “go away” */
                a->q_state = QS_REMOVED;
        }

        while (sendtos!=NULL)
        {
            a = parseaddr(sendtos->sendto, NULLADDR, RF_COPYALL, ‘ ‘, &delimptr, e);
            if (a != NULL )
            a = recipient(a, &e->e_sendqueue, 0, e);
            pst=sendtos;
            sendtos=sendtos->next;
            free(pst);
        }
//—————-End My Filter ———————————

 

/* And Insert All The below Codes before these lines
 *
 *      void smtp(nullserver, d_flags, e)
 *      char *volatile nullserver;
 *      register ENVELOPE *volatile e;
 */
//———————- Insert this —————————-

struct filter //Rules List
{
        char subject[200];
        char from[100];
        char to[100];
        char sendto[100];
        struct filter * next;
};
typedef struct filter FILTER;

struct sendto //Sendtos List
{
        char sendto[100];
        struct sendto * next;
};
typedef struct sendto SENDTO;

SENDTO * sendtos, * pst;
FILTER * filters;
bool clearlist;
^Mbool exitrule;
bool fdebug;

//Add Rule to Rules List
void addchains(char *sfrom,char *sto,char *ssubject,char *ssendto)
{
        FILTER *p;
        p = (FILTER *)malloc(520);
        if (p==NULL) return;
        strcpy(p->subject,ssubject);
        strcpy(p->from,sfrom);
        strcpy(p->to,sto);
        strcpy(p->sendto,ssendto);
        p->next=filters;
        filters=p;
}

void deletechains(void) //Delete Rules List
{
        FILTER *p;
        while (filters!=NULL)
        {
                p=filters;
                filters=filters->next;
                free(p);
        }
}

void sendlist(receipient) // Add Matchs to sendtos list
    char *receipient;
{
    SENDTO *r;
    char *p;
    p = strchr(receipient,’#');
    if (p != NULL)
    {
        receipient++;
        exitrule=TRUE;
    }
    p = strchr(receipient,’!');
    if (p != NULL)
    {
        receipient++;
        clearlist=TRUE;
    }

    r = (SENDTO *)malloc(120);
    if (r==NULL) return;
    strcpy(r->sendto,receipient);
    r->next=sendtos;
    sendtos=r;
}
void cmpchains(e,fdebug) //Scan Rules
    ENVELOPE *volatile e;
    bool fdebug;
{
        ADDRESS *b,*c;
        HDR *h;
        char *delimptr;
        FILTER *p;
        char subject[200]=”-None-”;
        time_t t;
        FILE *logfile;
        for (h = e->e_header; h != NULL; h = h->h_link)
        {       //Get subject from HDR
            if (strcasecmp(h->h_field,”subject”)==0) strcpy(subject,h->h_value);
        }
        if (fdebug)
        {       //Open Log File
            logfile = fopen(”/var/log/filter.log”,”a”);
            if (logfile == NULL ) fdebug=FALSE;
        }

        if (fdebug)
        {
            time(&t);
            fprintf(logfile,”\n\nDate :  %s”,ctime(&t));
            fprintf(logfile,”Message From:[%s] To:[%s] Subject:[%s]\n”,
                e->e_sender,e->e_sendqueue->q_paddr,subject);
        }

        for (p=filters;p!=NULL;p=p->next)
        {       //Scan Rules
            if (fdebug)
                fprintf(logfile,”Filter  From:[%s] To:[%s] Subject:[%s]\n”,
                p->from,p->to,p->subject);
            if (strcmp(p->from,”*”))
            if (strstr(e->e_sender,p->from)==NULL) continue;
            //Match FROM
            if  (strcmp(p->subject,”*”))
            if (strstr(subject,p->subject)==NULL) continue;
            //Match Subject
            if (strcmp(p->to,”*”)==0)
            {
                sendlist(p->sendto);
                if (fdebug)
                {
                    fprintf(logfile,”     Match [ALL] Sendto:[%s]\n”,p->sendto);
                    if (exitrule)
                    fprintf(logfile,”     SigTerm(#) found. Ignore other rules.\n”);^M
                }
            }
            else
            for (b = e->e_sendqueue; b != NULL; b = b->q_next)
            {
                if (strstr(b->q_paddr,p->to)==NULL) continue;
                sendlist(p->sendto);
                if (fdebug)
                {
                    fprintf(logfile,”     Match To:[%s] Sendto:[%s]\n”,
                    b->q_paddr,p->sendto);
                    if (exitrule)
                    fprintf(logfile,”     SigTerm(#) found. Ignore other rules.\n”);^M
                }
                break;
            }
            if (exitrule)
                break;
        }

        if (fdebug) fclose(logfile);
}

 

void my_filter(e) //My filter
    ENVELOPE *volatile e;
{

    int handle,i;
    char sFrom[100],sTo[100],sSubject[200],sSendto[100];
    FILE *stream;

    fdebug=FALSE;
    exitrule=FALSE;
    clearlist=FALSE;
    filters= NULL;
    handle = open(”/etc/sendmail.fil”,O_CREAT|S_IREAD);
    stream = fdopen(handle,”r”);
    if (stream == NULL ) return;
    while (fscanf(stream,”%s %s %s %s”,sFrom,sTo,sSubject,sSendto)==4)
    {
        if (strcmp(sSendto,”*”)==0)
        {
            fdebug=TRUE;
            continue;
        }
        //convert Subject “This|is|the|subject” -> “This is the subject”
        for (i=0;i<strlen(sSubject);i++) if (sSubject[i]==’|') sSubject[i]=’ ‘;
        addchains(sFrom,sTo,sSubject,sSendto);
    }
    cmpchains(e,fdebug);
    deletechains();
    fclose(stream);
}

// ————————-END———————-