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