Back to index

openldap  2.4.31
passwd.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 
00016 /*
00017  * int lutil_passwd(
00018  *     const struct berval *passwd,
00019  *     const struct berval *cred,
00020  *     const char **schemes )
00021  *
00022  * Returns true if user supplied credentials (cred) matches
00023  * the stored password (passwd). 
00024  *
00025  * Due to the use of the crypt(3) function 
00026  * this routine is NOT thread-safe.
00027  */
00028 
00029 #include "portable.h"
00030 
00031 #include <stdio.h>
00032 #include <ac/stdlib.h>
00033 #include <ac/string.h>
00034 #include <ac/unistd.h>
00035 
00036 #if defined(SLAPD_LMHASH)
00037 #if defined(HAVE_OPENSSL)
00038 #      include <openssl/des.h>
00039 
00040 
00041 typedef des_cblock des_key;
00042 typedef des_cblock des_data_block;
00043 typedef des_key_schedule des_context;
00044 #define des_failed(encrypted) 0
00045 #define des_finish(key, schedule) 
00046 
00047 #elif defined(HAVE_MOZNSS)
00048 /*
00049   hack hack hack
00050   We need to define this here so that nspr/obsolete/protypes.h will not be included
00051   if that file is included, it will create a uint32 typedef that will cause the
00052   one in lutil_sha1.h to blow up
00053 */
00054 #define PROTYPES_H 1
00055 #      include <nss/pk11pub.h>
00056 typedef PK11SymKey *des_key;
00057 typedef unsigned char des_data_block[8];
00058 typedef PK11Context *des_context[1];
00059 #define DES_ENCRYPT CKA_ENCRYPT
00060 
00061 #endif
00062 
00063 #endif /* SLAPD_LMHASH */
00064 
00065 #include <ac/param.h>
00066 
00067 #ifdef SLAPD_CRYPT
00068 # include <ac/crypt.h>
00069 
00070 # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
00071 #  ifdef HAVE_SHADOW_H
00072 #      include <shadow.h>
00073 #  endif
00074 #  ifdef HAVE_PWD_H
00075 #      include <pwd.h>
00076 #  endif
00077 #  ifdef HAVE_AIX_SECURITY
00078 #      include <userpw.h>
00079 #  endif
00080 # endif
00081 #endif
00082 
00083 #include <lber.h>
00084 
00085 #include "ldap_pvt.h"
00086 #include "lber_pvt.h"
00087 
00088 #include "lutil_md5.h"
00089 #include "lutil_sha1.h"
00090 #include "lutil.h"
00091 
00092 static const unsigned char crypt64[] =
00093        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
00094 
00095 #ifdef SLAPD_CRYPT
00096 static char *salt_format = NULL;
00097 static lutil_cryptfunc lutil_crypt;
00098 lutil_cryptfunc *lutil_cryptptr = lutil_crypt;
00099 #endif
00100 
00101 /* KLUDGE:
00102  *  chk_fn is NULL iff name is {CLEARTEXT}
00103  *     otherwise, things will break
00104  */
00105 struct pw_scheme {
00106        struct berval name;
00107        LUTIL_PASSWD_CHK_FUNC *chk_fn;
00108        LUTIL_PASSWD_HASH_FUNC *hash_fn;
00109 };
00110 
00111 struct pw_slist {
00112        struct pw_slist *next;
00113        struct pw_scheme s;
00114 };
00115 
00116 /* password check routines */
00117 
00118 #define       SALT_SIZE     4
00119 
00120 static LUTIL_PASSWD_CHK_FUNC chk_md5;
00121 static LUTIL_PASSWD_CHK_FUNC chk_smd5;
00122 static LUTIL_PASSWD_HASH_FUNC hash_smd5;
00123 static LUTIL_PASSWD_HASH_FUNC hash_md5;
00124 
00125 
00126 #ifdef LUTIL_SHA1_BYTES
00127 static LUTIL_PASSWD_CHK_FUNC chk_ssha1;
00128 static LUTIL_PASSWD_CHK_FUNC chk_sha1;
00129 static LUTIL_PASSWD_HASH_FUNC hash_sha1;
00130 static LUTIL_PASSWD_HASH_FUNC hash_ssha1;
00131 #endif
00132 
00133 #ifdef SLAPD_LMHASH
00134 static LUTIL_PASSWD_CHK_FUNC chk_lanman;
00135 static LUTIL_PASSWD_HASH_FUNC hash_lanman;
00136 #endif
00137 
00138 #ifdef SLAPD_CRYPT
00139 static LUTIL_PASSWD_CHK_FUNC chk_crypt;
00140 static LUTIL_PASSWD_HASH_FUNC hash_crypt;
00141 
00142 #if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
00143 static LUTIL_PASSWD_CHK_FUNC chk_unix;
00144 #endif
00145 #endif
00146 
00147 /* password hash routines */
00148 
00149 #ifdef SLAPD_CLEARTEXT
00150 static LUTIL_PASSWD_HASH_FUNC hash_clear;
00151 #endif
00152 
00153 static struct pw_slist *pw_schemes;
00154 static int pw_inited;
00155 
00156 static const struct pw_scheme pw_schemes_default[] =
00157 {
00158 #ifdef LUTIL_SHA1_BYTES
00159        { BER_BVC("{SSHA}"),        chk_ssha1, hash_ssha1 },
00160        { BER_BVC("{SHA}"),                chk_sha1, hash_sha1 },
00161 #endif
00162 
00163        { BER_BVC("{SMD5}"),        chk_smd5, hash_smd5 },
00164        { BER_BVC("{MD5}"),                chk_md5, hash_md5 },
00165 
00166 #ifdef SLAPD_LMHASH
00167        { BER_BVC("{LANMAN}"),             chk_lanman, hash_lanman },
00168 #endif /* SLAPD_LMHASH */
00169 
00170 #ifdef SLAPD_CRYPT
00171        { BER_BVC("{CRYPT}"),              chk_crypt, hash_crypt },
00172 # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
00173        { BER_BVC("{UNIX}"),        chk_unix, NULL },
00174 # endif
00175 #endif
00176 
00177 #ifdef SLAPD_CLEARTEXT
00178        /* pseudo scheme */
00179        { BER_BVC("{CLEARTEXT}"),   NULL, hash_clear },
00180 #endif
00181 
00182        { BER_BVNULL, NULL, NULL }
00183 };
00184 
00185 int lutil_passwd_add(
00186        struct berval *scheme,
00187        LUTIL_PASSWD_CHK_FUNC *chk,
00188        LUTIL_PASSWD_HASH_FUNC *hash )
00189 {
00190        struct pw_slist *ptr;
00191 
00192        if (!pw_inited) lutil_passwd_init();
00193 
00194        ptr = ber_memalloc( sizeof( struct pw_slist ));
00195        if (!ptr) return -1;
00196        ptr->next = pw_schemes;
00197        ptr->s.name = *scheme;
00198        ptr->s.chk_fn = chk;
00199        ptr->s.hash_fn = hash;
00200        pw_schemes = ptr;
00201        return 0;
00202 }
00203 
00204 void lutil_passwd_init()
00205 {
00206        struct pw_scheme *s;
00207 
00208        pw_inited = 1;
00209 
00210        for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) {
00211               if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn ) ) break;
00212        }
00213 }
00214 
00215 void lutil_passwd_destroy()
00216 {
00217        struct pw_slist *ptr, *next;
00218 
00219        for( ptr=pw_schemes; ptr; ptr=next ) {
00220               next = ptr->next;
00221               ber_memfree( ptr );
00222        }
00223 }
00224 
00225 static const struct pw_scheme *get_scheme(
00226        const char* scheme )
00227 {
00228        struct pw_slist *pws;
00229        struct berval bv;
00230 
00231        if (!pw_inited) lutil_passwd_init();
00232 
00233        bv.bv_val = strchr( scheme, '}' );
00234        if ( !bv.bv_val )
00235               return NULL;
00236 
00237        bv.bv_len = bv.bv_val - scheme + 1;
00238        bv.bv_val = (char *) scheme;
00239 
00240        for( pws=pw_schemes; pws; pws=pws->next ) {
00241               if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) {
00242                      return &(pws->s);
00243               }
00244        }
00245 
00246        return NULL;
00247 }
00248 
00249 int lutil_passwd_scheme(
00250        const char* scheme )
00251 {
00252        if( scheme == NULL ) {
00253               return 0;
00254        }
00255 
00256        return get_scheme(scheme) != NULL;
00257 }
00258 
00259 
00260 static int is_allowed_scheme( 
00261        const char* scheme,
00262        const char** schemes )
00263 {
00264        int i;
00265 
00266        if( schemes == NULL ) return 1;
00267 
00268        for( i=0; schemes[i] != NULL; i++ ) {
00269               if( strcasecmp( scheme, schemes[i] ) == 0 ) {
00270                      return 1;
00271               }
00272        }
00273        return 0;
00274 }
00275 
00276 static struct berval *passwd_scheme(
00277        const struct pw_scheme *scheme,
00278        const struct berval * passwd,
00279        struct berval *bv,
00280        const char** allowed )
00281 {
00282        if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
00283               return NULL;
00284        }
00285 
00286        if( passwd->bv_len >= scheme->name.bv_len ) {
00287               if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
00288                      bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
00289                      bv->bv_len = passwd->bv_len - scheme->name.bv_len;
00290 
00291                      return bv;
00292               }
00293        }
00294 
00295        return NULL;
00296 }
00297 
00298 /*
00299  * Return 0 if creds are good.
00300  */
00301 int
00302 lutil_passwd(
00303        const struct berval *passwd,       /* stored passwd */
00304        const struct berval *cred,         /* user cred */
00305        const char **schemes,
00306        const char **text )
00307 {
00308        struct pw_slist *pws;
00309 
00310        if ( text ) *text = NULL;
00311 
00312        if (cred == NULL || cred->bv_len == 0 ||
00313               passwd == NULL || passwd->bv_len == 0 )
00314        {
00315               return -1;
00316        }
00317 
00318        if (!pw_inited) lutil_passwd_init();
00319 
00320        for( pws=pw_schemes; pws; pws=pws->next ) {
00321               if( pws->s.chk_fn ) {
00322                      struct berval x;
00323                      struct berval *p = passwd_scheme( &(pws->s),
00324                             passwd, &x, schemes );
00325 
00326                      if( p != NULL ) {
00327                             return (pws->s.chk_fn)( &(pws->s.name), p, cred, text );
00328                      }
00329               }
00330        }
00331 
00332 #ifdef SLAPD_CLEARTEXT
00333        /* Do we think there is a scheme specifier here that we
00334         * didn't recognize? Assume a scheme name is at least 1 character.
00335         */
00336        if (( passwd->bv_val[0] == '{' ) &&
00337               ( ber_bvchr( passwd, '}' ) > passwd->bv_val+1 ))
00338        {
00339               return 1;
00340        }
00341        if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
00342               return ( passwd->bv_len == cred->bv_len ) ?
00343                      memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
00344                      : 1;
00345        }
00346 #endif
00347        return 1;
00348 }
00349 
00350 int lutil_passwd_generate( struct berval *pw, ber_len_t len )
00351 {
00352 
00353        if( len < 1 ) return -1;
00354 
00355        pw->bv_len = len;
00356        pw->bv_val = ber_memalloc( len + 1 );
00357 
00358        if( pw->bv_val == NULL ) {
00359               return -1;
00360        }
00361 
00362        if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) {
00363               return -1; 
00364        }
00365 
00366        for( len = 0; len < pw->bv_len; len++ ) {
00367               pw->bv_val[len] = crypt64[
00368                      pw->bv_val[len] % (sizeof(crypt64)-1) ];
00369        }
00370 
00371        pw->bv_val[len] = '\0';
00372        
00373        return 0;
00374 }
00375 
00376 int lutil_passwd_hash(
00377        const struct berval * passwd,
00378        const char * method,
00379        struct berval *hash,
00380        const char **text )
00381 {
00382        const struct pw_scheme *sc = get_scheme( method );
00383 
00384        hash->bv_val = NULL;
00385        hash->bv_len = 0;
00386 
00387        if( sc == NULL ) {
00388               if( text ) *text = "scheme not recognized";
00389               return -1;
00390        }
00391 
00392        if( ! sc->hash_fn ) {
00393               if( text ) *text = "scheme provided no hash function";
00394               return -1;
00395        }
00396 
00397        if( text ) *text = NULL;
00398 
00399        return (sc->hash_fn)( &sc->name, passwd, hash, text );
00400 }
00401 
00402 /* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */
00403 #if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)
00404 static int pw_string(
00405        const struct berval *sc,
00406        struct berval *passwd )
00407 {
00408        struct berval pw;
00409 
00410        pw.bv_len = sc->bv_len + passwd->bv_len;
00411        pw.bv_val = ber_memalloc( pw.bv_len + 1 );
00412 
00413        if( pw.bv_val == NULL ) {
00414               return LUTIL_PASSWD_ERR;
00415        }
00416 
00417        AC_MEMCPY( pw.bv_val, sc->bv_val, sc->bv_len );
00418        AC_MEMCPY( &pw.bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len );
00419 
00420        pw.bv_val[pw.bv_len] = '\0';
00421        *passwd = pw;
00422 
00423        return LUTIL_PASSWD_OK;
00424 }
00425 #endif /* SLAPD_LMHASH || SLAPD_CRYPT */
00426 
00427 int lutil_passwd_string64(
00428        const struct berval *sc,
00429        const struct berval *hash,
00430        struct berval *b64,
00431        const struct berval *salt )
00432 {
00433        int rc;
00434        struct berval string;
00435        size_t b64len;
00436 
00437        if( salt ) {
00438               /* need to base64 combined string */
00439               string.bv_len = hash->bv_len + salt->bv_len;
00440               string.bv_val = ber_memalloc( string.bv_len + 1 );
00441 
00442               if( string.bv_val == NULL ) {
00443                      return LUTIL_PASSWD_ERR;
00444               }
00445 
00446               AC_MEMCPY( string.bv_val, hash->bv_val,
00447                      hash->bv_len );
00448               AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
00449                      salt->bv_len );
00450               string.bv_val[string.bv_len] = '\0';
00451 
00452        } else {
00453               string = *hash;
00454        }
00455 
00456        b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
00457        b64->bv_len = b64len + sc->bv_len;
00458        b64->bv_val = ber_memalloc( b64->bv_len + 1 );
00459 
00460        if( b64->bv_val == NULL ) {
00461               if( salt ) ber_memfree( string.bv_val );
00462               return LUTIL_PASSWD_ERR;
00463        }
00464 
00465        AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
00466 
00467        rc = lutil_b64_ntop(
00468               (unsigned char *) string.bv_val, string.bv_len,
00469               &b64->bv_val[sc->bv_len], b64len );
00470 
00471        if( salt ) ber_memfree( string.bv_val );
00472        
00473        if( rc < 0 ) {
00474               return LUTIL_PASSWD_ERR;
00475        }
00476 
00477        /* recompute length */
00478        b64->bv_len = sc->bv_len + rc;
00479        assert( strlen(b64->bv_val) == b64->bv_len );
00480        return LUTIL_PASSWD_OK;
00481 }
00482 
00483 /* PASSWORD CHECK ROUTINES */
00484 
00485 #ifdef LUTIL_SHA1_BYTES
00486 static int chk_ssha1(
00487        const struct berval *sc,
00488        const struct berval * passwd,
00489        const struct berval * cred,
00490        const char **text )
00491 {
00492        lutil_SHA1_CTX SHA1context;
00493        unsigned char SHA1digest[LUTIL_SHA1_BYTES];
00494        int rc;
00495        unsigned char *orig_pass = NULL;
00496 
00497        /* safety check -- must have some salt */
00498        if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <= sizeof(SHA1digest)) {
00499               return LUTIL_PASSWD_ERR;
00500        }
00501 
00502        /* decode base64 password */
00503        orig_pass = (unsigned char *) ber_memalloc( (size_t) (
00504               LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
00505 
00506        if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
00507 
00508        rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
00509 
00510        /* safety check -- must have some salt */
00511        if (rc <= (int)(sizeof(SHA1digest))) {
00512               ber_memfree(orig_pass);
00513               return LUTIL_PASSWD_ERR;
00514        }
00515  
00516        /* hash credentials with salt */
00517        lutil_SHA1Init(&SHA1context);
00518        lutil_SHA1Update(&SHA1context,
00519               (const unsigned char *) cred->bv_val, cred->bv_len);
00520        lutil_SHA1Update(&SHA1context,
00521               (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
00522               rc - sizeof(SHA1digest));
00523        lutil_SHA1Final(SHA1digest, &SHA1context);
00524  
00525        /* compare */
00526        rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
00527        ber_memfree(orig_pass);
00528        return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
00529 }
00530 
00531 static int chk_sha1(
00532        const struct berval *sc,
00533        const struct berval * passwd,
00534        const struct berval * cred,
00535        const char **text )
00536 {
00537        lutil_SHA1_CTX SHA1context;
00538        unsigned char SHA1digest[LUTIL_SHA1_BYTES];
00539        int rc;
00540        unsigned char *orig_pass = NULL;
00541  
00542        /* safety check */
00543        if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) < sizeof(SHA1digest)) {
00544               return LUTIL_PASSWD_ERR;
00545        }
00546 
00547        /* base64 un-encode password */
00548        orig_pass = (unsigned char *) ber_memalloc( (size_t) (
00549               LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
00550 
00551        if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
00552 
00553        rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
00554 
00555        if( rc != sizeof(SHA1digest) ) {
00556               ber_memfree(orig_pass);
00557               return LUTIL_PASSWD_ERR;
00558        }
00559  
00560        /* hash credentials with salt */
00561        lutil_SHA1Init(&SHA1context);
00562        lutil_SHA1Update(&SHA1context,
00563               (const unsigned char *) cred->bv_val, cred->bv_len);
00564        lutil_SHA1Final(SHA1digest, &SHA1context);
00565  
00566        /* compare */
00567        rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
00568        ber_memfree(orig_pass);
00569        return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
00570 }
00571 #endif
00572 
00573 static int chk_smd5(
00574        const struct berval *sc,
00575        const struct berval * passwd,
00576        const struct berval * cred,
00577        const char **text )
00578 {
00579        lutil_MD5_CTX MD5context;
00580        unsigned char MD5digest[LUTIL_MD5_BYTES];
00581        int rc;
00582        unsigned char *orig_pass = NULL;
00583 
00584        /* safety check */
00585        if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <= sizeof(MD5digest)) {
00586               return LUTIL_PASSWD_ERR;
00587        }
00588 
00589        /* base64 un-encode password */
00590        orig_pass = (unsigned char *) ber_memalloc( (size_t) (
00591               LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
00592 
00593        if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
00594 
00595        rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
00596 
00597        if (rc <= (int)(sizeof(MD5digest))) {
00598               ber_memfree(orig_pass);
00599               return LUTIL_PASSWD_ERR;
00600        }
00601 
00602        /* hash credentials with salt */
00603        lutil_MD5Init(&MD5context);
00604        lutil_MD5Update(&MD5context,
00605               (const unsigned char *) cred->bv_val,
00606               cred->bv_len );
00607        lutil_MD5Update(&MD5context,
00608               &orig_pass[sizeof(MD5digest)],
00609               rc - sizeof(MD5digest));
00610        lutil_MD5Final(MD5digest, &MD5context);
00611 
00612        /* compare */
00613        rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
00614        ber_memfree(orig_pass);
00615        return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
00616 }
00617 
00618 static int chk_md5(
00619        const struct berval *sc,
00620        const struct berval * passwd,
00621        const struct berval * cred,
00622        const char **text )
00623 {
00624        lutil_MD5_CTX MD5context;
00625        unsigned char MD5digest[LUTIL_MD5_BYTES];
00626        int rc;
00627        unsigned char *orig_pass = NULL;
00628 
00629        /* safety check */
00630        if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) < sizeof(MD5digest)) {
00631               return LUTIL_PASSWD_ERR;
00632        }
00633 
00634        /* base64 un-encode password */
00635        orig_pass = (unsigned char *) ber_memalloc( (size_t) (
00636               LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
00637 
00638        if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
00639 
00640        rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
00641        if ( rc != sizeof(MD5digest) ) {
00642               ber_memfree(orig_pass);
00643               return LUTIL_PASSWD_ERR;
00644        }
00645 
00646        /* hash credentials with salt */
00647        lutil_MD5Init(&MD5context);
00648        lutil_MD5Update(&MD5context,
00649               (const unsigned char *) cred->bv_val,
00650               cred->bv_len );
00651        lutil_MD5Final(MD5digest, &MD5context);
00652 
00653        /* compare */
00654        rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
00655        ber_memfree(orig_pass);
00656        return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
00657 }
00658 
00659 #ifdef SLAPD_LMHASH
00660 
00661 #if defined(HAVE_OPENSSL)
00662 
00663 /*
00664  * abstract away setting the parity.
00665  */
00666 static void
00667 des_set_key_and_parity( des_key *key, unsigned char *keyData)
00668 {
00669     memcpy(key, keyData, 8);
00670     des_set_odd_parity( key );
00671 }
00672 
00673 
00674 #elif defined(HAVE_MOZNSS)
00675 
00676 /*
00677  * implement MozNSS wrappers for the openSSL calls 
00678  */
00679 static void
00680 des_set_key_and_parity( des_key *key, unsigned char *keyData)
00681 {
00682     SECItem keyDataItem;
00683     PK11SlotInfo *slot;
00684     *key = NULL;
00685 
00686     keyDataItem.data = keyData;
00687     keyDataItem.len = 8;
00688 
00689     slot = PK11_GetBestSlot(CKM_DES_ECB, NULL);
00690     if (slot == NULL) {
00691        return;
00692     }
00693 
00694     /* NOTE: this will not work in FIPS mode. In order to make lmhash
00695      * work in fips mode we need to define a LMHASH pbe mechanism and
00696      * do the fulll key derivation inside the token */
00697     *key = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginGenerated, 
00698               CKA_ENCRYPT, &keyDataItem, NULL);
00699 }
00700 
00701 static void
00702 des_set_key_unchecked( des_key *key, des_context ctxt )
00703 {
00704     ctxt[0] = NULL;
00705 
00706     /* handle error conditions from previous call */
00707     if (!*key) {
00708        return;
00709     }
00710 
00711     ctxt[0] = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, *key, NULL);
00712 }
00713 
00714 static void
00715 des_ecb_encrypt( des_data_block *plain, des_data_block *encrypted, 
00716                      des_context ctxt, int op)
00717 {
00718     SECStatus rv;
00719     int size;
00720 
00721     if (ctxt[0] == NULL) {
00722        /* need to fail here...  */
00723        memset(encrypted, 0, sizeof(des_data_block));
00724        return;
00725     }
00726     rv = PK11_CipherOp(ctxt[0], (unsigned char *)&encrypted[0], 
00727                      &size, sizeof(des_data_block),
00728                      (unsigned char *)&plain[0], sizeof(des_data_block));
00729     if (rv != SECSuccess) {
00730        /* signal failure */
00731        memset(encrypted, 0, sizeof(des_data_block));
00732        return;
00733     }
00734     return;
00735 }
00736 
00737 static int
00738 des_failed(des_data_block *encrypted)
00739 {
00740    static const des_data_block zero = { 0 };
00741    return memcmp(encrypted, zero, sizeof(zero)) == 0;
00742 }
00743 
00744 static void
00745 des_finish(des_key *key, des_context ctxt)
00746 {
00747      if (*key) {
00748        PK11_FreeSymKey(*key);
00749        *key = NULL;
00750      }
00751      if (ctxt[0]) {
00752        PK11_Finalize(ctxt[0]);
00753        PK11_DestroyContext(ctxt[0], PR_TRUE);
00754        ctxt[0] = NULL;
00755      }
00756 }
00757 
00758 #endif
00759 
00760 /* pseudocode from RFC2433
00761  * A.2 LmPasswordHash()
00762  * 
00763  *    LmPasswordHash(
00764  *    IN  0-to-14-oem-char Password,
00765  *    OUT 16-octet         PasswordHash )
00766  *    {
00767  *       Set UcasePassword to the uppercased Password
00768  *       Zero pad UcasePassword to 14 characters
00769  * 
00770  *       DesHash( 1st 7-octets of UcasePassword,
00771  *                giving 1st 8-octets of PasswordHash )
00772  * 
00773  *       DesHash( 2nd 7-octets of UcasePassword,
00774  *                giving 2nd 8-octets of PasswordHash )
00775  *    }
00776  * 
00777  * 
00778  * A.3 DesHash()
00779  * 
00780  *    DesHash(
00781  *    IN  7-octet Clear,
00782  *    OUT 8-octet Cypher )
00783  *    {
00784  *        *
00785  *        * Make Cypher an irreversibly encrypted form of Clear by
00786  *        * encrypting known text using Clear as the secret key.
00787  *        * The known text consists of the string
00788  *        *
00789  *        *              KGS!@#$%
00790  *        *
00791  * 
00792  *       Set StdText to "KGS!@#$%"
00793  *       DesEncrypt( StdText, Clear, giving Cypher )
00794  *    }
00795  * 
00796  * 
00797  * A.4 DesEncrypt()
00798  * 
00799  *    DesEncrypt(
00800  *    IN  8-octet Clear,
00801  *    IN  7-octet Key,
00802  *    OUT 8-octet Cypher )
00803  *    {
00804  *        *
00805  *        * Use the DES encryption algorithm [4] in ECB mode [9]
00806  *        * to encrypt Clear into Cypher such that Cypher can
00807  *        * only be decrypted back to Clear by providing Key.
00808  *        * Note that the DES algorithm takes as input a 64-bit
00809  *        * stream where the 8th, 16th, 24th, etc.  bits are
00810  *        * parity bits ignored by the encrypting algorithm.
00811  *        * Unless you write your own DES to accept 56-bit input
00812  *        * without parity, you will need to insert the parity bits
00813  *        * yourself.
00814  *        *
00815  *    }
00816  */
00817 
00818 static void lmPasswd_to_key(
00819        const char *lmPasswd,
00820        des_key *key)
00821 {
00822        const unsigned char *lpw = (const unsigned char *) lmPasswd;
00823        unsigned char k[8];
00824 
00825        /* make room for parity bits */
00826        k[0] = lpw[0];
00827        k[1] = ((lpw[0] & 0x01) << 7) | (lpw[1] >> 1);
00828        k[2] = ((lpw[1] & 0x03) << 6) | (lpw[2] >> 2);
00829        k[3] = ((lpw[2] & 0x07) << 5) | (lpw[3] >> 3);
00830        k[4] = ((lpw[3] & 0x0F) << 4) | (lpw[4] >> 4);
00831        k[5] = ((lpw[4] & 0x1F) << 3) | (lpw[5] >> 5);
00832        k[6] = ((lpw[5] & 0x3F) << 2) | (lpw[6] >> 6);
00833        k[7] = ((lpw[6] & 0x7F) << 1);
00834               
00835        des_set_key_and_parity( key, k );
00836 }      
00837 
00838 static int chk_lanman(
00839        const struct berval *scheme,
00840        const struct berval *passwd,
00841        const struct berval *cred,
00842        const char **text )
00843 {
00844        ber_len_t i;
00845        char UcasePassword[15];
00846        des_key key;
00847        des_context schedule;
00848        des_data_block StdText = "KGS!@#$%";
00849        des_data_block PasswordHash1, PasswordHash2;
00850        char PasswordHash[33], storedPasswordHash[33];
00851        
00852        for( i=0; i<cred->bv_len; i++) {
00853               if(cred->bv_val[i] == '\0') {
00854                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
00855               }
00856        }
00857        
00858        if( cred->bv_val[i] != '\0' ) {
00859               return LUTIL_PASSWD_ERR;    /* passwd must behave like a string */
00860        }
00861        
00862        strncpy( UcasePassword, cred->bv_val, 14 );
00863        UcasePassword[14] = '\0';
00864        ldap_pvt_str2upper( UcasePassword );
00865        
00866        lmPasswd_to_key( UcasePassword, &key );
00867        des_set_key_unchecked( &key, schedule );
00868        des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
00869 
00870        if (des_failed(&PasswordHash1)) {
00871            return LUTIL_PASSWD_ERR;
00872        }
00873        
00874        lmPasswd_to_key( &UcasePassword[7], &key );
00875        des_set_key_unchecked( &key, schedule );
00876        des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
00877        if (des_failed(&PasswordHash2)) {
00878            return LUTIL_PASSWD_ERR;
00879        }
00880 
00881        des_finish( &key, schedule );
00882        
00883        sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
00884               PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
00885               PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
00886               PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
00887               PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
00888        
00889        /* as a precaution convert stored password hash to lower case */
00890        strncpy( storedPasswordHash, passwd->bv_val, 32 );
00891        storedPasswordHash[32] = '\0';
00892        ldap_pvt_str2lower( storedPasswordHash );
00893        
00894        return memcmp( PasswordHash, storedPasswordHash, 32) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
00895 }
00896 #endif /* SLAPD_LMHASH */
00897 
00898 #ifdef SLAPD_CRYPT
00899 static int lutil_crypt(
00900        const char *key,
00901        const char *salt,
00902        char **hash )
00903 {
00904        char *cr = crypt( key, salt );
00905        int rc;
00906 
00907        if( cr == NULL || cr[0] == '\0' ) {
00908               /* salt must have been invalid */
00909               rc = LUTIL_PASSWD_ERR;
00910        } else {
00911               if ( hash ) {
00912                      *hash = ber_strdup( cr );
00913                      rc = LUTIL_PASSWD_OK;
00914               } else {
00915                      rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
00916               }
00917        }
00918        return rc;
00919 }
00920 
00921 static int chk_crypt(
00922        const struct berval *sc,
00923        const struct berval * passwd,
00924        const struct berval * cred,
00925        const char **text )
00926 {
00927        unsigned int i;
00928 
00929        for( i=0; i<cred->bv_len; i++) {
00930               if(cred->bv_val[i] == '\0') {
00931                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
00932               }
00933        }
00934 
00935        if( cred->bv_val[i] != '\0' ) {
00936               return LUTIL_PASSWD_ERR;    /* cred must behave like a string */
00937        }
00938 
00939        if( passwd->bv_len < 2 ) {
00940               return LUTIL_PASSWD_ERR;    /* passwd must be at least two characters long */
00941        }
00942 
00943        for( i=0; i<passwd->bv_len; i++) {
00944               if(passwd->bv_val[i] == '\0') {
00945                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
00946               }
00947        }
00948 
00949        if( passwd->bv_val[i] != '\0' ) {
00950               return LUTIL_PASSWD_ERR;    /* passwd must behave like a string */
00951        }
00952 
00953        return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL );
00954 }
00955 
00956 # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
00957 static int chk_unix(
00958        const struct berval *sc,
00959        const struct berval * passwd,
00960        const struct berval * cred,
00961        const char **text )
00962 {
00963        unsigned int i;
00964        char *pw;
00965 
00966        for( i=0; i<cred->bv_len; i++) {
00967               if(cred->bv_val[i] == '\0') {
00968                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
00969               }
00970        }
00971        if( cred->bv_val[i] != '\0' ) {
00972               return LUTIL_PASSWD_ERR;    /* cred must behave like a string */
00973        }
00974 
00975        for( i=0; i<passwd->bv_len; i++) {
00976               if(passwd->bv_val[i] == '\0') {
00977                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
00978               }
00979        }
00980 
00981        if( passwd->bv_val[i] != '\0' ) {
00982               return LUTIL_PASSWD_ERR;    /* passwd must behave like a string */
00983        }
00984 
00985        {
00986               struct passwd *pwd = getpwnam(passwd->bv_val);
00987 
00988               if(pwd == NULL) {
00989                      return LUTIL_PASSWD_ERR;    /* not found */
00990               }
00991 
00992               pw = pwd->pw_passwd;
00993        }
00994 #  ifdef HAVE_GETSPNAM
00995        {
00996               struct spwd *spwd = getspnam(passwd->bv_val);
00997 
00998               if(spwd != NULL) {
00999                      pw = spwd->sp_pwdp;
01000               }
01001        }
01002 #  endif
01003 #  ifdef HAVE_AIX_SECURITY
01004        {
01005               struct userpw *upw = getuserpw(passwd->bv_val);
01006 
01007               if (upw != NULL) {
01008                      pw = upw->upw_passwd;
01009               }
01010        }
01011 #  endif
01012 
01013        if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
01014               /* password must must be at least two characters long */
01015               return LUTIL_PASSWD_ERR;
01016        }
01017 
01018        return lutil_cryptptr( cred->bv_val, pw, NULL );
01019 }
01020 # endif
01021 #endif
01022 
01023 /* PASSWORD GENERATION ROUTINES */
01024 
01025 #ifdef LUTIL_SHA1_BYTES
01026 static int hash_ssha1(
01027        const struct berval *scheme,
01028        const struct berval  *passwd,
01029        struct berval *hash,
01030        const char **text )
01031 {
01032        lutil_SHA1_CTX  SHA1context;
01033        unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
01034        char            saltdata[SALT_SIZE];
01035        struct berval digest;
01036        struct berval salt;
01037 
01038        digest.bv_val = (char *) SHA1digest;
01039        digest.bv_len = sizeof(SHA1digest);
01040        salt.bv_val = saltdata;
01041        salt.bv_len = sizeof(saltdata);
01042 
01043        if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
01044               return LUTIL_PASSWD_ERR; 
01045        }
01046 
01047        lutil_SHA1Init( &SHA1context );
01048        lutil_SHA1Update( &SHA1context,
01049               (const unsigned char *)passwd->bv_val, passwd->bv_len );
01050        lutil_SHA1Update( &SHA1context,
01051               (const unsigned char *)salt.bv_val, salt.bv_len );
01052        lutil_SHA1Final( SHA1digest, &SHA1context );
01053 
01054        return lutil_passwd_string64( scheme, &digest, hash, &salt);
01055 }
01056 
01057 static int hash_sha1(
01058        const struct berval *scheme,
01059        const struct berval  *passwd,
01060        struct berval *hash,
01061        const char **text )
01062 {
01063        lutil_SHA1_CTX  SHA1context;
01064        unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
01065        struct berval digest;
01066        digest.bv_val = (char *) SHA1digest;
01067        digest.bv_len = sizeof(SHA1digest);
01068      
01069        lutil_SHA1Init( &SHA1context );
01070        lutil_SHA1Update( &SHA1context,
01071               (const unsigned char *)passwd->bv_val, passwd->bv_len );
01072        lutil_SHA1Final( SHA1digest, &SHA1context );
01073             
01074        return lutil_passwd_string64( scheme, &digest, hash, NULL);
01075 }
01076 #endif
01077 
01078 static int hash_smd5(
01079        const struct berval *scheme,
01080        const struct berval  *passwd,
01081        struct berval *hash,
01082        const char **text )
01083 {
01084        lutil_MD5_CTX   MD5context;
01085        unsigned char   MD5digest[LUTIL_MD5_BYTES];
01086        char            saltdata[SALT_SIZE];
01087        struct berval digest;
01088        struct berval salt;
01089 
01090        digest.bv_val = (char *) MD5digest;
01091        digest.bv_len = sizeof(MD5digest);
01092        salt.bv_val = saltdata;
01093        salt.bv_len = sizeof(saltdata);
01094 
01095        if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
01096               return LUTIL_PASSWD_ERR; 
01097        }
01098 
01099        lutil_MD5Init( &MD5context );
01100        lutil_MD5Update( &MD5context,
01101               (const unsigned char *) passwd->bv_val, passwd->bv_len );
01102        lutil_MD5Update( &MD5context,
01103               (const unsigned char *) salt.bv_val, salt.bv_len );
01104        lutil_MD5Final( MD5digest, &MD5context );
01105 
01106        return lutil_passwd_string64( scheme, &digest, hash, &salt );
01107 }
01108 
01109 static int hash_md5(
01110        const struct berval *scheme,
01111        const struct berval  *passwd,
01112        struct berval *hash,
01113        const char **text )
01114 {
01115        lutil_MD5_CTX   MD5context;
01116        unsigned char   MD5digest[LUTIL_MD5_BYTES];
01117 
01118        struct berval digest;
01119 
01120        digest.bv_val = (char *) MD5digest;
01121        digest.bv_len = sizeof(MD5digest);
01122 
01123        lutil_MD5Init( &MD5context );
01124        lutil_MD5Update( &MD5context,
01125               (const unsigned char *) passwd->bv_val, passwd->bv_len );
01126        lutil_MD5Final( MD5digest, &MD5context );
01127 
01128        return lutil_passwd_string64( scheme, &digest, hash, NULL );
01129 ;
01130 }
01131 
01132 #ifdef SLAPD_LMHASH 
01133 static int hash_lanman(
01134        const struct berval *scheme,
01135        const struct berval *passwd,
01136        struct berval *hash,
01137        const char **text )
01138 {
01139 
01140        ber_len_t i;
01141        char UcasePassword[15];
01142        des_key key;
01143        des_context schedule;
01144        des_data_block StdText = "KGS!@#$%";
01145        des_data_block PasswordHash1, PasswordHash2;
01146        char PasswordHash[33];
01147        
01148        for( i=0; i<passwd->bv_len; i++) {
01149               if(passwd->bv_val[i] == '\0') {
01150                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
01151               }
01152        }
01153        
01154        if( passwd->bv_val[i] != '\0' ) {
01155               return LUTIL_PASSWD_ERR;    /* passwd must behave like a string */
01156        }
01157        
01158        strncpy( UcasePassword, passwd->bv_val, 14 );
01159        UcasePassword[14] = '\0';
01160        ldap_pvt_str2upper( UcasePassword );
01161        
01162        lmPasswd_to_key( UcasePassword, &key );
01163        des_set_key_unchecked( &key, schedule );
01164        des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
01165        
01166        lmPasswd_to_key( &UcasePassword[7], &key );
01167        des_set_key_unchecked( &key, schedule );
01168        des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
01169        
01170        sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
01171               PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
01172               PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
01173               PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
01174               PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
01175        
01176        hash->bv_val = PasswordHash;
01177        hash->bv_len = 32;
01178        
01179        return pw_string( scheme, hash );
01180 }
01181 #endif /* SLAPD_LMHASH */
01182 
01183 #ifdef SLAPD_CRYPT
01184 static int hash_crypt(
01185        const struct berval *scheme,
01186        const struct berval *passwd,
01187        struct berval *hash,
01188        const char **text )
01189 {
01190        unsigned char salt[32];     /* salt suitable for most anything */
01191        unsigned int i;
01192        char *save;
01193        int rc;
01194 
01195        for( i=0; i<passwd->bv_len; i++) {
01196               if(passwd->bv_val[i] == '\0') {
01197                      return LUTIL_PASSWD_ERR;    /* NUL character in password */
01198               }
01199        }
01200 
01201        if( passwd->bv_val[i] != '\0' ) {
01202               return LUTIL_PASSWD_ERR;    /* passwd must behave like a string */
01203        }
01204 
01205        if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
01206               return LUTIL_PASSWD_ERR; 
01207        }
01208 
01209        for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
01210               salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
01211        }
01212        salt[sizeof( salt ) - 1 ] = '\0';
01213 
01214        if( salt_format != NULL ) {
01215               /* copy the salt we made into entropy before snprintfing
01216                  it back into the salt */
01217               char entropy[sizeof(salt)];
01218               strcpy( entropy, (char *) salt );
01219               snprintf( (char *) salt, sizeof(entropy), salt_format, entropy );
01220        }
01221 
01222        rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val );
01223        if ( rc != LUTIL_PASSWD_OK ) return rc;
01224 
01225        if( hash->bv_val == NULL ) return -1;
01226 
01227        hash->bv_len = strlen( hash->bv_val );
01228 
01229        save = hash->bv_val;
01230 
01231        if( hash->bv_len == 0 ) {
01232               rc = LUTIL_PASSWD_ERR;
01233        } else {
01234               rc = pw_string( scheme, hash );
01235        }
01236        ber_memfree( save );
01237        return rc;
01238 }
01239 #endif
01240 
01241 int lutil_salt_format(const char *format)
01242 {
01243 #ifdef SLAPD_CRYPT
01244        ber_memfree( salt_format );
01245 
01246        salt_format = format != NULL ? ber_strdup( format ) : NULL;
01247 #endif
01248 
01249        return 0;
01250 }
01251 
01252 #ifdef SLAPD_CLEARTEXT
01253 static int hash_clear(
01254        const struct berval *scheme,
01255        const struct berval  *passwd,
01256        struct berval *hash,
01257        const char **text )
01258 {
01259        ber_dupbv( hash, (struct berval *)passwd );
01260        return LUTIL_PASSWD_OK;
01261 }
01262 #endif
01263