This is a simple proposal to add support for NT MD4 password hashes to crypt(3).
NT MD4 password hashes are more insecure than the standard FreeBSD MD5 based password crypt or the much more stronger blowfish based encryption. Why are you/we so nut to use NT password hashes? The answer is very simple:

If you like to authenticate dialin users (ppp, pptp) with CHAP you need the plaintext password on the server and therefore its not possible to store the passwords in the systems master.passwd. Using PAP is a bad idea, because the passwords are transmitted as plaintext over the net. MS-CHAP solves this problem by using hashed passwords (md4).

With MS-CHAP and our modification to crypt(3) its not longer necessary to store plaintext secrets on your server!

But we think there are many more advantages:

1. Only one user database (password can easily changed by the user himself).
2. MS-CHAP can used, without storing the plaintext passwords on the server.
3. SAMBA can modified to use directly the master.passwd and not his own smbpasswd.
4. Samba can use NIS for encrypted passwords on FreeBSD.


1. No salt is used, users with same passwords have the same hash

The attached patches implements this as new password type $3 and it can be configured via login.conf (:passwd_format=nth:).

Patches for MPD, SAMBA and (soon) for PPP can be found here:

------------------------------- -------------------------------------
Michael Bretterklieber - [EMAIL PROTECTED]
JAWA Management Software GmbH - http://www.jawa.at
Liebenauer Hauptstr. 200 -------------- privat ---------------
A-8041 GRAZ GSM: ++43-(0)676-93 96 698
Tel: ++43-(0)316-403274-12 E-mail: [EMAIL PROTECTED]
Fax: ++43-(0)316-403274-10 http://www.bretterklieber.com
------------------------------- -------------------------------------
"...the number of UNIX installations has grown to 10, with more
expected..." - Dennis Ritchie and Ken Thompson, June 1972
diff -u libcrypt_orig/Makefile libcrypt/Makefile
--- libcrypt_orig/Makefile      Fri Jan 17 19:11:12 2003
+++ libcrypt/Makefile   Fri Jan 17 18:55:22 2003
@@ -6,9 +6,10 @@
 LIB=           crypt
 .PATH:         ${.CURDIR}/../libmd
-SRCS=          crypt.c crypt-md5.c md5c.c misc.c
+SRCS=          crypt.c crypt-nthash.c crypt-md5.c md5c.c misc.c
 MAN=           crypt.3
 MLINKS=                crypt.3 crypt_get_format.3 crypt.3 crypt_set_format.3
+LDADD+=                -lmd
 CFLAGS+=       -I${.CURDIR}/../libmd -I${.CURDIR}/../libutil
 CFLAGS+=       -DLIBC_SCCS -Wall
 # Pull in the crypt-des.c source, assuming it is present.
Only in libcrypt: crypt-nthash.c
diff -u libcrypt_orig/crypt.c libcrypt/crypt.c
--- libcrypt_orig/crypt.c       Fri Jan 17 19:11:06 2003
+++ libcrypt/crypt.c    Fri Jan 17 18:14:04 2003
@@ -62,6 +62,11 @@
+               "nth",
+               crypt_nthash,
+               "$3"
+       },
+       {
diff -u libcrypt_orig/crypt.h libcrypt/crypt.h
--- libcrypt_orig/crypt.h       Fri Jan 17 19:11:08 2003
+++ libcrypt/crypt.h    Fri Jan 17 18:14:30 2003
@@ -33,6 +33,7 @@
 char *crypt_des(const char *pw, const char *salt);
 char *crypt_md5(const char *pw, const char *salt);
 char *crypt_blowfish(const char *pw, const char *salt);
+char *crypt_nthash(const char *pw, const char *salt);
 extern void _crypt_to64(char *s, unsigned long v, int n);
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <[EMAIL PROTECTED]> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
 * ----------------------------------------------------------------------------
 * $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 2001/05/24 12:20:02 markm Exp $

#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = \
"$FreeBSD: src/lib/libcrypt/crypt-md5.c,v 2001/05/24 12:20:02 markm Exp $";
#endif /* LIBC_SCCS and not lint */

#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <md4.h>
#include <err.h>
#include "crypt.h"

#define MD4_SIZE 16

 * NT HASH = md4(str2unicode(pw))

char *crypt_nthash(pw, salt)
        const char *pw;
        const char *salt;
        int             unipwLen;
        static char     *magic = "$3$";
        static char     passwd[120];
        u_int16_t       unipw[128];
        u_char          final[32 + 1];
        const char      *s;
        MD4_CTX ctx;
    /* convert to unicode (thanx Archie) */
        for (unipwLen = 0, s = pw; unipwLen < sizeof(unipw) / 2 && *s; s++)
                unipw[unipwLen++] = htons(*s << 8);
    /* Compute MD4 of Unicode password */
        MD4Update(&ctx, (u_char *) unipw, unipwLen * sizeof(*unipw));
        MD4End(&ctx, final);  

        strcpy(passwd, magic);
        strcat(passwd, "$");
        strncat(passwd, final, 32);

        /* Don't leave anything around in vm they could use. */
        memset(final, 0, sizeof final);

        return passwd;

        char *pw;

        pw = crypt_nthash("MyPw", "");
        printf("NT-Hash: %s\n", pw);
        printf("Expected:%s\n", "$3$$FC156AF7EDCD6C0EDDE3337D427F4EAC");
        exit (0);

Reply via email to