/* $OpenLDAP$ */
/*
- * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/string.h>
+#include <ac/unistd.h>
+
+#ifdef SLAPD_LMHASH
+# include <openssl/des.h>
+#endif /* SLAPD_LMHASH */
#ifdef SLAPD_SPASSWD
# include <sasl.h>
#include <ac/param.h>
-#include <ac/unistd.h>
-#include <ac/crypt.h>
+#ifdef SLAPD_CRYPT
+# include <ac/crypt.h>
-#ifdef HAVE_SHADOW_H
+# if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
+# ifdef HAVE_SHADOW_H
# include <shadow.h>
-#endif
-#ifdef HAVE_PWD_H
+# endif
+# ifdef HAVE_PWD_H
# include <pwd.h>
-#endif
-#ifdef HAVE_AIX_SECURITY
+# endif
+# ifdef HAVE_AIX_SECURITY
# include <userpw.h>
+# endif
+# endif
#endif
#include <lber.h>
+#include "ldap_pvt.h"
+
#include "lutil_md5.h"
#include "lutil_sha1.h"
#include "lutil.h"
static const unsigned char crypt64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
+#ifdef SLAPD_CRYPT
+static char *salt_format = NULL;
+#endif
+
struct pw_scheme;
typedef int (*PASSWD_CHK_FUNC)(
const struct berval *passwd,
const struct berval *cred );
+#ifdef LUTIL_SHA1_BYTES
static int chk_ssha1(
const struct pw_scheme *scheme,
const struct berval *passwd,
const struct pw_scheme *scheme,
const struct berval *passwd,
const struct berval *cred );
+#endif
+
+#ifdef SLAPD_LMHASH
+static int chk_lanman(
+ const struct pw_scheme *scheme,
+ const struct berval *passwd,
+ const struct berval *cred );
+#endif
#ifdef SLAPD_SPASSWD
static int chk_sasl(
const struct berval *passwd,
const struct berval *cred );
-#if defined( HAVE_GETSPNAM ) \
- || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
+#if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
static int chk_unix(
const struct pw_scheme *scheme,
const struct berval *passwd,
#endif
+#ifdef LUTIL_SHA1_BYTES
/* password hash routines */
static struct berval *hash_sha1(
const struct pw_scheme *scheme,
static struct berval *hash_ssha1(
const struct pw_scheme *scheme,
const struct berval *passwd );
+#endif
static struct berval *hash_smd5(
const struct pw_scheme *scheme,
const struct pw_scheme *scheme,
const struct berval *passwd );
+#ifdef SLAPD_LMHASH
+static struct berval *hash_lanman(
+ const struct pw_scheme *scheme,
+ const struct berval *passwd );
+#endif
+
#ifdef SLAPD_CRYPT
static struct berval *hash_crypt(
const struct pw_scheme *scheme,
static const struct pw_scheme pw_schemes[] =
{
+#ifdef LUTIL_SHA1_BYTES
{ {sizeof("{SSHA}")-1, "{SSHA}"}, chk_ssha1, hash_ssha1 },
{ {sizeof("{SHA}")-1, "{SHA}"}, chk_sha1, hash_sha1 },
+#endif
{ {sizeof("{SMD5}")-1, "{SMD5}"}, chk_smd5, hash_smd5 },
{ {sizeof("{MD5}")-1, "{MD5}"}, chk_md5, hash_md5 },
+#ifdef SLAPD_LMHASH
+ { {sizeof("{LANMAN}")-1, "{LANMAN}"}, chk_lanman, hash_lanman },
+#endif /* SLAPD_LMHASH */
+
#ifdef SLAPD_SPASSWD
{ {sizeof("{SASL}")-1, "{SASL}"}, chk_sasl, NULL },
#endif
? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
: 1;
}
-#else
- return 1;
#endif
-
+ return 1;
}
struct berval * lutil_passwd_generate( ber_len_t len )
return (sc->hash_fn)( sc, passwd );
}
+/* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */
+#if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)
static struct berval * pw_string(
const struct pw_scheme *sc,
const struct berval *passwd )
return NULL;
}
- memcpy( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
- memcpy( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
+ AC_MEMCPY( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
+ AC_MEMCPY( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
pw->bv_val[pw->bv_len] = '\0';
return pw;
}
+#endif /* SLAPD_LMHASH || SLAPD_CRYPT */
static struct berval * pw_string64(
const struct pw_scheme *sc,
return NULL;
}
- memcpy( string.bv_val, hash->bv_val,
+ AC_MEMCPY( string.bv_val, hash->bv_val,
hash->bv_len );
- memcpy( &string.bv_val[hash->bv_len], salt->bv_val,
+ AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
salt->bv_len );
string.bv_val[string.bv_len] = '\0';
return NULL;
}
- memcpy(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
+ AC_MEMCPY(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
rc = lutil_b64_ntop(
string.bv_val, string.bv_len,
/* PASSWORD CHECK ROUTINES */
+#ifdef LUTIL_SHA1_BYTES
static int chk_ssha1(
const struct pw_scheme *sc,
const struct berval * passwd,
ber_memfree(orig_pass);
return rc ? 1 : 0;
}
+#endif
static int chk_smd5(
const struct pw_scheme *sc,
/* hash credentials with salt */
lutil_MD5Init(&MD5context);
lutil_MD5Update(&MD5context,
- (const unsigned char *) cred->bv_val, cred->bv_len );
+ (const unsigned char *) cred->bv_val,
+ cred->bv_len );
lutil_MD5Update(&MD5context,
- (const unsigned char *) &orig_pass[sizeof(MD5digest)],
+ &orig_pass[sizeof(MD5digest)],
rc - sizeof(MD5digest));
lutil_MD5Final(MD5digest, &MD5context);
/* hash credentials with salt */
lutil_MD5Init(&MD5context);
lutil_MD5Update(&MD5context,
- (const unsigned char *) cred->bv_val, cred->bv_len );
+ (const unsigned char *) cred->bv_val,
+ cred->bv_len );
lutil_MD5Final(MD5digest, &MD5context);
/* compare */
return rc ? 1 : 0;
}
+#ifdef SLAPD_LMHASH
+static int chk_lanman(
+ const struct pw_scheme *scheme,
+ const struct berval *passwd,
+ const struct berval *cred )
+{
+ struct berval *hash;
+
+ hash = hash_lanman( scheme, cred );
+ return memcmp( &hash->bv_val[scheme->name.bv_len], passwd->bv_val, 32);
+}
+#endif /* SLAPD_LMHASH */
+
#ifdef SLAPD_SPASSWD
#ifdef HAVE_CYRUS_SASL
sasl_conn_t *lutil_passwd_sasl_conn = NULL;
}
{
- char host[MAXHOSTNAMELEN];
+ char *host = ldap_pvt_get_fqdn( NULL );
- if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) {
+ if( host == NULL ) {
krb5_free_principal( context, client );
krb5_free_context( context );
return 1;
ret = krb5_sname_to_principal( context,
host, "ldap", KRB5_NT_SRV_HST, &server );
+
+ ber_memfree( host );
}
if (ret) {
krb5_free_principal( context, client );
krb5_free_principal( context, server );
- krb5_free_creds_contents( context, &creds );
+ krb5_free_cred_contents( context, &creds );
krb5_free_context( context );
rtn = !!ret;
/* PASSWORD GENERATION ROUTINES */
+#ifdef LUTIL_SHA1_BYTES
static struct berval *hash_ssha1(
const struct pw_scheme *scheme,
const struct berval *passwd )
const struct berval *passwd )
{
lutil_SHA1_CTX SHA1context;
- unsigned char SHA1digest[20];
+ unsigned char SHA1digest[LUTIL_SHA1_BYTES];
struct berval digest;
digest.bv_val = SHA1digest;
digest.bv_len = sizeof(SHA1digest);
return pw_string64( scheme, &digest, NULL);
}
+#endif
static struct berval *hash_smd5(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
lutil_MD5_CTX MD5context;
- unsigned char MD5digest[16];
+ unsigned char MD5digest[LUTIL_MD5_BYTES];
unsigned char saltdata[4];
struct berval digest;
struct berval salt;
const struct berval *passwd )
{
lutil_MD5_CTX MD5context;
- unsigned char MD5digest[16];
+ unsigned char MD5digest[LUTIL_MD5_BYTES];
struct berval digest;
;
}
+#ifdef SLAPD_LMHASH
+/* 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 unsigned char *lmPasswd,
+ des_cblock *key)
+{
+ /* make room for parity bits */
+ ((char *)key)[0] = lmPasswd[0];
+ ((char *)key)[1] = ((lmPasswd[0]&0x01)<<7) | (lmPasswd[1]>>1);
+ ((char *)key)[2] = ((lmPasswd[1]&0x03)<<6) | (lmPasswd[2]>>2);
+ ((char *)key)[3] = ((lmPasswd[2]&0x07)<<5) | (lmPasswd[3]>>3);
+ ((char *)key)[4] = ((lmPasswd[3]&0x0F)<<4) | (lmPasswd[4]>>4);
+ ((char *)key)[5] = ((lmPasswd[4]&0x1F)<<3) | (lmPasswd[5]>>5);
+ ((char *)key)[6] = ((lmPasswd[5]&0x3F)<<2) | (lmPasswd[6]>>6);
+ ((char *)key)[7] = ((lmPasswd[6]&0x7F)<<1);
+
+ des_set_odd_parity( key );
+}
+
+static struct berval *hash_lanman(
+ const struct pw_scheme *scheme,
+ const struct berval *passwd )
+{
+
+ int i;
+ char UcasePassword[15];
+ des_cblock key;
+ des_key_schedule schedule;
+ des_cblock StdText = "KGS!@#$%";
+ des_cblock hash1, hash2;
+ char lmhash[33];
+ struct berval hash;
+
+ for( i=0; i<passwd->bv_len; i++) {
+ if(passwd->bv_val[i] == '\0') {
+ return NULL; /* NUL character in password */
+ }
+ }
+
+ if( passwd->bv_val[i] != '\0' ) {
+ return NULL; /* 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, &hash1, schedule , DES_ENCRYPT );
+
+ lmPasswd_to_key( &UcasePassword[7], &key );
+ des_set_key_unchecked( &key, schedule );
+ des_ecb_encrypt( &StdText, &hash2, schedule , DES_ENCRYPT );
+
+ sprintf( lmhash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ hash1[0],hash1[1],hash1[2],hash1[3],hash1[4],hash1[5],hash1[6],hash1[7],
+ hash2[0],hash2[1],hash2[2],hash2[3],hash2[4],hash2[5],hash2[6],hash2[7] );
+
+ hash.bv_val = lmhash;
+ hash.bv_len = 32;
+
+ return pw_string( scheme, &hash );
+}
+#endif /* SLAPD_LMHASH */
+
#ifdef SLAPD_CRYPT
static struct berval *hash_crypt(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
struct berval hash;
- unsigned char salt[3];
+ unsigned char salt[32]; /* salt suitable for most anything */
int i;
for( i=0; i<passwd->bv_len; i++) {
return NULL; /* passwd must behave like a string */
}
- if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
+ if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
return NULL;
}
- salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
- salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
- salt[2] = '\0';
+ for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
+ salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
+ }
+ salt[sizeof( salt ) - 1 ] = '\0';
+
+ if( salt_format != NULL ) {
+ /* copy the salt we made into entropy before snprintfing
+ it back into the salt */
+ char entropy[sizeof(salt)];
+ strcpy( entropy, salt );
+ snprintf( salt, sizeof(entropy), salt_format, entropy );
+ }
hash.bv_val = crypt( passwd->bv_val, salt );
return pw_string( scheme, &hash );
}
#endif
+
+int lutil_salt_format(const char *format)
+{
+#ifdef SLAPD_CRYPT
+ free( salt_format );
+
+ salt_format = format != NULL ? strdup( format ) : NULL;
+#endif
+
+ return 0;
+}