Browse Source

add menu based configuration of a password

Waldemar Brodkorb 14 years ago
parent
commit
1879491b2b

+ 21 - 17
Config.in

@@ -18,30 +18,17 @@ config ADK_HAVE_DOT_CONFIG
 menu "ADK settings"
 
 config ADK_VENDOR
-	string "Vendor name (f.e. OpenADK)"
-	default "OpenADK"
+	string "vendor name"
+	default "openadk"
 	help
-	  Vendor string is used for uvd and other stuff.
+	  Vendor string is used for toolchain.
 
 config ADK_HOST
-	string "Webserver for packages and distfiles"
+	string "webserver for packages and distfiles"
 	default "www.openadk.org"
 	help
 	  Configure host for IPKG package management.
 
-config ADK_SSH_PUBKEY
-	string "SSH public key (root user only)"
-	default ""
-	help
-	  Paste your generated SSH public key here and it will be embedded into
-	  the built image, so you can use it to login instantly.
-
-#config ADK_PASSWORD
-#	string "root password for the embedded system"
-#	default "linux123"
-#	help
-#	  Predefine the root password enabled in the the built image.
-
 config ADK_DEVELSYSTEM
 	bool "Compile a ADK development system"
 	default n
@@ -161,4 +148,21 @@ endchoice
 endmenu
 
 source "target/Config.in"
+
+menu "Runtime configuration"
+config ADK_SSH_PUBKEY
+	string "SSH public key (root user only)"
+	default ""
+	help
+	  Paste your generated SSH public key here and it will be embedded into
+	  the built image, so you can use it to login instantly.
+
+config ADK_PASSWORD
+	string "root password for the embedded system"
+	default "linux123"
+	help
+	  Predefine the root password enabled in the built image.
+
+endmenu
+
 source "package/Config.in"

+ 6 - 3
mk/build.mk

@@ -90,12 +90,12 @@ ${TOPDIR}/package/Depends.mk: ${TOPDIR}/.config $(wildcard ${TOPDIR}/package/*/M
 world: $(DISTDIR) $(BUILD_DIR) $(TARGET_DIR) $(PACKAGE_DIR) ${TOPDIR}/.ADK_HAVE_DOT_CONFIG
 	${BASH} ${TOPDIR}/scripts/scan-pkgs.sh
 ifeq ($(ADK_NATIVE),y)
-	$(MAKE) -f mk/build.mk toolchain/kernel-headers-prepare target/config-prepare target/compile package/compile root_clean package/install package_index target/install
+	$(MAKE) -f mk/build.mk toolchain/kernel-headers-prepare tools/install target/config-prepare target/compile package/compile root_clean package/install package_index target/install
 else
 ifeq ($(ADK_TOOLCHAIN_ONLY),y)
-	$(MAKE) -f mk/build.mk toolchain/install package/compile
+	$(MAKE) -f mk/build.mk toolchain/install tools/install package/compile
 else
-	$(MAKE) -f mk/build.mk toolchain/install target/config-prepare target/compile package/compile root_clean package/install target/install package_index
+	$(MAKE) -f mk/build.mk toolchain/install tools/install target/config-prepare target/compile package/compile root_clean package/install target/install package_index
 endif
 endif
 
@@ -136,6 +136,9 @@ target/%: ${TOPDIR}/.ADK_HAVE_DOT_CONFIG
 toolchain/%: ${STAGING_DIR}
 	$(MAKE) -C toolchain $(patsubst toolchain/%,%,$@)
 
+tools/%:
+	$(MAKE) -C tools $(patsubst tools/%,%,$@)
+
 image:
 	$(MAKE) -C target image
 

+ 2 - 2
mk/vars.mk

@@ -37,8 +37,8 @@ PACKAGE_DIR:=		$(BIN_DIR)/packages
 TARGET_DIR:=		$(BASE_DIR)/root_${ADK_TARGET}_${ADK_LIBC}
 TARGET_DIR_PFX:=	$(BASE_DIR)/root_*
 TARGET_PATH=		${SCRIPT_DIR}:${STAGING_TOOLS}/bin:${STAGING_DIR}/scripts:${_PATH}
-REAL_GNU_TARGET_NAME=	$(CPU_ARCH)-openadk-linux-$(ADK_TARGET_SUFFIX)
-GNU_TARGET_NAME=	$(CPU_ARCH)-openadk-linux
+REAL_GNU_TARGET_NAME=	$(CPU_ARCH)-$(ADK_VENDOR)-linux-$(ADK_TARGET_SUFFIX)
+GNU_TARGET_NAME=	$(CPU_ARCH)-$(ADK_VENDOR)-linux
 TOOLCHAIN_SYSROOT:=	$(TOOLCHAIN_BUILD_DIR)/libc_dev
 ifeq ($(ADK_NATIVE),y) 
 TARGET_CROSS:=		

+ 6 - 2
package/base-files/Makefile

@@ -6,9 +6,9 @@ include $(TOPDIR)/mk/rootfs.mk
 
 PKG_NAME:=		base-files
 PKG_VERSION:=		1.0
-PKG_RELEASE:=		15
-PKG_DESCR:=		basic filesystem structure and scripts
+PKG_RELEASE:=		17
 PKG_SECTION:=		base
+PKG_DESCR:=		basic filesystem structure and scripts
 
 WRKDIST=		${WRKDIR}/base-files
 NO_DISTFILES:=		1
@@ -34,6 +34,7 @@ endif
 	$(SED) 's,@TARGET@,$(ADK_TARGET),g' $(IDIR_BASE_FILES)/etc/ipkg.conf
 	$(SED) 's,@HOST@,$(ADK_HOST),g' $(IDIR_BASE_FILES)/etc/ipkg.conf
 	$(SED) 's,@LIBC@,$(ADK_LIBC),g' $(IDIR_BASE_FILES)/etc/ipkg.conf
+	$(SED) 's,@VENDOR@,$(ADK_VENDOR),g' $(IDIR_BASE_FILES)/etc/ipkg.conf
 	echo /bin/sh >${IDIR_BASE_FILES}/etc/shells
 	echo /bin/ash >>${IDIR_BASE_FILES}/etc/shells
 ifneq (${ADK_PACKAGE_BASH},)
@@ -64,6 +65,9 @@ endif
 	ln -sf ../proc/mounts $(IDIR_BASE_FILES)/etc/mtab
 	rm -rf $(IDIR_BASE_FILES)/var
 	ln -sf tmp $(IDIR_BASE_FILES)/var
+	test -z $(ADK_PASSWORD) || \
+	    $(SED) 's,\*NP\*,'"$$(${STAGING_TOOLS}/bin/mkcrypt \
+	    ${ADK_PASSWORD}),g" $(IDIR_BASE_FILES)/etc/shadow
 	git log -1|head -1|sed -e 's#commit ##' \
 		> $(IDIR_BASE_FILES)/etc/adkversion
 ifneq (${ADK_PACKAGE_CONFIG_IN_ETC},)

+ 1 - 1
package/base-files/src/etc/ipkg.conf

@@ -1,3 +1,3 @@
-src openadk http://@HOST@/@TARGET@_@LIBC@/packages
+src @VENDOR@ http://@HOST@/@TARGET@_@LIBC@/packages
 dest root /
 dest ram /tmp

+ 1 - 2
package/base-files/src/etc/shadow

@@ -1,3 +1,2 @@
-root:$1$8sJkb6fV$46vEIu5ntmbUuljmr55zY/:14191:0:::::
-admin:$1$8sJkb6fV$46vEIu5ntmbUuljmr55zY/:14191:0:::::
+root:*NP*:14191:0:::::
 nobody:*:9797:0:::::

+ 1 - 0
rules.mk

@@ -28,6 +28,7 @@ endif
 ADK_TARGET:=		$(strip $(subst ",, $(ADK_TARGET)))
 ADK_LIBC:=		$(strip $(subst ",, $(ADK_LIBC)))
 ADK_HOST:=		$(strip $(subst ",, $(ADK_HOST)))
+ADK_VENDOR:=		$(strip $(subst ",, $(ADK_VENDOR)))
 ADK_TARGET_SUFFIX:=	$(strip $(subst ",, $(ADK_TARGET_SUFFIX)))
 ADK_COMPRESSION_TOOL:=	$(strip $(subst ",, $(ADK_COMPRESSION_TOOL)))
 

+ 1 - 1
toolchain/Makefile

@@ -3,7 +3,7 @@
 #
 # Steps to build toolchains
 # 1) build and install binutils
-# 2) build and install mpfr and gmp
+# 2) build and install mpfr, mpc and gmp
 # 3) build and install gcc c compiler
 # 4) install kernel-headers
 # 5) install libc headers

+ 33 - 0
tools/Makefile

@@ -0,0 +1,33 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+include $(TOPDIR)/rules.mk
+
+TARGETS:=mkcrypt
+TARGETS_INSTALL:=$(patsubst %,%-install,$(TARGETS))
+TARGETS_CLEAN:=$(patsubst %,%-clean,$(TARGETS))
+
+all: install
+prepare:
+compile:
+install: $(TARGETS_INSTALL)
+clean: $(TARGETS_CLEAN)
+
+$(TOOLS_BUILD_DIR):
+	mkdir -p $(TOOLS_BUILD_DIR)
+
+%-download:
+	$(TRACE) "tools/$(patsubst %-download,%,$@)-download: "
+	$(MAKE) -C $(patsubst %-download,%,$@) fetch
+
+%-compile: $(TOOLS_BUILD_DIR)
+	$(TRACE) "tools/$(patsubst %-compile,%,$@)-compile: "
+	$(MAKE) -C $(patsubst %-compile,%,$@) compile
+
+%-install:
+	$(TRACE) "tools/$(patsubst %-install,%,$@)-install: "
+	$(MAKE) -C $(patsubst %-install,%,$@) install
+
+%-clean:
+	$(TRACE) "tools/$(patsubst %-clean,%,$@)-clean: "
+	$(MAKE) -C $(patsubst %-clean,%,$@) clean

+ 22 - 0
tools/mkcrypt/Makefile

@@ -0,0 +1,22 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=		mkcrypt
+PKG_VERSION:=		0.1
+PKG_RELEASE:=		1
+NO_DISTFILES:=		1
+
+include ../rules.mk
+
+$(WRKBUILD)/.compiled: ${WRKDIST}/.prepared
+	$(HOSTCC) -o $(WRKBUILD)/mkcrypt mkcrypt.c
+	touch $@
+
+$(WRKBUILD)/.installed: $(WRKBUILD)/.compiled
+	$(INSTALL_BIN) $(WRKBUILD)/mkcrypt \
+		${STAGING_TOOLS}/bin
+	touch $@
+
+include $(TOPDIR)/mk/tools.mk

+ 441 - 0
tools/mkcrypt/mkcrypt.c

@@ -0,0 +1,441 @@
+/*-
+ * Copyright (c) 2007
+ *	Thorsten Glaser <tg@mirbsd.de>
+ *
+ * Provided that these terms and disclaimer and all copyright notices
+ * are retained or reproduced in an accompanying document, permission
+ * is granted to deal in this work without restriction, including un-
+ * limited rights to use, publicly perform, distribute, sell, modify,
+ * merge, give away, or sublicence.
+ *
+ * Advertising materials mentioning features or use of this work must
+ * display the following acknowledgement:
+ *	This product includes material provided by Thorsten Glaser.
+ *	This product includes software developed by Niels Provos.
+ *
+ * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
+ * the utmost extent permitted by applicable law, neither express nor
+ * implied; without malicious intent or gross negligence. In no event
+ * may a licensor, author or contributor be held liable for indirect,
+ * direct, other damage, loss, or other issues arising in any way out
+ * of dealing in the work, even if advised of the possibility of such
+ * damage or existence of a defect, except proven that it results out
+ * of said person's immediate fault when using the work as intended.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#define	MD5_BLOCK_LENGTH		64
+#define	MD5_DIGEST_LENGTH		16
+#define	MD5_DIGEST_STRING_LENGTH	(MD5_DIGEST_LENGTH * 2 + 1)
+
+typedef struct MD5Context {
+	u_int32_t state[4];
+	u_int64_t count;
+	u_int8_t  buffer[MD5_BLOCK_LENGTH];
+} MD5_CTX;
+
+/* low-level MD5 functions from md5c.c */
+void	MD5Init(MD5_CTX *);
+void	MD5Update(MD5_CTX *, const u_int8_t *, size_t);
+void	MD5Pad(MD5_CTX *);
+void	MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *);
+void	MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH]);
+
+/* high-level functions from mdXhl.c */
+char   *MD5End(MD5_CTX *, char *);
+char   *MD5File(const char *, char *);
+char   *MD5FileChunk(const char *, char *, off_t, off_t);
+char   *MD5Data(const u_int8_t *, size_t, char *);
+
+void to64(char *, u_int32_t, int);
+char *md5crypt(const char *pw, const char *salt);
+int pwd_gensalt(char *, int);
+
+static unsigned char itoa64[] =		/* 0 ... 63 => ascii - 64 */
+	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void
+to64(char *s, u_int32_t v, int n)
+{
+	while (--n >= 0) {
+		*s++ = itoa64[v&0x3f];
+		v >>= 6;
+	}
+}
+
+#define PUT_64BIT_LE(cp, value) do {					\
+	(cp)[7] = (value) >> 56;					\
+	(cp)[6] = (value) >> 48;					\
+	(cp)[5] = (value) >> 40;					\
+	(cp)[4] = (value) >> 32;					\
+	(cp)[3] = (value) >> 24;					\
+	(cp)[2] = (value) >> 16;					\
+	(cp)[1] = (value) >> 8;						\
+	(cp)[0] = (value); } while (0)
+
+#define PUT_32BIT_LE(cp, value) do {					\
+	(cp)[3] = (value) >> 24;					\
+	(cp)[2] = (value) >> 16;					\
+	(cp)[1] = (value) >> 8;						\
+	(cp)[0] = (value); } while (0)
+
+static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
+	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
+};
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(MD5_CTX *ctx)
+{
+	ctx->count = 0;
+	ctx->state[0] = 0x67452301;
+	ctx->state[1] = 0xefcdab89;
+	ctx->state[2] = 0x98badcfe;
+	ctx->state[3] = 0x10325476;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
+{
+	size_t have, need;
+
+	/* Check how many bytes we already have and how many more we need. */
+	have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
+	need = MD5_BLOCK_LENGTH - have;
+
+	/* Update bitcount */
+	ctx->count += (u_int64_t)len << 3;
+
+	if (len >= need) {
+		if (have != 0) {
+			memcpy(ctx->buffer + have, input, need);
+			MD5Transform(ctx->state, ctx->buffer);
+			input += need;
+			len -= need;
+			have = 0;
+		}
+
+		/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
+		while (len >= MD5_BLOCK_LENGTH) {
+			MD5Transform(ctx->state, input);
+			input += MD5_BLOCK_LENGTH;
+			len -= MD5_BLOCK_LENGTH;
+		}
+	}
+
+	/* Handle any remaining bytes of data. */
+	if (len != 0)
+		memcpy(ctx->buffer + have, input, len);
+}
+
+/*
+ * Pad pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Pad(MD5_CTX *ctx)
+{
+	u_int8_t count[8];
+	size_t padlen;
+
+	/* Convert count to 8 bytes in little endian order. */
+	PUT_64BIT_LE(count, ctx->count);
+
+	/* Pad out to 56 mod 64. */
+	padlen = MD5_BLOCK_LENGTH -
+	    ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
+	if (padlen < 1 + 8)
+		padlen += MD5_BLOCK_LENGTH;
+	MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
+	MD5Update(ctx, count, 8);
+}
+
+/*
+ * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
+ */
+void
+MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
+{
+	int i;
+
+	MD5Pad(ctx);
+	if (digest != NULL) {
+		for (i = 0; i < 4; i++)
+			PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
+		memset(ctx, 0, sizeof(*ctx));
+	}
+}
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* 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 )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
+{
+	u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+	memcpy(in, block, sizeof(in));
+#else
+	for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
+		in[a] = (u_int32_t)(
+		    (u_int32_t)(block[a * 4 + 0]) |
+		    (u_int32_t)(block[a * 4 + 1]) <<  8 |
+		    (u_int32_t)(block[a * 4 + 2]) << 16 |
+		    (u_int32_t)(block[a * 4 + 3]) << 24);
+	}
+#endif
+
+	a = state[0];
+	b = state[1];
+	c = state[2];
+	d = state[3];
+
+	MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
+	MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
+	MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
+	MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
+	MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
+	MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
+	MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
+	MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
+	MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
+	MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
+	MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
+	MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
+	MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
+
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+}
+
+/*
+ * UNIX password
+ *
+ * Use MD5 for what it is best at...
+ */
+
+char *
+md5crypt(const char *pw, const char *salt)
+{
+	/*
+	 * This string is magic for this algorithm.  Having
+	 * it this way, we can get get better later on
+	 */
+	static const unsigned char *magic = (const unsigned char *)"$1$";
+
+	static char     passwd[120], *p;
+	static const unsigned char *sp,*ep;
+	unsigned char	final[16];
+	int sl,pl,i;
+	MD5_CTX	ctx,ctx1;
+	u_int32_t l;
+
+	/* Refine the Salt first */
+	sp = (const unsigned char *)salt;
+
+	/* If it starts with the magic string, then skip that */
+	if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic)))
+		sp += strlen((const char *)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 unsigned char *)pw,strlen(pw));
+
+	/* Then our magic string */
+	MD5Update(&ctx,magic,strlen((const char *)magic));
+
+	/* Then the raw salt */
+	MD5Update(&ctx,sp,sl);
+
+	/* Then just as many characters of the MD5(pw,salt,pw) */
+	MD5Init(&ctx1);
+	MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
+	MD5Update(&ctx1,sp,sl);
+	MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
+	MD5Final(final,&ctx1);
+	for(pl = strlen(pw); pl > 0; pl -= 16)
+		MD5Update(&ctx,final,pl>16 ? 16 : 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, final, 1);
+		else
+		    MD5Update(&ctx, (const unsigned char *)pw, 1);
+
+	/* Now make the output string */
+	snprintf(passwd, sizeof(passwd), "%s%.*s$", magic,
+	    sl, (const char *)sp);
+
+	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 unsigned char *)pw,strlen(pw));
+		else
+			MD5Update(&ctx1,final,16);
+
+		if(i % 3)
+			MD5Update(&ctx1,sp,sl);
+
+		if(i % 7)
+			MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
+
+		if(i & 1)
+			MD5Update(&ctx1,final,16);
+		else
+			MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
+		MD5Final(final,&ctx1);
+	}
+
+	p = passwd + strlen(passwd);
+
+	l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
+	l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
+	l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
+	l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
+	l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
+	l =		       final[11]		; 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;
+}
+
+int pwd_gensalt(char *salt, int saltlen) {
+
+	*salt = '\0';
+
+	if (saltlen < 13) {	/* $1$8salt$\0 */
+		return 0;
+	}
+
+	strcpy(salt, "$1$");
+	to64(&salt[3], random(), 4);
+	to64(&salt[7], random(), 4);
+	strcpy(&salt[11], "$");
+	return 1;
+}
+
+int main(int argc, char *argv[]) {
+	char salt[16];
+	char *pw;
+
+	if (!argv[1]) {
+		fprintf(stderr, "Syntax Error!\n");
+		return (1);
+	}
+	if (!pwd_gensalt(salt, sizeof (salt)))
+		return (255);
+	if ((pw = md5crypt(argv[1], salt)) == NULL) {
+		fprintf(stderr, "Error generating password!\n");
+		return (1);
+	}
+	printf("%s\n", pw);
+	return (0);
+}

+ 7 - 0
tools/rules.mk

@@ -0,0 +1,7 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+WRKDIR_BASE=    ${TOOLS_BUILD_DIR}
+WRKDIR=		${WRKDIR_BASE}
+
+include ${TOPDIR}/mk/buildhlp.mk