1 /*	$NetBSD: tls_o.c,v 1.3 2010/12/12 15:46:33 adam Exp $	*/
2 
3 /* tls_o.c - Handle tls/ssl using OpenSSL */
4 /* OpenLDAP: pkg/ldap/libraries/libldap/tls_o.c,v 1.5.2.12 2010/04/15 21:25:28 quanah Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2008-2010 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS: Rewritten by Howard Chu
19  */
20 
21 #include "portable.h"
22 
23 #ifdef HAVE_OPENSSL
24 
25 #include "ldap_config.h"
26 
27 #include <stdio.h>
28 
29 #include <ac/stdlib.h>
30 #include <ac/errno.h>
31 #include <ac/socket.h>
32 #include <ac/string.h>
33 #include <ac/ctype.h>
34 #include <ac/time.h>
35 #include <ac/unistd.h>
36 #include <ac/param.h>
37 #include <ac/dirent.h>
38 
39 #include "ldap-int.h"
40 #include "ldap-tls.h"
41 
42 #ifdef LDAP_R_COMPILE
43 #include <ldap_pvt_thread.h>
44 #endif
45 
46 #ifdef HAVE_OPENSSL_SSL_H
47 #include <openssl/ssl.h>
48 #include <openssl/x509v3.h>
49 #include <openssl/err.h>
50 #include <openssl/rand.h>
51 #include <openssl/safestack.h>
52 #elif defined( HAVE_SSL_H )
53 #include <ssl.h>
54 #endif
55 
56 typedef SSL_CTX tlso_ctx;
57 typedef SSL tlso_session;
58 
59 static int  tlso_opt_trace = 1;
60 
61 static void tlso_report_error( void );
62 
63 static void tlso_info_cb( const SSL *ssl, int where, int ret );
64 static int tlso_verify_cb( int ok, X509_STORE_CTX *ctx );
65 static int tlso_verify_ok( int ok, X509_STORE_CTX *ctx );
66 static RSA * tlso_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
67 
68 static DH * tlso_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
69 
70 typedef struct dhplist {
71 	struct dhplist *next;
72 	int keylength;
73 	DH *param;
74 } dhplist;
75 
76 static dhplist *tlso_dhparams;
77 
78 static int tlso_seed_PRNG( const char *randfile );
79 
80 #ifdef LDAP_R_COMPILE
81 /*
82  * provide mutexes for the OpenSSL library.
83  */
84 static ldap_pvt_thread_mutex_t	tlso_mutexes[CRYPTO_NUM_LOCKS];
85 static ldap_pvt_thread_mutex_t	tlso_dh_mutex;
86 
87 static void tlso_locking_cb( int mode, int type, const char *file, int line )
88 {
89 	if ( mode & CRYPTO_LOCK ) {
90 		ldap_pvt_thread_mutex_lock( &tlso_mutexes[type] );
91 	} else {
92 		ldap_pvt_thread_mutex_unlock( &tlso_mutexes[type] );
93 	}
94 }
95 
96 static unsigned long tlso_thread_self( void )
97 {
98 	/* FIXME: CRYPTO_set_id_callback only works when ldap_pvt_thread_t
99 	 * is an integral type that fits in an unsigned long
100 	 */
101 
102 	/* force an error if the ldap_pvt_thread_t type is too large */
103 	enum { ok = sizeof( ldap_pvt_thread_t ) <= sizeof( unsigned long ) };
104 	typedef struct { int dummy: ok ? 1 : -1; } Check[ok ? 1 : -1];
105 
106 	return (unsigned long) ldap_pvt_thread_self();
107 }
108 
109 static void tlso_thr_init( void )
110 {
111 	int i;
112 
113 	for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
114 		ldap_pvt_thread_mutex_init( &tlso_mutexes[i] );
115 	}
116 	ldap_pvt_thread_mutex_init( &tlso_dh_mutex );
117 	CRYPTO_set_locking_callback( tlso_locking_cb );
118 	CRYPTO_set_id_callback( tlso_thread_self );
119 }
120 #endif /* LDAP_R_COMPILE */
121 
122 static STACK_OF(X509_NAME) *
123 tlso_ca_list( char * bundle, char * dir )
124 {
125 	STACK_OF(X509_NAME) *ca_list = NULL;
126 
127 	if ( bundle ) {
128 		ca_list = SSL_load_client_CA_file( bundle );
129 	}
130 #if defined(HAVE_DIRENT_H) || defined(dirent)
131 	if ( dir ) {
132 		int freeit = 0;
133 
134 		if ( !ca_list ) {
135 			ca_list = sk_X509_NAME_new_null();
136 			freeit = 1;
137 		}
138 		if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
139 			freeit ) {
140 			sk_X509_NAME_free( ca_list );
141 			ca_list = NULL;
142 		}
143 	}
144 #endif
145 	return ca_list;
146 }
147 
148 /*
149  * Initialize TLS subsystem. Should be called only once.
150  */
151 static int
152 tlso_init( void )
153 {
154 	struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
155 #ifdef HAVE_EBCDIC
156 	{
157 		char *file = LDAP_STRDUP( lo->ldo_tls_randfile );
158 		if ( file ) __atoe( file );
159 		(void) tlso_seed_PRNG( file );
160 		LDAP_FREE( file );
161 	}
162 #else
163 	(void) tlso_seed_PRNG( lo->ldo_tls_randfile );
164 #endif
165 
166 	SSL_load_error_strings();
167 	SSL_library_init();
168 	OpenSSL_add_all_digests();
169 
170 	/* FIXME: mod_ssl does this */
171 	X509V3_add_standard_extensions();
172 
173 	return 0;
174 }
175 
176 /*
177  * Tear down the TLS subsystem. Should only be called once.
178  */
179 static void
180 tlso_destroy( void )
181 {
182 	struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
183 
184 	EVP_cleanup();
185 	ERR_remove_state(0);
186 	ERR_free_strings();
187 
188 	if ( lo->ldo_tls_randfile ) {
189 		LDAP_FREE( lo->ldo_tls_randfile );
190 		lo->ldo_tls_randfile = NULL;
191 	}
192 }
193 
194 static tls_ctx *
195 tlso_ctx_new( struct ldapoptions *lo )
196 {
197 	return (tls_ctx *) SSL_CTX_new( SSLv23_method() );
198 }
199 
200 static void
201 tlso_ctx_ref( tls_ctx *ctx )
202 {
203 	tlso_ctx *c = (tlso_ctx *)ctx;
204 	CRYPTO_add( &c->references, 1, CRYPTO_LOCK_SSL_CTX );
205 }
206 
207 static void
208 tlso_ctx_free ( tls_ctx *ctx )
209 {
210 	tlso_ctx *c = (tlso_ctx *)ctx;
211 	SSL_CTX_free( c );
212 }
213 
214 /*
215  * initialize a new TLS context
216  */
217 static int
218 tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
219 {
220 	tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx;
221 	int i;
222 
223 	if ( is_server ) {
224 		SSL_CTX_set_session_id_context( ctx,
225 			(const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 );
226 	}
227 
228 	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 )
229 		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 );
230 	else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 )
231 		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 );
232 
233 	if ( lo->ldo_tls_ciphersuite &&
234 		!SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) )
235 	{
236 		Debug( LDAP_DEBUG_ANY,
237 			   "TLS: could not set cipher list %s.\n",
238 			   lo->ldo_tls_ciphersuite, 0, 0 );
239 		tlso_report_error();
240 		return -1;
241 	}
242 
243 	if (lo->ldo_tls_cacertfile != NULL || lo->ldo_tls_cacertdir != NULL) {
244 		if ( !SSL_CTX_load_verify_locations( ctx,
245 				lt->lt_cacertfile, lt->lt_cacertdir ) ||
246 			!SSL_CTX_set_default_verify_paths( ctx ) )
247 		{
248 			Debug( LDAP_DEBUG_ANY, "TLS: "
249 				"could not load verify locations (file:`%s',dir:`%s').\n",
250 				lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
251 				lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
252 				0 );
253 			tlso_report_error();
254 			return -1;
255 		}
256 
257 		if ( is_server ) {
258 			STACK_OF(X509_NAME) *calist;
259 			/* List of CA names to send to a client */
260 			calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir );
261 			if ( !calist ) {
262 				Debug( LDAP_DEBUG_ANY, "TLS: "
263 					"could not load client CA list (file:`%s',dir:`%s').\n",
264 					lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
265 					lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
266 					0 );
267 				tlso_report_error();
268 				return -1;
269 			}
270 
271 			SSL_CTX_set_client_CA_list( ctx, calist );
272 		}
273 	}
274 
275 	if ( lo->ldo_tls_certfile &&
276 		!SSL_CTX_use_certificate_file( ctx,
277 			lt->lt_certfile, SSL_FILETYPE_PEM ) )
278 	{
279 		Debug( LDAP_DEBUG_ANY,
280 			"TLS: could not use certificate `%s'.\n",
281 			lo->ldo_tls_certfile,0,0);
282 		tlso_report_error();
283 		return -1;
284 	}
285 
286 	/* Key validity is checked automatically if cert has already been set */
287 	if ( lo->ldo_tls_keyfile &&
288 		!SSL_CTX_use_PrivateKey_file( ctx,
289 			lt->lt_keyfile, SSL_FILETYPE_PEM ) )
290 	{
291 		Debug( LDAP_DEBUG_ANY,
292 			"TLS: could not use key file `%s'.\n",
293 			lo->ldo_tls_keyfile,0,0);
294 		tlso_report_error();
295 		return -1;
296 	}
297 
298 	if ( lo->ldo_tls_dhfile ) {
299 		DH *dh = NULL;
300 		BIO *bio;
301 		dhplist *p;
302 
303 		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
304 			Debug( LDAP_DEBUG_ANY,
305 				"TLS: could not use DH parameters file `%s'.\n",
306 				lo->ldo_tls_dhfile,0,0);
307 			tlso_report_error();
308 			return -1;
309 		}
310 		while (( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) {
311 			p = LDAP_MALLOC( sizeof(dhplist) );
312 			if ( p != NULL ) {
313 				p->keylength = DH_size( dh ) * 8;
314 				p->param = dh;
315 				p->next = tlso_dhparams;
316 				tlso_dhparams = p;
317 			}
318 		}
319 		BIO_free( bio );
320 	}
321 
322 	if ( tlso_opt_trace ) {
323 		SSL_CTX_set_info_callback( ctx, tlso_info_cb );
324 	}
325 
326 	i = SSL_VERIFY_NONE;
327 	if ( lo->ldo_tls_require_cert ) {
328 		i = SSL_VERIFY_PEER;
329 		if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
330 			 lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) {
331 			i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
332 		}
333 	}
334 
335 	SSL_CTX_set_verify( ctx, i,
336 		lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ?
337 		tlso_verify_ok : tlso_verify_cb );
338 	SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb );
339 	if ( lo->ldo_tls_dhfile ) {
340 		SSL_CTX_set_tmp_dh_callback( ctx, tlso_tmp_dh_cb );
341 	}
342 #ifdef HAVE_OPENSSL_CRL
343 	if ( lo->ldo_tls_crlcheck ) {
344 		X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx );
345 		if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) {
346 			X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK );
347 		} else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) {
348 			X509_STORE_set_flags( x509_s,
349 					X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL  );
350 		}
351 	}
352 #endif
353 	return 0;
354 }
355 
356 static tls_session *
357 tlso_session_new( tls_ctx *ctx, int is_server )
358 {
359 	tlso_ctx *c = (tlso_ctx *)ctx;
360 	return (tls_session *)SSL_new( c );
361 }
362 
363 static int
364 tlso_session_connect( LDAP *ld, tls_session *sess )
365 {
366 	tlso_session *s = (tlso_session *)sess;
367 
368 	/* Caller expects 0 = success, OpenSSL returns 1 = success */
369 	return SSL_connect( s ) - 1;
370 }
371 
372 static int
373 tlso_session_accept( tls_session *sess )
374 {
375 	tlso_session *s = (tlso_session *)sess;
376 
377 	/* Caller expects 0 = success, OpenSSL returns 1 = success */
378 	return SSL_accept( s ) - 1;
379 }
380 
381 static int
382 tlso_session_upflags( Sockbuf *sb, tls_session *sess, int rc )
383 {
384 	tlso_session *s = (tlso_session *)sess;
385 
386 	/* 1 was subtracted above, offset it back now */
387 	rc = SSL_get_error(s, rc+1);
388 	if (rc == SSL_ERROR_WANT_READ) {
389 		sb->sb_trans_needs_read  = 1;
390 		return 1;
391 
392 	} else if (rc == SSL_ERROR_WANT_WRITE) {
393 		sb->sb_trans_needs_write = 1;
394 		return 1;
395 
396 	} else if (rc == SSL_ERROR_WANT_CONNECT) {
397 		return 1;
398 	}
399 	return 0;
400 }
401 
402 static char *
403 tlso_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
404 {
405 	char err[256] = "";
406 	const char *certerr=NULL;
407 	tlso_session *s = (tlso_session *)sess;
408 
409 	rc = ERR_peek_error();
410 	if ( rc ) {
411 		ERR_error_string_n( rc, err, sizeof(err) );
412 		if ( ( ERR_GET_LIB(rc) == ERR_LIB_SSL ) &&
413 				( ERR_GET_REASON(rc) == SSL_R_CERTIFICATE_VERIFY_FAILED ) ) {
414 			int certrc = SSL_get_verify_result(s);
415 			certerr = (char *)X509_verify_cert_error_string(certrc);
416 		}
417 		snprintf(buf, len, "%s%s%s%s", err, certerr ? " (" :"",
418 				certerr ? certerr : "", certerr ?  ")" : "" );
419 		return buf;
420 	}
421 	return NULL;
422 }
423 
424 static int
425 tlso_session_my_dn( tls_session *sess, struct berval *der_dn )
426 {
427 	tlso_session *s = (tlso_session *)sess;
428 	X509 *x;
429 	X509_NAME *xn;
430 
431 	x = SSL_get_certificate( s );
432 
433 	if (!x) return LDAP_INVALID_CREDENTIALS;
434 
435 	xn = X509_get_subject_name(x);
436 	der_dn->bv_len = i2d_X509_NAME( xn, NULL );
437 	der_dn->bv_val = xn->bytes->data;
438 	/* Don't X509_free, the session is still using it */
439 	return 0;
440 }
441 
442 static X509 *
443 tlso_get_cert( SSL *s )
444 {
445 	/* If peer cert was bad, treat as if no cert was given */
446 	if (SSL_get_verify_result(s)) {
447 		return NULL;
448 	}
449 	return SSL_get_peer_certificate(s);
450 }
451 
452 static int
453 tlso_session_peer_dn( tls_session *sess, struct berval *der_dn )
454 {
455 	tlso_session *s = (tlso_session *)sess;
456 	X509 *x = tlso_get_cert( s );
457 	X509_NAME *xn;
458 
459 	if ( !x )
460 		return LDAP_INVALID_CREDENTIALS;
461 
462 	xn = X509_get_subject_name(x);
463 	der_dn->bv_len = i2d_X509_NAME( xn, NULL );
464 	der_dn->bv_val = xn->bytes->data;
465 	X509_free(x);
466 	return 0;
467 }
468 
469 /* what kind of hostname were we given? */
470 #define	IS_DNS	0
471 #define	IS_IP4	1
472 #define	IS_IP6	2
473 
474 static int
475 tlso_session_chkhost( LDAP *ld, tls_session *sess, const char *name_in )
476 {
477 	tlso_session *s = (tlso_session *)sess;
478 	int i, ret = LDAP_LOCAL_ERROR;
479 	X509 *x;
480 	const char *name;
481 	char *ptr;
482 	int ntype = IS_DNS, nlen;
483 #ifdef LDAP_PF_INET6
484 	struct in6_addr addr;
485 #else
486 	struct in_addr addr;
487 #endif
488 
489 	if( ldap_int_hostname &&
490 		( !name_in || !strcasecmp( name_in, "localhost" ) ) )
491 	{
492 		name = ldap_int_hostname;
493 	} else {
494 		name = name_in;
495 	}
496 	nlen = strlen(name);
497 
498 	x = tlso_get_cert(s);
499 	if (!x) {
500 		Debug( LDAP_DEBUG_ANY,
501 			"TLS: unable to get peer certificate.\n",
502 			0, 0, 0 );
503 		/* If this was a fatal condition, things would have
504 		 * aborted long before now.
505 		 */
506 		return LDAP_SUCCESS;
507 	}
508 
509 #ifdef LDAP_PF_INET6
510 	if (name[0] == '[' && strchr(name, ']')) {
511 		char *n2 = ldap_strdup(name+1);
512 		*strchr(n2, ']') = 0;
513 		if (inet_pton(AF_INET6, n2, &addr))
514 			ntype = IS_IP6;
515 		LDAP_FREE(n2);
516 	} else
517 #endif
518 	if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
519 		if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
520 	}
521 
522 	i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
523 	if (i >= 0) {
524 		X509_EXTENSION *ex;
525 		STACK_OF(GENERAL_NAME) *alt;
526 
527 		ex = X509_get_ext(x, i);
528 		alt = X509V3_EXT_d2i(ex);
529 		if (alt) {
530 			int n, len2 = 0;
531 			char *domain = NULL;
532 			GENERAL_NAME *gn;
533 
534 			if (ntype == IS_DNS) {
535 				domain = strchr(name, '.');
536 				if (domain) {
537 					len2 = nlen - (domain-name);
538 				}
539 			}
540 			n = sk_GENERAL_NAME_num(alt);
541 			for (i=0; i<n; i++) {
542 				char *sn;
543 				int sl;
544 				gn = sk_GENERAL_NAME_value(alt, i);
545 				if (gn->type == GEN_DNS) {
546 					if (ntype != IS_DNS) continue;
547 
548 					sn = (char *) ASN1_STRING_data(gn->d.ia5);
549 					sl = ASN1_STRING_length(gn->d.ia5);
550 
551 					/* ignore empty */
552 					if (sl == 0) continue;
553 
554 					/* Is this an exact match? */
555 					if ((nlen == sl) && !strncasecmp(name, sn, nlen)) {
556 						break;
557 					}
558 
559 					/* Is this a wildcard match? */
560 					if (domain && (sn[0] == '*') && (sn[1] == '.') &&
561 						(len2 == sl-1) && !strncasecmp(domain, &sn[1], len2))
562 					{
563 						break;
564 					}
565 
566 				} else if (gn->type == GEN_IPADD) {
567 					if (ntype == IS_DNS) continue;
568 
569 					sn = (char *) ASN1_STRING_data(gn->d.ia5);
570 					sl = ASN1_STRING_length(gn->d.ia5);
571 
572 #ifdef LDAP_PF_INET6
573 					if (ntype == IS_IP6 && sl != sizeof(struct in6_addr)) {
574 						continue;
575 					} else
576 #endif
577 					if (ntype == IS_IP4 && sl != sizeof(struct in_addr)) {
578 						continue;
579 					}
580 					if (!memcmp(sn, &addr, sl)) {
581 						break;
582 					}
583 				}
584 			}
585 
586 			GENERAL_NAMES_free(alt);
587 			if (i < n) {	/* Found a match */
588 				ret = LDAP_SUCCESS;
589 			}
590 		}
591 	}
592 
593 	if (ret != LDAP_SUCCESS) {
594 		X509_NAME *xn;
595 		X509_NAME_ENTRY *ne;
596 		ASN1_OBJECT *obj;
597 		ASN1_STRING *cn = NULL;
598 		int navas;
599 
600 		/* find the last CN */
601 		obj = OBJ_nid2obj( NID_commonName );
602 		if ( !obj ) goto no_cn;	/* should never happen */
603 
604 		xn = X509_get_subject_name(x);
605 		navas = X509_NAME_entry_count( xn );
606 		for ( i=navas-1; i>=0; i-- ) {
607 			ne = X509_NAME_get_entry( xn, i );
608 			if ( !OBJ_cmp( ne->object, obj )) {
609 				cn = X509_NAME_ENTRY_get_data( ne );
610 				break;
611 			}
612 		}
613 
614 		if( !cn )
615 		{
616 no_cn:
617 			Debug( LDAP_DEBUG_ANY,
618 				"TLS: unable to get common name from peer certificate.\n",
619 				0, 0, 0 );
620 			ret = LDAP_CONNECT_ERROR;
621 			if ( ld->ld_error ) {
622 				LDAP_FREE( ld->ld_error );
623 			}
624 			ld->ld_error = LDAP_STRDUP(
625 				_("TLS: unable to get CN from peer certificate"));
626 
627 		} else if ( cn->length == nlen &&
628 			strncasecmp( name, (char *) cn->data, nlen ) == 0 ) {
629 			ret = LDAP_SUCCESS;
630 
631 		} else if (( cn->data[0] == '*' ) && ( cn->data[1] == '.' )) {
632 			char *domain = strchr(name, '.');
633 			if( domain ) {
634 				int dlen;
635 
636 				dlen = nlen - (domain-name);
637 
638 				/* Is this a wildcard match? */
639 				if ((dlen == cn->length-1) &&
640 					!strncasecmp(domain, (char *) &cn->data[1], dlen)) {
641 					ret = LDAP_SUCCESS;
642 				}
643 			}
644 		}
645 
646 		if( ret == LDAP_LOCAL_ERROR ) {
647 			Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
648 				"common name in certificate (%.*s).\n",
649 				name, cn->length, cn->data );
650 			ret = LDAP_CONNECT_ERROR;
651 			if ( ld->ld_error ) {
652 				LDAP_FREE( ld->ld_error );
653 			}
654 			ld->ld_error = LDAP_STRDUP(
655 				_("TLS: hostname does not match CN in peer certificate"));
656 		}
657 	}
658 	X509_free(x);
659 	return ret;
660 }
661 
662 static int
663 tlso_session_strength( tls_session *sess )
664 {
665 	tlso_session *s = (tlso_session *)sess;
666 	const SSL_CIPHER *c;
667 
668 	c = SSL_get_current_cipher(s);
669 	return SSL_CIPHER_get_bits(c, NULL);
670 }
671 
672 /*
673  * TLS support for LBER Sockbufs
674  */
675 
676 struct tls_data {
677 	tlso_session		*session;
678 	Sockbuf_IO_Desc		*sbiod;
679 };
680 
681 static int
682 tlso_bio_create( BIO *b ) {
683 	b->init = 1;
684 	b->num = 0;
685 	b->ptr = NULL;
686 	b->flags = 0;
687 	return 1;
688 }
689 
690 static int
691 tlso_bio_destroy( BIO *b )
692 {
693 	if ( b == NULL ) return 0;
694 
695 	b->ptr = NULL;		/* sb_tls_remove() will free it */
696 	b->init = 0;
697 	b->flags = 0;
698 	return 1;
699 }
700 
701 static int
702 tlso_bio_read( BIO *b, char *buf, int len )
703 {
704 	struct tls_data		*p;
705 	int			ret;
706 
707 	if ( buf == NULL || len <= 0 ) return 0;
708 
709 	p = (struct tls_data *)b->ptr;
710 
711 	if ( p == NULL || p->sbiod == NULL ) {
712 		return 0;
713 	}
714 
715 	ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
716 
717 	BIO_clear_retry_flags( b );
718 	if ( ret < 0 ) {
719 		int err = sock_errno();
720 		if ( err == EAGAIN || err == EWOULDBLOCK ) {
721 			BIO_set_retry_read( b );
722 		}
723 	}
724 
725 	return ret;
726 }
727 
728 static int
729 tlso_bio_write( BIO *b, const char *buf, int len )
730 {
731 	struct tls_data		*p;
732 	int			ret;
733 
734 	if ( buf == NULL || len <= 0 ) return 0;
735 
736 	p = (struct tls_data *)b->ptr;
737 
738 	if ( p == NULL || p->sbiod == NULL ) {
739 		return 0;
740 	}
741 
742 	ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
743 
744 	BIO_clear_retry_flags( b );
745 	if ( ret < 0 ) {
746 		int err = sock_errno();
747 		if ( err == EAGAIN || err == EWOULDBLOCK ) {
748 			BIO_set_retry_write( b );
749 		}
750 	}
751 
752 	return ret;
753 }
754 
755 static long
756 tlso_bio_ctrl( BIO *b, int cmd, long num, void *ptr )
757 {
758 	if ( cmd == BIO_CTRL_FLUSH ) {
759 		/* The OpenSSL library needs this */
760 		return 1;
761 	}
762 	return 0;
763 }
764 
765 static int
766 tlso_bio_gets( BIO *b, char *buf, int len )
767 {
768 	return -1;
769 }
770 
771 static int
772 tlso_bio_puts( BIO *b, const char *str )
773 {
774 	return tlso_bio_write( b, str, strlen( str ) );
775 }
776 
777 static BIO_METHOD tlso_bio_method =
778 {
779 	( 100 | 0x400 ),		/* it's a source/sink BIO */
780 	"sockbuf glue",
781 	tlso_bio_write,
782 	tlso_bio_read,
783 	tlso_bio_puts,
784 	tlso_bio_gets,
785 	tlso_bio_ctrl,
786 	tlso_bio_create,
787 	tlso_bio_destroy
788 };
789 
790 static int
791 tlso_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
792 {
793 	struct tls_data		*p;
794 	BIO			*bio;
795 
796 	assert( sbiod != NULL );
797 
798 	p = LBER_MALLOC( sizeof( *p ) );
799 	if ( p == NULL ) {
800 		return -1;
801 	}
802 
803 	p->session = arg;
804 	p->sbiod = sbiod;
805 	bio = BIO_new( &tlso_bio_method );
806 	bio->ptr = (void *)p;
807 	SSL_set_bio( p->session, bio, bio );
808 	sbiod->sbiod_pvt = p;
809 	return 0;
810 }
811 
812 static int
813 tlso_sb_remove( Sockbuf_IO_Desc *sbiod )
814 {
815 	struct tls_data		*p;
816 
817 	assert( sbiod != NULL );
818 	assert( sbiod->sbiod_pvt != NULL );
819 
820 	p = (struct tls_data *)sbiod->sbiod_pvt;
821 	SSL_free( p->session );
822 	LBER_FREE( sbiod->sbiod_pvt );
823 	sbiod->sbiod_pvt = NULL;
824 	return 0;
825 }
826 
827 static int
828 tlso_sb_close( Sockbuf_IO_Desc *sbiod )
829 {
830 	struct tls_data		*p;
831 
832 	assert( sbiod != NULL );
833 	assert( sbiod->sbiod_pvt != NULL );
834 
835 	p = (struct tls_data *)sbiod->sbiod_pvt;
836 	SSL_shutdown( p->session );
837 	return 0;
838 }
839 
840 static int
841 tlso_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
842 {
843 	struct tls_data		*p;
844 
845 	assert( sbiod != NULL );
846 	assert( sbiod->sbiod_pvt != NULL );
847 
848 	p = (struct tls_data *)sbiod->sbiod_pvt;
849 
850 	if ( opt == LBER_SB_OPT_GET_SSL ) {
851 		*((tlso_session **)arg) = p->session;
852 		return 1;
853 
854 	} else if ( opt == LBER_SB_OPT_DATA_READY ) {
855 		if( SSL_pending( p->session ) > 0 ) {
856 			return 1;
857 		}
858 	}
859 
860 	return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
861 }
862 
863 static ber_slen_t
864 tlso_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
865 {
866 	struct tls_data		*p;
867 	ber_slen_t		ret;
868 	int			err;
869 
870 	assert( sbiod != NULL );
871 	assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
872 
873 	p = (struct tls_data *)sbiod->sbiod_pvt;
874 
875 	ret = SSL_read( p->session, (char *)buf, len );
876 #ifdef HAVE_WINSOCK
877 	errno = WSAGetLastError();
878 #endif
879 	err = SSL_get_error( p->session, ret );
880 	if (err == SSL_ERROR_WANT_READ ) {
881 		sbiod->sbiod_sb->sb_trans_needs_read = 1;
882 		sock_errset(EWOULDBLOCK);
883 	}
884 	else
885 		sbiod->sbiod_sb->sb_trans_needs_read = 0;
886 	return ret;
887 }
888 
889 static ber_slen_t
890 tlso_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
891 {
892 	struct tls_data		*p;
893 	ber_slen_t		ret;
894 	int			err;
895 
896 	assert( sbiod != NULL );
897 	assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
898 
899 	p = (struct tls_data *)sbiod->sbiod_pvt;
900 
901 	ret = SSL_write( p->session, (char *)buf, len );
902 #ifdef HAVE_WINSOCK
903 	errno = WSAGetLastError();
904 #endif
905 	err = SSL_get_error( p->session, ret );
906 	if (err == SSL_ERROR_WANT_WRITE ) {
907 		sbiod->sbiod_sb->sb_trans_needs_write = 1;
908 		sock_errset(EWOULDBLOCK);
909 
910 	} else {
911 		sbiod->sbiod_sb->sb_trans_needs_write = 0;
912 	}
913 	return ret;
914 }
915 
916 static Sockbuf_IO tlso_sbio =
917 {
918 	tlso_sb_setup,		/* sbi_setup */
919 	tlso_sb_remove,		/* sbi_remove */
920 	tlso_sb_ctrl,		/* sbi_ctrl */
921 	tlso_sb_read,		/* sbi_read */
922 	tlso_sb_write,		/* sbi_write */
923 	tlso_sb_close		/* sbi_close */
924 };
925 
926 /* Derived from openssl/apps/s_cb.c */
927 static void
928 tlso_info_cb( const SSL *ssl, int where, int ret )
929 {
930 	int w;
931 	char *op;
932 	char *state = (char *) SSL_state_string_long( (SSL *)ssl );
933 
934 	w = where & ~SSL_ST_MASK;
935 	if ( w & SSL_ST_CONNECT ) {
936 		op = "SSL_connect";
937 	} else if ( w & SSL_ST_ACCEPT ) {
938 		op = "SSL_accept";
939 	} else {
940 		op = "undefined";
941 	}
942 
943 #ifdef HAVE_EBCDIC
944 	if ( state ) {
945 		state = LDAP_STRDUP( state );
946 		__etoa( state );
947 	}
948 #endif
949 	if ( where & SSL_CB_LOOP ) {
950 		Debug( LDAP_DEBUG_TRACE,
951 			   "TLS trace: %s:%s\n",
952 			   op, state, 0 );
953 
954 	} else if ( where & SSL_CB_ALERT ) {
955 		char *atype = (char *) SSL_alert_type_string_long( ret );
956 		char *adesc = (char *) SSL_alert_desc_string_long( ret );
957 		op = ( where & SSL_CB_READ ) ? "read" : "write";
958 #ifdef HAVE_EBCDIC
959 		if ( atype ) {
960 			atype = LDAP_STRDUP( atype );
961 			__etoa( atype );
962 		}
963 		if ( adesc ) {
964 			adesc = LDAP_STRDUP( adesc );
965 			__etoa( adesc );
966 		}
967 #endif
968 		Debug( LDAP_DEBUG_TRACE,
969 			   "TLS trace: SSL3 alert %s:%s:%s\n",
970 			   op, atype, adesc );
971 #ifdef HAVE_EBCDIC
972 		if ( atype ) LDAP_FREE( atype );
973 		if ( adesc ) LDAP_FREE( adesc );
974 #endif
975 	} else if ( where & SSL_CB_EXIT ) {
976 		if ( ret == 0 ) {
977 			Debug( LDAP_DEBUG_TRACE,
978 				   "TLS trace: %s:failed in %s\n",
979 				   op, state, 0 );
980 		} else if ( ret < 0 ) {
981 			Debug( LDAP_DEBUG_TRACE,
982 				   "TLS trace: %s:error in %s\n",
983 				   op, state, 0 );
984 		}
985 	}
986 #ifdef HAVE_EBCDIC
987 	if ( state ) LDAP_FREE( state );
988 #endif
989 }
990 
991 static int
992 tlso_verify_cb( int ok, X509_STORE_CTX *ctx )
993 {
994 	X509 *cert;
995 	int errnum;
996 	int errdepth;
997 	X509_NAME *subject;
998 	X509_NAME *issuer;
999 	char *sname;
1000 	char *iname;
1001 	char *certerr = NULL;
1002 
1003 	cert = X509_STORE_CTX_get_current_cert( ctx );
1004 	errnum = X509_STORE_CTX_get_error( ctx );
1005 	errdepth = X509_STORE_CTX_get_error_depth( ctx );
1006 
1007 	/*
1008 	 * X509_get_*_name return pointers to the internal copies of
1009 	 * those things requested.  So do not free them.
1010 	 */
1011 	subject = X509_get_subject_name( cert );
1012 	issuer = X509_get_issuer_name( cert );
1013 	/* X509_NAME_oneline, if passed a NULL buf, allocate memomry */
1014 	sname = X509_NAME_oneline( subject, NULL, 0 );
1015 	iname = X509_NAME_oneline( issuer, NULL, 0 );
1016 	if ( !ok ) certerr = (char *)X509_verify_cert_error_string( errnum );
1017 #ifdef HAVE_EBCDIC
1018 	if ( sname ) __etoa( sname );
1019 	if ( iname ) __etoa( iname );
1020 	if ( certerr ) {
1021 		certerr = LDAP_STRDUP( certerr );
1022 		__etoa( certerr );
1023 	}
1024 #endif
1025 	Debug( LDAP_DEBUG_TRACE,
1026 		   "TLS certificate verification: depth: %d, err: %d, subject: %s,",
1027 		   errdepth, errnum,
1028 		   sname ? sname : "-unknown-" );
1029 	Debug( LDAP_DEBUG_TRACE, " issuer: %s\n", iname ? iname : "-unknown-", 0, 0 );
1030 	if ( !ok ) {
1031 		Debug( LDAP_DEBUG_ANY,
1032 			"TLS certificate verification: Error, %s\n",
1033 			certerr, 0, 0 );
1034 	}
1035 	if ( sname )
1036 		CRYPTO_free ( sname );
1037 	if ( iname )
1038 		CRYPTO_free ( iname );
1039 #ifdef HAVE_EBCDIC
1040 	if ( certerr ) LDAP_FREE( certerr );
1041 #endif
1042 	return ok;
1043 }
1044 
1045 static int
1046 tlso_verify_ok( int ok, X509_STORE_CTX *ctx )
1047 {
1048 	(void) tlso_verify_cb( ok, ctx );
1049 	return 1;
1050 }
1051 
1052 /* Inspired by ERR_print_errors in OpenSSL */
1053 static void
1054 tlso_report_error( void )
1055 {
1056 	unsigned long l;
1057 	char buf[200];
1058 	const char *file;
1059 	int line;
1060 
1061 	while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
1062 		ERR_error_string_n( l, buf, sizeof( buf ) );
1063 #ifdef HAVE_EBCDIC
1064 		if ( file ) {
1065 			file = LDAP_STRDUP( file );
1066 			__etoa( (char *)file );
1067 		}
1068 		__etoa( buf );
1069 #endif
1070 		Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
1071 			buf, file, line );
1072 #ifdef HAVE_EBCDIC
1073 		if ( file ) LDAP_FREE( (void *)file );
1074 #endif
1075 	}
1076 }
1077 
1078 static RSA *
1079 tlso_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
1080 {
1081 	RSA *tmp_rsa;
1082 	/* FIXME:  Pregenerate the key on startup */
1083 	/* FIXME:  Who frees the key? */
1084 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1085 	BIGNUM *bn = BN_new();
1086 	tmp_rsa = NULL;
1087 	if ( bn ) {
1088 		if ( BN_set_word( bn, RSA_F4 )) {
1089 			tmp_rsa = RSA_new();
1090 			if ( tmp_rsa && !RSA_generate_key_ex( tmp_rsa, key_length, bn, NULL )) {
1091 				RSA_free( tmp_rsa );
1092 				tmp_rsa = NULL;
1093 			}
1094 		}
1095 		BN_free( bn );
1096 	}
1097 #else
1098 	tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL );
1099 #endif
1100 
1101 	if ( !tmp_rsa ) {
1102 		Debug( LDAP_DEBUG_ANY,
1103 			"TLS: Failed to generate temporary %d-bit %s RSA key\n",
1104 			key_length, is_export ? "export" : "domestic", 0 );
1105 	}
1106 	return tmp_rsa;
1107 }
1108 
1109 static int
1110 tlso_seed_PRNG( const char *randfile )
1111 {
1112 #ifndef URANDOM_DEVICE
1113 	/* no /dev/urandom (or equiv) */
1114 	long total=0;
1115 	char buffer[MAXPATHLEN];
1116 
1117 	if (randfile == NULL) {
1118 		/* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd.
1119 		 * If $HOME is not set or buffer too small to hold the pathname,
1120 		 * an error occurs.	- From RAND_file_name() man page.
1121 		 * The fact is that when $HOME is NULL, .rnd is used.
1122 		 */
1123 		randfile = RAND_file_name( buffer, sizeof( buffer ) );
1124 
1125 	} else if (RAND_egd(randfile) > 0) {
1126 		/* EGD socket */
1127 		return 0;
1128 	}
1129 
1130 	if (randfile == NULL) {
1131 		Debug( LDAP_DEBUG_ANY,
1132 			"TLS: Use configuration file or $RANDFILE to define seed PRNG\n",
1133 			0, 0, 0);
1134 		return -1;
1135 	}
1136 
1137 	total = RAND_load_file(randfile, -1);
1138 
1139 	if (RAND_status() == 0) {
1140 		Debug( LDAP_DEBUG_ANY,
1141 			"TLS: PRNG not been seeded with enough data\n",
1142 			0, 0, 0);
1143 		return -1;
1144 	}
1145 
1146 	/* assume if there was enough bits to seed that it's okay
1147 	 * to write derived bits to the file
1148 	 */
1149 	RAND_write_file(randfile);
1150 
1151 #endif
1152 
1153 	return 0;
1154 }
1155 
1156 struct dhinfo {
1157 	int keylength;
1158 	const char *pem;
1159 	size_t size;
1160 };
1161 
1162 
1163 /* From the OpenSSL 0.9.7 distro */
1164 static const char tlso_dhpem512[] =
1165 "-----BEGIN DH PARAMETERS-----\n\
1166 MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn\n\
1167 a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC\n\
1168 -----END DH PARAMETERS-----\n";
1169 
1170 static const char tlso_dhpem1024[] =
1171 "-----BEGIN DH PARAMETERS-----\n\
1172 MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq\n\
1173 /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx\n\
1174 /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC\n\
1175 -----END DH PARAMETERS-----\n";
1176 
1177 static const char tlso_dhpem2048[] =
1178 "-----BEGIN DH PARAMETERS-----\n\
1179 MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o\n\
1180 AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh\n\
1181 z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo\n\
1182 pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW\n\
1183 aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA\n\
1184 Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg==\n\
1185 -----END DH PARAMETERS-----\n";
1186 
1187 static const char tlso_dhpem4096[] =
1188 "-----BEGIN DH PARAMETERS-----\n\
1189 MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7\n\
1190 vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H\n\
1191 TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF\n\
1192 bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1\n\
1193 rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE\n\
1194 EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9\n\
1195 bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3\n\
1196 W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH\n\
1197 ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb\n\
1198 NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR\n\
1199 jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI=\n\
1200 -----END DH PARAMETERS-----\n";
1201 
1202 static const struct dhinfo tlso_dhpem[] = {
1203 	{ 512, tlso_dhpem512, sizeof(tlso_dhpem512) },
1204 	{ 1024, tlso_dhpem1024, sizeof(tlso_dhpem1024) },
1205 	{ 2048, tlso_dhpem2048, sizeof(tlso_dhpem2048) },
1206 	{ 4096, tlso_dhpem4096, sizeof(tlso_dhpem4096) },
1207 	{ 0, NULL, 0 }
1208 };
1209 
1210 static DH *
1211 tlso_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
1212 {
1213 	struct dhplist *p = NULL;
1214 	BIO *b = NULL;
1215 	DH *dh = NULL;
1216 	int i;
1217 
1218 	/* Do we have params of this length already? */
1219 #ifdef LDAP_R_COMPILE
1220 	ldap_pvt_thread_mutex_lock( &tlso_dh_mutex );
1221 #endif
1222 	for ( p = tlso_dhparams; p; p=p->next ) {
1223 		if ( p->keylength == key_length ) {
1224 #ifdef LDAP_R_COMPILE
1225 			ldap_pvt_thread_mutex_unlock( &tlso_dh_mutex );
1226 #endif
1227 			return p->param;
1228 		}
1229 	}
1230 
1231 	/* No - check for hardcoded params */
1232 
1233 	for (i=0; tlso_dhpem[i].keylength; i++) {
1234 		if ( tlso_dhpem[i].keylength == key_length ) {
1235 			b = BIO_new_mem_buf( (char *)tlso_dhpem[i].pem, tlso_dhpem[i].size );
1236 			break;
1237 		}
1238 	}
1239 
1240 	if ( b ) {
1241 		dh = PEM_read_bio_DHparams( b, NULL, NULL, NULL );
1242 		BIO_free( b );
1243 	}
1244 
1245 	/* Generating on the fly is expensive/slow... */
1246 	if ( !dh ) {
1247 		dh = DH_generate_parameters( key_length, DH_GENERATOR_2, NULL, NULL );
1248 	}
1249 	if ( dh ) {
1250 		p = LDAP_MALLOC( sizeof(struct dhplist) );
1251 		if ( p != NULL ) {
1252 			p->keylength = key_length;
1253 			p->param = dh;
1254 			p->next = tlso_dhparams;
1255 			tlso_dhparams = p;
1256 		}
1257 	}
1258 
1259 #ifdef LDAP_R_COMPILE
1260 	ldap_pvt_thread_mutex_unlock( &tlso_dh_mutex );
1261 #endif
1262 	return dh;
1263 }
1264 
1265 tls_impl ldap_int_tls_impl = {
1266 	"OpenSSL",
1267 
1268 	tlso_init,
1269 	tlso_destroy,
1270 
1271 	tlso_ctx_new,
1272 	tlso_ctx_ref,
1273 	tlso_ctx_free,
1274 	tlso_ctx_init,
1275 
1276 	tlso_session_new,
1277 	tlso_session_connect,
1278 	tlso_session_accept,
1279 	tlso_session_upflags,
1280 	tlso_session_errmsg,
1281 	tlso_session_my_dn,
1282 	tlso_session_peer_dn,
1283 	tlso_session_chkhost,
1284 	tlso_session_strength,
1285 
1286 	&tlso_sbio,
1287 
1288 #ifdef LDAP_R_COMPILE
1289 	tlso_thr_init,
1290 #else
1291 	NULL,
1292 #endif
1293 
1294 	0
1295 };
1296 
1297 #endif /* HAVE_OPENSSL */
1298