~ubuntu-branches/ubuntu/dapper/clamav/dapper-updates

« back to all changes in this revision

Viewing changes to libclamav/matcher.c

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-03-29 15:19:17 UTC
  • mfrom: (12.1.9 dapper-security)
  • Revision ID: james.westby@ubuntu.com-20100329151917-lpe62mhy2p02rpw4
Tags: 0.95.3+dfsg-1ubuntu0.09.04~dapper2
No change rebuild from dapper-backports per microrelease exception

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
#include "special.h"
44
44
#include "str.h"
45
45
#include "cltypes.h"
46
 
 
47
 
 
48
 
int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli_file_t ftype)
 
46
#include "default.h"
 
47
 
 
48
 
 
49
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)
49
50
{
50
51
        int ret = CL_CLEAN;
51
52
        unsigned int i;
72
73
 
73
74
    if(troot) {
74
75
 
75
 
        if((ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, AC_DEFAULT_TRACKLEN)))
76
 
            return ret;
77
 
 
78
 
        if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, 0, ftype, -1)) != CL_VIRUS)
79
 
            ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, &mdata, 0, ftype, -1, NULL, AC_SCAN_VIR, NULL);
80
 
 
 
76
        if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
 
77
            return ret;
 
78
 
 
79
        if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, troot, offset, ftype, -1)) != CL_VIRUS)
 
80
            ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL);
 
81
 
 
82
        if(!acdata)
 
83
            cli_ac_freedata(&mdata);
 
84
 
 
85
        if(ret == CL_VIRUS)
 
86
            return ret;
 
87
    }
 
88
 
 
89
    if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
 
90
        return ret;
 
91
 
 
92
    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, groot, offset, ftype, -1)) != CL_VIRUS)
 
93
        ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL);
 
94
 
 
95
    if(!acdata)
81
96
        cli_ac_freedata(&mdata);
82
97
 
83
 
        if(ret == CL_VIRUS)
84
 
            return ret;
85
 
    }
86
 
 
87
 
    if((ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, AC_DEFAULT_TRACKLEN)))
88
 
        return ret;
89
 
 
90
 
    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, 0, ftype, -1)) != CL_VIRUS)
91
 
        ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, &mdata, 0, ftype, -1, NULL, AC_SCAN_VIR, NULL);
92
 
 
93
 
    cli_ac_freedata(&mdata);
94
 
 
95
98
    return ret;
96
99
}
97
100
 
105
108
 
106
109
    *ret = 0;
107
110
 
 
111
    if((pt = strchr(offstr, ',')))
 
112
        *maxshift = atoi(++pt);
 
113
 
 
114
    if(isdigit(offstr[0]))
 
115
        return atoi(offstr);
 
116
 
 
117
    if(fd == -1) {
 
118
        *ret = -1;
 
119
        return 0;
 
120
    }
 
121
 
108
122
    if(!strncmp(offstr, "EP", 2) || offstr[0] == 'S') {
109
123
 
110
124
        if(info->status == -1) {
137
151
        }
138
152
    }
139
153
 
140
 
    if((pt = strchr(offstr, ',')))
141
 
        *maxshift = atoi(++pt);
142
 
 
143
 
    if(isdigit(offstr[0])) {
144
 
        return atoi(offstr);
145
 
 
146
 
    } else if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
 
154
    if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
147
155
 
148
156
        if(offstr[2] == '+')
149
157
            return info->exeinfo.ep + atoi(offstr + 3);
196
204
    return 0;
197
205
}
198
206
 
199
 
static int cli_checkfp(int fd, const struct cl_engine *engine)
 
207
int cli_checkfp(int fd, cli_ctx *ctx)
200
208
{
201
209
        unsigned char *digest;
 
210
        char md5[33];
 
211
        unsigned int i;
202
212
        const char *virname;
203
 
 
204
 
 
205
 
    if(engine->md5_fp) {
 
213
        off_t pos;
 
214
        struct stat sb;
 
215
        const struct cli_bm_patt *patt = NULL;
 
216
 
 
217
 
 
218
    if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
 
219
        cli_errmsg("cli_checkfp(): lseek() failed\n");
 
220
        return 0;
 
221
    }
 
222
 
 
223
    lseek(fd, 0, SEEK_SET);
 
224
 
 
225
    if(ctx->engine->md5_fp) {
 
226
        if(fstat(fd, &sb) == -1) {
 
227
            cli_errmsg("cli_checkfp(): fstat(%d) failed\n", fd);
 
228
            lseek(fd, pos, SEEK_SET);
 
229
            return 0;
 
230
        }
 
231
 
206
232
        if(!(digest = cli_md5digest(fd))) {
207
233
            cli_errmsg("cli_checkfp(): Can't generate MD5 checksum\n");
 
234
            lseek(fd, pos, SEEK_SET);
208
235
            return 0;
209
236
        }
210
237
 
211
 
        if(cli_bm_scanbuff(digest, 16, &virname, engine->md5_fp, 0, 0, -1) == CL_VIRUS) {
212
 
            cli_dbgmsg("Eliminated false positive match (fp sig: %s)\n", virname);
 
238
        if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, 0, -1) == CL_VIRUS && patt->filesize == sb.st_size) {
 
239
            cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
213
240
            free(digest);
 
241
            lseek(fd, pos, SEEK_SET);
214
242
            return 1;
215
243
        }
 
244
        for(i = 0; i < 16; i++)
 
245
            sprintf(md5 + i * 2, "%02x", digest[i]);
 
246
        md5[32] = 0;
 
247
        cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) sb.st_size, *ctx->virname ? *ctx->virname : "Name");
216
248
        free(digest);
217
249
    }
218
250
 
 
251
    lseek(fd, pos, SEEK_SET);
219
252
    return 0;
220
253
}
221
254
 
226
259
        unsigned int maxshift = 0;
227
260
 
228
261
 
229
 
    if(offstr && desc != -1) {
 
262
    if(offstr) {
230
263
        offset = cli_caloff(offstr, info, desc, ftype, &ret, &maxshift);
231
264
 
232
 
        if(ret == -1) {
233
 
            cli_dbgmsg("cli_validatesig: Can't calculate offset for signature %s\n", virname);
 
265
        if(ret == -1)
234
266
            return 0;
235
 
        }
236
267
 
237
268
        if(maxshift) {
238
269
            if((fileoff < offset) || (fileoff > offset + (off_t) maxshift)) {
297
328
        return CL_EMEM;
298
329
    }
299
330
 
300
 
    if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, AC_DEFAULT_TRACKLEN)))
 
331
    if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
301
332
        return ret;
302
333
 
303
334
    if(troot) {
304
 
        if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, AC_DEFAULT_TRACKLEN)))
 
335
        if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
305
336
            return ret;
306
337
    }
307
338
 
325
356
            length += maxpatlen;
326
357
 
327
358
        if(troot) {
328
 
            if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, ftype, desc)) != CL_VIRUS)
 
359
            if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, troot, offset, ftype, desc)) != CL_VIRUS)
329
360
                ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, desc, ftoffset, acmode, NULL);
330
361
 
331
362
            if(ret == CL_VIRUS) {
334
365
                    cli_ac_freedata(&gdata);
335
366
                cli_ac_freedata(&tdata);
336
367
 
337
 
                lseek(desc, 0, SEEK_SET);
338
 
                if(cli_checkfp(desc, ctx->engine))
 
368
                if(cli_checkfp(desc, ctx))
339
369
                    return CL_CLEAN;
340
370
                else
341
371
                    return CL_VIRUS;
343
373
        }
344
374
 
345
375
        if(!ftonly) {
346
 
            if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, ftype, desc)) != CL_VIRUS)
 
376
            if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, groot, offset, ftype, desc)) != CL_VIRUS)
347
377
                ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, desc, ftoffset, acmode, NULL);
348
378
 
349
379
            if(ret == CL_VIRUS) {
351
381
                cli_ac_freedata(&gdata);
352
382
                if(troot)
353
383
                    cli_ac_freedata(&tdata);
354
 
                lseek(desc, 0, SEEK_SET);
355
 
                if(cli_checkfp(desc, ctx->engine))
 
384
                if(cli_checkfp(desc, ctx))
356
385
                    return CL_CLEAN;
357
386
                else
358
387
                    return CL_VIRUS;
414
443
 
415
444
    if(ret == CL_VIRUS) {
416
445
        lseek(desc, 0, SEEK_SET);
417
 
        if(cli_checkfp(desc, ctx->engine))
 
446
        if(cli_checkfp(desc, ctx))
418
447
            return CL_CLEAN;
419
448
        else
420
449
            return CL_VIRUS;
421
450
    }
422
451
 
423
452
    if(!ftonly && ctx->engine->md5_hdb) {
 
453
            const struct cli_bm_patt *patt;
 
454
            struct stat sb;
424
455
        cli_md5_final(digest, &md5ctx);
425
 
        if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS))
 
456
        fstat(desc, &sb);
 
457
        if(cli_bm_scanbuff(digest, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && patt->filesize == sb.st_size && (cli_bm_scanbuff(digest, 16, NULL, &patt, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS || patt->filesize != sb.st_size))
426
458
            return CL_VIRUS;
427
459
    }
428
460