[Avcheck] my patch for KAV 5.x

Varadi Gabor varadi at mithrandir.hu
Mon Mar 29 23:38:30 MSD 2004


Hi all.

I'm writting new code for KAV 5.x.
This patch is very-beta :)

TODO: cleaning code :))

-- 
    [Varadi Gabor]
-------------- next part --------------
--- avcheck.c.old	Thu Mar 25 12:07:43 2004
+++ avcheck.c	Mon Mar 29 21:30:39 2004
@@ -53,6 +53,12 @@
 
 static char buf[8192];          /* i/o buffer */
 
+#if AVP
+extern char vers[];
+extern char lastupdate[];
+extern char info[];
+#endif
+
 static void cleanup(  )
 {
   if( path )
@@ -271,6 +277,11 @@
 {
 
   static const char *htemplate = "X-AV-Checked: %.24s %s%s";
+#if AVP
+  static const char *htemplate2 = "X-AV-Updated: %s%s";
+  static const char *htemplate3 = "X-AV-Version: %s%s";
+  static const char *htemplate4 = "X-AV-Info: %s%s";
+#endif
 
   /* open mail stream */
 
@@ -300,6 +311,17 @@
     if( header ) {
       time_t now = time( NULL );
       fprintf( f, htemplate, ctime( &now ), header, "\r\n" );
+#if AVP
+      if( lastupdate[0] ) {
+        fprintf( f, htemplate2, lastupdate, "\r\n" );
+      }
+      if( vers[0] ) {
+        fprintf( f, htemplate3, vers, "\r\n" );
+      }
+      if( info[0] ) {
+        fprintf( f, htemplate4, info, "\r\n" );
+      }
+#endif
     }
     /* nl = 1 means we're at a start of a line (watch for dots!) */
     for( nl = 1, bp = be = buf;; ) {
@@ -404,110 +426,205 @@
 }
 
 #if AVP
-static int scan_avp( int fd, const char *path, const char *avname )
+
+static char avebuf[8192];
+static char vers[32];
+static char lastupdate[32];     //'YYYY-mm-dd / nn'
+static char expire[32];         //'YYYY-mm-dd ( nn day )'
+static char keys[32];
+static char msg[8192];
+static char last325[128];
+static char info[128];
+static int clean = 1;
+static int xcode = 0;
+
+static void aveparse( int code )
+{
+  char c;
+  unsigned int u, m, d, y, r, da;
+  char temp_buf[8192];
+
+/*
+220 File is clean
+221 File was infected and has been cured
+
+230 File is infected
+231 File is infected and can't be cured
+232 File is suspicious
+233 File has warnings
+234 File is corrupted
+
+240 File is encrypted
+241 Scan error has been detected
+*/
+
+  switch ( code ) {
+    case 220:
+    case 221:
+    case 230:
+    case 231:
+    case 232:
+    case 233:
+    case 234:
+    case 240:
+    case 241:
+      xcode = code;
+      if( code >= 230 && code <= 239 )
+        clean = 0;
+//      printf( "     Result: %s\n", msg_type );
+      bzero( avebuf, sizeof( avebuf ) );
+      break;
+    case 201:
+      sscanf( avebuf, "%u %u %u %2u%2u%4u %u %19s", &u, &u, &u, &d, &m, &y, &r, vers );
+      snprintf( lastupdate, sizeof( lastupdate ), "%04d-%02d-%02d / %d", y, m, d, r );
+//      printf( "Last update: %s\n", lastupdate );
+      bzero( avebuf, sizeof( avebuf ) );
+      break;
+    case 301:
+      sscanf( avebuf, "%20s %2u%2u%4u %u %c %u", keys, &d, &m, &y, &da, &c, &u );
+      snprintf( expire, sizeof( expire ), "%04d-%02d-%02d (%d day)", y, m, d, da );
+//      printf( "     Expire: %s\n", expire );
+      bzero( avebuf, sizeof( avebuf ) );
+      break;
+    case 322:
+      bzero( temp_buf, sizeof( temp_buf ) );
+      m = sizeof( temp_buf ) - 1;
+      for( u = 0; u < m; u++ ) {
+        if( avebuf[u] ) {
+          if( avebuf[u] != '/' ) {
+            temp_buf[u] = avebuf[u];
+          } else {
+            break;
+          }
+        }
+      }
+//      printf( "     Result: %s\n", temp_buf );
+      if( msg[0] )
+        strncat( msg, "; ", sizeof( msg ) );
+      strncat( msg, temp_buf, sizeof( msg ) );
+      bzero( avebuf, sizeof( avebuf ) );
+      break;
+    case 200:
+    case 310:
+    case 311:
+    case 312:
+    case 321:
+    case 325:
+      if( code == 325 ) {
+        char *pp = strrchr( buf, '/' );
+        if( pp != ( char * ) NULL ) {
+          strncpy( last325, pp + 1, sizeof( last325 ) );
+        }
+      }
+      bzero( avebuf, sizeof( avebuf ) );
+      break;
+    default:
+//      printf( "        %3d: %s\n", code, avebuf );
+      warn( "Aveserver:: not parsed return code %d: %s", code, avebuf );
+      break;
+  }
+}
+
+/* read ~SMTP~ dialog responce from opened filedescriptor fd */
+static int averead( int fd, int parse )
 {
+  int l;
+  char *p;
 
-  unsigned short r;             /*XXX size/endiannes problem */
-  char *p, *t, *n;
-  int l, len;
-  time_t now = time( NULL );
-
-  l = 3 + 15 + 1 + strlen( path );
-  p = ( char * ) alloca( l + 1 );
-  sprintf( p, "<0>%.15s:%s", ctime( &now ) + 4, path );
+  bzero( avebuf, sizeof( avebuf ) );
+  l = read( fd, buf, sizeof( buf ) );
+  if( l < 3 )
+    err( l < 0 ? errno : 0, "unable to read ave response" );
+  if( buf[--l] != '\n' )
+    err( 0, "long line in ave response" );
+  if( buf[l - 1] == '\r' )
+    --l;
+  buf[l] = '\0';
+  l = 0;
+  for( p = buf; p < buf + 3; ++p )
+    if( *p >= '0' && *p <= '9' )
+      l = l * 10 + ( *p - '0' );
+    else
+      break;
+  if( parse ) {
+    strncpy( avebuf, buf + 4, sizeof( avebuf ) );
+    aveparse( l );
+  }
+  return l;
+}
 
-  errno = 0;
+static void avecmd( int fd, const char *cmd, const char *avname )
+{
+  int l;
+  static char p[8192];
+
+  snprintf( p, 8192, "%s\r\n", cmd );
+  l = strlen( p );
   if( iwrite( fd, p, l ) < 0 )
-    err( errno, "unable to send command to %s", avname );
-  if( read( fd, &r, 2 ) != 2 )  /*XXX endiannes problem */
-    err( errno, "unable to read %s responce", avname );
-  /*XXX avp uses very bogus protocol.
-     Here we're ignoring it's text answer(s) unless code says that
-     it found some virus(es). */
-  switch ( r & 0xcf ) {
-    case 0:                    /* the only one OK result. */
-      /*XXX unfortunately avp is so buggy that it will report success
-         if it encountered some error(s), so that this is not really
-         "OK result." */
-      return 0;
-    case 1:                    /* virus scan was incomplete */
-      /* this returned when AVP is unable to parse file structure for
-         various reasons. */
-    case 8:                    /* file is corrupted (e.g. archive) - do not treat it as bad */
-      warn( "unexpected %s return code %d (0x%04x) (%s)", avname, r & 0xcf, r, ( ( r & 0xcf ) == 1 ) ? "virus scan was incomplete" : "file is corrupted" );
-      return 0;
-    case 4:                    /* known virus(es) detected */
-    case 3:                    /* suspicious object(s) found */
-    case 2:                    /* Found corrupted or changed virus (usually false positive,
-                                   controlled by Warnings=Yes|No in defUnix.prf) */
+    err( errno, "unable to send command <%s> to %s", cmd, avname );
+}
+
+static int scan_avp( int fd, const char *path, const char *avname )
+{
+  int l;
+  const char *opt = "xmQPRSTUWabcdefghi";
+  static char cmd[8192];
+
+  bzero( msg, sizeof( msg ) );
+  bzero( keys, sizeof( keys ) );
+  bzero( expire, sizeof( expire ) );
+  bzero( lastupdate, sizeof( lastupdate ) );
+  bzero( vers, sizeof( vers ) );
+  bzero( info, sizeof( info ) );
+  bzero( last325, sizeof( last325 ) );
+  clean = 1;
+
+  averead( fd, 0 );
+
+  snprintf( cmd, sizeof( cmd ), "SCAN %s %s", opt, path );
+  avecmd( fd, cmd, avname );
+  for( ;; ) {
+    l = averead( fd, 1 );
+    if( l < 300 || l >= 400 )
       break;
-    default:
-      /* some more additional codes to help diagnose problem(s) */
-      if( ( r & 0xcf ) == 7 )
-        p = "kavdaemon is corrupted";
-      else if( ( r & 0xcf ) == 0x0f )
-        p = "kavdaemon wants confirmation -- set InfectedAction to 0";
-      else if( r & 0x80 )
-        p = "kavdaemon integrity failed";
-      else if( r & 0x40 )
-        p = "kavdaemon av bases not found";
-      else if( r & 0x10 )
-        p = "kavdaemon key file not found or expired";
-      else
-        err( 0, "unexpected %s return code %d (0x%04x)", avname, r & 0xcf, r );
-      err( 0, "unexpected %s return code %d (0x%04x) (%s)", avname, r & 0xcf, r, p );
-  }
-  /* here we're if infected or suspicious object(s) was found by avp */
-
-  /* since we will work here with only one file (message),
-     we will not deal with memory deallocation for msg and *msgp. */
-  if( !( r & 0x0100 ) ) {       /* no message(s) */
-    buf[0] = '\0';
-    return 1;
   }
 
-  if( r & 0x0200 ) {
-    if( read( fd, &len, 4 ) != 4 )      /* read 4-byte junk */
-      err( errno, "unable to read %s junk response", avname );
+  snprintf( cmd, sizeof( cmd ), "INFO" );
+  avecmd( fd, cmd, avname );
+  averead( fd, 1 );
+
+  snprintf( cmd, sizeof( cmd ), "KEYS" );
+  avecmd( fd, cmd, avname );
+  for( ;; ) {
+    l = averead( fd, 1 );
+    if( l == 200 )
+      break;
   }
 
-  l = 0;
-  if( read( fd, &len, 4 ) != 4 )        /*XXX endiannes problem */
-    err( errno, "unable to read avp answer length" );
-  if( len >= sizeof( buf ) )    /* limit response len to avoid DoSes */
-    len = sizeof( buf ) - 1;
-  p = buf;
-  while( len && ( l = read( fd, p, len ) ) > 0 ) {
-    p += l;
-    len -= l;
-  }
-  if( len || l < 0 )
-    err( errno, "unable to read %s answer", avname );
-  *p = '\0';
-  /* now interpret avp response. */
-  /* we will cut junk from each line before tab character (the only
-     interesting information, rest of line is a crap) */
-  t = NULL;                     /* last tab seen */
-  p = buf;                      /* current write pointer */
-  n = buf;                      /* current read pointer */
+  snprintf( cmd, sizeof( cmd ), "QUIT" );
+  avecmd( fd, cmd, avname );
   for( ;; ) {
-    if( *n == '\t' || *n == ' ' )
-      t = ++n;
-    else if( *n == '\n' || *n == '\0' ) {
-      if( t && t != n ) {
-        memcpy( p, t, n - t );
-        p += n - t;
-        *p++ = '\n';
-      }
-      if( !*n )
-        break;
-      ++n;
-      t = NULL;
-    } else
-      ++n;
+    l = averead( fd, 1 );
+    if( l == 200 )
+      break;
   }
-  *p = '\0';
-  return 1;
+
+  if( xcode == 240 ) {
+    warn( "File is protected/encrypted: '%s'", last325 );
+    strncpy( info, "File is protected/encrypted: ", sizeof(info) );
+    strncat( info, last325, sizeof(info) );
+  }
+  if( xcode == 241 ) {
+    warn( "Scan error has been detected '%s'", last325 );
+    strncpy( info, "Scan error has been detected: ", sizeof(info) );
+    strncat( info, last325, sizeof(info) );
+  }
+  if( clean ) {
+    buf[0] = '\0';
+  } else {
+    strncpy( buf, msg, sizeof( buf ) );
+  }
+  return !clean;
 }
 
 #endif /* AVP */


More information about the Avcheck mailing list