From 004f8386ce2001dd6b2936369c3a5617f6029f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B6r=C3=B6k=20Edvin?= Date: Thu, 12 Feb 2009 15:50:47 +0000 Subject: [PATCH] output "stream" instead of "fd[]" for INSTREAM. Add INSTREAM command test. git-svn-id: file:///var/lib/svn/clamav-devel/branches/clamd-proto@4753 77e5149b-7576-45b1-b177-96237e5ba77b --- ChangeLog | 5 ++++ clamd/others.c | 1 + clamd/others.h | 1 + clamd/scanner.c | 7 +++-- clamd/scanner.h | 2 +- clamd/server-th.c | 2 ++ clamd/session.c | 4 +-- unit_tests/Makefile.am | 2 +- unit_tests/Makefile.in | 2 +- unit_tests/check_clamd.c | 63 +++++++++++++++++++++++++++++++++++++-- unit_tests/check_clamd.sh | 12 ++++---- 11 files changed, 86 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index cce825e56..b0693ea50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Feb 12 18:19:28 EET 2009 (edwin) +------------------------------------ + * clamd/, unit_tests/: output stream instead of fd[] for INSTREAM. + Add INSTREAM command test. + Thu Feb 12 17:11:16 EET 2009 (edwin) ------------------------------------ * Makefile.in, unit_tests/Makefile.am, unit_tests/Makefile.in, diff --git a/clamd/others.c b/clamd/others.c index cd1a80b95..e6c3b3542 100644 --- a/clamd/others.c +++ b/clamd/others.c @@ -317,6 +317,7 @@ static int buf_init(struct fd_buf *buf, int listen_only) buf->quota = 0; buf->dumpname = NULL; buf->group = NULL; + buf->term = '\0'; if (!listen_only) { if (!buf->buffer) { buf->bufsize = PATH_MAX+8; diff --git a/clamd/others.h b/clamd/others.h index 5b828173a..752cee00f 100644 --- a/clamd/others.h +++ b/clamd/others.h @@ -40,6 +40,7 @@ struct fd_buf { size_t bufsize; size_t off; int fd; + char term; int got_newdata; /* 0: no, 1: yes, -1: error */ int recvfd; /* TODO: these fields don't belong here, there are identical fields in conn diff --git a/clamd/scanner.c b/clamd/scanner.c index 256234fda..76879b2a9 100644 --- a/clamd/scanner.c +++ b/clamd/scanner.c @@ -234,14 +234,17 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned, const struct cl_engine *engine, - unsigned int options, const struct optstruct *opts, int odesc) + unsigned int options, const struct optstruct *opts, int odesc, int stream) { int ret; const char *virname; struct stat statbuf; char fdstr[32]; - snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd); + if (stream) + strncpy(fdstr, "stream", sizeof(fdstr)); + else + snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd); if(fstat(fd, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) { conn_reply(conn, fdstr, "Not a regular file", "ERROR"); logg("%s: Not a regular file. ERROR\n", fdstr); diff --git a/clamd/scanner.h b/clamd/scanner.h index 34a9e5d65..c6b132f1b 100644 --- a/clamd/scanner.h +++ b/clamd/scanner.h @@ -46,7 +46,7 @@ struct scan_cb_data { jobgroup_t *group; }; -int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, int odesc); +int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, int odesc, int stream); int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, char term); int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data); diff --git a/clamd/server-th.c b/clamd/server-th.c index bfd57b8e7..45e49349c 100644 --- a/clamd/server-th.c +++ b/clamd/server-th.c @@ -853,6 +853,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi } conn.term = term; + buf->term = term; if ((rc = execute_or_dispatch_command(&conn, cmdtype, argument)) < 0) { logg("!Command dispatch failed\n"); @@ -951,6 +952,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi if (!buf->chunksize) { /* chunksize 0 marks end of stream */ conn.scanfd = buf->dumpfd; + conn.term = buf->term; buf->dumpfd = -1; buf->mode = buf->group ? MODE_COMMAND : MODE_WAITREPLY; logg("*RECVTH: chunks complete\n"); diff --git a/clamd/session.c b/clamd/session.c index 78d8ebe40..320d363d4 100644 --- a/clamd/session.c +++ b/clamd/session.c @@ -236,7 +236,7 @@ int command(client_conn_t *conn, int *virus) if (conn->scanfd == -1) conn_reply_error(conn, "FILDES: didn't receive file descriptor."); else { - ret = scanfd(conn->scanfd, conn, NULL, engine, options, opts, desc); + ret = scanfd(conn->scanfd, conn, NULL, engine, options, opts, desc, 0); if (ret == CL_VIRUS) *virus = 1; if (ret == CL_EMEM) { @@ -268,7 +268,7 @@ int command(client_conn_t *conn, int *virus) } return 0; case COMMAND_INSTREAMSCAN: - ret = scanfd(conn->scanfd, conn, NULL, engine, options, opts, desc); + ret = scanfd(conn->scanfd, conn, NULL, engine, options, opts, desc, 1); if (ret == CL_VIRUS) *virus = 1; if (ret == CL_EMEM) { diff --git a/unit_tests/Makefile.am b/unit_tests/Makefile.am index 46dce9ed1..49a61ddc9 100644 --- a/unit_tests/Makefile.am +++ b/unit_tests/Makefile.am @@ -26,7 +26,7 @@ check_clamav_SOURCES = check_clamav.c checks.h checks_common.h $(top_builddir)/l check_clamav_CPPFLAGS = -I$(top_srcdir) @CHECK_CPPFLAGS@ -DSRCDIR=\"$(abs_srcdir)\" check_clamav_LDADD = $(top_builddir)/libclamav/libclamav.la @THREAD_LIBS@ @CHECK_LIBS@ check_clamd_SOURCES = check_clamd.c checks_common.h -check_clamd_CPPFLAGS = -I$(top_srcdir) @CHECK_CPPFLAGS@ -DSRCDIR=\"$(abs_srcdir)\" +check_clamd_CPPFLAGS = -I$(top_srcdir) @CHECK_CPPFLAGS@ -DSRCDIR=\"$(abs_srcdir)\" -DBUILDDIR=\"$(abs_builddir)\" check_clamd_LDADD = @CHECK_LIBS@ @CLAMD_LIBS@ else check_clamd_SOURCES = check_clamav_skip.c diff --git a/unit_tests/Makefile.in b/unit_tests/Makefile.in index eedc7cae4..ff2b847bb 100644 --- a/unit_tests/Makefile.in +++ b/unit_tests/Makefile.in @@ -271,7 +271,7 @@ check_SCRIPTS = $(scripts) @HAVE_LIBCHECK_TRUE@check_clamav_LDADD = $(top_builddir)/libclamav/libclamav.la @THREAD_LIBS@ @CHECK_LIBS@ @HAVE_LIBCHECK_FALSE@check_clamd_SOURCES = check_clamav_skip.c @HAVE_LIBCHECK_TRUE@check_clamd_SOURCES = check_clamd.c checks_common.h -@HAVE_LIBCHECK_TRUE@check_clamd_CPPFLAGS = -I$(top_srcdir) @CHECK_CPPFLAGS@ -DSRCDIR=\"$(abs_srcdir)\" +@HAVE_LIBCHECK_TRUE@check_clamd_CPPFLAGS = -I$(top_srcdir) @CHECK_CPPFLAGS@ -DSRCDIR=\"$(abs_srcdir)\" -DBUILDDIR=\"$(abs_builddir)\" @HAVE_LIBCHECK_TRUE@check_clamd_LDADD = @CHECK_LIBS@ @CLAMD_LIBS@ CLEANFILES = lcov.out *.gcno *.gcda *.log $(FILES) test-stderr.log clamscan.log valgrind-*.log duma.log duma2.log clamscan2.log EXTRA_DIST = .split $(srcdir)/*.ref input test-clamd.conf test-freshclam.conf valgrind.supp virusaction-test.sh $(scripts) preload_run.sh diff --git a/unit_tests/check_clamd.c b/unit_tests/check_clamd.c index f2bb36842..4f604c7df 100644 --- a/unit_tests/check_clamd.c +++ b/unit_tests/check_clamd.c @@ -2,6 +2,7 @@ #include "clamav-config.h" #endif +#include #include #include #include @@ -11,10 +12,14 @@ #include #endif #include +#include #include +#include + #include #include "checks_common.h" #include "libclamav/version.h" +#include "libclamav/cltypes.h" #ifdef CHECK_HAVE_LOOPS @@ -46,13 +51,20 @@ static void conn_teardown(void) #ifndef REPO_VERSION #define REPO_VERSION VERSION #endif + +#define SCANFILE BUILDDIR"/../test/clam.exe" +#define FOUNDREPLY SCANFILE": ClamAV-Test-File.UNOFFICIAL FOUND" + static struct basic_test { const char *command; const char *reply; } basic_tests[] = { {"PING", "PONG"}, {"RELOAD","RELOADING"}, - {"VERSION", "ClamAV "REPO_VERSION""VERSION_SUFFIX} + {"VERSION", "ClamAV "REPO_VERSION""VERSION_SUFFIX}, + {"SCAN "SCANFILE, FOUNDREPLY}, + {"CONTSCAN "SCANFILE, FOUNDREPLY}, + {"MULTISCAN "SCANFILE, FOUNDREPLY}, }; static void *recvfull(int sd, size_t *len) @@ -83,7 +95,7 @@ static void test_command(const char *cmd, size_t len, const char *expect, size_t void *recvdata; int rc; rc = send(sockd, cmd, len, 0); - fail_unless_fmt(rc != -1, "Unable to send(): %s\n", strerror(errno)); + fail_unless_fmt(rc == len, "Unable to send(): %s\n", strerror(errno)); recvdata = recvfull(sockd, &len); @@ -121,12 +133,59 @@ START_TEST (test_basic_commands) } END_TEST +#define EXPECT_INSTREAM "stream: ClamAV-Test-File.UNOFFICIAL FOUND\n" + +START_TEST (tc_instream) +{ + int fd, nread, rc; + struct stat stbuf; + uint32_t chunk; + void *recvdata; + size_t len, expect_len; + char buf[4096] = "nINSTREAM\n"; + size_t off = strlen(buf); + + fail_unless_fmt(stat(SCANFILE, &stbuf) != -1, "stat failed for %s: %s", SCANFILE, strerror(errno)); + + fd = open(SCANFILE, O_RDONLY); + fail_unless_fmt(fd != -1, "open failed: %s\n", strerror(errno)); + + chunk = htonl(stbuf.st_size); + memcpy(&buf[off], &chunk, sizeof(chunk)); + off += 4; + nread = read(fd, &buf[off], sizeof(buf)-off-4); + fail_unless_fmt(nread == stbuf.st_size, "read failed: %s\n", strerror(errno)); + off += nread; + buf[off++]=0; + buf[off++]=0; + buf[off++]=0; + buf[off++]=0; + close(fd); + + conn_setup(); + fail_unless(send(sockd, buf, off, 0) == off, "send() failed: %s\n", strerror(errno)); + + recvdata = recvfull(sockd, &len); + + expect_len = strlen(EXPECT_INSTREAM); + fail_unless_fmt(len == expect_len, "Reply has wrong size: %lu, expected %lu, reply: %s\n", + len, expect_len, recvdata); + + rc = memcmp(recvdata, EXPECT_INSTREAM, expect_len); + fail_unless_fmt(!rc, "Wrong reply for command INSTREAM: |%s|, expected: |%s|\n", recvdata, EXPECT_INSTREAM); + free(recvdata); + + conn_teardown(); +} +END_TEST + static Suite *test_clamd_suite(void) { Suite *s = suite_create("clamd"); TCase *tc_commands = tcase_create("clamd commands"); suite_add_tcase(s, tc_commands); tcase_add_loop_test(tc_commands, test_basic_commands, 0, sizeof(basic_tests)/sizeof(basic_tests[0])); + tcase_add_test(tc_commands, tc_instream); return s; } diff --git a/unit_tests/check_clamd.sh b/unit_tests/check_clamd.sh index a5a7f7d38..1ba56d02c 100755 --- a/unit_tests/check_clamd.sh +++ b/unit_tests/check_clamd.sh @@ -89,12 +89,6 @@ run_clamdscan() { cat clamdscan-multiscan.log die 1 fi - $TOP/unit_tests/check_clamd - ecode=$? - if test $ecode -ne 77 && test $ecode -ne 0; then - error "Failed clamd protocol test!" - die 1 - fi } run_reload_test() @@ -202,6 +196,12 @@ if test "$NFILES" -ne "0$NINFECTED_MULTI_FDPASS"; then scan_failed clamdscan-multiscan.log "clamd did not detect all testfiles correctly in fdpass+multiscan mode!" fi +$TOP/unit_tests/check_clamd +ecode=$? +if test $ecode -ne 77 && test $ecode -ne 0; then + error "Failed clamd protocol test!" + die 1 +fi # Test HeuristicScanPrecedence off feature run_clamdscan ../clam-phish-exe grep "ClamAV-Test-File" clamdscan.log >/dev/null 2>/dev/null;