]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
0d380079a8252c8fc4e2c11d8f20ad355c89f71e
[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         rc = ber_scanf( ber, "{iato}", &version, &cdn, &method, &cred );
55
56         if ( rc == LBER_ERROR ) {
57                 Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
58                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
59                     "decoding error" );
60                 return;
61         }
62
63         Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
64             version, cdn, method );
65
66         ndn = dn_normalize_case( ch_strdup( cdn ) );
67
68         Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
69             conn->c_connid, op->o_opid, ndn, method, 0 );
70
71         if ( version != LDAP_VERSION2 ) {
72                 if ( cdn != NULL ) {
73                         free( cdn );
74                 }
75                 if ( ndn != NULL ) {
76                         free( ndn );
77                 }
78                 if ( cred.bv_val != NULL ) {
79                         free( cred.bv_val );
80                 }
81
82                 Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
83                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
84                     "version not supported" );
85                 return;
86         }
87
88         /* accept null binds */
89         if ( ndn == NULL || *ndn == '\0' ) {
90                 if ( cdn != NULL ) {
91                         free( cdn );
92                 }
93                 if ( ndn != NULL ) {
94                         free( ndn );
95                 }
96                 if ( cred.bv_val != NULL ) {
97                         free( cred.bv_val );
98                 }
99
100                 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
101
102                 conn->c_protocol = version;
103
104                 if ( conn->c_cdn != NULL ) {
105                         free( conn->c_cdn );
106                         conn->c_cdn = NULL;
107                 }
108
109                 if ( conn->c_dn != NULL ) {
110                         free( conn->c_dn );
111                         conn->c_dn = NULL;
112                 }
113
114                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
115
116                 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
117                 return;
118         }
119
120         /*
121          * We could be serving multiple database backends.  Select the
122          * appropriate one, or send a referral to our "referral server"
123          * if we don't hold it.
124          */
125
126         if ( (be = select_backend( ndn )) == NULL ) {
127                 free( cdn );
128                 free( ndn );
129                 if ( cred.bv_val != NULL ) {
130                         free( cred.bv_val );
131                 }
132                 if ( cred.bv_len == 0 ) {
133                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
134
135                         conn->c_protocol = version;
136
137                         if ( conn->c_cdn != NULL ) {
138                                 free( conn->c_cdn );
139                                 conn->c_cdn = NULL;
140                         }
141
142                         if ( conn->c_dn != NULL ) {
143                                 free( conn->c_dn );
144                                 conn->c_dn = NULL;
145                         }
146
147                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
148
149                         send_ldap_result( conn, op, LDAP_SUCCESS,
150                                 NULL, NULL );
151                 } else if ( default_referral && *default_referral ) {
152                         send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS,
153                                 NULL, default_referral );
154                 } else {
155                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
156                                 NULL, default_referral );
157                 }
158                 return;
159         }
160
161         if ( be->be_bind ) {
162                 /* alias suffix */
163                 char *edn;
164
165                 ndn = suffixAlias( ndn, op, be );
166
167                 if ( (*be->be_bind)( be, conn, op, ndn, method, &cred, &edn ) == 0 ) {
168                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
169
170                         conn->c_protocol = version;
171
172                         if ( conn->c_cdn != NULL ) {
173                                 free( conn->c_cdn );
174                         }
175
176                         conn->c_cdn = cdn;
177                         cdn = NULL;
178
179                         if ( conn->c_dn != NULL ) {
180                                 free( conn->c_dn );
181                         }
182
183                         if(edn != NULL) {
184                                 conn->c_dn = edn;
185                         } else {
186                                 conn->c_dn = ndn;
187                                 ndn = NULL;
188                         }
189
190                         Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
191                         conn->c_cdn, conn->c_dn, method );
192
193                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
194
195                         /* send this here to avoid a race condition */
196                         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
197
198                 } else if (edn != NULL) {
199                         free( edn );
200                 }
201
202         } else {
203                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
204                     "Function not implemented" );
205         }
206
207         if( cdn != NULL ) {
208                 free( cdn );
209         }
210         if( ndn != NULL ) {
211                 free( ndn );
212         }
213         if ( cred.bv_val != NULL ) {
214                 free( cred.bv_val );
215         }
216 }