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