174
130
*sfx_check = metadata->crc;
177
cli_dbgmsg("RAR: %s, crc32: 0x%x, encrypted: %u, compressed: %u, normal: %u, method: %u, ratio: %u\n",
178
metadata->filename, metadata->crc, metadata->encrypted, (unsigned int) metadata->pack_size,
179
(unsigned int) metadata->unpack_size, metadata->method,
180
metadata->pack_size ? (unsigned int) (metadata->unpack_size / metadata->pack_size) : 0);
182
if(cli_matchmeta(ctx, metadata->filename, metadata->pack_size, metadata->unpack_size, metadata->encrypted, files, metadata->crc, NULL) == CL_VIRUS)
133
cli_dbgmsg("RAR: %s, crc32: 0x%x, encrypted: %d, compressed: %u, normal: %u, method: %d, ratio: %d (max: %d)\n",
134
metadata->filename, metadata->crc, metadata->encrypted, metadata->pack_size,
135
metadata->unpack_size, metadata->method,
136
metadata->pack_size ? ((unsigned int) metadata->unpack_size / (unsigned int) metadata->pack_size) : 0, ctx->limits ? ctx->limits->maxratio : 0);
139
mdata = ctx->engine->rar_mlist;
141
if(mdata->encrypted != metadata->encrypted)
144
if(mdata->crc32 && (unsigned int) mdata->crc32 != metadata->crc)
147
if(mdata->csize > 0 && (unsigned int) mdata->csize != metadata->pack_size)
150
if(mdata->size >= 0 && (unsigned int) mdata->size != metadata->unpack_size)
153
if(mdata->method >= 0 && mdata->method != metadata->method)
156
if(mdata->fileno && mdata->fileno != files)
159
if(mdata->maxdepth && ctx->arec > mdata->maxdepth)
162
/* TODO add support for regex */
163
/*if(mdata->filename && !strstr(zdirent.d_name, mdata->filename))*/
164
if(mdata->filename && strcmp((char *) metadata->filename, mdata->filename))
169
} while((mdata = mdata->next));
172
*ctx->virname = mdata->virname;
185
176
if(DETECT_ENCRYPTED && metadata->encrypted) {
186
177
cli_dbgmsg("RAR: Encrypted files found in archive.\n");
187
178
lseek(desc, 0, SEEK_SET);
188
ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
179
ret = cli_scandesc(desc, ctx, 0, 0, 0, NULL);
189
180
if(ret != CL_VIRUS) {
190
*ctx->virname = "Heuristics.Encrypted.RAR";
181
*ctx->virname = "Encrypted.RAR";
187
TROG - TODO: multi-volume files
188
if((rarlist->item.Flags & 0x03) != 0) {
189
cli_dbgmsg("RAR: Skipping %s (split)\n", rarlist->item.Name);
190
rarlist = rarlist->next;
197
static int cli_unrar_checklimits(const cli_ctx *ctx, const rar_metadata_t *metadata, unsigned int files)
200
if(ctx->limits->maxratio && metadata->unpack_size && metadata->pack_size) {
201
if(metadata->unpack_size / metadata->pack_size >= ctx->limits->maxratio) {
202
cli_dbgmsg("RAR: Max ratio reached (normal: %Lu, compressed: %Lu, max: %u)\n", metadata->unpack_size, metadata->pack_size, ctx->limits->maxratio);
204
*ctx->virname = "Oversized.RAR";
211
if(ctx->limits->maxfilesize && (metadata->unpack_size > ctx->limits->maxfilesize)) {
212
cli_dbgmsg("RAR: %s: Size exceeded (%Lu, max: %lu)\n", metadata->filename, metadata->unpack_size, ctx->limits->maxfilesize);
214
*ctx->virname = "RAR.ExceededFileSize";
220
if(ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) {
221
cli_dbgmsg("RAR: Files limit reached (max: %u)\n", ctx->limits->maxfiles);
223
*ctx->virname = "RAR.ExceededFilesLimit";
198
233
static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
200
235
int ret = CL_CLEAN;
201
unrar_metadata_t *metadata, *metadata_tmp;
236
rar_metadata_t *metadata, *metadata_tmp;
203
unrar_state_t rar_state;
238
rar_state_t rar_state;
206
241
cli_dbgmsg("in scanrar()\n");
209
if(lseek(desc, sfx_offset, SEEK_SET) == -1)
212
243
/* generate the temporary directory */
213
if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
244
dir = cli_gentemp(NULL);
216
245
if(mkdir(dir, 0700)) {
217
246
cli_dbgmsg("RAR: Can't create temporary directory %s\n", dir);
219
248
return CL_ETMPDIR;
222
if((ret = cli_unrar_open(desc, dir, &rar_state)) != UNRAR_OK) {
223
if(!ctx->engine->keeptmp)
252
lseek(desc, sfx_offset, SEEK_SET);
254
if((ret = cli_unrar_open(desc, dir, &rar_state)) != CL_SUCCESS) {
255
if(!cli_leavetemps_flag)
226
if(ret == UNRAR_PASSWD) {
227
cli_dbgmsg("RAR: Encrypted main header\n");
228
if(DETECT_ENCRYPTED) {
229
lseek(desc, 0, SEEK_SET);
230
ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
232
*ctx->virname = "Heuristics.Encrypted.RAR";
236
} if(ret == UNRAR_EMEM) {
258
cli_dbgmsg("RAR: Error: %s\n", cl_strerror(ret));
264
rar_state.unpack_data->ofd = -1;
246
265
ret = cli_unrar_extract_next_prepare(&rar_state,dir);
247
if(ret != UNRAR_OK) {
248
if(ret == UNRAR_BREAK)
250
else if(ret == UNRAR_EMEM)
266
if(ret != CL_SUCCESS)
256
if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
268
ret = cli_unrar_checklimits(ctx, rar_state.metadata_tail, rar_state.file_count);
269
if(ret && ret != CL_VIRUS) {
257
270
free(rar_state.file_header->filename);
258
271
free(rar_state.file_header);
274
} else if(ret == CL_VIRUS) {
275
/* needed since we didn't reach unrar_extract_next to clean this up*/
276
free(rar_state.file_header->filename);
277
free(rar_state.file_header);
262
if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
263
rar_state.maxfilesize = ctx->engine->maxscansize - ctx->scansize;
265
rar_state.maxfilesize = ctx->engine->maxfilesize;
267
280
ret = cli_unrar_extract_next(&rar_state,dir);
270
else if(ret == UNRAR_EMEM)
275
if(rar_state.ofd > 0) {
276
lseek(rar_state.ofd,0,SEEK_SET);
277
rc = cli_magic_scandesc(rar_state.ofd,ctx);
278
close(rar_state.ofd);
279
if(!ctx->engine->keeptmp)
280
if (cli_unlink(rar_state.filename)) ret = CL_EUNLINK;
281
if(rar_state.unpack_data->ofd > 0) {
282
lseek(rar_state.unpack_data->ofd,0,SEEK_SET);
283
rc = cli_magic_scandesc(rar_state.unpack_data->ofd,ctx);
284
close(rar_state.unpack_data->ofd);
285
if(!cli_leavetemps_flag)
286
unlink(rar_state.filename);
281
287
if(rc == CL_VIRUS ) {
282
288
cli_dbgmsg("RAR: infected with %s\n",*ctx->virname);
320
static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
327
static int cli_scanzip(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
322
int ret = CL_CLEAN, rc, file = 0;
323
arj_metadata_t metadata;
326
cli_dbgmsg("in cli_scanarj()\n");
328
/* generate the temporary directory */
329
if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
333
char *tmpname = NULL, *buff;
334
int fd, bytes, ret = CL_CLEAN;
335
unsigned long int size = 0;
336
unsigned int files = 0, encrypted, bfcnt;
338
struct cli_meta_node *mdata;
340
uint8_t swarning = 0, fail, success;
343
cli_dbgmsg("in scanzip()\n");
345
if((zdir = zip_dir_open(desc, sfx_offset, &err)) == NULL) {
346
cli_dbgmsg("Zip: zip_dir_open() return code: %d\n", err);
347
/* no return with CL_EZIP due to password protected zips */
351
fstat(desc, &source);
353
if(!(buff = (char *) cli_malloc(FILEBUFF))) {
354
cli_dbgmsg("Zip: unable to malloc(%u)\n", FILEBUFF);
332
if(mkdir(dir, 0700)) {
333
cli_dbgmsg("ARJ: Can't create temporary directory %s\n", dir);
339
lseek(desc, sfx_offset, SEEK_SET);
341
ret = cli_unarj_open(desc, dir);
342
if (ret != CL_SUCCESS) {
343
if(!ctx->engine->keeptmp)
346
cli_dbgmsg("ARJ: Error: %s\n", cl_strerror(ret));
351
metadata.filename = NULL;
352
ret = cli_unarj_prepare_file(desc, dir, &metadata);
353
if (ret != CL_SUCCESS) {
357
if(cli_matchmeta(ctx, metadata.filename, metadata.comp_size, metadata.orig_size, metadata.encrypted, file, 0, NULL) == CL_VIRUS)
360
if ((ret = cli_checklimits("ARJ", ctx, metadata.orig_size, metadata.comp_size, 0))!=CL_CLEAN) {
362
if (metadata.filename)
363
free(metadata.filename);
366
ret = cli_unarj_extract_file(desc, dir, &metadata);
367
if (metadata.ofd >= 0) {
368
lseek(metadata.ofd, 0, SEEK_SET);
369
rc = cli_magic_scandesc(metadata.ofd, ctx);
371
if (rc == CL_VIRUS) {
372
cli_dbgmsg("ARJ: infected with %s\n",*ctx->virname);
374
if (metadata.filename) {
375
free(metadata.filename);
376
metadata.filename = NULL;
381
if (metadata.filename) {
382
free(metadata.filename);
383
metadata.filename = NULL;
386
} while(ret == CL_SUCCESS);
388
if(!ctx->engine->keeptmp)
392
if (metadata.filename) {
393
free(metadata.filename);
396
cli_dbgmsg("ARJ: Exit code: %d\n", ret);
404
static int cli_scangzip_with_zib_from_the_80s(cli_ctx *ctx, unsigned char *buff) {
405
int fd, ret, outsize = 0, bytes;
406
fmap_t *map = *ctx->fmap;
414
lseek(fd, 0, SEEK_SET);
415
if(!(gz = gzdopen(fd, "rb"))) {
420
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
421
cli_dbgmsg("GZip: Can't generate temporary file.\n");
426
while((bytes = gzread(gz, buff, FILEBUFF)) > 0) {
428
if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN)
430
if(cli_writen(fd, buff, bytes) != bytes) {
433
if(cli_unlink(tmpname)) {
359
while(zip_dir_read(zdir, &zdirent)) {
362
if(files == 1 && sfx_check) {
363
if(*sfx_check == zdirent.d_crc32)
366
*sfx_check = zdirent.d_crc32;
369
if(!zdirent.d_name) {
370
cli_dbgmsg("Zip: zdirent.d_name == NULL\n");
371
*ctx->virname = "Suspect.Zip";
376
/* Bit 0: file is encrypted
377
* Bit 6: Strong encryption was used
378
* Bit 13: Encrypted central directory
380
encrypted = ((zdirent.d_flags & 0x2041) != 0);
382
cli_dbgmsg("Zip: %s, crc32: 0x%x, offset: %d, encrypted: %d, compressed: %u, normal: %u, method: %d, ratio: %d (max: %d)\n", zdirent.d_name, zdirent.d_crc32, zdirent.d_off, encrypted, zdirent.d_csize, zdirent.st_size, zdirent.d_compr, zdirent.d_csize ? (zdirent.st_size / zdirent.d_csize) : 0, ctx->limits ? ctx->limits->maxratio : 0);
384
if(!zdirent.st_size) {
385
if(zdirent.d_crc32) {
386
cli_dbgmsg("Zip: Broken file or modified information in local header part of archive\n");
387
*ctx->virname = "Exploit.Zip.ModifiedHeaders";
395
mdata = ctx->engine->zip_mlist;
397
if(mdata->encrypted != encrypted)
400
if(mdata->crc32 && mdata->crc32 != zdirent.d_crc32)
403
if(mdata->csize > 0 && (uint32_t) mdata->csize != zdirent.d_csize)
406
if(mdata->size >= 0 && (uint32_t) mdata->size != zdirent.st_size)
409
if(mdata->method >= 0 && (uint16_t) mdata->method != zdirent.d_compr)
412
if(mdata->fileno && mdata->fileno != files)
415
if(mdata->maxdepth && ctx->arec > mdata->maxdepth)
418
/* TODO add support for regex */
419
/*if(mdata->filename && !strstr(zdirent.d_name, mdata->filename))*/
420
if(mdata->filename && strcmp(zdirent.d_name, mdata->filename))
425
} while((mdata = mdata->next));
428
*ctx->virname = mdata->virname;
434
* Workaround for archives created with ICEOWS.
435
* ZZIP_DIRENT does not contain information on file type
436
* so we try to determine a directory via a filename
438
if(zdirent.d_name[strlen(zdirent.d_name) - 1] == '/') {
439
cli_dbgmsg("Zip: Directory entry with st_size != 0\n");
443
if(!zdirent.d_csize) {
444
cli_dbgmsg("Zip: Malformed file (d_csize == 0 but st_size != 0)\n");
445
*ctx->virname = "Suspect.Zip";
450
if(ctx->limits && ctx->limits->maxratio > 0 && ((unsigned) zdirent.st_size / (unsigned) zdirent.d_csize) >= ctx->limits->maxratio) {
451
*ctx->virname = "Oversized.Zip";
456
if(DETECT_ENCRYPTED && encrypted) {
457
cli_dbgmsg("Zip: Encrypted files found in archive.\n");
458
lseek(desc, 0, SEEK_SET);
459
ret = cli_scandesc(desc, ctx, 0, 0, 0, NULL);
462
} else if(ret != CL_VIRUS) {
463
*ctx->virname = "Encrypted.Zip";
470
if(ctx->limits->maxfilesize && ((unsigned int) zdirent.st_size > ctx->limits->maxfilesize)) {
471
cli_dbgmsg("Zip: %s: Size exceeded (%d, max: %ld)\n", zdirent.d_name, zdirent.st_size, ctx->limits->maxfilesize);
472
/* ret = CL_EMAXSIZE; */
474
*ctx->virname = "Zip.ExceededFileSize";
478
continue; /* continue scanning */
481
if(ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) {
482
cli_dbgmsg("Zip: Files limit reached (max: %d)\n", ctx->limits->maxfiles);
484
*ctx->virname = "Zip.ExceededFilesLimit";
492
if((zfp = zip_file_open(zdir, zdirent.d_name, zdirent.d_off)) == NULL) {
493
if(zdir->errcode == CL_ESUPPORT) {
496
cli_warnmsg("Not supported compression method in one or more files\n");
501
cli_dbgmsg("Zip: Can't open file %s\n", zdirent.d_name);
512
/* generate temporary file and get its descriptor */
513
if((tmpname = cli_gentempstream(NULL, &tmp)) == NULL) {
514
cli_dbgmsg("Zip: Can't generate tmpfile().\n");
520
while((bytes = zip_file_read(zfp, buff, FILEBUFF)) > 0) {
522
if(fwrite(buff, 1, bytes, tmp) != (size_t) bytes) {
523
cli_dbgmsg("Zip: Can't write to file.\n");
530
if(size != zdirent.st_size) {
531
cli_dbgmsg("Zip: Incorrectly decompressed (%d != %d)\n", size, zdirent.st_size);
532
if(zfp->bf[0] == -1) {
539
cli_dbgmsg("Zip: File decompressed to %s\n", tmpname);
545
if(fflush(tmp) != 0) {
546
cli_dbgmsg("Zip: fflush() failed\n");
553
lseek(fd, 0, SEEK_SET);
555
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
556
cli_dbgmsg("Zip: Infected with %s\n", *ctx->virname);
565
if(!cli_leavetemps_flag)
571
if(zfp->bf[bfcnt] == -1)
574
zfp->method = (uint16_t) zfp->bf[bfcnt];
575
cli_dbgmsg("Zip: Brute force mode - checking compression method %u\n", zfp->method);
581
if(!ret && !encrypted && !success) { /* brute-force decompression failed */
582
cli_dbgmsg("Zip: All attempts to decompress file failed\n");
444
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
445
cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
447
if(!ctx->engine->keeptmp) {
448
if (cli_unlink(tmpname)) {
593
if(!cli_leavetemps_flag)
457
if(!ctx->engine->keeptmp)
458
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
463
static int cli_scangzip(cli_ctx *ctx)
603
static int cli_scangzip(int desc, cli_ctx *ctx)
465
int fd, ret = CL_CLEAN;
466
unsigned char buff[FILEBUFF];
605
int fd, bytes, ret = CL_CLEAN;
606
unsigned long int size = 0;
469
size_t at = 0, outsize = 0;
470
fmap_t *map = *ctx->fmap;
472
613
cli_dbgmsg("in cli_scangzip()\n");
474
memset(&z, 0, sizeof(z));
475
if((ret = inflateInit2(&z, MAX_WBITS + 16)) != Z_OK) {
476
cli_dbgmsg("GZip: InflateInit failed: %d\n", ret);
477
return cli_scangzip_with_zib_from_the_80s(ctx, buff);
615
if((gd = gzdopen(dup(desc), "rb")) == NULL) {
616
cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
480
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
620
if((tmpname = cli_gentempstream(NULL, &tmp)) == NULL) {
481
621
cli_dbgmsg("GZip: Can't generate temporary file.\n");
627
if(!(buff = (char *) cli_malloc(FILEBUFF))) {
628
cli_dbgmsg("GZip: Unable to malloc %d bytes.\n", FILEBUFF);
631
if(!cli_leavetemps_flag)
637
while((bytes = gzread(gd, buff, FILEBUFF)) > 0) {
641
if(ctx->limits->maxfilesize && (size + FILEBUFF > ctx->limits->maxfilesize)) {
642
cli_dbgmsg("GZip: Size exceeded (stopped at %ld, max: %ld)\n", size, ctx->limits->maxfilesize);
644
*ctx->virname = "GZip.ExceededFileSize";
650
if(cli_writen(fd, buff, bytes) != bytes) {
651
cli_dbgmsg("GZip: Can't write to file.\n");
653
if(!cli_leavetemps_flag)
665
if(ret == CL_VIRUS) {
667
if(!cli_leavetemps_flag)
486
while (at < map->len) {
487
unsigned int bytes = MIN(map->len - at, map->pgsz);
488
if(!(z.next_in = fmap_need_off_once(map, at, bytes))) {
489
cli_dbgmsg("GZip: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
492
if (cli_unlink(tmpname)) {
503
z.avail_out = sizeof(buff);
505
inf = inflate(&z, Z_NO_FLUSH);
506
if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
507
cli_dbgmsg("GZip: Bad stream.\n");
511
if(cli_writen(fd, buff, sizeof(buff) - z.avail_out) < 0) {
514
if (cli_unlink(tmpname)) {
521
outsize += sizeof(buff) - z.avail_out;
522
if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN) {
526
if(inf == Z_STREAM_END) {
531
} while (z.avail_out == 0);
673
if(fsync(fd) == -1) {
674
cli_dbgmsg("GZip: Can't synchronise descriptor %d\n", fd);
676
if(!cli_leavetemps_flag)
536
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
682
lseek(fd, 0, SEEK_SET);
683
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
537
684
cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
539
if(!ctx->engine->keeptmp) {
540
if (cli_unlink(tmpname)) {
686
if(!cli_leavetemps_flag)
549
if(!ctx->engine->keeptmp)
550
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
692
if(!cli_leavetemps_flag)
557
static int cli_scanbzip(int desc, cli_ctx *ctx) {
558
cli_warnmsg("cli_scanbzip: bzip2 support not compiled in\n");
564
702
#ifdef NOBZ2PREFIX
565
703
#define BZ2_bzReadOpen bzReadOpen
780
1012
struct stat statbuf;
781
char *fullname, vbaname[1024];
1013
char *fname, *fullname;
782
1014
unsigned char *data;
787
1017
cli_dbgmsg("VBADir: %s\n", dirname);
788
hashcnt = uniq_get(U, "_vba_project", 12, NULL);
790
if(!(vba_project = (vba_project_t *)cli_vba_readdir(dirname, U, hashcnt))) continue;
1018
if((vba_project = (vba_project_t *) vba56_dir_read(dirname))) {
792
1020
for(i = 0; i < vba_project->count; i++) {
793
for(j = 0; (unsigned int)j < vba_project->colls[i]; j++) {
794
snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
795
vbaname[sizeof(vbaname)-1] = '\0';
796
fd = open(vbaname, O_RDONLY|O_BINARY);
797
if(fd == -1) continue;
798
cli_dbgmsg("VBADir: Decompress VBA project '%s_%u'\n", vba_project->name[i], j);
799
data = (unsigned char *)cli_vba_inflate(fd, vba_project->offset[i], &data_len);
803
cli_dbgmsg("VBADir: WARNING: VBA project '%s_%u' decompressed to NULL\n", vba_project->name[i], j);
805
/* cli_dbgmsg("Project content:\n%s", data); */
807
*ctx->scanned += data_len / CL_COUNT_PRECISION;
808
if(cli_scanbuff(data, data_len, 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
1021
fullname = (char *) cli_malloc(strlen(vba_project->dir) + strlen(vba_project->name[i]) + 2);
1026
sprintf(fullname, "%s/%s", vba_project->dir, vba_project->name[i]);
1027
fd = open(fullname, O_RDONLY|O_BINARY);
1029
cli_dbgmsg("VBADir: Can't open file %s\n", fullname);
1035
cli_dbgmsg("VBADir: Decompress VBA project '%s'\n", vba_project->name[i]);
1036
data = (unsigned char *) vba_decompress(fd, vba_project->offset[i], &data_len);
1040
cli_dbgmsg("VBADir: WARNING: VBA project '%s' decompressed to NULL\n", vba_project->name[i]);
1043
*ctx->scanned += data_len / CL_COUNT_PRECISION;
1045
if(cli_scanbuff(data, data_len, ctx->virname, ctx->engine, CL_TYPE_MSOLE2) == CL_VIRUS) {
1055
for(i = 0; i < vba_project->count; i++)
1056
free(vba_project->name[i]);
818
1057
free(vba_project->name);
819
free(vba_project->colls);
820
1058
free(vba_project->dir);
821
1059
free(vba_project->offset);
822
1060
free(vba_project);
823
if (ret == CL_VIRUS) break;
826
if(ret == CL_CLEAN && (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
828
snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
829
vbaname[sizeof(vbaname)-1] = '\0';
830
fd = open(vbaname, O_RDONLY|O_BINARY);
831
if (fd == -1) continue;
832
if ((fullname = cli_ppt_vba_read(fd, ctx))) {
834
if(cli_scandir(fullname, ctx) == CL_VIRUS) {
837
if(!ctx->engine->keeptmp)
838
cli_rmdirs(fullname);
1061
} else if ((fullname = ppt_vba_read(dirname))) {
1062
if(cli_scandir(fullname, ctx) == CL_VIRUS) {
1065
if(!cli_leavetemps_flag)
1066
cli_rmdirs(fullname);
1068
} else if ((vba_project = (vba_project_t *) wm_dir_read(dirname))) {
1069
for (i = 0; i < vba_project->count; i++) {
1070
fullname = (char *) cli_malloc(strlen(vba_project->dir) + strlen(vba_project->name[i]) + 2);
1075
sprintf(fullname, "%s/%s", vba_project->dir, vba_project->name[i]);
1076
fd = open(fullname, O_RDONLY|O_BINARY);
1078
cli_dbgmsg("VBADir: Can't open file %s\n", fullname);
845
if (ret == CL_CLEAN && (hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
847
snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
848
vbaname[sizeof(vbaname)-1] = '\0';
849
fd = open(vbaname, O_RDONLY|O_BINARY);
850
if (fd == -1) continue;
852
if (!(vba_project = (vba_project_t *)cli_wm_readdir(fd))) {
1084
cli_dbgmsg("VBADir: Decompress WM project '%s' macro:%d key:%d length:%d\n", vba_project->name[i], i, vba_project->key[i], vba_project->length[i]);
1085
if(vba_project->length[i])
1086
data = (unsigned char *) wm_decrypt_macro(fd, vba_project->offset[i], vba_project->length[i], vba_project->key[i]);
857
for (i = 0; i < vba_project->count; i++) {
858
cli_dbgmsg("VBADir: Decompress WM project macro:%d key:%d length:%d\n", i, vba_project->key[i], vba_project->length[i]);
859
data = (unsigned char *)cli_wm_decrypt_macro(fd, vba_project->offset[i], vba_project->length[i], vba_project->key[i]);
862
1092
cli_dbgmsg("VBADir: WARNING: WM project '%s' macro %d decrypted to NULL\n", vba_project->name[i], i);
864
cli_dbgmsg("Project content:\n%s", data);
865
1094
if(ctx->scanned)
866
1095
*ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION;
867
if(cli_scanbuff(data, vba_project->length[i], 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
1096
if(cli_scanbuff(data, vba_project->length[i], ctx->virname, ctx->engine, CL_TYPE_MSOLE2) == CL_VIRUS) {
877
free(vba_project->name);
878
free(vba_project->colls);
879
free(vba_project->dir);
880
free(vba_project->offset);
881
free(vba_project->key);
882
free(vba_project->length);
884
if(ret == CL_VIRUS) break;
1104
for(i = 0; i < vba_project->count; i++)
1105
free(vba_project->name[i]);
1106
free(vba_project->key);
1107
free(vba_project->length);
1108
free(vba_project->offset);
1109
free(vba_project->name);
1110
free(vba_project->dir);
888
1114
if(ret != CL_CLEAN)
891
1117
/* Check directory for embedded OLE objects */
892
hashcnt = uniq_get(U, "_1_ole10native", 14, &hash);
894
snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
895
vbaname[sizeof(vbaname)-1] = '\0';
1118
fullname = (char *) cli_malloc(strlen(dirname) + 16);
897
fd = open(vbaname, O_RDONLY|O_BINARY);
899
ret = cli_scan_ole10(fd, ctx);
1122
sprintf(fullname, "%s/_1_Ole10Native", dirname);
1123
fd = open(fullname, O_RDONLY|O_BINARY);
1126
ofd = cli_decode_ole_object(fd, dirname);
1128
ret = cli_scandesc(ofd, ctx, 0, 0, 0, NULL);
907
/* ACAB: since we now hash filenames and handle collisions we
908
* could avoid recursion by removing the block below and by
909
* flattening the paths in ole2_walk_property_tree (case 1) */
911
1136
if((dd = opendir(dirname)) != NULL) {
912
1137
#ifdef HAVE_READDIR_R_3
913
1138
while(!readdir_r(dd, &result.d, &dent) && dent) {
949
if(BLOCK_MACROS && hasmacros) {
950
*ctx->virname = "Heuristics.OLE2.ContainsMacros";
956
static int cli_scanhtml(cli_ctx *ctx)
1179
static int cli_scanhtml(int desc, cli_ctx *ctx)
958
1181
char *tempname, fullname[1024];
959
1182
int ret=CL_CLEAN, fd;
960
fmap_t *map = *ctx->fmap;
962
1186
cli_dbgmsg("in cli_scanhtml()\n");
1188
if(fstat(desc, &sb) == -1) {
1189
cli_errmsg("cli_scanhtml: fstat() failed for descriptor %d\n", desc);
964
1193
/* Because HTML detection is FP-prone and html_normalise_fd() needs to
965
1194
* mmap the file don't normalise files larger than 10 MB.
968
if(map->len > 10485760) {
1196
if(sb.st_size > 10485760) {
969
1197
cli_dbgmsg("cli_scanhtml: exiting (file larger than 10 MB)\n");
970
1198
return CL_CLEAN;
973
if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
1201
tempname = cli_gentemp(NULL);
976
1202
if(mkdir(tempname, 0700)) {
977
1203
cli_errmsg("cli_scanhtml: Can't create temporary directory %s\n", tempname);
979
1205
return CL_ETMPDIR;
982
cli_dbgmsg("cli_scanhtml: using tempdir %s\n", tempname);
984
html_normalise_map(map, tempname, NULL, ctx->dconf);
985
snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname);
1208
html_normalise_fd(desc, tempname, NULL);
1209
snprintf(fullname, 1024, "%s/comment.html", tempname);
986
1210
fd = open(fullname, O_RDONLY|O_BINARY);
988
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL);
992
if(ret == CL_CLEAN && map->len < 2097152) {
993
/* limit to 2 MB, we're not interesting in scanning large files in notags form */
994
/* TODO: don't even create notags if file is over 2 MB */
995
snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname);
996
fd = open(fullname, O_RDONLY|O_BINARY);
998
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL);
1003
if(ret == CL_CLEAN) {
1004
snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname);
1005
fd = open(fullname, O_RDONLY|O_BINARY);
1007
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL);
1008
if (ret == CL_CLEAN) {
1009
lseek(fd, 0, SEEK_SET);
1010
ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR, NULL);
1016
if (ret == CL_CLEAN) {
1017
snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname);
1018
ret = cli_scandir(fullname, ctx);
1021
if(!ctx->engine->keeptmp)
1212
ret = cli_scandesc(fd, ctx, 0, CL_TYPE_HTML, 0, NULL);
1216
if(ret < 0 || ret == CL_VIRUS) {
1217
if(!cli_leavetemps_flag)
1218
cli_rmdirs(tempname);
1223
if (ret == CL_CLEAN) {
1224
snprintf(fullname, 1024, "%s/nocomment.html", tempname);
1225
fd = open(fullname, O_RDONLY|O_BINARY);
1227
ret = cli_scandesc(fd, ctx, 0, CL_TYPE_HTML, 0, NULL);
1232
if(ret < 0 || ret == CL_VIRUS) {
1233
if(!cli_leavetemps_flag)
1234
cli_rmdirs(tempname);
1239
if (ret == CL_CLEAN) {
1240
snprintf(fullname, 1024, "%s/script.html", tempname);
1241
fd = open(fullname, O_RDONLY|O_BINARY);
1243
ret = cli_scandesc(fd, ctx, 0, CL_TYPE_HTML, 0, NULL);
1248
if(ret < 0 || ret == CL_VIRUS) {
1249
if(!cli_leavetemps_flag)
1250
cli_rmdirs(tempname);
1255
if (ret == CL_CLEAN) {
1256
snprintf(fullname, 1024, "%s/rfc2397", tempname);
1257
ret = cli_scandir(fullname, ctx);
1260
if(!cli_leavetemps_flag)
1022
1261
cli_rmdirs(tempname);
1024
1263
free(tempname);
1028
static int cli_scanscript(cli_ctx *ctx)
1030
unsigned char *buff;
1031
unsigned char* normalized;
1032
struct text_norm_state state;
1033
char *tmpname = NULL;
1035
struct cli_matcher *troot = ctx->engine->root[7];
1036
uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
1037
struct cli_matcher *groot = ctx->engine->root[0];
1038
struct cli_ac_data gmdata, tmdata;
1039
struct cli_ac_data *mdata[2];
1040
fmap_t *map = *ctx->fmap;
1043
cli_dbgmsg("in cli_scanscript()\n");
1045
if(map->len > 5242880) {
1046
cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
1050
/* dump to disk only if explicitly asked to,
1051
* otherwise we can process just in-memory */
1052
if(ctx->engine->keeptmp) {
1053
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &ofd))) {
1054
cli_dbgmsg("cli_scanscript: Can't generate temporary file/descriptor\n");
1057
cli_dbgmsg("cli_scanscript: saving normalized file to %s\n", tmpname);
1060
if(!(normalized = cli_malloc(SCANBUFF + maxpatlen))) {
1061
cli_dbgmsg("cli_scanscript: Unable to malloc %u bytes\n", SCANBUFF);
1065
text_normalize_init(&state, normalized, SCANBUFF + maxpatlen);
1068
if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
1071
if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) {
1072
cli_ac_freedata(&tmdata);
1079
size_t len = MIN(map->pgsz, map->len - at);
1080
buff = fmap_need_off_once(map, at, len);
1082
if(!buff || !len || state.out_pos + len > state.out_len) {
1083
/* flush if error/EOF, or too little buffer space left */
1084
if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
1085
cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
1088
/* we can continue to scan in memory */
1090
/* when we flush the buffer also scan */
1091
if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1096
*ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
1097
offset += state.out_pos;
1098
/* carry over maxpatlen from previous buffer */
1099
if (state.out_pos > maxpatlen)
1100
memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
1101
text_normalize_reset(&state);
1102
state.out_pos = maxpatlen;
1105
if(text_normalize_buffer(&state, buff, len) != len) {
1106
cli_dbgmsg("cli_scanscript: short read during normalizing\n");
1109
if(ctx->engine->keeptmp) {
1114
if(ret != CL_VIRUS) {
1115
ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL);
1117
ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL);
1119
cli_ac_freedata(&tmdata);
1120
cli_ac_freedata(&gmdata);
1125
static int cli_scanhtml_utf16(cli_ctx *ctx)
1127
char *tempname, *decoded, *buff;
1267
static int cli_scanhtml_utf16(int desc, cli_ctx *ctx)
1269
char *tempname, buff[512], *decoded;
1128
1270
int ret = CL_CLEAN, fd, bytes;
1130
fmap_t *map = *ctx->fmap;
1132
1273
cli_dbgmsg("in cli_scanhtml_utf16()\n");
1134
if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
1275
tempname = cli_gentemp(NULL);
1137
1276
if((fd = open(tempname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
1138
1277
cli_errmsg("cli_scanhtml_utf16: Can't create file %s\n", tempname);
1139
1278
free(tempname);
1143
cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
1145
while(at < map->len) {
1146
bytes = MIN(map->len - at, map->pgsz * 16);
1147
if(!(buff = fmap_need_off_once(map, at, bytes))) {
1149
cli_unlink(tempname);
1282
while((bytes = read(desc, buff, sizeof(buff))) > 0) {
1154
1283
decoded = cli_utf16toascii(buff, bytes);
1156
if(write(fd, decoded, bytes / 2) == -1) {
1285
if(write(fd, decoded, strlen(decoded)) == -1) {
1157
1286
cli_errmsg("cli_scanhtml_utf16: Can't write to file %s\n", tempname);
1160
cli_unlink(tempname);
1161
1289
free(tempname);
1168
*ctx->fmap = fmap(fd, 0, 0);
1170
ret = cli_scanhtml(ctx);
1173
cli_errmsg("cli_scanhtml_utf16: fmap of %s failed\n", tempname);
1298
lseek(fd, 0, SEEK_SET);
1299
ret = cli_scanhtml(fd, ctx);
1178
if(!ctx->engine->keeptmp) {
1179
if (cli_unlink(tempname)) ret = CL_EUNLINK;
1302
if(!cli_leavetemps_flag)
1181
1305
cli_dbgmsg("cli_scanhtml_utf16: Decoded HTML data saved in %s\n", tempname);
1182
1306
free(tempname);
1187
static int cli_scanole2(cli_ctx *ctx)
1311
static int cli_scanole2(int desc, cli_ctx *ctx)
1190
1314
int ret = CL_CLEAN;
1191
struct uniq *vba = NULL;
1193
1317
cli_dbgmsg("in cli_scanole2()\n");
1195
if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1198
1319
/* generate the temporary directory */
1199
if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1320
dir = cli_gentemp(NULL);
1202
1321
if(mkdir(dir, 0700)) {
1203
1322
cli_dbgmsg("OLE2: Can't create temporary directory %s\n", dir);
1205
1324
return CL_ETMPDIR;
1208
ret = cli_ole2_extract(dir, ctx, &vba);
1209
if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
1327
if((ret = cli_ole2_extract(desc, dir, ctx->limits))) {
1210
1328
cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
1211
if(!ctx->engine->keeptmp)
1329
if(!cli_leavetemps_flag)
1212
1330
cli_rmdirs(dir);
1220
ret = cli_vba_scandir(dir, ctx, vba);
1223
if(cli_scandir(dir, ctx) == CL_VIRUS)
1335
if((ret = cli_vba_scandir(dir, ctx)) != CL_VIRUS) {
1336
if(cli_scandir(dir, ctx) == CL_VIRUS) {
1228
if(!ctx->engine->keeptmp)
1341
if(!cli_leavetemps_flag)
1229
1342
cli_rmdirs(dir);
1559
1662
ret = cli_scandir(dir, ctx);
1561
if(!ctx->engine->keeptmp)
1664
if(!cli_leavetemps_flag)
1562
1665
cli_rmdirs(dir);
1568
static int cli_scan_structured(int desc, cli_ctx *ctx)
1572
unsigned int cc_count = 0;
1573
unsigned int ssn_count = 0;
1575
int (*ccfunc)(const unsigned char *buffer, int length);
1576
int (*ssnfunc)(const unsigned char *buffer, int length);
1582
if(ctx->engine->min_cc_count == 1)
1583
ccfunc = dlp_has_cc;
1585
ccfunc = dlp_get_cc_count;
1587
switch((ctx->options & CL_SCAN_STRUCTURED_SSN_NORMAL) | (ctx->options & CL_SCAN_STRUCTURED_SSN_STRIPPED)) {
1589
case (CL_SCAN_STRUCTURED_SSN_NORMAL | CL_SCAN_STRUCTURED_SSN_STRIPPED):
1590
if(ctx->engine->min_ssn_count == 1)
1591
ssnfunc = dlp_has_ssn;
1593
ssnfunc = dlp_get_ssn_count;
1596
case CL_SCAN_STRUCTURED_SSN_NORMAL:
1597
if(ctx->engine->min_ssn_count == 1)
1598
ssnfunc = dlp_has_normal_ssn;
1600
ssnfunc = dlp_get_normal_ssn_count;
1603
case CL_SCAN_STRUCTURED_SSN_STRIPPED:
1604
if(ctx->engine->min_ssn_count == 1)
1605
ssnfunc = dlp_has_stripped_ssn;
1607
ssnfunc = dlp_get_stripped_ssn_count;
1614
while(!done && ((result = cli_readn(desc, buf, 8191)) > 0)) {
1615
if((cc_count += ccfunc((const unsigned char *)buf, result)) >= ctx->engine->min_cc_count)
1618
if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= ctx->engine->min_ssn_count))
1622
if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1623
cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
1624
*ctx->virname = "Heuristics.Structured.CreditCardNumber";
1628
if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1629
cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
1630
*ctx->virname = "Heuristics.Structured.SSN";
1637
static int cli_scanembpe(cli_ctx *ctx, off_t offset)
1639
int fd, bytes, ret = CL_CLEAN;
1640
unsigned long int size = 0, todo;
1643
fmap_t *map = *ctx->fmap;
1644
unsigned int corrupted_input;
1646
tmpname = cli_gentemp(ctx->engine->tmpdir);
1650
if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
1651
cli_errmsg("cli_scanembpe: Can't create file %s\n", tmpname);
1656
todo = map->len - offset;
1658
bytes = MIN(todo, map->pgsz);
1662
if(!(buff = fmap_need_off_once(map, offset + size, bytes))) {
1664
if(!ctx->engine->keeptmp) {
1665
if (cli_unlink(tmpname)) {
1676
if(cli_checklimits("cli_scanembpe", ctx, size, 0, 0)!=CL_CLEAN)
1679
if(cli_writen(fd, buff, bytes) != bytes) {
1680
cli_dbgmsg("cli_scanembpe: Can't write to temporary file\n");
1682
if(!ctx->engine->keeptmp) {
1683
if (cli_unlink(tmpname)) {
1694
lseek(fd, 0, SEEK_SET);
1695
corrupted_input = ctx->corrupted_input;
1696
ctx->corrupted_input = 1;
1697
ret = cli_magic_scandesc(fd, ctx);
1698
ctx->corrupted_input = corrupted_input;
1699
if(ret == CL_VIRUS) {
1700
cli_dbgmsg("cli_scanembpe: Infected with %s\n", *ctx->virname);
1702
if(!ctx->engine->keeptmp) {
1703
if (cli_unlink(tmpname)) {
1714
if(!ctx->engine->keeptmp) {
1715
if (cli_unlink(tmpname)) {
1722
/* intentionally ignore possible errors from cli_magic_scandesc */
1726
static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype, unsigned char *refhash)
1671
static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type)
1728
1673
int ret = CL_CLEAN, nret = CL_CLEAN;
1674
unsigned short ftrec;
1729
1675
struct cli_matched_type *ftoffset = NULL, *fpt;
1730
1676
uint32_t lastzip, lastrar;
1731
struct cli_exe_info peinfo;
1732
unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
1733
fmap_t *map = *ctx->fmap;
1734
cli_file_t current_container_type = ctx->container_type;
1735
size_t current_container_size = ctx->container_size;
1738
if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1742
acmode |= AC_SCAN_FT;
1744
ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode, NULL, refhash);
1746
if(ret >= CL_TYPENO) {
1748
if(nret != CL_VIRUS) {
1749
lastzip = lastrar = 0xdeadbeef;
1752
if(fpt->offset) switch(fpt->type) {
1753
case CL_TYPE_RARSFX:
1754
if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
1755
ctx->container_type = CL_TYPE_RAR;
1756
ctx->container_size = map->len - fpt->offset; /* not precise */
1757
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1758
nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
1762
case CL_TYPE_ZIPSFX:
1763
if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
1764
ctx->container_type = CL_TYPE_ZIP;
1765
ctx->container_size = map->len - fpt->offset; /* not precise */
1766
cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1767
nret = cli_unzip_single(ctx, fpt->offset);
1771
case CL_TYPE_CABSFX:
1772
if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB)) {
1773
ctx->container_type = CL_TYPE_MSCAB;
1774
ctx->container_size = map->len - fpt->offset; /* not precise */
1775
cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1776
nret = cli_scanmscab(map->fd, ctx, fpt->offset);
1779
case CL_TYPE_ARJSFX:
1780
if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
1781
ctx->container_type = CL_TYPE_ARJ;
1782
ctx->container_size = map->len - fpt->offset; /* not precise */
1783
cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1784
nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
1788
case CL_TYPE_NULSFT:
1789
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
1790
ctx->container_type = CL_TYPE_NULSFT;
1791
ctx->container_size = map->len - fpt->offset; /* not precise */
1792
cli_dbgmsg("NSIS signature found at %u\n", (unsigned int) fpt->offset-4);
1793
nret = cli_scannulsft(map->fd, ctx, fpt->offset - 4);
1797
case CL_TYPE_AUTOIT:
1798
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_AUTOIT)) {
1799
ctx->container_type = CL_TYPE_AUTOIT;
1800
ctx->container_size = map->len - fpt->offset; /* not precise */
1801
cli_dbgmsg("AUTOIT signature found at %u\n", (unsigned int) fpt->offset);
1802
nret = cli_scanautoit(ctx, fpt->offset + 23);
1806
case CL_TYPE_ISHIELD_MSI:
1807
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ISHIELD)) {
1808
ctx->container_type = CL_TYPE_AUTOIT;
1809
ctx->container_size = map->len - fpt->offset; /* not precise */
1810
cli_dbgmsg("ISHIELD-MSI signature found at %u\n", (unsigned int) fpt->offset);
1811
nret = cli_scanishield_msi(ctx, fpt->offset + 14);
1816
if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
1817
ctx->container_type = CL_TYPE_PDF;
1818
ctx->container_size = map->len - fpt->offset; /* not precise */
1819
cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
1820
nret = cli_scanpdf(ctx, fpt->offset);
1825
if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) {
1826
if(map->len > 10485760)
1828
ctx->container_type = CL_TYPE_MSEXE; /* PE is a container for another executable here */
1829
ctx->container_size = map->len - fpt->offset; /* not precise */
1830
memset(&peinfo, 0, sizeof(struct cli_exe_info));
1831
peinfo.offset = fpt->offset;
1832
if(cli_peheader(map, &peinfo) == 0) {
1833
cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
1835
free(peinfo.section);
1836
cli_hashset_destroy(&peinfo.vinfo);
1838
nret = cli_scanembpe(ctx, fpt->offset);
1839
break_loop = 1; /* we can stop here and other
1840
* embedded executables will
1841
* be found recursively
1842
* through the above call
1849
cli_warnmsg("cli_scanraw: Type %u not handled in fpt loop\n", fpt->type);
1852
if(nret == CL_VIRUS || break_loop)
1857
ctx->container_type = current_container_type;
1858
ctx->container_size = current_container_size;
1680
case CL_TYPE_UNKNOWN_TEXT:
1688
if(lseek(desc, 0, SEEK_SET) < 0) {
1689
cli_errmsg("cli_scanraw: lseek() failed\n");
1693
if((ret = cli_scandesc(desc, ctx, ftrec, type, 0, &ftoffset)) == CL_VIRUS) {
1694
cli_dbgmsg("%s found in descriptor %d.\n", *ctx->virname, desc);
1697
} else if(ret < 0) {
1700
} else if(ret >= CL_TYPENO) {
1701
lseek(desc, 0, SEEK_SET);
1703
if((nret = cli_scandesc(desc, ctx, 0, ret, 1, NULL)) == CL_VIRUS) {
1704
cli_dbgmsg("%s found in descriptor %d when scanning file type %u\n", *ctx->virname, desc, ret);
1861
if(nret != CL_VIRUS) switch(ret) {
1708
ret == CL_TYPE_MAIL ? ctx->mrec++ : ctx->arec++;
1862
1710
case CL_TYPE_HTML:
1863
if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) {
1864
*dettype = CL_TYPE_HTML;
1865
nret = cli_scanhtml(ctx);
1711
if(SCAN_HTML && type == CL_TYPE_UNKNOWN_TEXT && (DCONF_DOC & DOC_CONF_HTML))
1712
if((nret = cli_scanhtml(desc, ctx)) == CL_VIRUS)
1869
1716
case CL_TYPE_MAIL:
1870
ctx->container_type = CL_TYPE_MAIL;
1871
ctx->container_size = map->len;
1872
if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX)) {
1873
*dettype = CL_TYPE_MAIL;
1874
nret = cli_scanmail(map->fd, ctx);
1717
if(SCAN_MAIL && type == CL_TYPE_UNKNOWN_TEXT && (DCONF_MAIL & MAIL_CONF_MBOX))
1718
if((nret = cli_scanmail(desc, ctx)) == CL_VIRUS)
1722
case CL_TYPE_RARSFX:
1723
case CL_TYPE_ZIPSFX:
1724
case CL_TYPE_CABSFX:
1725
if(type == CL_TYPE_MSEXE) {
1727
lastzip = lastrar = 0xdeadbeef;
1730
if(fpt->type == CL_TYPE_RARSFX && (DCONF_ARCH & ARCH_CONF_RAR)) {
1731
cli_dbgmsg("RAR-SFX signature found at %d\n", fpt->offset);
1732
if((nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar)) == CL_VIRUS)
1734
} else if(fpt->type == CL_TYPE_ZIPSFX && (DCONF_ARCH & ARCH_CONF_ZIP)) {
1735
cli_dbgmsg("ZIP-SFX signature found at %d\n", fpt->offset);
1736
if((nret = cli_scanzip(desc, ctx, fpt->offset, &lastzip)) == CL_VIRUS)
1738
} else if(fpt->type == CL_TYPE_CABSFX && (DCONF_ARCH & ARCH_CONF_CAB)) {
1739
cli_dbgmsg("CAB-SFX signature found at %d\n", fpt->offset);
1740
if((nret = cli_scanmscab(desc, ctx, fpt->offset)) == CL_VIRUS)
1750
ftoffset = ftoffset->next;
1754
if(nret == CL_VIRUS)
1876
ctx->container_type = current_container_type;
1877
ctx->container_size = current_container_size;
1762
ret == CL_TYPE_MAIL ? ctx->mrec-- : ctx->arec--;
1889
ftoffset = ftoffset->next;
1894
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, map->fd);
1900
static void emax_reached(cli_ctx *ctx) {
1901
fmap_t **ctx_fmap = ctx->fmap;
1905
fmap_t *map = *ctx_fmap;
1906
map->dont_cache_flag = 1;
1909
cli_dbgmsg("emax_reached: marked parents as non cacheable\n");
1912
#define LINESTR(x) #x
1913
#define LINESTR2(x) LINESTR(x)
1914
#define __AT__ " at line "LINESTR2(__LINE__)
1915
#define ret_from_magicscan(retcode) do { \
1916
cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); \
1917
if(ctx->engine->cb_post_scan) { \
1918
switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) { \
1920
cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n"); \
1923
cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n"); \
1925
*ctx->virname = "Detected.By.Callback"; \
1930
cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n"); \
1936
static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
1769
int cli_magic_scandesc(int desc, cli_ctx *ctx)
1938
1771
int ret = CL_CLEAN;
1939
cli_file_t dettype = 0;
1940
1773
struct stat sb;
1941
uint8_t typercg = 1;
1942
cli_file_t current_container_type = ctx->container_type;
1943
size_t current_container_size = ctx->container_size, hashed_size;
1944
unsigned char hash[16];
1945
bitset_t *old_hook_lsig_matches;
1947
#ifdef HAVE__INTERNAL__SHA_COLLECT
1948
if(ctx->sha_collect>0) ctx->sha_collect = 0;
1951
cli_dbgmsg("in cli_magic_scandesc (reclevel: %u/%u)\n", ctx->recursion, ctx->engine->maxreclevel);
1952
if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1953
cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
1955
ret_from_magicscan(CL_CLEAN);
1958
1776
if(fstat(desc, &sb) == -1) {
1959
cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
1960
ret_from_magicscan(CL_ESTAT);
1777
cli_errmsg("Can't fstat descriptor %d\n", desc);
1963
1781
if(sb.st_size <= 5) {
1964
cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) sb.st_size);
1965
ret_from_magicscan(CL_CLEAN);
1782
cli_dbgmsg("Small data (%d bytes)\n", sb.st_size);
1968
1786
if(!ctx->engine) {
1969
1787
cli_errmsg("CRITICAL: engine == NULL\n");
1970
ret_from_magicscan(CL_ENULLARG);
1973
if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
1974
cli_errmsg("CRITICAL: engine not compiled\n");
1975
ret_from_magicscan(CL_EMALFDB);
1978
if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN) {
1980
ret_from_magicscan(CL_CLEAN);
1984
if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
1985
cli_errmsg("CRITICAL: fmap() failed\n");
1987
ret_from_magicscan(CL_EMEM);
1990
if(ctx->engine->cb_pre_scan) {
1991
switch(ctx->engine->cb_pre_scan(desc, ctx->cb_ctx)) {
1993
cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");
1996
ret_from_magicscan(CL_CLEAN);
1998
cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");
2000
*ctx->virname = "Detected.By.Callback";
2003
ret_from_magicscan(CL_VIRUS);
2007
cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");
2011
if(cache_check(hash, ctx) == CL_CLEAN) {
2014
ret_from_magicscan(CL_CLEAN);
2016
hashed_size = (*ctx->fmap)->len;
2017
old_hook_lsig_matches = ctx->hook_lsig_matches;
2018
ctx->hook_lsig_matches = NULL;
2020
if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
2021
if(ctx->recursion == ctx->engine->maxreclevel)
2022
cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
2024
cli_dbgmsg("Raw mode: No support for special files\n");
2026
if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, NULL, hash)) == CL_VIRUS)
1791
if(!ctx->options) { /* raw mode (stdin, etc.) */
1792
cli_dbgmsg("Raw mode: No support for special files\n");
1793
if((ret = cli_scandesc(desc, ctx, 0, 0, 0, NULL)) == CL_VIRUS)
2027
1794
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
2028
else if(ret == CL_CLEAN) {
2029
if(ctx->recursion != ctx->engine->maxreclevel)
2030
cache_add(hash, hashed_size, ctx); /* Only cache if limits are not reached */
2035
ctx->hook_lsig_matches = old_hook_lsig_matches;
2038
ret_from_magicscan(ret);
2041
if(type == CL_TYPE_ANY)
2042
type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
2043
if(type == CL_TYPE_ERROR) {
2044
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
2047
ctx->hook_lsig_matches = old_hook_lsig_matches;
2048
ret_from_magicscan(CL_EREAD);
2051
#ifdef HAVE__INTERNAL__SHA_COLLECT
2052
if(!ctx->sha_collect && type==CL_TYPE_MSEXE) ctx->sha_collect = 1;
2054
lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
2056
ctx->hook_lsig_matches = cli_bitset_init();
2057
if (!ctx->hook_lsig_matches) {
2058
ctx->hook_lsig_matches = old_hook_lsig_matches;
2060
ret_from_magicscan(CL_EMEM);
2063
if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
2064
if((ret = cli_scanraw(ctx, type, 0, &dettype, hash)) == CL_VIRUS) {
2065
ret = cli_checkfp(hash, hashed_size, ctx);
2068
cli_bitset_free(ctx->hook_lsig_matches);
2069
ctx->hook_lsig_matches = old_hook_lsig_matches;
2070
ret_from_magicscan(ret);
2072
lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
1798
if(SCAN_ARCHIVE && ctx->limits && ctx->limits->maxreclevel)
1799
if(ctx->arec > ctx->limits->maxreclevel) {
1800
cli_dbgmsg("Archive recursion limit exceeded (arec == %d).\n", ctx->arec);
1802
*ctx->virname = "Archive.ExceededRecursionLimit";
1809
if(ctx->mrec > MAX_MAIL_RECURSION) {
1810
cli_dbgmsg("Mail recursion level exceeded (mrec == %d).\n", ctx->mrec);
1811
/* return CL_EMAXREC; */
1815
lseek(desc, 0, SEEK_SET);
1816
type = cli_filetype2(desc, ctx->engine);
1817
lseek(desc, 0, SEEK_SET);
1819
if(type != CL_TYPE_DATA && ctx->engine->sdb) {
1820
if((ret = cli_scanraw(desc, ctx, type)) == CL_VIRUS)
1822
lseek(desc, 0, SEEK_SET);
1825
type == CL_TYPE_MAIL ? ctx->mrec++ : ctx->arec++;
2077
case CL_TYPE_IGNORED:
2080
1828
case CL_TYPE_RAR:
2081
ctx->container_type = CL_TYPE_RAR;
2082
ctx->container_size = sb.st_size;
2083
if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1829
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
2084
1830
ret = cli_scanrar(desc, ctx, 0, NULL);
2087
1833
case CL_TYPE_ZIP:
2088
ctx->container_type = CL_TYPE_ZIP;
2089
ctx->container_size = sb.st_size;
2090
1834
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
2091
ret = cli_unzip(ctx);
1835
ret = cli_scanzip(desc, ctx, 0, NULL);
2094
1838
case CL_TYPE_GZ:
2095
1839
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
2096
ret = cli_scangzip(ctx);
1840
ret = cli_scangzip(desc, ctx);
2099
1843
case CL_TYPE_BZ:
2100
1845
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BZ))
2101
1846
ret = cli_scanbzip(desc, ctx);
2105
ctx->container_type = CL_TYPE_ARJ;
2106
ctx->container_size = sb.st_size;
2107
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
2108
ret = cli_scanarj(desc, ctx, 0, NULL);
2111
case CL_TYPE_NULSFT:
2112
ctx->container_type = CL_TYPE_NULSFT;
2113
ctx->container_size = sb.st_size;
2114
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
2115
ret = cli_scannulsft(desc, ctx, 0);
2118
case CL_TYPE_AUTOIT:
2119
ctx->container_type = CL_TYPE_AUTOIT;
2120
ctx->container_size = sb.st_size;
2121
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_AUTOIT))
2122
ret = cli_scanautoit(ctx, 23);
2125
1850
case CL_TYPE_MSSZDD:
2271
1940
case CL_TYPE_ELF:
2272
1941
if(SCAN_ELF && ctx->dconf->elf)
2273
ret = cli_scanelf(ctx);
2277
if(ctx->dconf->macho)
2278
ret = cli_scanmacho(ctx, NULL);
2281
case CL_TYPE_MACHO_UNIBIN:
2282
if(ctx->dconf->macho)
2283
ret = cli_scanmacho_unibin(ctx);
1942
ret = cli_scanelf(desc, ctx);
2286
1945
case CL_TYPE_SIS:
2287
ctx->container_type = CL_TYPE_SIS;
2288
ctx->container_size = sb.st_size;
2289
1946
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SIS))
2290
1947
ret = cli_scansis(desc, ctx);
2293
case CL_TYPE_BINARY_DATA:
2294
if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_MYDOOMLOG))
2295
ret = cli_check_mydoom_log(desc, ctx);
1951
/* it could be a false positive and a standard DOS .COM file */
1954
if(fstat(desc, &s) == 0 && S_ISREG(s.st_mode) && s.st_size < 65536)
1955
type = CL_TYPE_UNKNOWN_DATA;
2298
case CL_TYPE_TEXT_ASCII:
2299
if(SCAN_STRUCTURED && (DCONF_OTHER & OTHER_CONF_DLP))
2300
/* TODO: consider calling this from cli_scanscript() for
2303
ret = cli_scan_structured(desc, ctx);
1958
case CL_TYPE_UNKNOWN_DATA:
1959
ret = cli_check_mydoom_log(desc, ctx->virname);
2310
ctx->container_type = current_container_type;
2311
ctx->container_size = current_container_size;
2313
if(ret == CL_VIRUS) {
2314
ret = cli_checkfp(hash, hashed_size, ctx);
2317
cli_bitset_free(ctx->hook_lsig_matches);
2318
ctx->hook_lsig_matches = old_hook_lsig_matches;
2319
ret_from_magicscan(ret);
2322
if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
2323
if(sb.st_size > 1048576) {
2324
cli_dbgmsg("cli_magic_scandesc: Not checking for embedded PEs (zip file > 1 MB)\n");
2329
/* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
2330
if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
2331
if(cli_scanraw(ctx, type, typercg, &dettype, hash) == CL_VIRUS) {
2332
ret = cli_checkfp(hash, hashed_size, ctx);
2335
cli_bitset_free(ctx->hook_lsig_matches);
2336
ctx->hook_lsig_matches = old_hook_lsig_matches;
2337
ret_from_magicscan(ret);
1966
type == CL_TYPE_MAIL ? ctx->mrec-- : ctx->arec--;
1968
if(type != CL_TYPE_DATA && ret != CL_VIRUS && !ctx->engine->sdb) {
1969
if(cli_scanraw(desc, ctx, type) == CL_VIRUS)
2342
1974
lseek(desc, 0, SEEK_SET);
2344
/* bytecode hooks triggered by a lsig must be a hook
2345
* called from one of the functions here */
2346
case CL_TYPE_TEXT_ASCII:
2347
case CL_TYPE_TEXT_UTF16BE:
2348
case CL_TYPE_TEXT_UTF16LE:
2349
case CL_TYPE_TEXT_UTF8:
2350
if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
2351
ret = cli_scanscript(ctx);
2352
if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (ctx->container_type == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
2353
lseek(desc, 0, SEEK_SET);
2354
ret = cli_scandesc(desc, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL);
2357
1976
/* Due to performance reasons all executables were first scanned
2358
1977
* in raw mode. Now we will try to unpack them
2360
1979
case CL_TYPE_MSEXE:
2361
if(SCAN_PE && ctx->dconf->pe) {
2362
unsigned int corrupted_input = ctx->corrupted_input;
2363
ret = cli_scanpe(ctx);
2364
ctx->corrupted_input = corrupted_input;
2372
ret = cli_checkfp(hash, hashed_size, ctx);
2376
cli_bitset_free(ctx->hook_lsig_matches);
2377
ctx->hook_lsig_matches = old_hook_lsig_matches;
2384
cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2386
cache_add(hash, hashed_size, ctx);
2387
ret_from_magicscan(CL_CLEAN);
2389
ret_from_magicscan(ret);
2393
int cli_magic_scandesc(int desc, cli_ctx *ctx)
2395
return magic_scandesc(desc, ctx, CL_TYPE_ANY);
2398
int cli_magic_scandesc_type(int desc, cli_ctx *ctx, cli_file_t type)
2400
return magic_scandesc(desc, ctx, type);
2403
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2405
return cl_scandesc_callback(desc, virname, scanned, engine, scanoptions, NULL);
2408
int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
1980
if(SCAN_PE && ctx->dconf->pe)
1981
ret = cli_scanpe(desc, ctx);
1989
if(ret == CL_EFORMAT) {
1990
cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(CL_EFORMAT));
1997
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
2413
2001
memset(&ctx, '\0', sizeof(cli_ctx));
2414
2002
ctx.engine = engine;
2415
2003
ctx.virname = virname;
2004
ctx.limits = limits;
2416
2005
ctx.scanned = scanned;
2417
ctx.options = scanoptions;
2418
ctx.found_possibly_unwanted = 0;
2419
ctx.container_type = CL_TYPE_ANY;
2420
ctx.container_size = 0;
2006
ctx.options = options;
2421
2007
ctx.dconf = (struct cli_dconf *) engine->dconf;
2422
ctx.cb_ctx = context;
2423
ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 2);
2426
if (!(ctx.hook_lsig_matches = cli_bitset_init())) {
2431
#ifdef HAVE__INTERNAL__SHA_COLLECT
2432
if(scanoptions & CL_SCAN_INTERNAL_COLLECT_SHA) {
2436
snprintf(link, sizeof(link), "/proc/self/fd/%u", desc);
2437
link[sizeof(link)-1]='\0';
2438
if((linksz=readlink(link, ctx.entry_filename, sizeof(ctx.entry_filename)))==-1) {
2439
cli_errmsg("failed to resolve filename for descriptor %d (%s)\n", desc, link);
2440
strcpy(ctx.entry_filename, "NO_IDEA");
2442
ctx.entry_filename[linksz]='\0';
2446
cli_logg_setup(&ctx);
2447
rc = cli_magic_scandesc(desc, &ctx);
2449
cli_bitset_free(ctx.hook_lsig_matches);
2451
if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2457
int cli_found_possibly_unwanted(cli_ctx* ctx)
2460
cli_dbgmsg("found Possibly Unwanted: %s\n",*ctx->virname);
2461
if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) {
2462
/* we found a heuristic match, don't scan further,
2463
* but consider it a virus. */
2464
cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n");
2467
/* heuristic scan isn't taking precedence, keep scanning.
2468
* If this is part of an archive, and
2469
* we find a real malware we report that instead of the
2470
* heuristic match */
2471
ctx->found_possibly_unwanted = 1;
2473
cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n");
2009
return cli_magic_scandesc(desc, &ctx);
2479
2012
static int cli_scanfile(const char *filename, cli_ctx *ctx)