static void tst_fildes(const char *cmd, size_t len, int fd, const char *expect, size_t expect_len, int closefd, int singlemsg) { char *recvdata, *p; int rc; conn_setup(); fail_unless_fmt(sendmsg_fd(sockd, cmd, len, fd, singlemsg) != -1, "Failed to sendmsg: %s\n", strerror(errno)); if (closefd) close(fd); recvdata = recvfull(sockd, &len); p = strchr(recvdata, ':'); fail_unless_fmt(!!p, "Reply doesn't contain ':' : %s\n", recvdata); *p++ = '\0'; fail_unless_fmt(sscanf(recvdata, "fd[%u]", &rc) == 1, "Reply doesn't contain fd: %s\n", recvdata); len -= p - recvdata; fail_unless_fmt(len == expect_len, "Reply has wrong size: %lu, expected %lu, reply: %s, expected: %s\n", len, expect_len, p, expect); rc = memcmp(p, expect, expect_len); fail_unless_fmt(!rc, "Wrong reply for command %s: |%s|, expected: |%s|\n", cmd, p, expect); free(recvdata); conn_teardown(); }
END_TEST #endif #define EXPECT_INSTREAM "stream: ClamAV-Test-File.UNOFFICIAL FOUND\n" #define EXPECT_INSTREAM0 "stream: ClamAV-Test-File.UNOFFICIAL FOUND" #define STATS_REPLY "POOLS: 1\n\nSTATE: VALID PRIMARY\n" START_TEST (test_stats) { char *recvdata; size_t len = strlen("nSTATS\n"); int rc; conn_setup(); rc = send(sockd, "nSTATS\n", len, 0); fail_unless_fmt((size_t)rc == len, "Unable to send(): %s\n", strerror(errno)); recvdata = recvfull(sockd, &len); fail_unless_fmt(len > strlen(STATS_REPLY), "Reply has wrong size: %lu, minimum %lu, reply: %s\n", len, strlen(STATS_REPLY), recvdata); if (len > strlen(STATS_REPLY)) len = strlen(STATS_REPLY); rc = strncmp(recvdata, STATS_REPLY, len); fail_unless_fmt(rc == 0, "Wrong reply: %s\n", recvdata); free(recvdata); conn_teardown(); }
// // MS_Read(): // static INT32 MS_Read(msg_t *msg) { #ifdef NONET msg = NULL; return MS_READ_ERROR; #else if (recvfull(socket_fd, (char *)msg, HEADER_SIZE, 0) != HEADER_SIZE) return MS_READ_ERROR; msg->type = ntohl(msg->type); msg->length = ntohl(msg->length); msg->room = ntohl(msg->room); if (!msg->length) // fix a bug in Windows 2000 return 0; if (recvfull(socket_fd, (char *)msg->buffer, msg->length, 0) != msg->length) return MS_READ_ERROR; return 0; #endif }
END_TEST START_TEST (test_stream) { char buf[BUFSIZ]; char *recvdata; size_t len; unsigned port; int streamsd, infd, nread; infd = open(SCANFILE, O_RDONLY); fail_unless_fmt(infd != -1, "open failed: %s\n", strerror(errno)); conn_setup(); fail_unless_fmt( send(sockd, "zSTREAM", sizeof("zSTREAM"), 0) == sizeof("zSTREAM"), "send failed: %s\n", strerror(errno)); recvdata = recvpartial(sockd, &len, 1); fail_unless_fmt (sscanf(recvdata, "PORT %u\n", &port) == 1, "Wrong stream reply: %s\n", recvdata); free(recvdata); streamsd = conn_tcp(port); do { nread = read(infd, buf, sizeof(buf)); if (nread > 0) fail_unless_fmt(send(streamsd, buf, nread, 0) == nread, "send failed: %s\n", strerror(errno)); } while (nread > 0 || (nread == -1 && errno == EINTR)); fail_unless_fmt(nread != -1, "read failed: %s\n", strerror(errno)); close(infd); close(streamsd); recvdata = recvfull(sockd, &len); fail_unless_fmt(!strcmp(recvdata,"stream: ClamAV-Test-File.UNOFFICIAL FOUND"), "Wrong reply: %s\n", recvdata); free(recvdata); conn_teardown(); }
static void test_command(const char *cmd, size_t len, const char *extra, const char *expect, size_t expect_len) { void *recvdata; ssize_t rc; rc = send(sockd, cmd, len, 0); fail_unless_fmt((size_t)rc == len, "Unable to send(): %s\n", strerror(errno)); if (extra) { rc = send(sockd, extra, strlen(extra), 0); fail_unless_fmt((size_t)rc == strlen(extra), "Unable to send() extra for %s: %s\n", cmd, strerror(errno)); } shutdown(sockd, SHUT_WR); recvdata = recvfull(sockd, &len); fail_unless_fmt(len == expect_len, "Reply has wrong size: %lu, expected %lu, reply: %s, expected: %s\n", len, expect_len, recvdata, expect); rc = memcmp(recvdata, expect, expect_len); fail_unless_fmt(!rc, "Wrong reply for command %s: |%s|, expected: |%s|\n", cmd, recvdata, expect); free(recvdata); }
END_TEST START_TEST (test_fildes_unwanted) { char *recvdata; size_t len; int dummyfd; conn_setup(); dummyfd = open(SCANFILE, O_RDONLY); /* send a 'zVERSION\0' including the ancillary data. * The \0 is from the extra char needed when sending ancillary data */ fail_unless_fmt(sendmsg_fd(sockd, "zIDSESSION", strlen("zIDSESSION"), dummyfd, 1) != -1, "sendmsg failed: %s\n", strerror(errno)); recvdata = recvfull(sockd, &len); fail_unless_fmt(!strcmp(recvdata,"1: PROTOCOL ERROR: ancillary data sent without FILDES. ERROR"), "Wrong reply: %s\n", recvdata); free(recvdata); close(dummyfd); conn_teardown(); }
END_TEST #define END_CMD "zEND" #define INSTREAM_CMD "zINSTREAM" static void test_idsession_commands(int split, int instream) { char buf[20480]; size_t i, len=0, j=0; char *recvdata; char *p = buf; const char *replies[2 + sizeof(basic_tests)/sizeof(basic_tests[0])]; /* test all commands that must be accepted inside an IDSESSION */ for (i=0;i < sizeof(basic_tests)/sizeof(basic_tests[0]); i++) { const struct basic_test *test = &basic_tests[i]; if (test->skiproot && isroot) continue; if (test->ids == IDS_OK) { fail_unless(p+strlen(test->command)+2 < buf+sizeof(buf), "Buffer too small"); *p++ = 'z'; strcpy(p, test->command); p += strlen(test->command); *p++ = '\0'; if (test->extra) { fail_unless(p+strlen(test->extra) < buf+sizeof(buf), "Buffer too small"); strcpy(p, test->extra); p += strlen(test->extra); } replies[j++] = test->reply; } if (instream && test->ids == IDS_END) { uint32_t chunk; /* IDS_END - in middle of other commands, perfect for inserting * INSTREAM */ fail_unless(p+sizeof(INSTREAM_CMD)+544< buf+sizeof(buf), "Buffer too small"); memcpy(p, INSTREAM_CMD, sizeof(INSTREAM_CMD)); p += sizeof(INSTREAM_CMD); p += prepare_instream(p, 0, 552); replies[j++] = EXPECT_INSTREAM0; fail_unless(p+sizeof(INSTREAM_CMD)+16388< buf+sizeof(buf), "Buffer too small"); memcpy(p, INSTREAM_CMD, sizeof(INSTREAM_CMD)); p += sizeof(INSTREAM_CMD); chunk=htonl(16384); memcpy(p, &chunk, 4); p+=4; memset(p, 0x5a, 16384); p += 16384; *p++='\0'; *p++='\0'; *p++='\0'; *p++='\0'; replies[j++] = "stream: OK"; } } fail_unless(p+sizeof(END_CMD) < buf+sizeof(buf), "Buffer too small"); memcpy(p, END_CMD, sizeof(END_CMD)); p += sizeof(END_CMD); if (split) { /* test corner-cases: 1-byte sends */ for (i=0;i<(size_t)(p-buf);i++) fail_unless((size_t)send(sockd, &buf[i], 1, 0) == 1, "send() failed: %u, %s\n", i, strerror(errno)); } else { fail_unless(send(sockd, buf, p-buf, 0) == p-buf,"send() failed: %s\n", strerror(errno)); } recvdata = recvfull(sockd, &len); p = recvdata; for (i=0;i < sizeof(basic_tests)/sizeof(basic_tests[0]); i++) { const struct basic_test *test = &basic_tests[i]; if (test->skiproot && isroot) continue; if (test->ids == IDS_OK) { unsigned id; char *q = strchr(p, ':'); fail_unless_fmt(!!q, "No ID in reply: %s\n", p); *q = '\0'; fail_unless_fmt(sscanf(p, "%u", &id) == 1,"Wrong ID in reply: %s\n", p); fail_unless(id > 0, "ID cannot be zero"); fail_unless_fmt(id <= j, "ID too big: %u, max: %u\n", id, j); q += 2; fail_unless_fmt(!strcmp(q, replies[id-1]), "Wrong ID reply for ID %u: %s, expected %s\n", id, q, replies[id-1]); p = q + strlen(q)+1; } } free(recvdata); conn_teardown(); }