]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
c72368608e9ba82a6f9543c74e72855a5f314d3c
[openldap] / servers / slapd / bind.c
1 /* bind.c - decode an ldap bind operation and pass it to a backend db */
2
3 /*
4  * Copyright (c) 1995 Regents of the University of Michigan.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that this notice is preserved and that due credit is given
9  * to the University of Michigan at Ann Arbor. The name of the University
10  * may not be used to endorse or promote products derived from this
11  * software without specific prior written permission. This software
12  * is provided ``as is'' without express or implied warranty.
13  */
14
15 #include "portable.h"
16
17 #include <stdio.h>
18
19 #include <ac/string.h>
20 #include <ac/socket.h>
21
22 #include "slap.h"
23
24 void
25 do_bind(
26     Connection  *conn,
27     Operation   *op
28 )
29 {
30         BerElement      *ber = op->o_ber;
31         ber_int_t               version;
32         ber_tag_t method;
33         char            *cdn, *ndn;
34         ber_tag_t       rc;
35         struct berval   cred;
36         Backend         *be;
37
38         Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
39
40         /*
41          * Parse the bind request.  It looks like this:
42          *
43          *      BindRequest ::= SEQUENCE {
44          *              version         INTEGER,                 -- version
45          *              name            DistinguishedName,       -- dn
46          *              authentication  CHOICE {
47          *                      simple          [0] OCTET STRING -- passwd
48          *                      krbv42ldap      [1] OCTET STRING
49          *                      krbv42dsa       [1] OCTET STRING
50          *              }
51          *      }
52          */
53
54 #ifdef LDAP_COMPAT30
55         /*
56          * in version 3.0 there is an extra SEQUENCE tag after the
57          * BindRequest SEQUENCE tag.
58          */
59
60         {
61         BerElement      *tber;
62         ber_len_t       tlen;
63         ber_tag_t       ttag;
64
65         tber = ber_dup( op->o_ber );
66         ttag = ber_skip_tag( tber, &tlen );
67         if ( ber_peek_tag( tber, &tlen ) == LBER_SEQUENCE ) {
68                 Debug( LDAP_DEBUG_ANY, "bind: u-mich v3.0 detected\n", 0, 0, 0 );
69                 conn->c_version = 30;
70                 rc = ber_scanf(ber, "{{iato}}", &version, &cdn, &method, &cred);
71         } else {
72                 rc = ber_scanf( ber, "{iato}", &version, &cdn, &method, &cred );
73         }
74
75         ber_free( tber, 0 );
76         }
77 #else
78         rc = ber_scanf( ber, "{iato}", &version, &cdn, &method, &cred );
79 #endif
80
81         if ( rc == LBER_ERROR ) {
82                 Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
83                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
84                     "decoding error" );
85                 return;
86         }
87
88 #ifdef LDAP_COMPAT30
89         if ( conn->c_version == 30 ) {
90                 switch ( method ) {
91                 case LDAP_AUTH_SIMPLE_30:
92                         method = LDAP_AUTH_SIMPLE;
93                         break;
94 #ifdef HAVE_KERBEROS
95                 case LDAP_AUTH_KRBV41_30:
96                         method = LDAP_AUTH_KRBV41;
97                         break;
98                 case LDAP_AUTH_KRBV42_30:
99                         method = LDAP_AUTH_KRBV42;
100                         break;
101 #endif
102                 }
103         }
104 #endif /* compat30 */
105
106         Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
107             version, cdn, method );
108
109         ndn = dn_normalize_case( ch_strdup( cdn ) );
110
111         Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
112             conn->c_connid, op->o_opid, ndn, method, 0 );
113
114         if ( version != LDAP_VERSION2 ) {
115                 if ( cdn != NULL ) {
116                         free( cdn );
117                 }
118                 if ( ndn != NULL ) {
119                         free( ndn );
120                 }
121                 if ( cred.bv_val != NULL ) {
122                         free( cred.bv_val );
123                 }
124
125                 Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
126                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
127                     "version not supported" );
128                 return;
129         }
130
131         /* accept null binds */
132         if ( ndn == NULL || *ndn == '\0' ) {
133                 if ( cdn != NULL ) {
134                         free( cdn );
135                 }
136                 if ( ndn != NULL ) {
137                         free( ndn );
138                 }
139                 if ( cred.bv_val != NULL ) {
140                         free( cred.bv_val );
141                 }
142
143                 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
144
145                 conn->c_protocol = version;
146
147                 if ( conn->c_cdn != NULL ) {
148                         free( conn->c_cdn );
149                         conn->c_cdn = NULL;
150                 }
151
152                 if ( conn->c_dn != NULL ) {
153                         free( conn->c_dn );
154                         conn->c_dn = NULL;
155                 }
156
157                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
158
159                 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
160                 return;
161         }
162
163         /*
164          * We could be serving multiple database backends.  Select the
165          * appropriate one, or send a referral to our "referral server"
166          * if we don't hold it.
167          */
168
169         if ( (be = select_backend( ndn )) == NULL ) {
170                 free( cdn );
171                 free( ndn );
172                 if ( cred.bv_val != NULL ) {
173                         free( cred.bv_val );
174                 }
175                 if ( cred.bv_len == 0 ) {
176                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
177
178                         conn->c_protocol = version;
179
180                         if ( conn->c_cdn != NULL ) {
181                                 free( conn->c_cdn );
182                                 conn->c_cdn = NULL;
183                         }
184
185                         if ( conn->c_dn != NULL ) {
186                                 free( conn->c_dn );
187                                 conn->c_dn = NULL;
188                         }
189
190                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
191
192                         send_ldap_result( conn, op, LDAP_SUCCESS,
193                                 NULL, NULL );
194                 } else if ( default_referral && *default_referral ) {
195                         send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS,
196                                 NULL, default_referral );
197                 } else {
198                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
199                                 NULL, default_referral );
200                 }
201                 return;
202         }
203
204         if ( be->be_bind ) {
205                 /* alias suffix */
206                 char *edn;
207
208                 ndn = suffixAlias( ndn, op, be );
209
210                 if ( (*be->be_bind)( be, conn, op, ndn, method, &cred, &edn ) == 0 ) {
211                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
212
213                         conn->c_protocol = version;
214
215                         if ( conn->c_cdn != NULL ) {
216                                 free( conn->c_cdn );
217                         }
218
219                         conn->c_cdn = cdn;
220                         cdn = NULL;
221
222                         if ( conn->c_dn != NULL ) {
223                                 free( conn->c_dn );
224                         }
225
226                         if(edn != NULL) {
227                                 conn->c_dn = edn;
228                         } else {
229                                 conn->c_dn = ndn;
230                                 ndn = NULL;
231                         }
232
233                         Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
234                         conn->c_cdn, conn->c_dn, method );
235
236                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
237
238                         /* send this here to avoid a race condition */
239                         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
240
241                 } else if (edn != NULL) {
242                         free( edn );
243                 }
244
245         } else {
246                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
247                     "Function not implemented" );
248         }
249
250         if( cdn != NULL ) {
251                 free( cdn );
252         }
253         if( ndn != NULL ) {
254                 free( ndn );
255         }
256         if ( cred.bv_val != NULL ) {
257                 free( cred.bv_val );
258         }
259 }