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