summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--NEWS2
-rw-r--r--README.menu13
-rw-r--r--com32/libutil/Makefile3
-rw-r--r--com32/libutil/base64.c95
-rw-r--r--com32/libutil/crypt-md5.c169
-rw-r--r--com32/libutil/include/base64.h10
-rw-r--r--com32/libutil/md5.c281
-rw-r--r--com32/modules/menumain.c36
-rwxr-xr-xmd5pass34
-rw-r--r--syslinux.spec.in2
11 files changed, 632 insertions, 16 deletions
diff --git a/Makefile b/Makefile
index 4a53774f..a7101cee 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,8 @@ ISUBDIRS = mtools unix extlinux sample com32
DOCS = COPYING NEWS README TODO BUGS *.doc sample menu com32
OTHER = Makefile bin2c.pl now.pl genhash.pl keywords findpatch.pl \
keytab-lilo.pl version version.pl sys2ansi.pl \
- ppmtolss16 lss16toppm memdisk bin2hex.pl mkdiskimage.in
+ ppmtolss16 lss16toppm memdisk bin2hex.pl mkdiskimage.in \
+ sha1pass md5pass
OBSOLETE = pxelinux.bin
# Things to install in /usr/bin
diff --git a/NEWS b/NEWS
index d3b7300b..817fbb52 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,8 @@ Changes in 3.52:
* MEMDISK: Fix failures on some BIOSes.
* Simple menu system: new "MENU HIDDEN" option to not display
the menu unless the user presses a key.
+ * Simple menu system: support MD5-encrypted passwords (modern
+ Unix standard style, with "$1$" prefixes.)
Changes in 3.51:
* EXTLINUX: Fix failure to find the configuration file.
diff --git a/README.menu b/README.menu
index d9a156cc..dec54105 100644
--- a/README.menu
+++ b/README.menu
@@ -102,11 +102,16 @@ ENDTEXT
MENU PASSWD passwd
(Only valid after a LABEL statement.)
+
Sets a password on this menu entry. "passwd" can be either a
- cleartext password or a SHA-1 encrypted password; use the
- included Perl script "sha1pass" to encrypt passwords.
- (Obviously, if you don't encrypt your passwords they will not
- be very secure at all.)
+ cleartext password, a SHA-1 encrypted password (starting with
+ $4$), or and MD5 encrypted password (starting with $1$).
+
+ Use the included Perl scripts "sha1pass" or "md5pass" to
+ encrypt passwords. MD5 passwords are compatible with most
+ Unix password file utilities; SHA-1 passwords are probably
+ unique to SYSLINUX. Obviously, if you don't encrypt your
+ passwords they will not be very secure at all.
If you are using passwords, you want to make sure you also use
the settings "NOESCAPE 1", "PROMPT 0", and either set
diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 15393533..1e5c7bcf 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -48,7 +48,8 @@ LNXCFLAGS = -I./include -W -Wall -O -g
LNXSFLAGS = -g
LNXLDFLAGS = -g
OBJCOPY = objcopy
-LIBOBJS = ansiline.o ansiraw.o get_key.o sha1hash.o unbase64.o
+LIBOBJS = ansiline.o ansiraw.o get_key.o sha1hash.o unbase64.o \
+ md5.o crypt-md5.o base64.o
LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
.SUFFIXES: .lss .c .lo .o .elf .c32 .lnx
diff --git a/com32/libutil/base64.c b/com32/libutil/base64.c
new file mode 100644
index 00000000..7812bfe1
--- /dev/null
+++ b/com32/libutil/base64.c
@@ -0,0 +1,95 @@
+/*
+ * Output a base64 string.
+ *
+ * Options include:
+ * - Character 62 and 63;
+ * - To pad or not to pad.
+ */
+
+#include <inttypes.h>
+#include <base64.h>
+
+size_t genbase64(char *output, const void *input, size_t size, int flags)
+{
+ static char charz[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_";
+ uint8_t buf[3];
+ int j;
+ const uint8_t *p;
+ char *q;
+ uint32_t bv;
+ int left = size;
+
+ charz[62] = (char)flags;
+ charz[63] = (char)(flags >> 8);
+
+ p = input; q = output;
+
+ while (left > 0) {
+ if (left < 3) {
+ buf[0] = p[0];
+ buf[1] = (left > 1) ? p[1] : 0;
+ buf[2] = 0;
+ p = buf;
+ }
+
+ bv = (p[0] << 16) | (p[1] << 8) | p[2];
+ p += 3;
+ left -= 3;
+
+ for ( j = 0 ; j < 4 ; j++ ) {
+ *q++ = charz[(bv >> 18) & 0x3f];
+ bv <<= 6;
+ }
+ }
+
+ switch (left) {
+ case -1:
+ if (flags & BASE64_PAD)
+ q[-1] = '=';
+ else
+ q--;
+ break;
+
+ case -2:
+ if (flags & BASE64_PAD)
+ q[-2] = q[-1] = '=';
+ else
+ q -= 2;
+ break;
+
+ default:
+ break;
+ }
+
+ *q = '\0';
+
+ return q-output;
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ int i;
+ char buf[4096];
+ int len, bytes;
+
+ for (i = 1; i < argc; i++) {
+ printf("Original: \"%s\"\n", argv[i]);
+
+ len = strlen(argv[i]);
+ bytes = genbase64(buf, argv[i], len, BASE64_MIME|BASE64_PAD);
+ printf(" MIME: \"%s\" (%d)\n", buf, bytes);
+ bytes = genbase64(buf, argv[i], len, BASE64_SAFE);
+ printf(" Safe: \"%s\" (%d)\n", buf, bytes);
+ }
+
+ return 0;
+}
+
+#endif
+
diff --git a/com32/libutil/crypt-md5.c b/com32/libutil/crypt-md5.c
new file mode 100644
index 00000000..7804e4d5
--- /dev/null
+++ b/com32/libutil/crypt-md5.c
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 2003 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <inttypes.h>
+#include <md5.h>
+#include <string.h>
+
+/*
+ * UNIX password
+ */
+
+#include "crypt.h"
+
+static char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void
+_crypt_to64(char *s, uint32_t v, int n)
+{
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+char *
+crypt_md5(const char *pw, const char *salt)
+{
+ MD5_CTX ctx,ctx1;
+ unsigned long l;
+ int sl, pl;
+ uint32_t i;
+ uint8_t final[MD5_SIZE];
+ static const char *sp, *ep;
+ static char passwd[120], *p;
+ static const char *magic = "$1$";
+
+ /* Refine the Salt first */
+ sp = salt;
+
+ /* If it starts with the magic string, then skip that */
+ if(!strncmp(sp, magic, strlen(magic)))
+ sp += strlen(magic);
+
+ /* It stops at the first '$', max 8 chars */
+ for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
+ continue;
+
+ /* get the length of the true salt */
+ sl = ep - sp;
+
+ MD5Init(&ctx);
+
+ /* The password first, since that is what is most unknown */
+ MD5Update(&ctx, (const uint8_t *)pw, strlen(pw));
+
+ /* Then our magic string */
+ MD5Update(&ctx, (const uint8_t *)magic, strlen(magic));
+
+ /* Then the raw salt */
+ MD5Update(&ctx, (const uint8_t *)sp, (uint32_t)sl);
+
+ /* Then just as many characters of the MD5(pw,salt,pw) */
+ MD5Init(&ctx1);
+ MD5Update(&ctx1, (const uint8_t *)pw, strlen(pw));
+ MD5Update(&ctx1, (const uint8_t *)sp, (uint32_t)sl);
+ MD5Update(&ctx1, (const uint8_t *)pw, strlen(pw));
+ MD5Final(final, &ctx1);
+ for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE)
+ MD5Update(&ctx, (const uint8_t *)final,
+ (uint32_t)(pl > MD5_SIZE ? MD5_SIZE : pl));
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final, 0, sizeof(final));
+
+ /* Then something really weird... */
+ for (i = strlen(pw); i; i >>= 1)
+ if(i & 1)
+ MD5Update(&ctx, (const uint8_t *)final, 1);
+ else
+ MD5Update(&ctx, (const uint8_t *)pw, 1);
+
+ /* Now make the output string */
+ strcpy(passwd, magic);
+ strncat(passwd, sp, (uint32_t)sl);
+ strcat(passwd, "$");
+
+ MD5Final(final, &ctx);
+
+ /*
+ * and now, just to make sure things don't run too fast
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for(i = 0; i < 1000; i++) {
+ MD5Init(&ctx1);
+ if(i & 1)
+ MD5Update(&ctx1, (const uint8_t *)pw, strlen(pw));
+ else
+ MD5Update(&ctx1, (const uint8_t *)final, MD5_SIZE);
+
+ if(i % 3)
+ MD5Update(&ctx1, (const uint8_t *)sp, (uint32_t)sl);
+
+ if(i % 7)
+ MD5Update(&ctx1, (const uint8_t *)pw, strlen(pw));
+
+ if(i & 1)
+ MD5Update(&ctx1, (const uint8_t *)final, MD5_SIZE);
+ else
+ MD5Update(&ctx1, (const uint8_t *)pw, strlen(pw));
+ MD5Final(final, &ctx1);
+ }
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
+ _crypt_to64(p, l, 4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
+ _crypt_to64(p, l, 4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
+ _crypt_to64(p, l, 4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
+ _crypt_to64(p, l, 4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
+ _crypt_to64(p, l, 4); p += 4;
+ l = final[11];
+ _crypt_to64(p, l, 2); p += 2;
+ *p = '\0';
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final, 0, sizeof(final));
+
+ return (passwd);
+}
+
+#ifdef TEST
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ puts(crypt_md5(argv[1], argv[2]));
+ return 0;
+}
+
+#endif
diff --git a/com32/libutil/include/base64.h b/com32/libutil/include/base64.h
index 89ea1800..514eb177 100644
--- a/com32/libutil/include/base64.h
+++ b/com32/libutil/include/base64.h
@@ -36,6 +36,16 @@
#include <stddef.h>
+#define BASE64_PAD 0x10000
+
+/* There is plenty of disagreement w.r.t. the last few characters... */
+#define BASE64_MIME ('+' + ('/' << 8))
+#define BASE64_SAFE ('-' + ('_' << 8))
+#define BASE64_CRYPT ('.' + ('/' << 8))
+#define BASE64_URL ('*' + ('-' << 8)) /* Haven't seen myself */
+#define BASE64_REGEX ('|' + ('-' << 8)) /* Ditto... */
+
+size_t genbase64(char *output, const void *digest, size_t size, int flags);
size_t unbase64(unsigned char *, size_t, const char *);
#endif
diff --git a/com32/libutil/md5.c b/com32/libutil/md5.c
new file mode 100644
index 00000000..0e53db39
--- /dev/null
+++ b/com32/libutil/md5.c
@@ -0,0 +1,281 @@
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ *
+ * This code is the same as the code published by RSA Inc. It has been
+ * edited for clarity and style only.
+ */
+
+#include <string.h>
+#include <endian.h>
+#include <md5.h>
+
+static void MD5Transform(uint32_t [4], const unsigned char [64]);
+
+#define Encode memcpy
+#define Decode memcpy
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions. */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/*
+ * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context. */
+
+void
+MD5Init (MD5_CTX *context)
+{
+
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/*
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+
+void
+MD5Update (MD5_CTX *context, const void *in, size_t inputLen)
+{
+ unsigned int i, idx, partLen;
+ const unsigned char *input = in;
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((uint32_t)inputLen << 3))
+ < ((uint32_t)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((uint32_t)inputLen >> 29);
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+ if (inputLen >= partLen) {
+ memcpy((void *)&context->buffer[idx], (const void *)input,
+ partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy ((void *)&context->buffer[idx], (const void *)&input[i],
+ inputLen-i);
+}
+
+/*
+ * MD5 padding. Adds padding followed by original length.
+ */
+
+static void
+MD5Pad (MD5_CTX *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64. */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ MD5Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5Update (context, bits, 8);
+}
+
+/*
+ * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+
+void
+MD5Final (unsigned char digest[16], MD5_CTX *context)
+{
+ /* Do padding. */
+ MD5Pad (context);
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset ((void *)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+
+static void
+MD5Transform (state, block)
+ uint32_t state[4];
+ const unsigned char block[64];
+{
+ uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset ((void *)x, 0, sizeof (x));
+}
diff --git a/com32/modules/menumain.c b/com32/modules/menumain.c
index 257477b9..5bd0eb2b 100644
--- a/com32/modules/menumain.c
+++ b/com32/modules/menumain.c
@@ -28,6 +28,7 @@
#include <setjmp.h>
#include <limits.h>
#include <sha1.h>
+#include <md5.h>
#include <base64.h>
#include <colortbl.h>
#include <com32.h>
@@ -288,21 +289,12 @@ draw_row(int y, int sel, int top, int sbtop, int sbbot)
}
}
-static int
-passwd_compare(const char *passwd, const char *entry)
+static int passwd_compare_sha1(const char *passwd, const char *entry)
{
const char *p;
SHA1_CTX ctx;
unsigned char sha1[20], pwdsha1[20];
- if ( passwd[0] != '$' ) /* Plaintext passwd, yuck! */
- return !strcmp(entry, passwd);
-
- if ( strncmp(passwd, "$4$", 3) )
- return 0; /* Only SHA-1 passwds supported */
-
- SHA1Init(&ctx);
-
if ( (p = strchr(passwd+3, '$')) ) {
SHA1Update(&ctx, (void *)passwd+3, p-(passwd+3));
p++;
@@ -310,6 +302,8 @@ passwd_compare(const char *passwd, const char *entry)
p = passwd+3; /* Assume no salt */
}
+ SHA1Init(&ctx);
+
SHA1Update(&ctx, (void *)entry, strlen(entry));
SHA1Final(sha1, &ctx);
@@ -319,6 +313,28 @@ passwd_compare(const char *passwd, const char *entry)
return !memcmp(sha1, pwdsha1, 20);
}
+static int passwd_compare_md5(const char *passwd, const char *entry)
+{
+ const char *crypted = crypt_md5(entry, passwd+3);
+ int len = strlen(crypted);
+
+ return !strncmp(crypted, passwd, len) &&
+ (passwd[len] == '\0' || passwd[len] == '$');
+}
+
+static int
+passwd_compare(const char *passwd, const char *entry)
+{
+ if ( passwd[0] != '$' ) /* Plaintext passwd, yuck! */
+ return !strcmp(entry, passwd);
+ else if ( !strncmp(passwd, "$4$", 3) )
+ return passwd_compare_sha1(passwd, entry);
+ else if ( !strncmp(passwd, "$1$", 3) )
+ return passwd_compare_md5(passwd, entry);
+ else
+ return 0; /* Invalid encryption algorithm */
+}
+
static jmp_buf timeout_jump;
int mygetkey(clock_t timeout)
diff --git a/md5pass b/md5pass
new file mode 100755
index 00000000..3404f1d6
--- /dev/null
+++ b/md5pass
@@ -0,0 +1,34 @@
+#!/usr/bin/perl
+
+use bytes;
+use Crypt::PasswdMD5;
+use MIME::Base64;
+
+sub random_bytes($) {
+ my($n) = @_;
+ my($v, $i);
+
+ if ( open(RANDOM, '<', '/dev/random') ||
+ open(RANDOM, '<', '/dev/urandom') ) {
+ read(RANDOM, $v, $n);
+ } else {
+ # No real RNG available...
+ srand($$ ^ time);
+ $v = '';
+ for ( $i = 0 ; $i < $n ; $i++ ) {
+ $v .= ord(int(rand() * 256));
+ }
+ }
+
+ return $v;
+}
+
+
+($pass, $salt) = @ARGV;
+
+unless (defined($salt)) {
+ $salt = MIME::Base64::encode(random_bytes(6), '');
+ $salt =~ tr/\+/./; # . not +
+}
+
+print unix_md5_crypt($pass, $salt), "\n";
diff --git a/syslinux.spec.in b/syslinux.spec.in
index a5cb6086..23c313e2 100644
--- a/syslinux.spec.in
+++ b/syslinux.spec.in
@@ -100,6 +100,8 @@ rm -rf %{buildroot}
%{_bindir}/ppmtolss16
%{_bindir}/lss16toppm
%{_bindir}/gethostip
+%{_bindir}/sha1pass
+%{_bindir}/md5pass
%{_datadir}/syslinux/*.com
%{_datadir}/syslinux/*.exe
%{_datadir}/syslinux/*.c32