]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/bind.c
dc8b873bf5c9b9ce3d4ff9d6ce40c90d5ae624b1
[openldap] / servers / slapd / back-ldbm / bind.c
1 /* bind.c - ldbm backend bind and unbind routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 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 #include "back-ldbm.h"
19 #include "proto-back-ldbm.h"
20
21 int
22 ldbm_back_bind(
23     Backend             *be,
24     Connection          *conn,
25     Operation           *op,
26     char                *dn,
27     char                *ndn,
28     int                 method,
29         char            *mech,
30     struct berval       *cred,
31         char**  edn
32 )
33 {
34         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
35         Entry           *e;
36         Attribute       *a;
37         int             rc;
38         Entry           *matched;
39 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
40         char            krbname[MAX_K_NAME_SZ + 1];
41         AUTH_DAT        ad;
42 #endif
43
44 #ifdef SLAPD_SCHEMA_NOT_COMPAT
45         static AttributeDescription *password = NULL;
46         static AttributeDescription *entry = NULL;
47 #else
48         static const char *password = "userpassword";
49         static const char *entry = "entry";
50 #endif
51
52         Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn, 0, 0);
53
54         *edn = NULL;
55         dn = ndn;
56
57         /* get entry with reader lock */
58         if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
59                 char *matched_dn = NULL;
60                 struct berval **refs = NULL;
61
62                 if( matched != NULL ) {
63                         matched_dn = ch_strdup( matched->e_dn );
64
65                         refs = is_entry_referral( matched )
66                                 ? get_entry_referrals( be, conn, op, matched )
67                                 : NULL;
68
69                         cache_return_entry_r( &li->li_cache, matched );
70                 } else {
71                         refs = default_referral;
72                 }
73
74                 /* allow noauth binds */
75                 rc = 1;
76                 if ( method == LDAP_AUTH_SIMPLE ) {
77                         if( cred->bv_len == 0 ) {
78                                 /* SUCCESS */
79                                 send_ldap_result( conn, op, LDAP_SUCCESS,
80                                         NULL, NULL, NULL, NULL );
81
82                         } else if ( be_isroot_pw( be, dn, cred ) ) {
83                                 *edn = ch_strdup( be_root_dn( be ) );
84                                 rc = 0; /* front end will send result */
85
86                         } else if ( refs != NULL ) {
87                                 send_ldap_result( conn, op, LDAP_REFERRAL,
88                                         matched_dn, NULL, refs, NULL );
89
90                         } else {
91                                 send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
92                                         NULL, NULL, NULL, NULL );
93                         }
94
95                 } else if ( method == LDAP_AUTH_SASL ) {
96 #ifdef HAVE_CYRUS_SASL
97                         rc = sasl_bind( be, conn, op, 
98                                 dn, ndn, mech, cred, edn );
99 #else
100                         if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
101                                 /* insert DIGEST calls here */
102                                 send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
103                                         NULL, NULL, NULL, NULL );
104                                 
105                         } else {
106                                 send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
107                                         NULL, NULL, NULL, NULL );
108                         }
109 #endif /* HAVE_CYRUS_SASL */
110                 } else if ( refs != NULL ) {
111                         send_ldap_result( conn, op, LDAP_REFERRAL,
112                                 matched_dn, NULL, refs, NULL );
113
114                 } else {
115                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
116                                 NULL, NULL, NULL, NULL );
117                 }
118
119                 if ( matched != NULL ) {
120                         ber_bvecfree( refs );
121                         free( matched_dn );
122                 }
123                 return( rc );
124         }
125
126         *edn = ch_strdup( e->e_dn );
127
128         /* check for deleted */
129
130         if ( ! access_allowed( be, conn, op, e,
131                 entry, NULL, ACL_AUTH ) )
132         {
133                 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
134                         NULL, NULL, NULL, NULL );
135                 rc = 1;
136                 goto return_results;
137         }
138
139         if ( is_entry_alias( e ) ) {
140                 /* entry is an alias, don't allow bind */
141                 Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
142                     0, 0 );
143
144                 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
145                     NULL, NULL, NULL, NULL );
146
147                 rc = 1;
148                 goto return_results;
149         }
150
151         if ( is_entry_referral( e ) ) {
152                 /* entry is a referral, don't allow bind */
153                 struct berval **refs = get_entry_referrals( be,
154                         conn, op, e );
155
156                 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
157                     0, 0 );
158
159                 if( refs != NULL ) {
160                         send_ldap_result( conn, op, LDAP_REFERRAL,
161                                 e->e_dn, NULL, refs, NULL );
162
163                 } else {
164                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
165                                 NULL, NULL, NULL, NULL );
166                 }
167
168                 ber_bvecfree( refs );
169
170                 rc = 1;
171                 goto return_results;
172         }
173
174         switch ( method ) {
175         case LDAP_AUTH_SIMPLE:
176                 if ( cred->bv_len == 0 ) {
177                         send_ldap_result( conn, op, LDAP_SUCCESS,
178                                 NULL, NULL, NULL, NULL );
179
180                         /* stop front end from sending result */
181                         rc = 1;
182                         goto return_results;
183                 } 
184
185                 /* check for root dn/passwd */
186                 if ( be_isroot_pw( be, dn, cred ) ) {
187                         /* front end will send result */
188                         if(*edn != NULL) free( *edn );
189                         *edn = ch_strdup( be_root_dn( be ) );
190                         rc = 0;
191                         goto return_results;
192                 }
193
194                 if ( ! access_allowed( be, conn, op, e,
195                         password, NULL, ACL_AUTH ) )
196                 {
197                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
198                                 NULL, NULL, NULL, NULL );
199                         rc = 1;
200                         goto return_results;
201                 }
202
203                 if ( (a = attr_find( e->e_attrs, password )) == NULL ) {
204                         send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
205                             NULL, NULL, NULL, NULL );
206
207                         /* stop front end from sending result */
208                         rc = 1;
209                         goto return_results;
210                 }
211
212                 if ( slap_passwd_check( a, cred ) != 0 ) {
213                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
214                                 NULL, NULL, NULL, NULL );
215                         /* stop front end from sending result */
216                         rc = 1;
217                         goto return_results;
218                 }
219
220                 rc = 0;
221                 break;
222
223 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
224         case LDAP_AUTH_KRBV41:
225                 if ( ! access_allowed( be, conn, op, e,
226                         "krbname", NULL, ACL_AUTH ) )
227                 {
228                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
229                                 NULL, NULL, NULL, NULL );
230                         rc = 1;
231                         goto return_results;
232                 }
233
234                 if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
235                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
236                             NULL, NULL, NULL, NULL );
237                         rc = 1;
238                         goto return_results;
239                 }
240
241                 if ( ! access_allowed( be, conn, op, e,
242                         "krbname", NULL, ACL_AUTH ) )
243                 {
244                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
245                                 NULL, NULL, NULL, NULL );
246                         rc = 1;
247                         goto return_results;
248                 }
249
250                 sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
251                     : "", ad.pinst, ad.prealm );
252
253
254                 if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
255                         /*
256                          * no krbname values present:  check against DN
257                          */
258                         if ( strcasecmp( dn, krbname ) == 0 ) {
259                                 rc = 0;
260                                 break;
261                         }
262                         send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
263                             NULL, NULL, NULL, NULL );
264                         rc = 1;
265                         goto return_results;
266
267                 } else {        /* look for krbname match */
268                         struct berval   krbval;
269
270                         krbval.bv_val = krbname;
271                         krbval.bv_len = strlen( krbname );
272
273                         if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
274                                 send_ldap_result( conn, op,
275                                     LDAP_INVALID_CREDENTIALS,
276                                         NULL, NULL, NULL, NULL );
277                                 rc = 1;
278                                 goto return_results;
279                         }
280                 }
281                 rc = 0;
282                 break;
283
284         case LDAP_AUTH_KRBV42:
285                 send_ldap_result( conn, op, LDAP_SUCCESS,
286                         NULL, NULL, NULL, NULL );
287                 /* stop front end from sending result */
288                 rc = 1;
289                 goto return_results;
290 #endif
291
292         case LDAP_AUTH_SASL:
293                 /* insert SASL code here */
294 #ifdef HAVE_CYRUS_SASL
295                 /* this may discard edn as we always prefer the SASL authzid
296                  * because it may be sealed.
297                  */
298                 rc = sasl_bind( be, conn, op, dn, ndn, mech, cred, edn );
299 #endif /* HAVE_CYRUS_SASL */
300         default:
301                 send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
302                     NULL, "auth method not supported", NULL, NULL );
303                 rc = 1;
304                 goto return_results;
305         }
306
307 return_results:;
308         /* free entry and reader lock */
309         cache_return_entry_r( &li->li_cache, e );
310
311         /* front end with send result on success (rc==0) */
312         return( rc );
313 }
314