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