50
52
static int xar_cleanup_temp_file(cli_ctx *ctx, int fd, char * tmpname)
52
54
int rc = CL_SUCCESS;
54
if(!ctx->engine->keeptmp) {
55
if (cli_unlink(tmpname)) {
56
cli_errmsg("cli_scanxar: error unlinking tmpfile %s\n", tmpname);
57
if (tmpname != NULL) {
58
if (!ctx->engine->keeptmp) {
59
if (cli_unlink(tmpname)) {
60
cli_dbgmsg("cli_scanxar: error unlinking tmpfile %s\n", tmpname);
77
82
*value = atol((const char *)numstr);
79
cli_errmsg("cli_scanxar: XML element value %li\n", *value);
84
cli_dbgmsg("cli_scanxar: XML element value %li\n", *value);
85
cli_errmsg("cli_scanxar: No text for XML element\n");
90
cli_dbgmsg("cli_scanxar: No text for XML element\n");
122
129
cli_dbgmsg("cli_scanxar: checksum value is %s.\n", *cksum);
125
cli_errmsg("cli_scanxar: xmlTextReaderConstValue() returns NULL for checksum value.\n");
132
cli_dbgmsg("cli_scanxar: xmlTextReaderConstValue() returns NULL for checksum value.\n");
129
cli_errmsg("cli_scanxar: No text for XML checksum element.\n");
136
cli_dbgmsg("cli_scanxar: No text for XML checksum element.\n");
191
198
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
192
199
xmlChar * style = xmlTextReaderGetAttribute(reader, (const xmlChar *)"style");
193
200
if (style == NULL) {
194
cli_errmsg("cli_scaxar: xmlTextReaderGetAttribute no style attribute "
201
cli_dbgmsg("cli_scaxar: xmlTextReaderGetAttribute no style attribute "
195
202
"for encoding element\n");
196
203
*encoding = CL_TYPE_ANY;
197
204
} else if (xmlStrEqual(style, (const xmlChar *)"application/x-gzip")) {
210
217
cli_dbgmsg("cli_scanxar: encoding = application/x-xz.\n");
211
218
*encoding = CL_TYPE_XZ;
213
cli_errmsg("cli_scaxar: unknown style value=%s for encoding element\n", style);
220
cli_dbgmsg("cli_scaxar: unknown style value=%s for encoding element\n", style);
214
221
*encoding = CL_TYPE_ANY;
217
226
} else if (indata && xmlStrEqual(name, (const xmlChar *)"data") &&
218
227
xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) {
283
292
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
284
293
subdoc = xmlTextReaderReadInnerXml(reader);
285
294
if (subdoc == NULL) {
286
cli_errmsg("cli_scanxar: no content in subdoc element.\n");
295
cli_dbgmsg("cli_scanxar: no content in subdoc element.\n");
287
296
xmlTextReaderNext(reader);
290
// printf("subdoc:\n%s\n", subdoc);
291
299
subdoc_len = xmlStrlen(subdoc);
292
300
cli_dbgmsg("cli_scanxar: in-memory scan of xml subdocument, len %i.\n", subdoc_len);
293
301
rc = cli_mem_scandesc(subdoc, subdoc_len, ctx);
297
305
/* make a file to leave if --leave-temps in effect */
298
306
if(ctx->engine->keeptmp) {
299
307
if ((rc = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
300
cli_errmsg("cli_scanxar: Can't create temporary file for subdocument.\n");
308
cli_dbgmsg("cli_scanxar: Can't create temporary file for subdocument.\n");
302
310
cli_dbgmsg("cli_scanxar: Writing subdoc to temp file %s.\n", tmpname);
303
311
if (cli_writen(fd, subdoc, subdoc_len) < 0) {
304
cli_errmsg("cli_scanxar: cli_writen error writing subdoc temporary file.\n");
312
cli_dbgmsg("cli_scanxar: cli_writen error writing subdoc temporary file.\n");
307
315
rc = xar_cleanup_temp_file(ctx, fd, tmpname);
320
static void * xar_hash_init(int hash, SHA1Context *sc, cli_md5_ctx *mc)
328
static void * xar_hash_init(int hash, void **sc, void **mc)
325
333
case XAR_CKSUM_SHA1:
334
*sc = cl_hash_init("sha1");
328
340
case XAR_CKSUM_MD5:
341
*mc = cl_hash_init("md5");
331
347
case XAR_CKSUM_OTHER:
332
348
case XAR_CKSUM_NONE:
338
static void xar_hash_update(void * hash_ctx, const void * data, unsigned long size, int hash)
354
static void xar_hash_update(void * hash_ctx, void * data, unsigned long size, int hash)
340
356
if (!hash_ctx || !data || !size)
344
SHA1Update(hash_ctx, data, size);
347
if (0 == cli_md5_update(hash_ctx, data, size)) {
348
cli_errmsg("cli_scanxar: cli_md5_update invalid return.\n");
352
361
case XAR_CKSUM_OTHER:
365
cl_update_hash(hash_ctx, data, size);
359
368
static void xar_hash_final(void * hash_ctx, void * result, int hash)
362
370
if (!hash_ctx || !result)
366
SHA1Final(hash_ctx, result);
369
cli_md5_final(result, hash_ctx);
371
374
case XAR_CKSUM_OTHER:
372
375
case XAR_CKSUM_NONE:
379
cl_finish_hash(hash_ctx, result);
378
382
static int xar_hash_check(int hash, const void * result, const void * expected)
424
429
/* retrieve xar header */
425
430
if (fmap_readn(*ctx->fmap, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) {
426
cli_errmsg("cli_scanxar: Invalid header, too short.\n");
431
cli_dbgmsg("cli_scanxar: Invalid header, too short.\n");
427
432
return CL_EFORMAT;
429
434
hdr.magic = be32_to_host(hdr.magic);
451
456
/* Uncompress TOC */
452
457
strm.next_in = (unsigned char *)fmap_need_off_once(*ctx->fmap, hdr.size, hdr.toc_length_compressed);
453
458
if (strm.next_in == NULL) {
454
cli_errmsg("cli_scanxar: fmap_need_off_once fails on TOC.\n");
459
cli_dbgmsg("cli_scanxar: fmap_need_off_once fails on TOC.\n");
457
462
strm.avail_in = hdr.toc_length_compressed;
458
463
toc = cli_malloc(hdr.toc_length_decompressed+1);
459
464
if (toc == NULL) {
460
cli_errmsg("cli_scanxar: cli_malloc fails on TOC decompress buffer.\n");
465
cli_dbgmsg("cli_scanxar: cli_malloc fails on TOC decompress buffer.\n");
463
468
toc[hdr.toc_length_decompressed] = '\0';
465
470
strm.next_out = (unsigned char *)toc;
466
471
rc = inflateInit(&strm);
467
472
if (rc != Z_OK) {
468
cli_errmsg("cli_scanxar:inflateInit error %i \n", rc);
473
cli_dbgmsg("cli_scanxar:inflateInit error %i \n", rc);
472
477
rc = inflate(&strm, Z_SYNC_FLUSH);
473
478
if (rc != Z_OK && rc != Z_STREAM_END) {
474
cli_errmsg("cli_scanxar:inflate error %i \n", rc);
479
cli_dbgmsg("cli_scanxar:inflate error %i \n", rc);
478
483
rc = inflateEnd(&strm);
479
484
if (rc != Z_OK) {
480
cli_errmsg("cli_scanxar:inflateEnd error %i \n", rc);
485
cli_dbgmsg("cli_scanxar:inflateEnd error %i \n", rc);
498
503
/* make a file to leave if --leave-temps in effect */
499
504
if(ctx->engine->keeptmp) {
500
505
if ((rc = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
501
cli_errmsg("cli_scanxar: Can't create temporary file for TOC.\n");
506
cli_dbgmsg("cli_scanxar: Can't create temporary file for TOC.\n");
504
509
if (cli_writen(fd, toc, hdr.toc_length_decompressed) < 0) {
505
cli_errmsg("cli_scanxar: cli_writen error writing TOC.\n");
510
cli_dbgmsg("cli_scanxar: cli_writen error writing TOC.\n");
507
512
xar_cleanup_temp_file(ctx, fd, tmpname);
515
520
reader = xmlReaderForMemory(toc, hdr.toc_length_decompressed, "noname.xml", NULL, 0);
516
521
if (reader == NULL) {
517
cli_errmsg("cli_scanxar: xmlReaderForMemory error for TOC\n");
522
cli_dbgmsg("cli_scanxar: xmlReaderForMemory error for TOC\n");
521
526
rc = xar_scan_subdocuments(reader, ctx);
522
527
if (rc != CL_SUCCESS) {
523
cli_errmsg("xar_scan_subdocuments returns %i.\n", rc);
528
cli_dbgmsg("xar_scan_subdocuments returns %i.\n", rc);
524
529
goto exit_reader;
531
536
&a_cksum, &a_hash, &e_cksum, &e_hash))) {
532
537
int do_extract_cksum = 1;
533
538
unsigned char * blockp;
534
SHA1Context a_sc, e_sc;
535
cli_md5_ctx a_mc, e_mc;
536
541
void *a_hash_ctx, *e_hash_ctx;
537
542
char result[SHA1_HASH_SIZE];
547
552
at = offset + hdr.toc_length_compressed + hdr.size;
549
554
if ((rc = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
550
cli_errmsg("cli_scanxar: Can't generate temporary file.\n");
555
cli_dbgmsg("cli_scanxar: Can't generate temporary file.\n");
551
556
goto exit_reader;
564
569
/* inflate gzip directly because file segments do not contain magic */
565
570
memset(&strm, 0, sizeof(strm));
566
571
if ((rc = inflateInit(&strm)) != Z_OK) {
567
cli_errmsg("cli_scanxar: InflateInit failed: %d\n", rc);
572
cli_dbgmsg("cli_scanxar: InflateInit failed: %d\n", rc);
572
578
while (at < map->len && at < offset+hdr.toc_length_compressed+hdr.size+length) {
575
581
unsigned int bytes = MIN(map->len - at, map->pgsz);
576
582
bytes = MIN(length, bytes);
577
//cli_dbgmsg("cli_scanxar: fmap %u bytes\n", bytes);
578
583
if(!(strm.next_in = next_in = (void*)fmap_need_off_once(map, at, bytes))) {
579
584
cli_dbgmsg("cli_scanxar: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
580
585
inflateEnd(&strm);
588
593
unsigned char buff[FILEBUFF];
589
594
strm.avail_out = sizeof(buff);
590
595
strm.next_out = buff;
591
//cli_dbgmsg("cli_scanxar: inflating.....\n");
592
596
inf = inflate(&strm, Z_SYNC_FLUSH);
593
597
if (inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
594
cli_errmsg("cli_scanxar: inflate error %i %s.\n", inf, strm.msg?strm.msg:"");
598
cli_dbgmsg("cli_scanxar: inflate error %i %s.\n", inf, strm.msg?strm.msg:"");
600
604
bytes = sizeof(buff) - strm.avail_out;
602
606
xar_hash_update(e_hash_ctx, buff, bytes, e_hash);
604
608
if (cli_writen(fd, buff, bytes) < 0) {
605
cli_errmsg("cli_scanxar: cli_writen error file %s.\n", tmpname);
609
cli_dbgmsg("cli_scanxar: cli_writen error file %s.\n", tmpname);
606
610
inflateEnd(&strm);
608
612
goto exit_tmpfile;
631
638
unsigned long in_remaining = length;
632
639
unsigned long out_size = 0;
633
640
unsigned char * buff = __lzma_wrap_alloc(NULL, CLI_LZMA_OBUF_SIZE);
635
643
memset(&lz, 0, sizeof(lz));
636
644
if (buff == NULL) {
637
cli_errmsg("cli_scanxar: memory request for lzma decompression buffer fails.\n");
645
cli_dbgmsg("cli_scanxar: memory request for lzma decompression buffer fails.\n");
639
647
goto exit_tmpfile;
644
652
if (blockp == NULL) {
645
653
char errbuff[128];
646
654
cli_strerror(errno, errbuff, sizeof(errbuff));
647
cli_errmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
655
cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
648
656
length, at, errbuff);
650
658
__lzma_wrap_free(NULL, buff);
657
665
xar_hash_update(a_hash_ctx, blockp, CLI_LZMA_HDR_SIZE, a_hash);
659
rc = cli_LzmaInit(&lz, 0);
660
if (rc != LZMA_RESULT_OK) {
661
cli_errmsg("cli_scanxar: cli_LzmaInit() fails: %i.\n", rc);
667
lret = cli_LzmaInit(&lz, 0);
668
if (lret != LZMA_RESULT_OK) {
669
cli_dbgmsg("cli_scanxar: cli_LzmaInit() fails: %i.\n", lret);
663
671
__lzma_wrap_free(NULL, buff);
667
676
at += CLI_LZMA_HDR_SIZE;
668
677
in_remaining -= CLI_LZMA_HDR_SIZE;
669
678
while (at < map->len && at < offset+hdr.toc_length_compressed+hdr.size+length) {
679
688
if (lz.next_in == NULL) {
680
689
char errbuff[128];
681
690
cli_strerror(errno, errbuff, sizeof(errbuff));
682
cli_errmsg("cli_scanxar: Can't read %li bytes @ %li, errno: %s.\n",
691
cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno: %s.\n",
683
692
length, at, errbuff);
685
694
__lzma_wrap_free(NULL, buff);
687
696
goto exit_tmpfile;
690
rc = cli_LzmaDecode(&lz);
691
if (rc != LZMA_RESULT_OK && rc != LZMA_STREAM_END) {
692
cli_errmsg("cli_scanxar: cli_LzmaDecode() fails: %i.\n", rc);
699
lret = cli_LzmaDecode(&lz);
700
if (lret != LZMA_RESULT_OK && lret != LZMA_STREAM_END) {
701
cli_dbgmsg("cli_scanxar: cli_LzmaDecode() fails: %i.\n", lret);
694
__lzma_wrap_free(NULL, buff);
695
cli_LzmaShutdown(&lz);
699
707
in_consumed = avail_in - lz.avail_in;
712
720
/* cli_dbgmsg("Writing %li bytes to LZMA decompress temp file, " */
713
721
/* "consumed %li of %li available compressed bytes.\n", */
714
722
/* avail_out, in_consumed, avail_in); */
716
724
if (cli_writen(fd, buff, avail_out) < 0) {
717
725
cli_dbgmsg("cli_scanxar: cli_writen error writing lzma temp file for %li bytes.\n",
722
730
goto exit_tmpfile;
725
733
/* Check file size limitation. */
726
734
out_size += avail_out;
727
735
if (cli_checklimits("cli_scanxar", ctx, out_size, 0, 0) != CL_CLEAN) {
731
if (rc == LZMA_STREAM_END)
739
if (lret == LZMA_STREAM_END)
736
743
cli_LzmaShutdown(&lz);
737
744
__lzma_wrap_free(NULL, buff);
754
761
if (!(blockp = (void*)fmap_need_off_once(map, at, length))) {
755
762
char errbuff[128];
756
763
cli_strerror(errno, errbuff, sizeof(errbuff));
757
cli_errmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
764
cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
758
765
length, at, errbuff);
760
767
goto exit_tmpfile;
774
xar_hash_final(a_hash_ctx, result, a_hash);
781
if (rc == CL_SUCCESS) {
782
xar_hash_final(a_hash_ctx, result, a_hash);
783
if (a_cksum != NULL) {
784
expected = cli_hex2str((char *)a_cksum);
785
if (xar_hash_check(a_hash, result, expected) != 0) {
786
cli_dbgmsg("cli_scanxar: archived-checksum missing or mismatch.\n");
789
cli_dbgmsg("cli_scanxar: archived-checksum matched.\n");
793
if (e_cksum != NULL) {
794
if (do_extract_cksum) {
795
xar_hash_final(e_hash_ctx, result, e_hash);
796
expected = cli_hex2str((char *)e_cksum);
797
if (xar_hash_check(e_hash, result, expected) != 0) {
798
cli_dbgmsg("cli_scanxar: extracted-checksum missing or mismatch.\n");
801
cli_dbgmsg("cli_scanxar: extracted-checksum matched.\n");
807
rc = cli_magic_scandesc(fd, ctx);
808
if (rc != CL_SUCCESS) {
809
if (rc == CL_VIRUS) {
810
cli_dbgmsg("cli_scanxar: Infected with %s\n", cli_get_last_virus(ctx));
813
} else if (rc != CL_BREAK) {
814
cli_dbgmsg("cli_scanxar: cli_magic_scandesc error %i\n", rc);
775
820
if (a_cksum != NULL) {
776
expected = cli_hex2str((char *)a_cksum);
777
if (xar_hash_check(a_hash, result, expected) != 0) {
778
cli_dbgmsg("cli_scanxar: archived-checksum missing or mismatch.\n");
781
cli_dbgmsg("cli_scanxar: archived-checksum matched.\n");
784
821
xmlFree(a_cksum);
787
824
if (e_cksum != NULL) {
788
if (do_extract_cksum) {
789
xar_hash_final(e_hash_ctx, result, e_hash);
790
expected = cli_hex2str((char *)e_cksum);
791
if (xar_hash_check(e_hash, result, expected) != 0) {
792
cli_dbgmsg("cli_scanxar: extracted-checksum missing or mismatch.\n");
795
cli_dbgmsg("cli_scanxar: extracted-checksum matched.\n");
799
825
xmlFree(e_cksum);
803
rc = cli_magic_scandesc(fd, ctx);
804
if (rc != CL_SUCCESS) {
805
if (rc == CL_VIRUS) {
806
cli_dbgmsg("cli_scanxar: Infected with %s\n", cli_get_last_virus(ctx));
809
} else if (rc != CL_BREAK) {
810
cli_errmsg("cli_scanxar: cli_magic_scandesc error %i\n", rc);
817
831
xar_cleanup_temp_file(ctx, fd, tmpname);
818
834
if (a_cksum != NULL)
819
835
xmlFree(a_cksum);
820
836
if (e_cksum != NULL)
821
837
xmlFree(e_cksum);
824
838
xmlTextReaderClose(reader);
825
839
xmlFreeTextReader(reader);
832
846
cli_dbgmsg("cli_scanxar: can't scan xar files, need libxml2.\n");
834
if (cksum_fails != 0)
835
cli_warnmsg("cli_scanxar: %u checksums missing, mismatched, or unsupported - use --debug for more info.\n", cksum_fails);
848
if (cksum_fails + extract_errors != 0) {
849
cli_warnmsg("cli_scanxar: %u checksum errors and %u extraction errors, use --debug for more info.\n",
850
cksum_fails, extract_errors);