Protocol 30 now uses MD5 checksums instead of MD4.
authorWayne Davison <wayned@samba.org>
Sun, 18 Mar 2007 06:00:53 +0000 (06:00 +0000)
committerWayne Davison <wayned@samba.org>
Sun, 18 Mar 2007 06:00:53 +0000 (06:00 +0000)
13 files changed:
Makefile.in
authenticate.c
checksum.c
flist.c
generator.c
io.c
lib/md5.c [new file with mode: 0644]
lib/mdfour.c
lib/mdfour.h [deleted file]
lib/mdigest.h [new file with mode: 0644]
match.c
receiver.c
rsync.h

index c1c5510..f0d43e0 100644 (file)
@@ -27,7 +27,7 @@ VERSION=@VERSION@
 .SUFFIXES: .c .o
 
 HEADERS=byteorder.h config.h errcode.h proto.h rsync.h smb_acls.h lib/pool_alloc.h
-LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
+LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
        lib/permstring.o lib/pool_alloc.o lib/sysacls.o @LIBOBJS@
 ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
        zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
index 6fc71de..b699724 100644 (file)
@@ -57,8 +57,9 @@ void base64_encode(const char *buf, int len, char *out, int pad)
 static void gen_challenge(const char *addr, char *challenge)
 {
        char input[32];
-       char md4_out[MD4_SUM_LENGTH];
+       char digest[MAX_DIGEST_LEN];
        struct timeval tv;
+       int len;
 
        memset(input, 0, sizeof input);
 
@@ -70,9 +71,9 @@ static void gen_challenge(const char *addr, char *challenge)
 
        sum_init(0);
        sum_update(input, sizeof input);
-       sum_end(md4_out);
+       len = sum_end(digest);
 
-       base64_encode(md4_out, MD4_SUM_LENGTH, challenge, 0);
+       base64_encode(digest, len, challenge, 0);
 }
 
 
@@ -205,14 +206,15 @@ static const char *getpassf(const char *filename)
  * and the challenge string and return it base64-encoded. */
 static void generate_hash(const char *in, const char *challenge, char *out)
 {
-       char buf[MD4_SUM_LENGTH];
+       char buf[MAX_DIGEST_LEN];
+       int len;
 
        sum_init(0);
        sum_update(in, strlen(in));
        sum_update(challenge, strlen(challenge));
-       sum_end(buf);
+       len = sum_end(buf);
 
-       base64_encode(buf, MD4_SUM_LENGTH, out, 0);
+       base64_encode(buf, len, out, 0);
 }
 
 /* Possibly negotiate authentication with the client.  Use "leader" to
@@ -225,10 +227,10 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
                  const char *addr, const char *leader)
 {
        char *users = lp_auth_users(module);
-       char challenge[MD4_SUM_LENGTH*2];
+       char challenge[MAX_DIGEST_LEN*2];
        char line[BIGPATHBUFLEN];
        char secret[512];
-       char pass2[MD4_SUM_LENGTH*2];
+       char pass2[MAX_DIGEST_LEN*2];
        char *tok, *pass;
 
        /* if no auth list then allow anyone in! */
@@ -289,7 +291,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
 void auth_client(int fd, const char *user, const char *challenge)
 {
        const char *pass;
-       char pass2[MD4_SUM_LENGTH*2];
+       char pass2[MAX_DIGEST_LEN*2];
 
        if (!user || !*user)
                user = "nobody";
index e4b77bf..fe8a64c 100644 (file)
 
 #include "rsync.h"
 
-int csum_length = SHORT_SUM_LENGTH; /* initial value */
-
-#define CSUM_CHUNK 64
-
 extern int checksum_seed;
 extern int protocol_version;
 
+int csum_length = SHORT_SUM_LENGTH; /* initial value */
+
 /*
   a simple 32 bit checksum that can be upadted from either end
   (inspired by Mark Adler's Adler-32 checksum)
@@ -53,54 +51,64 @@ uint32 get_checksum1(char *buf1, int32 len)
 
 void get_checksum2(char *buf, int32 len, char *sum)
 {
-       int32 i;
-       static char *buf1;
-       static int32 len1;
-       struct mdfour m;
-
-       if (len > len1) {
-               if (buf1)
-                       free(buf1);
-               buf1 = new_array(char, len+4);
-               len1 = len;
-               if (!buf1)
-                       out_of_memory("get_checksum2");
-       }
-
-       mdfour_begin(&m);
-
-       memcpy(buf1,buf,len);
-       if (checksum_seed) {
-               SIVAL(buf1,len,checksum_seed);
-               len += 4;
-       }
-
-       for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
-               mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
-       }
-       /*
-        * Prior to version 27 an incorrect MD4 checksum was computed
-        * by failing to call mdfour_tail() for block sizes that
-        * 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) {
-               mdfour_update(&m, (uchar *)(buf1+i), (len-i));
+       md_context m;
+
+       if (protocol_version >= 30) {
+               uchar seedbuf[4];
+               md5_begin(&m);
+               if (checksum_seed) {
+                       SIVAL(seedbuf, 0, checksum_seed);
+                       md5_update(&m, seedbuf, 4);
+               }
+               md5_update(&m, (uchar *)buf, len);
+               md5_result(&m, (uchar *)sum);
+       } else {
+               int32 i;
+               static char *buf1;
+               static int32 len1;
+
+               mdfour_begin(&m);
+
+               if (len > len1) {
+                       if (buf1)
+                               free(buf1);
+                       buf1 = new_array(char, len+4);
+                       len1 = len;
+                       if (!buf1)
+                               out_of_memory("get_checksum2");
+               }
+
+               memcpy(buf1, buf, len);
+               if (checksum_seed) {
+                       SIVAL(buf1,len,checksum_seed);
+                       len += 4;
+               }
+
+               for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK)
+                       mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
+
+               /*
+                * Prior to version 27 an incorrect MD4 checksum was computed
+                * by failing to call mdfour_tail() for block sizes that
+                * 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)
+                       mdfour_update(&m, (uchar *)(buf1+i), len-i);
+
+               mdfour_result(&m, (uchar *)sum);
        }
-
-       mdfour_result(&m, (uchar *)sum);
 }
 
-
-void file_checksum(char *fname,char *sum,OFF_T size)
+void file_checksum(char *fname, char *sum, OFF_T size)
 {
        struct map_struct *buf;
        OFF_T i, len = size;
-       struct mdfour m;
+       md_context m;
        int32 remainder;
        int fd;
 
-       memset(sum,0,MD4_SUM_LENGTH);
+       memset(sum, 0, MAX_DIGEST_LEN);
 
        fd = do_open(fname, O_RDONLY, 0);
        if (fd == -1)
@@ -108,37 +116,55 @@ void file_checksum(char *fname,char *sum,OFF_T size)
 
        buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
 
-       mdfour_begin(&m);
+       if (protocol_version >= 30) {
+               md5_begin(&m);
 
-       for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
-               mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
-                             CSUM_CHUNK);
-       }
+               for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
+                       md5_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
+                                  CSUM_CHUNK);
+               }
 
-       /* Prior to version 27 an incorrect MD4 checksum was computed
-        * by failing to call mdfour_tail() for block sizes that
-        * 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)
-               mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
+               remainder = (int32)(len - i);
+               if (remainder > 0)
+                       md5_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
 
-       mdfour_result(&m, (uchar *)sum);
+               md5_result(&m, (uchar *)sum);
+       } else {
+               mdfour_begin(&m);
+
+               for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
+                       mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
+                                     CSUM_CHUNK);
+               }
+
+               /* Prior to version 27 an incorrect MD4 checksum was computed
+                * by failing to call mdfour_tail() for block sizes that
+                * 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)
+                       mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
+
+               mdfour_result(&m, (uchar *)sum);
+       }
 
        close(fd);
        unmap_file(buf);
 }
 
-
 static int32 sumresidue;
-static char sumrbuf[CSUM_CHUNK];
-static struct mdfour md;
+static md_context md;
 
 void sum_init(int seed)
 {
        char s[4];
-       mdfour_begin(&md);
-       sumresidue = 0;
+
+       if (protocol_version >= 30)
+               md5_begin(&md);
+       else {
+               mdfour_begin(&md);
+               sumresidue = 0;
+       }
        SIVAL(s, 0, seed);
        sum_update(s, 4);
 }
@@ -153,16 +179,21 @@ void sum_init(int seed)
  **/
 void sum_update(const char *p, int32 len)
 {
+       if (protocol_version >= 30) {
+               md5_update(&md, (uchar *)p, len);
+               return;
+       }
+
        if (len + sumresidue < CSUM_CHUNK) {
-               memcpy(sumrbuf + sumresidue, p, len);
+               memcpy(md.buffer + sumresidue, p, len);
                sumresidue += len;
                return;
        }
 
        if (sumresidue) {
                int32 i = CSUM_CHUNK - sumresidue;
-               memcpy(sumrbuf + sumresidue, p, i);
-               mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
+               memcpy(md.buffer + sumresidue, p, i);
+               mdfour_update(&md, (uchar *)md.buffer, CSUM_CHUNK);
                len -= i;
                p += i;
        }
@@ -175,13 +206,20 @@ void sum_update(const char *p, int32 len)
 
        sumresidue = len;
        if (sumresidue)
-               memcpy(sumrbuf, p, sumresidue);
+               memcpy(md.buffer, p, sumresidue);
 }
 
-void sum_end(char *sum)
+int sum_end(char *sum)
 {
+       if (protocol_version >= 30) {
+               md5_result(&md, (uchar *)sum);
+               return MD5_DIGEST_LEN;
+       }
+
        if (sumresidue || protocol_version >= 27)
-               mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
+               mdfour_update(&md, (uchar *)md.buffer, sumresidue);
 
        mdfour_result(&md, (uchar *)sum);
+
+       return MD4_DIGEST_LEN;
 }
diff --git a/flist.c b/flist.c
index a2bbc91..abbc6da 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -85,9 +85,9 @@ static dev_t tmp_rdev;
 #ifdef SUPPORT_HARD_LINKS
 static int64 tmp_dev, tmp_ino;
 #endif
-static char tmp_sum[MD4_SUM_LENGTH];
+static char tmp_sum[MAX_DIGEST_LEN];
 
-static char empty_sum[MD4_SUM_LENGTH];
+static char empty_sum[MAX_DIGEST_LEN];
 static int flist_count_offset; /* for --delete --progress */
 
 static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
@@ -99,7 +99,9 @@ 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 : MD4_SUM_LENGTH;
+       checksum_len = protocol_version < 21 ? 2
+                    : protocol_version < 30 ? MD4_DIGEST_LEN
+                    : MD5_DIGEST_LEN;
 }
 
 static int show_filelist_p(void)
index d1864b7..02d514c 100644 (file)
@@ -598,7 +598,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
        /* if always checksum is set then we use the checksum instead
           of the file time to determine whether to sync */
        if (always_checksum > 0 && S_ISREG(st->st_mode)) {
-               char sum[MD4_SUM_LENGTH];
+               char sum[MAX_DIGEST_LEN];
                file_checksum(fn, sum, st->st_size);
                return memcmp(sum, F_SUM(file), checksum_len) == 0;
        }
diff --git a/io.c b/io.c
index 6abaab2..eecab20 100644 (file)
--- a/io.c
+++ b/io.c
@@ -1159,7 +1159,7 @@ void read_sum_head(int f, struct sum_struct *sum)
                exit_cleanup(RERR_PROTOCOL);
        }
        sum->s2length = protocol_version < 27 ? csum_length : (int)read_int(f);
-       if (sum->s2length < 0 || sum->s2length > MD4_SUM_LENGTH) {
+       if (sum->s2length < 0 || sum->s2length > MAX_DIGEST_LEN) {
                rprintf(FERROR, "Invalid checksum length %d [%s]\n",
                        sum->s2length, who_am_i());
                exit_cleanup(RERR_PROTOCOL);
diff --git a/lib/md5.c b/lib/md5.c
new file mode 100644 (file)
index 0000000..c65054a
--- /dev/null
+++ b/lib/md5.c
@@ -0,0 +1,305 @@
+/*
+ * RFC 1321 compliant MD5 implementation
+ *
+ * Copyright (C) 2001-2003 Christophe Devine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "rsync.h"
+
+void md5_begin(md_context *ctx)
+{
+       ctx->A = 0x67452301;
+       ctx->B = 0xEFCDAB89;
+       ctx->C = 0x98BADCFE;
+       ctx->D = 0x10325476;
+
+       ctx->totalN = ctx->totalN2 = 0;
+}
+
+static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
+{
+       uint32 X[16], A, B, C, D;
+
+       A = ctx->A;
+       B = ctx->B;
+       C = ctx->C;
+       D = ctx->D;
+
+       X[0] = IVAL(data, 0);
+       X[1] = IVAL(data, 4);
+       X[2] = IVAL(data, 8);
+       X[3] = IVAL(data, 12);
+       X[4] = IVAL(data, 16);
+       X[5] = IVAL(data, 20);
+       X[6] = IVAL(data, 24);
+       X[7] = IVAL(data, 28);
+       X[8] = IVAL(data, 32);
+       X[9] = IVAL(data, 36);
+       X[10] = IVAL(data, 40);
+       X[11] = IVAL(data, 44);
+       X[12] = IVAL(data, 48);
+       X[13] = IVAL(data, 52);
+       X[14] = IVAL(data, 56);
+       X[15] = IVAL(data, 60);
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t) a += F(b,c,d) + X[k] + t, a = S(a,s) + b
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+       P(A, B, C, D,  0,  7, 0xD76AA478);
+       P(D, A, B, C,  1, 12, 0xE8C7B756);
+       P(C, D, A, B,  2, 17, 0x242070DB);
+       P(B, C, D, A,  3, 22, 0xC1BDCEEE);
+       P(A, B, C, D,  4,  7, 0xF57C0FAF);
+       P(D, A, B, C,  5, 12, 0x4787C62A);
+       P(C, D, A, B,  6, 17, 0xA8304613);
+       P(B, C, D, A,  7, 22, 0xFD469501);
+       P(A, B, C, D,  8,  7, 0x698098D8);
+       P(D, A, B, C,  9, 12, 0x8B44F7AF);
+       P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+       P(B, C, D, A, 11, 22, 0x895CD7BE);
+       P(A, B, C, D, 12,  7, 0x6B901122);
+       P(D, A, B, C, 13, 12, 0xFD987193);
+       P(C, D, A, B, 14, 17, 0xA679438E);
+       P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+       P(A, B, C, D,  1,  5, 0xF61E2562);
+       P(D, A, B, C,  6,  9, 0xC040B340);
+       P(C, D, A, B, 11, 14, 0x265E5A51);
+       P(B, C, D, A,  0, 20, 0xE9B6C7AA);
+       P(A, B, C, D,  5,  5, 0xD62F105D);
+       P(D, A, B, C, 10,  9, 0x02441453);
+       P(C, D, A, B, 15, 14, 0xD8A1E681);
+       P(B, C, D, A,  4, 20, 0xE7D3FBC8);
+       P(A, B, C, D,  9,  5, 0x21E1CDE6);
+       P(D, A, B, C, 14,  9, 0xC33707D6);
+       P(C, D, A, B,  3, 14, 0xF4D50D87);
+       P(B, C, D, A,  8, 20, 0x455A14ED);
+       P(A, B, C, D, 13,  5, 0xA9E3E905);
+       P(D, A, B, C,  2,  9, 0xFCEFA3F8);
+       P(C, D, A, B,  7, 14, 0x676F02D9);
+       P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+#define F(x,y,z) (x ^ y ^ z)
+
+       P(A, B, C, D,  5,  4, 0xFFFA3942);
+       P(D, A, B, C,  8, 11, 0x8771F681);
+       P(C, D, A, B, 11, 16, 0x6D9D6122);
+       P(B, C, D, A, 14, 23, 0xFDE5380C);
+       P(A, B, C, D,  1,  4, 0xA4BEEA44);
+       P(D, A, B, C,  4, 11, 0x4BDECFA9);
+       P(C, D, A, B,  7, 16, 0xF6BB4B60);
+       P(B, C, D, A, 10, 23, 0xBEBFBC70);
+       P(A, B, C, D, 13,  4, 0x289B7EC6);
+       P(D, A, B, C,  0, 11, 0xEAA127FA);
+       P(C, D, A, B,  3, 16, 0xD4EF3085);
+       P(B, C, D, A,  6, 23, 0x04881D05);
+       P(A, B, C, D,  9,  4, 0xD9D4D039);
+       P(D, A, B, C, 12, 11, 0xE6DB99E5);
+       P(C, D, A, B, 15, 16, 0x1FA27CF8);
+       P(B, C, D, A,  2, 23, 0xC4AC5665);
+
+#undef F
+#define F(x,y,z) (y ^ (x | ~z))
+
+       P(A, B, C, D,  0,  6, 0xF4292244);
+       P(D, A, B, C,  7, 10, 0x432AFF97);
+       P(C, D, A, B, 14, 15, 0xAB9423A7);
+       P(B, C, D, A,  5, 21, 0xFC93A039);
+       P(A, B, C, D, 12,  6, 0x655B59C3);
+       P(D, A, B, C,  3, 10, 0x8F0CCC92);
+       P(C, D, A, B, 10, 15, 0xFFEFF47D);
+       P(B, C, D, A,  1, 21, 0x85845DD1);
+       P(A, B, C, D,  8,  6, 0x6FA87E4F);
+       P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+       P(C, D, A, B,  6, 15, 0xA3014314);
+       P(B, C, D, A, 13, 21, 0x4E0811A1);
+       P(A, B, C, D,  4,  6, 0xF7537E82);
+       P(D, A, B, C, 11, 10, 0xBD3AF235);
+       P(C, D, A, B,  2, 15, 0x2AD7D2BB);
+       P(B, C, D, A,  9, 21, 0xEB86D391);
+
+#undef F
+
+       ctx->A += A;
+       ctx->B += B;
+       ctx->C += C;
+       ctx->D += D;
+}
+
+void md5_update(md_context *ctx, const uchar *input, uint32 length)
+{
+       uint32 left, fill;
+
+       if (!length)
+               return;
+
+       left = ctx->totalN & 0x3F;
+       fill = CSUM_CHUNK - left;
+
+       ctx->totalN += length;
+       ctx->totalN &= 0xFFFFFFFF;
+
+       if (ctx->totalN < length)
+               ctx->totalN2++;
+
+       if (left && length >= fill) {
+               memcpy(ctx->buffer + left, input, fill);
+               md5_process(ctx, ctx->buffer);
+               length -= fill;
+               input  += fill;
+               left = 0;
+       }
+
+       while (length >= CSUM_CHUNK) {
+               md5_process(ctx, input);
+               length -= CSUM_CHUNK;
+               input  += CSUM_CHUNK;
+       }
+
+       if (length)
+               memcpy(ctx->buffer + left, input, length);
+}
+
+static uchar md5_padding[CSUM_CHUNK] = { 0x80 };
+
+void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN])
+{
+       uint32 last, padn;
+       uint32 high, low;
+       uchar msglen[8];
+
+       high = (ctx->totalN >> 29)
+            | (ctx->totalN2 <<  3);
+       low  = (ctx->totalN <<  3);
+
+       SIVAL(msglen, 0, low);
+       SIVAL(msglen, 4, high);
+
+       last = ctx->totalN & 0x3F;
+       padn = last < 56 ? 56 - last : 120 - last;
+
+       md5_update(ctx, md5_padding, padn);
+       md5_update(ctx, msglen, 8);
+
+       SIVAL(digest, 0, ctx->A);
+       SIVAL(digest, 4, ctx->B);
+       SIVAL(digest, 8, ctx->C);
+       SIVAL(digest, 12, ctx->D);
+}
+
+void get_md5(uchar *out, const uchar *input, int n)
+{
+       md_context ctx;
+       md5_begin(&ctx);
+       md5_update(&ctx, input, n);
+       md5_result(&ctx, out);
+}
+
+#ifdef TEST_MD5
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * those are the standard RFC 1321 test vectors
+ */
+
+static struct {
+    char *str, *md5;
+} tests[] = {
+ { "",
+   "d41d8cd98f00b204e9800998ecf8427e" },
+ { "a",
+   "0cc175b9c0f1b6a831c399e269772661" },
+ { "abc",
+   "900150983cd24fb0d6963f7d28e17f72" },
+ { "message digest",
+   "f96b697d7cb7938d525a2f31aaf161d0" },
+ { "abcdefghijklmnopqrstuvwxyz",
+   "c3fcd3d76192e4007dfb496cca67e13b" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+   "d174ab98d277d9f5a5611c2c9f419d9f" },
+ { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+   "57edf4a22be3c955ac49da2e2107b67a" },
+ { NULL, NULL }
+};
+
+int main(int argc, char *argv[])
+{
+       FILE *f;
+       int i, j;
+       char output[33];
+       md_context ctx;
+       uchar buf[1000];
+       uchar md5sum[MD5_DIGEST_LEN];
+
+       if (argc < 2) {
+               printf("\nMD5 Validation Tests:\n\n");
+
+               for (i = 0; tests[i].str; i++) {
+                       char *str = tests[i].str;
+                       char *chk = tests[i].md5;
+
+                       printf("  Test %d ", i + 1);
+
+                       get_md5(md5sum, str, strlen(str));
+
+                       for (j = 0; j < MD5_DIGEST_LEN; j++)
+                               sprintf(output + j * 2, "%02x", md5sum[j]);
+
+                       if (memcmp(output, chk, 32)) {
+                               printf("failed!\n");
+                               return 1;
+                       }
+
+                       printf("passed.\n");
+               }
+
+               printf("\n");
+               return 0;
+       }
+
+       while (--argc) {
+               if (!(f = fopen(*++argv, "rb"))) {
+                       perror("fopen");
+                       return 1;
+               }
+
+               md5_begin(&ctx);
+
+               while ((i = fread(buf, 1, sizeof buf, f)) > 0)
+                       md5_update(&ctx, buf, i);
+
+               md5_result(&ctx, md5sum);
+
+               for (j = 0; j < MD5_DIGEST_LEN; j++)
+                       printf("%02x", md5sum[j]);
+
+               printf("  %s\n", *argv);
+       }
+
+       return 0;
+}
+
+#endif
index 7868f33..515f425 100644 (file)
@@ -4,7 +4,7 @@
  * An implementation of MD4 designed for use in the SMB authentication protocol.
  *
  * Copyright (C) 1997-1998 Andrew Tridgell
- * Copyright (C) 2005 Wayne Davison
+ * Copyright (C) 2005-2007 Wayne Davison
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
  *
  * It assumes that a int is at least 32 bits long. */
 
-static struct mdfour *m;
+static md_context *m;
 
 #define MASK32 (0xffffffff)
 
@@ -49,32 +49,31 @@ static void mdfour64(uint32 *M)
        A = m->A; B = m->B; C = m->C; D = m->D; 
        AA = A; BB = B; CC = C; DD = D;
 
-        ROUND1(A,B,C,D,  0,  3);  ROUND1(D,A,B,C,  1,  7);  
+       ROUND1(A,B,C,D,  0,  3);  ROUND1(D,A,B,C,  1,  7);  
        ROUND1(C,D,A,B,  2, 11);  ROUND1(B,C,D,A,  3, 19);
-        ROUND1(A,B,C,D,  4,  3);  ROUND1(D,A,B,C,  5,  7);  
+       ROUND1(A,B,C,D,  4,  3);  ROUND1(D,A,B,C,  5,  7);  
        ROUND1(C,D,A,B,  6, 11);  ROUND1(B,C,D,A,  7, 19);
-        ROUND1(A,B,C,D,  8,  3);  ROUND1(D,A,B,C,  9,  7);  
+       ROUND1(A,B,C,D,  8,  3);  ROUND1(D,A,B,C,  9,  7);  
        ROUND1(C,D,A,B, 10, 11);  ROUND1(B,C,D,A, 11, 19);
-        ROUND1(A,B,C,D, 12,  3);  ROUND1(D,A,B,C, 13,  7);  
+       ROUND1(A,B,C,D, 12,  3);  ROUND1(D,A,B,C, 13,  7);  
        ROUND1(C,D,A,B, 14, 11);  ROUND1(B,C,D,A, 15, 19);      
 
-
-        ROUND2(A,B,C,D,  0,  3);  ROUND2(D,A,B,C,  4,  5);  
+       ROUND2(A,B,C,D,  0,  3);  ROUND2(D,A,B,C,  4,  5);  
        ROUND2(C,D,A,B,  8,  9);  ROUND2(B,C,D,A, 12, 13);
-        ROUND2(A,B,C,D,  1,  3);  ROUND2(D,A,B,C,  5,  5);  
+       ROUND2(A,B,C,D,  1,  3);  ROUND2(D,A,B,C,  5,  5);  
        ROUND2(C,D,A,B,  9,  9);  ROUND2(B,C,D,A, 13, 13);
-        ROUND2(A,B,C,D,  2,  3);  ROUND2(D,A,B,C,  6,  5);  
+       ROUND2(A,B,C,D,  2,  3);  ROUND2(D,A,B,C,  6,  5);  
        ROUND2(C,D,A,B, 10,  9);  ROUND2(B,C,D,A, 14, 13);
-        ROUND2(A,B,C,D,  3,  3);  ROUND2(D,A,B,C,  7,  5);  
+       ROUND2(A,B,C,D,  3,  3);  ROUND2(D,A,B,C,  7,  5);  
        ROUND2(C,D,A,B, 11,  9);  ROUND2(B,C,D,A, 15, 13);
 
        ROUND3(A,B,C,D,  0,  3);  ROUND3(D,A,B,C,  8,  9);  
        ROUND3(C,D,A,B,  4, 11);  ROUND3(B,C,D,A, 12, 15);
-        ROUND3(A,B,C,D,  2,  3);  ROUND3(D,A,B,C, 10,  9);  
+       ROUND3(A,B,C,D,  2,  3);  ROUND3(D,A,B,C, 10,  9);  
        ROUND3(C,D,A,B,  6, 11);  ROUND3(B,C,D,A, 14, 15);
-        ROUND3(A,B,C,D,  1,  3);  ROUND3(D,A,B,C,  9,  9);  
+       ROUND3(A,B,C,D,  1,  3);  ROUND3(D,A,B,C,  9,  9);  
        ROUND3(C,D,A,B,  5, 11);  ROUND3(B,C,D,A, 13, 15);
-        ROUND3(A,B,C,D,  3,  3);  ROUND3(D,A,B,C, 11,  9);  
+       ROUND3(A,B,C,D,  3,  3);  ROUND3(D,A,B,C, 11,  9);  
        ROUND3(C,D,A,B,  7, 11);  ROUND3(B,C,D,A, 15, 15);
 
        A += AA; B += BB; 
@@ -86,16 +85,17 @@ static void mdfour64(uint32 *M)
        m->A = A; m->B = B; m->C = C; m->D = D;
 }
 
-static void copy64(uint32 *M, unsigned char *in)
+static void copy64(uint32 *M, const uchar *in)
 {
        int i;
 
-       for (i=0;i<16;i++)
-               M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
-                       (in[i*4+1]<<8) | (in[i*4+0]<<0);
+       for (i = 0; i < MD4_DIGEST_LEN; i++) {
+               M[i] = (in[i*4+3] << 24) | (in[i*4+2] << 16)
+                    | (in[i*4+1] << 8)  | (in[i*4+0] << 0);
+       }
 }
 
-static void copy4(unsigned char *out,uint32 x)
+static void copy4(uchar *out,uint32 x)
 {
        out[0] = x&0xFF;
        out[1] = (x>>8)&0xFF;
@@ -103,7 +103,7 @@ static void copy4(unsigned char *out,uint32 x)
        out[3] = (x>>24)&0xFF;
 }
 
-void mdfour_begin(struct mdfour *md)
+void mdfour_begin(md_context *md)
 {
        md->A = 0x67452301;
        md->B = 0xefcdab89;
@@ -113,27 +113,26 @@ void mdfour_begin(struct mdfour *md)
        md->totalN2 = 0;
 }
 
-
-static void mdfour_tail(unsigned char *in, uint32 n)
+static void mdfour_tail(const uchar *in, uint32 length)
 {
-       unsigned char buf[128];
+       uchar buf[128];
        uint32 M[16];
        extern int protocol_version;
 
        /*
         * Count total number of bits, modulo 2^64
         */
-       m->totalN += n << 3;
-       if (m->totalN < (n << 3)) {
+       m->totalN += length << 3;
+       if (m->totalN < (length << 3))
                m->totalN2++;
-       }
-       m->totalN2 += n >> 29;
+       m->totalN2 += length >> 29;
 
        memset(buf, 0, 128);
-       if (n) memcpy(buf, in, n);
-       buf[n] = 0x80;
+       if (length)
+               memcpy(buf, in, length);
+       buf[length] = 0x80;
 
-       if (n <= 55) {
+       if (length <= 55) {
                copy4(buf+56, m->totalN);
                /*
                 * Prior to protocol version 27 only the number of bits
@@ -141,9 +140,8 @@ static void mdfour_tail(unsigned char *in, uint32 n)
                 * of bits modulo 2^64, which was fixed starting with
                 * protocol version 27.
                 */
-               if (protocol_version >= 27) {
+               if (protocol_version >= 27)
                        copy4(buf+60, m->totalN2);
-               }
                copy64(M, buf);
                mdfour64(M);
        } else {
@@ -154,9 +152,8 @@ static void mdfour_tail(unsigned char *in, uint32 n)
                 * of bits modulo 2^64, which was fixed starting with
                 * protocol version 27.
                 */
-               if (protocol_version >= 27) {
+               if (protocol_version >= 27)
                        copy4(buf+124, m->totalN2); 
-               }
                copy64(M, buf);
                mdfour64(M);
                copy64(M, buf+64);
@@ -164,46 +161,45 @@ static void mdfour_tail(unsigned char *in, uint32 n)
        }
 }
 
-void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n)
+void mdfour_update(md_context *md, const uchar *in, uint32 length)
 {
        uint32 M[16];
 
        m = md;
 
-       if (n == 0) mdfour_tail(in, n);
+       if (length == 0)
+               mdfour_tail(in, length);
 
-       while (n >= 64) {
+       while (length >= 64) {
                copy64(M, in);
                mdfour64(M);
                in += 64;
-               n -= 64;
+               length -= 64;
                m->totalN += 64 << 3;
-               if (m->totalN < 64 << 3) {
+               if (m->totalN < 64 << 3)
                        m->totalN2++;
-               }
        }
 
-       if (n) mdfour_tail(in, n);
+       if (length)
+               mdfour_tail(in, length);
 }
 
-
-void mdfour_result(struct mdfour *md, unsigned char *out)
+void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN])
 {
        m = md;
 
-       copy4(out, m->A);
-       copy4(out+4, m->B);
-       copy4(out+8, m->C);
-       copy4(out+12, m->D);
+       copy4(digest, m->A);
+       copy4(digest+4, m->B);
+       copy4(digest+8, m->C);
+       copy4(digest+12, m->D);
 }
 
-
-void mdfour(unsigned char *out, unsigned char *in, int n)
+void mdfour(uchar digest[MD4_DIGEST_LEN], uchar *in, int length)
 {
-       struct mdfour md;
+       md_context md;
        mdfour_begin(&md);
-       mdfour_update(&md, in, n);
-       mdfour_result(&md, out);
+       mdfour_update(&md, in, length);
+       mdfour_result(&md, digest);
 }
 
 #ifdef TEST_MDFOUR
@@ -212,8 +208,8 @@ int protocol_version = 28;
 static void file_checksum1(char *fname)
 {
        int fd, i, was_multiple_of_64 = 1;
-       struct mdfour md;
-       unsigned char buf[64*1024], sum[16];
+       md_context md;
+       uchar buf[64*1024], sum[MD4_DIGEST_LEN];
        
        fd = open(fname,O_RDONLY);
        if (fd == -1) {
@@ -224,7 +220,7 @@ static void file_checksum1(char *fname)
        mdfour_begin(&md);
 
        while (1) {
-               int n = read(fd, buf, sizeof(buf));
+               int n = read(fd, buf, sizeof buf);
                if (n <= 0)
                        break;
                was_multiple_of_64 = !(n % 64);
@@ -237,54 +233,15 @@ static void file_checksum1(char *fname)
 
        mdfour_result(&md, sum);
 
-       for (i=0;i<16;i++)
-               printf("%02X", sum[i]);
-       printf("\n");
-}
-
-#if 0
-#include "../md4.h"
-
-static void file_checksum2(char *fname)
-{
-       int fd, i;
-       MDstruct md;
-       unsigned char buf[64], sum[16];
-
-       fd = open(fname,O_RDONLY);
-       if (fd == -1) {
-               perror("fname");
-               exit(1);
-       }
-       
-       MDbegin(&md);
-
-       while (1) {
-               int n = read(fd, buf, sizeof(buf));
-               if (n <= 0) break;
-               MDupdate(&md, buf, n*8);
-       }
-
-       if (!md.done) {
-               MDupdate(&md, buf, 0);
-       }
-
-       close(fd);
-
-       memcpy(sum, md.buffer, 16);
-
-       for (i=0;i<16;i++)
+       for (i = 0; i < MD4_DIGEST_LEN; i++)
                printf("%02X", sum[i]);
        printf("\n");
 }
-#endif
 
  int main(int argc, char *argv[])
 {
-       file_checksum1(argv[1]);
-#if 0
-       file_checksum2(argv[1]);
-#endif
+       while (--argc)
+               file_checksum1(*++argv);
        return 0;
 }
 #endif
diff --git a/lib/mdfour.h b/lib/mdfour.h
deleted file mode 100644 (file)
index 138456a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 
- * Unix SMB/Netbios implementation.
- * Version 1.9.
- * An implementation of MD4 designed for use in the SMB authentication protocol.
- *
- * Copyright (C) 1997-1998 Andrew Tridgell
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-struct mdfour {
-       uint32 A, B, C, D;
-       uint32 totalN;          /* bit count, lower 32 bits */
-       uint32 totalN2;         /* bit count, upper 32 bits */
-};
-
-void mdfour_begin(struct mdfour *md);
-void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n);
-void mdfour_result(struct mdfour *md, unsigned char *out);
-void mdfour(unsigned char *out, unsigned char *in, int n);
diff --git a/lib/mdigest.h b/lib/mdigest.h
new file mode 100644 (file)
index 0000000..e0e33ed
--- /dev/null
@@ -0,0 +1,26 @@
+/* The include file for both the MD4 and MD5 routines. */
+
+#define MD4_DIGEST_LEN 16
+#define MD5_DIGEST_LEN 16
+#define MAX_DIGEST_LEN MD5_DIGEST_LEN
+
+#define CSUM_CHUNK 64
+
+typedef struct {
+       uint32 A, B, C, D;
+       uint32 totalN;          /* bit count, lower 32 bits */
+       uint32 totalN2;         /* bit count, upper 32 bits */
+       uchar buffer[CSUM_CHUNK];
+} md_context;
+
+void mdfour_begin(md_context *md);
+void mdfour_update(md_context *md, const uchar *in, uint32 length);
+void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN]);
+
+void get_mdfour(uchar digest[MD4_DIGEST_LEN], const uchar *in, int length);
+
+void md5_begin(md_context *ctx);
+void md5_update(md_context *ctx, const uchar *input, uint32 length);
+void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN]);
+
+void get_md5(uchar digest[MD5_DIGEST_LEN], const uchar *input, int n);
diff --git a/match.c b/match.c
index b856bb4..9719319 100644 (file)
--- a/match.c
+++ b/match.c
@@ -303,7 +303,8 @@ static void hash_search(int f,struct sum_struct *s,
  **/
 void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
 {
-       char file_sum[MD4_SUM_LENGTH];
+       char file_sum[MAX_DIGEST_LEN];
+       int sum_len;
 
        last_match = 0;
        false_alarms = 0;
@@ -323,10 +324,10 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
                        last_match = j;
                }
                if (last_match < s->flength) {
-                       int32 len = (int32)(s->flength - last_match);
+                       int32 n = (int32)(s->flength - last_match);
                        if (buf && do_progress)
                                show_progress(last_match, buf->file_size);
-                       sum_update(map_ptr(buf, last_match, len), len);
+                       sum_update(map_ptr(buf, last_match, n), n);
                        last_match = s->flength;
                }
                s->count = 0;
@@ -338,7 +339,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
                if (verbose > 2)
                        rprintf(FINFO,"built hash table\n");
 
-               hash_search(f,s,buf,len);
+               hash_search(f, s, buf, len);
 
                if (verbose > 2)
                        rprintf(FINFO,"done hash search\n");
@@ -350,14 +351,14 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
                matched(f, s, buf, len, -1);
        }
 
-       sum_end(file_sum);
+       sum_len = sum_end(file_sum);
        /* If we had a read error, send a bad checksum. */
        if (buf && buf->status != 0)
                file_sum[0]++;
 
        if (verbose > 2)
                rprintf(FINFO,"sending file_sum\n");
-       write_buf(f,file_sum,MD4_SUM_LENGTH);
+       write_buf(f, file_sum, sum_len);
 
        if (verbose > 2)
                rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
index 3b3c51e..f7db385 100644 (file)
@@ -125,11 +125,11 @@ int get_tmpname(char *fnametmp, char *fname)
 static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                        char *fname, int fd, OFF_T total_size)
 {
-       static char file_sum1[MD4_SUM_LENGTH];
-       static char file_sum2[MD4_SUM_LENGTH];
+       static char file_sum1[MAX_DIGEST_LEN];
+       static char file_sum2[MAX_DIGEST_LEN];
        struct map_struct *mapbuf;
        struct sum_struct sum;
-       int32 len;
+       int32 len, sum_len;
        OFF_T offset = 0;
        OFF_T offset2;
        char *data;
@@ -257,15 +257,15 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                exit_cleanup(RERR_FILEIO);
        }
 
-       sum_end(file_sum1);
+       sum_len = sum_end(file_sum1);
 
        if (mapbuf)
                unmap_file(mapbuf);
 
-       read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
+       read_buf(f_in, file_sum2, sum_len);
        if (verbose > 2)
                rprintf(FINFO,"got file_sum\n");
-       if (fd != -1 && memcmp(file_sum1, file_sum2, MD4_SUM_LENGTH) != 0)
+       if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
                return 0;
        return 1;
 }
diff --git a/rsync.h b/rsync.h
index 46a4a8a..a273a61 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -517,8 +517,6 @@ struct idev_node {
 #define MAXHOSTNAMELEN 256
 #endif
 
-/* the length of the md4 checksum */
-#define MD4_SUM_LENGTH 16
 #define SUM_LENGTH 16
 #define SHORT_SUM_LENGTH 2
 #define BLOCKSUM_BIAS 10
@@ -575,7 +573,7 @@ extern int preserve_acls;
 #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
 #define EXTRA_LEN (sizeof (union file_extras))
 #define PTR_EXTRA_LEN ((sizeof (char *) + EXTRA_LEN - 1) / EXTRA_LEN)
-#define SUM_EXTRA_CNT ((MD4_SUM_LENGTH + EXTRA_LEN - 1) / EXTRA_LEN)
+#define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
 
 #define REQ_EXTRA(f,ndx) ((union file_extras*)(f) - (ndx))
 #define OPT_EXTRA(f,bump) ((union file_extras*)(f) - file_extra_cnt - 1 - (bump))
@@ -772,7 +770,7 @@ typedef struct {
        (type*)expand_item_list(lp, sizeof (type), #type, incr)
 
 #include "byteorder.h"
-#include "lib/mdfour.h"
+#include "lib/mdigest.h"
 #include "lib/wildmatch.h"
 #include "lib/permstring.h"
 #include "lib/addrinfo.h"