]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
include portable.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 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include "slap.h"
22
23 extern Backend  *select_backend();
24
25 extern char     *default_referral;
26
27 void
28 do_bind(
29     Connection  *conn,
30     Operation   *op
31 )
32 {
33         BerElement      *ber = op->o_ber;
34         int             version, method, len, rc;
35         char            *dn;
36         struct berval   cred;
37         Backend         *be;
38
39         Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
40
41         /*
42          * Parse the bind request.  It looks like this:
43          *
44          *      BindRequest ::= SEQUENCE {
45          *              version         INTEGER,                 -- version
46          *              name            DistinguishedName,       -- dn
47          *              authentication  CHOICE {
48          *                      simple          [0] OCTET STRING -- passwd
49          *                      krbv42ldap      [1] OCTET STRING
50          *                      krbv42dsa       [1] OCTET STRING
51          *              }
52          *      }
53          */
54
55 #ifdef COMPAT30
56         /*
57          * in version 3.0 there is an extra SEQUENCE tag after the
58          * BindRequest SEQUENCE tag.
59          */
60
61         {
62         BerElement      tber;
63         unsigned long   tlen, ttag;
64
65         tber = *op->o_ber;
66         ttag = ber_skip_tag( &tber, &tlen );
67         if ( ber_peek_tag( &tber, &tlen ) == LBER_SEQUENCE ) {
68                 Debug( LDAP_DEBUG_ANY, "version 3.0 detected\n", 0, 0, 0 );
69                 conn->c_version = 30;
70                 rc = ber_scanf(ber, "{{iato}}", &version, &dn, &method, &cred);
71         } else {
72                 rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
73         }
74         }
75 #else
76         rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
77 #endif
78         if ( rc == LBER_ERROR ) {
79                 Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
80                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
81                     "decoding error" );
82                 return;
83         }
84 #ifdef COMPAT30
85         if ( conn->c_version == 30 ) {
86                 switch ( method ) {
87                 case LDAP_AUTH_SIMPLE_30:
88                         method = LDAP_AUTH_SIMPLE;
89                         break;
90 #ifdef KERBEROS
91                 case LDAP_AUTH_KRBV41_30:
92                         method = LDAP_AUTH_KRBV41;
93                         break;
94                 case LDAP_AUTH_KRBV42_30:
95                         method = LDAP_AUTH_KRBV42;
96                         break;
97 #endif
98                 }
99         }
100 #endif /* compat30 */
101         dn_normalize( dn );
102
103         Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
104             conn->c_connid, op->o_opid, dn, method, 0 );
105
106         if ( version != LDAP_VERSION2 ) {
107                 if ( dn != NULL ) {
108                         free( dn );
109                 }
110                 if ( cred.bv_val != NULL ) {
111                         free( cred.bv_val );
112                 }
113
114                 Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
115                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
116                     "version not supported" );
117                 return;
118         }
119
120         Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
121             version, dn, method );
122
123         /* accept null binds */
124         if ( dn == NULL || *dn == '\0' ) {
125                 if ( dn != NULL ) {
126                         free( dn );
127                 }
128                 if ( cred.bv_val != NULL ) {
129                         free( cred.bv_val );
130                 }
131
132                 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
133                 return;
134         }
135
136         /*
137          * We could be serving multiple database backends.  Select the
138          * appropriate one, or send a referral to our "referral server"
139          * if we don't hold it.
140          */
141
142         if ( (be = select_backend( dn )) == NULL ) {
143                 free( dn );
144                 if ( cred.bv_val != NULL ) {
145                         free( cred.bv_val );
146                 }
147                 if ( cred.bv_len == 0 ) {
148                         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
149                 } else {
150                         send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
151                             default_referral );
152                 }
153                 return;
154         }
155
156         if ( be->be_bind != NULL ) {
157                 if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
158                         pthread_mutex_lock( &conn->c_dnmutex );
159                         if ( conn->c_dn != NULL ) {
160                                 free( conn->c_dn );
161                         }
162                         conn->c_dn = strdup( dn );
163                         pthread_mutex_unlock( &conn->c_dnmutex );
164
165                         /* send this here to avoid a race condition */
166                         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
167                 }
168         } else {
169                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
170                     "Function not implemented" );
171         }
172
173         free( dn );
174         if ( cred.bv_val != NULL ) {
175                 free( cred.bv_val );
176         }
177 }