]> git.sur5r.net Git - openldap/blob - servers/slapd/passwd.c
Y2k copyright update
[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         SLAP_EXTOP_CALLBACK_FN ext_callback,
23         Connection *conn, Operation *op,
24         char *reqoid,
25         struct berval *reqdata,
26         char **rspoid,
27         struct berval **rspdata,
28         LDAPControl ***rspctrls,
29         char **text,
30         struct berval ***refs )
31 {
32         int rc;
33
34         assert( reqoid != NULL );
35         assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, reqoid ) == 0 );
36
37         if( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
38                 *text = "only authenicated 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         {
44                 if( global_readonly || conn->c_authz_backend->be_readonly ) {
45                         *text = "authorization database is read only";
46                         rc = LDAP_UNWILLING_TO_PERFORM;
47
48                 } else if( conn->c_authz_backend->be_update_ndn != NULL ) {
49                         /* we SHOULD return a referral in this case */
50                         *refs = conn->c_authz_backend->be_update_refs;
51                         rc = LDAP_REFERRAL;
52
53                 } else {
54                         rc = conn->c_authz_backend->be_extended(
55                                 conn->c_authz_backend, conn, op,
56                                 reqoid, reqdata,
57                                 rspoid, rspdata, rspctrls,
58                                 text, refs );
59                 }
60
61         } else {
62                 *text = "operation not supported for current user";
63                 rc = LDAP_UNWILLING_TO_PERFORM;
64         }
65
66         return rc;
67 }
68
69 int slap_passwd_parse( struct berval *reqdata,
70         struct berval **id,
71         struct berval **oldpass,
72         struct berval **newpass,
73         char **text )
74 {
75         int rc = LDAP_SUCCESS;
76         ber_tag_t tag;
77         ber_len_t len;
78         BerElement *ber;
79
80         if( reqdata == NULL ) {
81                 return LDAP_SUCCESS;
82         }
83
84         ber = ber_init( reqdata );
85
86         if( ber == NULL ) {
87                 Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ber_init failed\n",
88                         0, 0, 0 );
89                 *text = "password decoding error";
90                 return LDAP_PROTOCOL_ERROR;
91         }
92
93         tag = ber_scanf( ber, "{" /*}*/ );
94
95         if( tag != LBER_ERROR ) {
96                 tag = ber_peek_tag( ber, &len );
97         }
98
99         if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID ) {
100                 if( id == NULL ) {
101                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n",
102                                 0, 0, 0 );
103                         *text = "user must change own password";
104                         rc = LDAP_UNWILLING_TO_PERFORM;
105                         goto done;
106                 }
107
108                 tag = ber_scanf( ber, "O", id );
109
110                 if( tag == LBER_ERROR ) {
111                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
112                                 0, 0, 0 );
113                         goto decoding_error;
114                 }
115
116                 tag = ber_peek_tag( ber, &len);
117         }
118
119         if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_OLD ) {
120                 if( oldpass == NULL ) {
121                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n",
122                                 0, 0, 0 );
123                         *text = "use bind to verify old password";
124                         rc = LDAP_UNWILLING_TO_PERFORM;
125                         goto done;
126                 }
127
128                 tag = ber_scanf( ber, "O", oldpass );
129
130                 if( tag == LBER_ERROR ) {
131                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
132                                 0, 0, 0 );
133                         goto decoding_error;
134                 }
135
136                 tag = ber_peek_tag( ber, &len);
137         }
138
139         if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW ) {
140                 if( newpass == NULL ) {
141                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n",
142                                 0, 0, 0 );
143                         *text = "user specified passwords disallowed";
144                         rc = LDAP_UNWILLING_TO_PERFORM;
145                         goto done;
146                 }
147
148                 tag = ber_scanf( ber, "O", newpass );
149
150                 if( tag == LBER_ERROR ) {
151                         Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n",
152                                 0, 0, 0 );
153                         goto decoding_error;
154                 }
155
156                 tag = ber_peek_tag( ber, &len );
157         }
158
159         if( len != 0 ) {
160 decoding_error:
161                 Debug( LDAP_DEBUG_TRACE,
162                         "slap_passwd_parse: decoding error, len=%ld\n",
163                         (long) len, 0, 0 );
164
165                 *text = "data decoding error";
166                 rc = LDAP_PROTOCOL_ERROR;
167         }
168
169 done:
170         if( rc != LDAP_SUCCESS ) {
171                 if( id != NULL ) {
172                         ber_bvfree( *id );
173                         *id = NULL;
174                 }
175
176                 if( oldpass != NULL ) {
177                         ber_bvfree( *oldpass );
178                         *oldpass = NULL;
179                 }
180
181                 if( newpass != NULL ) {
182                         ber_bvfree( *newpass );
183                         *newpass = NULL;
184                 }
185         }
186
187         ber_free( ber, 1 );
188         return rc;
189 }
190
191 struct berval * slap_passwd_return(
192         struct berval           *cred )
193 {
194         int rc;
195         struct berval *bv;
196         BerElement *ber = ber_alloc_t(LBER_USE_DER);
197
198         assert( cred != NULL );
199
200         Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
201                 (long) cred->bv_len, 0, 0 );
202
203         if( ber == NULL ) return NULL;
204         
205         rc = ber_printf( ber, "{tO}",
206                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_GEN, cred );
207
208         if( rc == -1 ) {
209                 ber_free( ber, 1 );
210                 return NULL;
211         }
212
213         (void) ber_flatten( ber, &bv );
214
215         ber_free( ber, 1 );
216
217         return bv;
218 }
219
220 int
221 slap_passwd_check(
222         Attribute *a,
223         struct berval *cred )
224 {
225         int     i;
226         for ( i = 0; a->a_vals[i] != NULL; i++ ) {
227                 int result;
228
229 #ifdef SLAPD_CRYPT
230                 ldap_pvt_thread_mutex_lock( &crypt_mutex );
231 #endif
232
233                 result = lutil_passwd( a->a_vals[i], cred, NULL );
234
235 #ifdef SLAPD_CRYPT
236                 ldap_pvt_thread_mutex_unlock( &crypt_mutex );
237 #endif
238
239                 if( !result )
240                         return result;
241         }
242
243         return( 1 );
244 }
245
246 struct berval * slap_passwd_generate( void )
247 {
248         Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
249
250         /*
251          * generate passwords of only 8 characters as some getpass(3)
252          * implementations truncate at 8 characters.
253          */
254         return lutil_passwd_generate( 8 );
255 }
256
257 struct berval * slap_passwd_hash(
258         struct berval * cred )
259 {
260         char* hash = default_passwd_hash ? default_passwd_hash : "{SSHA}";
261
262         struct berval *new;
263
264 #ifdef SLAPD_CRYPT
265         ldap_pvt_thread_mutex_lock( &crypt_mutex );
266 #endif
267
268         new = lutil_passwd_hash( cred , hash );
269         
270 #ifdef SLAPD_CRYPT
271         ldap_pvt_thread_mutex_unlock( &crypt_mutex );
272 #endif
273
274         return new;
275 }