1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2021 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 
16 #include "portable.h"
17 
18 #include <ac/socket.h>
19 #include <ac/errno.h>
20 #include <ac/string.h>
21 #include <ac/time.h>
22 #include <ac/unistd.h>
23 
24 #include "lload.h"
25 
26 #include "lutil.h"
27 #include "lutil_ldap.h"
28 
29 #ifdef HAVE_CYRUS_SASL
30 static const sasl_callback_t client_callbacks[] = {
31 #ifdef SASL_CB_GETREALM
32         { SASL_CB_GETREALM, NULL, NULL },
33 #endif
34         { SASL_CB_USER, NULL, NULL },
35         { SASL_CB_AUTHNAME, NULL, NULL },
36         { SASL_CB_PASS, NULL, NULL },
37         { SASL_CB_LIST_END, NULL, NULL }
38 };
39 #endif /* HAVE_CYRUS_SASL */
40 
41 static void upstream_unlink( LloadConnection *upstream );
42 
43 int
lload_upstream_entry_cmp(const void * l,const void * r)44 lload_upstream_entry_cmp( const void *l, const void *r )
45 {
46     return SLAP_PTRCMP( l, r );
47 }
48 
49 static void
linked_upstream_lost(LloadConnection * client)50 linked_upstream_lost( LloadConnection *client )
51 {
52     int gentle = 1;
53 
54     CONNECTION_LOCK(client);
55     assert( client->c_restricted >= LLOAD_OP_RESTRICTED_UPSTREAM );
56     assert( client->c_linked_upstream );
57 
58     client->c_restricted = LLOAD_OP_NOT_RESTRICTED;
59     client->c_linked_upstream = NULL;
60     CONNECTION_UNLOCK(client);
61     lload_connection_close( client, &gentle );
62 }
63 
64 int
forward_response(LloadConnection * client,LloadOperation * op,BerElement * ber)65 forward_response( LloadConnection *client, LloadOperation *op, BerElement *ber )
66 {
67     BerElement *output;
68     BerValue response, controls = BER_BVNULL;
69     ber_int_t msgid;
70     ber_tag_t tag, response_tag;
71     ber_len_t len;
72 
73     CONNECTION_LOCK(client);
74     if ( op->o_client_msgid ) {
75         msgid = op->o_client_msgid;
76     } else {
77         assert( op->o_pin_id );
78         msgid = op->o_saved_msgid;
79         op->o_saved_msgid = 0;
80     }
81     CONNECTION_UNLOCK(client);
82 
83     response_tag = ber_skip_element( ber, &response );
84 
85     tag = ber_peek_tag( ber, &len );
86     if ( tag == LDAP_TAG_CONTROLS ) {
87         ber_skip_element( ber, &controls );
88     }
89 
90     Debug( LDAP_DEBUG_TRACE, "forward_response: "
91             "%s to client connid=%lu request msgid=%d\n",
92             lload_msgtype2str( response_tag ), op->o_client_connid, msgid );
93 
94     checked_lock( &client->c_io_mutex );
95     output = client->c_pendingber;
96     if ( output == NULL && (output = ber_alloc()) == NULL ) {
97         ber_free( ber, 1 );
98         checked_unlock( &client->c_io_mutex );
99         return -1;
100     }
101     client->c_pendingber = output;
102 
103     ber_printf( output, "t{titOtO}", LDAP_TAG_MESSAGE,
104             LDAP_TAG_MSGID, msgid,
105             response_tag, &response,
106             LDAP_TAG_CONTROLS, BER_BV_OPTIONAL( &controls ) );
107 
108     checked_unlock( &client->c_io_mutex );
109 
110     ber_free( ber, 1 );
111     connection_write_cb( -1, 0, client );
112     return 0;
113 }
114 
115 int
forward_final_response(LloadConnection * client,LloadOperation * op,BerElement * ber)116 forward_final_response(
117         LloadConnection *client,
118         LloadOperation *op,
119         BerElement *ber )
120 {
121     int rc;
122 
123     Debug( LDAP_DEBUG_STATS, "forward_final_response: "
124             "connid=%lu msgid=%d finishing up with a request for "
125             "client connid=%lu\n",
126             op->o_upstream_connid, op->o_upstream_msgid, op->o_client_connid );
127 
128     rc = forward_response( client, op, ber );
129 
130     op->o_res = LLOAD_OP_COMPLETED;
131     if ( !op->o_pin_id ) {
132         operation_unlink( op );
133     }
134 
135     return rc;
136 }
137 
138 static int
handle_unsolicited(LloadConnection * c,BerElement * ber)139 handle_unsolicited( LloadConnection *c, BerElement *ber )
140 {
141     CONNECTION_ASSERT_LOCKED(c);
142     if ( c->c_state != LLOAD_C_PREPARING ) {
143         c->c_state = LLOAD_C_CLOSING;
144     }
145 
146     Debug( LDAP_DEBUG_STATS, "handle_unsolicited: "
147             "teardown for upstream connection connid=%lu\n",
148             c->c_connid );
149 
150     CONNECTION_DESTROY(c);
151     ber_free( ber, 1 );
152 
153     return -1;
154 }
155 
156 /*
157  * Pull c->c_currentber from the connection and try to look up the operation on
158  * the upstream.
159  *
160  * If it's a notice of disconnection, we won't find it and need to tear down
161  * the connection and tell the clients, if we can't find the operation, ignore
162  * the message (either client already disconnected/abandoned it or the upstream
163  * is pulling our leg).
164  *
165  * Some responses need special handling:
166  * - Bind response
167  * - VC response where the client requested a Bind (both need to update the
168  *   client's bind status)
169  * - search entries/referrals and intermediate responses (will not trigger
170  *   operation to be removed)
171  *
172  * If the worker pool is overloaded, we might be called directly from
173  * the read callback, at that point, the connection hasn't been muted.
174  *
175  * TODO: when the client already has data pending on write, we should mute the
176  * upstream.
177  * - should record the BerElement on the Op and the Op on the client
178  *
179  * The following hold on entering any of the handlers:
180  * - op->o_upstream_refcnt > 0
181  * - op->o_upstream->c_refcnt > 0
182  * - op->o_client->c_refcnt > 0
183  */
184 static int
handle_one_response(LloadConnection * c)185 handle_one_response( LloadConnection *c )
186 {
187     BerElement *ber;
188     LloadOperation *op = NULL, needle = { .o_upstream_connid = c->c_connid };
189     LloadOperationHandler handler = NULL;
190     ber_tag_t tag;
191     ber_len_t len;
192     int rc = LDAP_SUCCESS;
193 
194     ber = c->c_currentber;
195     c->c_currentber = NULL;
196 
197     tag = ber_get_int( ber, &needle.o_upstream_msgid );
198     if ( tag != LDAP_TAG_MSGID ) {
199         rc = -1;
200         ber_free( ber, 1 );
201         goto fail;
202     }
203 
204     CONNECTION_LOCK(c);
205     if ( needle.o_upstream_msgid == 0 ) {
206         return handle_unsolicited( c, ber );
207     } else if ( !( op = ldap_tavl_find(
208                            c->c_ops, &needle, operation_upstream_cmp ) ) ) {
209         /* Already abandoned, do nothing */
210         CONNECTION_UNLOCK(c);
211         ber_free( ber, 1 );
212         return rc;
213         /*
214     } else if ( op->o_response_pending ) {
215         c->c_pendingop = op;
216         event_del( c->c_read_event );
217     */
218     } else {
219         CONNECTION_UNLOCK(c);
220         /*
221         op->o_response_pending = ber;
222         */
223 
224         tag = ber_peek_tag( ber, &len );
225         switch ( tag ) {
226             case LDAP_RES_SEARCH_ENTRY:
227             case LDAP_RES_SEARCH_REFERENCE:
228             case LDAP_RES_INTERMEDIATE:
229                 handler = forward_response;
230                 break;
231             case LDAP_RES_BIND:
232                 handler = handle_bind_response;
233                 break;
234             case LDAP_RES_EXTENDED:
235                 if ( op->o_tag == LDAP_REQ_BIND ) {
236 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
237                     if ( lload_features & LLOAD_FEATURE_VC ) {
238                         handler = handle_vc_bind_response;
239                     } else
240 #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
241                     {
242                         handler = handle_whoami_response;
243                     }
244                 }
245                 break;
246         }
247         if ( !handler ) {
248             handler = forward_final_response;
249         }
250     }
251     if ( op ) {
252         struct timeval tv, tvdiff;
253         uintptr_t diff;
254 
255         gettimeofday( &tv, NULL );
256         if ( !timerisset( &op->o_last_response ) ) {
257             LloadBackend *b = c->c_backend;
258 
259             timersub( &tv, &op->o_start, &tvdiff );
260             diff = 1000000 * tvdiff.tv_sec + tvdiff.tv_usec;
261 
262             __atomic_add_fetch( &b->b_operation_count, 1, __ATOMIC_RELAXED );
263             __atomic_add_fetch( &b->b_operation_time, diff, __ATOMIC_RELAXED );
264         }
265         op->o_last_response = tv;
266 
267         Debug( LDAP_DEBUG_STATS2, "handle_one_response: "
268                 "upstream connid=%lu, processing response for "
269                 "client connid=%lu, msgid=%d\n",
270                 c->c_connid, op->o_client_connid, op->o_client_msgid );
271     } else {
272         tag = ber_peek_tag( ber, &len );
273         Debug( LDAP_DEBUG_STATS2, "handle_one_response: "
274                 "upstream connid=%lu, %s, msgid=%d not for a pending "
275                 "operation\n",
276                 c->c_connid, lload_msgtype2str( tag ),
277                 needle.o_upstream_msgid );
278     }
279 
280     if ( handler ) {
281         LloadConnection *client;
282 
283         checked_lock( &op->o_link_mutex );
284         client = op->o_client;
285         checked_unlock( &op->o_link_mutex );
286         if ( client && IS_ALIVE( client, c_live ) ) {
287             rc = handler( client, op, ber );
288         } else {
289             ber_free( ber, 1 );
290         }
291     } else {
292         assert(0);
293         ber_free( ber, 1 );
294     }
295 
296 fail:
297     if ( rc ) {
298         Debug( LDAP_DEBUG_STATS, "handle_one_response: "
299                 "error on processing a response (%s) on upstream connection "
300                 "connid=%ld, tag=%lx\n",
301                 lload_msgtype2str( tag ), c->c_connid, tag );
302         CONNECTION_LOCK_DESTROY(c);
303     }
304     return rc;
305 }
306 
307 #ifdef HAVE_CYRUS_SASL
308 static int
sasl_bind_step(LloadConnection * c,BerValue * scred,BerValue * ccred)309 sasl_bind_step( LloadConnection *c, BerValue *scred, BerValue *ccred )
310 {
311     LloadBackend *b = c->c_backend;
312     sasl_conn_t *ctx = c->c_sasl_authctx;
313     sasl_interact_t *prompts = NULL;
314     unsigned credlen;
315     int rc = -1;
316 
317     if ( !ctx ) {
318         const char *mech = NULL;
319 #ifdef HAVE_TLS
320         void *ssl;
321 #endif /* HAVE_TLS */
322 
323         if ( sasl_client_new( "ldap", b->b_host, NULL, NULL, client_callbacks,
324                      0, &ctx ) != SASL_OK ) {
325             goto done;
326         }
327         c->c_sasl_authctx = ctx;
328 
329         assert( c->c_sasl_defaults == NULL );
330         c->c_sasl_defaults =
331                 lutil_sasl_defaults( NULL, bindconf.sb_saslmech.bv_val,
332                         bindconf.sb_realm.bv_val, bindconf.sb_authcId.bv_val,
333                         bindconf.sb_cred.bv_val, bindconf.sb_authzId.bv_val );
334 
335 #ifdef HAVE_TLS
336         /* Check for TLS */
337         ssl = ldap_pvt_tls_sb_ctx( c->c_sb );
338         if ( ssl ) {
339             struct berval authid = BER_BVNULL;
340             ber_len_t ssf;
341 
342             ssf = ldap_pvt_tls_get_strength( ssl );
343             (void)ldap_pvt_tls_get_my_dn( ssl, &authid, NULL, 0 );
344 
345             sasl_setprop( ctx, SASL_SSF_EXTERNAL, &ssf );
346             sasl_setprop( ctx, SASL_AUTH_EXTERNAL, authid.bv_val );
347             ch_free( authid.bv_val );
348 #ifdef SASL_CHANNEL_BINDING /* 2.1.25+ */
349             {
350                 char cbinding[64];
351                 struct berval cbv = { sizeof(cbinding), cbinding };
352                 if ( ldap_pvt_tls_get_unique( ssl, &cbv, 0 ) ) {
353                     sasl_channel_binding_t *cb =
354                             ch_malloc( sizeof(*cb) + cbv.bv_len );
355                     void *cb_data;
356                     cb->name = "ldap";
357                     cb->critical = 0;
358                     cb->len = cbv.bv_len;
359                     cb->data = cb_data = cb + 1;
360                     memcpy( cb_data, cbv.bv_val, cbv.bv_len );
361                     sasl_setprop( ctx, SASL_CHANNEL_BINDING, cb );
362                     c->c_sasl_cbinding = cb;
363                 }
364             }
365 #endif
366         }
367 #endif
368 
369 #if !defined(_WIN32)
370         /* Check for local */
371         if ( b->b_proto == LDAP_PROTO_IPC ) {
372             char authid[sizeof( "gidNumber=4294967295+uidNumber=4294967295,"
373                                 "cn=peercred,cn=external,cn=auth" )];
374             int ssf = LDAP_PVT_SASL_LOCAL_SSF;
375 
376             sprintf( authid,
377                     "gidNumber=%u+uidNumber=%u,"
378                     "cn=peercred,cn=external,cn=auth",
379                     getegid(), geteuid() );
380             sasl_setprop( ctx, SASL_SSF_EXTERNAL, &ssf );
381             sasl_setprop( ctx, SASL_AUTH_EXTERNAL, authid );
382         }
383 #endif
384 
385         do {
386             rc = sasl_client_start( ctx, bindconf.sb_saslmech.bv_val,
387                     &prompts,
388                     (const char **)&ccred->bv_val, &credlen,
389                     &mech );
390 
391             if ( rc == SASL_INTERACT ) {
392                 if ( lutil_sasl_interact( NULL, LDAP_SASL_QUIET,
393                              c->c_sasl_defaults, prompts ) ) {
394                     break;
395                 }
396             }
397         } while ( rc == SASL_INTERACT );
398 
399         ber_str2bv( mech, 0, 0, &c->c_sasl_bind_mech );
400     } else {
401         assert( c->c_sasl_defaults );
402 
403         do {
404             rc = sasl_client_step( ctx,
405                     (scred == NULL) ? NULL : scred->bv_val,
406                     (scred == NULL) ? 0 : scred->bv_len,
407                     &prompts,
408                     (const char **)&ccred->bv_val, &credlen);
409 
410             if ( rc == SASL_INTERACT ) {
411                 if ( lutil_sasl_interact( NULL, LDAP_SASL_QUIET,
412                              c->c_sasl_defaults, prompts ) ) {
413                     break;
414                 }
415             }
416         } while ( rc == SASL_INTERACT );
417     }
418 
419     if ( rc == SASL_OK ) {
420         sasl_ssf_t *ssf;
421         rc = sasl_getprop( ctx, SASL_SSF, (const void **)(char *)&ssf );
422         if ( rc == SASL_OK && ssf && *ssf ) {
423             Debug( LDAP_DEBUG_CONNS, "sasl_bind_step: "
424                     "connid=%lu mech=%s setting up a new SASL security layer\n",
425                     c->c_connid, c->c_sasl_bind_mech.bv_val );
426             ldap_pvt_sasl_install( c->c_sb, ctx );
427         }
428     }
429     ccred->bv_len = credlen;
430 
431 done:
432     Debug( LDAP_DEBUG_TRACE, "sasl_bind_step: "
433             "connid=%lu next step for SASL bind mech=%s rc=%d\n",
434             c->c_connid, c->c_sasl_bind_mech.bv_val, rc );
435     return rc;
436 }
437 #endif /* HAVE_CYRUS_SASL */
438 
439 int
upstream_bind_cb(LloadConnection * c)440 upstream_bind_cb( LloadConnection *c )
441 {
442     BerElement *ber = c->c_currentber;
443     LloadBackend *b = c->c_backend;
444     BerValue matcheddn, message;
445     ber_tag_t tag;
446     ber_int_t msgid, result;
447 
448     c->c_currentber = NULL;
449 
450     if ( ber_scanf( ber, "it", &msgid, &tag ) == LBER_ERROR ) {
451         Debug( LDAP_DEBUG_ANY, "upstream_bind_cb: "
452                 "protocol violation from server\n" );
453         goto fail;
454     }
455 
456     if ( msgid != ( c->c_next_msgid - 1 ) || tag != LDAP_RES_BIND ) {
457         Debug( LDAP_DEBUG_ANY, "upstream_bind_cb: "
458                 "unexpected %s from server, msgid=%d\n",
459                 lload_msgtype2str( tag ), msgid );
460         goto fail;
461     }
462 
463     if ( ber_scanf( ber, "{emm" /* "}" */, &result, &matcheddn, &message ) ==
464                  LBER_ERROR ) {
465         Debug( LDAP_DEBUG_ANY, "upstream_bind_cb: "
466                 "response does not conform with a bind response\n" );
467         goto fail;
468     }
469 
470     switch ( result ) {
471         case LDAP_SUCCESS:
472 #ifdef HAVE_CYRUS_SASL
473         case LDAP_SASL_BIND_IN_PROGRESS:
474             if ( !BER_BVISNULL( &c->c_sasl_bind_mech ) ) {
475                 BerValue scred = BER_BVNULL, ccred;
476                 ber_len_t len;
477                 int rc;
478 
479                 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SASL_RES_CREDS &&
480                         ber_scanf( ber, "m", &scred ) == LBER_ERROR ) {
481                     Debug( LDAP_DEBUG_ANY, "upstream_bind_cb: "
482                             "sasl bind response malformed\n" );
483                     goto fail;
484                 }
485 
486                 rc = sasl_bind_step( c, &scred, &ccred );
487                 if ( rc != SASL_OK &&
488                         ( rc != SASL_CONTINUE || result == LDAP_SUCCESS ) ) {
489                     goto fail;
490                 }
491 
492                 if ( result == LDAP_SASL_BIND_IN_PROGRESS ) {
493                     BerElement *outber;
494 
495                     checked_lock( &c->c_io_mutex );
496                     outber = c->c_pendingber;
497                     if ( outber == NULL && (outber = ber_alloc()) == NULL ) {
498                         checked_unlock( &c->c_io_mutex );
499                         goto fail;
500                     }
501                     c->c_pendingber = outber;
502 
503                     msgid = c->c_next_msgid++;
504                     ber_printf( outber, "{it{iOt{OON}N}}",
505                             msgid, LDAP_REQ_BIND, LDAP_VERSION3,
506                             &bindconf.sb_binddn, LDAP_AUTH_SASL,
507                             &c->c_sasl_bind_mech, BER_BV_OPTIONAL( &ccred ) );
508                     checked_unlock( &c->c_io_mutex );
509 
510                     connection_write_cb( -1, 0, c );
511 
512                     if ( rc == SASL_OK ) {
513                         BER_BVZERO( &c->c_sasl_bind_mech );
514                     }
515                     break;
516                 }
517             }
518             if ( result == LDAP_SASL_BIND_IN_PROGRESS ) {
519                 goto fail;
520             }
521 #endif /* HAVE_CYRUS_SASL */
522             CONNECTION_LOCK(c);
523             c->c_pdu_cb = handle_one_response;
524             c->c_state = LLOAD_C_READY;
525             c->c_type = LLOAD_C_OPEN;
526             c->c_read_timeout = NULL;
527             Debug( LDAP_DEBUG_CONNS, "upstream_bind_cb: "
528                     "connection connid=%lu for backend server '%s' is ready "
529                     "for use\n",
530                     c->c_connid, b->b_name.bv_val );
531             CONNECTION_UNLOCK(c);
532             checked_lock( &b->b_mutex );
533             LDAP_CIRCLEQ_REMOVE( &b->b_preparing, c, c_next );
534             b->b_active++;
535             b->b_opening--;
536             b->b_failed = 0;
537             if ( b->b_last_conn ) {
538                 LDAP_CIRCLEQ_INSERT_AFTER(
539                         &b->b_conns, b->b_last_conn, c, c_next );
540             } else {
541                 LDAP_CIRCLEQ_INSERT_HEAD( &b->b_conns, c, c_next );
542             }
543             b->b_last_conn = c;
544             backend_retry( b );
545             checked_unlock( &b->b_mutex );
546             break;
547         default:
548             Debug( LDAP_DEBUG_ANY, "upstream_bind_cb: "
549                     "upstream bind failed, rc=%d, message='%s'\n",
550                     result, message.bv_val );
551             goto fail;
552     }
553 
554     checked_lock( &c->c_io_mutex );
555     c->c_io_state &= ~LLOAD_C_READ_HANDOVER;
556     checked_unlock( &c->c_io_mutex );
557     event_add( c->c_read_event, c->c_read_timeout );
558     ber_free( ber, 1 );
559     return -1;
560 
561 fail:
562     CONNECTION_LOCK_DESTROY(c);
563     ber_free( ber, 1 );
564     return -1;
565 }
566 
567 void *
upstream_bind(void * ctx,void * arg)568 upstream_bind( void *ctx, void *arg )
569 {
570     LloadConnection *c = arg;
571     BerElement *ber;
572     ber_int_t msgid;
573 
574     /* A reference was passed on to us */
575     assert( IS_ALIVE( c, c_refcnt ) );
576 
577     if ( !IS_ALIVE( c, c_live ) ) {
578         RELEASE_REF( c, c_refcnt, c->c_destroy );
579         return NULL;
580     }
581 
582     CONNECTION_LOCK(c);
583     assert( !event_pending( c->c_read_event, EV_READ, NULL ) );
584     c->c_pdu_cb = upstream_bind_cb;
585     CONNECTION_UNLOCK(c);
586 
587     checked_lock( &c->c_io_mutex );
588     ber = c->c_pendingber;
589     if ( ber == NULL && (ber = ber_alloc()) == NULL ) {
590         goto fail;
591     }
592     c->c_pendingber = ber;
593     msgid = c->c_next_msgid++;
594 
595     if ( bindconf.sb_method == LDAP_AUTH_SIMPLE ) {
596         /* simple bind */
597         ber_printf( ber, "{it{iOtON}}",
598                 msgid, LDAP_REQ_BIND, LDAP_VERSION3,
599                 &bindconf.sb_binddn, LDAP_AUTH_SIMPLE,
600                 &bindconf.sb_cred );
601 
602 #ifdef HAVE_CYRUS_SASL
603     } else {
604         BerValue cred;
605         int rc;
606 
607         rc = sasl_bind_step( c, NULL, &cred );
608         if ( rc != SASL_OK && rc != SASL_CONTINUE ) {
609             goto fail;
610         }
611 
612         ber_printf( ber, "{it{iOt{OON}N}}",
613                 msgid, LDAP_REQ_BIND, LDAP_VERSION3,
614                 &bindconf.sb_binddn, LDAP_AUTH_SASL,
615                 &c->c_sasl_bind_mech, BER_BV_OPTIONAL( &cred ) );
616 
617         if ( rc == SASL_OK ) {
618             BER_BVZERO( &c->c_sasl_bind_mech );
619         }
620 #endif /* HAVE_CYRUS_SASL */
621     }
622     /* TODO: can we be paused at this point? Then we'd have to move this line
623      * after connection_write_cb */
624     c->c_io_state &= ~LLOAD_C_READ_HANDOVER;
625     checked_unlock( &c->c_io_mutex );
626 
627     connection_write_cb( -1, 0, c );
628 
629     CONNECTION_LOCK(c);
630     c->c_read_timeout = lload_timeout_net;
631     event_add( c->c_read_event, c->c_read_timeout );
632     CONNECTION_UNLOCK(c);
633 
634     RELEASE_REF( c, c_refcnt, c->c_destroy );
635     return NULL;
636 
637 fail:
638     checked_unlock( &c->c_io_mutex );
639     CONNECTION_LOCK_DESTROY(c);
640     RELEASE_REF( c, c_refcnt, c->c_destroy );
641     return NULL;
642 }
643 
644 /*
645  * The backend is already locked when entering the function.
646  */
647 static int
upstream_finish(LloadConnection * c)648 upstream_finish( LloadConnection *c )
649 {
650     LloadBackend *b = c->c_backend;
651     int is_bindconn = 0;
652 
653     assert_locked( &b->b_mutex );
654     CONNECTION_ASSERT_LOCKED(c);
655     assert( c->c_live );
656     c->c_pdu_cb = handle_one_response;
657 
658     /* Unless we are configured to use the VC exop, consider allocating the
659      * connection into the bind conn pool. Start off by allocating one for
660      * general use, then one for binds, then we start filling up the general
661      * connection pool, finally the bind pool */
662     if (
663 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
664             !(lload_features & LLOAD_FEATURE_VC) &&
665 #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
666             b->b_active && b->b_numbindconns ) {
667         if ( !b->b_bindavail ) {
668             is_bindconn = 1;
669         } else if ( b->b_active >= b->b_numconns &&
670                 b->b_bindavail < b->b_numbindconns ) {
671             is_bindconn = 1;
672         }
673     }
674 
675     if ( is_bindconn ) {
676         LDAP_CIRCLEQ_REMOVE( &b->b_preparing, c, c_next );
677         c->c_state = LLOAD_C_READY;
678         c->c_type = LLOAD_C_BIND;
679         b->b_bindavail++;
680         b->b_opening--;
681         b->b_failed = 0;
682         if ( b->b_last_bindconn ) {
683             LDAP_CIRCLEQ_INSERT_AFTER(
684                     &b->b_bindconns, b->b_last_bindconn, c, c_next );
685         } else {
686             LDAP_CIRCLEQ_INSERT_HEAD( &b->b_bindconns, c, c_next );
687         }
688         b->b_last_bindconn = c;
689     } else if ( bindconf.sb_method == LDAP_AUTH_NONE ) {
690         LDAP_CIRCLEQ_REMOVE( &b->b_preparing, c, c_next );
691         c->c_state = LLOAD_C_READY;
692         c->c_type = LLOAD_C_OPEN;
693         b->b_active++;
694         b->b_opening--;
695         b->b_failed = 0;
696         if ( b->b_last_conn ) {
697             LDAP_CIRCLEQ_INSERT_AFTER( &b->b_conns, b->b_last_conn, c, c_next );
698         } else {
699             LDAP_CIRCLEQ_INSERT_HEAD( &b->b_conns, c, c_next );
700         }
701         b->b_last_conn = c;
702     } else {
703         if ( ldap_pvt_thread_pool_submit(
704                      &connection_pool, upstream_bind, c ) ) {
705             Debug( LDAP_DEBUG_ANY, "upstream_finish: "
706                     "failed to set up a bind callback for connid=%lu\n",
707                     c->c_connid );
708             return -1;
709         }
710         /* keep a reference for upstream_bind */
711         acquire_ref( &c->c_refcnt );
712 
713         Debug( LDAP_DEBUG_CONNS, "upstream_finish: "
714                 "scheduled a bind callback for connid=%lu\n",
715                 c->c_connid );
716         return LDAP_SUCCESS;
717     }
718     event_add( c->c_read_event, c->c_read_timeout );
719 
720     Debug( LDAP_DEBUG_CONNS, "upstream_finish: "
721             "%sconnection connid=%lu for backend server '%s' is ready for "
722             "use\n",
723             is_bindconn ? "bind " : "", c->c_connid, b->b_name.bv_val );
724 
725     backend_retry( b );
726     return LDAP_SUCCESS;
727 }
728 
729 #ifdef HAVE_TLS
730 static void
upstream_tls_handshake_cb(evutil_socket_t s,short what,void * arg)731 upstream_tls_handshake_cb( evutil_socket_t s, short what, void *arg )
732 {
733     LloadConnection *c = arg;
734     LloadBackend *b;
735     epoch_t epoch;
736     int rc = LDAP_SUCCESS;
737 
738     CONNECTION_LOCK(c);
739     if ( what & EV_TIMEOUT ) {
740         Debug( LDAP_DEBUG_CONNS, "upstream_tls_handshake_cb: "
741                 "connid=%lu, timeout reached, destroying\n",
742                 c->c_connid );
743         goto fail;
744     }
745     b = c->c_backend;
746 
747     rc = ldap_pvt_tls_connect( lload_tls_backend_ld, c->c_sb, b->b_host );
748     if ( rc < 0 ) {
749         goto fail;
750     }
751 
752     if ( rc == 0 ) {
753         struct event_base *base = event_get_base( c->c_read_event );
754 
755         /*
756          * We're finished, replace the callbacks
757          *
758          * This is deadlock-safe, since both share the same base - the one
759          * that's just running us.
760          */
761         event_del( c->c_read_event );
762         event_del( c->c_write_event );
763 
764         c->c_read_timeout = NULL;
765         event_assign( c->c_read_event, base, c->c_fd, EV_READ|EV_PERSIST,
766                 connection_read_cb, c );
767         event_assign( c->c_write_event, base, c->c_fd, EV_WRITE,
768                 connection_write_cb, c );
769         Debug( LDAP_DEBUG_CONNS, "upstream_tls_handshake_cb: "
770                 "connid=%lu finished\n",
771                 c->c_connid );
772         c->c_is_tls = LLOAD_TLS_ESTABLISHED;
773 
774         CONNECTION_UNLOCK(c);
775         checked_lock( &b->b_mutex );
776         CONNECTION_LOCK(c);
777 
778         rc = upstream_finish( c );
779         checked_unlock( &b->b_mutex );
780 
781         if ( rc ) {
782             goto fail;
783         }
784     } else if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
785         event_add( c->c_write_event, lload_write_timeout );
786         Debug( LDAP_DEBUG_CONNS, "upstream_tls_handshake_cb: "
787                 "connid=%lu need write rc=%d\n",
788                 c->c_connid, rc );
789     }
790     CONNECTION_UNLOCK(c);
791     return;
792 
793 fail:
794     Debug( LDAP_DEBUG_CONNS, "upstream_tls_handshake_cb: "
795             "connid=%lu failed rc=%d\n",
796             c->c_connid, rc );
797 
798     assert( c->c_ops == NULL );
799     epoch = epoch_join();
800     CONNECTION_DESTROY(c);
801     epoch_leave( epoch );
802 }
803 
804 static int
upstream_starttls(LloadConnection * c)805 upstream_starttls( LloadConnection *c )
806 {
807     BerValue matcheddn, message, responseOid,
808              startTLSOid = BER_BVC(LDAP_EXOP_START_TLS);
809     BerElement *ber = c->c_currentber;
810     struct event_base *base;
811     ber_int_t msgid, result;
812     ber_tag_t tag;
813 
814     c->c_currentber = NULL;
815     CONNECTION_LOCK(c);
816 
817     if ( ber_scanf( ber, "it", &msgid, &tag ) == LBER_ERROR ) {
818         Debug( LDAP_DEBUG_ANY, "upstream_starttls: "
819                 "protocol violation from server\n" );
820         goto fail;
821     }
822 
823     if ( msgid != ( c->c_next_msgid - 1 ) || tag != LDAP_RES_EXTENDED ) {
824         Debug( LDAP_DEBUG_ANY, "upstream_starttls: "
825                 "unexpected %s from server, msgid=%d\n",
826                 lload_msgtype2str( tag ), msgid );
827         goto fail;
828     }
829 
830     if ( ber_scanf( ber, "{emm}", &result, &matcheddn, &message ) ==
831                  LBER_ERROR ) {
832         Debug( LDAP_DEBUG_ANY, "upstream_starttls: "
833                 "protocol violation on StartTLS response\n" );
834         goto fail;
835     }
836 
837     if ( (tag = ber_get_tag( ber )) != LBER_DEFAULT ) {
838         if ( tag != LDAP_TAG_EXOP_RES_OID ||
839                 ber_scanf( ber, "{m}", &responseOid ) == LBER_DEFAULT ) {
840             Debug( LDAP_DEBUG_ANY, "upstream_starttls: "
841                     "protocol violation on StartTLS response\n" );
842             goto fail;
843         }
844 
845         if ( ber_bvcmp( &responseOid, &startTLSOid ) ) {
846             Debug( LDAP_DEBUG_ANY, "upstream_starttls: "
847                     "oid=%s not a StartTLS response\n",
848                     responseOid.bv_val );
849             goto fail;
850         }
851     }
852 
853     if ( result != LDAP_SUCCESS ) {
854         LloadBackend *b = c->c_backend;
855         int rc;
856 
857         Debug( LDAP_DEBUG_STATS, "upstream_starttls: "
858                 "server doesn't support StartTLS rc=%d message='%s'%s\n",
859                 result, message.bv_val,
860                 (c->c_is_tls == LLOAD_STARTTLS_OPTIONAL) ? ", ignored" : "" );
861         if ( c->c_is_tls != LLOAD_STARTTLS_OPTIONAL ) {
862             goto fail;
863         }
864         c->c_is_tls = LLOAD_CLEARTEXT;
865 
866         CONNECTION_UNLOCK(c);
867         checked_lock( &b->b_mutex );
868         CONNECTION_LOCK(c);
869 
870         rc = upstream_finish( c );
871         checked_unlock( &b->b_mutex );
872 
873         if ( rc ) {
874             goto fail;
875         }
876 
877         ber_free( ber, 1 );
878         CONNECTION_UNLOCK(c);
879 
880         checked_lock( &c->c_io_mutex );
881         c->c_io_state &= ~LLOAD_C_READ_HANDOVER;
882         checked_unlock( &c->c_io_mutex );
883 
884         /* Do not keep handle_pdus running, we have adjusted c_read_event as we
885          * need it. */
886         return -1;
887     }
888 
889     base = event_get_base( c->c_read_event );
890 
891     c->c_io_state &= ~LLOAD_C_READ_HANDOVER;
892     event_del( c->c_read_event );
893     event_del( c->c_write_event );
894 
895     c->c_read_timeout = lload_timeout_net;
896     event_assign( c->c_read_event, base, c->c_fd, EV_READ|EV_PERSIST,
897             upstream_tls_handshake_cb, c );
898     event_assign( c->c_write_event, base, c->c_fd, EV_WRITE,
899             upstream_tls_handshake_cb, c );
900 
901     event_add( c->c_read_event, c->c_read_timeout );
902     event_add( c->c_write_event, lload_write_timeout );
903 
904     CONNECTION_UNLOCK(c);
905 
906     ber_free( ber, 1 );
907     return -1;
908 
909 fail:
910     ber_free( ber, 1 );
911     CONNECTION_DESTROY(c);
912     return -1;
913 }
914 #endif /* HAVE_TLS */
915 
916 /*
917  * We must already hold b->b_mutex when called.
918  */
919 LloadConnection *
upstream_init(ber_socket_t s,LloadBackend * b)920 upstream_init( ber_socket_t s, LloadBackend *b )
921 {
922     LloadConnection *c;
923     struct event_base *base = lload_get_base( s );
924     struct event *event;
925     int flags;
926 
927     assert( b != NULL );
928 
929     flags = (b->b_proto == LDAP_PROTO_IPC) ? CONN_IS_IPC : 0;
930     if ( (c = lload_connection_init( s, b->b_host, flags )) == NULL ) {
931         return NULL;
932     }
933 
934     CONNECTION_LOCK(c);
935     c->c_backend = b;
936 #ifdef HAVE_TLS
937     c->c_is_tls = b->b_tls;
938 #endif
939     c->c_pdu_cb = handle_one_response;
940 
941     LDAP_CIRCLEQ_INSERT_HEAD( &b->b_preparing, c, c_next );
942     c->c_type = LLOAD_C_PREPARING;
943 
944     {
945         ber_len_t max = sockbuf_max_incoming_upstream;
946         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
947     }
948 
949     event = event_new( base, s, EV_READ|EV_PERSIST, connection_read_cb, c );
950     if ( !event ) {
951         Debug( LDAP_DEBUG_ANY, "upstream_init: "
952                 "Read event could not be allocated\n" );
953         goto fail;
954     }
955     c->c_read_event = event;
956 
957     event = event_new( base, s, EV_WRITE, connection_write_cb, c );
958     if ( !event ) {
959         Debug( LDAP_DEBUG_ANY, "upstream_init: "
960                 "Write event could not be allocated\n" );
961         goto fail;
962     }
963     /* We only add the write event when we have data pending */
964     c->c_write_event = event;
965 
966 #ifdef BALANCER_MODULE
967     if ( b->b_monitor ) {
968         acquire_ref( &c->c_refcnt );
969         CONNECTION_UNLOCK(c);
970         checked_unlock( &b->b_mutex );
971         if ( lload_monitor_conn_entry_create( c, b->b_monitor ) ) {
972             RELEASE_REF( c, c_refcnt, c->c_destroy );
973             checked_lock( &b->b_mutex );
974             CONNECTION_LOCK(c);
975             goto fail;
976         }
977         checked_lock( &b->b_mutex );
978         CONNECTION_LOCK(c);
979         RELEASE_REF( c, c_refcnt, c->c_destroy );
980     }
981 #endif /* BALANCER_MODULE */
982 
983     c->c_destroy = upstream_destroy;
984     c->c_unlink = upstream_unlink;
985 
986 #ifdef HAVE_TLS
987     if ( c->c_is_tls == LLOAD_CLEARTEXT ) {
988 #endif /* HAVE_TLS */
989         if ( upstream_finish( c ) ) {
990             goto fail;
991         }
992 #ifdef HAVE_TLS
993     } else if ( c->c_is_tls == LLOAD_LDAPS ) {
994         event_assign( c->c_read_event, base, s, EV_READ|EV_PERSIST,
995                 upstream_tls_handshake_cb, c );
996         event_add( c->c_read_event, c->c_read_timeout );
997         event_assign( c->c_write_event, base, s, EV_WRITE,
998                 upstream_tls_handshake_cb, c );
999         event_add( c->c_write_event, lload_write_timeout );
1000     } else if ( c->c_is_tls == LLOAD_STARTTLS ||
1001             c->c_is_tls == LLOAD_STARTTLS_OPTIONAL ) {
1002         BerElement *output;
1003 
1004         checked_lock( &c->c_io_mutex );
1005         if ( (output = c->c_pendingber = ber_alloc()) == NULL ) {
1006             checked_unlock( &c->c_io_mutex );
1007             goto fail;
1008         }
1009         ber_printf( output, "t{tit{ts}}", LDAP_TAG_MESSAGE,
1010                 LDAP_TAG_MSGID, c->c_next_msgid++,
1011                 LDAP_REQ_EXTENDED,
1012                 LDAP_TAG_EXOP_REQ_OID, LDAP_EXOP_START_TLS );
1013         checked_unlock( &c->c_io_mutex );
1014 
1015         c->c_pdu_cb = upstream_starttls;
1016         CONNECTION_UNLOCK(c);
1017         connection_write_cb( s, 0, c );
1018         CONNECTION_LOCK(c);
1019         if ( IS_ALIVE( c, c_live ) ) {
1020             event_add( c->c_read_event, c->c_read_timeout );
1021         }
1022     }
1023 #endif /* HAVE_TLS */
1024     CONNECTION_UNLOCK(c);
1025 
1026     return c;
1027 
1028 fail:
1029     if ( !IS_ALIVE( c, c_live ) ) {
1030         /*
1031          * Released while we were unlocked, it's scheduled for destruction
1032          * already
1033          */
1034         return NULL;
1035     }
1036 
1037     if ( c->c_write_event ) {
1038         event_del( c->c_write_event );
1039         event_free( c->c_write_event );
1040     }
1041     if ( c->c_read_event ) {
1042         event_del( c->c_read_event );
1043         event_free( c->c_read_event );
1044     }
1045 
1046     c->c_state = LLOAD_C_INVALID;
1047     c->c_live--;
1048     c->c_refcnt--;
1049     connection_destroy( c );
1050 
1051     return NULL;
1052 }
1053 
1054 static void
upstream_unlink(LloadConnection * c)1055 upstream_unlink( LloadConnection *c )
1056 {
1057     LloadBackend *b = c->c_backend;
1058     struct event *read_event, *write_event;
1059     TAvlnode *root, *linked_root;
1060     long freed, executing;
1061 
1062     Debug( LDAP_DEBUG_CONNS, "upstream_unlink: "
1063             "removing upstream connid=%lu\n",
1064             c->c_connid );
1065     CONNECTION_ASSERT_LOCKED(c);
1066 
1067     assert( c->c_state != LLOAD_C_INVALID );
1068     assert( c->c_state != LLOAD_C_DYING );
1069 
1070     c->c_state = LLOAD_C_DYING;
1071 
1072     read_event = c->c_read_event;
1073     write_event = c->c_write_event;
1074 
1075     root = c->c_ops;
1076     c->c_ops = NULL;
1077     executing = c->c_n_ops_executing;
1078     c->c_n_ops_executing = 0;
1079 
1080     linked_root = c->c_linked;
1081     c->c_linked = NULL;
1082 
1083     CONNECTION_UNLOCK(c);
1084 
1085     freed = ldap_tavl_free( root, (AVL_FREE)operation_lost_upstream );
1086     assert( freed == executing );
1087 
1088     ldap_tavl_free( linked_root, (AVL_FREE)linked_upstream_lost );
1089 
1090     /*
1091      * Avoid a deadlock:
1092      * event_del will block if the event is currently executing its callback,
1093      * that callback might be waiting to lock c->c_mutex
1094      */
1095     if ( read_event ) {
1096         event_del( read_event );
1097     }
1098 
1099     if ( write_event ) {
1100         event_del( write_event );
1101     }
1102 
1103     checked_lock( &b->b_mutex );
1104     if ( c->c_type == LLOAD_C_PREPARING ) {
1105         LDAP_CIRCLEQ_REMOVE( &b->b_preparing, c, c_next );
1106         b->b_opening--;
1107         b->b_failed++;
1108     } else if ( c->c_type == LLOAD_C_BIND ) {
1109         if ( c == b->b_last_bindconn ) {
1110             LloadConnection *prev =
1111                     LDAP_CIRCLEQ_LOOP_PREV( &b->b_bindconns, c, c_next );
1112             if ( prev == c ) {
1113                 b->b_last_bindconn = NULL;
1114             } else {
1115                 b->b_last_bindconn = prev;
1116             }
1117         }
1118         LDAP_CIRCLEQ_REMOVE( &b->b_bindconns, c, c_next );
1119         b->b_bindavail--;
1120     } else {
1121         if ( c == b->b_last_conn ) {
1122             LloadConnection *prev =
1123                     LDAP_CIRCLEQ_LOOP_PREV( &b->b_conns, c, c_next );
1124             if ( prev == c ) {
1125                 b->b_last_conn = NULL;
1126             } else {
1127                 b->b_last_conn = prev;
1128             }
1129         }
1130         LDAP_CIRCLEQ_REMOVE( &b->b_conns, c, c_next );
1131         b->b_active--;
1132     }
1133     b->b_n_ops_executing -= executing;
1134     backend_retry( b );
1135     checked_unlock( &b->b_mutex );
1136 
1137     CONNECTION_LOCK(c);
1138     CONNECTION_ASSERT_LOCKED(c);
1139 }
1140 
1141 void
upstream_destroy(LloadConnection * c)1142 upstream_destroy( LloadConnection *c )
1143 {
1144     Debug( LDAP_DEBUG_CONNS, "upstream_destroy: "
1145             "freeing connection connid=%lu\n",
1146             c->c_connid );
1147 
1148     CONNECTION_LOCK(c);
1149     assert( c->c_state == LLOAD_C_DYING );
1150 
1151 #ifdef BALANCER_MODULE
1152     /*
1153      * Can't do this in upstream_unlink as that could be run from cn=monitor
1154      * modify callback.
1155      */
1156     if ( !BER_BVISNULL( &c->c_monitor_dn ) ) {
1157         lload_monitor_conn_unlink( c );
1158     }
1159 #endif /* BALANCER_MODULE */
1160 
1161     c->c_state = LLOAD_C_INVALID;
1162 
1163     assert( c->c_ops == NULL );
1164 
1165     if ( c->c_read_event ) {
1166         event_free( c->c_read_event );
1167         c->c_read_event = NULL;
1168     }
1169 
1170     if ( c->c_write_event ) {
1171         event_free( c->c_write_event );
1172         c->c_write_event = NULL;
1173     }
1174 
1175     if ( c->c_type != LLOAD_C_BIND ) {
1176         BER_BVZERO( &c->c_sasl_bind_mech );
1177     }
1178     connection_destroy( c );
1179 }
1180