Skip to content

Commit

Permalink
Add --checksum-choice option to choose the checksum algorithms.
Browse files Browse the repository at this point in the history
  • Loading branch information
Wayne Davison committed May 2, 2016
1 parent 4fc7887 commit a5a7d3a
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 54 deletions.
16 changes: 14 additions & 2 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,21 @@ Changes since 3.1.2:

BUG FIXES:

- ...
- Don't output about a new backup dir with appropriate info verbosity.
- Fixed some issues with the sort functions in support/rsyncstats.
- Added a way to specify group names that contain spaces in daemon config.
- If a backup fails (e.g. full disk) rsync exits with an error.
- Avoid invalid output in the summary if either the start or end time had
an error.

ENHANCEMENTS:

- Add the ability for rsync to compare nanosecond times in its file-check
- Added the ability for rsync to compare nanosecond times in its file-check
comparisons. Also added a short-option (-@) for --modify-window.
- Added the --checksum-choice=NAME[,NAME] option to choose the checksum
algorithms.

DEVELOPER RELATED:

- Tweak the "make" output when yodl isn't around to create the man pages.
- Changed an obsolete compile macro in configure.
4 changes: 2 additions & 2 deletions authenticate.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void gen_challenge(const char *addr, char *challenge)
SIVAL(input, 20, tv.tv_usec);
SIVAL(input, 24, getpid());

sum_init(0);
sum_init(-1, 0);
sum_update(input, sizeof input);
len = sum_end(digest);

Expand All @@ -85,7 +85,7 @@ static void generate_hash(const char *in, const char *challenge, char *out)
char buf[MAX_DIGEST_LEN];
int len;

sum_init(0);
sum_init(-1, 0);
sum_update(in, strlen(in));
sum_update(challenge, strlen(challenge));
len = sum_end(buf);
Expand Down
155 changes: 135 additions & 20 deletions checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,76 @@
extern int checksum_seed;
extern int protocol_version;
extern int proper_seed_order;
extern char *checksum_choice;

#define CSUM_NONE 0
#define CSUM_ARCHAIC 1
#define CSUM_MD4_BUSTED 2
#define CSUM_MD4_OLD 3
#define CSUM_MD4 4
#define CSUM_MD5 5

int xfersum_type = 0; /* used for the file transfer checksums */
int checksum_type = 0; /* used for the pre-transfer (--checksum) checksums */

/* Returns 1 if --whole-file must be enabled. */
int parse_checksum_choice(void)
{
char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL;
if (cp) {
xfersum_type = parse_csum_name(checksum_choice, cp - checksum_choice);
checksum_type = parse_csum_name(cp+1, -1);
} else
xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1);
return xfersum_type == CSUM_NONE;
}

int parse_csum_name(const char *name, int len)
{
if (len < 0 && name)
len = strlen(name);

if (!name || (len == 4 && strncasecmp(name, "auto", 4) == 0)) {
if (protocol_version >= 30)
return CSUM_MD5;
if (protocol_version >= 27)
return CSUM_MD4_OLD;
if (protocol_version >= 21)
return CSUM_MD4_BUSTED;
return CSUM_ARCHAIC;
}
if (len == 3 && strncasecmp(name, "md4", 3) == 0)
return CSUM_MD4;
if (len == 3 && strncasecmp(name, "md5", 3) == 0)
return CSUM_MD5;
if (len == 4 && strncasecmp(name, "none", 4) == 0)
return CSUM_NONE;

rprintf(FERROR, "unknown checksum name: %s\n", name);
exit_cleanup(RERR_UNSUPPORTED);
}

int csum_len_for_type(int cst)
{
switch (cst) {
case CSUM_NONE:
return 1;
case CSUM_ARCHAIC:
return 2;
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
return MD4_DIGEST_LEN;
case CSUM_MD5:
return MD5_DIGEST_LEN;
}
return 0;
}

int canonical_checksum(int csum_type)
{
return csum_type >= CSUM_MD4 ? 1 : 0;
}

/*
a simple 32 bit checksum that can be upadted from either end
Expand All @@ -47,12 +117,12 @@ uint32 get_checksum1(char *buf1, int32 len)
return (s1 & 0xffff) + (s2 << 16);
}


void get_checksum2(char *buf, int32 len, char *sum)
{
md_context m;

if (protocol_version >= 30) {
switch (xfersum_type) {
case CSUM_MD5: {
uchar seedbuf[4];
md5_begin(&m);
if (proper_seed_order) {
Expand All @@ -69,7 +139,11 @@ void get_checksum2(char *buf, int32 len, char *sum)
}
}
md5_result(&m, (uchar *)sum);
} else {
break;
}
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED: {
int32 i;
static char *buf1;
static int32 len1;
Expand Down Expand Up @@ -100,10 +174,12 @@ void get_checksum2(char *buf, int32 len, char *sum)
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes.
*/
if (len - i > 0 || protocol_version >= 27)
if (len - i > 0 || xfersum_type != CSUM_MD4_BUSTED)
mdfour_update(&m, (uchar *)(buf1+i), len-i);

mdfour_result(&m, (uchar *)sum);
break;
}
}
}

Expand All @@ -123,7 +199,8 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)

buf = map_file(fd, len, MAX_MAP_SIZE, CSUM_CHUNK);

if (protocol_version >= 30) {
switch (checksum_type) {
case CSUM_MD5:
md5_begin(&m);

for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
Expand All @@ -136,7 +213,10 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
md5_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);

md5_result(&m, (uchar *)sum);
} else {
break;
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
mdfour_begin(&m);

for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
Expand All @@ -149,10 +229,14 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes. */
remainder = (int32)(len - i);
if (remainder > 0 || protocol_version >= 27)
if (remainder > 0 || checksum_type != CSUM_MD4_BUSTED)
mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);

mdfour_result(&m, (uchar *)sum);
break;
default:
rprintf(FERROR, "invalid checksum-choice for the --checksum option (%d)\n", checksum_type);
exit_cleanup(RERR_UNSUPPORTED);
}

close(fd);
Expand All @@ -161,18 +245,33 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)

static int32 sumresidue;
static md_context md;
static int cursum_type;

void sum_init(int seed)
void sum_init(int csum_type, int seed)
{
char s[4];

if (protocol_version >= 30)
if (csum_type < 0)
csum_type = parse_csum_name(NULL, 0);
cursum_type = csum_type;

switch (csum_type) {
case CSUM_MD5:
md5_begin(&md);
else {
break;
case CSUM_MD4:
mdfour_begin(&md);
sumresidue = 0;
break;
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
mdfour_begin(&md);
sumresidue = 0;
SIVAL(s, 0, seed);
sum_update(s, 4);
break;
case CSUM_NONE:
break;
}
}

Expand All @@ -186,13 +285,17 @@ void sum_init(int seed)
**/
void sum_update(const char *p, int32 len)
{
if (protocol_version >= 30) {
switch (cursum_type) {
case CSUM_MD5:
md5_update(&md, (uchar *)p, len);
} else {
break;
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
if (len + sumresidue < CSUM_CHUNK) {
memcpy(md.buffer + sumresidue, p, len);
sumresidue += len;
return;
break;
}

if (sumresidue) {
Expand All @@ -212,20 +315,32 @@ void sum_update(const char *p, int32 len)
sumresidue = len;
if (sumresidue)
memcpy(md.buffer, p, sumresidue);
break;
case CSUM_NONE:
break;
}
}

int sum_end(char *sum)
{
if (protocol_version >= 30) {
switch (cursum_type) {
case CSUM_MD5:
md5_result(&md, (uchar *)sum);
return MD5_DIGEST_LEN;
} else {
if (sumresidue || protocol_version >= 27)
break;
case CSUM_MD4:
case CSUM_MD4_OLD:
mdfour_update(&md, (uchar *)md.buffer, sumresidue);
mdfour_result(&md, (uchar *)sum);
break;
case CSUM_MD4_BUSTED:
if (sumresidue)
mdfour_update(&md, (uchar *)md.buffer, sumresidue);

mdfour_result(&md, (uchar *)sum);

return MD4_DIGEST_LEN;
break;
case CSUM_NONE:
*sum = '\0';
break;
}

return csum_len_for_type(cursum_type);
}
2 changes: 2 additions & 0 deletions compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,6 @@ void setup_protocol(int f_out,int f_in)
} else {
checksum_seed = read_int(f_in);
}

init_flist();
}
6 changes: 3 additions & 3 deletions flist.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern int am_sender;
extern int am_generator;
extern int inc_recurse;
extern int always_checksum;
extern int checksum_type;
extern int module_id;
extern int ignore_errors;
extern int numeric_ids;
Expand Down Expand Up @@ -137,9 +138,8 @@ void init_flist(void)
rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n",
(int)FILE_STRUCT_LEN, (int)EXTRA_LEN);
}
checksum_len = protocol_version < 21 ? 2
: protocol_version < 30 ? MD4_DIGEST_LEN
: MD5_DIGEST_LEN;
parse_checksum_choice(); /* Sets checksum_type && xfersum_type */
checksum_len = csum_len_for_type(checksum_type);
}

static int show_filelist_p(void)
Expand Down
20 changes: 12 additions & 8 deletions log.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ extern int am_generator;
extern int local_server;
extern int quiet;
extern int module_id;
extern int checksum_len;
extern int allow_8bit_chars;
extern int protocol_version;
extern int always_checksum;
extern int preserve_times;
extern int msgs2stderr;
extern int xfersum_type;
extern int checksum_type;
extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
Expand All @@ -46,6 +47,7 @@ extern int64 total_data_written;
extern int64 total_data_read;
extern mode_t orig_umask;
extern char *auth_user;
extern char *checksum_choice;
extern char *stdout_format;
extern char *logfile_format;
extern char *logfile_name;
Expand Down Expand Up @@ -669,13 +671,15 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
n = buf2;
break;
case 'C':
if (protocol_version >= 30
&& (iflags & ITEM_TRANSFER
|| (always_checksum && S_ISREG(file->mode)))) {
const char *sum = iflags & ITEM_TRANSFER
? sender_file_sum : F_SUM(file);
n = sum_as_hex(sum);
} else {
n = NULL;
if (S_ISREG(file->mode)) {
if (always_checksum && canonical_checksum(checksum_type))
n = sum_as_hex(checksum_type, F_SUM(file));
else if (iflags & ITEM_TRANSFER && canonical_checksum(xfersum_type))
n = sum_as_hex(xfersum_type, sender_file_sum);
}
if (!n) {
int checksum_len = csum_len_for_type(always_checksum ? checksum_type : xfersum_type);
memset(buf2, ' ', checksum_len*2);
buf2[checksum_len*2] = '\0';
n = buf2;
Expand Down
2 changes: 0 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1595,8 +1595,6 @@ int main(int argc,char *argv[])
* that implement getcwd that way "pwd" can't be found after chroot. */
change_dir(NULL, CD_NORMAL);

init_flist();

if ((write_batch || read_batch) && !am_server) {
if (write_batch)
write_batch_shell_file(orig_argc, orig_argv, argc);
Expand Down
Loading

0 comments on commit a5a7d3a

Please sign in to comment.