]> git.sur5r.net Git - openldap/blob - servers/slapd/passwd.c
f5ee86d109c820f12b8c4fcfef34dd95132097f7
[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.bv_len == 0 ) {
37                 *text = "only authenticated 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.bv_len ) {
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 = NULL;
243         char berbuf[256];
244         /* opaque structure, size unknown but smaller than berbuf */
245         BerElement *ber = (BerElement *)berbuf;
246
247         assert( cred != NULL );
248
249 #ifdef NEW_LOGGING
250         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
251                    "slap_passwd_return: %ld\n",(long)cred->bv_len ));
252 #else
253         Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
254                 (long) cred->bv_len, 0, 0 );
255 #endif
256         
257         ber_init_w_nullc( ber, LBER_USE_DER );
258
259         rc = ber_printf( ber, "{tON}",
260                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_GEN, cred );
261
262         if( rc >= 0 ) {
263                 (void) ber_flatten( ber, &bv );
264         }
265
266         ber_free_buf( ber );
267
268         return bv;
269 }
270
271 int
272 slap_passwd_check(
273         Connection *conn,
274         Attribute *a,
275         struct berval *cred )
276 {
277         int     i;
278         int result = 1;
279
280 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
281         ldap_pvt_thread_mutex_lock( &passwd_mutex );
282 #ifdef SLAPD_SPASSWD
283         lutil_passwd_sasl_conn = conn->c_sasl_context;
284 #endif
285 #endif
286
287         for ( i = 0; a->a_vals[i] != NULL; i++ ) {
288                 if( !lutil_passwd( a->a_vals[i], cred, NULL ) ) {
289                         result = 0;
290                         break;
291                 }
292         }
293
294 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
295 #ifdef SLAPD_SPASSWD
296         lutil_passwd_sasl_conn = NULL;
297 #endif
298         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
299 #endif
300
301         return result;
302 }
303
304 struct berval * slap_passwd_generate( void )
305 {
306 #ifdef NEW_LOGGING
307         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
308                    "slap_passwd_generate: begin\n" ));
309 #else
310         Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
311 #endif
312
313
314         /*
315          * generate passwords of only 8 characters as some getpass(3)
316          * implementations truncate at 8 characters.
317          */
318         return lutil_passwd_generate( 8 );
319 }
320
321 struct berval * slap_passwd_hash(
322         struct berval * cred )
323 {
324 #ifdef LUTIL_SHA1_BYTES
325         char* hash = default_passwd_hash ?  default_passwd_hash : "{SSHA}";
326 #else
327         char* hash = default_passwd_hash ?  default_passwd_hash : "{SMD5}";
328 #endif
329         
330
331         struct berval *new;
332
333 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
334         ldap_pvt_thread_mutex_lock( &passwd_mutex );
335 #endif
336
337         new = lutil_passwd_hash( cred , hash );
338         
339 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
340         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
341 #endif
342
343         return new;
344 }