+/*
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
+
+ The main author of Bacula is Kern Sibbald, with contributions from
+ many others, a complete list can be found in the file AUTHORS.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version three of the GNU Affero General Public
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
+
+ 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 Affero 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.
+
+ Bacula® is a registered trademark of Kern Sibbald.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
/*
* This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
+ * The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*
- * Version $Id$
*/
/* Brutally hacked by John Walker back from ANSI C to K&R (no
prototypes) to maintain the tradition that Netfone will compile
with Sun's original "cc". */
+
+
#include "bacula.h"
-#ifndef HAVE_BIGENDIAN
-#define byteReverse(buf, len) /* Nothing */
-#else
/*
- * Note: this code is harmless on little-endian machines.
+ * Note: this code is harmless on little-endian machines. We'll swap the bytes
+ * on big-endian machines.
*/
void byteReverse(unsigned char *buf, unsigned longs)
{
uint32_t t;
- do {
- t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32_t *) buf = t;
- buf += 4;
- } while (--longs);
+ if (bigendian()) {
+ do {
+ t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(uint32_t *) buf = t;
+ buf += 4;
+ } while (--longs);
+ }
}
-#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
-
- t = 64 - t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += t;
- len -= t;
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+ buf += t;
+ len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += 64;
- len -= 64;
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+ buf += 64;
+ len -= 64;
}
/* Handle any remaining bytes of data. */
/* Pad out to 56 mod 64 */
if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
} else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
}
#ifdef MD5_SUM
+#define OUTPUT_BASE64 1
+
+static void usage()
+{
+ fprintf(stderr,
+"\n"
+"Usage: md5sum [-d decode] <data-file>\n"
+" -d decode the data file\n"
+" -? print this message.\n"
+"\n\n");
+
+ exit(1);
+}
+
+static bool decode = false;
+
/*
* Reads a single ASCII file and prints the HEX md5 sum.
*/
MD5Context ctx;
char buf[5000];
char signature[20];
+ int ch;
+
+ while ((ch = getopt(argc, argv, "d?")) != -1) {
+ switch (ch) {
+ case 'd':
+ decode = true;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
if (argc < 1) {
printf("Must have filename\n");
exit(1);
}
- fd = fopen(argv[1], "r");
+
+ fd = fopen(argv[0], "rb");
if (!fd) {
- printf("Could not open %s: ERR=%s\n", argv[1], strerror(errno));
+ printf("Could not open %s: ERR=%s\n", argv[0], strerror(errno));
exit(1);
}
+ if (decode) {
+ goto decode_it;
+ }
MD5Init(&ctx);
while (fgets(buf, sizeof(buf), fd)) {
MD5Update(&ctx, (unsigned char *)buf, strlen(buf));
}
MD5Final((unsigned char *)signature, &ctx);
for (int i=0; i < 16; i++) {
- printf("%02x", signature[i]& 0xFF);
+ printf("%02x", signature[i]& 0xFF);
+ }
+#ifdef OUTPUT_BASE64
+ char MD5buf[40]; /* 24 should do */
+ memset(MD5buf, 0, 40);
+ bin_to_base64(MD5buf, sizeof(MD5buf), (char *)signature, 16, true); /* encode 16 bytes */
+ printf(" %s", MD5buf);
+#endif
+ printf(" %s\n", argv[0]);
+ exit(0);
+
+decode_it:
+ while (fgets(buf, sizeof(buf), fd)) {
+ char bin[40];
+ unsigned char *p = (unsigned char *)buf;
+ unsigned char ch;
+ int val;
+ for (int i=0; i < 16; i++) {
+ if (*p <= '9') {
+ val = *p - '0';
+ } else {
+ val = *p - 'a' + 10;
+ }
+ ch = val << 4;
+ p++;
+ if (*p <= '9') {
+ val = *p - '0';
+ } else {
+ val = *p - 'a' + 10;
+ }
+ signature[i] = ch + val;
+ p++;
+ }
+ signature[16] = 0;
+ printf("%s", buf);
+ bin_to_base64(bin, sizeof(bin), (char *)signature, 16, true);
+ printf("%s\n", bin);
}
- printf(" %s\n", argv[1]);
+ fclose(fd);
}
#endif