]> git.sur5r.net Git - openldap/blob - libraries/liblutil/passwd.c
New dn2id format with base/one/subtree indices (ldbm/bdb2)
[openldap] / libraries / liblutil / passwd.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*
6  * lutil_password(credentials, password)
7  *
8  * Returns true if user supplied credentials matches
9  * the stored password. 
10  *
11  * Due to the use of the crypt(3) function 
12  * this routine is NOT thread-safe.
13  */
14
15 #include "portable.h"
16
17 #include <ac/stdlib.h>
18
19 #include <ac/string.h>
20 #include <ac/unistd.h>
21
22 #include "lutil_md5.h"
23 #include "lutil_sha1.h"
24 #include "lutil.h"
25
26 #ifdef HAVE_SHADOW_H
27 #       include <shadow.h>
28 #endif
29 #ifdef HAVE_PWD_H
30 #       include <pwd.h>
31 #endif
32
33 static int supported_hash(
34         const char* method,
35         const char** methods )
36 {
37         int i;
38
39         if(methods == NULL) {
40                 return 1;
41         }
42
43         for(i=0; methods[i] != NULL; i++) {
44                 if(strcasecmp(method, methods[i]) == 0) {
45                         return 1;
46                 }
47         }
48
49         return 0;
50 }
51
52 static const char *passwd_hash(
53         const char* passwd,
54         const char* method,
55         const char** methods )
56 {
57         int len;
58
59         if( !supported_hash( method, methods ) ) {
60                 return NULL;
61         }
62
63         len = strlen(method);
64
65         if( strncasecmp( passwd, method, len ) == 0 ) {
66                 return &passwd[len];
67         }
68
69         return NULL;
70 }
71
72 /*
73  * Return 0 if creds are good.
74  */
75 int
76 lutil_passwd(
77         const char *cred,
78         const char *passwd,
79         const char **methods)
80 {
81         const char *p;
82
83         if (cred == NULL || passwd == NULL) {
84                 return -1;
85         }
86
87         if ((p = passwd_hash( passwd, "{MD5}", methods )) != NULL ) {
88                 lutil_MD5_CTX MD5context;
89                 unsigned char MD5digest[16];
90                 char base64digest[25];  /* ceiling(sizeof(input)/3) * 4 + 1 */
91
92                 lutil_MD5Init(&MD5context);
93                 lutil_MD5Update(&MD5context,
94                                (const unsigned char *)cred, strlen(cred));
95                 lutil_MD5Final(MD5digest, &MD5context);
96
97                 if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
98                         base64digest, sizeof(base64digest)) < 0)
99                 {
100                         return ( 1 );
101                 }
102
103                 return( strcmp(p, base64digest) );
104
105         } else if ((p = passwd_hash( passwd, "{SHA}", methods )) != NULL ) {
106                 lutil_SHA1_CTX SHA1context;
107                 unsigned char SHA1digest[20];
108                 char base64digest[29];  /* ceiling(sizeof(input)/3) * 4 + 1 */
109
110                 lutil_SHA1Init(&SHA1context);
111                 lutil_SHA1Update(&SHA1context,
112                                 (const unsigned char *) cred, strlen(cred));
113                 lutil_SHA1Final(SHA1digest, &SHA1context);
114
115                 if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
116                         base64digest, sizeof(base64digest)) < 0)
117                 {
118                         return ( 1 );
119                 }
120
121                 return( strcmp(p, base64digest) );
122
123         } else if ((p = passwd_hash( passwd, "{SSHA}", methods )) != NULL ) {
124                 lutil_SHA1_CTX SHA1context;
125                 unsigned char SHA1digest[20];
126                 int pw_len = strlen(p);
127                 int rc;
128                 unsigned char *orig_pass = NULL;
129  
130                 /* base64 un-encode password */
131                 orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1));
132                 if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
133                 {
134                         free(orig_pass);
135                         return ( 1 );
136                 }
137  
138                 /* hash credentials with salt */
139                 lutil_SHA1Init(&SHA1context);
140                 lutil_SHA1Update(&SHA1context,
141                                 (const unsigned char *) cred, strlen(cred));
142                 lutil_SHA1Update(&SHA1context,
143                                 (const unsigned char *) orig_pass + sizeof(SHA1digest),
144                                 rc - sizeof(SHA1digest));
145                 lutil_SHA1Final(SHA1digest, &SHA1context);
146  
147                 /* compare */
148                 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
149                 free(orig_pass);
150                 return(rc);
151
152         } else if ((p = passwd_hash( passwd, "{SMD5}", methods )) != NULL ) {
153                 lutil_MD5_CTX MD5context;
154                 unsigned char MD5digest[16];
155                 int pw_len = strlen(p);
156                 int rc;
157                 unsigned char *orig_pass = NULL;
158
159                 /* base64 un-encode password */
160                 orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1));
161                 if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
162                 {
163                         free(orig_pass);
164                         return ( 1 );
165                 }
166
167                 /* hash credentials with salt */
168                 lutil_MD5Init(&MD5context);
169                 lutil_MD5Update(&MD5context,
170                                 (const unsigned char *) cred, strlen(cred));
171                 lutil_MD5Update(&MD5context,
172                                 (const unsigned char *) orig_pass + sizeof(MD5digest),
173                                 rc - sizeof(MD5digest));
174                 lutil_MD5Final(MD5digest, &MD5context);
175
176                 /* compare */
177                 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
178                 free(orig_pass);
179                 return ( rc );
180
181 #ifdef SLAPD_CRYPT
182         } else if ((p = passwd_hash( passwd, "{CRYPT}", methods )) != NULL ) {
183                 return( strcmp(p, crypt(cred, p)) );
184
185 # if defined( HAVE_GETSPNAM ) \
186   || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
187         } else if ((p = passwd_hash( passwd, "{UNIX}", methods )) != NULL ) {
188
189 #  ifdef HAVE_GETSPNAM
190                 struct spwd *spwd = getspnam(p);
191
192                 if(spwd == NULL) {
193                         return 1;       /* not found */
194                 }
195
196                 return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
197 #  else
198                 struct passwd *pwd = getpwnam(p);
199
200                 if(pwd == NULL) {
201                         return 1;       /* not found */
202                 }
203
204                 return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
205 #  endif
206 # endif
207 #endif
208         }
209
210 #ifdef SLAPD_CLEARTEXT
211         return supported_hash("{CLEARTEXT}", methods ) &&
212                 strcmp(passwd, cred) != 0;
213 #else
214         return( 1 );
215 #endif
216
217 }