]> git.sur5r.net Git - openldap/blob - servers/ldapd/bind.c
Initial revision
[openldap] / servers / ldapd / bind.c
1 /*
2  * Copyright (c) 1990 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <netdb.h>
17 #include <netinet/in.h>
18 #include <quipu/commonarg.h>
19 #include <quipu/attrvalue.h>
20 #include <quipu/ds_error.h>
21 #include <quipu/bind.h>
22 #include <quipu/compare.h>
23 #include "lber.h"
24 #include "ldap.h"
25 #include "common.h"
26
27 #ifdef COMPAT20
28 extern int      ldap_compat;
29 #define BINDTAG (ldap_compat == 20 ? OLD_LDAP_RES_BIND : LDAP_RES_BIND)
30 #else
31 #define BINDTAG LDAP_RES_BIND
32 #endif
33
34 /*
35  * do_bind - perform an X.500 bind operation.  Since we always respond
36  * to the request in here, always return 0 to signify the incoming message
37  * can be discarded.
38  */
39
40 int
41 do_bind( 
42     Sockbuf     *clientsb,
43     struct msg  *m,
44     BerElement  *ber,
45     int         *bound
46 )
47 {
48         int             err;
49         unsigned long   method;
50         unsigned long   len;
51         char            *dn, *pw;
52         char            *matched;
53         struct PSAPaddr *addr, *psap_cpy();
54         extern char     *dsa_address;
55         extern int      version;
56
57         Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
58
59         /*
60          * Parse the bind request.  It looks like this:
61          *      BindRequest ::= SEQUENCE {
62          *              version         INTEGER,                 -- version
63          *              name            DistinguishedName,       -- dn
64          *              authentication  CHOICE {
65          *                      simple          [0] OCTET STRING -- passwd
66          *                      krbv42ldap      [1] OCTET STRING
67          *                      krbv42dsa       [1] OCTET STRING
68          *              }
69          *      }
70          */
71
72         if ( ber_scanf( ber, "{ia", &version, &dn ) == LBER_ERROR ) {
73                 Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
74                 send_ldap_msgresult( clientsb, BINDTAG, m,
75                     LDAP_PROTOCOL_ERROR, NULL, "Decoding error" );
76                 return( 0 );
77         }
78 #ifdef COMPAT30
79         if ( ldap_compat == 30 )
80                 method = ber_skip_tag( ber, &len );
81         else
82 #endif
83                 method = ber_peek_tag( ber, &len );
84
85         if ( ber_scanf( ber, "la}", &len, &pw ) == LBER_ERROR ) {
86                 Debug( LDAP_DEBUG_ANY, "ber_scanf2 failed\n", 0, 0, 0 );
87                 send_ldap_msgresult( clientsb, BINDTAG, m,
88                     LDAP_PROTOCOL_ERROR, NULL, "Decoding error" );
89                 return( 0 );
90         }
91
92         if ( version != LDAP_VERSION1 && version != LDAP_VERSION2 ) {
93                 Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
94                 send_ldap_msgresult( clientsb, BINDTAG, m,
95                     LDAP_PROTOCOL_ERROR, NULL, "Version not supported" );
96                 return( 0 );
97         }
98
99         Debug( LDAP_DEBUG_ARGS, "do_bind: version %d dn (%s) method %d\n",
100             version, dn, method );
101
102         if ( m->m_conn->c_paddr == NULLPA ) {
103                 char    buf[256];
104
105                 sprintf( buf, "Bad DSA address (%s)", dsa_address ?
106                     dsa_address : "NULL" );
107                 send_ldap_msgresult( clientsb, BINDTAG, m,
108                     LDAP_OPERATIONS_ERROR, NULL, buf );
109                 return( 0 );
110         }
111
112         if ( m->m_conn->c_dn )
113                 free( m->m_conn->c_dn );
114         if ( m->m_conn->c_cred )
115                 free( m->m_conn->c_cred );
116         m->m_conn->c_dn = dn;
117         m->m_conn->c_cred = pw;
118         m->m_conn->c_credlen = len;
119         m->m_conn->c_method = method;
120
121         err = do_bind_real( m->m_conn, bound, &matched );
122
123         send_ldap_msgresult( clientsb, BINDTAG, m, err, matched, "" );
124
125         if ( matched != NULL )
126                 free( matched );
127
128         return( 0 );
129 }
130
131 int
132 do_bind_real(
133     struct conn *dsaconn,
134     int         *bound,
135     char        **matched
136 )
137 {
138         struct ds_bind_arg      ba;
139         struct ds_bind_arg      br;
140         struct ds_bind_error    be;
141         struct DSError          dse;
142         char                    *dn = dsaconn->c_dn;
143         int                     err;
144 #ifdef KERBEROS
145         u_long                  nonce;
146 #endif
147         extern DN               ldap_str2dn();
148
149         Debug( LDAP_DEBUG_TRACE, "do_bind_real\n", 0, 0, 0 );
150
151         *matched = NULL;
152         if ( (ba.dba_dn = ldap_str2dn( dn )) == NULLDN && *dn != '\0' ) {
153                 Debug( LDAP_DEBUG_ANY, "ldap_str2dn (%s) failed\n", dn, 0, 0 );
154                 return( LDAP_INVALID_DN_SYNTAX );
155         }
156
157         switch ( dsaconn->c_method ) {
158 #ifdef COMPAT20
159         case OLD_LDAP_AUTH_SIMPLE:
160 #endif
161 #ifdef COMPAT30
162         case LDAP_AUTH_SIMPLE_30:
163 #endif
164         case LDAP_AUTH_SIMPLE:  /* x.500 simple authentication */
165                 if ( dsaconn->c_credlen > DBA_MAX_PASSWD_LEN ) {
166                         Debug( LDAP_DEBUG_ANY, "Password too long\n", 0, 0, 0 );
167                         return( LDAP_INAPPROPRIATE_AUTH );
168                 }
169                 if (( ba.dba_passwd_len = dsaconn->c_credlen ) > 0 ) {
170                         SAFEMEMCPY( ba.dba_passwd, dsaconn->c_cred,
171                             ba.dba_passwd_len );
172                         ba.dba_auth_type = DBA_AUTH_SIMPLE;
173                 } else {
174                         ba.dba_auth_type = DBA_AUTH_NONE;
175                 }
176                 ba.dba_version = DBA_VERSION_V1988;
177                 break;
178
179 #ifdef KERBEROS
180 #ifdef COMPAT20
181         case OLD_LDAP_AUTH_KRBV4:
182 #endif
183 #ifdef COMPAT30
184         case LDAP_AUTH_KRBV41_30:
185 #endif
186         case LDAP_AUTH_KRBV41:  /* kerberos authentication to ldap server */
187                 return( kerberosv4_ldap_auth( dsaconn->c_cred,
188                     dsaconn->c_credlen ) );
189                 break;
190
191 #ifdef COMPAT20
192         case OLD_LDAP_AUTH_KRBV42:
193 #endif
194 #ifdef COMPAT30
195         case LDAP_AUTH_KRBV42_30:
196 #endif
197         case LDAP_AUTH_KRBV42:  /* kerberos authentication to x500 dsa */
198                 if ( (err = kerberosv4_bindarg( &ba, ba.dba_dn, dsaconn->c_cred,
199                     dsaconn->c_credlen, &nonce )) != 0 )
200                         return( err );
201                 break;
202 #endif
203
204         default:
205                 return( LDAP_PROTOCOL_ERROR );
206                 break;
207         }
208
209         if ( dsaconn->c_ad != -1 )
210                 dap_unbind( dsaconn->c_ad );
211
212         Debug( LDAP_DEBUG_TRACE, "dap_bind to dsa (%s)...\n", paddr2str(
213             dsaconn->c_paddr, NULLNA ), 0, 0 );
214
215         err = dap_bind( &dsaconn->c_ad, &ba, &be, &br, dsaconn->c_paddr );
216
217         if ( err != DS_OK && ba.dba_dn != NULLDN && ba.dba_auth_type
218             == DBA_AUTH_NONE && be.dbe_type == DBE_TYPE_SECURITY ) {
219                 /* if doing a NULL bind, retry with a NULL dn */
220                 Debug( LDAP_DEBUG_TRACE, "retring NULL dap_bind\n", 0, 0, 0 );
221                 dn_free( ba.dba_dn );
222                 ba.dba_dn = NULLDN;
223                 err = dap_bind( &dsaconn->c_ad, &ba, &be, &br,
224                     dsaconn->c_paddr );
225         }
226
227         if ( err != DS_OK ) {
228                 if ( ba.dba_dn != NULLDN )
229                         dn_free( ba.dba_dn );
230
231                 if ( be.dbe_type == DBE_TYPE_SERVICE ) {
232                         dse.dse_type = DSE_SERVICEERROR;
233                         dse.ERR_SERVICE.DSE_sv_problem = be.dbe_value;
234                 } else if ( be.dbe_type == DBE_TYPE_SECURITY ) {
235                         dse.dse_type = DSE_SECURITYERROR;
236                         dse.ERR_SECURITY.DSE_sc_problem = be.dbe_value;
237                 } else {
238                         dse.dse_type = DSE_REMOTEERROR;
239                 }
240                 err = x500err2ldaperr( &dse, matched );
241
242 #ifdef LDAP_DEBUG
243                 if ( ldap_debug )
244                         print_error( &dse );    /* prints and then frees */
245                 else
246 #endif
247                         ds_error_free( &dse );
248
249                 dsaconn->c_ad = -1;
250
251                 return( err );
252         }
253         bind_arg_free( &br );
254
255         Debug( LDAP_DEBUG_TRACE, "dap_bind successful\n", 0, 0, 0 );
256
257 #ifdef KERBEROS
258 /* XXX why doesn't this work??
259         if ( dsaconn->c_method == LDAP_AUTH_KRBV42 &&
260             kerberos_check_mutual( &br, nonce ) != 0 ) {
261                 Debug( LDAP_DEBUG_ANY, "Mutual authentication failed\n", 0, 0,
262                     0 );
263                 return( LDAP_INVALID_CREDENTIALS );
264         }
265 */
266 #endif
267
268         *bound = 1;
269
270         return( LDAP_SUCCESS );
271 }