Check "socket" scanner commandline spec for no more than one %s expansion
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 16 Feb 2014 18:09:40 +0000 (18:09 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 16 Feb 2014 18:09:40 +0000 (18:09 +0000)
src/src/malware.c

index 298031aa39a2777905cbcdec9fdca5c5696499c6..93e30c06f1b3b78e4d2ea790c2370eb2010e640f 100644 (file)
@@ -154,7 +154,7 @@ malware_errlog(const uschar * str)
 {
   log_write(0, LOG_MAIN|LOG_PANIC, "malware acl condition: %s", str);
 }
-static int
+static inline int
 malware_errlog_defer(const uschar * str)
 {
   malware_errlog(str);
@@ -269,7 +269,8 @@ m_unixsocket(const uschar * path, uschar ** errstr)
   }
 
   server.sun_family = AF_UNIX;
-  Ustrcpy(server.sun_path, path);
+  Ustrncpy(server.sun_path, path, sizeof(server.sun_path)-1);
+  server.sun_path[sizeof(server.sun_path)-1] = '\0';
   if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
     int err = errno;
     (void)close(sock);
@@ -1531,18 +1532,26 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          by David Saez and the cmdline code
       */
       {
-       int sock, bread=0;
+       int sock, bread;
        uschar * commandline;
        uschar av_buffer[1024];
        uschar * linebuffer;
-       uschar *sockline_scanner;
+       uschar * sockline_scanner;
        uschar sockline_scanner_default[] = "%s\n";
        const pcre *sockline_trig_re;
        const pcre *sockline_name_re;
+       int err;
 
        /* find scanner command line */
-       if (!(sockline_scanner = string_nextinlist(&av_scanner_work, &sep,
+       if ((sockline_scanner = string_nextinlist(&av_scanner_work, &sep,
                                            NULL, 0)))
+       {       /* check for no expansions apart from one %s */
+         char * s = index(sockline_scanner, '%');
+         if (s++)
+           if (*s != 's' && *s != '%'  ||  index(s+1, '%'))
+             return sock_errlog_defer("unsafe sock scanner call spec");
+       }
+       else
          sockline_scanner = sockline_scanner_default;
 
        /* find scanner output trigger */
@@ -1557,7 +1566,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        if (!sockline_name_re)
          return sock_errlog_defer(errstr);
 
-       /* prepare scanner call */
+       /* prepare scanner call - security depends on expansions check above */
        commandline = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
        commandline = string_sprintf( CS sockline_scanner, CS commandline);
 
@@ -1573,17 +1582,15 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        if (m_sock_send(sock, commandline, Ustrlen(commandline), &errstr) < 0)
          return sock_errlog_defer(errstr);
 
-       /* We're done sending, close socket for writing. */
-       /* shutdown(sock, SHUT_WR); */
-
        /* Read the result */
        memset(av_buffer, 0, sizeof(av_buffer));
        bread = read(sock, av_buffer, sizeof(av_buffer));
+       err = errno;
        (void)close(sock);
 
        if (!(bread > 0))
          return sock_errlog_defer(
-           string_sprintf("unable to read from socket (%s)", strerror(errno)));
+           string_sprintf("unable to read from socket (%s)", strerror(err)));
 
        if (bread == sizeof(av_buffer))
          return sock_errlog_defer("buffer too small");