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