]> git.sur5r.net Git - openldap/blob - servers/slapd/bind.c
d980c36bb083957c0d27a185acfbbd1d698a1da0
[openldap] / servers / slapd / bind.c
1 /* bind.c - decode an ldap bind operation and pass it to a backend db */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 /*
9  * Copyright (c) 1995 Regents of the University of Michigan.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms are permitted
13  * provided that this notice is preserved and that due credit is given
14  * to the University of Michigan at Ann Arbor. The name of the University
15  * may not be used to endorse or promote products derived from this
16  * software without specific prior written permission. This software
17  * is provided ``as is'' without express or implied warranty.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/string.h>
25 #include <ac/socket.h>
26
27 #include "ldap_pvt.h"
28 #include "slap.h"
29
30 int
31 do_bind(
32     Connection  *conn,
33     Operation   *op
34 )
35 {
36         BerElement *ber = op->o_ber;
37         ber_int_t version;
38         ber_tag_t method;
39         char *mech = NULL;
40         struct berval dn = { 0, NULL };
41         struct berval *pdn = NULL;
42         struct berval *ndn = NULL;
43         ber_tag_t tag;
44         int     rc = LDAP_SUCCESS;
45         const char *text;
46         struct berval cred = { 0, NULL };
47         Backend *be;
48
49 #ifdef NEW_LOGGING
50         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
51                 "do_bind: conn %d\n", conn->c_connid ));
52 #else
53         Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
54 #endif
55
56         /*
57          * Force to connection to "anonymous" until bind succeeds.
58          */
59         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
60         connection2anonymous( conn );
61         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
62
63         if ( op->o_dn.bv_val != NULL ) {
64                 free( op->o_dn.bv_val );
65                 op->o_dn.bv_val = ch_strdup( "" );
66                 op->o_dn.bv_len = 0;
67         }
68
69         if ( op->o_ndn.bv_val != NULL ) {
70                 free( op->o_ndn.bv_val );
71                 op->o_ndn.bv_val = ch_strdup( "" );
72                 op->o_ndn.bv_len = 0;
73         }
74
75         /*
76          * Parse the bind request.  It looks like this:
77          *
78          *      BindRequest ::= SEQUENCE {
79          *              version         INTEGER,                 -- version
80          *              name            DistinguishedName,       -- dn
81          *              authentication  CHOICE {
82          *                      simple          [0] OCTET STRING -- passwd
83          *                      krbv42ldap      [1] OCTET STRING
84          *                      krbv42dsa       [2] OCTET STRING
85          *                      SASL            [3] SaslCredentials
86          *              }
87          *      }
88          *
89          *      SaslCredentials ::= SEQUENCE {
90      *          mechanism           LDAPString,
91      *          credentials         OCTET STRING OPTIONAL
92          *      }
93          */
94
95         tag = ber_scanf( ber, "{iot" /*}*/, &version, &dn, &method );
96
97         if ( tag == LBER_ERROR ) {
98 #ifdef NEW_LOGGING
99                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
100                         "do_bind: conn %d  ber_scanf failed\n", conn->c_connid ));
101 #else
102                 Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
103 #endif
104                 send_ldap_disconnect( conn, op,
105                         LDAP_PROTOCOL_ERROR, "decoding error" );
106                 rc = -1;
107                 goto cleanup;
108         }
109
110         op->o_protocol = version;
111
112         if( method != LDAP_AUTH_SASL ) {
113                 tag = ber_scanf( ber, /*{*/ "o}", &cred );
114
115         } else {
116                 tag = ber_scanf( ber, "{a" /*}*/, &mech );
117
118                 if ( tag != LBER_ERROR ) {
119                         ber_len_t len;
120                         tag = ber_peek_tag( ber, &len );
121
122                         if ( tag == LDAP_TAG_LDAPCRED ) { 
123                                 tag = ber_scanf( ber, "o", &cred );
124                         } else {
125                                 tag = LDAP_TAG_LDAPCRED;
126                                 cred.bv_val = NULL;
127                                 cred.bv_len = 0;
128                         }
129
130                         if ( tag != LBER_ERROR ) {
131                                 tag = ber_scanf( ber, /*{{*/ "}}" );
132                         }
133                 }
134         }
135
136         if ( tag == LBER_ERROR ) {
137                 send_ldap_disconnect( conn, op,
138                         LDAP_PROTOCOL_ERROR,
139                 "decoding error" );
140                 rc = SLAPD_DISCONNECT;
141                 goto cleanup;
142         }
143
144         if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
145 #ifdef NEW_LOGGING
146                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
147                         "do_bind: conn %d  get_ctrls failed\n", conn->c_connid ));
148 #else
149                 Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
150 #endif
151                 goto cleanup;
152         } 
153
154         rc = dnPretty( NULL, &dn, &pdn );
155         if ( rc != LDAP_SUCCESS ) {
156 #ifdef NEW_LOGGING
157                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
158                         "do_bind: conn %d  invalid dn (%s)\n",
159                         conn->c_connid, dn.bv_val ));
160 #else
161                 Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n",
162                         dn.bv_val, 0, 0 );
163 #endif
164                 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
165                     "invalid DN", NULL, NULL );
166                 goto cleanup;
167         }
168
169         rc = dnNormalize( NULL, &dn, &ndn );
170         if ( rc != LDAP_SUCCESS ) {
171 #ifdef NEW_LOGGING
172                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
173                         "do_bind: conn %d  invalid dn (%s)\n",
174                         conn->c_connid, dn.bv_val ));
175 #else
176                 Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n",
177                         dn.bv_val, 0, 0 );
178 #endif
179                 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
180                     "invalid DN", NULL, NULL );
181                 goto cleanup;
182         }
183
184         if( method == LDAP_AUTH_SASL ) {
185 #ifdef NEW_LOGGING
186                 LDAP_LOG(( "operation",  LDAP_LEVEL_DETAIL1,
187                         "do_sasl_bind: conn %d  dn (%s) mech %s\n", conn->c_connid,
188                         pdn->bv_val, mech ));
189 #else
190                 Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
191                         pdn->bv_val, mech, NULL );
192 #endif
193
194         } else {
195 #ifdef NEW_LOGGING
196                 LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
197                         "do_bind: conn %d  version=%ld dn=\"%s\" method=%ld\n",
198                         conn->c_connid, (unsigned long) version,
199                         pdn->bv_val, (unsigned long)method ));
200 #else
201                 Debug( LDAP_DEBUG_TRACE,
202                         "do_bind: version=%ld dn=\"%s\" method=%ld\n",
203                         (unsigned long) version,
204                         pdn->bv_val, (unsigned long) method );
205 #endif
206         }
207
208         Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d BIND dn=\"%s\" method=%ld\n",
209             op->o_connid, op->o_opid, pdn->bv_val, (unsigned long) method, 0 );
210
211         if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
212 #ifdef NEW_LOGGING
213                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
214                         "do_bind: conn %d  unknown version = %ld\n",
215                         conn->c_connid, (unsigned long)version ));
216 #else
217                 Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
218                         (unsigned long) version, 0, 0 );
219 #endif
220                 send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
221                         NULL, "requested protocol version not supported", NULL, NULL );
222                 goto cleanup;
223
224         } else if (!( global_allows & SLAP_ALLOW_BIND_V2 ) &&
225                 version < LDAP_VERSION3 )
226         {
227                 send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
228                         NULL, "requested protocol version not allowed", NULL, NULL );
229                 goto cleanup;
230         }
231
232         /* we set connection version regardless of whether bind succeeds
233          * or not.
234          */
235         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
236         conn->c_protocol = version;
237         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
238
239         if ( method == LDAP_AUTH_SASL ) {
240                 char *edn;
241                 slap_ssf_t ssf = 0;
242
243                 if ( version < LDAP_VERSION3 ) {
244 #ifdef NEW_LOGGING
245                         LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
246                                 "do_bind: conn %d  sasl with LDAPv%ld\n",
247                                 conn->c_connid, (unsigned long)version ));
248 #else
249                         Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
250                                 (unsigned long) version, 0, 0 );
251 #endif
252                         send_ldap_disconnect( conn, op,
253                                 LDAP_PROTOCOL_ERROR, "SASL bind requires LDAPv3" );
254                         rc = SLAPD_DISCONNECT;
255                         goto cleanup;
256                 }
257
258                 if( mech == NULL || *mech == '\0' ) {
259 #ifdef NEW_LOGGING
260                         LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
261                                    "do_bind: conn %d  no SASL mechanism provided\n",
262                                    conn->c_connid ));
263 #else
264                         Debug( LDAP_DEBUG_ANY,
265                                 "do_bind: no sasl mechanism provided\n",
266                                 0, 0, 0 );
267 #endif
268                         send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
269                                 NULL, "no SASL mechanism provided", NULL, NULL );
270                         goto cleanup;
271                 }
272
273                 /* check restrictions */
274                 rc = backend_check_restrictions( NULL, conn, op, mech, &text );
275                 if( rc != LDAP_SUCCESS ) {
276                         send_ldap_result( conn, op, rc,
277                                 NULL, text, NULL, NULL );
278                         goto cleanup;
279                 }
280
281                 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
282                 if ( conn->c_sasl_bind_in_progress ) {
283                         if((strcmp(conn->c_sasl_bind_mech, mech) != 0)) {
284                                 /* mechanism changed between bind steps */
285                                 slap_sasl_reset(conn);
286                         }
287                 } else {
288                         conn->c_sasl_bind_mech = mech;
289                         mech = NULL;
290                 }
291                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
292
293                 edn = NULL;
294                 rc = slap_sasl_bind( conn, op,
295                         pdn->bv_val, ndn->bv_val,
296                         &cred, &edn, &ssf );
297
298                 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
299                 if( rc == LDAP_SUCCESS ) {
300                         conn->c_dn.bv_val = edn;
301                         if( edn != NULL ) {
302                                 struct berval *cndn;
303                                 conn->c_dn.bv_len = strlen( edn );
304                                 dnNormalize( NULL, &conn->c_dn, &cndn );
305                                 conn->c_ndn = *cndn;
306                                 free( cndn );
307                         }
308                         conn->c_authmech = conn->c_sasl_bind_mech;
309                         conn->c_sasl_bind_mech = NULL;
310                         conn->c_sasl_bind_in_progress = 0;
311
312                         conn->c_sasl_ssf = ssf;
313                         if( ssf > conn->c_ssf ) {
314                                 conn->c_ssf = ssf;
315                         }
316
317                         if( conn->c_dn.bv_len != 0 ) {
318                                 ber_len_t max = sockbuf_max_incoming;
319                                 ber_sockbuf_ctrl( conn->c_sb,
320                                         LBER_SB_OPT_SET_MAX_INCOMING, &max );
321                         }
322
323                 } else if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) {
324                         conn->c_sasl_bind_in_progress = 1;
325
326                 } else {
327                         if ( conn->c_sasl_bind_mech ) {
328                                 free( conn->c_sasl_bind_mech );
329                                 conn->c_sasl_bind_mech = NULL;
330                         }
331                         conn->c_sasl_bind_in_progress = 0;
332                 }
333                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
334
335                 goto cleanup;
336
337         } else {
338                 /* Not SASL, cancel any in-progress bind */
339                 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
340
341                 if ( conn->c_sasl_bind_mech != NULL ) {
342                         free(conn->c_sasl_bind_mech);
343                         conn->c_sasl_bind_mech = NULL;
344                 }
345                 conn->c_sasl_bind_in_progress = 0;
346
347                 slap_sasl_reset( conn );
348                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
349         }
350
351         if ( method == LDAP_AUTH_SIMPLE ) {
352                 /* accept "anonymous" binds */
353                 if ( cred.bv_len == 0 || ndn->bv_len == 0 ) {
354                         rc = LDAP_SUCCESS;
355                         text = NULL;
356
357                         if( cred.bv_len &&
358                                 !( global_allows & SLAP_ALLOW_BIND_ANON_CRED ))
359                         {
360                                 /* cred is not empty, disallow */
361                                 rc = LDAP_INVALID_CREDENTIALS;
362
363                         } else if ( ndn->bv_len &&
364                                 !( global_allows & SLAP_ALLOW_BIND_ANON_DN ))
365                         {
366                                 /* DN is not empty, disallow */
367                                 rc = LDAP_UNWILLING_TO_PERFORM;
368                                 text = "unwilling to allow anonymous bind with non-empty DN";
369
370                         } else if ( global_disallows & SLAP_DISALLOW_BIND_ANON ) {
371                                 /* disallow */
372                                 rc = LDAP_INAPPROPRIATE_AUTH;
373                                 text = "anonymous bind disallowed";
374
375                         } else {
376                                 rc = backend_check_restrictions( NULL, conn, op, mech, &text );
377                         }
378
379                         /*
380                          * we already forced connection to "anonymous",
381                          * just need to send success
382                          */
383                         send_ldap_result( conn, op, rc,
384                                 NULL, text, NULL, NULL );
385 #ifdef NEW_LOGGING
386                         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
387                                    "do_bind: conn %d  v%d anonymous bind\n",
388                                    conn->c_connid, version ));
389 #else
390                         Debug( LDAP_DEBUG_TRACE, "do_bind: v%d anonymous bind\n",
391                                 version, 0, 0 );
392 #endif
393                         goto cleanup;
394
395                 } else if ( global_disallows & SLAP_DISALLOW_BIND_SIMPLE ) {
396                         /* disallow simple authentication */
397                         rc = LDAP_UNWILLING_TO_PERFORM;
398                         text = "unwilling to perform simple authentication";
399
400                         send_ldap_result( conn, op, rc,
401                                 NULL, text, NULL, NULL );
402 #ifdef NEW_LOGGING
403                         LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
404                                    "do_bind: conn %d  v%d simple bind(%s) disallowed\n",
405                                    conn->c_connid, version, ndn ));
406 #else
407                         Debug( LDAP_DEBUG_TRACE,
408                                 "do_bind: v%d simple bind(%s) disallowed\n",
409                                 version, ndn, 0 );
410 #endif
411                         goto cleanup;
412                 }
413
414 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
415         } else if ( method == LDAP_AUTH_KRBV41 || method == LDAP_AUTH_KRBV42 ) {
416                 if ( global_disallows & SLAP_DISALLOW_BIND_KRBV4 ) {
417                         /* disallow simple authentication */
418                         rc = LDAP_UNWILLING_TO_PERFORM;
419                         text = "unwilling to perform Kerberos V4 bind";
420
421                         send_ldap_result( conn, op, rc,
422                                 NULL, text, NULL, NULL );
423 #ifdef NEW_LOGGING
424                         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
425                                    "do_bind: conn %d  v%d Kerberos V4 bind\n",
426                                    conn->c_connid, version ));
427 #else
428                         Debug( LDAP_DEBUG_TRACE, "do_bind: v%d Kerberos V4 bind\n",
429                                 version, 0, 0 );
430 #endif
431                         goto cleanup;
432                 }
433 #endif
434
435         } else {
436                 rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
437                 text = "unknown authentication method";
438
439                 send_ldap_result( conn, op, rc,
440                         NULL, text, NULL, NULL );
441 #ifdef NEW_LOGGING
442                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
443                            "do_bind: conn %ld  v%d unknown authentication method (%ld)\n",
444                            conn->c_connid, version, method ));
445 #else
446                 Debug( LDAP_DEBUG_TRACE,
447                         "do_bind: v%d unknown authentication method (%ld)\n",
448                         version, method, 0 );
449 #endif
450                 goto cleanup;
451         }
452
453         /*
454          * We could be serving multiple database backends.  Select the
455          * appropriate one, or send a referral to our "referral server"
456          * if we don't hold it.
457          */
458
459         if ( (be = select_backend( ndn, 0, 0 )) == NULL ) {
460                 if ( default_referral ) {
461                         struct berval **ref = referral_rewrite( default_referral,
462                                 NULL, pdn, LDAP_SCOPE_DEFAULT );
463
464                         send_ldap_result( conn, op, rc = LDAP_REFERRAL,
465                                 NULL, NULL, ref ? ref : default_referral, NULL );
466
467                         ber_bvecfree( ref );
468
469                 } else {
470                         /* noSuchObject is not allowed to be returned by bind */
471                         send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
472                                 NULL, NULL, NULL, NULL );
473                 }
474
475                 goto cleanup;
476         }
477
478         /* check restrictions */
479         rc = backend_check_restrictions( be, conn, op, NULL, &text );
480         if( rc != LDAP_SUCCESS ) {
481                 send_ldap_result( conn, op, rc,
482                         NULL, text, NULL, NULL );
483                 goto cleanup;
484         }
485
486         conn->c_authz_backend = be;
487
488         if ( be->be_bind ) {
489                 int ret;
490                 /* alias suffix */
491                 struct berval edn = { 0, NULL };
492
493                 /* deref suffix alias if appropriate */
494                 suffix_alias( be, ndn );
495
496                 ret = (*be->be_bind)( be, conn, op,
497                         pdn, ndn, method, &cred, &edn );
498
499                 if ( ret == 0 ) {
500                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
501
502                         if(edn.bv_len) {
503                                 conn->c_dn = edn;
504                         } else {
505                                 conn->c_dn.bv_val = ch_strdup( pdn->bv_val );
506                                 conn->c_dn.bv_len = pdn->bv_len;
507                         }
508                         conn->c_cdn = pdn->bv_val;
509                         pdn->bv_val = NULL;
510                         pdn->bv_len = 0;
511
512                         conn->c_ndn = *ndn;
513                         ndn->bv_val = NULL;
514                         ndn->bv_len = 0;
515
516                         if( conn->c_dn.bv_len != 0 ) {
517                                 ber_len_t max = sockbuf_max_incoming;
518                                 ber_sockbuf_ctrl( conn->c_sb,
519                                         LBER_SB_OPT_SET_MAX_INCOMING, &max );
520                         }
521
522 #ifdef NEW_LOGGING
523                         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
524                                 "do_bind: conn %d  v%d bind: \"%s\" to \"%s\" \n",
525                                 conn->c_connid, version, conn->c_cdn, conn->c_dn.bv_val ));
526 #else
527                         Debug( LDAP_DEBUG_TRACE,
528                                 "do_bind: v%d bind: \"%s\" to \"%s\"\n",
529                                 version, conn->c_cdn, conn->c_dn.bv_val );
530 #endif
531
532                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
533
534                         /* send this here to avoid a race condition */
535                         send_ldap_result( conn, op, LDAP_SUCCESS,
536                                 NULL, NULL, NULL, NULL );
537
538                 } else if (edn.bv_val != NULL) {
539                         free( edn.bv_val );
540                 }
541
542         } else {
543                 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
544                         NULL, "operation not supported within namingContext",
545                         NULL, NULL );
546         }
547
548 cleanup:
549         free( dn.bv_val );
550         if( pdn != NULL ) {
551                 ber_bvfree( pdn );
552         }
553         if( ndn != NULL ) {
554                 ber_bvfree( ndn );
555         }
556         if ( mech != NULL ) {
557                 free( mech );
558         }
559         if ( cred.bv_val != NULL ) {
560                 free( cred.bv_val );
561         }
562
563         return rc;
564 }