]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
Added Will Ballantyne's General Aliasing code.
[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 <stdio.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include "slap.h"
20
21 extern Backend  *select_backend();
22 extern char     *suffixAlias();
23
24 extern char     *default_referral;
25
26 void
27 do_bind(
28     Connection  *conn,
29     Operation   *op
30 )
31 {
32         BerElement      *ber = op->o_ber;
33         int             version, method, len, rc;
34         char            *dn;
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 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 = *op->o_ber;
65         ttag = ber_skip_tag( &tber, &tlen );
66         if ( ber_peek_tag( &tber, &tlen ) == LBER_SEQUENCE ) {
67                 Debug( LDAP_DEBUG_ANY, "version 3.0 detected\n", 0, 0, 0 );
68                 conn->c_version = 30;
69                 rc = ber_scanf(ber, "{{iato}}", &version, &dn, &method, &cred);
70         } else {
71                 rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
72         }
73         }
74 #else
75         rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
76 #endif
77         if ( rc == LBER_ERROR ) {
78                 Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
79                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
80                     "decoding error" );
81                 return;
82         }
83 #ifdef COMPAT30
84         if ( conn->c_version == 30 ) {
85                 switch ( method ) {
86                 case LDAP_AUTH_SIMPLE_30:
87                         method = LDAP_AUTH_SIMPLE;
88                         break;
89 #ifdef KERBEROS
90                 case LDAP_AUTH_KRBV41_30:
91                         method = LDAP_AUTH_KRBV41;
92                         break;
93                 case LDAP_AUTH_KRBV42_30:
94                         method = LDAP_AUTH_KRBV42;
95                         break;
96 #endif
97                 }
98         }
99 #endif /* compat30 */
100         dn_normalize( dn );
101
102         Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
103             conn->c_connid, op->o_opid, dn, method, 0 );
104
105         if ( version != LDAP_VERSION2 ) {
106                 if ( dn != NULL ) {
107                         free( dn );
108                 }
109                 if ( cred.bv_val != NULL ) {
110                         free( cred.bv_val );
111                 }
112
113                 Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
114                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
115                     "version not supported" );
116                 return;
117         }
118
119         Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
120             version, dn, method );
121
122         /* accept null binds */
123         if ( dn == NULL || *dn == '\0' ) {
124                 if ( dn != NULL ) {
125                         free( dn );
126                 }
127                 if ( cred.bv_val != NULL ) {
128                         free( cred.bv_val );
129                 }
130
131                 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
132                 return;
133         }
134
135         /*
136          * We could be serving multiple database backends.  Select the
137          * appropriate one, or send a referral to our "referral server"
138          * if we don't hold it.
139          */
140
141         if ( (be = select_backend( dn )) == NULL ) {
142                 free( dn );
143                 if ( cred.bv_val != NULL ) {
144                         free( cred.bv_val );
145                 }
146                 if ( cred.bv_len == 0 ) {
147                         send_ldap_result( conn, op, LDAP_SUCCESS,
148                                 NULL, NULL );
149                 } else if ( default_referral && *default_referral ) {
150                         send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS,
151                                 NULL, default_referral );
152                 } else {
153                         send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
154                                 NULL, default_referral );
155                 }
156                 return;
157         }
158
159         /* alias suffix */
160         dn = suffixAlias ( dn, op, be );
161
162         if ( be->be_bind != NULL ) {
163                 if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
164                         pthread_mutex_lock( &conn->c_dnmutex );
165                         if ( conn->c_dn != NULL ) {
166                                 free( conn->c_dn );
167                         }
168                         conn->c_dn = strdup( dn );
169                         pthread_mutex_unlock( &conn->c_dnmutex );
170
171                         /* send this here to avoid a race condition */
172                         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
173                 }
174         } else {
175                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
176                     "Function not implemented" );
177         }
178
179         free( dn );
180         if ( cred.bv_val != NULL ) {
181                 free( cred.bv_val );
182         }
183 }