2
* Copyright (C) 2006 Sensory Networks, Inc.
3
* (C) 2007 Tomasz Kojm <tkojm@clamav.net>
4
* Written by Tomasz Kojm
2
* Copyright (C) 2006 Tomasz Kojm <tkojm@clamav.net>
6
4
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
10
9
* This program is distributed in the hope that it will be useful,
11
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
29
28
#include <sys/types.h>
30
29
#include <sys/stat.h>
32
30
#include <unistd.h>
32
#include "shared/memory.h"
35
33
#include "shared/misc.h"
36
34
#include "shared/output.h"
37
35
#include "shared/cdiff.h"
38
#include "libclamav/sha256.h"
40
37
#include "libclamav/str.h"
41
38
#include "libclamav/others.h"
42
39
#include "libclamav/cvd.h"
43
#include "libclamav/default.h"
40
#include "libclamav/sha256.h"
43
#include "libclamav/dsig.h"
47
#include "libclamav/dsig.h"
49
#define PSS_NSTR "14783905874077467090262228516557917570254599638376203532031989214105552847269687489771975792123442185817287694951949800908791527542017115600501303394778618535864845235700041590056318230102449612217458549016089313306591388590790796515819654102320725712300822356348724011232654837503241736177907784198700834440681124727060540035754699658105895050096576226753008596881698828185652424901921668758326578462003247906470982092298106789657211905488986281078346361469524484829559560886227198091995498440676639639830463593211386055065360288422394053998134458623712540683294034953818412458362198117811990006021989844180721010947"
50
#define PSS_ESTR "100002053"
51
#define PSS_NBITS 2048
52
#define PSS_DIGEST_LENGTH 32
54
/* the line size can be changed from within .cdiff */
55
#define CDIFF_LINE_SIZE CLI_DEFAULT_LSIG_BUFSIZE + 32
57
48
struct cdiff_node {
58
49
unsigned int lineno;
65
56
struct cdiff_node *add_start, *add_last;
66
57
struct cdiff_node *del_start;
67
struct cdiff_node *xchg_start, *xchg_last;
58
struct cdiff_node *xchg_start;
72
63
unsigned short argc;
73
int (*handler)(const char *, struct cdiff_ctx *, char *, unsigned int);
64
int (*handler)(const char *, struct cdiff_ctx *);
76
static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
77
static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
78
static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
79
static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
80
static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
81
static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
82
static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
67
static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx);
68
static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx);
69
static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx);
70
static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx);
71
static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx);
72
static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx);
73
static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx);
84
75
static struct cdiff_cmd commands[] = {
234
static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
225
static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx)
237
228
struct cdiff_node *pt, *last, *new;
291
static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
282
static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx)
293
284
char *arg, *arg2;
294
285
struct cdiff_node *pt, *last, *new;
324
315
new->str2 = arg2;
325
316
new->lineno = lineno;
318
if(!ctx->xchg_start) {
328
320
ctx->xchg_start = new;
330
ctx->xchg_last->next = new;
332
ctx->xchg_last = new;
324
if(lineno < ctx->xchg_start->lineno) {
325
new->next = ctx->xchg_start;
326
ctx->xchg_start = new;
329
pt = ctx->xchg_start;
333
if((pt->lineno < lineno) && (!pt->next || lineno < pt->next->lineno))
339
new->next = last->next;
336
static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
347
static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx)
338
349
struct cdiff_node *add, *del, *xchg;
339
350
unsigned int lines = 0;
351
char *tmp, line[1024];
341
352
FILE *fh, *tmpfh;
353
364
if(del || xchg) {
355
if(!(fh = fopen(ctx->open_db, "rb"))) {
366
if(!(fh = fopen(ctx->open_db, "r"))) {
356
367
logg("!cdiff_cmd_close: Can't open file %s for reading\n", ctx->open_db);
366
if(!(tmpfh = fopen(tmp, "wb"))) {
377
if(!(tmpfh = fopen(tmp, "w"))) {
367
378
logg("!cdiff_cmd_close: Can't open file %s for writing\n", tmp);
373
while(fgets(lbuf, lbuflen, fh)) {
384
while(fgets(line, sizeof(line), fh)) {
376
387
if(del && del->lineno == lines) {
377
if(strncmp(lbuf, del->str, strlen(del->str))) {
388
if(strncmp(line, del->str, strlen(del->str))) {
382
393
logg("!cdiff_cmd_close: Can't apply DEL at line %d of %s\n", lines, ctx->open_db);
389
401
if(xchg && xchg->lineno == lines) {
390
if(strncmp(lbuf, xchg->str, strlen(xchg->str))) {
402
if(strncmp(line, xchg->str, strlen(xchg->str))) {
450
if(!(fh = fopen(ctx->open_db, "ab"))) {
462
if(!(fh = fopen(ctx->open_db, "a"))) {
451
463
logg("!cdiff_cmd_close: Can't open file %s for appending\n", ctx->open_db);
472
static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
484
static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
474
486
unsigned int lines = 0, start_line, end_line;
475
char *arg, *srcdb, *dstdb, *tmpdb, *start_str, *end_str;
487
char *arg, *srcdb, *dstdb, *tmpdb, line[1024], *start_str, *end_str;
476
488
FILE *src, *dst, *tmp;
521
if(!(src = fopen(srcdb, "rb"))) {
533
if(!(src = fopen(srcdb, "r"))) {
522
534
logg("!cdiff_cmd_move: Can't open %s for reading\n", srcdb);
538
if(!(dst = fopen(dstdb, "ab"))) {
550
if(!(dst = fopen(dstdb, "a"))) {
539
551
logg("!cdiff_cmd_move: Can't open %s for appending\n", dstdb);
559
if(!(tmp = fopen(tmpdb, "wb"))) {
571
if(!(tmp = fopen(tmpdb, "w"))) {
560
572
logg("!cdiff_cmd_move: Can't open file %s for writing\n", tmpdb);
571
while(fgets(lbuf, lbuflen, src)) {
583
while(fgets(line, sizeof(line), src)) {
574
586
if(lines == start_line) {
575
if(strncmp(lbuf, start_str, strlen(start_str))) {
587
if(strncmp(line, start_str, strlen(start_str))) {
603
} while((lines < end_line) && fgets(lbuf, lbuflen, src) && lines++);
615
} while((lines < end_line) && fgets(line, sizeof(line), src) && lines++);
610
if(strncmp(lbuf, end_str, strlen(end_str))) {
622
if(strncmp(line, end_str, strlen(end_str))) {
713
static int cdiff_execute(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
719
static int cdiff_execute(const char *cmdstr, struct cdiff_ctx *ctx)
715
721
char *cmd_name, *tmp;
716
int (*cmd_handler)(const char *, struct cdiff_ctx *, char *, unsigned int) = NULL;
722
int (*cmd_handler)(const char *, struct cdiff_ctx *) = NULL;
746
if(cmd_handler(cmdstr, ctx, lbuf, lbuflen)) {
752
if(cmd_handler(cmdstr, ctx)) {
747
753
logg("!cdiff_apply: Can't execute command %s\n", cmd_name);
758
764
struct cdiff_ctx ctx;
761
char *line, *lbuf, buff[FILEBUFF], *dsig = NULL;
767
char line[1024], buff[FILEBUFF], *dsig = NULL;
762
768
unsigned int lines = 0, cmds = 0;
763
unsigned int difflen, diffremain, line_size = CDIFF_LINE_SIZE;
769
unsigned int difflen, diffremain;
767
774
SHA256_CTX sha256ctx;
768
775
unsigned char digest[32];
770
778
#define DSIGBUFF 350
772
780
memset(&ctx, 0, sizeof(ctx));
779
if(!(line = malloc(line_size))) {
780
logg("!cdiff_apply: Can't allocate memory for 'line'\n");
785
if(!(lbuf = malloc(line_size))) {
786
logg("!cdiff_apply: Can't allocate memory for 'lbuf'\n");
792
787
if(mode == 1) { /* .cdiff */
794
789
if(lseek(desc, -DSIGBUFF, SEEK_END) == -1) {
795
790
logg("!cdiff_apply: lseek(desc, %d, SEEK_END) failed\n", -DSIGBUFF);
802
memset(line, 0, line_size);
795
memset(line, 0, sizeof(line));
803
796
if(read(desc, line, DSIGBUFF) != DSIGBUFF) {
804
797
logg("!cdiff_apply: Can't read %d bytes\n", DSIGBUFF);
836
823
logg("!cdiff_apply: compressed data end offset < 0\n");
843
828
if(lseek(desc, 0, SEEK_SET) == -1) {
844
829
logg("!cdiff_apply: lseek(desc, 0, SEEK_SET) failed\n");
851
835
sha256_init(&sha256ctx);
853
837
while((bread = read(desc, buff, FILEBUFF)) > 0) {
862
sha256_final(&sha256ctx, digest);
846
sha256_final(&sha256ctx);
847
sha256_digest(&sha256ctx, digest);
864
if(cli_versig2(digest, dsig, PSS_NSTR, PSS_ESTR) != CL_SUCCESS) {
849
if(cli_versigpss(digest, dsig)) {
865
850
logg("!cdiff_apply: Incorrect digital signature\n");
872
856
if(lseek(desc, 0, SEEK_SET) == -1) {
873
857
logg("!cdiff_apply: lseek(desc, 0, SEEK_SET) failed\n");
889
871
if(sscanf(buff, "ClamAV-Diff:%*u:%u:", &difflen) != 1) {
890
872
logg("!cdiff_apply: Incorrect file format\n");
897
877
if(!(gzh = gzdopen(desc, "rb"))) {
898
878
logg("!cdiff_apply: Can't gzdopen descriptor %d\n", desc);
905
883
diffremain = difflen;
906
884
while(diffremain) {
907
unsigned int bufsize = diffremain < line_size ? diffremain + 1 : line_size;
885
unsigned int bufsize = diffremain < sizeof(line) ? diffremain + 1 : sizeof(line);
909
887
if(!gzgets(gzh, line, bufsize)) {
910
888
logg("!cdiff_apply: Premature EOF at line %d\n", lines + 1);
911
889
cdiff_ctx_free(&ctx);
917
893
diffremain -= strlen(line);
924
if(!strncmp(line, "#LSIZE", 6) && sscanf(line, "#LSIZE %u", &line_size) == 1) {
926
if(line_size < CDIFF_LINE_SIZE || line_size > 10485760) {
927
logg("^cdiff_apply: Ignoring new buffer size request - invalid size %d\n", line_size);
928
line_size = CDIFF_LINE_SIZE;
931
r1 = realloc(line, line_size);
932
r2 = realloc(lbuf, line_size);
934
logg("!cdiff_apply: Can't resize line buffer to %d bytes\n", line_size);
935
cdiff_ctx_free(&ctx);
897
if(line[0] == '#' || !strlen(line))
955
if(cdiff_execute(line, &ctx, lbuf, line_size) == -1) {
900
if(cdiff_execute(line, &ctx) == -1) {
956
901
logg("!cdiff_apply: Error executing command at line %d\n", lines);
957
902
cdiff_ctx_free(&ctx);
968
911
} else { /* .script */
970
if(!(fh = fdopen(desc, "rb"))) {
913
if(!(fh = fdopen(desc, "r"))) {
971
914
logg("!cdiff_apply: fdopen() failed for descriptor %d\n", desc);
978
while(fgets(line, line_size, fh)) {
919
while(fgets(line, sizeof(line), fh)) {
985
if(!strncmp(line, "#LSIZE", 6) && sscanf(line, "#LSIZE %u", &line_size) == 1) {
987
if(line_size < CDIFF_LINE_SIZE || line_size > 10485760) {
988
logg("^cdiff_apply: Ignoring new buffer size request - invalid size %d\n", line_size);
989
line_size = CDIFF_LINE_SIZE;
992
r1 = realloc(line, line_size);
993
r2 = realloc(lbuf, line_size);
995
logg("!cdiff_apply: Can't resize line buffer to %d bytes\n", line_size);
996
cdiff_ctx_free(&ctx);
923
if(line[0] == '#' || !strlen(line))
1016
if(cdiff_execute(line, &ctx, lbuf, line_size) == -1) {
926
if(cdiff_execute(line, &ctx) == -1) {
1017
927
logg("!cdiff_apply: Error executing command at line %d\n", lines);
1018
928
cdiff_ctx_free(&ctx);