]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
ldap.h:
[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         int             version;
32         unsigned long method;
33         char            *cdn, *ndn;
34         unsigned long   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         unsigned long   tlen, ttag;
63
64         tber = ber_dup( op->o_ber );
65         ttag = ber_skip_tag( tber, &tlen );
66         if ( ber_peek_tag( tber, &tlen ) == LBER_SEQUENCE ) {
67                 Debug( LDAP_DEBUG_ANY, "bind: u-mich v3.0 detected\n", 0, 0, 0 );
68                 conn->c_version = 30;
69                 rc = ber_scanf(ber, "{{iato}}", &version, &cdn, &method, &cred);
70         } else {
71                 rc = ber_scanf( ber, "{iato}", &version, &cdn, &method, &cred );
72         }
73
74         ber_free( tber, 0 );
75         }
76 #else
77         rc = ber_scanf( ber, "{iato}", &version, &cdn, &method, &cred );
78 #endif
79
80         if ( rc == LBER_ERROR ) {
81                 Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
82                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
83                     "decoding error" );
84                 return;
85         }
86
87 #ifdef LDAP_COMPAT30
88         if ( conn->c_version == 30 ) {
89                 switch ( method ) {
90                 case LDAP_AUTH_SIMPLE_30:
91                         method = LDAP_AUTH_SIMPLE;
92                         break;
93 #ifdef HAVE_KERBEROS
94                 case LDAP_AUTH_KRBV41_30:
95                         method = LDAP_AUTH_KRBV41;
96                         break;
97                 case LDAP_AUTH_KRBV42_30:
98                         method = LDAP_AUTH_KRBV42;
99                         break;
100 #endif
101                 }
102         }
103 #endif /* compat30 */
104
105         Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
106             version, cdn, method );
107
108         ndn = dn_normalize_case( ch_strdup( cdn ) );
109
110         Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
111             conn->c_connid, op->o_opid, ndn, method, 0 );
112
113         if ( version != LDAP_VERSION2 ) {
114                 if ( cdn != NULL ) {
115                         free( cdn );
116                 }
117                 if ( ndn != NULL ) {
118                         free( ndn );
119                 }
120                 if ( cred.bv_val != NULL ) {
121                         free( cred.bv_val );
122                 }
123
124                 Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
125                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
126                     "version not supported" );
127                 return;
128         }
129
130         /* accept null binds */
131         if ( ndn == NULL || *ndn == '\0' ) {
132                 if ( cdn != NULL ) {
133                         free( cdn );
134                 }
135                 if ( ndn != NULL ) {
136                         free( ndn );
137                 }
138                 if ( cred.bv_val != NULL ) {
139                         free( cred.bv_val );
140                 }
141
142                 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
143
144                 conn->c_protocol = version;
145
146                 if ( conn->c_cdn != NULL ) {
147                         free( conn->c_cdn );
148                         conn->c_cdn = NULL;
149                 }
150
151                 if ( conn->c_dn != NULL ) {
152                         free( conn->c_dn );
153                         conn->c_dn = NULL;
154                 }
155
156                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
157
158                 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
159                 return;
160         }
161
162         /*
163          * We could be serving multiple database backends.  Select the
164          * appropriate one, or send a referral to our "referral server"
165          * if we don't hold it.
166          */
167
168         if ( (be = select_backend( ndn )) == NULL ) {
169                 free( cdn );
170                 free( ndn );
171                 if ( cred.bv_val != NULL ) {
172                         free( cred.bv_val );
173                 }
174                 if ( cred.bv_len == 0 ) {
175                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
176
177                         conn->c_protocol = version;
178
179                         if ( conn->c_cdn != NULL ) {
180                                 free( conn->c_cdn );
181                                 conn->c_cdn = NULL;
182                         }
183
184                         if ( conn->c_dn != NULL ) {
185                                 free( conn->c_dn );
186                                 conn->c_dn = NULL;
187                         }
188
189                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
190
191                         send_ldap_result( conn, op, LDAP_SUCCESS,
192                                 NULL, NULL );
193                 } else if ( default_referral && *default_referral ) {
194                         send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS,
195                                 NULL, default_referral );
196                 } else {
197                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
198                                 NULL, default_referral );
199                 }
200                 return;
201         }
202
203         if ( be->be_bind ) {
204                 /* alias suffix */
205                 char *edn;
206
207                 ndn = suffixAlias( ndn, op, be );
208
209                 if ( (*be->be_bind)( be, conn, op, ndn, method, &cred, &edn ) == 0 ) {
210                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
211
212                         conn->c_protocol = version;
213
214                         if ( conn->c_cdn != NULL ) {
215                                 free( conn->c_cdn );
216                         }
217
218                         conn->c_cdn = cdn;
219                         cdn = NULL;
220
221                         if ( conn->c_dn != NULL ) {
222                                 free( conn->c_dn );
223                         }
224
225                         if(edn != NULL) {
226                                 conn->c_dn = edn;
227                         } else {
228                                 conn->c_dn = ndn;
229                                 ndn = NULL;
230                         }
231
232                         Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
233                         conn->c_cdn, conn->c_dn, method );
234
235                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
236
237                         /* send this here to avoid a race condition */
238                         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
239
240                 } else if (edn != NULL) {
241                         free( edn );
242                 }
243
244         } else {
245                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
246                     "Function not implemented" );
247         }
248
249         if( cdn != NULL ) {
250                 free( cdn );
251         }
252         if( ndn != NULL ) {
253                 free( ndn );
254         }
255         if ( cred.bv_val != NULL ) {
256                 free( cred.bv_val );
257         }
258 }