]> git.sur5r.net Git - openldap/blob - servers/slapd/passwd.c
ITS#1716 is_entry_subentr/ies/y/
[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_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         char berbuf[256];
78         BerElement *ber = (BerElement *)berbuf;
79
80         if( reqdata == NULL ) {
81                 return LDAP_SUCCESS;
82         }
83
84         /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
85         ber_init2( ber, reqdata, 0 );
86
87         tag = ber_scanf( ber, "{" /*}*/ );
88
89         if( tag != LBER_ERROR ) {
90                 tag = ber_peek_tag( ber, &len );
91         }
92
93         if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
94                 if( id == NULL ) {
95 #ifdef NEW_LOGGING
96                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
97                                    "slap_passwd_parse: ID not allowed.\n"));
98 #else
99                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n",
100                                 0, 0, 0 );
101 #endif
102
103                         *text = "user must change own password";
104                         rc = LDAP_UNWILLING_TO_PERFORM;
105                         goto done;
106                 }
107
108                 tag = ber_scanf( ber, "m", id );
109
110                 if( tag == LBER_ERROR ) {
111 #ifdef NEW_LOGGING
112                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
113                                    "slap_passwd_parse:  ID parse failed.\n"));
114 #else
115                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
116                                 0, 0, 0 );
117 #endif
118
119                         goto decoding_error;
120                 }
121
122                 tag = ber_peek_tag( ber, &len);
123         }
124
125         if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ) {
126                 if( oldpass == NULL ) {
127 #ifdef NEW_LOGGING
128                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
129                                    "slap_passwd_parse: OLD not allowed.\n" ));
130 #else
131                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n",
132                                 0, 0, 0 );
133 #endif
134
135                         *text = "use bind to verify old password";
136                         rc = LDAP_UNWILLING_TO_PERFORM;
137                         goto done;
138                 }
139
140                 tag = ber_scanf( ber, "m", oldpass );
141
142                 if( tag == LBER_ERROR ) {
143 #ifdef NEW_LOGGING
144                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
145                                    "slap_passwd_parse:  ID parse failed.\n" ));
146 #else
147                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
148                                 0, 0, 0 );
149 #endif
150
151                         goto decoding_error;
152                 }
153
154                 tag = ber_peek_tag( ber, &len );
155         }
156
157         if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ) {
158                 if( newpass == NULL ) {
159 #ifdef NEW_LOGGING
160                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
161                                    "slap_passwd_parse:  NEW not allowed.\n" ));
162 #else
163                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n",
164                                 0, 0, 0 );
165 #endif
166
167                         *text = "user specified passwords disallowed";
168                         rc = LDAP_UNWILLING_TO_PERFORM;
169                         goto done;
170                 }
171
172                 tag = ber_scanf( ber, "m", newpass );
173
174                 if( tag == LBER_ERROR ) {
175 #ifdef NEW_LOGGING
176                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
177                                    "slap_passwd_parse:  OLD parse failed.\n"));
178 #else
179                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n",
180                                 0, 0, 0 );
181 #endif
182
183                         goto decoding_error;
184                 }
185
186                 tag = ber_peek_tag( ber, &len );
187         }
188
189         if( len != 0 ) {
190 decoding_error:
191 #ifdef NEW_LOGGING
192                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
193                            "slap_passwd_parse: decoding error, len=%ld\n", (long)len ));
194 #else
195                 Debug( LDAP_DEBUG_TRACE,
196                         "slap_passwd_parse: decoding error, len=%ld\n",
197                         (long) len, 0, 0 );
198 #endif
199
200
201                 *text = "data decoding error";
202                 rc = LDAP_PROTOCOL_ERROR;
203         }
204
205 done:
206         return rc;
207 }
208
209 struct berval * slap_passwd_return(
210         struct berval           *cred )
211 {
212         int rc;
213         struct berval *bv = NULL;
214         char berbuf[256];
215         /* opaque structure, size unknown but smaller than berbuf */
216         BerElement *ber = (BerElement *)berbuf;
217
218         assert( cred != NULL );
219
220 #ifdef NEW_LOGGING
221         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
222                    "slap_passwd_return: %ld\n",(long)cred->bv_len ));
223 #else
224         Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
225                 (long) cred->bv_len, 0, 0 );
226 #endif
227         
228         ber_init_w_nullc( ber, LBER_USE_DER );
229
230         rc = ber_printf( ber, "{tON}",
231                 LDAP_TAG_EXOP_MODIFY_PASSWD_GEN, cred );
232
233         if( rc >= 0 ) {
234                 (void) ber_flatten( ber, &bv );
235         }
236
237         ber_free_buf( ber );
238
239         return bv;
240 }
241
242 int
243 slap_passwd_check(
244         Connection *conn,
245         Attribute *a,
246         struct berval *cred )
247 {
248         int result = 1;
249         struct berval *bv;
250
251 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
252         ldap_pvt_thread_mutex_lock( &passwd_mutex );
253 #ifdef SLAPD_SPASSWD
254         lutil_passwd_sasl_conn = conn->c_sasl_context;
255 #endif
256 #endif
257
258         for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) {
259                 if( !lutil_passwd( bv, cred, NULL ) ) {
260                         result = 0;
261                         break;
262                 }
263         }
264
265 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
266 #ifdef SLAPD_SPASSWD
267         lutil_passwd_sasl_conn = NULL;
268 #endif
269         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
270 #endif
271
272         return result;
273 }
274
275 void
276 slap_passwd_generate( struct berval *pass )
277 {
278         struct berval *tmp;
279 #ifdef NEW_LOGGING
280         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
281                    "slap_passwd_generate: begin\n" ));
282 #else
283         Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
284 #endif
285         /*
286          * generate passwords of only 8 characters as some getpass(3)
287          * implementations truncate at 8 characters.
288          */
289         tmp = lutil_passwd_generate( 8 );
290         if (tmp) {
291                 *pass = *tmp;
292                 free(tmp);
293         } else {
294                 pass->bv_val = NULL;
295                 pass->bv_len = 0;
296         }
297 }
298
299 void
300 slap_passwd_hash(
301         struct berval * cred,
302         struct berval * new )
303 {
304         struct berval *tmp;
305 #ifdef LUTIL_SHA1_BYTES
306         char* hash = default_passwd_hash ?  default_passwd_hash : "{SSHA}";
307 #else
308         char* hash = default_passwd_hash ?  default_passwd_hash : "{SMD5}";
309 #endif
310         
311
312 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
313         ldap_pvt_thread_mutex_lock( &passwd_mutex );
314 #endif
315
316         tmp = lutil_passwd_hash( cred , hash );
317         assert( tmp != NULL );
318         
319 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
320         ldap_pvt_thread_mutex_unlock( &passwd_mutex );
321 #endif
322         *new = *tmp;
323         free( tmp );
324
325         return;
326 }