xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-mdb/bind.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: bind.c,v 1.1.1.1 2014/05/28 09:58:49 tron Exp $	*/
2 
3 /* bind.c - mdb backend bind routine */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2000-2014 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 #include "portable.h"
20 
21 #include <stdio.h>
22 #include <ac/string.h>
23 #include <ac/unistd.h>
24 
25 #include "back-mdb.h"
26 
27 int
28 mdb_bind( Operation *op, SlapReply *rs )
29 {
30 	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
31 	Entry		*e;
32 	Attribute	*a;
33 
34 	AttributeDescription *password = slap_schema.si_ad_userPassword;
35 
36 	MDB_txn		*rtxn;
37 	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;
38 
39 	Debug( LDAP_DEBUG_ARGS,
40 		"==> " LDAP_XSTRING(mdb_bind) ": dn: %s\n",
41 		op->o_req_dn.bv_val, 0, 0);
42 
43 	/* allow noauth binds */
44 	switch ( be_rootdn_bind( op, NULL ) ) {
45 	case LDAP_SUCCESS:
46 		/* frontend will send result */
47 		return rs->sr_err = LDAP_SUCCESS;
48 
49 	default:
50 		/* give the database a chance */
51 		/* NOTE: this behavior departs from that of other backends,
52 		 * since the others, in case of password checking failure
53 		 * do not give the database a chance.  If an entry with
54 		 * rootdn's name does not exist in the database the result
55 		 * will be the same.  See ITS#4962 for discussion. */
56 		break;
57 	}
58 
59 	rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi);
60 	switch(rs->sr_err) {
61 	case 0:
62 		break;
63 	default:
64 		rs->sr_text = "internal error";
65 		send_ldap_result( op, rs );
66 		return rs->sr_err;
67 	}
68 
69 	rtxn = moi->moi_txn;
70 
71 	/* get entry with reader lock */
72 	rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 0 );
73 
74 	switch(rs->sr_err) {
75 	case MDB_NOTFOUND:
76 		rs->sr_err = LDAP_INVALID_CREDENTIALS;
77 		goto done;
78 	case 0:
79 		break;
80 	case LDAP_BUSY:
81 		rs->sr_text = "ldap_server_busy";
82 		goto done;
83 	default:
84 		rs->sr_err = LDAP_OTHER;
85 		rs->sr_text = "internal error";
86 		goto done;
87 	}
88 
89 	ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );
90 
91 	/* check for deleted */
92 	if ( is_entry_subentry( e ) ) {
93 		/* entry is an subentry, don't allow bind */
94 		Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0,
95 			0, 0 );
96 		rs->sr_err = LDAP_INVALID_CREDENTIALS;
97 		goto done;
98 	}
99 
100 	if ( is_entry_alias( e ) ) {
101 		/* entry is an alias, don't allow bind */
102 		Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
103 		rs->sr_err = LDAP_INVALID_CREDENTIALS;
104 		goto done;
105 	}
106 
107 	if ( is_entry_referral( e ) ) {
108 		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
109 			0, 0 );
110 		rs->sr_err = LDAP_INVALID_CREDENTIALS;
111 		goto done;
112 	}
113 
114 	switch ( op->oq_bind.rb_method ) {
115 	case LDAP_AUTH_SIMPLE:
116 		a = attr_find( e->e_attrs, password );
117 		if ( a == NULL ) {
118 			rs->sr_err = LDAP_INVALID_CREDENTIALS;
119 			goto done;
120 		}
121 
122 		if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
123 					&rs->sr_text ) != 0 )
124 		{
125 			/* failure; stop front end from sending result */
126 			rs->sr_err = LDAP_INVALID_CREDENTIALS;
127 			goto done;
128 		}
129 
130 		rs->sr_err = 0;
131 		break;
132 
133 	default:
134 		assert( 0 ); /* should not be reachable */
135 		rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
136 		rs->sr_text = "authentication method not supported";
137 	}
138 
139 done:
140 	if ( moi == &opinfo ) {
141 		mdb_txn_reset( moi->moi_txn );
142 		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
143 	} else {
144 		moi->moi_ref--;
145 	}
146 	/* free entry and reader lock */
147 	if( e != NULL ) {
148 		mdb_entry_return( op, e );
149 	}
150 
151 	if ( rs->sr_err ) {
152 		send_ldap_result( op, rs );
153 		if ( rs->sr_ref ) {
154 			ber_bvarray_free( rs->sr_ref );
155 			rs->sr_ref = NULL;
156 		}
157 	}
158 	/* front end will send result on success (rs->sr_err==0) */
159 	return rs->sr_err;
160 }
161