コード例 #1
0
ファイル: matcher.c プロジェクト: iomato/clamav-win32
int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
{
	int ret = CL_CLEAN;
	unsigned int i, viruses_found = 0;
	struct cli_ac_data mdata;
	struct cli_matcher *groot, *troot = NULL;
	const char *virname = NULL;
	const struct cl_engine *engine=ctx->engine;

    if(!engine) {
	cli_errmsg("cli_scanbuff: engine == NULL\n");
	return CL_ENULLARG;
    }

    groot = engine->root[0]; /* generic signatures */

    if(ftype) {
	for(i = 1; i < CLI_MTARGETS; i++) {
	    if(cli_mtargets[i].target == ftype) {
		troot = engine->root[i];
		break;
	    }
	}
    }

    if(troot) {

	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
	    return ret;

	ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);

	if(!acdata)
	    cli_ac_freedata(&mdata);

	if(ret == CL_EMEM)
	    return ret;
	if(ret == CL_VIRUS) {
	    viruses_found = 1;
	    if(ctx && !SCAN_ALL) {
		return ret;
	    }
	}
    }

    virname = NULL;

    if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
	return ret;

    ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);

    if(!acdata)
	cli_ac_freedata(&mdata);

    if(viruses_found)
	return CL_VIRUS;
    return ret;
}
コード例 #2
0
END_TEST

START_TEST (test_pcre_scanbuff_allscan) {
	struct cli_ac_data mdata;
	struct cli_matcher *root;
	char *hexsig;
	unsigned int i, hexlen;
	int ret;

    root = ctx.engine->root[0];
    fail_unless(root != NULL, "root == NULL");

#ifdef USE_MPOOL
    root->mempool = mpool_create();
#endif
    ret = cli_pcre_init();
    fail_unless(ret == CL_SUCCESS, "[pcre] cli_pcre_init() failed");

    for(i = 0; pcre_testdata[i].data; i++) {
	hexlen = strlen(PCRE_BYPASS) + strlen(pcre_testdata[i].hexsig) + 1;

	hexsig = cli_calloc(hexlen, sizeof(char));
	fail_unless(hexsig != NULL, "[pcre] failed to prepend bypass (out-of-memory)");

	strncat(hexsig, PCRE_BYPASS, hexlen);
	strncat(hexsig, pcre_testdata[i].hexsig, hexlen);

	ret = cli_parse_add(root, pcre_testdata[i].virname, hexsig, 0, 0, 0, pcre_testdata[i].offset, 0, NULL, 0);
	fail_unless(ret == CL_SUCCESS, "[pcre] cli_parse_add() failed");
	free(hexsig);
    }

    ret = cli_pcre_build(root, CLI_DEFAULT_PCRE_MATCH_LIMIT, CLI_DEFAULT_PCRE_RECMATCH_LIMIT, NULL);
    fail_unless(ret == CL_SUCCESS, "[pcre] cli_pcre_build() failed");

    // recomputate offsets

    ret = cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, root->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN);
    fail_unless(ret == CL_SUCCESS, "[pcre] cli_ac_initdata() failed");

    ctx.options |= CL_SCAN_ALLMATCHES;
    for(i = 0; pcre_testdata[i].data; i++) {
	ret = cli_pcre_scanbuf((const unsigned char*)pcre_testdata[i].data, strlen(pcre_testdata[i].data), &virname, NULL, root, NULL, NULL, NULL);
	fail_unless_fmt(ret == pcre_testdata[i].expected_result, "[pcre] cli_pcre_scanbuff() failed for %s (%d != %d)", pcre_testdata[i].virname, ret, pcre_testdata[i].expected_result);
	if (pcre_testdata[i].expected_result == CL_VIRUS)
	    fail_unless_fmt(!strncmp(virname, pcre_testdata[i].virname, strlen(pcre_testdata[i].virname)), "[pcre] Dataset %u matched with %s", i, virname);

	ret = cli_scanbuff((const unsigned char*)pcre_testdata[i].data, strlen(pcre_testdata[i].data), 0, &ctx, 0, NULL);
	fail_unless_fmt(ret == pcre_testdata[i].expected_result, "[pcre] cli_scanbuff() failed for %s", pcre_testdata[i].virname);
	/* num_virus field add to test case struct */
	if (ctx.num_viruses)
	    ctx.num_viruses = 0;
    }

    cli_ac_freedata(&mdata);
}
コード例 #3
0
END_TEST

START_TEST (test_ac_scanbuff_allscan) {
	struct cli_ac_data mdata;
	struct cli_matcher *root;
	unsigned int i;
	int ret;

    root = ctx.engine->root[0];
    fail_unless(root != NULL, "root == NULL");
    root->ac_only = 1;

#ifdef USE_MPOOL
    root->mempool = mpool_create();
#endif
    ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1);
    fail_unless(ret == CL_SUCCESS, "cli_ac_init() failed");


    for(i = 0; ac_testdata[i].data; i++) {
	ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0);
	fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
    }

    ret = cli_ac_buildtrie(root);
    fail_unless(ret == CL_SUCCESS, "cli_ac_buildtrie() failed");

    ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN);
    fail_unless(ret == CL_SUCCESS, "cli_ac_initdata() failed");

    ctx.options |= CL_SCAN_ALLMATCHES;
    for(i = 0; ac_testdata[i].data; i++) {
	ret = cli_ac_scanbuff((const unsigned char*)ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
	fail_unless_fmt(ret == CL_VIRUS, "cli_ac_scanbuff() failed for %s", ac_testdata[i].virname);
	fail_unless_fmt(!strncmp(virname, ac_testdata[i].virname, strlen(ac_testdata[i].virname)), "Dataset %u matched with %s", i, virname);

	ret = cli_scanbuff((const unsigned char*)ac_testdata[i].data, strlen(ac_testdata[i].data), 0, &ctx, 0, NULL);
	fail_unless_fmt(ret == CL_VIRUS, "cli_scanbuff() failed for %s", ac_testdata[i].virname);
	fail_unless_fmt(!strncmp(virname, ac_testdata[i].virname, strlen(ac_testdata[i].virname)), "Dataset %u matched with %s", i, virname);
	if (ctx.num_viruses)
	    ctx.num_viruses = 0;
     }

    cli_ac_freedata(&mdata);
}
コード例 #4
0
END_TEST

START_TEST (test_ac_scanbuff_ex) {
	struct cli_ac_data mdata;
	struct cli_matcher *root;
	unsigned int i;
	int ret;

    root = ctx.engine->root[0];
    fail_unless(root != NULL, "root == NULL");
    root->ac_only = 1;

#ifdef USE_MPOOL
    root->mempool = mpool_create();
#endif
    ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1);
    fail_unless(ret == CL_SUCCESS, "[ac_ex] cli_ac_init() failed");

    for(i = 0; ac_sigopts_testdata[i].data; i++) {
	ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, 0, NULL, 0);
	fail_unless(ret == CL_SUCCESS, "[ac_ex] cli_sigopts_handler() failed");
    }

    ret = cli_ac_buildtrie(root);
    fail_unless(ret == CL_SUCCESS, "[ac_ex] cli_ac_buildtrie() failed");

    ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN);
    fail_unless(ret == CL_SUCCESS, "[ac_ex] cli_ac_initdata() failed");

    for(i = 0; ac_sigopts_testdata[i].data; i++) {
	ret = cli_ac_scanbuff((const unsigned char*)ac_sigopts_testdata[i].data, ac_sigopts_testdata[i].dlength, &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
	fail_unless_fmt(ret == ac_sigopts_testdata[i].expected_result, "[ac_ex] cli_ac_scanbuff() failed for %s (%d != %d)", ac_sigopts_testdata[i].virname, ret, ac_sigopts_testdata[i].expected_result);
	if (ac_sigopts_testdata[i].expected_result == CL_VIRUS)
	    fail_unless_fmt(!strncmp(virname, ac_sigopts_testdata[i].virname, strlen(ac_sigopts_testdata[i].virname)), "[ac_ex] Dataset %u matched with %s", i, virname);

	ret = cli_scanbuff((const unsigned char*)ac_sigopts_testdata[i].data, ac_sigopts_testdata[i].dlength, 0, &ctx, 0, NULL);
	fail_unless_fmt(ret == ac_sigopts_testdata[i].expected_result, "[ac_ex] cli_ac_scanbuff() failed for %s (%d != %d)", ac_sigopts_testdata[i].virname, ret, ac_sigopts_testdata[i].expected_result);
    }

    cli_ac_freedata(&mdata);
}
コード例 #5
0
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash)
{
    const unsigned char *buff;
    int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES];
    unsigned int i = 0, j = 0, bm_offmode = 0;
    uint32_t maxpatlen, offset = 0;
    struct cli_ac_data gdata, tdata;
    struct cli_bm_off toff;
    struct cli_pcre_off gpoff, tpoff;
    unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
    struct cli_matcher *groot = NULL, *troot = NULL;
    struct cli_target_info info;
    fmap_t *map = *ctx->fmap;
    struct cli_matcher *hdb, *fp;
    const char *virname = NULL;
    uint32_t viruses_found = 0;
    void *md5ctx, *sha1ctx, *sha256ctx;

    if(!ctx->engine) {
        cli_errmsg("cli_scandesc: engine == NULL\n");
        return CL_ENULLARG;
    }

    md5ctx = cl_hash_init("md5");
    if (!(md5ctx))
        return CL_EMEM;

    sha1ctx = cl_hash_init("sha1");
    if (!(sha1ctx)) {
        cl_hash_destroy(md5ctx);
        return CL_EMEM;
    }

    sha256ctx = cl_hash_init("sha256");
    if (!(sha256ctx)) {
        cl_hash_destroy(md5ctx);
        cl_hash_destroy(sha1ctx);
        return CL_EMEM;
    }

    if(!ftonly)
        groot = ctx->engine->root[0]; /* generic signatures */

    if(ftype) {
        for(i = 1; i < CLI_MTARGETS; i++) {
            for (j = 0; j < cli_mtargets[i].target_count; ++j) {
                if(cli_mtargets[i].target[j] == ftype) {
                    troot = ctx->engine->root[i];
                    break;
                }
            }
            if (troot) break;
        }
    }

    if(ftonly) {
        if(!troot) {
            cl_hash_destroy(md5ctx);
            cl_hash_destroy(sha1ctx);
            cl_hash_destroy(sha256ctx);
            return CL_CLEAN;
        }

        maxpatlen = troot->maxpatlen;
    } else {
        if(troot)
            maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
        else
            maxpatlen = groot->maxpatlen;
    }

    cli_targetinfo(&info, i, map);

    if(!ftonly) {
        if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info))) {
            if(info.exeinfo.section)
                free(info.exeinfo.section);

            cli_hashset_destroy(&info.exeinfo.vinfo);
            cl_hash_destroy(md5ctx);
            cl_hash_destroy(sha1ctx);
            cl_hash_destroy(sha256ctx);
            return ret;
        }
        if((ret = cli_pcre_recaloff(groot, &gpoff, &info, ctx))) {
            cli_ac_freedata(&gdata);
            if(info.exeinfo.section)
                free(info.exeinfo.section);

            cli_hashset_destroy(&info.exeinfo.vinfo);
            cl_hash_destroy(md5ctx);
            cl_hash_destroy(sha1ctx);
            cl_hash_destroy(sha256ctx);
            return ret;

        }
    }

    if(troot) {
        if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info))) {
            if(!ftonly) {
                cli_ac_freedata(&gdata);
                cli_pcre_freeoff(&gpoff);
            }
            if(info.exeinfo.section)
                free(info.exeinfo.section);

            cli_hashset_destroy(&info.exeinfo.vinfo);
            cl_hash_destroy(md5ctx);
            cl_hash_destroy(sha1ctx);
            cl_hash_destroy(sha256ctx);
            return ret;
        }
        if(troot->bm_offmode) {
            if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
                if((ret = cli_bm_initoff(troot, &toff, &info))) {
                    if(!ftonly) {
                        cli_ac_freedata(&gdata);
                        cli_pcre_freeoff(&gpoff);
                    }

                    cli_ac_freedata(&tdata);
                    if(info.exeinfo.section)
                        free(info.exeinfo.section);

                    cli_hashset_destroy(&info.exeinfo.vinfo);
                    cl_hash_destroy(md5ctx);
                    cl_hash_destroy(sha1ctx);
                    cl_hash_destroy(sha256ctx);
                    return ret;
                }

                bm_offmode = 1;
            }
        }
        if ((ret = cli_pcre_recaloff(troot, &tpoff, &info, ctx))) {
            if(!ftonly) {
                cli_ac_freedata(&gdata);
                cli_pcre_freeoff(&gpoff);
            }

            cli_ac_freedata(&tdata);
            if(bm_offmode)
                cli_bm_freeoff(&toff);
            if(info.exeinfo.section)
                free(info.exeinfo.section);

            cli_hashset_destroy(&info.exeinfo.vinfo);
            cl_hash_destroy(md5ctx);
            cl_hash_destroy(sha1ctx);
            cl_hash_destroy(sha256ctx);
            return ret;
        }
    }

    hdb = ctx->engine->hm_hdb;
    fp = ctx->engine->hm_fp;

    if(!ftonly && hdb) {
        if(!refhash) {
            if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)
               || cli_hm_have_wild(hdb, CLI_HASH_MD5) || cli_hm_have_wild(fp, CLI_HASH_MD5)) {
                compute_hash[CLI_HASH_MD5] = 1;
            } else {
                compute_hash[CLI_HASH_MD5] = 0;
            }
        } else {
            compute_hash[CLI_HASH_MD5] = 0;
            memcpy(digest[CLI_HASH_MD5], refhash, 16);
        }

        if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1)
            || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) {
            compute_hash[CLI_HASH_SHA1] = 1;
        } else {
            compute_hash[CLI_HASH_SHA1] = 0;
        }

        if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256)
            || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) {
            compute_hash[CLI_HASH_SHA256] = 1;
        } else {
            compute_hash[CLI_HASH_SHA256] = 0;
        }
    }

    while(offset < map->len) {
        bytes = MIN(map->len - offset, SCANBUFF);
        if(!(buff = fmap_need_off_once(map, offset, bytes)))
            break;
        if(ctx->scanned)
            *ctx->scanned += bytes / CL_COUNT_PRECISION;

        if(troot) {
                virname = NULL;
                ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, PCRE_SCAN_FMAP, acres, map, bm_offmode ? &toff : NULL, &tpoff, ctx);

            if (virname) {
                /* virname already appended by matcher_run */
                viruses_found = 1;
            }
            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
                if(!ftonly) {
                    cli_ac_freedata(&gdata);
                    cli_pcre_freeoff(&gpoff);
                }

                cli_ac_freedata(&tdata);
                if(bm_offmode)
                    cli_bm_freeoff(&toff);
                cli_pcre_freeoff(&tpoff);

                if(info.exeinfo.section)
                    free(info.exeinfo.section);

                cli_hashset_destroy(&info.exeinfo.vinfo);
                cl_hash_destroy(md5ctx);
                cl_hash_destroy(sha1ctx);
                cl_hash_destroy(sha256ctx);
                return ret;
            }
        }

        if(!ftonly) {
            virname = NULL;
            ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, PCRE_SCAN_FMAP, acres, map, NULL, &gpoff, ctx);

            if (virname) {
                /* virname already appended by matcher_run */
                viruses_found = 1;
            }
            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
                cli_ac_freedata(&gdata);
                cli_pcre_freeoff(&gpoff);
                if(troot) {
                    cli_ac_freedata(&tdata);
                    if(bm_offmode)
                        cli_bm_freeoff(&toff);
                    cli_pcre_freeoff(&tpoff);
                }

                if(info.exeinfo.section)
                    free(info.exeinfo.section);

                cli_hashset_destroy(&info.exeinfo.vinfo);
                cl_hash_destroy(md5ctx);
                cl_hash_destroy(sha1ctx);
                cl_hash_destroy(sha256ctx);
                return ret;
            } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
                if(ret > type)
                    type = ret;
            }

            /* if (bytes <= (maxpatlen * (offset!=0))), it means the last window finished the file hashing *
             *   since the last window is responsible for adding intersection between windows (maxpatlen)  */
            if(hdb && (bytes > (maxpatlen * (offset!=0)))) {
                const void *data = buff + maxpatlen * (offset!=0);
                uint32_t data_len = bytes - maxpatlen * (offset!=0);

                if(compute_hash[CLI_HASH_MD5])
                    cl_update_hash(md5ctx, (void *)data, data_len);
                if(compute_hash[CLI_HASH_SHA1])
                    cl_update_hash(sha1ctx, (void *)data, data_len);
                if(compute_hash[CLI_HASH_SHA256])
                    cl_update_hash(sha256ctx, (void *)data, data_len);
            }
        }

        if(bytes < SCANBUFF)
            break;

        offset += bytes - maxpatlen;
    }

    if(!ftonly && hdb) {
        enum CLI_HASH_TYPE hashtype, hashtype2;

        if(compute_hash[CLI_HASH_MD5]) {
            cl_finish_hash(md5ctx, digest[CLI_HASH_MD5]);
            md5ctx = NULL;
        }
        if(refhash)
            compute_hash[CLI_HASH_MD5] = 1;
        if(compute_hash[CLI_HASH_SHA1]) {
            cl_finish_hash(sha1ctx, digest[CLI_HASH_SHA1]);
            sha1ctx = NULL;
        }
        if(compute_hash[CLI_HASH_SHA256]) {
            cl_finish_hash(sha256ctx, digest[CLI_HASH_SHA256]);
            sha256ctx = NULL;
        }

        virname = NULL;
        for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) {
            const char * virname_w = NULL;
            int found = 0;

            /* If no hash, skip to next type */
            if(!compute_hash[hashtype])
                continue;

            /* Do hash scan */
            if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
                found += 1;
            }
            if(!found || SCAN_ALL) {
                if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS)
                    found += 2;
            }

            /* If found, do immediate hash-only FP check */
            if (found && fp) {
                for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) {
                    if(!compute_hash[hashtype2])
                        continue;
                    if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) {
                        found = 0;
                        ret = CL_CLEAN;
                        break;
                    }
                    else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) {
                        found = 0;
                        ret = CL_CLEAN;
                        break;
                    }
                }
            }

            /* If matched size-based hash ... */
            if (found % 2) {
                viruses_found = 1;
                cli_append_virus(ctx, virname);
                if (!SCAN_ALL)
                    break;
                virname = NULL;
            }
            /* If matched size-agnostic hash ... */
            if (found > 1) {
                viruses_found = 1;
                cli_append_virus(ctx, virname_w);

                if (!SCAN_ALL)
                    break;
            }
        }
    }

    cl_hash_destroy(md5ctx);
    cl_hash_destroy(sha1ctx);
    cl_hash_destroy(sha256ctx);

    if(troot) {
        if(ret != CL_VIRUS || SCAN_ALL)
            ret = cli_exp_eval(ctx, troot, &tdata, &info, (const char *)refhash);
        if (ret == CL_VIRUS)
            viruses_found++;

        cli_ac_freedata(&tdata);
        if(bm_offmode)
            cli_bm_freeoff(&toff);
        cli_pcre_freeoff(&tpoff);
    }

    if(groot) {
        if(ret != CL_VIRUS || SCAN_ALL)
            ret = cli_exp_eval(ctx, groot, &gdata, &info, (const char *)refhash);
        cli_ac_freedata(&gdata);
        cli_pcre_freeoff(&gpoff);
    }

    if(info.exeinfo.section)
        free(info.exeinfo.section);

    cli_hashset_destroy(&info.exeinfo.vinfo);

    if (SCAN_ALL && viruses_found)
        return CL_VIRUS;
    if(ret == CL_VIRUS)
        return CL_VIRUS;

    return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
}
コード例 #6
0
ファイル: matcher.c プロジェクト: iomato/clamav-win32
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash)
{
	const unsigned char *buff;
	int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES];
	unsigned int i = 0, bm_offmode = 0;
	uint32_t maxpatlen, offset = 0;
	struct cli_ac_data gdata, tdata;
	struct cli_bm_off toff;
	cli_md5_ctx md5ctx;
	SHA256_CTX sha256ctx;
	SHA1Context sha1ctx;
	unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
	struct cli_matcher *groot = NULL, *troot = NULL;
	struct cli_target_info info;
	fmap_t *map = *ctx->fmap;
	struct cli_matcher *hdb, *fp;
	const char *virname = NULL;
	uint32_t viroffset = 0;
	uint32_t viruses_found = 0;

    if(!ctx->engine) {
	cli_errmsg("cli_scandesc: engine == NULL\n");
	return CL_ENULLARG;
    }

    if(!ftonly)
	groot = ctx->engine->root[0]; /* generic signatures */

    if(ftype) {
	for(i = 1; i < CLI_MTARGETS; i++) {
	    if(cli_mtargets[i].target == ftype) {
		troot = ctx->engine->root[i];
		break;
	    }
	}
    }

    if(ftonly) {
	if(!troot)
	    return CL_CLEAN;

	maxpatlen = troot->maxpatlen;
    } else {
	if(troot)
	    maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
	else
	    maxpatlen = groot->maxpatlen;
    }

    targetinfo(&info, i, map);

    if(!ftonly)
	if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info))) {
	    if(info.exeinfo.section)
		free(info.exeinfo.section);
	    cli_hashset_destroy(&info.exeinfo.vinfo);
	    return ret;
	}

    if(troot) {
	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info))) {
	    if(!ftonly)
		cli_ac_freedata(&gdata);
	    if(info.exeinfo.section)
		free(info.exeinfo.section);
	    cli_hashset_destroy(&info.exeinfo.vinfo);
	    return ret;
	}
	if(troot->bm_offmode) {
	    if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
		if((ret = cli_bm_initoff(troot, &toff, &info))) {
		    if(!ftonly)
			cli_ac_freedata(&gdata);
		    cli_ac_freedata(&tdata);
		    if(info.exeinfo.section)
			free(info.exeinfo.section);
		    cli_hashset_destroy(&info.exeinfo.vinfo);
		    return ret;
		}
		bm_offmode = 1;
	    }
	}
    }

    hdb = ctx->engine->hm_hdb;
    fp = ctx->engine->hm_fp;

    if(!ftonly && hdb) {
	if(!refhash) {
	    if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) {
		cli_md5_init(&md5ctx);
		compute_hash[CLI_HASH_MD5] = 1;
	    } else
		compute_hash[CLI_HASH_MD5] = 0;
	} else {
	    compute_hash[CLI_HASH_MD5] = 0;
	    memcpy(digest[CLI_HASH_MD5], refhash, 16);
	}

	if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1)
		|| cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) {
	    SHA1Init(&sha1ctx);
	    compute_hash[CLI_HASH_SHA1] = 1;
	} else
	    compute_hash[CLI_HASH_SHA1] = 0;

	if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256)
		|| cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) {
	    sha256_init(&sha256ctx);
	    compute_hash[CLI_HASH_SHA256] = 1;
	} else
	    compute_hash[CLI_HASH_SHA256] = 0;
    }

    while(offset < map->len) {
	bytes = MIN(map->len - offset, SCANBUFF);
	if(!(buff = fmap_need_off_once(map, offset, bytes)))
	    break;
	if(ctx->scanned)
	    *ctx->scanned += bytes / CL_COUNT_PRECISION;

    if (ctx->engine->cb_progress && map->handle_is_fd && !ctx->engine->cb_progress((ssize_t) map->handle, bytes, ctx->engine->cb_progress_ctx))
        return CL_BREAK;

	if(troot) {
            virname = NULL;
            viroffset = 0;
	    ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);

	    if (virname) {
		/* virname already appended by matcher_run */
		viruses_found = 1;
	    }
	    if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
		if(!ftonly)
		    cli_ac_freedata(&gdata);
		cli_ac_freedata(&tdata);
		if(bm_offmode)
		    cli_bm_freeoff(&toff);
		if(info.exeinfo.section)
		    free(info.exeinfo.section);
		cli_hashset_destroy(&info.exeinfo.vinfo);
		return ret;
	    }
	}

	if(!ftonly) {
	    virname = NULL;
	    viroffset = 0;
	    ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);

            if (virname) {
		/* virname already appended by matcher_run */
		viruses_found = 1;
	    }
	    if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
		cli_ac_freedata(&gdata);
		if(troot) {
		    cli_ac_freedata(&tdata);
		    if(bm_offmode)
			cli_bm_freeoff(&toff);
		}
		if(info.exeinfo.section)
		    free(info.exeinfo.section);
		cli_hashset_destroy(&info.exeinfo.vinfo);
		return ret;
	    } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
		if(ret > type)
		    type = ret;
	    }

	    if(hdb && !SCAN_ALL) {
		const void *data = buff + maxpatlen * (offset!=0);
		uint32_t data_len = bytes - maxpatlen * (offset!=0);

		if(compute_hash[CLI_HASH_MD5])
		    cli_md5_update(&md5ctx, data, data_len);
		if(compute_hash[CLI_HASH_SHA1])
		    SHA1Update(&sha1ctx, data, data_len);
		if(compute_hash[CLI_HASH_SHA256])
		    sha256_update(&sha256ctx, data, data_len);
	    }
	}

	if(SCAN_ALL && viroffset) {
	    offset = viroffset;
	    continue;
	}
	if(bytes < SCANBUFF) break;
	offset += bytes - maxpatlen;
    }

    if(!ftonly && hdb) {
	enum CLI_HASH_TYPE hashtype, hashtype2;

	if(compute_hash[CLI_HASH_MD5])
	    cli_md5_final(digest[CLI_HASH_MD5], &md5ctx);
	if(refhash)
	    compute_hash[CLI_HASH_MD5] = 1;
	if(compute_hash[CLI_HASH_SHA1])
	    SHA1Final(&sha1ctx, digest[CLI_HASH_SHA1]);
	if(compute_hash[CLI_HASH_SHA256])
	    sha256_final(&sha256ctx, digest[CLI_HASH_SHA256]);

	virname = NULL;
	for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) {
	    const char * virname_w = NULL;
	    int found = 0;

	    /* If no hash, skip to next type */
	    if(!compute_hash[hashtype])
		continue;

	    /* Do hash scan */
	    if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
		found += 1;
	    }
	    if(!found || SCAN_ALL) {
		if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS)
		    found += 2;
	    }

	    /* If found, do immediate hash-only FP check */
	    if (found && fp) {
		for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) {
		    if(!compute_hash[hashtype2])
			continue;
		    if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) {
			found = 0;
			ret = CL_CLEAN;
			break;
		    }
		    else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) {
			found = 0;
			ret = CL_CLEAN;
			break;
		    }
		}
	    }

	    /* If matched size-based hash ... */
	    if (found % 2) {
		viruses_found = 1;
		cli_append_virus(ctx, virname);
		if (!SCAN_ALL)
		    break;
		virname = NULL;
	    }
	    /* If matched size-agnostic hash ... */
	    if (found > 1) {
		viruses_found = 1;
		cli_append_virus(ctx, virname_w);
		if (!SCAN_ALL)
		    break;
	    }
	}
    }

    if(troot) {
	if(ret != CL_VIRUS || SCAN_ALL)
	    ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash);
	if (ret == CL_VIRUS)
	    viruses_found++;
	cli_ac_freedata(&tdata);
	if(bm_offmode)
	    cli_bm_freeoff(&toff);
    }

    if(groot) {
	if(ret != CL_VIRUS || SCAN_ALL)
	    ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash);
	cli_ac_freedata(&gdata);
    }

    if(info.exeinfo.section)
	free(info.exeinfo.section);
    cli_hashset_destroy(&info.exeinfo.vinfo);

    if (SCAN_ALL && viruses_found)
	return CL_VIRUS;
    if(ret == CL_VIRUS)
	return CL_VIRUS;

    return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
}
コード例 #7
0
ファイル: matcher.c プロジェクト: eqmcc/clamav_decode
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash)
{
    //CHR ftype => type == CL_TYPE_TEXT_ASCII ? 0 : type
    //CHR ftonly => 0
    cli_infomsg(NULL,"DEBUG: in cli_fmap_scandesc\n");//CHR
	const unsigned char *buff;
	int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES];
	unsigned int i = 0, bm_offmode = 0;
	uint32_t maxpatlen, offset = 0;
	struct cli_ac_data gdata, tdata;
	struct cli_bm_off toff;
	cli_md5_ctx md5ctx;
	SHA256_CTX sha256ctx;
	SHA1Context sha1ctx;
	unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
	struct cli_matcher *groot = NULL, *troot = NULL;
	struct cli_target_info info;
	fmap_t *map = *ctx->fmap;
	struct cli_matcher *hdb, *fp;
	const char *virname = NULL;
	uint32_t viroffset = 0;
	uint32_t viruses_found = 0;

    if(!ctx->engine) {
	cli_errmsg("cli_scandesc: engine == NULL\n");
	return CL_ENULLARG;
    }

    cli_infomsg(NULL,"DEBUG: ftype=%d, ftonly=%d(using generic signatures for groot)\n",ftype,ftonly);//CHR

    if(!ftonly)
	groot = ctx->engine->root[0]; /* generic signatures */

    //CHR in test.txt case, ftype=0, troot is for sepcific types: from 1 to CLI_MTARGETS
    if(ftype) {
	for(i = 1; i < CLI_MTARGETS; i++) {
	    if(cli_mtargets[i].target == ftype) {
		troot = ctx->engine->root[i];
		break;
	    }
	}
    }

    if(ftonly) {
	if(!troot)
	    return CL_CLEAN;

	maxpatlen = troot->maxpatlen;
    } else {
	if(troot)
	    maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
	else{
	    maxpatlen = groot->maxpatlen;
        cli_infomsg(NULL,"DEBUG: no troot, maxpatlen using groot->maxpatlen=%d\n",groot->maxpatlen);//CHR
        }
    }

    targetinfo(&info, i, map);

    if(!ftonly)
    // CHR init AC scan structure?
	if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info))) {
	    if(info.exeinfo.section)
		free(info.exeinfo.section);
	    cli_hashset_destroy(&info.exeinfo.vinfo);
	    return ret;
	}

    // not run in this case test.txt
    if(troot) { 
	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info))) {
	    if(!ftonly)
		cli_ac_freedata(&gdata);
	    if(info.exeinfo.section)
		free(info.exeinfo.section);
	    cli_hashset_destroy(&info.exeinfo.vinfo);
	    return ret;
	}
	if(troot->bm_offmode) {// CHR offset mode
	    if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
		if((ret = cli_bm_initoff(troot, &toff, &info))) {
		    if(!ftonly)
			cli_ac_freedata(&gdata);
		    cli_ac_freedata(&tdata);
		    if(info.exeinfo.section)
			free(info.exeinfo.section);
		    cli_hashset_destroy(&info.exeinfo.vinfo);
		    return ret;
		}
		bm_offmode = 1;
	    }
	}
    }

    hdb = ctx->engine->hm_hdb;
    fp = ctx->engine->hm_fp;

    // hdb related
    if(!ftonly && hdb) { //CHR if have hdb should init mn5 contex
	if(!refhash) {
	    if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) {
		cli_md5_init(&md5ctx);
		compute_hash[CLI_HASH_MD5] = 1;
	    } else
		compute_hash[CLI_HASH_MD5] = 0;
	} else {
	    compute_hash[CLI_HASH_MD5] = 0;
	    memcpy(digest[CLI_HASH_MD5], refhash, 16);
	}

	if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len)) {
	    SHA1Init(&sha1ctx);
	    compute_hash[CLI_HASH_SHA1] = 1;
	} else
	    compute_hash[CLI_HASH_SHA1] = 0;

	if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len)) {
	    sha256_init(&sha256ctx);
	    compute_hash[CLI_HASH_SHA256] = 1;
	} else
	    compute_hash[CLI_HASH_SHA256] = 0;
    }

    while(offset < map->len) {
	bytes = MIN(map->len - offset, SCANBUFF);
	if(!(buff = fmap_need_off_once(map, offset, bytes)))
	    break;
	if(ctx->scanned)
	    *ctx->scanned += bytes / CL_COUNT_PRECISION;

    // CHR not troot for this case
	if(troot) {
            cli_infomsg(NULL,"DEBUG: not troot, should not show this msg\n");//CHR
            virname = NULL;
            viroffset = 0;
            // CHR run match
	    ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);

	    if (virname) {
		viruses_found++;
	    }
	    if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
		if(!ftonly)
		    cli_ac_freedata(&gdata);
		cli_ac_freedata(&tdata);
		if(bm_offmode)
		    cli_bm_freeoff(&toff);
		if(info.exeinfo.section)
		    free(info.exeinfo.section);
		cli_hashset_destroy(&info.exeinfo.vinfo);
		return ret;
	    }
	}

	if(!ftonly) {
        cli_infomsg(NULL,"DEBUG: !ftonly=true, will run matcher_run with groot with generic sigs\n");//CHR
	    virname = NULL;
	    viroffset = 0;
	    ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);

            if (virname) {
		viruses_found++;
	    }
	    if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
		cli_ac_freedata(&gdata);
		if(troot) {
		    cli_ac_freedata(&tdata);
		    if(bm_offmode)
			cli_bm_freeoff(&toff);
		}
		if(info.exeinfo.section)
		    free(info.exeinfo.section);
		cli_hashset_destroy(&info.exeinfo.vinfo);
		return ret;
	    } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
		if(ret > type)
		    type = ret;
	    }

	    if(hdb && !SCAN_ALL) {
		const void *data = buff + maxpatlen * (offset!=0);
		uint32_t data_len = bytes - maxpatlen * (offset!=0);

		if(compute_hash[CLI_HASH_MD5])
		    cli_md5_update(&md5ctx, data, data_len);
		if(compute_hash[CLI_HASH_SHA1])
		    SHA1Update(&sha1ctx, data, data_len);
		if(compute_hash[CLI_HASH_SHA256])
		    sha256_update(&sha256ctx, data, data_len);
	    }
	}

	if(SCAN_ALL && viroffset) {
	    offset = viroffset;
	    continue;
	}
	if(bytes < SCANBUFF) break;
	offset += bytes - maxpatlen;
    }

    if(!ftonly && hdb) {
	enum CLI_HASH_TYPE hashtype, hashtype2;

	if(compute_hash[CLI_HASH_MD5])
	    cli_md5_final(digest[CLI_HASH_MD5], &md5ctx);
	if(refhash)
	    compute_hash[CLI_HASH_MD5] = 1;
	if(compute_hash[CLI_HASH_SHA1])
	    SHA1Final(&sha1ctx, digest[CLI_HASH_SHA1]);
	if(compute_hash[CLI_HASH_SHA256])
	    sha256_final(&sha256ctx, digest[CLI_HASH_SHA256]);

	virname = NULL;
	for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) {
	    if(compute_hash[hashtype] &&
	       (ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
		if(fp) {
		    for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) {
			if(compute_hash[hashtype2] &&
			   cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) {
			    ret = CL_CLEAN;
			    break;
			}
		    }
		}
		if (ret == CL_VIRUS) {
		    viruses_found++;
		    cli_append_virus(ctx, virname);
		    if (!SCAN_ALL)
			break;
		}
		virname = NULL;
	    }
	}
    }

    if(troot) {
	if(ret != CL_VIRUS || SCAN_ALL)
	    ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash);
	if (ret == CL_VIRUS)
	    viruses_found++;
	cli_ac_freedata(&tdata);
	if(bm_offmode)
	    cli_bm_freeoff(&toff);
    }

    if(groot) {
	if(ret != CL_VIRUS || SCAN_ALL)
	    ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash);
	cli_ac_freedata(&gdata);
    }

    if(info.exeinfo.section)
	free(info.exeinfo.section);
    cli_hashset_destroy(&info.exeinfo.vinfo);

    if (SCAN_ALL && viruses_found)
	return CL_VIRUS;
    if(ret == CL_VIRUS)
	return CL_VIRUS;

    return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
}
コード例 #8
0
cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
{
	unsigned char smallbuff[MAGIC_BUFFER_SIZE + 1], *decoded, *bigbuff;
	int bread, sret;
	cli_file_t ret = CL_TYPE_UNKNOWN_DATA;
	struct cli_matcher *root;
	struct cli_ac_data mdata;


    memset(smallbuff, 0, sizeof(smallbuff));
    if((bread = read(desc, smallbuff, MAGIC_BUFFER_SIZE)) > 0)
	ret = cli_filetype(smallbuff, bread);

    if(engine && ret == CL_TYPE_UNKNOWN_TEXT) {
	root = engine->root[0];
	if(!root)
	    return ret;

	if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN))
	    return ret;

	sret = cli_ac_scanbuff(smallbuff, bread, NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL);

	cli_ac_freedata(&mdata);

	if(sret >= CL_TYPENO) {
	    ret = sret;
	} else {
	    if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN))
		return ret;

	    decoded = (unsigned char *) cli_utf16toascii((char *) smallbuff, bread);
	    if(decoded) {
		sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL);
		free(decoded);
		if(sret == CL_TYPE_HTML)
		    ret = CL_TYPE_HTML_UTF16;
	    }
	    cli_ac_freedata(&mdata);

	    if((((struct cli_dconf*) engine->dconf)->phishing & PHISHING_CONF_ENTCONV) && ret != CL_TYPE_HTML_UTF16) {
		    struct entity_conv conv;
		    const size_t conv_size = 2*bread < 256 ? 256 : 2*bread;

		if(init_entity_converter(&conv,UNKNOWN,conv_size) == 0) {
			int end = 0;
			m_area_t area;
			area.buffer = (unsigned char *) smallbuff;
			area.length = bread;
			area.offset = 0;

		    while(!end) {
			if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN))
			    return ret;

			decoded =  encoding_norm_readline(&conv, NULL, &area, bread);

			if(decoded) {
			    sret = cli_ac_scanbuff(decoded, strlen((const char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL);
			    free(decoded);
			    if(sret == CL_TYPE_HTML) {
				ret = CL_TYPE_HTML;
				end = 1;
			    }
			} else
			    end = 1;

			cli_ac_freedata(&mdata);
		    }

		    entity_norm_done(&conv);

		} else {
		    cli_warnmsg("cli_filetype2: Error initializing entity converter\n");
		}
	    }
	}
    }

    if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) {

	if(!(bigbuff = (unsigned char *) cli_calloc(37638 + 1, sizeof(unsigned char))))
	    return ret;

	lseek(desc, 0, SEEK_SET);
	if((bread = read(desc, bigbuff, 37638)) > 0) {

	    bigbuff[bread] = 0;

	    switch(is_tar(bigbuff, bread)) {
		case 1:
		    ret = CL_TYPE_OLD_TAR;
		    cli_dbgmsg("Recognized old fashioned tar file\n");
		    break;
		case 2:
		    ret = CL_TYPE_POSIX_TAR;
		    cli_dbgmsg("Recognized POSIX tar file\n");
		    break;
	    }
	}

	if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) {

	    if(!memcmp(bigbuff + 32769, "CD001" , 5) || !memcmp(bigbuff + 37633, "CD001" , 5)) {
		cli_dbgmsg("Recognized ISO 9660 CD-ROM data\n");
		ret = CL_TYPE_DATA;
	    } else if(!memcmp(bigbuff + 32776, "CDROM" , 5)) {
		cli_dbgmsg("Recognized High Sierra CD-ROM data\n");
		ret = CL_TYPE_DATA;
	    }
	}

	free(bigbuff);
    }

    return ret;
}