1 /* bind.c - decode an ldap bind operation and pass it to a backend db */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
9 * Copyright (c) 1995 Regents of the University of Michigan.
10 * All rights reserved.
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.
24 #include <ac/string.h>
25 #include <ac/socket.h>
36 BerElement *ber = op->o_ber;
39 struct berval mech = { 0, NULL };
40 struct berval dn = { 0, NULL };
41 struct berval pdn = { 0, NULL };
42 struct berval ndn = { 0, NULL };
43 struct berval edn = { 0, NULL };
45 int rc = LDAP_SUCCESS;
47 struct berval cred = { 0, NULL };
51 LDAP_LOG( OPERATION, ENTRY, "do_bind: conn %d\n", conn->c_connid, 0, 0 );
53 Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
57 * Force to connection to "anonymous" until bind succeeds.
59 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
60 if ( conn->c_sasl_bind_in_progress ) be = conn->c_authz_backend;
62 /* log authorization identity demotion */
63 if ( conn->c_dn.bv_len ) {
64 Statslog( LDAP_DEBUG_STATS,
65 "conn=%lu op=%lu AUTHZ anonymous mech=implicit ssf=0",
66 op->o_connid, op->o_opid, 0, 0, 0 );
69 connection2anonymous( conn );
70 if ( conn->c_sasl_bind_in_progress ) conn->c_authz_backend = be;
71 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
73 if ( op->o_dn.bv_val != NULL ) {
74 free( op->o_dn.bv_val );
75 op->o_dn.bv_val = ch_strdup( "" );
79 if ( op->o_ndn.bv_val != NULL ) {
80 free( op->o_ndn.bv_val );
81 op->o_ndn.bv_val = ch_strdup( "" );
86 * Parse the bind request. It looks like this:
88 * BindRequest ::= SEQUENCE {
89 * version INTEGER, -- version
90 * name DistinguishedName, -- dn
91 * authentication CHOICE {
92 * simple [0] OCTET STRING -- passwd
93 * krbv42ldap [1] OCTET STRING
94 * krbv42dsa [2] OCTET STRING
95 * SASL [3] SaslCredentials
99 * SaslCredentials ::= SEQUENCE {
100 * mechanism LDAPString,
101 * credentials OCTET STRING OPTIONAL
105 tag = ber_scanf( ber, "{imt" /*}*/, &version, &dn, &method );
107 if ( tag == LBER_ERROR ) {
109 LDAP_LOG( OPERATION, ERR,
110 "do_bind: conn %d ber_scanf failed\n", conn->c_connid, 0, 0 );
112 Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
114 send_ldap_disconnect( conn, op,
115 LDAP_PROTOCOL_ERROR, "decoding error" );
120 op->o_protocol = version;
122 if( method != LDAP_AUTH_SASL ) {
123 tag = ber_scanf( ber, /*{*/ "m}", &cred );
126 tag = ber_scanf( ber, "{o" /*}*/, &mech );
128 if ( tag != LBER_ERROR ) {
130 tag = ber_peek_tag( ber, &len );
132 if ( tag == LDAP_TAG_LDAPCRED ) {
133 tag = ber_scanf( ber, "m", &cred );
135 tag = LDAP_TAG_LDAPCRED;
140 if ( tag != LBER_ERROR ) {
141 tag = ber_scanf( ber, /*{{*/ "}}" );
146 if ( tag == LBER_ERROR ) {
147 send_ldap_disconnect( conn, op,
150 rc = SLAPD_DISCONNECT;
154 if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
156 LDAP_LOG( OPERATION, INFO,
157 "do_bind: conn %d get_ctrls failed\n", conn->c_connid, 0, 0 );
159 Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
164 rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
165 if ( rc != LDAP_SUCCESS ) {
167 LDAP_LOG( OPERATION, INFO,
168 "do_bind: conn %d invalid dn (%s)\n",
169 conn->c_connid, dn.bv_val, 0 );
171 Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n",
174 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
175 "invalid DN", NULL, NULL );
179 if( method == LDAP_AUTH_SASL ) {
181 LDAP_LOG( OPERATION, DETAIL1,
182 "do_sasl_bind: conn %d dn (%s) mech %s\n",
183 conn->c_connid, pdn.bv_val, mech.bv_val );
185 Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
186 pdn.bv_val, mech.bv_val, NULL );
191 LDAP_LOG( OPERATION, DETAIL1,
192 "do_bind: version=%ld dn=\"%s\" method=%ld\n",
193 (unsigned long) version, pdn.bv_val, (unsigned long)method );
195 Debug( LDAP_DEBUG_TRACE,
196 "do_bind: version=%ld dn=\"%s\" method=%ld\n",
197 (unsigned long) version,
198 pdn.bv_val, (unsigned long) method );
202 Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu BIND dn=\"%s\" method=%ld\n",
203 op->o_connid, op->o_opid, pdn.bv_val, (unsigned long) method, 0 );
205 if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
207 LDAP_LOG( OPERATION, INFO,
208 "do_bind: conn %d unknown version = %ld\n",
209 conn->c_connid, (unsigned long)version, 0 );
211 Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
212 (unsigned long) version, 0, 0 );
214 send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
215 NULL, "requested protocol version not supported", NULL, NULL );
218 } else if (!( global_allows & SLAP_ALLOW_BIND_V2 ) &&
219 version < LDAP_VERSION3 )
221 send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
222 NULL, "requested protocol version not allowed", NULL, NULL );
226 /* we set connection version regardless of whether bind succeeds
229 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
230 conn->c_protocol = version;
231 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
233 /* check for inappropriate controls */
234 if( get_manageDSAit( op ) == SLAP_CRITICAL_CONTROL ) {
235 send_ldap_result( conn, op,
236 rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
237 NULL, "manageDSAit control inappropriate",
242 /* Set the bindop for the benefit of in-directory SASL lookups */
243 conn->c_sasl_bindop = op;
245 if ( method == LDAP_AUTH_SASL ) {
248 if ( version < LDAP_VERSION3 ) {
250 LDAP_LOG( OPERATION, INFO,
251 "do_bind: conn %d sasl with LDAPv%ld\n",
252 conn->c_connid, (unsigned long)version , 0 );
254 Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
255 (unsigned long) version, 0, 0 );
257 send_ldap_disconnect( conn, op,
258 LDAP_PROTOCOL_ERROR, "SASL bind requires LDAPv3" );
259 rc = SLAPD_DISCONNECT;
263 if( mech.bv_len == 0 ) {
265 LDAP_LOG( OPERATION, INFO,
266 "do_bind: conn %d no SASL mechanism provided\n",
267 conn->c_connid, 0, 0 );
269 Debug( LDAP_DEBUG_ANY,
270 "do_bind: no sasl mechanism provided\n",
273 send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
274 NULL, "no SASL mechanism provided", NULL, NULL );
278 /* check restrictions */
279 rc = backend_check_restrictions( NULL, conn, op, &mech, &text );
280 if( rc != LDAP_SUCCESS ) {
281 send_ldap_result( conn, op, rc,
282 NULL, text, NULL, NULL );
286 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
287 if ( conn->c_sasl_bind_in_progress ) {
288 if( !bvmatch( &conn->c_sasl_bind_mech, &mech ) ) {
289 /* mechanism changed between bind steps */
290 slap_sasl_reset(conn);
293 conn->c_sasl_bind_mech = mech;
297 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
299 rc = slap_sasl_bind( conn, op,
303 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
304 if( rc == LDAP_SUCCESS ) {
306 if( edn.bv_len != 0 ) {
307 /* edn is always normalized already */
308 ber_dupbv( &conn->c_ndn, &conn->c_dn );
310 conn->c_authmech = conn->c_sasl_bind_mech;
311 conn->c_sasl_bind_mech.bv_val = NULL;
312 conn->c_sasl_bind_mech.bv_len = 0;
313 conn->c_sasl_bind_in_progress = 0;
315 conn->c_sasl_ssf = ssf;
316 if( ssf > conn->c_ssf ) {
320 if( conn->c_dn.bv_len != 0 ) {
321 ber_len_t max = sockbuf_max_incoming_auth;
322 ber_sockbuf_ctrl( conn->c_sb,
323 LBER_SB_OPT_SET_MAX_INCOMING, &max );
326 /* log authorization identity */
327 Statslog( LDAP_DEBUG_STATS,
328 "conn=%lu op=%lu AUTHZ dn=\"%s\" mech=%s ssf=%d\n",
329 op->o_connid, op->o_opid,
330 conn->c_dn.bv_val, conn->c_authmech.bv_val, ssf );
333 LDAP_LOG( OPERATION, DETAIL1,
334 "do_bind: SASL/%s bind: dn=\"%s\" ssf=%d\n",
335 conn->c_authmech.bv_val, conn->c_dn.bv_val, ssf );
337 Debug( LDAP_DEBUG_TRACE,
338 "do_bind: SASL/%s bind: dn=\"%s\" ssf=%d\n",
339 conn->c_authmech.bv_val, conn->c_dn.bv_val, ssf );
342 } else if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) {
343 conn->c_sasl_bind_in_progress = 1;
346 if ( conn->c_sasl_bind_mech.bv_val ) {
347 free( conn->c_sasl_bind_mech.bv_val );
348 conn->c_sasl_bind_mech.bv_val = NULL;
349 conn->c_sasl_bind_mech.bv_len = 0;
351 conn->c_sasl_bind_in_progress = 0;
353 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
358 /* Not SASL, cancel any in-progress bind */
359 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
361 if ( conn->c_sasl_bind_mech.bv_val != NULL ) {
362 free(conn->c_sasl_bind_mech.bv_val);
363 conn->c_sasl_bind_mech.bv_val = NULL;
364 conn->c_sasl_bind_mech.bv_len = 0;
366 conn->c_sasl_bind_in_progress = 0;
368 slap_sasl_reset( conn );
369 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
372 if ( method == LDAP_AUTH_SIMPLE ) {
373 /* accept "anonymous" binds */
374 if ( cred.bv_len == 0 || ndn.bv_len == 0 ) {
379 !( global_allows & SLAP_ALLOW_BIND_ANON_CRED ))
381 /* cred is not empty, disallow */
382 rc = LDAP_INVALID_CREDENTIALS;
384 } else if ( ndn.bv_len &&
385 !( global_allows & SLAP_ALLOW_BIND_ANON_DN ))
387 /* DN is not empty, disallow */
388 rc = LDAP_UNWILLING_TO_PERFORM;
389 text = "unwilling to allow anonymous bind with non-empty DN";
391 } else if ( global_disallows & SLAP_DISALLOW_BIND_ANON ) {
393 rc = LDAP_INAPPROPRIATE_AUTH;
394 text = "anonymous bind disallowed";
397 rc = backend_check_restrictions( NULL, conn, op,
402 * we already forced connection to "anonymous",
403 * just need to send success
405 send_ldap_result( conn, op, rc,
406 NULL, text, NULL, NULL );
408 LDAP_LOG( OPERATION, DETAIL1,
409 "do_bind: conn %d v%d anonymous bind\n",
410 conn->c_connid, version , 0 );
412 Debug( LDAP_DEBUG_TRACE, "do_bind: v%d anonymous bind\n",
417 } else if ( global_disallows & SLAP_DISALLOW_BIND_SIMPLE ) {
418 /* disallow simple authentication */
419 rc = LDAP_UNWILLING_TO_PERFORM;
420 text = "unwilling to perform simple authentication";
422 send_ldap_result( conn, op, rc,
423 NULL, text, NULL, NULL );
425 LDAP_LOG( OPERATION, INFO,
426 "do_bind: conn %d v%d simple bind(%s) disallowed\n",
427 conn->c_connid, version, ndn.bv_val );
429 Debug( LDAP_DEBUG_TRACE,
430 "do_bind: v%d simple bind(%s) disallowed\n",
431 version, ndn.bv_val, 0 );
435 } else if (( global_disallows & SLAP_DISALLOW_BIND_SIMPLE_UNPROTECTED )
436 && ( op->o_ssf <= 1 ))
438 rc = LDAP_CONFIDENTIALITY_REQUIRED;
439 text = "unwilling to perform simple authentication "
440 "without confidentilty protection";
442 send_ldap_result( conn, op, rc,
443 NULL, text, NULL, NULL );
446 LDAP_LOG( OPERATION, INFO, "do_bind: conn %d "
447 "v%d unprotected simple bind(%s) disallowed\n",
448 conn->c_connid, version, ndn.bv_val );
450 Debug( LDAP_DEBUG_TRACE,
451 "do_bind: v%d unprotected simple bind(%s) disallowed\n",
452 version, ndn.bv_val, 0 );
457 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
458 } else if ( method == LDAP_AUTH_KRBV41 || method == LDAP_AUTH_KRBV42 ) {
459 if ( global_disallows & SLAP_DISALLOW_BIND_KRBV4 ) {
460 /* disallow simple authentication */
461 rc = LDAP_UNWILLING_TO_PERFORM;
462 text = "unwilling to perform Kerberos V4 bind";
464 send_ldap_result( conn, op, rc,
465 NULL, text, NULL, NULL );
467 LDAP_LOG( OPERATION, DETAIL1,
468 "do_bind: conn %d v%d Kerberos V4 bind\n",
469 conn->c_connid, version , 0 );
471 Debug( LDAP_DEBUG_TRACE, "do_bind: v%d Kerberos V4 bind\n",
479 rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
480 text = "unknown authentication method";
482 send_ldap_result( conn, op, rc,
483 NULL, text, NULL, NULL );
485 LDAP_LOG( OPERATION, INFO,
486 "do_bind: conn %ld v%d unknown authentication method (%ld)\n",
487 conn->c_connid, version, method );
489 Debug( LDAP_DEBUG_TRACE,
490 "do_bind: v%d unknown authentication method (%ld)\n",
491 version, method, 0 );
497 * We could be serving multiple database backends. Select the
498 * appropriate one, or send a referral to our "referral server"
499 * if we don't hold it.
502 if ( (be = select_backend( &ndn, 0, 0 )) == NULL ) {
503 if ( default_referral ) {
504 BerVarray ref = referral_rewrite( default_referral,
505 NULL, &pdn, LDAP_SCOPE_DEFAULT );
507 send_ldap_result( conn, op, rc = LDAP_REFERRAL,
508 NULL, NULL, ref ? ref : default_referral, NULL );
510 ber_bvarray_free( ref );
513 /* noSuchObject is not allowed to be returned by bind */
514 send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
515 NULL, NULL, NULL, NULL );
521 /* check restrictions */
522 rc = backend_check_restrictions( be, conn, op, NULL, &text );
523 if( rc != LDAP_SUCCESS ) {
524 send_ldap_result( conn, op, rc,
525 NULL, text, NULL, NULL );
532 /* deref suffix alias if appropriate */
533 suffix_alias( be, &ndn );
535 ret = (*be->be_bind)( be, conn, op,
536 &pdn, &ndn, method, &cred, &edn );
539 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
541 if( conn->c_authz_backend == NULL ) {
542 conn->c_authz_backend = be;
557 if( conn->c_dn.bv_len != 0 ) {
558 ber_len_t max = sockbuf_max_incoming_auth;
559 ber_sockbuf_ctrl( conn->c_sb,
560 LBER_SB_OPT_SET_MAX_INCOMING, &max );
563 /* log authorization identity */
564 Statslog( LDAP_DEBUG_STATS,
565 "conn=%lu op=%lu AUTHZ dn=\"%s\" mech=simple ssf=0\n",
566 op->o_connid, op->o_opid,
567 conn->c_dn.bv_val, conn->c_authmech.bv_val, 0 );
570 LDAP_LOG( OPERATION, DETAIL1,
571 "do_bind: v%d bind: \"%s\" to \"%s\" \n",
572 version, conn->c_dn.bv_val, conn->c_dn.bv_val );
574 Debug( LDAP_DEBUG_TRACE,
575 "do_bind: v%d bind: \"%s\" to \"%s\"\n",
576 version, dn.bv_val, conn->c_dn.bv_val );
579 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
581 /* send this here to avoid a race condition */
582 send_ldap_result( conn, op, LDAP_SUCCESS,
583 NULL, NULL, NULL, NULL );
585 } else if (edn.bv_val != NULL) {
590 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
591 NULL, "operation not supported within namingContext",
596 conn->c_sasl_bindop = NULL;
598 if( pdn.bv_val != NULL ) {
601 if( ndn.bv_val != NULL ) {
604 if ( mech.bv_val != NULL ) {