int get_clamd_version(const struct optstruct *opts) { char *buff; int len, sockd; struct RCVLN rcv; isremote(opts); if((sockd = dconnect()) < 0) return 2; recvlninit(&rcv, sockd); if(sendln(sockd, "zVERSION", 9)) { closesocket(sockd); return 2; } while((len = recvln(&rcv, &buff, NULL))) { if(len == -1) { logg("!Error occoured while receiving version information.\n"); break; } printf("%s\n", buff); } closesocket(sockd); return 0; }
/* * Initialize filesystem. Read in file system metadata and initialize * memory structures. If there are inconsistencies, now would also be * a good time to deal with that. * * HINT: You don't need to deal with the 'conn' parameter AND you may * just return NULL. * */ static void* vfs_mount(struct fuse_conn_info *conn) { fprintf(stderr, "vfs_mount called\n"); // Do not touch or move this code; connects the disk dconnect(); /* 3600: YOU SHOULD ADD CODE HERE TO CHECK THE CONSISTENCY OF YOUR DISK AND LOAD ANY DATA STRUCTURES INTO MEMORY */ vcb volblock = getvcb(); if(volblock.disk_id != MAGICNUM){ fprintf(stderr, "Invalid disk: Invalid magic number."); dunconnect(); } if(volblock.mounted != 0){ fprintf(stderr, "Invalid disk: Disk did not unmount correctly."); dunconnect(); } else{ volblock.mounted = 1; setvcb(volblock); } return NULL; }
/* * Initialize filesystem. Read in file system metadata and initialize * memory structures. If there are inconsistencies, now would also be * a good time to deal with that. * * HINT: You don't need to deal with the 'conn' parameter AND you may * just return NULL. * */ static void* vfs_mount(struct fuse_conn_info *conn) { fprintf(stderr, "vfs_mount called\n"); // Do not touch or move this code; connects the disk dconnect(); /* 3600: YOU SHOULD ADD CODE HERE TO CHECK THE CONSISTENCY OF YOUR DISK AND LOAD ANY DATA STRUCTURES INTO MEMORY */ return NULL; }
/* FTW callback for scanning in non IDSESSION mode * Returns SUCCESS or BREAK on success, CL_EXXX on error */ static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { struct client_serial_data *c = (struct client_serial_data *)data->data; int sockd, ret; const char *f = filename; UNUSEDPARAM(sb); if(chkpath(path)) return CL_SUCCESS; c->files++; switch(reason) { case error_stat: logg("!Can't access file %s\n", path); c->errors++; return CL_SUCCESS; case error_mem: logg("!Memory allocation failed in ftw\n"); c->errors++; return CL_EMEM; case warning_skipped_dir: logg("^Directory recursion limit reached\n"); case warning_skipped_link: return CL_SUCCESS; case warning_skipped_special: logg("^%s: Not supported file type\n", path); c->errors++; return CL_SUCCESS; case visit_directory_toplev: if(c->scantype >= STREAM) return CL_SUCCESS; f = path; filename = NULL; case visit_file: break; } if((sockd = dconnect()) < 0) { if(filename) free(filename); c->errors++; return CL_EOPEN; } ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors); if(filename) free(filename); closesocket(sockd); if(ret < 0) { c->errors++; return CL_EOPEN; } c->infected += ret; if(reason == visit_directory_toplev) return CL_BREAK; return CL_SUCCESS; }
/* IDSESSION handler * Returns non zero for serious errors, zero otherwise */ int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) { struct cli_ftw_cbdata data; struct client_parallel_data cdata; int ftw; if((cdata.sockd = dconnect()) < 0) return 1; if(sendln(cdata.sockd, "zIDSESSION", 11)) { closesocket(cdata.sockd); return 1; } cdata.infected = 0; cdata.files = 0; cdata.errors = 0; cdata.scantype = scantype; cdata.lastid = 0; cdata.ids = NULL; cdata.printok = printinfected^1; data.data = &cdata; ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, ftw_chkpath); if(ftw != CL_SUCCESS) { *err += cdata.errors; *infected += cdata.infected; closesocket(cdata.sockd); return 1; } sendln(cdata.sockd, "zEND", 5); while(cdata.ids && !dspresult(&cdata)); closesocket(cdata.sockd); *infected += cdata.infected; *err += cdata.errors; if(cdata.ids) { logg("!Clamd closed the connection before scanning all files.\n"); return 1; } if(cdata.errors) return 1; if(!cdata.files) return 0; if(cdata.printok) logg("~%s: OK\n", file); return 0; }
int reload_clamd_database(const struct optstruct *opts) { char *buff; int len, sockd; struct RCVLN rcv; isremote(opts); if((sockd = dconnect()) < 0) return 2; recvlninit(&rcv, sockd); if(sendln(sockd, "zRELOAD", 8)) { closesocket(sockd); return 2; } if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) { logg("!Clamd did not reload the database\n"); closesocket(sockd); return 2; } closesocket(sockd); return 0; }
int client(const struct optstruct *opts, int *infected, int *err) { int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0; const char *fname; scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]); remote = isremote(opts) | optget(opts, "stream")->enabled; #ifdef HAVE_FD_PASSING if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) { scantype = FILDES; session = optget(opts, "multiscan")->enabled; } else #endif if(remote || scandash) { scantype = STREAM; session = optget(opts, "multiscan")->enabled; } else if(optget(opts, "multiscan")->enabled) scantype = MULTI; else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH; else scantype = CONT; maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg; maxstream = optget(clamdopts, "StreamMaxLength")->numarg; if (optget(clamdopts, "FollowDirectorySymlinks")->enabled) flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; if (optget(clamdopts, "FollowFileSymlinks")->enabled) flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; flags |= CLI_FTW_TRIM_SLASHES; *infected = 0; if(scandash) { int sockd, ret; STATBUF sb; if(FSTAT(0, &sb) < 0) { logg("client.c: fstat failed for file name \"%s\", with %s\n.", opts->filename[0], strerror(errno)); return 2; } if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM; if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0) *infected = ret; else errors = 1; if(sockd >= 0) closesocket(sockd); } else if(opts->filename || optget(opts, "file-list")->enabled) { if(opts->filename && optget(opts, "file-list")->enabled) logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n"); while((fname = filelist(opts, NULL))) { if(!strcmp(fname, "-")) { logg("!Scanning from standard input requires \"-\" to be the only file argument\n"); continue; } errors += client_scan(fname, scantype, infected, err, maxrec, session, flags); /* this may be too strict if(errors >= 10) { logg("!Too many errors\n"); break; } */ } } else { errors = client_scan("", scantype, infected, err, maxrec, session, flags); } return *infected ? 1 : (errors ? 2 : 0); }
int client(const struct optstruct *opt, int *infected) { char cwd[200], *fullpath; int sockd, ret, errors = 0; struct stat sb; *infected = 0; /* parse argument list */ if(opt->filename == NULL || strlen(opt->filename) == 0) { /* scan current directory */ if(!getcwd(cwd, 200)) { mprintf("@Can't get absolute pathname of current working directory.\n"); return 2; } if((sockd = dconnect(opt)) < 0) return 2; if((ret = dsfile(sockd, cwd, opt)) >= 0) *infected += ret; else errors++; close(sockd); #if defined(ENABLE_FD_PASSING) && defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) && !defined(C_CYGWIN) } else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */ if((sockd = dconnect(opt)) < 0) return 2; if((ret = dsfd(sockd, 0, opt)) >= 0) *infected += ret; else errors++; close(sockd); #else } else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */ if((sockd = dconnect(opt)) < 0) return 2; if((ret = dsstream(sockd, opt)) >= 0) *infected += ret; else errors++; close(sockd); #endif } else { int x; char *thefilename; for (x = 0; (thefilename = cli_strtok(opt->filename, x, "\t")) != NULL; x++) { fullpath = thefilename; if(stat(fullpath, &sb) == -1) { mprintf("@Can't access file %s\n", fullpath); perror(fullpath); errors++; } else { if(strlen(fullpath) < 2 || (fullpath[0] != '/' && fullpath[0] != '\\' && fullpath[1] != ':')) { fullpath = abpath(thefilename); free(thefilename); if(!fullpath) { mprintf("@Can't determine absolute path.\n"); return 2; } } switch(sb.st_mode & S_IFMT) { case S_IFREG: case S_IFDIR: if((sockd = dconnect(opt)) < 0) return 2; if((ret = dsfile(sockd, fullpath, opt)) >= 0) *infected += ret; else errors++; close(sockd); break; default: mprintf("@Not supported file type (%s)\n", fullpath); errors++; } } free(fullpath); } } return *infected ? 1 : (errors ? 2 : 0); }