]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
SLAPI fix - no-op when slapi_plugins_used == 0
[openldap] / servers / slapd / bind.c
1 /* bind.c - decode an ldap bind operation and pass it to a backend db */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 /*
9  * Copyright (c) 1995 Regents of the University of Michigan.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms are permitted
13  * provided that this notice is preserved and that due credit is given
14  * to the University of Michigan at Ann Arbor. The name of the University
15  * may not be used to endorse or promote products derived from this
16  * software without specific prior written permission. This software
17  * is provided ``as is'' without express or implied warranty.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/string.h>
25 #include <ac/socket.h>
26
27 #include "ldap_pvt.h"
28 #include "slap.h"
29 #ifdef LDAP_SLAPI
30 #include "slapi.h"
31 #endif
32
33
34 int
35 do_bind(
36     Operation   *op,
37     SlapReply   *rs
38 )
39 {
40         BerElement *ber = op->o_ber;
41         ber_int_t version;
42         ber_tag_t method;
43         struct berval mech = { 0, NULL };
44         struct berval dn = { 0, NULL };
45         ber_tag_t tag;
46         Backend *be = NULL;
47
48 #ifdef NEW_LOGGING
49         LDAP_LOG( OPERATION, ENTRY, "do_bind: conn %d\n", op->o_connid, 0, 0 );
50 #else
51         Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
52 #endif
53
54         /*
55          * Force to connection to "anonymous" until bind succeeds.
56          */
57         ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
58         if ( op->o_conn->c_sasl_bind_in_progress ) {
59                 be = op->o_conn->c_authz_backend;
60         }
61         if ( op->o_conn->c_dn.bv_len ) {
62                 /* log authorization identity demotion */
63                 Statslog( LDAP_DEBUG_STATS,
64                         "conn=%lu op=%lu BIND anonymous mech=implicit ssf=0\n",
65                         op->o_connid, op->o_opid, 0, 0, 0 );
66         }
67         connection2anonymous( op->o_conn );
68         if ( op->o_conn->c_sasl_bind_in_progress ) {
69                 op->o_conn->c_authz_backend = be;
70         }
71         ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
72         if ( op->o_dn.bv_val != NULL ) {
73                 free( op->o_dn.bv_val );
74                 op->o_dn.bv_val = ch_strdup( "" );
75                 op->o_dn.bv_len = 0;
76         }
77         if ( op->o_ndn.bv_val != NULL ) {
78                 free( op->o_ndn.bv_val );
79                 op->o_ndn.bv_val = ch_strdup( "" );
80                 op->o_ndn.bv_len = 0;
81         }
82
83         /*
84          * Parse the bind request.  It looks like this:
85          *
86          *      BindRequest ::= SEQUENCE {
87          *              version         INTEGER,                 -- version
88          *              name            DistinguishedName,       -- dn
89          *              authentication  CHOICE {
90          *                      simple          [0] OCTET STRING -- passwd
91          *                      krbv42ldap      [1] OCTET STRING
92          *                      krbv42dsa       [2] OCTET STRING
93          *                      SASL            [3] SaslCredentials
94          *              }
95          *      }
96          *
97          *      SaslCredentials ::= SEQUENCE {
98          *              mechanism           LDAPString,
99          *              credentials         OCTET STRING OPTIONAL
100          *      }
101          */
102
103         tag = ber_scanf( ber, "{imt" /*}*/, &version, &dn, &method );
104
105         if ( tag == LBER_ERROR ) {
106 #ifdef NEW_LOGGING
107                 LDAP_LOG( OPERATION, ERR, 
108                         "do_bind: conn %d  ber_scanf failed\n", op->o_connid, 0, 0 );
109 #else
110                 Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
111 #endif
112                 send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
113                 rs->sr_err = -1;
114                 goto cleanup;
115         }
116
117         op->o_protocol = version;
118
119         if( method != LDAP_AUTH_SASL ) {
120                 tag = ber_scanf( ber, /*{*/ "m}", &op->orb_cred );
121
122         } else {
123                 tag = ber_scanf( ber, "{m" /*}*/, &mech );
124
125                 if ( tag != LBER_ERROR ) {
126                         ber_len_t len;
127                         tag = ber_peek_tag( ber, &len );
128
129                         if ( tag == LDAP_TAG_LDAPCRED ) { 
130                                 tag = ber_scanf( ber, "m", &op->orb_cred );
131                         } else {
132                                 tag = LDAP_TAG_LDAPCRED;
133                                 op->orb_cred.bv_val = NULL;
134                                 op->orb_cred.bv_len = 0;
135                         }
136
137                         if ( tag != LBER_ERROR ) {
138                                 tag = ber_scanf( ber, /*{{*/ "}}" );
139                         }
140                 }
141         }
142
143         if ( tag == LBER_ERROR ) {
144                 send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
145                 rs->sr_err = SLAPD_DISCONNECT;
146                 goto cleanup;
147         }
148
149         if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
150 #ifdef NEW_LOGGING
151                 LDAP_LOG( OPERATION, INFO, 
152                         "do_bind: conn %d  get_ctrls failed\n", op->o_connid, 0, 0 );
153 #else
154                 Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
155 #endif
156                 goto cleanup;
157         } 
158
159         /* We use the tmpmemctx here because it speeds up normalization.
160          * However, we must dup with regular malloc when storing any
161          * resulting DNs in the op or conn structures.
162          */
163         rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
164                 op->o_tmpmemctx );
165         if ( rs->sr_err != LDAP_SUCCESS ) {
166 #ifdef NEW_LOGGING
167                 LDAP_LOG( OPERATION, INFO, 
168                         "do_bind: conn %d  invalid dn (%s)\n", 
169                         op->o_connid, dn.bv_val, 0 );
170 #else
171                 Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n",
172                         dn.bv_val, 0, 0 );
173 #endif
174                 send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
175                 goto cleanup;
176         }
177
178         if( method == LDAP_AUTH_SASL ) {
179 #ifdef NEW_LOGGING
180                 LDAP_LOG( OPERATION,     DETAIL1, 
181                         "do_sasl_bind: conn %d  dn (%s) mech %s\n", 
182                         op->o_connid, op->o_req_dn.bv_val, mech.bv_val );
183 #else
184                 Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
185                         op->o_req_dn.bv_val, mech.bv_val, NULL );
186 #endif
187
188         } else {
189 #ifdef NEW_LOGGING
190                 LDAP_LOG( OPERATION, DETAIL1, 
191                         "do_bind: version=%ld dn=\"%s\" method=%ld\n",
192                         (unsigned long) version, op->o_req_dn.bv_val,
193                         (unsigned long) method );
194 #else
195                 Debug( LDAP_DEBUG_TRACE,
196                         "do_bind: version=%ld dn=\"%s\" method=%ld\n",
197                         (unsigned long) version, op->o_req_dn.bv_val,
198                         (unsigned long) method );
199 #endif
200         }
201
202         Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu BIND dn=\"%s\" method=%ld\n",
203             op->o_connid, op->o_opid, op->o_req_dn.bv_val, (unsigned long) method,
204                 0 );
205
206         if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
207 #ifdef NEW_LOGGING
208                 LDAP_LOG( OPERATION, INFO, 
209                         "do_bind: conn %d  unknown version = %ld\n",
210                         op->o_connid, (unsigned long)version, 0 );
211 #else
212                 Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
213                         (unsigned long) version, 0, 0 );
214 #endif
215                 send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
216                         "requested protocol version not supported" );
217                 goto cleanup;
218
219         } else if (!( global_allows & SLAP_ALLOW_BIND_V2 ) &&
220                 version < LDAP_VERSION3 )
221         {
222                 send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
223                         "historical protocol version requested, use LDAPv3 instead" );
224                 goto cleanup;
225         }
226
227         /*
228          * we set connection version regardless of whether bind succeeds or not.
229          */
230         ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
231         op->o_conn->c_protocol = version;
232         ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
233
234         /* check for inappropriate controls */
235         if( get_manageDSAit( op ) == SLAP_CRITICAL_CONTROL ) {
236                 send_ldap_error( op, rs,
237                         LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
238                         "manageDSAit control inappropriate" );
239                 goto cleanup;
240         }
241
242         /* Set the bindop for the benefit of in-directory SASL lookups */
243         op->o_conn->c_sasl_bindop = op;
244
245         if ( method == LDAP_AUTH_SASL ) {
246                 if ( version < LDAP_VERSION3 ) {
247 #ifdef NEW_LOGGING
248                         LDAP_LOG( OPERATION, INFO, 
249                                 "do_bind: conn %d  sasl with LDAPv%ld\n",
250                                 op->o_connid, (unsigned long)version , 0 );
251 #else
252                         Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
253                                 (unsigned long) version, 0, 0 );
254 #endif
255                         send_ldap_discon( op, rs,
256                                 LDAP_PROTOCOL_ERROR, "SASL bind requires LDAPv3" );
257                         rs->sr_err = SLAPD_DISCONNECT;
258                         goto cleanup;
259                 }
260
261                 if( mech.bv_len == 0 ) {
262 #ifdef NEW_LOGGING
263                         LDAP_LOG( OPERATION, INFO, 
264                                    "do_bind: conn %d  no SASL mechanism provided\n",
265                                    op->o_connid, 0, 0 );
266 #else
267                         Debug( LDAP_DEBUG_ANY,
268                                 "do_bind: no sasl mechanism provided\n",
269                                 0, 0, 0 );
270 #endif
271                         send_ldap_error( op, rs, LDAP_AUTH_METHOD_NOT_SUPPORTED,
272                                 "no SASL mechanism provided" );
273                         goto cleanup;
274                 }
275
276                 /* check restrictions */
277                 if( backend_check_restrictions( op, rs, &mech ) != LDAP_SUCCESS ) {
278                         send_ldap_result( op, rs );
279                         goto cleanup;
280                 }
281
282                 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
283                 if ( op->o_conn->c_sasl_bind_in_progress ) {
284                         if( !bvmatch( &op->o_conn->c_sasl_bind_mech, &mech ) ) {
285                                 /* mechanism changed between bind steps */
286                                 slap_sasl_reset(op->o_conn);
287                         }
288                 } else {
289                         ber_dupbv(&op->o_conn->c_sasl_bind_mech, &mech);
290                 }
291                 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
292
293                 rs->sr_err = slap_sasl_bind( op, rs );
294
295                 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
296                 if( rs->sr_err == LDAP_SUCCESS ) {
297                         ber_dupbv(&op->o_conn->c_dn, &op->orb_edn);
298                         if( op->orb_edn.bv_len != 0 ) {
299                                 /* edn is always normalized already */
300                                 ber_dupbv( &op->o_conn->c_ndn, &op->o_conn->c_dn );
301                         }
302                         op->o_tmpfree( op->orb_edn.bv_val, op->o_tmpmemctx );
303                         op->orb_edn.bv_val = NULL;
304                         op->orb_edn.bv_len = 0;
305                         op->o_conn->c_authmech = op->o_conn->c_sasl_bind_mech;
306                         op->o_conn->c_sasl_bind_mech.bv_val = NULL;
307                         op->o_conn->c_sasl_bind_mech.bv_len = 0;
308                         op->o_conn->c_sasl_bind_in_progress = 0;
309
310                         op->o_conn->c_sasl_ssf = op->orb_ssf;
311                         if( op->orb_ssf > op->o_conn->c_ssf ) {
312                                 op->o_conn->c_ssf = op->orb_ssf;
313                         }
314
315                         if( op->o_conn->c_dn.bv_len != 0 ) {
316                                 ber_len_t max = sockbuf_max_incoming_auth;
317                                 ber_sockbuf_ctrl( op->o_conn->c_sb,
318                                         LBER_SB_OPT_SET_MAX_INCOMING, &max );
319                         }
320
321                         /* log authorization identity */
322                         Statslog( LDAP_DEBUG_STATS,
323                                 "conn=%lu op=%lu BIND dn=\"%s\" mech=%s ssf=%d\n",
324                                 op->o_connid, op->o_opid,
325                                 op->o_conn->c_dn.bv_val ? op->o_conn->c_dn.bv_val : "<empty>",
326                                 op->o_conn->c_authmech.bv_val, op->orb_ssf );
327
328 #ifdef NEW_LOGGING
329                         LDAP_LOG( OPERATION, DETAIL1, 
330                                 "do_bind: SASL/%s bind: dn=\"%s\" ssf=%d\n",
331                                 op->o_conn->c_authmech.bv_val,
332                                 op->o_conn->c_dn.bv_val ? op->o_conn->c_dn.bv_val : "<empty>",
333                                 op->orb_ssf );
334 #else
335                         Debug( LDAP_DEBUG_TRACE,
336                                 "do_bind: SASL/%s bind: dn=\"%s\" ssf=%d\n",
337                                 op->o_conn->c_authmech.bv_val,
338                                 op->o_conn->c_dn.bv_val ? op->o_conn->c_dn.bv_val : "<empty>",
339                                 op->orb_ssf );
340 #endif
341
342                 } else if ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ) {
343                         op->o_conn->c_sasl_bind_in_progress = 1;
344
345                 } else {
346                         if ( op->o_conn->c_sasl_bind_mech.bv_val ) {
347                                 free( op->o_conn->c_sasl_bind_mech.bv_val );
348                                 op->o_conn->c_sasl_bind_mech.bv_val = NULL;
349                                 op->o_conn->c_sasl_bind_mech.bv_len = 0;
350                         }
351                         op->o_conn->c_sasl_bind_in_progress = 0;
352                 }
353
354 #ifdef LDAP_SLAPI
355 #define pb      op->o_pb
356                 /*
357                  * Normally post-operation plugins are called only after the
358                  * backend operation. Because the front-end performs SASL
359                  * binds on behalf of the backend, we'll make a special
360                  * exception to call the post-operation plugins after a
361                  * SASL bind.
362                  */
363                 if ( pb ) {
364                         slapi_x_pblock_set_operation( pb, op );
365                         slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
366                         slapi_pblock_set( pb, SLAPI_BIND_METHOD, (void *)method );
367                         slapi_pblock_set( pb, SLAPI_BIND_CREDENTIALS, (void *)&op->orb_cred );
368                         slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(0) );
369                         (void) doPluginFNs( op->o_bd, SLAPI_PLUGIN_POST_BIND_FN, pb );
370                 }
371 #endif /* LDAP_SLAPI */
372
373                 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
374
375                 goto cleanup;
376
377         } else {
378                 /* Not SASL, cancel any in-progress bind */
379                 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
380
381                 if ( op->o_conn->c_sasl_bind_mech.bv_val != NULL ) {
382                         free(op->o_conn->c_sasl_bind_mech.bv_val);
383                         op->o_conn->c_sasl_bind_mech.bv_val = NULL;
384                         op->o_conn->c_sasl_bind_mech.bv_len = 0;
385                 }
386                 op->o_conn->c_sasl_bind_in_progress = 0;
387
388                 slap_sasl_reset( op->o_conn );
389                 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
390         }
391
392         if ( method == LDAP_AUTH_SIMPLE ) {
393                 /* accept "anonymous" binds */
394                 if ( op->orb_cred.bv_len == 0 || op->o_req_ndn.bv_len == 0 ) {
395                         rs->sr_err = LDAP_SUCCESS;
396
397                         if( op->orb_cred.bv_len &&
398                                 !( global_allows & SLAP_ALLOW_BIND_ANON_CRED ))
399                         {
400                                 /* cred is not empty, disallow */
401                                 rs->sr_err = LDAP_INVALID_CREDENTIALS;
402
403                         } else if ( op->o_req_ndn.bv_len &&
404                                 !( global_allows & SLAP_ALLOW_BIND_ANON_DN ))
405                         {
406                                 /* DN is not empty, disallow */
407                                 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
408                                 rs->sr_text =
409                                         "unauthenticated bind (DN with no password) disallowed";
410
411                         } else if ( global_disallows & SLAP_DISALLOW_BIND_ANON ) {
412                                 /* disallow */
413                                 rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
414                                 rs->sr_text = "anonymous bind disallowed";
415
416                         } else {
417                                 backend_check_restrictions( op, rs, &mech );
418                         }
419
420                         /*
421                          * we already forced connection to "anonymous",
422                          * just need to send success
423                          */
424                         send_ldap_result( op, rs );
425 #ifdef NEW_LOGGING
426                         LDAP_LOG( OPERATION, DETAIL1, 
427                                    "do_bind: conn %d  v%d anonymous bind\n",
428                                    op->o_connid, version , 0 );
429 #else
430                         Debug( LDAP_DEBUG_TRACE, "do_bind: v%d anonymous bind\n",
431                                 version, 0, 0 );
432 #endif
433                         goto cleanup;
434
435                 } else if ( global_disallows & SLAP_DISALLOW_BIND_SIMPLE ) {
436                         /* disallow simple authentication */
437                         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
438                         rs->sr_text = "unwilling to perform simple authentication";
439
440                         send_ldap_result( op, rs );
441 #ifdef NEW_LOGGING
442                         LDAP_LOG( OPERATION, INFO, 
443                                 "do_bind: conn %d  v%d simple bind(%s) disallowed\n",
444                                 op->o_connid, version, op->o_req_ndn.bv_val );
445 #else
446                         Debug( LDAP_DEBUG_TRACE,
447                                 "do_bind: v%d simple bind(%s) disallowed\n",
448                                 version, op->o_req_ndn.bv_val, 0 );
449 #endif
450                         goto cleanup;
451                 }
452
453 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
454         } else if ( method == LDAP_AUTH_KRBV41 || method == LDAP_AUTH_KRBV42 ) {
455                 if ( global_disallows & SLAP_DISALLOW_BIND_KRBV4 ) {
456                         /* disallow simple authentication */
457                         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
458                         rs->sr_text = "unwilling to perform Kerberos V4 bind";
459
460                         send_ldap_result( op, rs );
461 #ifdef NEW_LOGGING
462                         LDAP_LOG( OPERATION, DETAIL1, 
463                                 "do_bind: conn %d  v%d Kerberos V4 bind\n",
464                                 op->o_connid, version , 0 );
465 #else
466                         Debug( LDAP_DEBUG_TRACE, "do_bind: v%d Kerberos V4 bind\n",
467                                 version, 0, 0 );
468 #endif
469                         goto cleanup;
470                 }
471 #endif
472
473         } else {
474                 rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
475                 rs->sr_text = "unknown authentication method";
476
477                 send_ldap_result( op, rs );
478 #ifdef NEW_LOGGING
479                 LDAP_LOG( OPERATION, INFO, 
480                         "do_bind: conn %ld  v%d unknown authentication method (%ld)\n",
481                         op->o_connid, version, method );
482 #else
483                 Debug( LDAP_DEBUG_TRACE,
484                         "do_bind: v%d unknown authentication method (%ld)\n",
485                         version, method, 0 );
486 #endif
487                 goto cleanup;
488         }
489
490         /*
491          * We could be serving multiple database backends.  Select the
492          * appropriate one, or send a referral to our "referral server"
493          * if we don't hold it.
494          */
495
496         if ( (op->o_bd = select_backend( &op->o_req_ndn, 0, 0 )) == NULL ) {
497                 if ( default_referral ) {
498                         rs->sr_ref = referral_rewrite( default_referral,
499                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
500                         if (!rs->sr_ref) rs->sr_ref = default_referral;
501
502                         rs->sr_err = LDAP_REFERRAL;
503                         send_ldap_result( op, rs );
504
505                         if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
506
507                 } else {
508                         /* noSuchObject is not allowed to be returned by bind */
509                         rs->sr_err = LDAP_INVALID_CREDENTIALS;
510                         send_ldap_result( op, rs );
511                 }
512
513                 goto cleanup;
514         }
515
516         /* check restrictions */
517         if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
518                 send_ldap_result( op, rs );
519                 goto cleanup;
520         }
521
522 #if defined( LDAP_SLAPI )
523         if ( pb ) {
524                 int rc;
525                 slapi_x_pblock_set_operation( pb, op );
526                 slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
527                 slapi_pblock_set( pb, SLAPI_BIND_METHOD, (void *)method );
528                 slapi_pblock_set( pb, SLAPI_BIND_CREDENTIALS, (void *)&op->orb_cred );
529                 slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(0) );
530                 slapi_pblock_set( pb, SLAPI_CONN_DN, (void *)(0) );
531
532                 rc = doPluginFNs( op->o_bd, SLAPI_PLUGIN_PRE_BIND_FN, pb );
533
534 #ifdef NEW_LOGGING
535                 LDAP_LOG( OPERATION, INFO,
536                         "do_bind: Bind preoperation plugin returned %d\n",
537                         rs->sr_err, 0, 0);
538 #else
539                 Debug(LDAP_DEBUG_TRACE,
540                         "do_bind: Bind preoperation plugin returned %d.\n",
541                         rs->sr_err, 0, 0);
542 #endif
543
544                 switch ( rc ) {
545                 case SLAPI_BIND_SUCCESS:
546                         /* Continue with backend processing */
547                         break;
548                 case SLAPI_BIND_FAIL:
549                         /* Failure, server sends result */
550                         rs->sr_err = LDAP_INVALID_CREDENTIALS;
551                         send_ldap_result( op, rs );
552                         goto cleanup;
553                         break;
554                 case SLAPI_BIND_ANONYMOUS:
555                         /* SLAPI_BIND_ANONYMOUS is undocumented XXX */
556                 default:
557                         /* Authoritative, plugin sent result, or no plugins called. */
558                         if ( slapi_pblock_get( op->o_pb, SLAPI_RESULT_CODE,
559                                 (void *)&rs->sr_err) != 0 )
560                         {
561                                 rs->sr_err = LDAP_OTHER;
562                         }
563
564                         op->orb_edn.bv_val = NULL;
565                         op->orb_edn.bv_len = 0;
566
567                         if ( rs->sr_err == LDAP_SUCCESS ) {
568                                 slapi_pblock_get( pb, SLAPI_CONN_DN, (void *)&op->orb_edn.bv_val );
569                                 if ( op->orb_edn.bv_val == NULL ) {
570                                         if ( rc == 1 ) {
571                                                 /* No plugins were called; continue. */
572                                                 break;
573                                         }
574                                 } else {
575                                         op->orb_edn.bv_len = strlen( op->orb_edn.bv_val );
576                                 }
577                                 rs->sr_err = dnPrettyNormal( NULL, &op->orb_edn,
578                                         &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
579                                 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
580                                 ber_dupbv(&op->o_conn->c_dn, &op->o_req_dn);
581                                 ber_dupbv(&op->o_conn->c_ndn, &op->o_req_ndn);
582                                 op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
583                                 op->o_req_dn.bv_val = NULL;
584                                 op->o_req_dn.bv_len = 0;
585                                 op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
586                                 op->o_req_ndn.bv_val = NULL;
587                                 op->o_req_ndn.bv_len = 0;
588                                 if ( op->o_conn->c_dn.bv_len != 0 ) {
589                                         ber_len_t max = sockbuf_max_incoming_auth;
590                                         ber_sockbuf_ctrl( op->o_conn->c_sb,
591                                                 LBER_SB_OPT_SET_MAX_INCOMING, &max );
592                                 }
593                                 /* log authorization identity */
594                                 Statslog( LDAP_DEBUG_STATS,
595                                         "conn=%lu op=%lu BIND dn=\"%s\" mech=simple (SLAPI) ssf=0\n",
596                                         op->o_connid, op->o_opid,
597                                         op->o_conn->c_dn.bv_val ? op->o_conn->c_dn.bv_val : "<empty>",
598                                         0, 0 );
599                                 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
600                         }
601                         goto cleanup;
602                         break;
603                 }
604         }
605 #endif /* defined( LDAP_SLAPI ) */
606
607         if( op->o_bd->be_bind ) {
608                 op->orb_method = method;
609                 rs->sr_err = (op->o_bd->be_bind)( op, rs );
610
611                 if ( rs->sr_err == 0 ) {
612                         ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
613
614                         if( op->o_conn->c_authz_backend == NULL ) {
615                                 op->o_conn->c_authz_backend = op->o_bd;
616                         }
617
618                         /* be_bind returns regular/global edn */
619                         if( op->orb_edn.bv_len ) {
620                                 op->o_conn->c_dn = op->orb_edn;
621                         } else {
622                                 ber_dupbv(&op->o_conn->c_dn, &op->o_req_dn);
623                         }
624
625                         ber_dupbv( &op->o_conn->c_ndn, &op->o_req_ndn );
626
627                         if( op->o_conn->c_dn.bv_len != 0 ) {
628                                 ber_len_t max = sockbuf_max_incoming_auth;
629                                 ber_sockbuf_ctrl( op->o_conn->c_sb,
630                                         LBER_SB_OPT_SET_MAX_INCOMING, &max );
631                         }
632
633                         /* log authorization identity */
634                         Statslog( LDAP_DEBUG_STATS,
635                                 "conn=%lu op=%lu BIND dn=\"%s\" mech=simple ssf=0\n",
636                                 op->o_connid, op->o_opid,
637                                 op->o_conn->c_dn.bv_val, 0, 0 );
638
639 #ifdef NEW_LOGGING
640                         LDAP_LOG( OPERATION, DETAIL1, 
641                                 "do_bind: v%d bind: \"%s\" to \"%s\" \n",
642                                 version, op->o_conn->c_dn.bv_val, op->o_conn->c_dn.bv_val );
643 #else
644                         Debug( LDAP_DEBUG_TRACE,
645                                 "do_bind: v%d bind: \"%s\" to \"%s\"\n",
646                                 version, dn.bv_val, op->o_conn->c_dn.bv_val );
647 #endif
648
649                         ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
650
651                         /* send this here to avoid a race condition */
652                         send_ldap_result( op, rs );
653
654                 } else if (op->orb_edn.bv_val != NULL) {
655                         free( op->orb_edn.bv_val );
656                 }
657
658         } else {
659                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
660                         "operation not supported within naming context" );
661         }
662
663 #if defined( LDAP_SLAPI )
664         if ( pb && doPluginFNs( op->o_bd, SLAPI_PLUGIN_POST_BIND_FN, pb ) < 0 ) {
665 #ifdef NEW_LOGGING
666                 LDAP_LOG( OPERATION, INFO,
667                         "do_bind: Bind postoperation plugins failed\n",
668                         0, 0, 0);
669 #else
670                 Debug(LDAP_DEBUG_TRACE,
671                         "do_bind: Bind postoperation plugins failed.\n",
672                         0, 0, 0);
673 #endif
674         }
675 #endif /* defined( LDAP_SLAPI ) */
676
677 cleanup:
678
679         op->o_conn->c_sasl_bindop = NULL;
680
681         if( op->o_req_dn.bv_val != NULL ) {
682                 sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx );
683                 op->o_req_dn.bv_val = NULL;
684         }
685         if( op->o_req_ndn.bv_val != NULL ) {
686                 sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx );
687                 op->o_req_ndn.bv_val = NULL;
688         }
689
690         return rs->sr_err;
691 }