diff --git a/clamdscan/client.c b/clamdscan/client.c index b2bddea80..79208b0be 100644 --- a/clamdscan/client.c +++ b/clamdscan/client.c @@ -21,6 +21,7 @@ #endif #include +#include #include #include #include @@ -35,6 +36,8 @@ #include #include #include +#include + #ifdef HAVE_SYS_UIO_H #include @@ -195,31 +198,18 @@ static int dsresult(int sockd, const char *scantype, const char *filename) static int dsstream(int sockd) { - int wsockd, loopw = 60, bread, port, infected = 0; + int wsockd, bread, port, infected = 0; struct sockaddr_in server; struct sockaddr_in peer; socklen_t peer_size; + struct RCVLN rcv; char buff[4096], *pt; - if(write(sockd, "STREAM", 6) <= 0) { - logg("!Can't write to the socket.\n"); - return 2; - } - - while(loopw) { - memset(buff, 0, sizeof(buff)); - if(read(sockd, buff, sizeof(buff)) > 0) { - if((pt = strstr(buff, "PORT"))) { - pt += 5; - sscanf(pt, "%d", &port); - break; - } - } - loopw--; - } - - if(!loopw) { + if(sendln(sockd, "zSTREAM", 8)) return 2; + recvlninit(&rcv, sockd); + bread = recvln(&rcv, &pt, NULL); + if(bread < 7 || memcmp(pt, "PORT ", 5) || (port = atoi(&pt[5])) == 0) { logg("!Daemon not ready for stream scanning.\n"); return -1; } @@ -261,8 +251,9 @@ static int dsstream(int sockd) return -1; } - while((bread = read(0, buff, sizeof(buff))) > 0) { - if(write(wsockd, buff, bread) <= 0) { + while((bread = read(0, buff, sizeof(buff))) > 0) { /* FIXME: this is stdin only, not nice */ + if(sendln(wsockd, buff, bread)) { + /* FIXME: we may just be overlimit here */ logg("!Can't write to the socket.\n"); close(wsockd); return -1; @@ -270,7 +261,13 @@ static int dsstream(int sockd) } close(wsockd); + bread = recvln(&rcv, &pt, NULL); + /* logg("~%s\n", bol); *//* FIXME: btw this is useless spam */ + + /* HERE */ + memset(buff, 0, sizeof(buff)); + while((bread = read(sockd, buff, sizeof(buff))) > 0) { logg("%s", buff); if(strstr(buff, "FOUND\n")) { @@ -449,6 +446,84 @@ int reload_clamd_database(const struct optstruct *opts) return 0; } +static int client_scan(const char *file, const char *scantype, int *infected, int *errors, const struct optstruct *opts) { + struct stat sb; + char *fullpath; + DIR *dir; + struct dirent *dent; + int ret, sockd; + + /* BUF + basename/thisname/child */ + + if(stat(file, &sb) == -1) { + logg("^Can't access file %s\n", file); + perror(file); + (*errors)++; + return 0; + } + if(!(fullpath = malloc(PATH_MAX + 1))) { + logg("^Can't make room for fullpath.\n"); + (*errors)++; + return 0; + } + + if(*file != '/') { /* FIXME: to be unified */ + int namelen; + if(!getcwd(fullpath, PATH_MAX)) { + logg("^Can't get absolute pathname of current working directory.\n"); + free(fullpath); + (*errors)++; + return 0; + } + namelen = strlen(fullpath); + snprintf(&fullpath[namelen], PATH_MAX - namelen, "/%s", file); + } else { + strncpy(fullpath, file, PATH_MAX); + } + fullpath[PATH_MAX] = '\0'; + + /* FIXME: i should break out ASAP here for SCAN, continue for MULTISCAN, CONTSCAN */ + switch(sb.st_mode & S_IFMT) { + case S_IFDIR: + /* FIXME: if (remote) { */ + if(!(dir = opendir(file))) + break; + ret = strlen(fullpath); + while((dent = readdir(dir))) { + if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; + snprintf(&fullpath[ret], PATH_MAX - ret, "/%s", dent->d_name); + fullpath[PATH_MAX] = '\0'; + if(client_scan(fullpath, scantype, infected, errors, opts)) { + closedir(dir); + free(fullpath); + return 1; + } + } + closedir(dir); + break; + /* } else fallback to S_IFREG for external recursion */ + + case S_IFREG: + if((sockd = dconnect(opts, NULL)) < 0) + return 1; + + if((ret = dsresult(sockd, scantype, fullpath)) >= 0) + *infected += ret; + else + (*errors)++; + close(sockd); + break; + + default: + logg("^Not supported file type (%s)\n", fullpath); + errors++; + } + + free(fullpath); + return 0; +} + int client(const struct optstruct *opts, int *infected) { char cwd[PATH_MAX+1], *fullpath; @@ -461,6 +536,9 @@ int client(const struct optstruct *opts, int *infected) if(optget(opts, "multiscan")->enabled) scantype = "MULTISCAN"; + client_scan(opts->filename, scantype, infected, &errors, opts); + return 0; /* FIXME */ + /* parse argument list */ if(opts->filename == NULL || strlen(opts->filename) == 0) {