]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/bind.c
Add OpenLDAP RCSid to *.[ch] in clients, libraries, and servers.
[openldap] / servers / slapd / back-bdb2 / bind.c
1 /* bind.c - bdb2 backend bind and unbind routines */
2 /* $OpenLDAP$ */
3
4 #include "portable.h"
5
6 #include <stdio.h>
7
8 #include <ac/krb.h>
9 #include <ac/socket.h>
10 #include <ac/string.h>
11 #include <ac/unistd.h>
12
13 #include "slap.h"
14 #include "back-bdb2.h"
15 #include "proto-back-bdb2.h"
16
17 #include <lutil.h>
18
19 #ifdef HAVE_KERBEROS
20 extern int      bdb2i_krbv4_ldap_auth();
21 #endif
22
23 static int
24 crypted_value_find(
25         struct berval       **vals,
26         struct berval       *v,
27         int                 syntax,
28         int                 normalize,
29         struct berval           *cred
30 )
31 {
32         int     i;
33         for ( i = 0; vals[i] != NULL; i++ ) {
34                 if ( syntax != SYNTAX_BIN ) {
35                         int result;
36
37 #ifdef SLAPD_CRYPT
38                         ldap_pvt_thread_mutex_lock( &crypt_mutex );
39 #endif
40
41                         result = lutil_passwd(
42                                 (char*) cred->bv_val,
43                                 (char*) vals[i]->bv_val,
44                                 NULL );
45
46 #ifdef SLAPD_CRYPT
47                         ldap_pvt_thread_mutex_unlock( &crypt_mutex );
48 #endif
49
50                         return result;
51
52                 } else {
53                 if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
54                         return( 0 );
55                 }
56         }
57         }
58
59         return( 1 );
60 }
61
62 static int
63 bdb2i_back_bind_internal(
64     BackendDB           *be,
65     Connection          *conn,
66     Operation           *op,
67     char                *dn,
68     int                 method,
69         char            *mech,
70     struct berval       *cred,
71         char**  edn
72 )
73 {
74         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
75         Entry           *e;
76         Attribute       *a;
77         int             rc;
78         Entry           *matched;
79 #ifdef HAVE_KERBEROS
80         char            krbname[MAX_K_NAME_SZ + 1];
81         AUTH_DAT        ad;
82 #endif
83
84         Debug(LDAP_DEBUG_ARGS, "==> bdb2_back_bind: dn: %s\n", dn, 0, 0);
85
86         *edn = NULL;
87
88         /* get entry with reader lock */
89         if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
90                 char *matched_dn = NULL;
91                 struct berval **refs = NULL;
92
93                 if ( matched != NULL ) {
94                         matched_dn = ch_strdup( matched->e_dn );
95                         refs = is_entry_referral( matched )
96                                 ? get_entry_referrals( be, conn, op, matched )
97                                 : NULL;
98                         bdb2i_cache_return_entry_r( &li->li_cache, matched );
99                 } else {
100                         refs = default_referral;
101                 }
102
103                 /* allow noauth binds */
104                 rc = 1;
105                 if ( method == LDAP_AUTH_SIMPLE ) {
106                         if( cred->bv_len == 0 ) {
107                                 /* SUCCESS */
108                                 send_ldap_result( conn, op, LDAP_SUCCESS,
109                                         NULL, NULL, NULL, NULL );
110
111                         } else if ( be_isroot_pw( be, dn, cred ) ) {
112                                 /* front end will send result */
113                                 *edn = ch_strdup( be_root_dn( be ) );
114                                 rc = 0;
115
116                         } else {
117                                 send_ldap_result( conn, op, LDAP_REFERRAL,
118                                         matched_dn, NULL, refs, NULL );
119                         }
120
121                 } else if ( method == LDAP_AUTH_SASL ) {
122                         if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
123                                 /* insert DIGEST calls here */
124                                 send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
125                                         NULL, NULL, NULL, NULL );
126
127                         } else {
128                                 send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
129                                         NULL, NULL, NULL, NULL );
130                         }
131
132                 } else {
133                         send_ldap_result( conn, op, LDAP_REFERRAL,
134                                 matched_dn, NULL, refs, NULL );
135                         rc = 1;
136                 }
137
138                 if ( matched != NULL ) {
139                         ber_bvecfree( refs );
140                         free( matched_dn );
141                 }
142                 return( rc );
143         }
144
145         *edn = ch_strdup( e->e_dn );
146
147         /* check for deleted */
148
149         if ( ! access_allowed( be, conn, op, e,
150                 "entry", NULL, ACL_AUTH ) )
151         {
152                 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
153                         NULL, NULL, NULL, NULL );
154                 rc = 1;
155                 goto return_results;
156         }
157
158         if ( is_entry_alias( e ) ) {
159                 /* entry is a alias, don't allow bind */
160                 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
161                         0, 0 );
162
163                 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
164                         NULL, NULL, NULL, NULL );
165
166                 rc = 1;
167                 goto return_results;
168         }
169
170
171         if ( is_entry_referral( e ) ) {
172                 /* entry is a referral, don't allow bind */
173                 struct berval **refs = get_entry_referrals( be,
174                         conn, op, e );
175
176                 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
177                         0, 0 );
178
179                 send_ldap_result( conn, op, LDAP_REFERRAL,
180                         e->e_dn, NULL, refs, NULL );
181
182                 ber_bvecfree( refs );
183
184                 rc = 1;
185                 goto return_results;
186         }
187
188         switch ( method ) {
189         case LDAP_AUTH_SIMPLE:
190                 if ( cred->bv_len == 0 ) {
191                         send_ldap_result( conn, op, LDAP_SUCCESS,
192                                 NULL, NULL, NULL, NULL );
193
194                         /* stop front end from sending result */
195                         rc = 1;
196                         goto return_results;
197                 }
198
199                 /* check for root dn/passwd */
200                 if ( be_isroot_pw( be, dn, cred ) ) {
201                         /* front end will send result */
202                         if( *edn != NULL ) free( *edn );
203                         *edn = ch_strdup( be_root_dn( be ) );
204                         rc = 0;
205                         goto return_results;
206                 }
207
208                 if ( ! access_allowed( be, conn, op, e,
209                         "userpassword", NULL, ACL_AUTH ) )
210                 {
211                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
212                                 NULL, NULL, NULL, NULL);
213                         rc = 1;
214                         goto return_results;
215                 }
216
217                 if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
218                         send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
219                                 NULL, NULL, NULL, NULL);
220
221                         /* stop front end from sending result */
222                         rc = 1;
223                         goto return_results;
224                 }
225
226                 if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
227                 {
228                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
229                                 NULL, NULL, NULL, NULL);
230                         /* stop front end from sending result */
231                         rc = 1;
232                         goto return_results;
233                 }
234                 rc = 0;
235                 break;
236
237 #ifdef HAVE_KERBEROS
238         case LDAP_AUTH_KRBV41:
239                 if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
240                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
241                                 NULL, NULL, NULL, NULL);
242                         rc = 1;
243                         goto return_results;
244                 }
245
246                 if ( ! access_allowed( be, conn, op, e,
247                         "krbname", NULL, ACL_AUTH ) )
248                 {
249                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
250                                 NULL, NULL, NULL, NULL);
251                         rc = 1;
252                         goto return_results;
253                 }
254
255                 sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
256                     : "", ad.pinst, ad.prealm );
257
258                 if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
259                         /*
260                          * no krbName values present:  check against DN
261                          */
262                         if ( strcasecmp( dn, krbname ) == 0 ) {
263                                 rc = 0; /* XXX wild ass guess */
264                                 break;
265                         }
266                         send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
267                                 NULL, NULL, NULL, NULL);
268                         rc = 1;
269                         goto return_results;
270                 } else {        /* look for krbName match */
271                         struct berval   krbval;
272
273                         krbval.bv_val = krbname;
274                         krbval.bv_len = strlen( krbname );
275
276                         if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
277                                 send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
278                                         NULL, NULL, NULL, NULL);
279                                 rc = 1;
280                                 goto return_results;
281                         }
282                 }
283                 rc = 0;
284                 break;
285
286         case LDAP_AUTH_KRBV42:
287                 send_ldap_result( conn, op, LDAP_SUCCESS,
288                         NULL, NULL, NULL, NULL );
289                 /* stop front end from sending result */
290                 rc = 1;
291                 goto return_results;
292 #endif
293
294         case LDAP_AUTH_SASL:
295                 /* insert sasl code here */
296
297         default:
298                 send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
299                     NULL, "auth method not supported", NULL, NULL );
300                 rc = 1;
301                 goto return_results;
302         }
303
304 return_results:;
305         /* free entry and reader lock */
306         bdb2i_cache_return_entry_r( &li->li_cache, e );
307
308         /* front end with send result on success (rc==0) */
309         return( rc );
310 }
311
312
313 int
314 bdb2_back_bind(
315     BackendDB           *be,
316     Connection          *conn,
317     Operation           *op,
318     char                *dn,
319     int                 method,
320         char            *mech,
321     struct berval       *cred,
322         char**  edn
323 )
324 {
325         DB_LOCK         lock;
326         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
327         struct timeval  time1;
328         int             ret;
329
330         bdb2i_start_timing( be->bd_info, &time1 );
331
332         if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
333                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
334                         NULL, NULL, NULL, NULL );
335                 return( 1 );
336         }
337
338         ret = bdb2i_back_bind_internal( be, conn, op, dn, method, mech, cred, edn );
339
340         (void) bdb2i_leave_backend_r( lock );
341
342         bdb2i_stop_timing( be->bd_info, time1, "BIND", conn, op );
343
344         return( ret );
345 }
346
347