/*
 * noattach.c - libmilter filter to reject incoming messages with
 *              specific attachments.
 *
 * Currently rejects VBS, SHS, and DLL attachments.
 *
 * Adapted from filter code written by Al Smith <Al.Smith@aeschi.ch.eu.org>
 *
 * Catches mixed case MIME filename labels.  Identified by:
 *   Brett Glass  <brett@lariat.org> and
 *   Jason Storm  <jms@negation.net>
 */
#include <string.h>
#include "libmilter/mfapi.h"

static int bad_extension(SMFICTX *ctx, const char *s1, const char *s2, int len) {
   int n;
   const char *p, *q;
   char x, y;
   char m[1024];

   sprintf (m, "Sorry, I can't accept messages with .%s attachments.", s2);

   n = 0;
   for (p=s1, q=s2; *p && *q && n < len; p++, q++) {
      x = (isalpha((int)*p)) ? tolower(*p) : *p;
      y = (isalpha((int)*q)) ? tolower(*q) : *q;

      if ( x == y )
         n++;
   }

   if (n != len)
      return (0);

   smfi_setreply(ctx, "554", "5.6.1", m);
   return (1);
}

sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t bodylen) {
   u_char *p, *q, *r;

   /* check body block for vbs data */
   for(p = bodyp; p && (p = strstr(p, "Content-Type:")); p++) {
      /* convert to lowercase */
      q = p;
      while (*q) {
         *q = tolower(*q);
         q++;
      }
      if ((q = strstr(p, "name=\""))) {
         for(r=q+6; *r != '\n' && *r != '\0' && *r != '"'; r++);
            if (*r == '"') {
               /* Filter for bad extensions */
               if (bad_extension(ctx, r-3, "vbs", 3))  return SMFIS_REJECT;
               if (bad_extension(ctx, r-3, "shs", 3))  return SMFIS_REJECT;
               if (bad_extension(ctx, r-3, "dll", 3))  return SMFIS_REJECT;
            }
      }
   }

   /* continue processing */
   return SMFIS_CONTINUE;
}

struct smfiDesc smfilter = {
   "VBFilter", 		/* filter name */
   SMFI_VERSION, 	/* version code -- do not change */
   0,  			/* flags */
   NULL,  		/* connection info filter */
   NULL,  		/* SMTP HELO command filter */
   NULL,  		/* envelope sender filter */
   NULL,  		/* envelope recipient filter */
   NULL,  		/* header filter */
   NULL,  		/* end of header */
   mlfi_body, 		/* body block filter */
   NULL,  		/* end of message */
   NULL,  		/* message aborted */
   NULL  		/* connection cleanup */
};


int main(int argc, char *argv[]) {
   char c;
   const char *args = "p:";

   /* Process command line options */
   while ((c = getopt(argc, argv, args)) != -1) {
      switch (c) {
         case 'p':
            if (optarg == NULL || *optarg == '\0') {
               (void) fprintf(stderr, "Illegal conn: %s\n", optarg);
               exit(EX_USAGE);
            }
            (void) smfi_setconn(optarg);
            break;

      }
   }

   if (smfi_register(smfilter) == MI_FAILURE) {
      fprintf(stderr, "smfi_register failed\n");
      exit(EX_UNAVAILABLE);
   }
   return smfi_main();
}
