home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / liblutil / passwd.c < prev    next >
C/C++ Source or Header  |  2001-06-14  |  24KB  |  1,078 lines

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