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>
23 #include "lutil_md5.h"
24 #include "lutil_sha1.h"
34 static int supported_hash(
36 const char** methods )
44 for(i=0; methods[i] != NULL; i++) {
45 if(strcasecmp(method, methods[i]) == 0) {
53 static const char *passwd_hash(
56 const char** methods )
60 if( !supported_hash( method, methods ) ) {
66 if( strncasecmp( passwd, method, len ) == 0 ) {
74 * Return 0 if creds are good.
84 if (cred == NULL || passwd == NULL) {
88 if ((p = passwd_hash( passwd, "{MD5}", methods )) != NULL ) {
89 lutil_MD5_CTX MD5context;
90 unsigned char MD5digest[16];
91 char base64digest[25]; /* ceiling(sizeof(input)/3) * 4 + 1 */
93 lutil_MD5Init(&MD5context);
94 lutil_MD5Update(&MD5context,
95 (const unsigned char *)cred, strlen(cred));
96 lutil_MD5Final(MD5digest, &MD5context);
98 if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
99 base64digest, sizeof(base64digest)) < 0)
104 return( strcmp(p, base64digest) );
106 } else if ((p = passwd_hash( passwd, "{SHA}", methods )) != NULL ) {
107 lutil_SHA1_CTX SHA1context;
108 unsigned char SHA1digest[20];
109 char base64digest[29]; /* ceiling(sizeof(input)/3) * 4 + 1 */
111 lutil_SHA1Init(&SHA1context);
112 lutil_SHA1Update(&SHA1context,
113 (const unsigned char *) cred, strlen(cred));
114 lutil_SHA1Final(SHA1digest, &SHA1context);
116 if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
117 base64digest, sizeof(base64digest)) < 0)
122 return( strcmp(p, base64digest) );
124 } else if ((p = passwd_hash( passwd, "{SSHA}", methods )) != NULL ) {
125 lutil_SHA1_CTX SHA1context;
126 unsigned char SHA1digest[20];
127 int pw_len = strlen(p);
129 unsigned char *orig_pass = NULL;
131 /* base64 un-encode password */
132 orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1));
133 if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
139 /* hash credentials with salt */
140 lutil_SHA1Init(&SHA1context);
141 lutil_SHA1Update(&SHA1context,
142 (const unsigned char *) cred, strlen(cred));
143 lutil_SHA1Update(&SHA1context,
144 (const unsigned char *) orig_pass + sizeof(SHA1digest),
145 rc - sizeof(SHA1digest));
146 lutil_SHA1Final(SHA1digest, &SHA1context);
149 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
153 } else if ((p = passwd_hash( passwd, "{SMD5}", methods )) != NULL ) {
154 lutil_MD5_CTX MD5context;
155 unsigned char MD5digest[16];
156 int pw_len = strlen(p);
158 unsigned char *orig_pass = NULL;
160 /* base64 un-encode password */
161 orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1));
162 if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
168 /* hash credentials with salt */
169 lutil_MD5Init(&MD5context);
170 lutil_MD5Update(&MD5context,
171 (const unsigned char *) cred, strlen(cred));
172 lutil_MD5Update(&MD5context,
173 (const unsigned char *) orig_pass + sizeof(MD5digest),
174 rc - sizeof(MD5digest));
175 lutil_MD5Final(MD5digest, &MD5context);
178 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
183 } else if ((p = passwd_hash( passwd, "{CRYPT}", methods )) != NULL ) {
184 return( strcmp(p, crypt(cred, p)) );
186 # if defined( HAVE_GETSPNAM ) \
187 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
188 } else if ((p = passwd_hash( passwd, "{UNIX}", methods )) != NULL ) {
190 # ifdef HAVE_GETSPNAM
191 struct spwd *spwd = getspnam(p);
194 return 1; /* not found */
197 return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
199 struct passwd *pwd = getpwnam(p);
202 return 1; /* not found */
205 return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
211 #ifdef SLAPD_CLEARTEXT
212 return supported_hash("{CLEARTEXT}", methods ) &&
213 strcmp(passwd, cred) != 0;