[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