]> git.sur5r.net Git - openldap/blob - libraries/liblutil/passwd.c
* build/top.mk: removed references to TMPROOT and added DESTDIR support
[openldap] / libraries / liblutil / passwd.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * lutil_password(credentials, password)
8  *
9  * Returns true if user supplied credentials matches
10  * the stored password. 
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 <ac/stdlib.h>
19
20 #include <ac/string.h>
21 #include <ac/unistd.h>
22
23 #include "lutil_md5.h"
24 #include "lutil_sha1.h"
25 #include "lutil.h"
26
27 #ifdef HAVE_SHADOW_H
28 #       include <shadow.h>
29 #endif
30 #ifdef HAVE_PWD_H
31 #       include <pwd.h>
32 #endif
33
34 static int supported_hash(
35         const char* method,
36         const char** methods )
37 {
38         int i;
39
40         if(methods == NULL) {
41                 return 1;
42         }
43
44         for(i=0; methods[i] != NULL; i++) {
45                 if(strcasecmp(method, methods[i]) == 0) {
46                         return 1;
47                 }
48         }
49
50         return 0;
51 }
52
53 static const char *passwd_hash(
54         const char* passwd,
55         const char* method,
56         const char** methods )
57 {
58         int len;
59
60         if( !supported_hash( method, methods ) ) {
61                 return NULL;
62         }
63
64         len = strlen(method);
65
66         if( strncasecmp( passwd, method, len ) == 0 ) {
67                 return &passwd[len];
68         }
69
70         return NULL;
71 }
72
73 /*
74  * Return 0 if creds are good.
75  */
76 int
77 lutil_passwd(
78         const char *cred,
79         const char *passwd,
80         const char **methods)
81 {
82         const char *p;
83
84         if (cred == NULL || passwd == NULL) {
85                 return -1;
86         }
87
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 */
92
93                 lutil_MD5Init(&MD5context);
94                 lutil_MD5Update(&MD5context,
95                                (const unsigned char *)cred, strlen(cred));
96                 lutil_MD5Final(MD5digest, &MD5context);
97
98                 if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
99                         base64digest, sizeof(base64digest)) < 0)
100                 {
101                         return ( 1 );
102                 }
103
104                 return( strcmp(p, base64digest) );
105
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 */
110
111                 lutil_SHA1Init(&SHA1context);
112                 lutil_SHA1Update(&SHA1context,
113                                 (const unsigned char *) cred, strlen(cred));
114                 lutil_SHA1Final(SHA1digest, &SHA1context);
115
116                 if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
117                         base64digest, sizeof(base64digest)) < 0)
118                 {
119                         return ( 1 );
120                 }
121
122                 return( strcmp(p, base64digest) );
123
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);
128                 int rc;
129                 unsigned char *orig_pass = NULL;
130  
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)
134                 {
135                         free(orig_pass);
136                         return ( 1 );
137                 }
138  
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);
147  
148                 /* compare */
149                 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
150                 free(orig_pass);
151                 return(rc);
152
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);
157                 int rc;
158                 unsigned char *orig_pass = NULL;
159
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)
163                 {
164                         free(orig_pass);
165                         return ( 1 );
166                 }
167
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);
176
177                 /* compare */
178                 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
179                 free(orig_pass);
180                 return ( rc );
181
182 #ifdef SLAPD_CRYPT
183         } else if ((p = passwd_hash( passwd, "{CRYPT}", methods )) != NULL ) {
184                 return( strcmp(p, crypt(cred, p)) );
185
186 # if defined( HAVE_GETSPNAM ) \
187   || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
188         } else if ((p = passwd_hash( passwd, "{UNIX}", methods )) != NULL ) {
189
190 #  ifdef HAVE_GETSPNAM
191                 struct spwd *spwd = getspnam(p);
192
193                 if(spwd == NULL) {
194                         return 1;       /* not found */
195                 }
196
197                 return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
198 #  else
199                 struct passwd *pwd = getpwnam(p);
200
201                 if(pwd == NULL) {
202                         return 1;       /* not found */
203                 }
204
205                 return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
206 #  endif
207 # endif
208 #endif
209         }
210
211 #ifdef SLAPD_CLEARTEXT
212         return supported_hash("{CLEARTEXT}", methods ) &&
213                 strcmp(passwd, cred) != 0;
214 #else
215         return( 1 );
216 #endif
217
218 }