[exim-cvs] cvs commit: exim/exim-src/src malware.c

Góra strony
Delete this message
Reply to this message
Autor: Tom Kistner
Data:  
Dla: exim-cvs
Temat: [exim-cvs] cvs commit: exim/exim-src/src malware.c
tom 2008/03/27 13:16:53 GMT

  Modified files:
    exim-src/src         malware.c 
  Log:
  Bugzilla 673: merge f-protd support, courtesy of Mark Daniel Reidel <mr@???>


  Revision  Changes    Path
  1.16      +108 -1    exim/exim-src/src/malware.c


  Index: malware.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/malware.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- malware.c    6 Jul 2006 14:19:50 -0000    1.15
  +++ malware.c    27 Mar 2008 13:16:52 -0000    1.16
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/malware.c,v 1.15 2006/07/06 14:19:50 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/malware.c,v 1.16 2008/03/27 13:16:52 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -139,10 +139,117 @@
         return DEFER;
       };


  +  /* "f-protd" scanner type ----------------------------------------------- */
  +  if (strcmpic(scanner_name, US"f-protd") == 0) {
  +    uschar *fp_options, *fp_scan_option;
  +    uschar fp_scan_option_buffer[1024];
  +    uschar fp_options_buffer[1024];
  +    uschar fp_options_default[] = "localhost 10200-10204";
  +    uschar hostname[256];
  +    unsigned int port, portlow, porthigh, connect_ok=0, detected=0, par_count = 0;
  +    struct hostent *he;
  +    struct in_addr in;
  +    int sock;
  +    uschar scanrequest[2048], buf[32768], *strhelper, *strhelper2;
  +
  +    if ((fp_options = string_nextinlist(&av_scanner_work, &sep,
  +      fp_options_buffer, sizeof(fp_options_buffer))) == NULL) {
  +      /* no options supplied, use default options */
  +      fp_options = fp_options_default;
  +    };
  +
  +    /* extract host and port part */
  +    if ( sscanf(CS fp_options, "%s %u-%u", hostname, &portlow, &porthigh) != 3 ) {
  +      if ( sscanf(CS fp_options, "%s %u", hostname, &portlow) != 2 ) {
  +        log_write(0, LOG_MAIN|LOG_PANIC,
  +          "malware acl condition: f-protd: invalid socket '%s'", fp_options);
  +        return DEFER;
  +      }
  +      porthigh = portlow;
  +    }
  +
  +    /* Lookup the host */
  +    if((he = gethostbyname(CS hostname)) == 0) {
  +      log_write(0, LOG_MAIN|LOG_PANIC,
  +        "malware acl condition: f-protd: failed to lookup host '%s'", hostname);
  +      return DEFER;
  +    }
  +
  +    in = *(struct in_addr *) he->h_addr_list[0];
  +    port = portlow;
  +
  +
  +    /* Open the f-protd TCP socket */
  +    if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
  +      log_write(0, LOG_MAIN|LOG_PANIC,
  +        "malware acl condition: f-protd: unable to acquire socket (%s)",
  +        strerror(errno));
  +      return DEFER;
  +    }
  +
  +    /* Try to connect to all portslow-high until connection is established */
  +    for (port = portlow; !connect_ok && port < porthigh; port++) {
  +      if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) >= 0) {
  +        connect_ok = 1;
  +      }
  +    }
  +
  +    if ( !connect_ok ) {
  +      log_write(0, LOG_MAIN|LOG_PANIC,
  +        "malware acl condition: f-protd: connection to %s, port %u-%u failed (%s)",
  +        inet_ntoa(in), portlow, porthigh, strerror(errno));
  +      (void)close(sock);
  +      return DEFER;
  +    }
  +
  +    (void)string_format(scanrequest, 1024, CS"GET %s/scan/%s/%s.eml",
  +          spool_directory, message_id, message_id);
  +
  +    while ((fp_scan_option = string_nextinlist(&av_scanner_work, &sep,
  +      fp_scan_option_buffer, sizeof(fp_scan_option_buffer))) != NULL) {
  +      if ( par_count ) {
  +        Ustrcat(scanrequest, "%20");
  +      } else {
  +        Ustrcat(scanrequest, "?");
  +      }
  +      Ustrcat(scanrequest, fp_scan_option);
  +      par_count++;
  +    }
  +    Ustrcat(scanrequest, " HTTP/1.0\r\n\r\n");
  +
  +    /* send scan request */
  +    if (send(sock, &scanrequest, Ustrlen(scanrequest)+1, 0) < 0) {
  +      (void)close(sock);
  +      log_write(0, LOG_MAIN|LOG_PANIC,
  +        "malware acl condition: f-protd: unable to send command to socket (%s)", scanrequest);
  +      return DEFER;
  +    }
  +
  +    /* We get a lot of empty lines, so we need this hack to check for any data at all */
  +    while( recv(sock, buf, 1, MSG_PEEK) > 0 ) {
  +      if ( recv_line(sock, buf, 32768) > 0) {
  +        if ( Ustrstr(buf, US"<detected type=\"") != NULL ) {
  +          detected = 1;
  +        } else if ( detected && (strhelper = Ustrstr(buf, US"<name>")) ) {
  +          if (strhelper2 = Ustrstr(buf, US"</name>")) {
  +            *strhelper2 = '\0';
  +            Ustrcpy(malware_name_buffer, strhelper + 6);
  +          }
  +        } else if ( Ustrstr(buf, US"<summary code=\"") ) {
  +          if ( Ustrstr(buf, US"<summary code=\"11\">") ) {
  +            malware_name = malware_name_buffer;
  +          } else {
  +            malware_name = NULL;
  +          }
  +        }
  +      }
  +    }
  +    (void)close(sock);
  +  }
     /* "drweb" scanner type ----------------------------------------------- */
     /* v0.1 - added support for tcp sockets          */
     /* v0.0 - initial release -- support for unix sockets      */
  -  if (strcmpic(scanner_name,US"drweb") == 0) {
  +  else if (strcmpic(scanner_name,US"drweb") == 0) {
       uschar *drweb_options;
       uschar drweb_options_buffer[1024];
       uschar drweb_options_default[] = "/usr/local/drweb/run/drwebd.sock";