3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * lutil_password(credentials, password)
9 * Returns true if user supplied credentials matches
10 * the stored password.
12 * Due to the use of the crypt(3) function
13 * this routine is NOT thread-safe.
18 #include <ac/stdlib.h>
20 #include <ac/string.h>
21 #include <ac/unistd.h>
24 #include "lutil_md5.h"
25 #include "lutil_sha1.h"
35 static int is_allowed_scheme(
37 const char** schemes )
45 for(i=0; schemes[i] != NULL; i++) {
46 if(strcasecmp(scheme, schemes[i]) == 0) {
54 const char *lutil_passwd_schemes[] = {
60 # if defined( HAVE_GETSPNAM ) \
61 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
64 #ifdef SLAPD_CLEARTEXT
65 "{CLEARTEXT}", /* psuedo scheme */
70 int lutil_passwd_scheme( char *scheme ) {
71 return is_allowed_scheme( scheme, lutil_passwd_schemes );
74 static const char *passwd_scheme(
77 const char** schemes )
81 if( !is_allowed_scheme( scheme, schemes ) ) {
87 if( strncasecmp( passwd, scheme, len ) == 0 ) {
95 * Return 0 if creds are good.
101 const char **schemes)
105 if (cred == NULL || passwd == NULL) {
109 if ((p = passwd_scheme( passwd, "{MD5}", schemes )) != NULL ) {
110 lutil_MD5_CTX MD5context;
111 unsigned char MD5digest[16];
112 char base64digest[LUTIL_BASE64_ENCODE_LEN(16)];
114 lutil_MD5Init(&MD5context);
115 lutil_MD5Update(&MD5context,
116 (const unsigned char *)cred, strlen(cred));
117 lutil_MD5Final(MD5digest, &MD5context);
119 if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
120 base64digest, sizeof(base64digest)) < 0)
125 return( strcmp(p, base64digest) );
127 } else if ((p = passwd_scheme( passwd, "{SHA}", schemes )) != NULL ) {
128 lutil_SHA1_CTX SHA1context;
129 unsigned char SHA1digest[20];
130 char base64digest[LUTIL_BASE64_ENCODE_LEN(20)];
132 lutil_SHA1Init(&SHA1context);
133 lutil_SHA1Update(&SHA1context,
134 (const unsigned char *) cred, strlen(cred));
135 lutil_SHA1Final(SHA1digest, &SHA1context);
137 if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
138 base64digest, sizeof(base64digest)) < 0)
143 return( strcmp(p, base64digest) );
145 } else if ((p = passwd_scheme( passwd, "{SSHA}", schemes )) != NULL ) {
146 lutil_SHA1_CTX SHA1context;
147 unsigned char SHA1digest[20];
148 int pw_len = strlen(p);
150 unsigned char *orig_pass = NULL;
152 /* base64 un-encode password */
153 orig_pass = (unsigned char *) malloc( (size_t) (
154 LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
155 if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
161 /* hash credentials with salt */
162 lutil_SHA1Init(&SHA1context);
163 lutil_SHA1Update(&SHA1context,
164 (const unsigned char *) cred, strlen(cred));
165 lutil_SHA1Update(&SHA1context,
166 (const unsigned char *) orig_pass + sizeof(SHA1digest),
167 rc - sizeof(SHA1digest));
168 lutil_SHA1Final(SHA1digest, &SHA1context);
171 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
175 } else if ((p = passwd_scheme( passwd, "{SMD5}", schemes )) != NULL ) {
176 lutil_MD5_CTX MD5context;
177 unsigned char MD5digest[16];
178 int pw_len = strlen(p);
180 unsigned char *orig_pass = NULL;
182 /* base64 un-encode password */
183 orig_pass = (unsigned char *) malloc( (size_t) (
184 LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
185 if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
191 /* hash credentials with salt */
192 lutil_MD5Init(&MD5context);
193 lutil_MD5Update(&MD5context,
194 (const unsigned char *) cred, strlen(cred));
195 lutil_MD5Update(&MD5context,
196 (const unsigned char *) orig_pass + sizeof(MD5digest),
197 rc - sizeof(MD5digest));
198 lutil_MD5Final(MD5digest, &MD5context);
201 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
206 } else if ((p = passwd_scheme( passwd, "{CRYPT}", schemes )) != NULL ) {
207 return( strcmp(p, crypt(cred, p)) );
209 # if defined( HAVE_GETSPNAM ) \
210 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
211 } else if ((p = passwd_scheme( passwd, "{UNIX}", schemes )) != NULL ) {
213 # ifdef HAVE_GETSPNAM
214 struct spwd *spwd = getspnam(p);
217 return 1; /* not found */
220 return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
222 struct passwd *pwd = getpwnam(p);
225 return 1; /* not found */
228 return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
234 #ifdef SLAPD_CLEARTEXT
235 return is_allowed_scheme("{CLEARTEXT}", schemes ) &&
236 strcmp(passwd, cred) != 0;