home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / liblutil / authpasswd.c next >
C/C++ Source or Header  |  2000-08-17  |  20KB  |  932 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/liblutil/authpasswd.c,v 1.3.2.3 2000/08/16 19:29:01 kurt Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  4.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  5.  */
  6. /*
  7.  * lutil_authpassword(authpasswd, cred)
  8.  *
  9.  * Returns true if user supplied credentials (cred) matches
  10.  * the stored authentication password (authpasswd). 
  11.  *
  12.  * Due to the use of the crypt(3) function 
  13.  * this routine is NOT thread-safe.
  14.  */
  15.  
  16. #include "portable.h"
  17.  
  18. #include <stdio.h>
  19. #include <ac/stdlib.h>
  20. #include <ac/string.h>
  21.  
  22. #ifdef SLAPD_KPASSWD
  23. #    include <ac/krb.h>
  24. #    include <ac/krb5.h>
  25. #endif
  26.  
  27. #include <ac/param.h>
  28.  
  29. #include <ac/unistd.h>
  30. #include <ac/crypt.h>
  31.  
  32. #ifdef HAVE_SHADOW_H
  33. #    include <shadow.h>
  34. #endif
  35. #ifdef HAVE_PWD_H
  36. #    include <pwd.h>
  37. #endif
  38.  
  39. #include <lber.h>
  40.  
  41. #include "lutil_md5.h"
  42. #include "lutil_sha1.h"
  43. #include "lutil.h"
  44.  
  45. static const unsigned char crypt64[] =
  46.     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
  47.  
  48. struct pw_scheme;
  49.  
  50. typedef int (*PASSWD_CHK_FUNC)(
  51.     const struct pw_scheme *scheme,
  52.     const struct berval *passwd,
  53.     const struct berval *salt,
  54.     const struct berval *cred );
  55.  
  56. typedef int (*PASSWD_HASH_FUNC) (
  57.     const struct pw_scheme *scheme,
  58.     const struct berval *cred,
  59.     const struct berval *salt,
  60.     struct berval **passwd_out,
  61.     struct berval **salt_out );
  62.  
  63. /* password check routines */
  64. static int chk_md5(
  65.     const struct pw_scheme *scheme,
  66.     const struct berval *passwd,
  67.     const struct berval *salt,
  68.     const struct berval *cred );
  69.  
  70. static int chk_sha1(
  71.     const struct pw_scheme *scheme,
  72.     const struct berval *passwd,
  73.     const struct berval *salt,
  74.     const struct berval *cred );
  75.  
  76. static int chk_crypt(
  77.     const struct pw_scheme *scheme,
  78.     const struct berval *passwd,
  79.     const struct berval *salt,
  80.     const struct berval *cred );
  81.  
  82. static int chk_ext(
  83.     const struct pw_scheme *scheme,
  84.     const struct berval *passwd,
  85.     const struct berval *salt,
  86.     const struct berval *cred );
  87.  
  88. static int chk_ext_kerberos(
  89.     const struct pw_scheme *scheme,
  90.     const struct berval *passwd,
  91.     const struct berval *cred );
  92.  
  93. static int chk_ext_unix(
  94.     const struct pw_scheme *scheme,
  95.     const struct berval *passwd,
  96.     const struct berval *cred );
  97.  
  98.  
  99. /* password hash routines */
  100. static int *hash_sha1(
  101.     const struct pw_scheme *scheme,
  102.     const struct berval *cred,
  103.     const struct berval *salt,
  104.     struct berval **passwd_out,
  105.     struct berval **salt_out );
  106.  
  107. static int *hash_md5(
  108.     const struct pw_scheme *scheme,
  109.     const struct berval *cred,
  110.     const struct berval *salt,
  111.     struct berval **passwd_out,
  112.     struct berval **salt_out );
  113.  
  114. static int *hash_crypt(
  115.     const struct pw_scheme *scheme,
  116.     const struct berval *cred,
  117.     const struct berval *salt,
  118.     struct berval **passwd_out,
  119.     struct berval **salt_out );
  120.  
  121.  
  122. struct pw_scheme {
  123.     struct berval name;
  124.     PASSWD_CHK_FUNC chk_fn;
  125.     PASSWD_HASH_FUNC hash_fn;
  126.     int saltbytes;
  127. };
  128.  
  129. static const struct pw_scheme pw_schemes[] =
  130. {
  131.     { {sizeof("SHA1")-1, "SHA1"},    chk_sha1, 0 /* hash_sha1 */, 4 },
  132.     { {sizeof("MD5")-1, "MD5"},        chk_md5, 0 /* hash_md5 */, 4 },
  133.  
  134. #ifdef SLAPD_CRYPT
  135.     { {sizeof("CRYPT")-1, "CRYPT"},    chk_crypt, hash_crypt, 2 },
  136. #endif
  137.  
  138. #ifdef EXT_PASSWD
  139.     { {sizeof("EXTERNAL")-1, "EXTERNAL"}, chk_ext, NULL, 0 },
  140. #endif
  141.  
  142.     { {0, NULL}, NULL, NULL, 0 }
  143. };
  144.  
  145. #ifdef EXT_PASSWD
  146. struct ext_scheme {
  147.     struct berval name;
  148.     EXT_CHK_FUNC chk_fn;
  149. };
  150.  
  151. static const struct ext_scheme ext_schemes[] =
  152. {
  153.     { {0, NULL}, NULL, NULL, 0 }
  154. };
  155. #endif
  156.  
  157. static const struct pw_scheme *get_scheme(
  158.     const char *scheme )
  159. {
  160.     int i;
  161.  
  162.     if( scheme == NULL || *scheme == '\0' ) return NULL;
  163.  
  164.     for( i=0; pw_schemes[i].name.bv_val; i++) {
  165.         if( pw_schemes[i].name.bv_len == 0 ) continue;
  166.  
  167.         if( strncasecmp( scheme,
  168.             pw_schemes[i].name.bv_val,
  169.             pw_schemes[i].name.bv_len) == 0 )
  170.         {
  171.             return &pw_schemes[i];
  172.         }
  173.     }
  174.  
  175.     return NULL;
  176. }
  177.  
  178. int lutil_authpasswd_scheme(
  179.     const char *scheme )
  180. {
  181.     return get_scheme( scheme ) != NULL;
  182. }
  183.  
  184.  
  185. static int is_allowed_scheme( 
  186.     const char* scheme,
  187.     const char** schemes )
  188. {
  189.     int i;
  190.  
  191.     if( scheme == NULL || *scheme == '\0' ) return 1;
  192.  
  193.     for( i=0; schemes[i] != NULL; i++ ) {
  194.         if( strcasecmp( scheme, schemes[i] ) == 0 ) {
  195.             return 1;
  196.         }
  197.     }
  198.     return 0;
  199. }
  200.  
  201. static int parse_authpasswd(
  202.     char **scheme,
  203.     struct berval *salt,
  204.     struct berval *passwd )
  205. {
  206.     *scheme = NULL;
  207.     return -1;
  208. }
  209.  
  210. /*
  211.  * Return 0 if creds are good.
  212.  */
  213. int
  214. lutil_authpasswd(
  215.     const struct berval *value,    /* stored authpasswd */
  216.     const struct berval *cred,        /* user cred */
  217.     const char **schemes )
  218. {
  219.     char *scheme;
  220.     struct berval salt, passwd;
  221.     const struct pw_scheme *pws;
  222.     int rc = -1;
  223.  
  224.     if (cred == NULL || cred->bv_len == 0 ||
  225.         value == NULL || value->bv_len == 0 )
  226.     {
  227.         return -1;
  228.     }
  229.  
  230.     rc = parse_authpasswd( &scheme, &salt, &passwd );
  231.  
  232.     if( rc != 0 ) return -1;
  233.  
  234.     if( !is_allowed_scheme( scheme, schemes ) ) {
  235.         goto done;
  236.     }
  237.  
  238.     pws = get_scheme( scheme );
  239.  
  240.     if( pws == NULL || !pws->chk_fn ) {
  241.         goto done;
  242.     };
  243.  
  244.     rc = (pws->chk_fn)( pws, &salt, &passwd, cred );
  245.  
  246. done:
  247.     if( scheme != NULL ) {
  248.         ber_memfree( scheme );
  249.         ber_memfree( salt.bv_val );
  250.         ber_memfree( passwd.bv_val );
  251.     }
  252.  
  253.     return rc ? -1 : 0;
  254. }
  255.  
  256. struct berval * lutil_authpasswd_generate( ber_len_t len )
  257. {
  258.     struct berval *pw;
  259.  
  260.     if( len < 1 ) return NULL;
  261.  
  262.     pw = ber_memalloc( sizeof( struct berval ) );
  263.     if( pw == NULL ) return NULL;
  264.  
  265.     pw->bv_len = len;
  266.     pw->bv_val = ber_memalloc( len + 1 );
  267.  
  268.     if( pw->bv_val == NULL ) {
  269.         ber_memfree( pw );
  270.         return NULL;
  271.     }
  272.  
  273.     if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) {
  274.         ber_bvfree( pw );
  275.         return NULL; 
  276.     }
  277.  
  278.     for( len = 0; len < pw->bv_len; len++ ) {
  279.         pw->bv_val[len] = crypt64[
  280.             pw->bv_val[len] % (sizeof(crypt64)-1) ];
  281.     }
  282.  
  283.     pw->bv_val[len] = '\0';
  284.     
  285.     return pw;
  286. }
  287.  
  288. int lutil_authpasswd_hash(
  289.     const struct berval * cred,
  290.     struct berval ** passwd_out,
  291.     struct berval ** salt_out,
  292.     const char * method )
  293. {
  294.     const struct pw_scheme *sc;
  295.     int rc;
  296.  
  297.     if( passwd_out == NULL ) return -1;
  298.     
  299.     sc = get_scheme( method );
  300.     if( sc == NULL || !sc->hash_fn ) return -1;
  301.  
  302.     if( sc->saltbytes && salt_out != NULL ) {
  303.         struct berval salt;
  304.         salt.bv_val = ber_memalloc( sc->saltbytes );
  305.  
  306.         if( salt.bv_val == NULL ) {
  307.             return -1;
  308.         }
  309.         salt.bv_len = sc->saltbytes;
  310.  
  311.         if( lutil_entropy( salt.bv_val, salt.bv_len ) < 0 ) {
  312.             ber_memfree( salt.bv_val );
  313.             return -1; 
  314.         }
  315.  
  316.         rc = (sc->hash_fn)( sc, cred, &salt, passwd_out, NULL );
  317.         ber_memfree( salt.bv_val );
  318.  
  319.     } else if ( sc->saltbytes ) {
  320.         /* wants salt, disallow */
  321.         return -1;
  322.  
  323.     } else {
  324.         rc = (sc->hash_fn)( sc, cred, NULL, passwd_out, salt_out );
  325.     }
  326.  
  327.     return rc;
  328. }
  329.  
  330. static struct berval * base64(
  331.     const struct berval *value )
  332. {
  333.     int rc;
  334.     struct berval *b64; 
  335.  
  336.     assert( value != NULL );
  337.  
  338.     if( value == NULL || value->bv_len == 0 ) return NULL;
  339.  
  340.     b64 = ber_memalloc( sizeof(struct berval) );
  341.     if( b64 == NULL ) return NULL;
  342.  
  343.     b64->bv_len = LUTIL_BASE64_ENCODE_LEN( value->bv_len );
  344.     b64->bv_val = ber_memalloc( b64->bv_len + 1 );
  345.  
  346.     if( b64->bv_val == NULL ) {
  347.         ber_memfree( b64 );
  348.         return NULL;
  349.     }
  350.  
  351.     rc = lutil_b64_ntop(
  352.         value->bv_val, value->bv_len,
  353.         b64->bv_val, b64->bv_len );
  354.  
  355.     b64->bv_val[b64->bv_len] = '\0';
  356.  
  357.     if( rc < 0 ) {
  358.         ber_bvfree( b64 );
  359.         return NULL;
  360.     }
  361.  
  362.     return b64;
  363. }
  364.  
  365. /* PASSWORD CHECK ROUTINES */
  366.  
  367. static int chk_sha1(
  368.     const struct pw_scheme *sc,
  369.     const struct berval * passwd,
  370.     const struct berval * salt,
  371.     const struct berval * cred )
  372. {
  373.     lutil_SHA1_CTX SHA1context;
  374.     unsigned char SHA1digest[LUTIL_SHA1_BYTES];
  375.     int rc;
  376.     unsigned char *orig_pass = NULL;
  377.     unsigned char *orig_salt = NULL;
  378.     int saltlen;
  379.  
  380.     if( passwd == NULL || passwd->bv_len == 0 ) {
  381.         return 1;
  382.     }
  383.  
  384.     /* decode base64 password */
  385.     orig_pass = (unsigned char *) ber_memalloc( (size_t) (
  386.         LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
  387.  
  388.     if( orig_pass == NULL ) {
  389.         rc = -1;
  390.         goto done;
  391.     }
  392.  
  393.     rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
  394.  
  395.     if( rc < 0 ) {
  396.         goto done;
  397.     }
  398.  
  399.     /* decode base64 salt */
  400.     if( salt != NULL && salt->bv_len > 0 ) {
  401.          orig_salt = (unsigned char *) ber_memalloc( (size_t) (
  402.             LUTIL_BASE64_DECODE_LEN(salt->bv_len) + 1) );
  403.  
  404.         if( orig_salt == NULL ) {
  405.             rc = -1;
  406.             goto done;
  407.         }
  408.  
  409.         saltlen = lutil_b64_pton(passwd->bv_val, orig_salt, passwd->bv_len);
  410.  
  411.         if( saltlen < 0 ) {
  412.             goto done;
  413.         }
  414.     }
  415.  
  416.     /* hash credentials with salt */
  417.     lutil_SHA1Init(&SHA1context);
  418.     lutil_SHA1Update(&SHA1context,
  419.         (const unsigned char *) cred->bv_val, cred->bv_len);
  420.     if( orig_salt != NULL ) {
  421.         lutil_SHA1Update(&SHA1context,
  422.             orig_salt, saltlen );
  423.     }
  424.     lutil_SHA1Final(SHA1digest, &SHA1context);
  425.  
  426.     /* compare */
  427.     rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
  428.  
  429. done:
  430.     ber_memfree(orig_pass);
  431.     ber_memfree(orig_salt);
  432.     return rc;
  433. }
  434.  
  435. static int chk_md5(
  436.     const struct pw_scheme *sc,
  437.     const struct berval * passwd,
  438.     const struct berval * salt,
  439.     const struct berval * cred )
  440. {
  441.     lutil_MD5_CTX MD5context;
  442.     unsigned char MD5digest[LUTIL_MD5_BYTES];
  443.     int rc;
  444.     unsigned char *orig_pass = NULL;
  445.     unsigned char *orig_salt = NULL;
  446.     int saltlen;
  447.  
  448.     if( passwd == NULL || passwd->bv_len == 0 ) {
  449.         return 1;
  450.     }
  451.  
  452.     /* decode base64 password */
  453.     orig_pass = (unsigned char *) ber_memalloc( (size_t) (
  454.         LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
  455.  
  456.     if( orig_pass == NULL ) {
  457.         rc = -1;
  458.         goto done;
  459.     }
  460.  
  461.     rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
  462.  
  463.     if( rc < 0 ) {
  464.         goto done;
  465.     }
  466.  
  467.     /* decode base64 salt */
  468.     if( salt != NULL && salt->bv_len > 0 ) {
  469.          orig_salt = (unsigned char *) ber_memalloc( (size_t) (
  470.             LUTIL_BASE64_DECODE_LEN(salt->bv_len) + 1) );
  471.  
  472.         if( orig_salt == NULL ) {
  473.             rc = -1;
  474.             goto done;
  475.         }
  476.  
  477.         saltlen = lutil_b64_pton(passwd->bv_val, orig_salt, passwd->bv_len);
  478.  
  479.         if( saltlen < 0 ) {
  480.             goto done;
  481.         }
  482.     }
  483.  
  484.     /* hash credentials with salt */
  485.     lutil_MD5Init(&MD5context);
  486.     lutil_MD5Update(&MD5context,
  487.         (const unsigned char *) cred->bv_val, cred->bv_len);
  488.     if( orig_salt != NULL ) {
  489.         lutil_MD5Update(&MD5context,
  490.             orig_salt, saltlen );
  491.     }
  492.     lutil_MD5Final(MD5digest, &MD5context);
  493.  
  494.     /* compare */
  495.     rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
  496.  
  497. done:
  498.     ber_memfree(orig_pass);
  499.     ber_memfree(orig_salt);
  500.     return rc;
  501. }
  502.  
  503. #ifdef SLAPD_KPASSWD
  504. static int chk_kerberos(
  505.     const struct pw_scheme *sc,
  506.     const struct berval * passwd,
  507.     const struct berval * cred,
  508.     const struct berval * salt )
  509. {
  510.     int i;
  511.     int rtn;
  512.  
  513.     for( i=0; i<cred->bv_len; i++) {
  514.         if(cred->bv_val[i] == '\0') {
  515.             return 1;    /* NUL character in password */
  516.         }
  517.     }
  518.  
  519.     if( cred->bv_val[i] != '\0' ) {
  520.         return 1;    /* cred must behave like a string */
  521.     }
  522.  
  523.     for( i=0; i<passwd->bv_len; i++) {
  524.         if(passwd->bv_val[i] == '\0') {
  525.             return 1;    /* NUL character in password */
  526.         }
  527.     }
  528.  
  529.     if( passwd->bv_val[i] != '\0' ) {
  530.         return 1;    /* passwd must behave like a string */
  531.     }
  532.  
  533.     rtn = 1;
  534.  
  535. #ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
  536.     {
  537. /* Portions:
  538.  * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
  539.  * (Royal Institute of Technology, Stockholm, Sweden).
  540.  * All rights reserved.
  541.  *
  542.  * Redistribution and use in source and binary forms, with or without
  543.  * modification, are permitted provided that the following conditions
  544.  * are met:
  545.  *
  546.  * 1. Redistributions of source code must retain the above copyright
  547.  *    notice, this list of conditions and the following disclaimer.
  548.  *
  549.  * 2. Redistributions in binary form must reproduce the above copyright
  550.  *    notice, this list of conditions and the following disclaimer in the
  551.  *    documentation and/or other materials provided with the distribution.
  552.  *
  553.  * 3. Neither the name of the Institute nor the names of its contributors
  554.  *    may be used to endorse or promote products derived from this software
  555.  *    without specific prior written permission.
  556.  *
  557.  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  558.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  559.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  560.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  561.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  562.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  563.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  564.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  565.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  566.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  567.  * SUCH DAMAGE.
  568.  */
  569.  
  570.         krb5_context context;
  571.            krb5_error_code ret;
  572.            krb5_creds creds;
  573.            krb5_get_init_creds_opt get_options;
  574.            krb5_verify_init_creds_opt verify_options;
  575.         krb5_principal client, server;
  576. #ifdef notdef
  577.         krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
  578. #endif
  579.  
  580.         ret = krb5_init_context( &context );
  581.         if (ret) {
  582.             return 1;
  583.         }
  584.  
  585. #ifdef notdef
  586.         krb5_get_init_creds_opt_set_preauth_list(&get_options,
  587.             pre_auth_types, 1);
  588. #endif
  589.  
  590.            krb5_get_init_creds_opt_init( &get_options );
  591.  
  592.         krb5_verify_init_creds_opt_init( &verify_options );
  593.     
  594.         ret = krb5_parse_name( context, passwd->bv_val, &client );
  595.  
  596.         if (ret) {
  597.             krb5_free_context( context );
  598.             return 1;
  599.         }
  600.  
  601.         ret = krb5_get_init_creds_password( context,
  602.             &creds, client, cred->bv_val, NULL,
  603.             NULL, 0, NULL, &get_options );
  604.  
  605.         if (ret) {
  606.             krb5_free_principal( context, client );
  607.             krb5_free_context( context );
  608.             return 1;
  609.         }
  610.  
  611.         {
  612.             char *host = ldap_pvt_get_fqdn( NULL );
  613.  
  614.             if( host == NULL ) {
  615.                 krb5_free_principal( context, client );
  616.                 krb5_free_context( context );
  617.                 return 1;
  618.             }
  619.  
  620.             ret = krb5_sname_to_principal( context,
  621.                 host, "ldap", KRB5_NT_SRV_HST, &server );
  622.  
  623.             ber_memfree( host );
  624.         }
  625.  
  626.         if (ret) {
  627.             krb5_free_principal( context, client );
  628.             krb5_free_context( context );
  629.             return 1;
  630.         }
  631.  
  632.         ret = krb5_verify_init_creds( context,
  633.             &creds, server, NULL, NULL, &verify_options );
  634.  
  635.         krb5_free_principal( context, client );
  636.         krb5_free_principal( context, server );
  637.         krb5_free_creds_contents( context, &creds );
  638.         krb5_free_context( context );
  639.  
  640.         rtn = !!ret;
  641.     }
  642. #elif    defined(HAVE_KRB4)
  643.     {
  644.         /* Borrowed from Heimdal kpopper */
  645. /* Portions:
  646.  * Copyright (c) 1989 Regents of the University of California.
  647.  * All rights reserved.  The Berkeley software License Agreement
  648.  * specifies the terms and conditions for redistribution.
  649.  */
  650.  
  651.         int status;
  652.         char lrealm[REALM_SZ];
  653.         char tkt[MAXHOSTNAMELEN];
  654.  
  655.         status = krb_get_lrealm(lrealm,1);
  656.         if (status == KFAILURE) {
  657.             return 1;
  658.         }
  659.  
  660.         snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
  661.             TKT_ROOT, (unsigned)getpid());
  662.         krb_set_tkt_string (tkt);
  663.  
  664.         status = krb_verify_user( passwd->bv_val, "", lrealm,
  665.             cred->bv_val, 1, "ldap");
  666.  
  667.         dest_tkt(); /* no point in keeping the tickets */
  668.  
  669.         return status == KFAILURE;
  670.     }
  671. #endif
  672.  
  673.     return rtn;
  674. }
  675. #endif /* SLAPD_KPASSWD */
  676.  
  677. #ifdef SLAPD_CRYPT
  678. static int chk_crypt(
  679.     const struct pw_scheme *sc,
  680.     const struct berval * passwd,
  681.     const struct berval * cred )
  682. {
  683.     char *cr;
  684.     int i;
  685.  
  686.     for( i=0; i<cred->bv_len; i++) {
  687.         if(cred->bv_val[i] == '\0') {
  688.             return 1;    /* NUL character in password */
  689.         }
  690.     }
  691.  
  692.     if( cred->bv_val[i] != '\0' ) {
  693.         return 1;    /* cred must behave like a string */
  694.     }
  695.  
  696.     if( passwd->bv_len < 2 ) {
  697.         return 1;    /* passwd must be at least two characters long */
  698.     }
  699.  
  700.     for( i=0; i<passwd->bv_len; i++) {
  701.         if(passwd->bv_val[i] == '\0') {
  702.             return 1;    /* NUL character in password */
  703.         }
  704.     }
  705.  
  706.     if( passwd->bv_val[i] != '\0' ) {
  707.         return 1;    /* passwd must behave like a string */
  708.     }
  709.  
  710.     cr = crypt( cred->bv_val, passwd->bv_val );
  711.  
  712.     if( cr == NULL || cr[0] == '\0' ) {
  713.         /* salt must have been invalid */
  714.         return 1;
  715.     }
  716.  
  717.     return strcmp( passwd->bv_val, cr );
  718. }
  719.  
  720. # if defined( HAVE_GETSPNAM ) \
  721.   || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
  722. static int chk_unix(
  723.     const struct pw_scheme *sc,
  724.     const struct berval * passwd,
  725.     const struct berval * cred )
  726. {
  727.     int i;
  728.     char *pw,*cr;
  729.  
  730.     for( i=0; i<cred->bv_len; i++) {
  731.         if(cred->bv_val[i] == '\0') {
  732.             return 1;    /* NUL character in password */
  733.         }
  734.     }
  735.     if( cred->bv_val[i] != '\0' ) {
  736.         return 1;    /* cred must behave like a string */
  737.     }
  738.  
  739.     for( i=0; i<passwd->bv_len; i++) {
  740.         if(passwd->bv_val[i] == '\0') {
  741.             return 1;    /* NUL character in password */
  742.         }
  743.     }
  744.  
  745.     if( passwd->bv_val[i] != '\0' ) {
  746.         return 1;    /* passwd must behave like a string */
  747.     }
  748.  
  749. #  ifdef HAVE_GETSPNAM
  750.     {
  751.         struct spwd *spwd = getspnam(passwd->bv_val);
  752.  
  753.         if(spwd == NULL) {
  754.             return 1;    /* not found */
  755.         }
  756.  
  757.         pw = spwd->sp_pwdp;
  758.     }
  759.  
  760. #  else
  761.     {
  762.         struct passwd *pwd = getpwnam(passwd->bv_val);
  763.  
  764.         if(pwd == NULL) {
  765.             return 1;    /* not found */
  766.         }
  767.  
  768.         pw = pwd->pw_passwd;
  769.     }
  770. #  endif
  771.  
  772.     if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
  773.         /* password must must be at least two characters long */
  774.         return 1;
  775.     }
  776.  
  777.     cr = crypt(cred->bv_val, pw);
  778.  
  779.     if( cr == NULL || cr[0] == '\0' ) {
  780.         /* salt must have been invalid */
  781.         return 1;
  782.     }
  783.  
  784.     return strcmp(pw, cr);
  785.  
  786. }
  787. # endif
  788. #endif
  789.  
  790. /* PASSWORD GENERATION ROUTINES */
  791.  
  792. #ifdef SLAPD_GENERATE
  793.  
  794. static struct berval *hash_ssha1(
  795.     const struct pw_scheme *scheme,
  796.     const struct berval *passwd )
  797. {
  798.     lutil_SHA1_CTX  SHA1context;
  799.     unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
  800.     unsigned char   saltdata[4];
  801.     struct berval digest;
  802.     struct berval salt;
  803.  
  804.     digest.bv_val = SHA1digest;
  805.     digest.bv_len = sizeof(SHA1digest);
  806.     salt.bv_val = saltdata;
  807.     salt.bv_len = sizeof(saltdata);
  808.  
  809.     if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
  810.         return NULL; 
  811.     }
  812.  
  813.     lutil_SHA1Init( &SHA1context );
  814.     lutil_SHA1Update( &SHA1context,
  815.         (const unsigned char *)passwd->bv_val, passwd->bv_len );
  816.     lutil_SHA1Update( &SHA1context,
  817.         (const unsigned char *)salt.bv_val, salt.bv_len );
  818.     lutil_SHA1Final( SHA1digest, &SHA1context );
  819.  
  820.     return pw_string64( scheme, &digest, &salt);
  821. }
  822.  
  823. static struct berval *hash_sha1(
  824.     const struct pw_scheme *scheme,
  825.     const struct berval  *passwd )
  826. {
  827.     lutil_SHA1_CTX  SHA1context;
  828.     unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
  829.     struct berval digest;
  830.     digest.bv_val = SHA1digest;
  831.     digest.bv_len = sizeof(SHA1digest);
  832.      
  833.     lutil_SHA1Init( &SHA1context );
  834.     lutil_SHA1Update( &SHA1context,
  835.         (const unsigned char *)passwd->bv_val, passwd->bv_len );
  836.     lutil_SHA1Final( SHA1digest, &SHA1context );
  837.             
  838.     return pw_string64( scheme, &digest, NULL);
  839. }
  840.  
  841. static struct berval *hash_smd5(
  842.     const struct pw_scheme *scheme,
  843.     const struct berval  *passwd )
  844. {
  845.     lutil_MD5_CTX   MD5context;
  846.     unsigned char   MD5digest[LUTIL_MD5_BYTES];
  847.     unsigned char   saltdata[4];
  848.     struct berval digest;
  849.     struct berval salt;
  850.  
  851.     digest.bv_val = MD5digest;
  852.     digest.bv_len = sizeof(MD5digest);
  853.     salt.bv_val = saltdata;
  854.     salt.bv_len = sizeof(saltdata);
  855.  
  856.     if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
  857.         return NULL; 
  858.     }
  859.  
  860.     lutil_MD5Init( &MD5context );
  861.     lutil_MD5Update( &MD5context,
  862.         (const unsigned char *) passwd->bv_val, passwd->bv_len );
  863.     lutil_MD5Update( &MD5context,
  864.         (const unsigned char *) salt.bv_val, salt.bv_len );
  865.     lutil_MD5Final( MD5digest, &MD5context );
  866.  
  867.     return pw_string64( scheme, &digest, &salt );
  868. }
  869.  
  870. static struct berval *hash_md5(
  871.     const struct pw_scheme *scheme,
  872.     const struct berval  *passwd )
  873. {
  874.     lutil_MD5_CTX   MD5context;
  875.     unsigned char   MD5digest[LUTIL_MD5_BYTES];
  876.  
  877.     struct berval digest;
  878.  
  879.     digest.bv_val = MD5digest;
  880.     digest.bv_len = sizeof(MD5digest);
  881.  
  882.     lutil_MD5Init( &MD5context );
  883.     lutil_MD5Update( &MD5context,
  884.         (const unsigned char *) passwd->bv_val, passwd->bv_len );
  885.     lutil_MD5Final( MD5digest, &MD5context );
  886.  
  887.     return pw_string64( scheme, &digest, NULL );
  888. ;
  889. }
  890.  
  891. #ifdef SLAPD_CRYPT
  892. static struct berval *hash_crypt(
  893.     const struct pw_scheme *scheme,
  894.     const struct berval *passwd )
  895. {
  896.     struct berval hash;
  897.     unsigned char salt[3];
  898.     int i;
  899.  
  900.     for( i=0; i<passwd->bv_len; i++) {
  901.         if(passwd->bv_val[i] == '\0') {
  902.             return NULL;    /* NUL character in password */
  903.         }
  904.     }
  905.  
  906.     if( passwd->bv_val[i] != '\0' ) {
  907.         return NULL;    /* passwd must behave like a string */
  908.     }
  909.  
  910.     if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
  911.         return NULL; 
  912.     }
  913.  
  914.     salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
  915.     salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
  916.     salt[2] = '\0';
  917.  
  918.     hash.bv_val = crypt( passwd->bv_val, salt );
  919.  
  920.     if( hash.bv_val == NULL ) return NULL;
  921.  
  922.     hash.bv_len = strlen( hash.bv_val );
  923.  
  924.     if( hash.bv_len == 0 ) {
  925.         return NULL;
  926.     }
  927.  
  928.     return pw_string( scheme, &hash );
  929. }
  930. #endif
  931. #endif
  932.