/* * Set default IP parameters and ensure that any that are set are being used. */ static void set_parameters(long msgSize) { setp_u32(0, L_MSG_SIZE, msgSize); setp_u32(0, R_MSG_SIZE, msgSize); par_use(L_PORT); par_use(R_PORT); par_use(L_SOCK_BUF_SIZE); par_use(R_SOCK_BUF_SIZE); opt_check(); }
void opt_init(char *name, int argc, char **argv) { if (argc < 2) print_usage(name); memset(&options, 0, sizeof(options)); list_init(&options.passwd); options.loader.flags = DB_LOGIN; list_init(&options.loader.users); list_init(&options.loader.groups); list_init(&options.loader.shells); options.length = -1; opt_process(opt_list, &options.flags, argv); ext_flags = 0; if (options.flags & FLG_EXTERNAL_CHK) { if (options.flags & (FLG_CRACKING_CHK | FLG_MAKECHR_CHK)) { ext_flags = EXT_REQ_FILTER | EXT_USES_FILTER; } else { options.flags |= FLG_CRACKING_SET; ext_flags = EXT_REQ_GENERATE | EXT_USES_GENERATE | EXT_USES_FILTER; } } if (!(options.flags & FLG_ACTION)) options.flags |= FLG_BATCH_SET; opt_check(opt_list, options.flags, argv); if (options.session) { #if OS_FORK char *p = strrchr(options.session, '.'); int bad = 0; if (p) { while (*++p) { if (*p < '0' || *p > '9') { bad = 0; break; } bad = 1; } } if (bad) { fprintf(stderr, "Invalid session name: all-digits suffix\n"); error(); } #endif rec_name = options.session; rec_name_completed = 0; } if (options.flags & FLG_RESTORE_CHK) { #if OS_FORK char *rec_name_orig = rec_name; #endif rec_restore_args(1); #if OS_FORK if (options.fork) { rec_name = rec_name_orig; rec_name_completed = 0; } #endif return; } if (options.flags & FLG_STATUS_CHK) { #if OS_FORK char *rec_name_orig = rec_name; #endif rec_restore_args(0); options.flags |= FLG_STATUS_SET; status_init(NULL, 1); status_print(); #if OS_FORK if (options.fork) { unsigned int i; for (i = 2; i <= options.fork; i++) { rec_name = rec_name_orig; rec_name_completed = 0; rec_restoring_now = 0; options.node_min = options.node_max = i; john_main_process = 0; rec_restore_args(0); john_main_process = 1; options.node_min = options.node_max = i; options.flags |= FLG_STATUS_SET; if (rec_restoring_now) status_print(); } } #endif exit(0); } if (options.flags & FLG_SALTS) if (options.loader.min_pps < 0) { options.loader.max_pps = -1 - options.loader.min_pps; options.loader.min_pps = 0; } if (options.length < 0) options.length = PLAINTEXT_BUFFER_SIZE - 3; else if (options.length < 1 || options.length > PLAINTEXT_BUFFER_SIZE - 3) { fprintf(stderr, "Invalid plaintext length requested\n"); error(); } if (options.flags & FLG_STDOUT) options.flags &= ~FLG_PWD_REQ; #if OS_FORK if ((options.flags & FLG_FORK) && (options.fork < 2 || options.fork > 1024)) { fprintf(stderr, "--fork number must be between 2 and 1024\n"); error(); } #endif if (options.node_str) { const char *msg = NULL; int n; if ((n = sscanf(options.node_str, "%u-%u/%u", &options.node_min, &options.node_max, &options.node_count)) != 3) { n = sscanf(options.node_str, "%u/%u", &options.node_min, &options.node_count); options.node_max = options.node_min; #if OS_FORK if (options.fork) options.node_max += options.fork - 1; #endif } if (n < 2) msg = "valid syntax is MIN-MAX/TOTAL or N/TOTAL"; else if (!options.node_min) msg = "valid node numbers start from 1"; else if (options.node_min > options.node_max) msg = "range start can't exceed range end"; else if (options.node_count < 2) msg = "node count must be at least 2"; else if (options.node_max > options.node_count) msg = "node numbers can't exceed node count"; #if OS_FORK else if (options.fork && options.node_max - options.node_min + 1 != options.fork) msg = "range must be consistent with --fork number"; #endif else if (!options.fork && options.node_max - options.node_min + 1 == options.node_count) msg = "node numbers can't span the whole range"; if (msg) { fprintf(stderr, "Invalid node specification: %s: %s\n", options.node_str, msg); error(); } #if OS_FORK } else if (options.fork) { options.node_min = 1; options.node_max = options.node_min + options.fork - 1; options.node_count = options.node_max; #endif } if ((options.flags & (FLG_PASSWD | FLG_PWD_REQ)) == FLG_PWD_REQ) { fprintf(stderr, "Password files required, " "but none specified\n"); error(); } if ((options.flags & (FLG_PASSWD | FLG_PWD_SUP)) == FLG_PASSWD) { fprintf(stderr, "Password files specified, " "but no option would use them\n"); error(); } rec_argc = argc; rec_argv = argv; rec_check = 0; }
void opt_init(char *name, int argc, char **argv) { if (argc < 2) print_usage(name); memset(&options, 0, sizeof(options)); list_init(&options.passwd); options.loader.flags = DB_LOGIN; list_init(&options.loader.users); list_init(&options.loader.groups); list_init(&options.loader.shells); options.length = -1; opt_process(opt_list, &options.flags, argv); ext_flags = 0; if (options.flags & FLG_EXTERNAL_CHK) { if (options.flags & (FLG_CRACKING_CHK | FLG_MAKECHR_CHK)) { ext_flags = EXT_REQ_FILTER | EXT_USES_FILTER; } else { options.flags |= FLG_CRACKING_SET; ext_flags = EXT_REQ_GENERATE | EXT_USES_GENERATE | EXT_USES_FILTER; } } if (!(options.flags & FLG_ACTION)) options.flags |= FLG_BATCH_SET; opt_check(opt_list, options.flags, argv); if (options.session) { rec_name = options.session; rec_name_completed = 0; } if (options.flags & FLG_RESTORE_CHK) { rec_restore_args(1); return; } if (options.flags & FLG_STATUS_CHK) { rec_restore_args(0); options.flags |= FLG_STATUS_SET; status_init(NULL, 1); status_print(); exit(0); } if (options.flags & FLG_SALTS) if (options.loader.min_pps < 0) { options.loader.max_pps = -1 - options.loader.min_pps; options.loader.min_pps = 0; } if (options.length < 0) options.length = PLAINTEXT_BUFFER_SIZE - 3; else if (options.length < 1 || options.length > PLAINTEXT_BUFFER_SIZE - 3) { fprintf(stderr, "Invalid plaintext length requested\n"); error(); } if (options.flags & FLG_STDOUT) options.flags &= ~FLG_PWD_REQ; if ((options.flags & (FLG_PASSWD | FLG_PWD_REQ)) == FLG_PWD_REQ) { fprintf(stderr, "Password files required, " "but none specified\n"); error(); } if ((options.flags & (FLG_PASSWD | FLG_PWD_SUP)) == FLG_PASSWD) { fprintf(stderr, "Password files specified, " "but no option would use them\n"); error(); } rec_argc = argc; rec_argv = argv; rec_check = 0; }
static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opt, const struct cl_limits *limits, unsigned int options, unsigned int depth) { DIR *dd; struct dirent *dent; struct stat statbuf; char *fname; int scanret = 0, included; unsigned int maxdepth; const struct optnode *optnode; char *argument; if(opt_check(opt, "exclude-dir")) { argument = opt_firstarg(opt, "exclude-dir", &optnode); while(argument) { if(cli_matchregex(dirname, argument)) { if(!printinfected) logg("~%s: Excluded\n", dirname); return 0; } argument = opt_nextarg(&optnode, "exclude-dir"); } } if(opt_check(opt, "include-dir")) { included = 0; argument = opt_firstarg(opt, "include-dir", &optnode); while(argument && !included) { if(cli_matchregex(dirname, argument)) { included = 1; break; } argument = opt_nextarg(&optnode, "include-dir"); } if(!included) { if(!printinfected) logg("~%s: Excluded\n", dirname); return 0; } } if(opt_check(opt, "max-dir-recursion")) maxdepth = atoi(opt_arg(opt, "max-dir-recursion")); else maxdepth = 15; if(depth > maxdepth) return 0; info.dirs++; depth++; if((dd = opendir(dirname)) != NULL) { while((dent = readdir(dd))) { #if !defined(C_INTERIX) && !defined(_WIN32) if(dent->d_ino) #endif { if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { /* build the full name */ fname = malloc(strlen(dirname) + strlen(dent->d_name) + 2); if(!strcmp(dirname, "/")) sprintf(fname, "/%s", dent->d_name); else sprintf(fname, "%s/%s", dirname, dent->d_name); #ifdef _WIN32 NORMALIZE_PATH(fname, 1, continue); #endif /* stat the file */ if(lstat(fname, &statbuf) != -1) { if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion) { if(scandirs(fname, engine, opt, limits, options, depth) == 1) scanret++; } else { if(S_ISREG(statbuf.st_mode)) scanret += scanfile(fname, engine, opt, limits, options); } } free(fname); } } } } else {
static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opt, const struct cl_limits *limits, unsigned int options) { int ret = 0, fd, included, printclean = 1; const struct optnode *optnode; char *argument; const char *virname; #ifdef C_LINUX struct stat sb; /* argh, don't scan /proc files */ if(procdev) if(stat(filename, &sb) != -1) if(sb.st_dev == procdev) { if(!printinfected) logg("~%s: Excluded (/proc)\n", filename); return 0; } #endif if(opt_check(opt, "exclude")) { argument = opt_firstarg(opt, "exclude", &optnode); while(argument) { if(cli_matchregex(filename, argument)) { if(!printinfected) logg("~%s: Excluded\n", filename); return 0; } argument = opt_nextarg(&optnode, "exclude"); } } if(opt_check(opt, "include")) { included = 0; argument = opt_firstarg(opt, "include", &optnode); while(argument && !included) { if(cli_matchregex(filename, argument)) { included = 1; break; } argument = opt_nextarg(&optnode, "include"); } if(!included) { if(!printinfected) logg("~%s: Excluded\n", filename); return 0; } } if(fileinfo(filename, 1) == 0) { if(!printinfected) logg("~%s: Empty file\n", filename); return 0; } #ifndef C_WINDOWS if(geteuid()) if(checkaccess(filename, NULL, R_OK) != 1) { if(!printinfected) logg("~%s: Access denied\n", filename); return 0; } #endif logg("*Scanning %s\n", filename); if((fd = open(filename, O_RDONLY|O_BINARY)) == -1) { logg("~%s: %s\n", filename, strerror(errno)); return 54; } cbdata.count = 0; cbdata.fd = fd; cbdata.oldvalue = 0; cbdata.filename = filename; cbdata.size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); info.files++; if((ret = cl_scandesc(fd, &virname, &info.blocks, engine, limits, options)) == CL_VIRUS) { logg("~%s: %s FOUND\n", filename, virname); info.ifiles++; if(bell) fprintf(stderr, "\007"); } else if(ret == CL_CLEAN) { if(!printinfected && printclean) mprintf("~%s: OK\n", filename); } else if(!printinfected) logg("~%s: %s\n", filename, cl_strerror(ret)); close(fd); if(ret == CL_VIRUS) { if(opt_check(opt, "remove")) { if(unlink(filename)) { logg("^%s: Can't remove\n", filename); info.notremoved++; } else { logg("~%s: Removed\n", filename); } } else if(opt_check(opt, "move") || opt_check(opt, "copy")) move_infected(filename, opt); } return ret; }
int main(int argc, char **argv) { int ds, dms, ret; double mb; struct timeval t1, t2; #ifndef C_WINDOWS struct timezone tz; sigset_t sigset; #endif struct optstruct *opt; const char *pt; #if defined(C_WINDOWS) && defined(CL_THREAD_SAFE) if(!pthread_win32_process_attach_np()) { mprintf("!Can't start the win32 pthreads layer\n"); return 72; } #endif #if !defined(C_WINDOWS) && !defined(C_BEOS) sigemptyset(&sigset); sigaddset(&sigset, SIGXFSZ); sigprocmask(SIG_SETMASK, &sigset, NULL); #endif opt = opt_parse(argc, argv, clamscan_shortopt, clamscan_longopt, NULL, clamscan_deprecated); if(!opt) { mprintf("!Can't parse the command line\n"); return 40; } if(opt_check(opt, "verbose")) { mprintf_verbose = 1; logg_verbose = 1; } if(opt_check(opt, "quiet")) mprintf_quiet = 1; if(opt_check(opt, "stdout")) mprintf_stdout = 1; if(opt_check(opt, "debug")) { #if defined(C_LINUX) /* [email protected]: create a dump if needed */ struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; if(setrlimit(RLIMIT_CORE, &rlim) < 0) perror("setrlimit"); #endif cl_debug(); /* enable debug messages */ } if(opt_check(opt, "version")) { print_version(opt_arg(opt, "database")); opt_free(opt); return 0; } if(opt_check(opt, "help")) { opt_free(opt); help(); return 0; } if(opt_check(opt, "recursive")) recursion = 1; if(opt_check(opt, "infected")) printinfected = 1; if(opt_check(opt, "bell")) bell = 1; if(opt_check(opt, "tempdir")) cl_settempdir(opt_arg(opt, "tempdir"), 0); if(opt_check(opt, "leave-temps")) cl_settempdir(NULL, 1); /* initialize logger */ if(opt_check(opt, "log")) { logg_file = opt_arg(opt, "log"); if(logg("#\n-------------------------------------------------------------------------------\n\n")) { mprintf("!Problem with internal logger.\n"); opt_free(opt); return 62; } } else logg_file = NULL; /* validate some numerical options */ if(opt_check(opt, "max-scansize")) { pt = opt_arg(opt, "max-scansize"); if(!strchr(pt, 'M') && !strchr(pt, 'm')) { if(!cli_isnumber(pt)) { logg("!--max-scansize requires a natural number\n"); opt_free(opt); return 40; } } } if(opt_check(opt, "max-filesize")) { pt = opt_arg(opt, "max-filesize"); if(!strchr(pt, 'M') && !strchr(pt, 'm')) { if(!cli_isnumber(pt)) { logg("!--max-filesize requires a natural number\n"); opt_free(opt); return 40; } } } if(opt_check(opt, "max-files")) { if(!cli_isnumber(opt_arg(opt, "max-files"))) { logg("!--max-files requires a natural number\n"); opt_free(opt); return 40; } } if(opt_check(opt, "max-recursion")) { if(!cli_isnumber(opt_arg(opt, "max-recursion"))) { logg("!--max-recursion requires a natural number\n"); opt_free(opt); return 40; } } if(opt_check(opt, "max-mail-recursion")) { if(!cli_isnumber(opt_arg(opt, "max-mail-recursion"))) { logg("!--max-mail-recursion requires a natural number\n"); opt_free(opt); return 40; } } if(opt_check(opt, "max-dir-recursion")) { if(!cli_isnumber(opt_arg(opt, "max-dir-recursion"))) { logg("!--max-dir-recursion requires a natural number\n"); opt_free(opt); return 40; } } if(opt_check(opt, "max-ratio")) { if(!cli_isnumber(opt_arg(opt, "max-ratio"))) { logg("!--max-ratio requires a natural number\n"); opt_free(opt); return 40; } } memset(&info, 0, sizeof(struct s_info)); #ifdef _WIN32 SetConsoleCtrlHandler((PHANDLER_ROUTINE) clamscan_ctrl_handler, TRUE); #endif #ifdef C_WINDOWS _set_fmode(_O_BINARY); #ifdef CL_DEBUG { _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); } #endif gettimeofday(&t1, NULL); #else gettimeofday(&t1, &tz); #endif ret = scanmanager(opt); if(!opt_check(opt, "disable-summary") && !opt_check(opt, "no-summary")) { #ifdef C_WINDOWS gettimeofday(&t2, NULL); #else gettimeofday(&t2, &tz); #endif ds = t2.tv_sec - t1.tv_sec; dms = t2.tv_usec - t1.tv_usec; ds -= (dms < 0) ? (1):(0); dms += (dms < 0) ? (1000000):(0); logg("\n----------- SCAN SUMMARY -----------\n"); logg("Known viruses: %u\n", info.sigs); logg("Engine version: %s\n", get_version()); logg("Scanned directories: %u\n", info.dirs); logg("Scanned files: %u\n", info.files); logg("Infected files: %u\n", info.ifiles); if(info.notremoved) { logg("Not removed: %u\n", info.notremoved); } if(info.notmoved) { logg("Not %s: %u\n", opt_check(opt, "copy") ? "moved" : "copied", info.notmoved); } mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0; logg("Data scanned: %2.2lf MB\n", mb); logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms/1000, ds/60, ds%60); } opt_free(opt); #if defined(C_WINDOWS) && defined(CL_THREAD_SAFE) if(!pthread_win32_process_detach_np()) { logg("!Can't stop the win32 pthreads layer\n"); return 72; } #endif return ret; }
static void opt_parse(int argc, char **argv, t_options *opt) { int argval, n, opt_set[opt_last]; /* initialize `opt_set' with the value 0 (option not used) */ for (n = 0; n < opt_last; n++) opt_set[n] = opt_unset; /* process the options */ opterr = 0; while (1) { argval = getopt_long(argc, argv, optstring, longopts, NULL); if (argval == -1) break; switch (argval) { case 0: break; case 'c': opt_set[opt_c]++; opt->action = crypt_ios; break; case 's': /* set the salt string (4 character long) */ opt_set[opt_s]++; opt->action = crypt_ios; if (strlen(optarg) != MD5_SALT_SIZE) tty_error(ERR_USAGE, "bad length (not %d bytes) for salt `%s'", MD5_SALT_SIZE, optarg); opt->cryptopt.salt = (u_char *) str_alloc_copy(optarg); break; #ifdef EGD_SUPPORT case 'e': opt_set[opt_e]++; opt->cryptopt.get_entropy = get_egd_entropy; if (optarg) opt->cryptopt.egd_path = str_alloc_copy(optarg); break; #endif #ifdef DEV_RANDOM_SUPPORT case 'd': opt_set[opt_d]++; opt->cryptopt.get_entropy = get_dev_entropy; break; #endif #if defined (EGD_SUPPORT) || defined (DEV_RANDOM_SUPPORT) case 'y': opt_set[opt_y]++; opt->cryptopt.get_entropy = get_sys_entropy; break; #endif case 'p': opt_set[opt_p]++; opt->action = crypt_pix; break; case 'l': opt_set[opt_l]++; n = sscanf(optarg, "%d:%d", &opt->decryptopt.fromlen, &opt->decryptopt.tolen); switch (n) { case 0: /* option --length used with no values */ usage(ERR_USAGE); break; case 1: /* only 'fromlen' set */ opt->decryptopt.tolen = opt->decryptopt.fromlen; case 2: if (opt->decryptopt.fromlen > opt->decryptopt.tolen) tty_error(ERR_USAGE, "bad order for `--length' limits"); if (opt->decryptopt.fromlen < 1) tty_error(ERR_USAGE, "illegal downlimit for `--length'"); if (opt->decryptopt.tolen > MAX_PLAIN_SIZE) tty_error(ERR_USAGE, "the `--length' upperlimit exceed `%d'", MAX_PLAIN_SIZE); } break; case 'b': /* try the brute-force attack */ opt_set[opt_b]++; opt->action = decrypt_bf; if (optarg) opt->decryptopt.regexpr = str_alloc_copy(optarg); break; case 'w': /* try the vocabulary attack */ opt_set[opt_w]++; opt->action = decrypt_wl; opt->decryptopt.wordlist = str_alloc_copy(optarg); break; #if defined (HAVE_WORKING_FORK) case 'D': opt_set[opt_D]++; opt->daemonize = 1; break; #endif case 'r': opt_set[opt_r]++; opt->action = resume; /* default rescue file is `RESTORE_FILE' */ opt->decryptopt.restore_file = optarg ? str_alloc_copy(optarg) : str_alloc_copy(RESTORE_FILE); break; case 'q': /* minimize the program output */ opt_set[opt_q]++; opt->verbose = 0; break; case 'h': /* help */ #if 0 opt_set[opt_h]++; #endif usage(SUCCESS); break; case 'v': /* verbose mode */ opt_set[opt_v]++; opt->verbose++; break; case 'L': #if 0 opt_set[opt_L]++; #endif license(); /* GPL license message */ exit(SUCCESS); break; case 'V': /* program name, version, etc. */ #if 0 opt_set[opt_V]++; #endif version(); exit(SUCCESS); break; case '?': tty_error(ERR_USAGE, "ambiguous match or extraneous parameter `%s'", argv[optind - 1]); break; default: /* should catch nothing (?) */ tty_error(ERR_USAGE, "illegal command line argument"); } } /* check for option inconsistences */ opt_check(opt_set); }