1/*	$NetBSD: tls_o.c,v 1.1.1.2 2010/12/12 15:21:40 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
56typedef SSL_CTX tlso_ctx;
57typedef SSL tlso_session;
58
59static int  tlso_opt_trace = 1;
60
61static void tlso_report_error( void );
62
63static void tlso_info_cb( const SSL *ssl, int where, int ret );
64static int tlso_verify_cb( int ok, X509_STORE_CTX *ctx );
65static int tlso_verify_ok( int ok, X509_STORE_CTX *ctx );
66static RSA * tlso_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
67
68static DH * tlso_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
69
70typedef struct dhplist {
71	struct dhplist *next;
72	int keylength;
73	DH *param;
74} dhplist;
75
76static dhplist *tlso_dhparams;
77
78static int tlso_seed_PRNG( const char *randfile );
79
80#ifdef LDAP_R_COMPILE
81/*
82 * provide mutexes for the OpenSSL library.
83 */
84static ldap_pvt_thread_mutex_t	tlso_mutexes[CRYPTO_NUM_LOCKS];
85static ldap_pvt_thread_mutex_t	tlso_dh_mutex;
86
87static 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
96static 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
109static 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
122static STACK_OF(X509_NAME) *
123tlso_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 */
151static int
152tlso_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 */
179static void
180tlso_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
194static tls_ctx *
195tlso_ctx_new( struct ldapoptions *lo )
196{
197	return (tls_ctx *) SSL_CTX_new( SSLv23_method() );
198}
199
200static void
201tlso_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
207static void
208tlso_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 */
217static int
218tlso_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
356static tls_session *
357tlso_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
363static int
364tlso_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
372static int
373tlso_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
381static int
382tlso_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
402static char *
403tlso_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
424static int
425tlso_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
442static X509 *
443tlso_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
452static int
453tlso_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
474static int
475tlso_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		{
616no_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
662static int
663tlso_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
676struct tls_data {
677	tlso_session		*session;
678	Sockbuf_IO_Desc		*sbiod;
679};
680
681static int
682tlso_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
690static int
691tlso_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
701static int
702tlso_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
728static int
729tlso_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
755static long
756tlso_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
765static int
766tlso_bio_gets( BIO *b, char *buf, int len )
767{
768	return -1;
769}
770
771static int
772tlso_bio_puts( BIO *b, const char *str )
773{
774	return tlso_bio_write( b, str, strlen( str ) );
775}
776
777static 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
790static int
791tlso_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
812static int
813tlso_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
827static int
828tlso_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
840static int
841tlso_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
863static ber_slen_t
864tlso_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
889static ber_slen_t
890tlso_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
916static 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 */
927static void
928tlso_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
991static int
992tlso_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
1045static int
1046tlso_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 */
1053static void
1054tlso_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
1078static RSA *
1079tlso_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
1109static int
1110tlso_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
1156struct dhinfo {
1157	int keylength;
1158	const char *pem;
1159	size_t size;
1160};
1161
1162
1163/* From the OpenSSL 0.9.7 distro */
1164static const char tlso_dhpem512[] =
1165"-----BEGIN DH PARAMETERS-----\n\
1166MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn\n\
1167a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC\n\
1168-----END DH PARAMETERS-----\n";
1169
1170static const char tlso_dhpem1024[] =
1171"-----BEGIN DH PARAMETERS-----\n\
1172MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq\n\
1173/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx\n\
1174/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC\n\
1175-----END DH PARAMETERS-----\n";
1176
1177static const char tlso_dhpem2048[] =
1178"-----BEGIN DH PARAMETERS-----\n\
1179MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o\n\
1180AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh\n\
1181z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo\n\
1182pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW\n\
1183aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA\n\
1184Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg==\n\
1185-----END DH PARAMETERS-----\n";
1186
1187static const char tlso_dhpem4096[] =
1188"-----BEGIN DH PARAMETERS-----\n\
1189MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7\n\
1190vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H\n\
1191TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF\n\
1192bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1\n\
1193rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE\n\
1194EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9\n\
1195bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3\n\
1196W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH\n\
1197ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb\n\
1198NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR\n\
1199jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI=\n\
1200-----END DH PARAMETERS-----\n";
1201
1202static 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
1210static DH *
1211tlso_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
1265tls_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