]> git.sur5r.net Git - openldap/blob - servers/slapd/passwd.c
Changed be_issuffix and dnParent to struct bervals
[openldap] / servers / slapd / passwd.c
1 /* bind.c - ldbm backend bind and unbind routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 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         BerVarray *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, "m", 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, "m", 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, "m", 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 && id->bv_val != NULL ) {
219                         free( id->bv_val );
220                         id->bv_val = NULL;
221                 }
222
223                 if( oldpass && oldpass->bv_val != NULL ) {
224                         free( oldpass->bv_val );
225                         oldpass->bv_val = NULL;
226                 }
227
228                 if( newpass && newpass->bv_val != NULL ) {
229                         free( newpass->bv_val );
230                         newpass->bv_val = 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 result = 1;
278         struct berval *bv;
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 ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) {
288                 if( !lutil_passwd( bv, 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 void
305 slap_passwd_generate( struct berval *pass )
306 {
307         struct berval *tmp;
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          * generate passwords of only 8 characters as some getpass(3)
316          * implementations truncate at 8 characters.
317          */
318         tmp = lutil_passwd_generate( 8 );
319         if (tmp) {
320                 *pass = *tmp;
321                 free(tmp);
322         } else {
323                 pass->bv_val = NULL;
324                 pass->bv_len = 0;
325         }
326 }
327
328 void
329 slap_passwd_hash(
330         struct berval * cred,
331         struct berval * new )
332 {
333         struct berval *tmp;
334 #ifdef LUTIL_SHA1_BYTES
335         char* hash = default_passwd_hash ?  default_passwd_hash : "{SSHA}";
336 #else
337         char* hash = default_passwd_hash ?  default_passwd_hash : "{SMD5}";
338 #endif
339         
340
341 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
342         ldap_pvt_thread_mutex_lock( &passwd_mutex );
343 #endif
344
345         tmp = lutil_passwd_hash( cred , hash );
346         
347 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
348         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
349 #endif
350         *new = *tmp;
351         free( tmp );
352
353         return;
354 }