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