Refactor listarg RE compiles
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 3 Feb 2014 00:19:23 +0000 (00:19 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 3 Feb 2014 00:19:23 +0000 (00:19 +0000)
src/src/malware.c

index b72253e7b87cc72f759d8d62c0db7e67cc798c62..ba62e103b0cd05d4d02ccb12136f90cd0a15afef 100644 (file)
@@ -62,8 +62,7 @@ test_byte_order()
   return(byte[0] ? LITTLE_MY_ENDIAN : BIG_MY_ENDIAN);
 }
 
-static uschar * malware_name_internal = NULL;
-int malware_ok = 0;
+BOOL malware_ok = FALSE;
 
 /* Gross hacks for the -bmalware option; perhaps we should just create
 the scan directory normally for that case, but look into rigging up the
@@ -362,6 +361,19 @@ m_pcre_exec(const pcre * cre, uschar * text)
   return substr;
 }
 
+static const pcre *
+m_pcre_nextinlist(uschar ** list, int * sep, char * listerr, uschar ** errstr)
+{
+  const uschar * list_ele;
+  const pcre * cre = NULL;
+
+  if (!(list_ele = string_nextinlist(list, sep, NULL, 0)))
+    *errstr = US listerr;
+  else
+    cre = m_pcre_compile(CS list_ele, errstr);
+  return cre;
+}
+
 /*************************************************
 *          Scan content for malware              *
 *************************************************/
@@ -416,12 +428,12 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
   const uschar * scanner_options;
 
   /* make sure the eml mbox file is spooled up */
-  mbox_file = spool_mbox(&mbox_size, faking ? eml_filename : NULL);
-  if (mbox_file == NULL)  /* error while spooling */
+  if (!(mbox_file = spool_mbox(&mbox_size, faking ? eml_filename : NULL)))
     return malware_errlog_defer("error while creating mbox spool file");
 
   /* none of our current scanners need the mbox
      file as a stream, so we can close it right away */
+  /*XXX drweb and clamd do!! */
   (void)fclose(mbox_file);
 
   /* extract the malware regex to match against from the option list */
@@ -429,17 +441,14 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
     /* parse 1st option */
     if ( (strcmpic(malware_regex,US"false") == 0) ||
-         (Ustrcmp(malware_regex,"0") == 0) ) {
-      /* explicitly no matching */
-      return FAIL;
-    }
+         (Ustrcmp(malware_regex,"0") == 0) )
+      return FAIL;             /* explicitly no matching */
 
     /* special cases (match anything except empty) */
     if ( (strcmpic(malware_regex,US"true") == 0) ||
          (Ustrcmp(malware_regex,"*") == 0) ||
-         (Ustrcmp(malware_regex,"1") == 0) ) {
+         (Ustrcmp(malware_regex,"1") == 0) )
       malware_regex = malware_regex_default;
-    }
   }
   else /* empty means "don't match anything" */
     return FAIL;
@@ -453,21 +462,19 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
   /* if av_scanner starts with a dollar, expand it first */
   if (*av_scanner == '$') {
-    av_scanner_work = expand_string(av_scanner);
-    if (!av_scanner_work)
+    if (!(av_scanner_work = expand_string(av_scanner)))
       return malware_errlog_defer(
            string_sprintf("av_scanner starts with $, but expansion failed: %s",
           expand_string_message));
-    else {
-      debug_printf("Expanded av_scanner global: %s\n", av_scanner_work);
-      /* disable result caching in this case */
-      malware_name = NULL;
-      malware_ok = 0;
-    }
+
+    debug_printf("Expanded av_scanner global: %s\n", av_scanner_work);
+    /* disable result caching in this case */
+    malware_name = NULL;
+    malware_ok = FALSE;
   }
 
   /* Do not scan twice. */
-  if (malware_ok == 0) {
+  if (!malware_ok) {
 
     /* find the scanner type from the av_scanner option */
     if (!(scanner_name = string_nextinlist(&av_scanner_work, &sep, NULL, 0)))
@@ -491,6 +498,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        int sock;
        uschar * scanrequest;
        uschar buf[32768], *strhelper, *strhelper2;
+       uschar * malware_name_internal = NULL;
 
        if ((sock = m_tcpsocket_fromdef(scanner_options, &errstr)) < 0)
          return fprotd_errlog_defer(errstr);
@@ -512,7 +520,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
        /* 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 ( recv_line(sock, buf, sizeof(buf)) > 0) {
            if ( Ustrstr(buf, US"<detected type=\"") != NULL )
              detected = 1;
            else if ( detected && (strhelper = Ustrstr(buf, US"<name>")) ) {
@@ -614,8 +622,9 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
              string_sprintf("unable to send file body to socket (%s)", scanner_options));
          }
          (void)close(drweb_fd);
-       }
-       else {
+
+       } else {
+
          if((sock = m_unixsocket(scanner_options, &errstr)) < 0)
            return drweb_errlog_defer(errstr);
 
@@ -657,8 +666,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          int i;
 
          /* setup default virus name */
-         malware_name_internal = "unknown";
-         malware_name = malware_name_internal;
+         malware_name = "unknown";
 
          /* set up match regex */
          drweb_re = m_pcre_compile( "infected\\swith\\s*(.+?)$", &errstr);
@@ -690,14 +698,13 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
              pcre_get_substring(CS tmpbuf, ovector, result, 1, &pre_malware_nb);
 
-             /* the first name we just copy to malware_name */
-             if (i==0)
-               malware_name_internal = string_append(NULL, &size, &off,
+             if (i==0) /* the first name we just copy to malware_name */
+               malware_name = string_append(NULL, &size, &off,
                                            1, pre_malware_nb);
-             else
-               /* concatenate each new virus name to previous */
-               malware_name_internal = string_append(malware_name_internal,
-                                           &size, &off, 2, "/", pre_malware_nb);
+
+             else      /* concatenate each new virus name to previous */
+               malware_name = string_append(malware_name, &size, &off,
+                                           2, "/", pre_malware_nb);
 
              pcre_free_substring(pre_malware_nb);
            }
@@ -763,26 +770,20 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          debug_printf("aveserver: %s\n", buf);
          if (buf[0] == '2')
            break;
-         if (buf[0] == '5') {
-           /* aveserver is having problems */
-           log_write(0, LOG_MAIN|LOG_PANIC,
-              "malware acl condition: unable to scan file %s (Responded: %s).",
-              eml_filename, buf);
-           result = DEFER;
+         if (buf[0] == '5') {          /* aveserver is having problems */
+           result = aves_errlog_defer(
+              string_sprintf("unable to scan file %s (Responded: %s).",
+                              eml_filename, buf));
            break;
          } else if (Ustrncmp(buf,"322",3) == 0) {
            uschar *p = Ustrchr(&buf[4],' ');
            *p = '\0';
-           malware_name_internal = string_copy(&buf[4]);
-           malware_name = malware_name_internal;
+           malware_name = string_copy(&buf[4]);
          }
        }
 
-       /* prepare our command */
-       (void)string_format(buf, sizeof(buf), "quit\r\n");
-
        /* and send it */
-       if (m_sock_send(sock, buf, Ustrlen(buf), &errstr) < 0)
+       if (m_sock_send(sock, "quit\r\n", 6, &errstr) < 0)
          return aves_errlog_defer(errstr);
 
        /* read aveserver's greeting and see if it is ready (2xx greeting) */
@@ -952,8 +953,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          int report_flag = 0;
 
          /* setup default virus name */
-         malware_name_internal = string_copy("unknown");
-         malware_name = malware_name_internal;
+         malware_name = "unknown";
 
          report_flag = tmpbuf[ test_byte_order() == LITTLE_MY_ENDIAN ? 1 : 0 ];
 
@@ -1002,9 +1002,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
     case M_CMDL: /* "cmdline" scanner type ---------------------------------- */
       {
        const uschar *cmdline_scanner = scanner_options;
-       uschar *cmdline_trigger;
        const pcre *cmdline_trigger_re;
-       uschar *cmdline_regex;
        const pcre *cmdline_regex_re;
        uschar * file_name;
        uschar * commandline;
@@ -1021,19 +1019,15 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          return cmdl_errlog_defer("missing commandline specification");
 
        /* find scanner output trigger */
-       if (!(cmdline_trigger = string_nextinlist(&av_scanner_work, &sep, NULL, 0)))
-         return cmdl_errlog_defer("missing trigger specification");
-
-       /* precompile trigger regex */
-       if (!(cmdline_trigger_re = m_pcre_compile(CS cmdline_trigger, &errstr)))
+       cmdline_trigger_re = m_pcre_nextinlist(&av_scanner_work, &sep,
+                                 "missing trigger specification", &errstr);
+       if (!cmdline_trigger_re)
          return cmdl_errlog_defer(errstr);
 
        /* find scanner name regex */
-       if (!(cmdline_regex = string_nextinlist(&av_scanner_work, &sep, NULL, 0)))
-         return cmdl_errlog_defer("missing virus name regex specification");
-
-       /* precompile name regex */
-       if (!(cmdline_regex_re = m_pcre_compile(CS cmdline_regex, &errstr)))
+       cmdline_regex_re = m_pcre_nextinlist(&av_scanner_work, &sep,
+                           "missing virus name regex specification", &errstr);
+       if (!cmdline_regex_re)
          return cmdl_errlog_defer(errstr);
 
        /* prepare scanner call; despite the naming, file_name holds a directory
@@ -1078,7 +1072,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        }
 
        /* look for trigger while recording output */
-       while(fgets(CS linebuffer, sizeof(linebuffer), scanner_out) != NULL) {
+       while(fgets(CS linebuffer, sizeof(linebuffer), scanner_out)) {
          if ( Ustrlen(linebuffer) > fwrite(linebuffer, 1, Ustrlen(linebuffer), scanner_record) ) {
            /* short write */
            pclose(scanner_out);
@@ -1104,7 +1098,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
          /* re-open the scanner output file, look for name match */
          scanner_record = fopen(CS file_name, "rb");
-         while(fgets(CS linebuffer,32767,scanner_record) != NULL) {
+         while(fgets(CS linebuffer, sizeof(linebuffer), scanner_record)) {
            /* try match */
            if ((s = m_pcre_exec(cmdline_regex_re, linebuffer)))
              malware_name = s;
@@ -1156,9 +1150,10 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
        /* infected ? */
        if (av_buffer[0] == '1') {
-         if (Ustrchr(av_buffer, '\n')) *Ustrchr(av_buffer, '\n') = '\0';
-         malware_name_internal = string_copy(&av_buffer[2]);
-         malware_name = malware_name_internal;
+         uschar * s = Ustrchr(av_buffer, '\n');
+         if (s)
+           *s = '\0';
+         malware_name = string_copy(&av_buffer[2]);
        }
        else if (!strncmp(CS av_buffer, "-1", 2))
          return soph_errlog_defer("scanner reported error");
@@ -1563,8 +1558,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
            if (p)
              *p = '\0';
          }
-         malware_name_internal = string_copy(vname);
-         malware_name = malware_name_internal;
+         malware_name = string_copy(vname);
          DEBUG(D_acl) debug_printf("Malware found, name \"%s\"\n", malware_name);
 
        } else if (Ustrcmp(result_tag, "ERROR") == 0)
@@ -1594,9 +1588,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        uschar * linebuffer;
        uschar *sockline_scanner;
        uschar sockline_scanner_default[] = "%s\n";
-       uschar *sockline_trigger;
        const pcre *sockline_trig_re;
-       uschar *sockline_regex;
        const pcre *sockline_name_re;
 
        /* find scanner command line */
@@ -1605,21 +1597,15 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          sockline_scanner = sockline_scanner_default;
 
        /* find scanner output trigger */
-       if (!(sockline_trigger = string_nextinlist(&av_scanner_work, &sep,
-                                           NULL, 0)))
-         return sock_errlog_defer("missing trigger specification");
-
-       /* precompile trigger regex */
-       if (!(sockline_trig_re = m_pcre_compile(CS sockline_trigger, &errstr)))
+       sockline_trig_re = m_pcre_nextinlist(&av_scanner_work, &sep,
+                                 "missing trigger specification", &errstr);
+       if (!sockline_trig_re)
          return sock_errlog_defer(errstr);
 
        /* find virus name regex */
-       if (!(sockline_regex = string_nextinlist(&av_scanner_work, &sep,
-                                              NULL, 0)))
-         return sock_errlog_defer("missing virus name regex specification");
-
-       /* precompile name regex */
-       if (!(sockline_name_re = m_pcre_compile(CS sockline_regex, &errstr)))
+       sockline_name_re = m_pcre_nextinlist(&av_scanner_work, &sep,
+                           "missing virus name regex specification", &errstr);
+       if (!sockline_name_re)
          return sock_errlog_defer(errstr);
 
        /* prepare scanner call */
@@ -1696,13 +1682,11 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
       }
     }
 
-    /* set "been here, done that" marker */
-    malware_ok = 1;
+    malware_ok = TRUE;                 /* set "been here, done that" marker */
   }
 
   /* match virus name against pattern (caseless ------->----------v) */
-  if ( (malware_name != NULL) &&
-       (regex_match_and_setup(re, malware_name, 0, -1)) ) {
+  if ( malware_name && (regex_match_and_setup(re, malware_name, 0, -1)) ) {
     DEBUG(D_acl) debug_printf("Matched regex to malware [%s] [%s]\n", malware_regex, malware_name);
     return OK;
   }
@@ -1810,8 +1794,7 @@ mksd_parse_line (char *line)
         if (((p-line) > 5) && (line[3] == ' '))
           if (((p = strchr (line+4, ' ')) != NULL) && ((p-line) > 4)) {
             *p = '\0';
-            malware_name_internal = string_copy(line+4);
-           malware_name = malware_name_internal;
+            malware_name = string_copy(line+4);
             return OK;
           }
       }