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