]> git.sur5r.net Git - openldap/blob - servers/slapd/passwd.c
6e0b31b0e338bc53db8e096e3662010137f67a19
[openldap] / servers / slapd / passwd.c
1 /* bind.c - ldbm backend bind and unbind routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/krb.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/unistd.h>
16
17 #include "slap.h"
18
19 #include <lutil.h>
20
21 int passwd_extop(
22         Connection *conn, Operation *op,
23         const char *reqoid,
24         struct berval *reqdata,
25         char **rspoid,
26         struct berval **rspdata,
27         LDAPControl ***rspctrls,
28         const char **text,
29         struct berval ***refs )
30 {
31         int rc;
32
33         assert( reqoid != NULL );
34         assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, reqoid ) == 0 );
35
36         if( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
37                 *text = "only authenicated users may change passwords";
38                 return LDAP_STRONG_AUTH_REQUIRED;
39         }
40
41         if( conn->c_authz_backend != NULL && conn->c_authz_backend->be_extended ) {
42                 if( conn->c_authz_backend->be_restrictops & SLAP_RESTRICT_OP_MODIFY ) {
43                         *text = "authorization database is read only";
44                         rc = LDAP_UNWILLING_TO_PERFORM;
45
46                 } else if( conn->c_authz_backend->be_update_ndn != NULL ) {
47                         /* we SHOULD return a referral in this case */
48                         *refs = conn->c_authz_backend->be_update_refs;
49                         rc = LDAP_REFERRAL;
50
51                 } else {
52                         rc = conn->c_authz_backend->be_extended(
53                                 conn->c_authz_backend, conn, op,
54                                 reqoid, reqdata,
55                                 rspoid, rspdata, rspctrls,
56                                 text, refs );
57                 }
58
59         } else {
60                 *text = "operation not supported for current user";
61                 rc = LDAP_UNWILLING_TO_PERFORM;
62         }
63
64         return rc;
65 }
66
67 int slap_passwd_parse( struct berval *reqdata,
68         struct berval **id,
69         struct berval **oldpass,
70         struct berval **newpass,
71         const char **text )
72 {
73         int rc = LDAP_SUCCESS;
74         ber_tag_t tag;
75         ber_len_t len;
76         BerElement *ber;
77
78         if( reqdata == NULL ) {
79                 return LDAP_SUCCESS;
80         }
81
82         ber = ber_init( reqdata );
83
84         if( ber == NULL ) {
85 #ifdef NEW_LOGGING
86                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
87                            "slap_passwd_parse: ber_init failed\n" ));
88 #else
89                 Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ber_init failed\n",
90                         0, 0, 0 );
91 #endif
92
93                 *text = "password decoding error";
94                 return LDAP_PROTOCOL_ERROR;
95         }
96
97         tag = ber_scanf( ber, "{" /*}*/ );
98
99         if( tag != LBER_ERROR ) {
100                 tag = ber_peek_tag( ber, &len );
101         }
102
103         if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID ) {
104                 if( id == NULL ) {
105 #ifdef NEW_LOGGING
106                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
107                                    "slap_passwd_parse: ID not allowed.\n"));
108 #else
109                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n",
110                                 0, 0, 0 );
111 #endif
112
113                         *text = "user must change own password";
114                         rc = LDAP_UNWILLING_TO_PERFORM;
115                         goto done;
116                 }
117
118                 tag = ber_scanf( ber, "O", id );
119
120                 if( tag == LBER_ERROR ) {
121 #ifdef NEW_LOGGING
122                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
123                                    "slap_passwd_parse:  ID parse failed.\n"));
124 #else
125                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
126                                 0, 0, 0 );
127 #endif
128
129                         goto decoding_error;
130                 }
131
132                 tag = ber_peek_tag( ber, &len);
133         }
134
135         if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_OLD ) {
136                 if( oldpass == NULL ) {
137 #ifdef NEW_LOGGING
138                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
139                                    "slap_passwd_parse: OLD not allowed.\n" ));
140 #else
141                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n",
142                                 0, 0, 0 );
143 #endif
144
145                         *text = "use bind to verify old password";
146                         rc = LDAP_UNWILLING_TO_PERFORM;
147                         goto done;
148                 }
149
150                 tag = ber_scanf( ber, "O", oldpass );
151
152                 if( tag == LBER_ERROR ) {
153 #ifdef NEW_LOGGING
154                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
155                                    "slap_passwd_parse:  ID parse failed.\n" ));
156 #else
157                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
158                                 0, 0, 0 );
159 #endif
160
161                         goto decoding_error;
162                 }
163
164                 tag = ber_peek_tag( ber, &len);
165         }
166
167         if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW ) {
168                 if( newpass == NULL ) {
169 #ifdef NEW_LOGGING
170                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
171                                    "slap_passwd_parse:  NEW not allowed.\n" ));
172 #else
173                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n",
174                                 0, 0, 0 );
175 #endif
176
177                         *text = "user specified passwords disallowed";
178                         rc = LDAP_UNWILLING_TO_PERFORM;
179                         goto done;
180                 }
181
182                 tag = ber_scanf( ber, "O", newpass );
183
184                 if( tag == LBER_ERROR ) {
185 #ifdef NEW_LOGGING
186                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
187                                    "slap_passwd_parse:  OLD parse failed.\n"));
188 #else
189                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n",
190                                 0, 0, 0 );
191 #endif
192
193                         goto decoding_error;
194                 }
195
196                 tag = ber_peek_tag( ber, &len );
197         }
198
199         if( len != 0 ) {
200 decoding_error:
201 #ifdef NEW_LOGGING
202                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
203                            "slap_passwd_parse: decoding error, len=%ld\n", (long)len ));
204 #else
205                 Debug( LDAP_DEBUG_TRACE,
206                         "slap_passwd_parse: decoding error, len=%ld\n",
207                         (long) len, 0, 0 );
208 #endif
209
210
211                 *text = "data decoding error";
212                 rc = LDAP_PROTOCOL_ERROR;
213         }
214
215 done:
216         if( rc != LDAP_SUCCESS ) {
217                 if( id != NULL ) {
218                         ber_bvfree( *id );
219                         *id = NULL;
220                 }
221
222                 if( oldpass != NULL ) {
223                         ber_bvfree( *oldpass );
224                         *oldpass = NULL;
225                 }
226
227                 if( newpass != NULL ) {
228                         ber_bvfree( *newpass );
229                         *newpass = NULL;
230                 }
231         }
232
233         ber_free( ber, 1 );
234         return rc;
235 }
236
237 struct berval * slap_passwd_return(
238         struct berval           *cred )
239 {
240         int rc;
241         struct berval *bv;
242         BerElement *ber = ber_alloc_t(LBER_USE_DER);
243
244         assert( cred != NULL );
245
246 #ifdef NEW_LOGGING
247         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
248                    "slap_passwd_return: %ld\n",(long)cred->bv_len ));
249 #else
250         Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
251                 (long) cred->bv_len, 0, 0 );
252 #endif
253
254
255         if( ber == NULL ) return NULL;
256         
257         rc = ber_printf( ber, "{tON}",
258                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_GEN, cred );
259
260         if( rc == -1 ) {
261                 ber_free( ber, 1 );
262                 return NULL;
263         }
264
265         (void) ber_flatten( ber, &bv );
266
267         ber_free( ber, 1 );
268
269         return bv;
270 }
271
272 int
273 slap_passwd_check(
274         Connection *conn,
275         Attribute *a,
276         struct berval *cred )
277 {
278         int     i;
279         int result = 1;
280
281 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
282         ldap_pvt_thread_mutex_lock( &passwd_mutex );
283 #ifdef SLAPD_SPASSWD
284         lutil_passwd_sasl_conn = conn->c_sasl_context;
285 #endif
286 #endif
287
288         for ( i = 0; a->a_vals[i] != NULL; i++ ) {
289                 if( !lutil_passwd( a->a_vals[i], cred, NULL ) ) {
290                         result = 0;
291                         break;
292                 }
293         }
294
295 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
296 #ifdef SLAPD_SPASSWD
297         lutil_passwd_sasl_conn = NULL;
298 #endif
299         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
300 #endif
301
302         return result;
303 }
304
305 struct berval * slap_passwd_generate( void )
306 {
307 #ifdef NEW_LOGGING
308         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
309                    "slap_passwd_generate: begin\n" ));
310 #else
311         Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
312 #endif
313
314
315         /*
316          * generate passwords of only 8 characters as some getpass(3)
317          * implementations truncate at 8 characters.
318          */
319         return lutil_passwd_generate( 8 );
320 }
321
322 struct berval * slap_passwd_hash(
323         struct berval * cred )
324 {
325 #ifdef LUTIL_SHA1_BYTES
326         char* hash = default_passwd_hash ?  default_passwd_hash : "{SSHA}";
327 #else
328         char* hash = default_passwd_hash ?  default_passwd_hash : "{SMD5}";
329 #endif
330         
331
332         struct berval *new;
333
334 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
335         ldap_pvt_thread_mutex_lock( &passwd_mutex );
336 #endif
337
338         new = lutil_passwd_hash( cred , hash );
339         
340 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
341         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
342 #endif
343
344         return new;
345 }