Commit 6f5cc45f authored by Andrew Lawrence's avatar Andrew Lawrence Committed by Ryan Tandy
Browse files

ITS#8639 remove LANMAN hashed passwords

parent 1c05dce3
......@@ -271,7 +271,6 @@ OL_ARG_ENABLE(dynacl,[ --enable-dynacl enable run-time loadable ACL support
OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs (experimental)], no, [no yes mod])dnl
OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl
OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], no)dnl
OL_ARG_ENABLE(lmpasswd,[ --enable-lmpasswd enable LAN Manager passwords], no)dnl
OL_ARG_ENABLE(spasswd,[ --enable-spasswd enable (Cyrus) SASL password verification], no)dnl
OL_ARG_ENABLE(modules,[ --enable-modules enable dynamic module support], no)dnl
OL_ARG_ENABLE(rewrite,[ --enable-rewrite enable DN rewriting in back-ldap and rwm overlay], auto)dnl
......@@ -507,12 +506,6 @@ if test $ol_enable_asyncmeta/$ol_enable_ldap = yes/no ; then
AC_MSG_ERROR([--enable-asyncmeta requires --enable-ldap])
fi
if test $ol_enable_lmpasswd = yes ; then
if test $ol_with_tls = no ; then
AC_MSG_ERROR([LAN Manager passwords require OpenSSL])
fi
fi
if test $ol_enable_spasswd = yes ; then
if test $ol_with_cyrus_sasl = no ; then
AC_MSG_ERROR([options require --with-cyrus-sasl])
......@@ -1293,15 +1286,6 @@ else
AC_MSG_WARN([TLS data protection not supported!])
fi
dnl ----------------------------------------------------------------
dnl LAN Manger password checking requires DES from OpenSSL
if test $ol_enable_lmpasswd != no; then
if test $ol_link_tls != yes ; then
AC_MSG_ERROR([LAN Manager passwords require OpenSSL])
fi
AC_DEFINE(SLAPD_LMHASH, 1, [define to support LAN Manager passwords])
fi
dnl ----------------------------------------------------------------
dnl Threads?
......
......@@ -32,36 +32,6 @@
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/unistd.h>
#if defined(SLAPD_LMHASH)
#if defined(HAVE_OPENSSL)
# include <openssl/des.h>
typedef DES_cblock des_key;
typedef DES_cblock des_data_block;
typedef DES_key_schedule des_context[1];
#define des_failed(encrypted) 0
#define des_finish(key, schedule)
#elif defined(HAVE_MOZNSS)
/*
hack hack hack
We need to define this here so that nspr/obsolete/protypes.h will not be included
if that file is included, it will create a uint32 typedef that will cause the
one in lutil_sha1.h to blow up
*/
#define PROTYPES_H 1
# include <nss/pk11pub.h>
typedef PK11SymKey *des_key;
typedef unsigned char des_data_block[8];
typedef PK11Context *des_context[1];
#define DES_ENCRYPT CKA_ENCRYPT
#endif
#endif /* SLAPD_LMHASH */
#include <ac/param.h>
#ifdef SLAPD_CRYPT
......@@ -130,10 +100,6 @@ static LUTIL_PASSWD_HASH_FUNC hash_sha1;
static LUTIL_PASSWD_HASH_FUNC hash_ssha1;
#endif
#ifdef SLAPD_LMHASH
static LUTIL_PASSWD_CHK_FUNC chk_lanman;
static LUTIL_PASSWD_HASH_FUNC hash_lanman;
#endif
#ifdef SLAPD_CRYPT
static LUTIL_PASSWD_CHK_FUNC chk_crypt;
......@@ -163,10 +129,6 @@ static const struct pw_scheme pw_schemes_default[] =
{ BER_BVC("{SMD5}"), chk_smd5, hash_smd5 },
{ BER_BVC("{MD5}"), chk_md5, hash_md5 },
#ifdef SLAPD_LMHASH
{ BER_BVC("{LANMAN}"), chk_lanman, hash_lanman },
#endif /* SLAPD_LMHASH */
#ifdef SLAPD_CRYPT
{ BER_BVC("{CRYPT}"), chk_crypt, hash_crypt },
# if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
......@@ -399,8 +361,8 @@ int lutil_passwd_hash(
return (sc->hash_fn)( &sc->name, passwd, hash, text );
}
/* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */
#if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)
/* pw_string is only called when SLAPD_CRYPT is defined */
#if defined(SLAPD_CRYPT)
static int pw_string(
const struct berval *sc,
struct berval *passwd )
......@@ -422,7 +384,7 @@ static int pw_string(
return LUTIL_PASSWD_OK;
}
#endif /* SLAPD_LMHASH || SLAPD_CRYPT */
#endif /* SLAPD_CRYPT */
int lutil_passwd_string64(
const struct berval *sc,
......@@ -656,245 +618,6 @@ static int chk_md5(
return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
}
#ifdef SLAPD_LMHASH
#if defined(HAVE_OPENSSL)
/*
* abstract away setting the parity.
*/
static void
des_set_key_and_parity( des_key *key, unsigned char *keyData)
{
memcpy(key, keyData, 8);
DES_set_odd_parity( key );
}
#elif defined(HAVE_MOZNSS)
/*
* implement MozNSS wrappers for the openSSL calls
*/
static void
des_set_key_and_parity( des_key *key, unsigned char *keyData)
{
SECItem keyDataItem;
PK11SlotInfo *slot;
*key = NULL;
keyDataItem.data = keyData;
keyDataItem.len = 8;
slot = PK11_GetBestSlot(CKM_DES_ECB, NULL);
if (slot == NULL) {
return;
}
/* NOTE: this will not work in FIPS mode. In order to make lmhash
* work in fips mode we need to define a LMHASH pbe mechanism and
* do the fulll key derivation inside the token */
*key = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginGenerated,
CKA_ENCRYPT, &keyDataItem, NULL);
}
static void
DES_set_key_unchecked( des_key *key, des_context ctxt )
{
ctxt[0] = NULL;
/* handle error conditions from previous call */
if (!*key) {
return;
}
ctxt[0] = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, *key, NULL);
}
static void
DES_ecb_encrypt( des_data_block *plain, des_data_block *encrypted,
des_context ctxt, int op)
{
SECStatus rv;
int size;
if (ctxt[0] == NULL) {
/* need to fail here... */
memset(encrypted, 0, sizeof(des_data_block));
return;
}
rv = PK11_CipherOp(ctxt[0], (unsigned char *)&encrypted[0],
&size, sizeof(des_data_block),
(unsigned char *)&plain[0], sizeof(des_data_block));
if (rv != SECSuccess) {
/* signal failure */
memset(encrypted, 0, sizeof(des_data_block));
return;
}
return;
}
static int
des_failed(des_data_block *encrypted)
{
static const des_data_block zero = { 0 };
return memcmp(encrypted, zero, sizeof(zero)) == 0;
}
static void
des_finish(des_key *key, des_context ctxt)
{
if (*key) {
PK11_FreeSymKey(*key);
*key = NULL;
}
if (ctxt[0]) {
PK11_Finalize(ctxt[0]);
PK11_DestroyContext(ctxt[0], PR_TRUE);
ctxt[0] = NULL;
}
}
#endif
/* pseudocode from RFC2433
* A.2 LmPasswordHash()
*
* LmPasswordHash(
* IN 0-to-14-oem-char Password,
* OUT 16-octet PasswordHash )
* {
* Set UcasePassword to the uppercased Password
* Zero pad UcasePassword to 14 characters
*
* DesHash( 1st 7-octets of UcasePassword,
* giving 1st 8-octets of PasswordHash )
*
* DesHash( 2nd 7-octets of UcasePassword,
* giving 2nd 8-octets of PasswordHash )
* }
*
*
* A.3 DesHash()
*
* DesHash(
* IN 7-octet Clear,
* OUT 8-octet Cypher )
* {
* *
* * Make Cypher an irreversibly encrypted form of Clear by
* * encrypting known text using Clear as the secret key.
* * The known text consists of the string
* *
* * KGS!@#$%
* *
*
* Set StdText to "KGS!@#$%"
* DesEncrypt( StdText, Clear, giving Cypher )
* }
*
*
* A.4 DesEncrypt()
*
* DesEncrypt(
* IN 8-octet Clear,
* IN 7-octet Key,
* OUT 8-octet Cypher )
* {
* *
* * Use the DES encryption algorithm [4] in ECB mode [9]
* * to encrypt Clear into Cypher such that Cypher can
* * only be decrypted back to Clear by providing Key.
* * Note that the DES algorithm takes as input a 64-bit
* * stream where the 8th, 16th, 24th, etc. bits are
* * parity bits ignored by the encrypting algorithm.
* * Unless you write your own DES to accept 56-bit input
* * without parity, you will need to insert the parity bits
* * yourself.
* *
* }
*/
static void lmPasswd_to_key(
const char *lmPasswd,
des_key *key)
{
const unsigned char *lpw = (const unsigned char *) lmPasswd;
unsigned char k[8];
/* make room for parity bits */
k[0] = lpw[0];
k[1] = ((lpw[0] & 0x01) << 7) | (lpw[1] >> 1);
k[2] = ((lpw[1] & 0x03) << 6) | (lpw[2] >> 2);
k[3] = ((lpw[2] & 0x07) << 5) | (lpw[3] >> 3);
k[4] = ((lpw[3] & 0x0F) << 4) | (lpw[4] >> 4);
k[5] = ((lpw[4] & 0x1F) << 3) | (lpw[5] >> 5);
k[6] = ((lpw[5] & 0x3F) << 2) | (lpw[6] >> 6);
k[7] = ((lpw[6] & 0x7F) << 1);
des_set_key_and_parity( key, k );
}
static int chk_lanman(
const struct berval *scheme,
const struct berval *passwd,
const struct berval *cred,
const char **text )
{
ber_len_t i;
char UcasePassword[15];
des_key key;
des_context schedule;
des_data_block StdText = "KGS!@#$%";
des_data_block PasswordHash1, PasswordHash2;
char PasswordHash[33], storedPasswordHash[33];
for( i=0; i<cred->bv_len; i++) {
if(cred->bv_val[i] == '\0') {
return LUTIL_PASSWD_ERR; /* NUL character in password */
}
}
if( cred->bv_val[i] != '\0' ) {
return LUTIL_PASSWD_ERR; /* passwd must behave like a string */
}
strncpy( UcasePassword, cred->bv_val, 14 );
UcasePassword[14] = '\0';
ldap_pvt_str2upper( UcasePassword );
lmPasswd_to_key( UcasePassword, &key );
DES_set_key_unchecked( &key, schedule );
DES_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
if (des_failed(&PasswordHash1)) {
return LUTIL_PASSWD_ERR;
}
lmPasswd_to_key( &UcasePassword[7], &key );
DES_set_key_unchecked( &key, schedule );
DES_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
if (des_failed(&PasswordHash2)) {
return LUTIL_PASSWD_ERR;
}
des_finish( &key, schedule );
sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
/* as a precaution convert stored password hash to lower case */
strncpy( storedPasswordHash, passwd->bv_val, 32 );
storedPasswordHash[32] = '\0';
ldap_pvt_str2lower( storedPasswordHash );
return memcmp( PasswordHash, storedPasswordHash, 32) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
}
#endif /* SLAPD_LMHASH */
#ifdef SLAPD_CRYPT
static int lutil_crypt(
const char *key,
......@@ -1129,57 +852,6 @@ static int hash_md5(
;
}
#ifdef SLAPD_LMHASH
static int hash_lanman(
const struct berval *scheme,
const struct berval *passwd,
struct berval *hash,
const char **text )
{
ber_len_t i;
char UcasePassword[15];
des_key key;
des_context schedule;
des_data_block StdText = "KGS!@#$%";
des_data_block PasswordHash1, PasswordHash2;
char PasswordHash[33];
for( i=0; i<passwd->bv_len; i++) {
if(passwd->bv_val[i] == '\0') {
return LUTIL_PASSWD_ERR; /* NUL character in password */
}
}
if( passwd->bv_val[i] != '\0' ) {
return LUTIL_PASSWD_ERR; /* passwd must behave like a string */
}
strncpy( UcasePassword, passwd->bv_val, 14 );
UcasePassword[14] = '\0';
ldap_pvt_str2upper( UcasePassword );
lmPasswd_to_key( UcasePassword, &key );
DES_set_key_unchecked( &key, schedule );
DES_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
lmPasswd_to_key( &UcasePassword[7], &key );
DES_set_key_unchecked( &key, schedule );
DES_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
hash->bv_val = PasswordHash;
hash->bv_len = 32;
return pw_string( scheme, hash );
}
#endif /* SLAPD_LMHASH */
#ifdef SLAPD_CRYPT
static int hash_crypt(
const struct berval *scheme,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment