xref: /freebsd/contrib/sendmail/src/tls.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
140266059SGregory Neil Shapiro /*
25b0945b5SGregory Neil Shapiro  * Copyright (c) 2000-2006, 2008, 2009, 2011, 2013-2016 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *	All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  *
940266059SGregory Neil Shapiro  */
1040266059SGregory Neil Shapiro 
1140266059SGregory Neil Shapiro #include <sendmail.h>
1240266059SGregory Neil Shapiro 
134313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: tls.c,v 8.127 2013-11-27 02:51:11 gshapiro Exp $")
1440266059SGregory Neil Shapiro 
1540266059SGregory Neil Shapiro #if STARTTLS
1640266059SGregory Neil Shapiro # include <openssl/err.h>
1740266059SGregory Neil Shapiro # include <openssl/bio.h>
1840266059SGregory Neil Shapiro # include <openssl/pem.h>
1940266059SGregory Neil Shapiro # ifndef HASURANDOMDEV
2040266059SGregory Neil Shapiro #  include <openssl/rand.h>
215b0945b5SGregory Neil Shapiro # endif
225b0945b5SGregory Neil Shapiro # include <openssl/engine.h>
235b0945b5SGregory Neil Shapiro # if _FFR_TLS_ALTNAMES
245b0945b5SGregory Neil Shapiro #  include <openssl/x509v3.h>
255b0945b5SGregory Neil Shapiro # endif
262fb4f839SGregory Neil Shapiro # include <tls.h>
275b0945b5SGregory Neil Shapiro 
285b0945b5SGregory Neil Shapiro # if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER <= 0x00907000L
29*d39bd2c1SGregory Neil Shapiro #  error "OpenSSL versions <= 0x00907000L are unsupported."
30*d39bd2c1SGregory Neil Shapiro # endif
31*d39bd2c1SGregory Neil Shapiro 
32*d39bd2c1SGregory Neil Shapiro # if DANE && OPENSSL_VERSION_NUMBER == 0x30200000L
33*d39bd2c1SGregory Neil Shapiro #  error OpenSSL 3.2.0 has a bug related to DANE
34*d39bd2c1SGregory Neil Shapiro #  error see https://github.com/openssl/openssl/pull/22821
355b0945b5SGregory Neil Shapiro # endif
365b0945b5SGregory Neil Shapiro 
372fb4f839SGregory Neil Shapiro /*
382fb4f839SGregory Neil Shapiro **  *SSL version numbers:
39*d39bd2c1SGregory Neil Shapiro **  OpenSSL 0.9 - 1.1 (so far), 3.[012]
402fb4f839SGregory Neil Shapiro **  LibreSSL 2.0 (0x20000000L - part of "These will never change")
412fb4f839SGregory Neil Shapiro */
422fb4f839SGregory Neil Shapiro 
43*d39bd2c1SGregory Neil Shapiro # if (OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER < 0x20000000L) || OPENSSL_VERSION_NUMBER >= 0x30000000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL)
445b0945b5SGregory Neil Shapiro #  define MTA_HAVE_DH_set0_pqg 1
455b0945b5SGregory Neil Shapiro #  define MTA_HAVE_DSA_GENERATE_EX	1
465b0945b5SGregory Neil Shapiro #  define MTA_HAVE_OPENSSL_init_ssl	1
475b0945b5SGregory Neil Shapiro #  define MTA_ASN1_STRING_data ASN1_STRING_get0_data
485b0945b5SGregory Neil Shapiro #  include <openssl/bn.h>
495b0945b5SGregory Neil Shapiro #  include <openssl/dsa.h>
505b0945b5SGregory Neil Shapiro # else
515b0945b5SGregory Neil Shapiro #  define X509_STORE_CTX_get0_cert(ctx)	(ctx)->cert
525b0945b5SGregory Neil Shapiro #  define MTA_RSA_TMP_CB	1
535b0945b5SGregory Neil Shapiro #  define MTA_ASN1_STRING_data ASN1_STRING_data
545b0945b5SGregory Neil Shapiro # endif
555b0945b5SGregory Neil Shapiro 
56*d39bd2c1SGregory Neil Shapiro /* Is this ok or use HAVE_SSL_get1_peer_certificate instead? */
57*d39bd2c1SGregory Neil Shapiro #if OPENSSL_VERSION_NUMBER >= 0x30000000L
58*d39bd2c1SGregory Neil Shapiro # define MTA_SSL_get_peer_certificate SSL_get1_peer_certificate
59*d39bd2c1SGregory Neil Shapiro 
60*d39bd2c1SGregory Neil Shapiro # ifndef HAVE_ERR_get_error_all
61*d39bd2c1SGregory Neil Shapiro #  define HAVE_ERR_get_error_all 1
62*d39bd2c1SGregory Neil Shapiro # endif
63*d39bd2c1SGregory Neil Shapiro 
64*d39bd2c1SGregory Neil Shapiro /* use SSL_CTX_set_dh_auto()?  which versions provide it? */
65*d39bd2c1SGregory Neil Shapiro # define MTA_DH_AUTO	1
66*d39bd2c1SGregory Neil Shapiro #else
67*d39bd2c1SGregory Neil Shapiro # define MTA_SSL_get_peer_certificate SSL_get_peer_certificate
68*d39bd2c1SGregory Neil Shapiro # define MTA_DH_AUTO	0
69*d39bd2c1SGregory Neil Shapiro #endif
70*d39bd2c1SGregory Neil Shapiro 
71*d39bd2c1SGregory Neil Shapiro #if HAVE_ERR_get_error_all
72*d39bd2c1SGregory Neil Shapiro # define MTA_SSL_ERR_get(f, l, d, fl, fct) ERR_get_error_all(f, l, fct, d, fl)
73*d39bd2c1SGregory Neil Shapiro #else /* if HAVE_ERR_get_error_line_data ? */
74*d39bd2c1SGregory Neil Shapiro # define MTA_SSL_ERR_get(f, l, d, fl, fct) ERR_get_error_line_data(f, l, d, fl)
75*d39bd2c1SGregory Neil Shapiro #endif
76*d39bd2c1SGregory Neil Shapiro 
775b0945b5SGregory Neil Shapiro # if !TLS_NO_RSA && MTA_RSA_TMP_CB
7840266059SGregory Neil Shapiro static RSA *rsa_tmp = NULL;	/* temporary RSA key */
7940266059SGregory Neil Shapiro static RSA *tmp_rsa_key __P((SSL *, int, int));
805b0945b5SGregory Neil Shapiro # endif
81605302a5SGregory Neil Shapiro static int	tls_verify_cb __P((X509_STORE_CTX *, void *));
8240266059SGregory Neil Shapiro 
83e92d3f3fSGregory Neil Shapiro static int x509_verify_cb __P((int, X509_STORE_CTX *));
84e92d3f3fSGregory Neil Shapiro 
855b0945b5SGregory Neil Shapiro static void	apps_ssl_info_cb __P((const SSL *, int, int));
86b6bacd31SGregory Neil Shapiro static bool	tls_ok_f __P((char *, char *, int));
87b6bacd31SGregory Neil Shapiro static bool	tls_safe_f __P((char *, long, bool));
88da7d7b9cSGregory Neil Shapiro static int	tls_verify_log __P((int, X509_STORE_CTX *, const char *));
8940266059SGregory Neil Shapiro 
905b0945b5SGregory Neil Shapiro int TLSsslidx = -1;
9141451aa3SJung-uk Kim 
925b0945b5SGregory Neil Shapiro # if !NO_DH
935b0945b5SGregory Neil Shapiro # include <openssl/dh.h>
9440266059SGregory Neil Shapiro static DH *get_dh512 __P((void));
9540266059SGregory Neil Shapiro 
9640266059SGregory Neil Shapiro static unsigned char dh512_p[] =
9740266059SGregory Neil Shapiro {
9840266059SGregory Neil Shapiro 	0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
9940266059SGregory Neil Shapiro 	0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
10040266059SGregory Neil Shapiro 	0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
10140266059SGregory Neil Shapiro 	0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
10240266059SGregory Neil Shapiro 	0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
10340266059SGregory Neil Shapiro 	0x47,0x74,0xE8,0x33
10440266059SGregory Neil Shapiro };
10540266059SGregory Neil Shapiro static unsigned char dh512_g[] =
10640266059SGregory Neil Shapiro {
10740266059SGregory Neil Shapiro 	0x02
10840266059SGregory Neil Shapiro };
10940266059SGregory Neil Shapiro 
11040266059SGregory Neil Shapiro static DH *
get_dh512()11140266059SGregory Neil Shapiro get_dh512()
11240266059SGregory Neil Shapiro {
1135b0945b5SGregory Neil Shapiro 	DH *dh = NULL;
1145b0945b5SGregory Neil Shapiro #  if MTA_HAVE_DH_set0_pqg
11541451aa3SJung-uk Kim 	BIGNUM *dhp_bn, *dhg_bn;
1165b0945b5SGregory Neil Shapiro #  endif
11740266059SGregory Neil Shapiro 
1189f5609e9SJung-uk Kim 	if ((dh = DH_new()) == NULL)
119b7aeb266SJung-uk Kim 		return NULL;
1205b0945b5SGregory Neil Shapiro #  if MTA_HAVE_DH_set0_pqg
12141451aa3SJung-uk Kim 	dhp_bn = BN_bin2bn(dh512_p, sizeof (dh512_p), NULL);
12241451aa3SJung-uk Kim 	dhg_bn = BN_bin2bn(dh512_g, sizeof (dh512_g), NULL);
1235b0945b5SGregory Neil Shapiro 	if (dhp_bn == NULL || dhg_bn == NULL || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn))  {
1248c9735fbSJung-uk Kim 		DH_free(dh);
12541451aa3SJung-uk Kim 		BN_free(dhp_bn);
12641451aa3SJung-uk Kim 		BN_free(dhg_bn);
127a33b3343SJung-uk Kim 		return NULL;
12841451aa3SJung-uk Kim 	}
1295b0945b5SGregory Neil Shapiro #  else
1305b0945b5SGregory Neil Shapiro 	dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
1315b0945b5SGregory Neil Shapiro 	dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
1325b0945b5SGregory Neil Shapiro 	if ((dh->p == NULL) || (dh->g == NULL))
133a5f8e6f6SJung-uk Kim 	{
134a5f8e6f6SJung-uk Kim 		DH_free(dh);
135a5f8e6f6SJung-uk Kim 		return NULL;
136a5f8e6f6SJung-uk Kim 	}
1375b0945b5SGregory Neil Shapiro #  endif
1389f5609e9SJung-uk Kim 	return dh;
13940266059SGregory Neil Shapiro }
140da7d7b9cSGregory Neil Shapiro 
141da7d7b9cSGregory Neil Shapiro #  if 0
142da7d7b9cSGregory Neil Shapiro 
143da7d7b9cSGregory Neil Shapiro This is the data from which the C code has been generated:
144da7d7b9cSGregory Neil Shapiro 
145da7d7b9cSGregory Neil Shapiro -----BEGIN DH PARAMETERS-----
146da7d7b9cSGregory Neil Shapiro MIIBCAKCAQEArDcgcLpxEksQHPlolRKCUJ2szKRziseWV9cUSQNZGxoGw7KkROz4
147da7d7b9cSGregory Neil Shapiro HF9QSbg5axyNIG+QbZYtx0jp3l6/GWq1dLOj27yZkgYgaYgFrvKPiZ2jJ5xETQVH
148da7d7b9cSGregory Neil Shapiro UpZwbjRcyjyWkWYJVsx1aF4F/iY4kT0n/+iGEoimI3C9V3KXTJ2S6jIkyJ6M/CrN
149da7d7b9cSGregory Neil Shapiro EtrDynMlUMGlc7S1ouXVOTrtKeqy3S2L9eBLxVI+sChEijGIfELupdVeXihK006p
150da7d7b9cSGregory Neil Shapiro MgnABPDbkTx6OOtYmSZaGQX+OLW2FPmwvcrzgCz9t9cAsuUcBZv1LeHEqZZttyLU
151da7d7b9cSGregory Neil Shapiro oK0jjSXgFyeU4/NfyA+zuNeWzUL6bHmigwIBAg==
152da7d7b9cSGregory Neil Shapiro -----END DH PARAMETERS-----
153da7d7b9cSGregory Neil Shapiro #  endif /* 0 */
154da7d7b9cSGregory Neil Shapiro 
155da7d7b9cSGregory Neil Shapiro static DH *
156da7d7b9cSGregory Neil Shapiro get_dh2048()
157da7d7b9cSGregory Neil Shapiro {
158da7d7b9cSGregory Neil Shapiro 	static unsigned char dh2048_p[]={
159da7d7b9cSGregory Neil Shapiro 		0xAC,0x37,0x20,0x70,0xBA,0x71,0x12,0x4B,0x10,0x1C,0xF9,0x68,
160da7d7b9cSGregory Neil Shapiro 		0x95,0x12,0x82,0x50,0x9D,0xAC,0xCC,0xA4,0x73,0x8A,0xC7,0x96,
161da7d7b9cSGregory Neil Shapiro 		0x57,0xD7,0x14,0x49,0x03,0x59,0x1B,0x1A,0x06,0xC3,0xB2,0xA4,
162da7d7b9cSGregory Neil Shapiro 		0x44,0xEC,0xF8,0x1C,0x5F,0x50,0x49,0xB8,0x39,0x6B,0x1C,0x8D,
163da7d7b9cSGregory Neil Shapiro 		0x20,0x6F,0x90,0x6D,0x96,0x2D,0xC7,0x48,0xE9,0xDE,0x5E,0xBF,
164da7d7b9cSGregory Neil Shapiro 		0x19,0x6A,0xB5,0x74,0xB3,0xA3,0xDB,0xBC,0x99,0x92,0x06,0x20,
165da7d7b9cSGregory Neil Shapiro 		0x69,0x88,0x05,0xAE,0xF2,0x8F,0x89,0x9D,0xA3,0x27,0x9C,0x44,
166da7d7b9cSGregory Neil Shapiro 		0x4D,0x05,0x47,0x52,0x96,0x70,0x6E,0x34,0x5C,0xCA,0x3C,0x96,
167da7d7b9cSGregory Neil Shapiro 		0x91,0x66,0x09,0x56,0xCC,0x75,0x68,0x5E,0x05,0xFE,0x26,0x38,
168da7d7b9cSGregory Neil Shapiro 		0x91,0x3D,0x27,0xFF,0xE8,0x86,0x12,0x88,0xA6,0x23,0x70,0xBD,
169da7d7b9cSGregory Neil Shapiro 		0x57,0x72,0x97,0x4C,0x9D,0x92,0xEA,0x32,0x24,0xC8,0x9E,0x8C,
170da7d7b9cSGregory Neil Shapiro 		0xFC,0x2A,0xCD,0x12,0xDA,0xC3,0xCA,0x73,0x25,0x50,0xC1,0xA5,
171da7d7b9cSGregory Neil Shapiro 		0x73,0xB4,0xB5,0xA2,0xE5,0xD5,0x39,0x3A,0xED,0x29,0xEA,0xB2,
172da7d7b9cSGregory Neil Shapiro 		0xDD,0x2D,0x8B,0xF5,0xE0,0x4B,0xC5,0x52,0x3E,0xB0,0x28,0x44,
173da7d7b9cSGregory Neil Shapiro 		0x8A,0x31,0x88,0x7C,0x42,0xEE,0xA5,0xD5,0x5E,0x5E,0x28,0x4A,
174da7d7b9cSGregory Neil Shapiro 		0xD3,0x4E,0xA9,0x32,0x09,0xC0,0x04,0xF0,0xDB,0x91,0x3C,0x7A,
175da7d7b9cSGregory Neil Shapiro 		0x38,0xEB,0x58,0x99,0x26,0x5A,0x19,0x05,0xFE,0x38,0xB5,0xB6,
176da7d7b9cSGregory Neil Shapiro 		0x14,0xF9,0xB0,0xBD,0xCA,0xF3,0x80,0x2C,0xFD,0xB7,0xD7,0x00,
177da7d7b9cSGregory Neil Shapiro 		0xB2,0xE5,0x1C,0x05,0x9B,0xF5,0x2D,0xE1,0xC4,0xA9,0x96,0x6D,
178da7d7b9cSGregory Neil Shapiro 		0xB7,0x22,0xD4,0xA0,0xAD,0x23,0x8D,0x25,0xE0,0x17,0x27,0x94,
179da7d7b9cSGregory Neil Shapiro 		0xE3,0xF3,0x5F,0xC8,0x0F,0xB3,0xB8,0xD7,0x96,0xCD,0x42,0xFA,
180da7d7b9cSGregory Neil Shapiro 		0x6C,0x79,0xA2,0x83,
181da7d7b9cSGregory Neil Shapiro 		};
182da7d7b9cSGregory Neil Shapiro 	static unsigned char dh2048_g[]={ 0x02, };
183da7d7b9cSGregory Neil Shapiro 	DH *dh;
1845b0945b5SGregory Neil Shapiro #  if MTA_HAVE_DH_set0_pqg
18541451aa3SJung-uk Kim 	BIGNUM *dhp_bn, *dhg_bn;
1865b0945b5SGregory Neil Shapiro #  endif
187da7d7b9cSGregory Neil Shapiro 
1889f5609e9SJung-uk Kim 	if ((dh=DH_new()) == NULL)
1895b0945b5SGregory Neil Shapiro 		return(NULL);
1905b0945b5SGregory Neil Shapiro #  if MTA_HAVE_DH_set0_pqg
19141451aa3SJung-uk Kim 	dhp_bn = BN_bin2bn(dh2048_p, sizeof (dh2048_p), NULL);
19241451aa3SJung-uk Kim 	dhg_bn = BN_bin2bn(dh2048_g, sizeof (dh2048_g), NULL);
1935b0945b5SGregory Neil Shapiro 	if (dhp_bn == NULL || dhg_bn == NULL || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn))  {
1948c9735fbSJung-uk Kim 		DH_free(dh);
19541451aa3SJung-uk Kim 		BN_free(dhp_bn);
19641451aa3SJung-uk Kim 		BN_free(dhg_bn);
197a33b3343SJung-uk Kim 		return NULL;
1989f5609e9SJung-uk Kim 	}
1995b0945b5SGregory Neil Shapiro #  else
2005b0945b5SGregory Neil Shapiro 	dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
2015b0945b5SGregory Neil Shapiro 	dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
2025b0945b5SGregory Neil Shapiro 	if ((dh->p == NULL) || (dh->g == NULL))
203a5f8e6f6SJung-uk Kim 	{
204a5f8e6f6SJung-uk Kim 		DH_free(dh);
2055b0945b5SGregory Neil Shapiro 		return(NULL);
206a5f8e6f6SJung-uk Kim 	}
2075b0945b5SGregory Neil Shapiro #  endif
2085b0945b5SGregory Neil Shapiro 	return(dh);
209da7d7b9cSGregory Neil Shapiro }
21040266059SGregory Neil Shapiro # endif /* !NO_DH */
21140266059SGregory Neil Shapiro 
21240266059SGregory Neil Shapiro /*
21340266059SGregory Neil Shapiro **  TLS_RAND_INIT -- initialize STARTTLS random generator
21440266059SGregory Neil Shapiro **
21540266059SGregory Neil Shapiro **	Parameters:
21640266059SGregory Neil Shapiro **		randfile -- name of file with random data
21740266059SGregory Neil Shapiro **		logl -- loglevel
21840266059SGregory Neil Shapiro **
21940266059SGregory Neil Shapiro **	Returns:
22040266059SGregory Neil Shapiro **		success/failure
22140266059SGregory Neil Shapiro **
22240266059SGregory Neil Shapiro **	Side Effects:
22340266059SGregory Neil Shapiro **		initializes PRNG for tls library.
22440266059SGregory Neil Shapiro */
22540266059SGregory Neil Shapiro 
22640266059SGregory Neil Shapiro # define MIN_RAND_BYTES	128	/* 1024 bits */
22740266059SGregory Neil Shapiro 
22840266059SGregory Neil Shapiro # define RF_OK		0	/* randfile OK */
22940266059SGregory Neil Shapiro # define RF_MISS	1	/* randfile == NULL || *randfile == '\0' */
23040266059SGregory Neil Shapiro # define RF_UNKNOWN	2	/* unknown prefix for randfile */
23140266059SGregory Neil Shapiro 
23240266059SGregory Neil Shapiro # define RI_NONE	0	/* no init yet */
23340266059SGregory Neil Shapiro # define RI_SUCCESS	1	/* init was successful */
23440266059SGregory Neil Shapiro # define RI_FAIL	2	/* init failed */
23540266059SGregory Neil Shapiro 
23640266059SGregory Neil Shapiro static bool	tls_rand_init __P((char *, int));
23740266059SGregory Neil Shapiro 
23840266059SGregory Neil Shapiro static bool
23940266059SGregory Neil Shapiro tls_rand_init(randfile, logl)
24040266059SGregory Neil Shapiro 	char *randfile;
24140266059SGregory Neil Shapiro 	int logl;
24240266059SGregory Neil Shapiro {
24340266059SGregory Neil Shapiro # ifndef HASURANDOMDEV
24440266059SGregory Neil Shapiro 	/* not required if /dev/urandom exists, OpenSSL does it internally */
24540266059SGregory Neil Shapiro 
24640266059SGregory Neil Shapiro 	bool ok;
24740266059SGregory Neil Shapiro 	int randdef;
24840266059SGregory Neil Shapiro 	static int done = RI_NONE;
24940266059SGregory Neil Shapiro 
25040266059SGregory Neil Shapiro 	/*
25140266059SGregory Neil Shapiro 	**  initialize PRNG
25240266059SGregory Neil Shapiro 	*/
25340266059SGregory Neil Shapiro 
25440266059SGregory Neil Shapiro 	/* did we try this before? if yes: return old value */
25540266059SGregory Neil Shapiro 	if (done != RI_NONE)
25640266059SGregory Neil Shapiro 		return done == RI_SUCCESS;
25740266059SGregory Neil Shapiro 
25840266059SGregory Neil Shapiro 	/* set default values */
25940266059SGregory Neil Shapiro 	ok = false;
26040266059SGregory Neil Shapiro 	done = RI_FAIL;
2612fb4f839SGregory Neil Shapiro 	randdef = (SM_IS_EMPTY(randfile)) ? RF_MISS : RF_OK;
26240266059SGregory Neil Shapiro #  if EGD
26340266059SGregory Neil Shapiro 	if (randdef == RF_OK && sm_strncasecmp(randfile, "egd:", 4) == 0)
26440266059SGregory Neil Shapiro 	{
26540266059SGregory Neil Shapiro 		randfile += 4;
26640266059SGregory Neil Shapiro 		if (RAND_egd(randfile) < 0)
26740266059SGregory Neil Shapiro 		{
26840266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
26940266059SGregory Neil Shapiro 				  "STARTTLS: RAND_egd(%s) failed: random number generator not seeded",
27040266059SGregory Neil Shapiro 				   randfile);
27140266059SGregory Neil Shapiro 		}
27240266059SGregory Neil Shapiro 		else
27340266059SGregory Neil Shapiro 			ok = true;
27440266059SGregory Neil Shapiro 	}
27540266059SGregory Neil Shapiro 	else
27640266059SGregory Neil Shapiro #  endif /* EGD */
2772fb4f839SGregory Neil Shapiro 	/* "else" in #if code above */
27840266059SGregory Neil Shapiro 	if (randdef == RF_OK && sm_strncasecmp(randfile, "file:", 5) == 0)
27940266059SGregory Neil Shapiro 	{
28040266059SGregory Neil Shapiro 		int fd;
28140266059SGregory Neil Shapiro 		long sff;
28240266059SGregory Neil Shapiro 		struct stat st;
28340266059SGregory Neil Shapiro 
28440266059SGregory Neil Shapiro 		randfile += 5;
28540266059SGregory Neil Shapiro 		sff = SFF_SAFEDIRPATH | SFF_NOWLINK
28640266059SGregory Neil Shapiro 		      | SFF_NOGWFILES | SFF_NOWWFILES
28740266059SGregory Neil Shapiro 		      | SFF_NOGRFILES | SFF_NOWRFILES
28840266059SGregory Neil Shapiro 		      | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT;
289605302a5SGregory Neil Shapiro 		if (DontLockReadFiles)
290605302a5SGregory Neil Shapiro 			sff |= SFF_NOLOCK;
29140266059SGregory Neil Shapiro 		if ((fd = safeopen(randfile, O_RDONLY, 0, sff)) >= 0)
29240266059SGregory Neil Shapiro 		{
29340266059SGregory Neil Shapiro 			if (fstat(fd, &st) < 0)
29440266059SGregory Neil Shapiro 			{
29540266059SGregory Neil Shapiro 				if (LogLevel > logl)
29640266059SGregory Neil Shapiro 					sm_syslog(LOG_ERR, NOQID,
29740266059SGregory Neil Shapiro 						  "STARTTLS: can't fstat(%s)",
29840266059SGregory Neil Shapiro 						  randfile);
29940266059SGregory Neil Shapiro 			}
30040266059SGregory Neil Shapiro 			else
30140266059SGregory Neil Shapiro 			{
30240266059SGregory Neil Shapiro 				bool use, problem;
30340266059SGregory Neil Shapiro 
30440266059SGregory Neil Shapiro 				use = true;
30540266059SGregory Neil Shapiro 				problem = false;
30640266059SGregory Neil Shapiro 
30740266059SGregory Neil Shapiro 				/* max. age of file: 10 minutes */
30840266059SGregory Neil Shapiro 				if (st.st_mtime + 600 < curtime())
30940266059SGregory Neil Shapiro 				{
31040266059SGregory Neil Shapiro 					use = bitnset(DBS_INSUFFICIENTENTROPY,
31140266059SGregory Neil Shapiro 						      DontBlameSendmail);
31240266059SGregory Neil Shapiro 					problem = true;
31340266059SGregory Neil Shapiro 					if (LogLevel > logl)
31440266059SGregory Neil Shapiro 						sm_syslog(LOG_ERR, NOQID,
31540266059SGregory Neil Shapiro 							  "STARTTLS: RandFile %s too old: %s",
31640266059SGregory Neil Shapiro 							  randfile,
31740266059SGregory Neil Shapiro 							  use ? "unsafe" :
31840266059SGregory Neil Shapiro 								"unusable");
31940266059SGregory Neil Shapiro 				}
32040266059SGregory Neil Shapiro 				if (use && st.st_size < MIN_RAND_BYTES)
32140266059SGregory Neil Shapiro 				{
32240266059SGregory Neil Shapiro 					use = bitnset(DBS_INSUFFICIENTENTROPY,
32340266059SGregory Neil Shapiro 						      DontBlameSendmail);
32440266059SGregory Neil Shapiro 					problem = true;
32540266059SGregory Neil Shapiro 					if (LogLevel > logl)
32640266059SGregory Neil Shapiro 						sm_syslog(LOG_ERR, NOQID,
32740266059SGregory Neil Shapiro 							  "STARTTLS: size(%s) < %d: %s",
32840266059SGregory Neil Shapiro 							  randfile,
32940266059SGregory Neil Shapiro 							  MIN_RAND_BYTES,
33040266059SGregory Neil Shapiro 							  use ? "unsafe" :
33140266059SGregory Neil Shapiro 								"unusable");
33240266059SGregory Neil Shapiro 				}
33340266059SGregory Neil Shapiro 				if (use)
33440266059SGregory Neil Shapiro 					ok = RAND_load_file(randfile, -1) >=
33540266059SGregory Neil Shapiro 					     MIN_RAND_BYTES;
33640266059SGregory Neil Shapiro 				if (use && !ok)
33740266059SGregory Neil Shapiro 				{
33840266059SGregory Neil Shapiro 					if (LogLevel > logl)
33940266059SGregory Neil Shapiro 						sm_syslog(LOG_WARNING, NOQID,
34040266059SGregory Neil Shapiro 							  "STARTTLS: RAND_load_file(%s) failed: random number generator not seeded",
34140266059SGregory Neil Shapiro 							  randfile);
34240266059SGregory Neil Shapiro 				}
34340266059SGregory Neil Shapiro 				if (problem)
34440266059SGregory Neil Shapiro 					ok = false;
34540266059SGregory Neil Shapiro 			}
34640266059SGregory Neil Shapiro 			if (ok || bitnset(DBS_INSUFFICIENTENTROPY,
34740266059SGregory Neil Shapiro 					  DontBlameSendmail))
34840266059SGregory Neil Shapiro 			{
34940266059SGregory Neil Shapiro 				/* add this even if fstat() failed */
350d0cef73dSGregory Neil Shapiro 				RAND_seed((void *) &st, sizeof(st));
35140266059SGregory Neil Shapiro 			}
35240266059SGregory Neil Shapiro 			(void) close(fd);
35340266059SGregory Neil Shapiro 		}
35440266059SGregory Neil Shapiro 		else
35540266059SGregory Neil Shapiro 		{
35640266059SGregory Neil Shapiro 			if (LogLevel > logl)
35740266059SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
35840266059SGregory Neil Shapiro 					  "STARTTLS: Warning: safeopen(%s) failed",
35940266059SGregory Neil Shapiro 					  randfile);
36040266059SGregory Neil Shapiro 		}
36140266059SGregory Neil Shapiro 	}
36240266059SGregory Neil Shapiro 	else if (randdef == RF_OK)
36340266059SGregory Neil Shapiro 	{
36440266059SGregory Neil Shapiro 		if (LogLevel > logl)
36540266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
36640266059SGregory Neil Shapiro 				  "STARTTLS: Error: no proper random file definition %s",
36740266059SGregory Neil Shapiro 				  randfile);
36840266059SGregory Neil Shapiro 		randdef = RF_UNKNOWN;
36940266059SGregory Neil Shapiro 	}
37040266059SGregory Neil Shapiro 	if (randdef == RF_MISS)
37140266059SGregory Neil Shapiro 	{
37240266059SGregory Neil Shapiro 		if (LogLevel > logl)
37340266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
37440266059SGregory Neil Shapiro 				  "STARTTLS: Error: missing random file definition");
37540266059SGregory Neil Shapiro 	}
37640266059SGregory Neil Shapiro 	if (!ok && bitnset(DBS_INSUFFICIENTENTROPY, DontBlameSendmail))
37740266059SGregory Neil Shapiro 	{
37840266059SGregory Neil Shapiro 		int i;
37940266059SGregory Neil Shapiro 		long r;
38040266059SGregory Neil Shapiro 		unsigned char buf[MIN_RAND_BYTES];
38140266059SGregory Neil Shapiro 
38240266059SGregory Neil Shapiro 		/* assert((MIN_RAND_BYTES % sizeof(long)) == 0); */
38340266059SGregory Neil Shapiro 		for (i = 0; i <= sizeof(buf) - sizeof(long); i += sizeof(long))
38440266059SGregory Neil Shapiro 		{
38540266059SGregory Neil Shapiro 			r = get_random();
38640266059SGregory Neil Shapiro 			(void) memcpy(buf + i, (void *) &r, sizeof(long));
38740266059SGregory Neil Shapiro 		}
388d0cef73dSGregory Neil Shapiro 		RAND_seed(buf, sizeof(buf));
38940266059SGregory Neil Shapiro 		if (LogLevel > logl)
39040266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
39140266059SGregory Neil Shapiro 				  "STARTTLS: Warning: random number generator not properly seeded");
39240266059SGregory Neil Shapiro 		ok = true;
39340266059SGregory Neil Shapiro 	}
39440266059SGregory Neil Shapiro 	done = ok ? RI_SUCCESS : RI_FAIL;
39540266059SGregory Neil Shapiro 	return ok;
39640266059SGregory Neil Shapiro # else /* ! HASURANDOMDEV */
39740266059SGregory Neil Shapiro 	return true;
39840266059SGregory Neil Shapiro # endif /* ! HASURANDOMDEV */
39940266059SGregory Neil Shapiro }
400*d39bd2c1SGregory Neil Shapiro 
40140266059SGregory Neil Shapiro /*
40240266059SGregory Neil Shapiro **  INIT_TLS_LIBRARY -- Calls functions which set up TLS library for global use.
40340266059SGregory Neil Shapiro **
40440266059SGregory Neil Shapiro **	Parameters:
405552d4955SGregory Neil Shapiro **		fipsmode -- use FIPS?
40640266059SGregory Neil Shapiro **
40740266059SGregory Neil Shapiro **	Returns:
4085b0945b5SGregory Neil Shapiro **		0: OK
4095b0945b5SGregory Neil Shapiro **		<0: perm.fail
4105b0945b5SGregory Neil Shapiro **		>0: fail but can continue
41140266059SGregory Neil Shapiro */
41240266059SGregory Neil Shapiro 
4135b0945b5SGregory Neil Shapiro int
414552d4955SGregory Neil Shapiro init_tls_library(fipsmode)
415552d4955SGregory Neil Shapiro 	bool fipsmode;
41640266059SGregory Neil Shapiro {
417552d4955SGregory Neil Shapiro 	bool bv;
418552d4955SGregory Neil Shapiro 
419*d39bd2c1SGregory Neil Shapiro # if _FFR_FIPSMODE
420*d39bd2c1SGregory Neil Shapiro 	if (fipsmode && CertFingerprintAlgorithm == NULL)
421*d39bd2c1SGregory Neil Shapiro 		CertFingerprintAlgorithm = "sha1";
422*d39bd2c1SGregory Neil Shapiro #  if OPENSSL_VERSION_NUMBER >= 0x30000000L
423*d39bd2c1SGregory Neil Shapiro 	if (LogLevel > 12)
424*d39bd2c1SGregory Neil Shapiro 		sm_syslog(LOG_DEBUG, NOQID,
425*d39bd2c1SGregory Neil Shapiro 			"fipsmode=%d, evp_is_FIPS=%d", fipsmode,
426*d39bd2c1SGregory Neil Shapiro 			EVP_default_properties_is_fips_enabled(NULL));
427*d39bd2c1SGregory Neil Shapiro #  endif
428*d39bd2c1SGregory Neil Shapiro # endif /* _FFR_FIPSMODE  */
429*d39bd2c1SGregory Neil Shapiro 
4305b0945b5SGregory Neil Shapiro 	/*
4315b0945b5SGregory Neil Shapiro 	**  OPENSSL_init_ssl(3): "As of version 1.1.0 OpenSSL will
4325b0945b5SGregory Neil Shapiro 	**  automatically allocate all resources that it needs
4335b0945b5SGregory Neil Shapiro 	**  so no explicit initialisation is required."
4345b0945b5SGregory Neil Shapiro 	*/
4355b0945b5SGregory Neil Shapiro 
4365b0945b5SGregory Neil Shapiro # if !MTA_HAVE_OPENSSL_init_ssl
43740266059SGregory Neil Shapiro 	/* basic TLS initialization, ignore result for now */
43840266059SGregory Neil Shapiro 	SSL_library_init();
43940266059SGregory Neil Shapiro 	SSL_load_error_strings();
4405dd76dd0SGregory Neil Shapiro 	OpenSSL_add_all_algorithms();
4415b0945b5SGregory Neil Shapiro # endif
44240266059SGregory Neil Shapiro 
4435b0945b5SGregory Neil Shapiro 	bv = true;
4445b0945b5SGregory Neil Shapiro 	if (TLSsslidx < 0)
4455b0945b5SGregory Neil Shapiro 	{
4465b0945b5SGregory Neil Shapiro 		TLSsslidx = SSL_get_ex_new_index(0, 0, 0, 0, 0);
4475b0945b5SGregory Neil Shapiro 		if (TLSsslidx < 0)
4485b0945b5SGregory Neil Shapiro 		{
4495b0945b5SGregory Neil Shapiro 			if (LogLevel > 0)
4505b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
4515b0945b5SGregory Neil Shapiro 					"STARTTLS=init, SSL_get_ex_new_index=%d",
4525b0945b5SGregory Neil Shapiro 					TLSsslidx);
4535b0945b5SGregory Neil Shapiro 			bv = false;
4545b0945b5SGregory Neil Shapiro 		}
4555b0945b5SGregory Neil Shapiro 	}
4565b0945b5SGregory Neil Shapiro 
4575b0945b5SGregory Neil Shapiro 	if (bv)
458552d4955SGregory Neil Shapiro 		bv = tls_rand_init(RandFile, 7);
459*d39bd2c1SGregory Neil Shapiro # if _FFR_FIPSMODE && OPENSSL_VERSION_NUMBER < 0x30000000L
460552d4955SGregory Neil Shapiro 	if (bv && fipsmode)
461552d4955SGregory Neil Shapiro 	{
462552d4955SGregory Neil Shapiro 		if (!FIPS_mode_set(1))
463552d4955SGregory Neil Shapiro 		{
464552d4955SGregory Neil Shapiro 			unsigned long err;
465552d4955SGregory Neil Shapiro 
466552d4955SGregory Neil Shapiro 			err = ERR_get_error();
467552d4955SGregory Neil Shapiro 			if (LogLevel > 0)
468552d4955SGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
469552d4955SGregory Neil Shapiro 					"STARTTLS=init, FIPSMode=%s",
470552d4955SGregory Neil Shapiro 					ERR_error_string(err, NULL));
4715b0945b5SGregory Neil Shapiro 			return -1;
472552d4955SGregory Neil Shapiro 		}
473*d39bd2c1SGregory Neil Shapiro 		else if (LogLevel > 9)
474552d4955SGregory Neil Shapiro 		{
475552d4955SGregory Neil Shapiro 			sm_syslog(LOG_INFO, NOQID,
476552d4955SGregory Neil Shapiro 				"STARTTLS=init, FIPSMode=ok");
477552d4955SGregory Neil Shapiro 		}
478552d4955SGregory Neil Shapiro 	}
479*d39bd2c1SGregory Neil Shapiro # endif /* _FFR_FIPSMODE && OPENSSL_VERSION_NUMBER < 0x30000000L */
4805b0945b5SGregory Neil Shapiro 
4815b0945b5SGregory Neil Shapiro 	if (!TLS_set_engine(SSLEngine, true))
4825b0945b5SGregory Neil Shapiro 	{
4835b0945b5SGregory Neil Shapiro 		if (LogLevel > 0)
4845b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID,
4855b0945b5SGregory Neil Shapiro 				  "STARTTLS=init, engine=%s, TLS_set_engine=failed",
4865b0945b5SGregory Neil Shapiro 				  SSLEngine);
4875b0945b5SGregory Neil Shapiro 		return -1;
4885b0945b5SGregory Neil Shapiro 	}
4895b0945b5SGregory Neil Shapiro 
490da7d7b9cSGregory Neil Shapiro 	if (bv && CertFingerprintAlgorithm != NULL)
491da7d7b9cSGregory Neil Shapiro 	{
492da7d7b9cSGregory Neil Shapiro 		const EVP_MD *md;
493da7d7b9cSGregory Neil Shapiro 
494da7d7b9cSGregory Neil Shapiro 		md = EVP_get_digestbyname(CertFingerprintAlgorithm);
495da7d7b9cSGregory Neil Shapiro 		if (NULL == md)
496da7d7b9cSGregory Neil Shapiro 		{
497da7d7b9cSGregory Neil Shapiro 			bv = false;
498da7d7b9cSGregory Neil Shapiro 			if (LogLevel > 0)
499da7d7b9cSGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
500da7d7b9cSGregory Neil Shapiro 					"STARTTLS=init, CertFingerprintAlgorithm=%s, status=invalid"
501da7d7b9cSGregory Neil Shapiro 					, CertFingerprintAlgorithm);
502da7d7b9cSGregory Neil Shapiro 		}
503da7d7b9cSGregory Neil Shapiro 		else
504da7d7b9cSGregory Neil Shapiro 			EVP_digest = md;
505da7d7b9cSGregory Neil Shapiro 	}
5065b0945b5SGregory Neil Shapiro 	return bv ? 0 : 1;
50740266059SGregory Neil Shapiro }
508da7d7b9cSGregory Neil Shapiro 
50940266059SGregory Neil Shapiro /*
51040266059SGregory Neil Shapiro **  TLS_SET_VERIFY -- request client certificate?
51140266059SGregory Neil Shapiro **
51240266059SGregory Neil Shapiro **	Parameters:
51340266059SGregory Neil Shapiro **		ctx -- TLS context
5145b0945b5SGregory Neil Shapiro **		ssl -- TLS session context
515da7d7b9cSGregory Neil Shapiro **		vrfy -- request certificate?
51640266059SGregory Neil Shapiro **
51740266059SGregory Neil Shapiro **	Returns:
51840266059SGregory Neil Shapiro **		none.
51940266059SGregory Neil Shapiro **
52040266059SGregory Neil Shapiro **	Side Effects:
52140266059SGregory Neil Shapiro **		Sets verification state for TLS
52240266059SGregory Neil Shapiro **
52340266059SGregory Neil Shapiro # if TLS_VRFY_PER_CTX
52440266059SGregory Neil Shapiro **	Notice:
52540266059SGregory Neil Shapiro **		This is per TLS context, not per TLS structure;
52640266059SGregory Neil Shapiro **		the former is global, the latter per connection.
52740266059SGregory Neil Shapiro **		It would be nice to do this per connection, but this
52840266059SGregory Neil Shapiro **		doesn't work in the current TLS libraries :-(
52940266059SGregory Neil Shapiro # endif * TLS_VRFY_PER_CTX *
53040266059SGregory Neil Shapiro */
53140266059SGregory Neil Shapiro 
53240266059SGregory Neil Shapiro void
53340266059SGregory Neil Shapiro tls_set_verify(ctx, ssl, vrfy)
53440266059SGregory Neil Shapiro 	SSL_CTX *ctx;
53540266059SGregory Neil Shapiro 	SSL *ssl;
53640266059SGregory Neil Shapiro 	bool vrfy;
53740266059SGregory Neil Shapiro {
53840266059SGregory Neil Shapiro # if !TLS_VRFY_PER_CTX
53940266059SGregory Neil Shapiro 	SSL_set_verify(ssl, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
5405b0945b5SGregory Neil Shapiro # else
54140266059SGregory Neil Shapiro 	SSL_CTX_set_verify(ctx, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,
54240266059SGregory Neil Shapiro 			NULL);
5435b0945b5SGregory Neil Shapiro # endif
54440266059SGregory Neil Shapiro }
54540266059SGregory Neil Shapiro 
54640266059SGregory Neil Shapiro /*
54740266059SGregory Neil Shapiro **  status in initialization
54840266059SGregory Neil Shapiro **  these flags keep track of the status of the initialization
54940266059SGregory Neil Shapiro **  i.e., whether a file exists (_EX) and whether it can be used (_OK)
55040266059SGregory Neil Shapiro **  [due to permissions]
55140266059SGregory Neil Shapiro */
55240266059SGregory Neil Shapiro 
55340266059SGregory Neil Shapiro # define TLS_S_NONE	0x00000000	/* none yet */
55413bd1963SGregory Neil Shapiro # define TLS_S_CERT_EX	0x00000001	/* cert file exists */
55513bd1963SGregory Neil Shapiro # define TLS_S_CERT_OK	0x00000002	/* cert file is ok */
55613bd1963SGregory Neil Shapiro # define TLS_S_KEY_EX	0x00000004	/* key file exists */
55713bd1963SGregory Neil Shapiro # define TLS_S_KEY_OK	0x00000008	/* key file is ok */
55813bd1963SGregory Neil Shapiro # define TLS_S_CERTP_EX	0x00000010	/* CA cert path exists */
55913bd1963SGregory Neil Shapiro # define TLS_S_CERTP_OK	0x00000020	/* CA cert path is ok */
56013bd1963SGregory Neil Shapiro # define TLS_S_CERTF_EX	0x00000040	/* CA cert file exists */
56113bd1963SGregory Neil Shapiro # define TLS_S_CERTF_OK	0x00000080	/* CA cert file is ok */
562e92d3f3fSGregory Neil Shapiro # define TLS_S_CRLF_EX	0x00000100	/* CRL file exists */
563e92d3f3fSGregory Neil Shapiro # define TLS_S_CRLF_OK	0x00000200	/* CRL file is ok */
56440266059SGregory Neil Shapiro 
56513bd1963SGregory Neil Shapiro # define TLS_S_CERT2_EX	0x00001000	/* 2nd cert file exists */
56613bd1963SGregory Neil Shapiro # define TLS_S_CERT2_OK	0x00002000	/* 2nd cert file is ok */
56713bd1963SGregory Neil Shapiro # define TLS_S_KEY2_EX	0x00004000	/* 2nd key file exists */
56813bd1963SGregory Neil Shapiro # define TLS_S_KEY2_OK	0x00008000	/* 2nd key file is ok */
56940266059SGregory Neil Shapiro 
57040266059SGregory Neil Shapiro # define TLS_S_DH_OK	0x00200000	/* DH cert is ok */
57140266059SGregory Neil Shapiro # define TLS_S_DHPAR_EX	0x00400000	/* DH param file exists */
57240266059SGregory Neil Shapiro # define TLS_S_DHPAR_OK	0x00800000	/* DH param file is ok to use */
57340266059SGregory Neil Shapiro 
574323f6dcbSGregory Neil Shapiro /* Type of variable */
575323f6dcbSGregory Neil Shapiro # define TLS_T_OTHER	0
576323f6dcbSGregory Neil Shapiro # define TLS_T_SRV	1
577323f6dcbSGregory Neil Shapiro # define TLS_T_CLT	2
578323f6dcbSGregory Neil Shapiro 
57940266059SGregory Neil Shapiro /*
58040266059SGregory Neil Shapiro **  TLS_OK_F -- can var be an absolute filename?
58140266059SGregory Neil Shapiro **
58240266059SGregory Neil Shapiro **	Parameters:
58340266059SGregory Neil Shapiro **		var -- filename
58440266059SGregory Neil Shapiro **		fn -- what is the filename used for?
585323f6dcbSGregory Neil Shapiro **		type -- type of variable
58640266059SGregory Neil Shapiro **
58740266059SGregory Neil Shapiro **	Returns:
58840266059SGregory Neil Shapiro **		ok?
58940266059SGregory Neil Shapiro */
59040266059SGregory Neil Shapiro 
59140266059SGregory Neil Shapiro static bool
592323f6dcbSGregory Neil Shapiro tls_ok_f(var, fn, type)
59340266059SGregory Neil Shapiro 	char *var;
59440266059SGregory Neil Shapiro 	char *fn;
595323f6dcbSGregory Neil Shapiro 	int type;
59640266059SGregory Neil Shapiro {
59740266059SGregory Neil Shapiro 	/* must be absolute pathname */
59840266059SGregory Neil Shapiro 	if (var != NULL && *var == '/')
59940266059SGregory Neil Shapiro 		return true;
60040266059SGregory Neil Shapiro 	if (LogLevel > 12)
60140266059SGregory Neil Shapiro 		sm_syslog(LOG_WARNING, NOQID, "STARTTLS: %s%s missing",
602323f6dcbSGregory Neil Shapiro 			  type == TLS_T_SRV ? "Server" :
603e92d3f3fSGregory Neil Shapiro 			  (type == TLS_T_CLT ? "Client" : ""), fn);
60440266059SGregory Neil Shapiro 	return false;
60540266059SGregory Neil Shapiro }
60640266059SGregory Neil Shapiro /*
60740266059SGregory Neil Shapiro **  TLS_SAFE_F -- is a file safe to use?
60840266059SGregory Neil Shapiro **
60940266059SGregory Neil Shapiro **	Parameters:
61040266059SGregory Neil Shapiro **		var -- filename
61140266059SGregory Neil Shapiro **		sff -- flags for safefile()
61240266059SGregory Neil Shapiro **		srv -- server side?
61340266059SGregory Neil Shapiro **
61440266059SGregory Neil Shapiro **	Returns:
61540266059SGregory Neil Shapiro **		ok?
61640266059SGregory Neil Shapiro */
61740266059SGregory Neil Shapiro 
61840266059SGregory Neil Shapiro static bool
61940266059SGregory Neil Shapiro tls_safe_f(var, sff, srv)
62040266059SGregory Neil Shapiro 	char *var;
62140266059SGregory Neil Shapiro 	long sff;
62240266059SGregory Neil Shapiro 	bool srv;
62340266059SGregory Neil Shapiro {
62440266059SGregory Neil Shapiro 	int ret;
62540266059SGregory Neil Shapiro 
62640266059SGregory Neil Shapiro 	if ((ret = safefile(var, RunAsUid, RunAsGid, RunAsUserName, sff,
62740266059SGregory Neil Shapiro 			    S_IRUSR, NULL)) == 0)
62840266059SGregory Neil Shapiro 		return true;
62940266059SGregory Neil Shapiro 	if (LogLevel > 7)
63040266059SGregory Neil Shapiro 		sm_syslog(LOG_WARNING, NOQID, "STARTTLS=%s: file %s unsafe: %s",
63140266059SGregory Neil Shapiro 			  srv ? "server" : "client", var, sm_errstring(ret));
63240266059SGregory Neil Shapiro 	return false;
63340266059SGregory Neil Shapiro }
63440266059SGregory Neil Shapiro 
63540266059SGregory Neil Shapiro /*
63640266059SGregory Neil Shapiro **  TLS_OK_F -- macro to simplify calls to tls_ok_f
63740266059SGregory Neil Shapiro **
63840266059SGregory Neil Shapiro **	Parameters:
63940266059SGregory Neil Shapiro **		var -- filename
64040266059SGregory Neil Shapiro **		fn -- what is the filename used for?
64140266059SGregory Neil Shapiro **		req -- is the file required?
64240266059SGregory Neil Shapiro **		st -- status bit to set if ok
643323f6dcbSGregory Neil Shapiro **		type -- type of variable
64440266059SGregory Neil Shapiro **
64540266059SGregory Neil Shapiro **	Side Effects:
64640266059SGregory Neil Shapiro **		uses r, ok; may change ok and status.
64740266059SGregory Neil Shapiro **
64840266059SGregory Neil Shapiro */
64940266059SGregory Neil Shapiro 
650323f6dcbSGregory Neil Shapiro # define TLS_OK_F(var, fn, req, st, type) if (ok) \
65140266059SGregory Neil Shapiro 	{ \
652323f6dcbSGregory Neil Shapiro 		r = tls_ok_f(var, fn, type); \
65340266059SGregory Neil Shapiro 		if (r) \
65440266059SGregory Neil Shapiro 			status |= st; \
65540266059SGregory Neil Shapiro 		else if (req) \
65640266059SGregory Neil Shapiro 			ok = false; \
65740266059SGregory Neil Shapiro 	}
65840266059SGregory Neil Shapiro 
65940266059SGregory Neil Shapiro /*
66040266059SGregory Neil Shapiro **  TLS_UNR -- macro to return whether a file should be unreadable
66140266059SGregory Neil Shapiro **
66240266059SGregory Neil Shapiro **	Parameters:
66340266059SGregory Neil Shapiro **		bit -- flag to test
66440266059SGregory Neil Shapiro **		req -- flags
66540266059SGregory Neil Shapiro **
66640266059SGregory Neil Shapiro **	Returns:
66740266059SGregory Neil Shapiro **		0/SFF_NORFILES
66840266059SGregory Neil Shapiro */
6695b0945b5SGregory Neil Shapiro 
67040266059SGregory Neil Shapiro # define TLS_UNR(bit, req)	(bitset(bit, req) ? SFF_NORFILES : 0)
67140266059SGregory Neil Shapiro # define TLS_OUNR(bit, req)	(bitset(bit, req) ? SFF_NOWRFILES : 0)
67240266059SGregory Neil Shapiro # define TLS_KEYSFF(req)	\
67340266059SGregory Neil Shapiro 	(bitnset(DBS_GROUPREADABLEKEYFILE, DontBlameSendmail) ?	\
67440266059SGregory Neil Shapiro 		TLS_OUNR(TLS_I_KEY_OUNR, req) :			\
67540266059SGregory Neil Shapiro 		TLS_UNR(TLS_I_KEY_UNR, req))
67640266059SGregory Neil Shapiro 
67740266059SGregory Neil Shapiro /*
67840266059SGregory Neil Shapiro **  TLS_SAFE_F -- macro to simplify calls to tls_safe_f
67940266059SGregory Neil Shapiro **
68040266059SGregory Neil Shapiro **	Parameters:
68140266059SGregory Neil Shapiro **		var -- filename
68240266059SGregory Neil Shapiro **		sff -- flags for safefile()
68340266059SGregory Neil Shapiro **		req -- is the file required?
68440266059SGregory Neil Shapiro **		ex -- does the file exist?
68540266059SGregory Neil Shapiro **		st -- status bit to set if ok
68640266059SGregory Neil Shapiro **		srv -- server side?
68740266059SGregory Neil Shapiro **
68840266059SGregory Neil Shapiro **	Side Effects:
68940266059SGregory Neil Shapiro **		uses r, ok, ex; may change ok and status.
69040266059SGregory Neil Shapiro **
69140266059SGregory Neil Shapiro */
69240266059SGregory Neil Shapiro 
69340266059SGregory Neil Shapiro # define TLS_SAFE_F(var, sff, req, ex, st, srv) if (ex && ok) \
69440266059SGregory Neil Shapiro 	{ \
69540266059SGregory Neil Shapiro 		r = tls_safe_f(var, sff, srv); \
69640266059SGregory Neil Shapiro 		if (r) \
69740266059SGregory Neil Shapiro 			status |= st;	\
69840266059SGregory Neil Shapiro 		else if (req) \
69940266059SGregory Neil Shapiro 			ok = false;	\
70040266059SGregory Neil Shapiro 	}
70140266059SGregory Neil Shapiro 
702da7d7b9cSGregory Neil Shapiro /*
703da7d7b9cSGregory Neil Shapiro **  LOAD_CERTKEY -- load cert/key for TLS session
704da7d7b9cSGregory Neil Shapiro **
705da7d7b9cSGregory Neil Shapiro **	Parameters:
706da7d7b9cSGregory Neil Shapiro **		ssl -- TLS session context
7075b0945b5SGregory Neil Shapiro **		srv -- server side?
708da7d7b9cSGregory Neil Shapiro **		certfile -- filename of certificate
709da7d7b9cSGregory Neil Shapiro **		keyfile -- filename of private key
710da7d7b9cSGregory Neil Shapiro **
711da7d7b9cSGregory Neil Shapiro **	Returns:
712da7d7b9cSGregory Neil Shapiro **		succeeded?
713da7d7b9cSGregory Neil Shapiro */
714da7d7b9cSGregory Neil Shapiro 
715da7d7b9cSGregory Neil Shapiro bool
716da7d7b9cSGregory Neil Shapiro load_certkey(ssl, srv, certfile, keyfile)
717da7d7b9cSGregory Neil Shapiro 	SSL *ssl;
718da7d7b9cSGregory Neil Shapiro 	bool srv;
719da7d7b9cSGregory Neil Shapiro 	char *certfile;
720da7d7b9cSGregory Neil Shapiro 	char *keyfile;
721da7d7b9cSGregory Neil Shapiro {
722da7d7b9cSGregory Neil Shapiro 	bool ok;
723da7d7b9cSGregory Neil Shapiro 	int r;
724da7d7b9cSGregory Neil Shapiro 	long sff, status;
725da7d7b9cSGregory Neil Shapiro 	unsigned long req;
726da7d7b9cSGregory Neil Shapiro 	char *who;
727da7d7b9cSGregory Neil Shapiro 
728da7d7b9cSGregory Neil Shapiro 	ok = true;
729da7d7b9cSGregory Neil Shapiro 	who = srv ? "server" : "client";
730da7d7b9cSGregory Neil Shapiro 	status = TLS_S_NONE;
731da7d7b9cSGregory Neil Shapiro 	req = TLS_I_CERT_EX|TLS_I_KEY_EX;
732da7d7b9cSGregory Neil Shapiro 	TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req),
733da7d7b9cSGregory Neil Shapiro 		 TLS_S_CERT_EX, srv ? TLS_T_SRV : TLS_T_CLT);
734da7d7b9cSGregory Neil Shapiro 	TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req),
735da7d7b9cSGregory Neil Shapiro 		 TLS_S_KEY_EX, srv ? TLS_T_SRV : TLS_T_CLT);
736da7d7b9cSGregory Neil Shapiro 
737da7d7b9cSGregory Neil Shapiro 	/* certfile etc. must be "safe". */
738da7d7b9cSGregory Neil Shapiro 	sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK
739da7d7b9cSGregory Neil Shapiro 	     | SFF_NOGWFILES | SFF_NOWWFILES
740*d39bd2c1SGregory Neil Shapiro 	     | SFF_ROOTOK | SFF_OPENASROOT;
741*d39bd2c1SGregory Neil Shapiro 	if (!bitnset(DBS_CERTOWNER, DontBlameSendmail))
742*d39bd2c1SGregory Neil Shapiro 		sff |= SFF_MUSTOWN;
743da7d7b9cSGregory Neil Shapiro 	if (DontLockReadFiles)
744da7d7b9cSGregory Neil Shapiro 		sff |= SFF_NOLOCK;
745da7d7b9cSGregory Neil Shapiro 
746da7d7b9cSGregory Neil Shapiro 	TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req),
747da7d7b9cSGregory Neil Shapiro 		   bitset(TLS_I_CERT_EX, req),
748da7d7b9cSGregory Neil Shapiro 		   bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv);
749da7d7b9cSGregory Neil Shapiro 	TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req),
750da7d7b9cSGregory Neil Shapiro 		   bitset(TLS_I_KEY_EX, req),
751da7d7b9cSGregory Neil Shapiro 		   bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv);
752da7d7b9cSGregory Neil Shapiro 
753da7d7b9cSGregory Neil Shapiro # define SSL_use_cert(ssl, certfile) \
754da7d7b9cSGregory Neil Shapiro 	SSL_use_certificate_file(ssl, certfile, SSL_FILETYPE_PEM)
755da7d7b9cSGregory Neil Shapiro # define SSL_USE_CERT "SSL_use_certificate_file"
756da7d7b9cSGregory Neil Shapiro 
757da7d7b9cSGregory Neil Shapiro 	if (bitset(TLS_S_CERT_OK, status) &&
758da7d7b9cSGregory Neil Shapiro 	    SSL_use_cert(ssl, certfile) <= 0)
759da7d7b9cSGregory Neil Shapiro 	{
760da7d7b9cSGregory Neil Shapiro 		if (LogLevel > 7)
761da7d7b9cSGregory Neil Shapiro 		{
762da7d7b9cSGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
763da7d7b9cSGregory Neil Shapiro 				  "STARTTLS=%s, error: %s(%s) failed",
764da7d7b9cSGregory Neil Shapiro 				  who, SSL_USE_CERT, certfile);
7655b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
766da7d7b9cSGregory Neil Shapiro 		}
767da7d7b9cSGregory Neil Shapiro 		if (bitset(TLS_I_USE_CERT, req))
768da7d7b9cSGregory Neil Shapiro 			return false;
769da7d7b9cSGregory Neil Shapiro 	}
770da7d7b9cSGregory Neil Shapiro 	if (bitset(TLS_S_KEY_OK, status) &&
771da7d7b9cSGregory Neil Shapiro 	    SSL_use_PrivateKey_file(ssl, keyfile, SSL_FILETYPE_PEM) <= 0)
772da7d7b9cSGregory Neil Shapiro 	{
773da7d7b9cSGregory Neil Shapiro 		if (LogLevel > 7)
774da7d7b9cSGregory Neil Shapiro 		{
775da7d7b9cSGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
776da7d7b9cSGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_use_PrivateKey_file(%s) failed",
777da7d7b9cSGregory Neil Shapiro 				  who, keyfile);
7785b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
779da7d7b9cSGregory Neil Shapiro 		}
780da7d7b9cSGregory Neil Shapiro 		if (bitset(TLS_I_USE_KEY, req))
781da7d7b9cSGregory Neil Shapiro 			return false;
782da7d7b9cSGregory Neil Shapiro 	}
783da7d7b9cSGregory Neil Shapiro 
784da7d7b9cSGregory Neil Shapiro 	/* check the private key */
785da7d7b9cSGregory Neil Shapiro 	if (bitset(TLS_S_KEY_OK, status) &&
786da7d7b9cSGregory Neil Shapiro 	    (r = SSL_check_private_key(ssl)) <= 0)
787da7d7b9cSGregory Neil Shapiro 	{
788da7d7b9cSGregory Neil Shapiro 		/* Private key does not match the certificate public key */
789da7d7b9cSGregory Neil Shapiro 		if (LogLevel > 5)
790da7d7b9cSGregory Neil Shapiro 		{
791da7d7b9cSGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
792da7d7b9cSGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_check_private_key failed(%s): %d",
793da7d7b9cSGregory Neil Shapiro 				  who, keyfile, r);
7945b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
795da7d7b9cSGregory Neil Shapiro 		}
796da7d7b9cSGregory Neil Shapiro 		if (bitset(TLS_I_USE_KEY, req))
797da7d7b9cSGregory Neil Shapiro 			return false;
798da7d7b9cSGregory Neil Shapiro 	}
799da7d7b9cSGregory Neil Shapiro 
800da7d7b9cSGregory Neil Shapiro 	return true;
801da7d7b9cSGregory Neil Shapiro }
8025b0945b5SGregory Neil Shapiro 
8035b0945b5SGregory Neil Shapiro /*
8045b0945b5SGregory Neil Shapiro **  LOAD_CRLFILE -- load a file holding a CRL into the TLS context
8055b0945b5SGregory Neil Shapiro **
8065b0945b5SGregory Neil Shapiro **	Parameters:
8075b0945b5SGregory Neil Shapiro **		ctx -- TLS context
8085b0945b5SGregory Neil Shapiro **		srv -- server side?
8095b0945b5SGregory Neil Shapiro **		filename -- filename of CRL
8105b0945b5SGregory Neil Shapiro **
8115b0945b5SGregory Neil Shapiro **	Returns:
8125b0945b5SGregory Neil Shapiro **		succeeded?
8135b0945b5SGregory Neil Shapiro */
8145b0945b5SGregory Neil Shapiro 
8155b0945b5SGregory Neil Shapiro static bool load_crlfile __P((SSL_CTX *, bool, char *));
8165b0945b5SGregory Neil Shapiro 
8175b0945b5SGregory Neil Shapiro static bool
8185b0945b5SGregory Neil Shapiro load_crlfile(ctx, srv, filename)
8195b0945b5SGregory Neil Shapiro 	SSL_CTX *ctx;
8205b0945b5SGregory Neil Shapiro 	bool srv;
8215b0945b5SGregory Neil Shapiro 	char *filename;
8225b0945b5SGregory Neil Shapiro {
8235b0945b5SGregory Neil Shapiro 	char *who;
8245b0945b5SGregory Neil Shapiro 	BIO *crl_file;
8255b0945b5SGregory Neil Shapiro 	X509_CRL *crl;
8265b0945b5SGregory Neil Shapiro 	X509_STORE *store;
8275b0945b5SGregory Neil Shapiro 
8285b0945b5SGregory Neil Shapiro 	who = srv ? "server" : "client";
8295b0945b5SGregory Neil Shapiro 	crl_file = BIO_new(BIO_s_file());
8305b0945b5SGregory Neil Shapiro 	if (crl_file == NULL)
8315b0945b5SGregory Neil Shapiro 	{
8325b0945b5SGregory Neil Shapiro 		if (LogLevel > 9)
8335b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
8345b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, error: BIO_new=failed", who);
8355b0945b5SGregory Neil Shapiro 		return false;
8365b0945b5SGregory Neil Shapiro 	}
8375b0945b5SGregory Neil Shapiro 
8385b0945b5SGregory Neil Shapiro 	if (BIO_read_filename(crl_file, filename) < 0)
8395b0945b5SGregory Neil Shapiro 	{
8405b0945b5SGregory Neil Shapiro 		if (LogLevel > 9)
8415b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
8425b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, error: BIO_read_filename(%s)=failed",
8435b0945b5SGregory Neil Shapiro 				  who, filename);
8445b0945b5SGregory Neil Shapiro 
8455b0945b5SGregory Neil Shapiro 		/* avoid memory leaks */
8465b0945b5SGregory Neil Shapiro 		BIO_free(crl_file);
8475b0945b5SGregory Neil Shapiro 		return false;
8485b0945b5SGregory Neil Shapiro 	}
8495b0945b5SGregory Neil Shapiro 
8505b0945b5SGregory Neil Shapiro 	crl = PEM_read_bio_X509_CRL(crl_file, NULL, NULL, NULL);
8515b0945b5SGregory Neil Shapiro 	if (crl == NULL)
8525b0945b5SGregory Neil Shapiro 	{
8535b0945b5SGregory Neil Shapiro 		if (LogLevel > 9)
8545b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
8555b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, error: PEM_read_bio_X509_CRL(%s)=failed",
8565b0945b5SGregory Neil Shapiro 				  who, filename);
8575b0945b5SGregory Neil Shapiro 		BIO_free(crl_file);
8585b0945b5SGregory Neil Shapiro 		return true;	/* XXX should probably be 'false' */
8595b0945b5SGregory Neil Shapiro 	}
8605b0945b5SGregory Neil Shapiro 
8615b0945b5SGregory Neil Shapiro 	BIO_free(crl_file);
8625b0945b5SGregory Neil Shapiro 
8635b0945b5SGregory Neil Shapiro 	/* get a pointer to the current certificate validation store */
8645b0945b5SGregory Neil Shapiro 	store = SSL_CTX_get_cert_store(ctx);	/* does not fail */
8655b0945b5SGregory Neil Shapiro 
8665b0945b5SGregory Neil Shapiro 	if (X509_STORE_add_crl(store, crl) == 0)
8675b0945b5SGregory Neil Shapiro 	{
8685b0945b5SGregory Neil Shapiro 		if (LogLevel > 9)
8695b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
8705b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, error: X509_STORE_add_crl=failed",
8715b0945b5SGregory Neil Shapiro 				  who);
8725b0945b5SGregory Neil Shapiro 		X509_CRL_free(crl);
8735b0945b5SGregory Neil Shapiro 		return false;
8745b0945b5SGregory Neil Shapiro 	}
8755b0945b5SGregory Neil Shapiro 
8765b0945b5SGregory Neil Shapiro 	X509_CRL_free(crl);
8775b0945b5SGregory Neil Shapiro 
8785b0945b5SGregory Neil Shapiro 	X509_STORE_set_flags(store,
8795b0945b5SGregory Neil Shapiro 		X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
8805b0945b5SGregory Neil Shapiro 	X509_STORE_set_verify_cb_func(store, x509_verify_cb);
8815b0945b5SGregory Neil Shapiro 
8825b0945b5SGregory Neil Shapiro 	return true;
8835b0945b5SGregory Neil Shapiro }
8845b0945b5SGregory Neil Shapiro 
8855b0945b5SGregory Neil Shapiro /*
8865b0945b5SGregory Neil Shapiro **  LOAD_CRLPATH -- configure the TLS context to lookup CRLs in a directory
8875b0945b5SGregory Neil Shapiro **
8885b0945b5SGregory Neil Shapiro **	Parameters:
8895b0945b5SGregory Neil Shapiro **		ctx -- TLS context
8905b0945b5SGregory Neil Shapiro **		srv -- server side?
8915b0945b5SGregory Neil Shapiro **		path -- path of hashed directory of CRLs
8925b0945b5SGregory Neil Shapiro **
8935b0945b5SGregory Neil Shapiro **	Returns:
8945b0945b5SGregory Neil Shapiro **		succeeded?
8955b0945b5SGregory Neil Shapiro */
8965b0945b5SGregory Neil Shapiro 
8975b0945b5SGregory Neil Shapiro static bool load_crlpath __P((SSL_CTX *, bool, char *));
8985b0945b5SGregory Neil Shapiro 
8995b0945b5SGregory Neil Shapiro static bool
9005b0945b5SGregory Neil Shapiro load_crlpath(ctx, srv, path)
9015b0945b5SGregory Neil Shapiro 	SSL_CTX *ctx;
9025b0945b5SGregory Neil Shapiro 	bool srv;
9035b0945b5SGregory Neil Shapiro 	char *path;
9045b0945b5SGregory Neil Shapiro {
9055b0945b5SGregory Neil Shapiro 	char *who;
9065b0945b5SGregory Neil Shapiro 	X509_STORE *store;
9075b0945b5SGregory Neil Shapiro 	X509_LOOKUP *lookup;
9085b0945b5SGregory Neil Shapiro 
9095b0945b5SGregory Neil Shapiro 	who = srv ? "server" : "client";
9105b0945b5SGregory Neil Shapiro 
9115b0945b5SGregory Neil Shapiro 	/* get a pointer to the current certificate validation store */
9125b0945b5SGregory Neil Shapiro 	store = SSL_CTX_get_cert_store(ctx);	/* does not fail */
9135b0945b5SGregory Neil Shapiro 
9145b0945b5SGregory Neil Shapiro 	lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
9155b0945b5SGregory Neil Shapiro 	if (lookup == NULL)
9165b0945b5SGregory Neil Shapiro 	{
9175b0945b5SGregory Neil Shapiro 		if (LogLevel > 9)
9185b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
9195b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, error: X509_STORE_add_lookup(hash)=failed",
9205b0945b5SGregory Neil Shapiro 				  who);
9215b0945b5SGregory Neil Shapiro 		return false;
9225b0945b5SGregory Neil Shapiro 	}
9235b0945b5SGregory Neil Shapiro 
9245b0945b5SGregory Neil Shapiro 	if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) == 0)
9255b0945b5SGregory Neil Shapiro 	{
9265b0945b5SGregory Neil Shapiro 		if (LogLevel > 9)
9275b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
9285b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, error: X509_LOOKUP_add_dir(%s)=failed",
9295b0945b5SGregory Neil Shapiro 				  who, path);
9305b0945b5SGregory Neil Shapiro 		return false;
9315b0945b5SGregory Neil Shapiro 	}
9325b0945b5SGregory Neil Shapiro 
9335b0945b5SGregory Neil Shapiro 	X509_STORE_set_flags(store,
9345b0945b5SGregory Neil Shapiro 		X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
9355b0945b5SGregory Neil Shapiro 	X509_STORE_set_verify_cb_func(store, x509_verify_cb);
9365b0945b5SGregory Neil Shapiro 
9375b0945b5SGregory Neil Shapiro 	return true;
9385b0945b5SGregory Neil Shapiro }
939da7d7b9cSGregory Neil Shapiro 
94040266059SGregory Neil Shapiro /*
94140266059SGregory Neil Shapiro **  INITTLS -- initialize TLS
94240266059SGregory Neil Shapiro **
94340266059SGregory Neil Shapiro **	Parameters:
94440266059SGregory Neil Shapiro **		ctx -- pointer to context
94540266059SGregory Neil Shapiro **		req -- requirements for initialization (see sendmail.h)
9469bd497b8SGregory Neil Shapiro **		options -- options
94740266059SGregory Neil Shapiro **		srv -- server side?
94840266059SGregory Neil Shapiro **		certfile -- filename of certificate
94940266059SGregory Neil Shapiro **		keyfile -- filename of private key
95040266059SGregory Neil Shapiro **		cacertpath -- path to CAs
95140266059SGregory Neil Shapiro **		cacertfile -- file with CA(s)
95240266059SGregory Neil Shapiro **		dhparam -- parameters for DH
95340266059SGregory Neil Shapiro **
95440266059SGregory Neil Shapiro **	Returns:
95540266059SGregory Neil Shapiro **		succeeded?
95640266059SGregory Neil Shapiro */
95740266059SGregory Neil Shapiro 
9584e4196cbSGregory Neil Shapiro /*
9594e4196cbSGregory Neil Shapiro **  The session_id_context identifies the service that created a session.
9604e4196cbSGregory Neil Shapiro **  This information is used to distinguish between multiple TLS-based
9614e4196cbSGregory Neil Shapiro **  servers running on the same server. We use the name of the mail system.
9624e4196cbSGregory Neil Shapiro **  Note: the session cache is not persistent.
9634e4196cbSGregory Neil Shapiro */
9644e4196cbSGregory Neil Shapiro 
9654e4196cbSGregory Neil Shapiro static char server_session_id_context[] = "sendmail8";
9664e4196cbSGregory Neil Shapiro 
967af9557fdSGregory Neil Shapiro /* 0.9.8a and b have a problem with SSL_OP_TLS_BLOCK_PADDING_BUG */
968af9557fdSGregory Neil Shapiro # if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
969af9557fdSGregory Neil Shapiro #  define SM_SSL_OP_TLS_BLOCK_PADDING_BUG	1
970af9557fdSGregory Neil Shapiro # else
971af9557fdSGregory Neil Shapiro #  define SM_SSL_OP_TLS_BLOCK_PADDING_BUG	0
972af9557fdSGregory Neil Shapiro # endif
973af9557fdSGregory Neil Shapiro 
97440266059SGregory Neil Shapiro bool
9759bd497b8SGregory Neil Shapiro inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
97640266059SGregory Neil Shapiro 	SSL_CTX **ctx;
97740266059SGregory Neil Shapiro 	unsigned long req;
978da7d7b9cSGregory Neil Shapiro 	unsigned long options;
97940266059SGregory Neil Shapiro 	bool srv;
98040266059SGregory Neil Shapiro 	char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam;
98140266059SGregory Neil Shapiro {
98240266059SGregory Neil Shapiro # if !NO_DH
98340266059SGregory Neil Shapiro 	static DH *dh = NULL;
9845b0945b5SGregory Neil Shapiro # endif
98540266059SGregory Neil Shapiro 	int r;
98640266059SGregory Neil Shapiro 	bool ok;
9879bd497b8SGregory Neil Shapiro 	long sff, status;
98840266059SGregory Neil Shapiro 	char *who;
98940266059SGregory Neil Shapiro 	char *cf2, *kf2;
9905b0945b5SGregory Neil Shapiro # if SM_CONF_SHM && !TLS_NO_RSA && MTA_RSA_TMP_CB
99140266059SGregory Neil Shapiro 	extern int ShmId;
9925b0945b5SGregory Neil Shapiro # endif
993af9557fdSGregory Neil Shapiro # if SM_SSL_OP_TLS_BLOCK_PADDING_BUG
994af9557fdSGregory Neil Shapiro 	long rt_version;
995af9557fdSGregory Neil Shapiro 	STACK_OF(SSL_COMP) *comp_methods;
996af9557fdSGregory Neil Shapiro # endif
99740266059SGregory Neil Shapiro 
99840266059SGregory Neil Shapiro 	status = TLS_S_NONE;
99940266059SGregory Neil Shapiro 	who = srv ? "server" : "client";
100040266059SGregory Neil Shapiro 	if (ctx == NULL)
1001af9557fdSGregory Neil Shapiro 	{
100240266059SGregory Neil Shapiro 		syserr("STARTTLS=%s, inittls: ctx == NULL", who);
1003af9557fdSGregory Neil Shapiro 		/* NOTREACHED */
1004af9557fdSGregory Neil Shapiro 		SM_ASSERT(ctx != NULL);
1005af9557fdSGregory Neil Shapiro 	}
100640266059SGregory Neil Shapiro 
100740266059SGregory Neil Shapiro 	/* already initialized? (we could re-init...) */
100840266059SGregory Neil Shapiro 	if (*ctx != NULL)
100940266059SGregory Neil Shapiro 		return true;
101040266059SGregory Neil Shapiro 	ok = true;
101140266059SGregory Neil Shapiro 
101240266059SGregory Neil Shapiro 	/*
101340266059SGregory Neil Shapiro 	**  look for a second filename: it must be separated by a ','
101440266059SGregory Neil Shapiro 	**  no blanks allowed (they won't be skipped).
101540266059SGregory Neil Shapiro 	**  we change a global variable here! this change will be undone
101640266059SGregory Neil Shapiro 	**  before return from the function but only if it returns true.
101740266059SGregory Neil Shapiro 	**  this isn't a problem since in a failure case this function
101840266059SGregory Neil Shapiro 	**  won't be called again with the same (overwritten) values.
101940266059SGregory Neil Shapiro 	**  otherwise each return must be replaced with a goto endinittls.
102040266059SGregory Neil Shapiro 	*/
102140266059SGregory Neil Shapiro 
102240266059SGregory Neil Shapiro 	cf2 = NULL;
102340266059SGregory Neil Shapiro 	kf2 = NULL;
102440266059SGregory Neil Shapiro 	if (certfile != NULL && (cf2 = strchr(certfile, ',')) != NULL)
102540266059SGregory Neil Shapiro 	{
102640266059SGregory Neil Shapiro 		*cf2++ = '\0';
102740266059SGregory Neil Shapiro 		if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL)
102840266059SGregory Neil Shapiro 			*kf2++ = '\0';
102940266059SGregory Neil Shapiro 	}
103040266059SGregory Neil Shapiro 
103140266059SGregory Neil Shapiro 	/*
103240266059SGregory Neil Shapiro 	**  Check whether files/paths are defined
103340266059SGregory Neil Shapiro 	*/
103440266059SGregory Neil Shapiro 
103540266059SGregory Neil Shapiro 	TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req),
1036323f6dcbSGregory Neil Shapiro 		 TLS_S_CERT_EX, srv ? TLS_T_SRV : TLS_T_CLT);
103740266059SGregory Neil Shapiro 	TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req),
1038323f6dcbSGregory Neil Shapiro 		 TLS_S_KEY_EX, srv ? TLS_T_SRV : TLS_T_CLT);
103913bd1963SGregory Neil Shapiro 	TLS_OK_F(cacertpath, "CACertPath", bitset(TLS_I_CERTP_EX, req),
1040323f6dcbSGregory Neil Shapiro 		 TLS_S_CERTP_EX, TLS_T_OTHER);
104113bd1963SGregory Neil Shapiro 	TLS_OK_F(cacertfile, "CACertFile", bitset(TLS_I_CERTF_EX, req),
1042323f6dcbSGregory Neil Shapiro 		 TLS_S_CERTF_EX, TLS_T_OTHER);
104340266059SGregory Neil Shapiro 
1044e92d3f3fSGregory Neil Shapiro 	TLS_OK_F(CRLFile, "CRLFile", bitset(TLS_I_CRLF_EX, req),
1045e92d3f3fSGregory Neil Shapiro 		 TLS_S_CRLF_EX, TLS_T_OTHER);
1046e92d3f3fSGregory Neil Shapiro 
104740266059SGregory Neil Shapiro 	/*
104840266059SGregory Neil Shapiro 	**  if the second file is specified it must exist
104940266059SGregory Neil Shapiro 	**  XXX: it is possible here to define only one of those files
105040266059SGregory Neil Shapiro 	*/
105140266059SGregory Neil Shapiro 
105240266059SGregory Neil Shapiro 	if (cf2 != NULL)
105340266059SGregory Neil Shapiro 	{
105440266059SGregory Neil Shapiro 		TLS_OK_F(cf2, "CertFile", bitset(TLS_I_CERT_EX, req),
1055323f6dcbSGregory Neil Shapiro 			 TLS_S_CERT2_EX, srv ? TLS_T_SRV : TLS_T_CLT);
105640266059SGregory Neil Shapiro 	}
105740266059SGregory Neil Shapiro 	if (kf2 != NULL)
105840266059SGregory Neil Shapiro 	{
105940266059SGregory Neil Shapiro 		TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req),
1060323f6dcbSGregory Neil Shapiro 			 TLS_S_KEY2_EX, srv ? TLS_T_SRV : TLS_T_CLT);
106140266059SGregory Neil Shapiro 	}
106240266059SGregory Neil Shapiro 
106340266059SGregory Neil Shapiro 	/*
106440266059SGregory Neil Shapiro 	**  valid values for dhparam are (only the first char is checked)
106540266059SGregory Neil Shapiro 	**  none	no parameters: don't use DH
1066da7d7b9cSGregory Neil Shapiro 	**  i		use precomputed 2048 bit parameters
10675dd76dd0SGregory Neil Shapiro 	**  512		use precomputed 512 bit parameters
106840266059SGregory Neil Shapiro 	**  1024	generate 1024 bit parameters
10695dd76dd0SGregory Neil Shapiro 	**  2048	generate 2048 bit parameters
107040266059SGregory Neil Shapiro 	**  /file/name	read parameters from /file/name
107140266059SGregory Neil Shapiro 	*/
107240266059SGregory Neil Shapiro 
1073*d39bd2c1SGregory Neil Shapiro # if MTA_DH_AUTO
1074*d39bd2c1SGregory Neil Shapiro #  define SET_DH_DFL	\
1075*d39bd2c1SGregory Neil Shapiro 	do {	\
1076*d39bd2c1SGregory Neil Shapiro 		dhparam = "a";	\
1077*d39bd2c1SGregory Neil Shapiro 		req |= TLS_I_DHAUTO;	\
1078*d39bd2c1SGregory Neil Shapiro 	} while (0)
1079*d39bd2c1SGregory Neil Shapiro # else
1080da7d7b9cSGregory Neil Shapiro #  define SET_DH_DFL	\
1081da7d7b9cSGregory Neil Shapiro 	do {	\
1082da7d7b9cSGregory Neil Shapiro 		dhparam = "I";	\
1083da7d7b9cSGregory Neil Shapiro 		req |= TLS_I_DHFIXED;	\
1084da7d7b9cSGregory Neil Shapiro 	} while (0)
1085*d39bd2c1SGregory Neil Shapiro # endif
1086da7d7b9cSGregory Neil Shapiro 
108740266059SGregory Neil Shapiro 	if (bitset(TLS_I_TRY_DH, req))
108840266059SGregory Neil Shapiro 	{
108940266059SGregory Neil Shapiro 		if (dhparam != NULL)
109040266059SGregory Neil Shapiro 		{
109140266059SGregory Neil Shapiro 			char c = *dhparam;
109240266059SGregory Neil Shapiro 
1093*d39bd2c1SGregory Neil Shapiro # if MTA_DH_AUTO
1094*d39bd2c1SGregory Neil Shapiro 			if (c == 'a')
1095*d39bd2c1SGregory Neil Shapiro 				req |= TLS_I_DHAUTO;
1096*d39bd2c1SGregory Neil Shapiro 			else
1097*d39bd2c1SGregory Neil Shapiro # endif
109840266059SGregory Neil Shapiro 			if (c == '1')
109940266059SGregory Neil Shapiro 				req |= TLS_I_DH1024;
1100da7d7b9cSGregory Neil Shapiro 			else if (c == 'I' || c == 'i')
1101da7d7b9cSGregory Neil Shapiro 				req |= TLS_I_DHFIXED;
11025dd76dd0SGregory Neil Shapiro 			else if (c == '2')
11035dd76dd0SGregory Neil Shapiro 				req |= TLS_I_DH2048;
110440266059SGregory Neil Shapiro 			else if (c == '5')
110540266059SGregory Neil Shapiro 				req |= TLS_I_DH512;
1106da7d7b9cSGregory Neil Shapiro 			else if (c == 'n' || c == 'N')
1107da7d7b9cSGregory Neil Shapiro 				req &= ~TLS_I_TRY_DH;
1108da7d7b9cSGregory Neil Shapiro 			else if (c != '/')
110940266059SGregory Neil Shapiro 			{
111040266059SGregory Neil Shapiro 				if (LogLevel > 12)
111140266059SGregory Neil Shapiro 					sm_syslog(LOG_WARNING, NOQID,
1112da7d7b9cSGregory Neil Shapiro 						  "STARTTLS=%s, error: illegal value '%s' for DHParameters",
111340266059SGregory Neil Shapiro 						  who, dhparam);
111440266059SGregory Neil Shapiro 				dhparam = NULL;
111540266059SGregory Neil Shapiro 			}
111640266059SGregory Neil Shapiro 		}
111740266059SGregory Neil Shapiro 		if (dhparam == NULL)
1118da7d7b9cSGregory Neil Shapiro 			SET_DH_DFL;
111940266059SGregory Neil Shapiro 		else if (*dhparam == '/')
112040266059SGregory Neil Shapiro 		{
112140266059SGregory Neil Shapiro 			TLS_OK_F(dhparam, "DHParameters",
112240266059SGregory Neil Shapiro 				 bitset(TLS_I_DHPAR_EX, req),
1123323f6dcbSGregory Neil Shapiro 				 TLS_S_DHPAR_EX, TLS_T_OTHER);
112440266059SGregory Neil Shapiro 		}
112540266059SGregory Neil Shapiro 	}
112640266059SGregory Neil Shapiro 	if (!ok)
112740266059SGregory Neil Shapiro 		return ok;
112840266059SGregory Neil Shapiro 
112940266059SGregory Neil Shapiro 	/* certfile etc. must be "safe". */
113040266059SGregory Neil Shapiro 	sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK
113140266059SGregory Neil Shapiro 	     | SFF_NOGWFILES | SFF_NOWWFILES
1132*d39bd2c1SGregory Neil Shapiro 	     | SFF_ROOTOK | SFF_OPENASROOT;
1133*d39bd2c1SGregory Neil Shapiro 	if (!bitnset(DBS_CERTOWNER, DontBlameSendmail))
1134*d39bd2c1SGregory Neil Shapiro 		sff |= SFF_MUSTOWN;
113540266059SGregory Neil Shapiro 	if (DontLockReadFiles)
113640266059SGregory Neil Shapiro 		sff |= SFF_NOLOCK;
113740266059SGregory Neil Shapiro 
113840266059SGregory Neil Shapiro 	TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req),
113940266059SGregory Neil Shapiro 		   bitset(TLS_I_CERT_EX, req),
114040266059SGregory Neil Shapiro 		   bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv);
114140266059SGregory Neil Shapiro 	TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req),
114240266059SGregory Neil Shapiro 		   bitset(TLS_I_KEY_EX, req),
114340266059SGregory Neil Shapiro 		   bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv);
114440266059SGregory Neil Shapiro 	TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req),
114540266059SGregory Neil Shapiro 		   bitset(TLS_I_CERTF_EX, req),
114640266059SGregory Neil Shapiro 		   bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK, srv);
1147da7d7b9cSGregory Neil Shapiro 	if (dhparam != NULL && *dhparam == '/')
1148da7d7b9cSGregory Neil Shapiro 	{
114940266059SGregory Neil Shapiro 		TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req),
115040266059SGregory Neil Shapiro 			   bitset(TLS_I_DHPAR_EX, req),
115140266059SGregory Neil Shapiro 			   bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv);
1152da7d7b9cSGregory Neil Shapiro 		if (!bitset(TLS_S_DHPAR_OK, status))
1153da7d7b9cSGregory Neil Shapiro 			SET_DH_DFL;
1154da7d7b9cSGregory Neil Shapiro 	}
1155e92d3f3fSGregory Neil Shapiro 	TLS_SAFE_F(CRLFile, sff | TLS_UNR(TLS_I_CRLF_UNR, req),
1156e92d3f3fSGregory Neil Shapiro 		   bitset(TLS_I_CRLF_EX, req),
1157e92d3f3fSGregory Neil Shapiro 		   bitset(TLS_S_CRLF_EX, status), TLS_S_CRLF_OK, srv);
115840266059SGregory Neil Shapiro 	if (!ok)
115940266059SGregory Neil Shapiro 		return ok;
116040266059SGregory Neil Shapiro 	if (cf2 != NULL)
116140266059SGregory Neil Shapiro 	{
116240266059SGregory Neil Shapiro 		TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req),
116340266059SGregory Neil Shapiro 			   bitset(TLS_I_CERT_EX, req),
116440266059SGregory Neil Shapiro 			   bitset(TLS_S_CERT2_EX, status), TLS_S_CERT2_OK, srv);
116540266059SGregory Neil Shapiro 	}
116640266059SGregory Neil Shapiro 	if (kf2 != NULL)
116740266059SGregory Neil Shapiro 	{
116840266059SGregory Neil Shapiro 		TLS_SAFE_F(kf2, sff | TLS_KEYSFF(req),
116940266059SGregory Neil Shapiro 			   bitset(TLS_I_KEY_EX, req),
117040266059SGregory Neil Shapiro 			   bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK, srv);
117140266059SGregory Neil Shapiro 	}
117240266059SGregory Neil Shapiro 
117340266059SGregory Neil Shapiro 	/* create a method and a new context */
117440266059SGregory Neil Shapiro 	if ((*ctx = SSL_CTX_new(srv ? SSLv23_server_method() :
117540266059SGregory Neil Shapiro 				      SSLv23_client_method())) == NULL)
117640266059SGregory Neil Shapiro 	{
117740266059SGregory Neil Shapiro 		if (LogLevel > 7)
117840266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
117940266059SGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_CTX_new(SSLv23_%s_method()) failed",
118040266059SGregory Neil Shapiro 				  who, who);
11815b0945b5SGregory Neil Shapiro 		tlslogerr(LOG_WARNING, 9, who);
118240266059SGregory Neil Shapiro 		return false;
118340266059SGregory Neil Shapiro 	}
118440266059SGregory Neil Shapiro 
11855b0945b5SGregory Neil Shapiro # if _FFR_VRFY_TRUSTED_FIRST
11865b0945b5SGregory Neil Shapiro 	if (!tTd(88, 101))
1187e92d3f3fSGregory Neil Shapiro 	{
11885b0945b5SGregory Neil Shapiro 		X509_STORE *store;
11895b0945b5SGregory Neil Shapiro 
1190e92d3f3fSGregory Neil Shapiro 		/* get a pointer to the current certificate validation store */
1191e92d3f3fSGregory Neil Shapiro 		store = SSL_CTX_get_cert_store(*ctx);	/* does not fail */
11925b0945b5SGregory Neil Shapiro 		SM_ASSERT(store != NULL);
11935b0945b5SGregory Neil Shapiro 		X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST);
1194e92d3f3fSGregory Neil Shapiro 	}
11955b0945b5SGregory Neil Shapiro # endif
1196e92d3f3fSGregory Neil Shapiro 
11975b0945b5SGregory Neil Shapiro 	if (CRLFile != NULL && !load_crlfile(*ctx, srv, CRLFile))
1198e92d3f3fSGregory Neil Shapiro 		return false;
11995b0945b5SGregory Neil Shapiro 	if (CRLPath != NULL && !load_crlpath(*ctx, srv, CRLPath))
1200e92d3f3fSGregory Neil Shapiro 		return false;
12015b0945b5SGregory Neil Shapiro 
12025b0945b5SGregory Neil Shapiro # if defined(SSL_MODE_AUTO_RETRY) && OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER < 0x20000000L
12035b0945b5SGregory Neil Shapiro 	/*
12045b0945b5SGregory Neil Shapiro 	 *  Turn off blocking I/O handling in OpenSSL: someone turned
12055b0945b5SGregory Neil Shapiro 	 *  this on by default in 1.1? should we check first?
12065b0945b5SGregory Neil Shapiro 	 */
12075b0945b5SGregory Neil Shapiro #  if _FFR_TESTS
12085b0945b5SGregory Neil Shapiro 	if (LogLevel > 9) {
12095b0945b5SGregory Neil Shapiro 		sff = SSL_CTX_get_mode(*ctx);
12105b0945b5SGregory Neil Shapiro 		if (sff & SSL_MODE_AUTO_RETRY)
12115b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
12125b0945b5SGregory Neil Shapiro 				"STARTTLS=%s, SSL_MODE_AUTO_RETRY=set, mode=%#lx",
12135b0945b5SGregory Neil Shapiro 				who, sff);
1214e92d3f3fSGregory Neil Shapiro 	}
12155b0945b5SGregory Neil Shapiro 
12165b0945b5SGregory Neil Shapiro 	/* hack for testing! */
12175b0945b5SGregory Neil Shapiro 	if (tTd(96, 101) || getenv("SSL_MODE_AUTO_RETRY") != NULL)
12185b0945b5SGregory Neil Shapiro 		SSL_CTX_set_mode(*ctx, SSL_MODE_AUTO_RETRY);
12195b0945b5SGregory Neil Shapiro 	else
12202fb4f839SGregory Neil Shapiro #  endif /* _FFR_TESTS */
12212fb4f839SGregory Neil Shapiro 	/* "else" in #if code above */
12225b0945b5SGregory Neil Shapiro 	SSL_CTX_clear_mode(*ctx, SSL_MODE_AUTO_RETRY);
12235b0945b5SGregory Neil Shapiro # endif /* defined(SSL_MODE_AUTO_RETRY) && OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER < 0x20000000L */
12245b0945b5SGregory Neil Shapiro 
122540266059SGregory Neil Shapiro # if TLS_NO_RSA
122640266059SGregory Neil Shapiro 	/* turn off backward compatibility, required for no-rsa */
122740266059SGregory Neil Shapiro 	SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2);
12285b0945b5SGregory Neil Shapiro # endif
122940266059SGregory Neil Shapiro 
12305b0945b5SGregory Neil Shapiro # if !TLS_NO_RSA && MTA_RSA_TMP_CB
123140266059SGregory Neil Shapiro 	/*
123240266059SGregory Neil Shapiro 	**  Create a temporary RSA key
123340266059SGregory Neil Shapiro 	**  XXX  Maybe we shouldn't create this always (even though it
123440266059SGregory Neil Shapiro 	**  is only at startup).
123540266059SGregory Neil Shapiro 	**  It is a time-consuming operation and it is not always necessary.
123640266059SGregory Neil Shapiro 	**  maybe we should do it only on demand...
123740266059SGregory Neil Shapiro 	*/
123840266059SGregory Neil Shapiro 
1239b7aeb266SJung-uk Kim 	if (bitset(TLS_I_RSA_TMP, req)
12409f5609e9SJung-uk Kim #  if SM_CONF_SHM
12419f5609e9SJung-uk Kim 	    && ShmId != SM_SHM_NO_ID &&
12425b0945b5SGregory Neil Shapiro 	    (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL,
12435b0945b5SGregory Neil Shapiro 					NULL)) == NULL
12449f5609e9SJung-uk Kim #  else /* SM_CONF_SHM */
12459f5609e9SJung-uk Kim 	    && 0	/* no shared memory: no need to generate key now */
12469f5609e9SJung-uk Kim #  endif /* SM_CONF_SHM */
12479f5609e9SJung-uk Kim 	   )
124840266059SGregory Neil Shapiro 	{
124940266059SGregory Neil Shapiro 		if (LogLevel > 7)
125040266059SGregory Neil Shapiro 		{
125140266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
125240266059SGregory Neil Shapiro 				  "STARTTLS=%s, error: RSA_generate_key failed",
125340266059SGregory Neil Shapiro 				  who);
12545b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
125540266059SGregory Neil Shapiro 		}
125640266059SGregory Neil Shapiro 		return false;
125740266059SGregory Neil Shapiro 	}
12585b0945b5SGregory Neil Shapiro # endif /* !TLS_NO_RSA && MTA_RSA_TMP_CB */
125940266059SGregory Neil Shapiro 
126040266059SGregory Neil Shapiro 	/*
126140266059SGregory Neil Shapiro 	**  load private key
126240266059SGregory Neil Shapiro 	**  XXX change this for DSA-only version
126340266059SGregory Neil Shapiro 	*/
126440266059SGregory Neil Shapiro 
126540266059SGregory Neil Shapiro 	if (bitset(TLS_S_KEY_OK, status) &&
126640266059SGregory Neil Shapiro 	    SSL_CTX_use_PrivateKey_file(*ctx, keyfile,
126740266059SGregory Neil Shapiro 					 SSL_FILETYPE_PEM) <= 0)
126840266059SGregory Neil Shapiro 	{
126940266059SGregory Neil Shapiro 		if (LogLevel > 7)
127040266059SGregory Neil Shapiro 		{
127140266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
127240266059SGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed",
127340266059SGregory Neil Shapiro 				  who, keyfile);
12745b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
127540266059SGregory Neil Shapiro 		}
127640266059SGregory Neil Shapiro 		if (bitset(TLS_I_USE_KEY, req))
127740266059SGregory Neil Shapiro 			return false;
127840266059SGregory Neil Shapiro 	}
127940266059SGregory Neil Shapiro 
1280da7d7b9cSGregory Neil Shapiro # if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE
1281da7d7b9cSGregory Neil Shapiro #  define SSL_CTX_use_cert(ssl_ctx, certfile) \
1282da7d7b9cSGregory Neil Shapiro 	SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile)
1283da7d7b9cSGregory Neil Shapiro #  define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_chain_file"
1284da7d7b9cSGregory Neil Shapiro # else
1285da7d7b9cSGregory Neil Shapiro #  define SSL_CTX_use_cert(ssl_ctx, certfile) \
1286da7d7b9cSGregory Neil Shapiro 	SSL_CTX_use_certificate_file(ssl_ctx, certfile, SSL_FILETYPE_PEM)
1287da7d7b9cSGregory Neil Shapiro #  define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_file"
1288da7d7b9cSGregory Neil Shapiro # endif
1289da7d7b9cSGregory Neil Shapiro 
129040266059SGregory Neil Shapiro 	/* get the certificate file */
129140266059SGregory Neil Shapiro 	if (bitset(TLS_S_CERT_OK, status) &&
1292da7d7b9cSGregory Neil Shapiro 	    SSL_CTX_use_cert(*ctx, certfile) <= 0)
129340266059SGregory Neil Shapiro 	{
129440266059SGregory Neil Shapiro 		if (LogLevel > 7)
129540266059SGregory Neil Shapiro 		{
129640266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
1297da7d7b9cSGregory Neil Shapiro 				  "STARTTLS=%s, error: %s(%s) failed",
1298da7d7b9cSGregory Neil Shapiro 				  who, SSL_CTX_USE_CERT, certfile);
12995b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
130040266059SGregory Neil Shapiro 		}
130140266059SGregory Neil Shapiro 		if (bitset(TLS_I_USE_CERT, req))
130240266059SGregory Neil Shapiro 			return false;
130340266059SGregory Neil Shapiro 	}
130440266059SGregory Neil Shapiro 
130540266059SGregory Neil Shapiro 	/* check the private key */
130640266059SGregory Neil Shapiro 	if (bitset(TLS_S_KEY_OK, status) &&
130740266059SGregory Neil Shapiro 	    (r = SSL_CTX_check_private_key(*ctx)) <= 0)
130840266059SGregory Neil Shapiro 	{
130940266059SGregory Neil Shapiro 		/* Private key does not match the certificate public key */
131040266059SGregory Neil Shapiro 		if (LogLevel > 5)
131140266059SGregory Neil Shapiro 		{
131240266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
131340266059SGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_CTX_check_private_key failed(%s): %d",
131440266059SGregory Neil Shapiro 				  who, keyfile, r);
13155b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
131640266059SGregory Neil Shapiro 		}
131740266059SGregory Neil Shapiro 		if (bitset(TLS_I_USE_KEY, req))
131840266059SGregory Neil Shapiro 			return false;
131940266059SGregory Neil Shapiro 	}
132040266059SGregory Neil Shapiro 
132140266059SGregory Neil Shapiro 	/* XXX this code is pretty much duplicated from above! */
132240266059SGregory Neil Shapiro 
132340266059SGregory Neil Shapiro 	/* load private key */
132440266059SGregory Neil Shapiro 	if (bitset(TLS_S_KEY2_OK, status) &&
132540266059SGregory Neil Shapiro 	    SSL_CTX_use_PrivateKey_file(*ctx, kf2, SSL_FILETYPE_PEM) <= 0)
132640266059SGregory Neil Shapiro 	{
132740266059SGregory Neil Shapiro 		if (LogLevel > 7)
132840266059SGregory Neil Shapiro 		{
132940266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
133040266059SGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed",
133140266059SGregory Neil Shapiro 				  who, kf2);
13325b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
133340266059SGregory Neil Shapiro 		}
133440266059SGregory Neil Shapiro 	}
133540266059SGregory Neil Shapiro 
133640266059SGregory Neil Shapiro 	/* get the certificate file */
133740266059SGregory Neil Shapiro 	if (bitset(TLS_S_CERT2_OK, status) &&
1338da7d7b9cSGregory Neil Shapiro 	    SSL_CTX_use_cert(*ctx, cf2) <= 0)
133940266059SGregory Neil Shapiro 	{
134040266059SGregory Neil Shapiro 		if (LogLevel > 7)
134140266059SGregory Neil Shapiro 		{
134240266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
1343da7d7b9cSGregory Neil Shapiro 				  "STARTTLS=%s, error: %s(%s) failed",
1344da7d7b9cSGregory Neil Shapiro 				  who, SSL_CTX_USE_CERT, cf2);
13455b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
134640266059SGregory Neil Shapiro 		}
134740266059SGregory Neil Shapiro 	}
134840266059SGregory Neil Shapiro 
134940266059SGregory Neil Shapiro 	/* also check the private key */
135040266059SGregory Neil Shapiro 	if (bitset(TLS_S_KEY2_OK, status) &&
135140266059SGregory Neil Shapiro 	    (r = SSL_CTX_check_private_key(*ctx)) <= 0)
135240266059SGregory Neil Shapiro 	{
135340266059SGregory Neil Shapiro 		/* Private key does not match the certificate public key */
135440266059SGregory Neil Shapiro 		if (LogLevel > 5)
135540266059SGregory Neil Shapiro 		{
135640266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
135740266059SGregory Neil Shapiro 				  "STARTTLS=%s, error: SSL_CTX_check_private_key 2 failed: %d",
135840266059SGregory Neil Shapiro 				  who, r);
13595b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 9, who);
136040266059SGregory Neil Shapiro 		}
136140266059SGregory Neil Shapiro 	}
136240266059SGregory Neil Shapiro 
136340266059SGregory Neil Shapiro 	/* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */
1364af9557fdSGregory Neil Shapiro 
1365af9557fdSGregory Neil Shapiro # if SM_SSL_OP_TLS_BLOCK_PADDING_BUG
1366af9557fdSGregory Neil Shapiro 
1367af9557fdSGregory Neil Shapiro 	/*
1368af9557fdSGregory Neil Shapiro 	**  In OpenSSL 0.9.8[ab], enabling zlib compression breaks the
1369af9557fdSGregory Neil Shapiro 	**  padding bug work-around, leading to false positives and
1370af9557fdSGregory Neil Shapiro 	**  failed connections. We may not interoperate with systems
1371af9557fdSGregory Neil Shapiro 	**  with the bug, but this is better than breaking on all 0.9.8[ab]
1372af9557fdSGregory Neil Shapiro 	**  systems that have zlib support enabled.
1373af9557fdSGregory Neil Shapiro 	**  Note: this checks the runtime version of the library, not
1374af9557fdSGregory Neil Shapiro 	**  just the compile time version.
1375af9557fdSGregory Neil Shapiro 	*/
1376af9557fdSGregory Neil Shapiro 
13775b0945b5SGregory Neil Shapiro 	rt_version = TLS_version_num();
1378af9557fdSGregory Neil Shapiro 	if (rt_version >= 0x00908000L && rt_version <= 0x0090802fL)
1379af9557fdSGregory Neil Shapiro 	{
1380af9557fdSGregory Neil Shapiro 		comp_methods = SSL_COMP_get_compression_methods();
1381af9557fdSGregory Neil Shapiro 		if (comp_methods != NULL && sk_SSL_COMP_num(comp_methods) > 0)
1382af9557fdSGregory Neil Shapiro 			options &= ~SSL_OP_TLS_BLOCK_PADDING_BUG;
1383af9557fdSGregory Neil Shapiro 	}
1384af9557fdSGregory Neil Shapiro # endif
1385da7d7b9cSGregory Neil Shapiro 	SSL_CTX_set_options(*ctx, (long) options);
138640266059SGregory Neil Shapiro 
138740266059SGregory Neil Shapiro # if !NO_DH
138840266059SGregory Neil Shapiro 	/* Diffie-Hellman initialization */
138940266059SGregory Neil Shapiro 	if (bitset(TLS_I_TRY_DH, req))
139040266059SGregory Neil Shapiro 	{
13915b0945b5SGregory Neil Shapiro #  if TLS_EC == 1
13925dd76dd0SGregory Neil Shapiro 		EC_KEY *ecdh;
13935b0945b5SGregory Neil Shapiro #  endif
1394da7d7b9cSGregory Neil Shapiro 
1395*d39bd2c1SGregory Neil Shapiro 		if (tTd(96, 81))
1396*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("inittls: where=try_dh, req=%#lx, status=%#lx\n",
1397da7d7b9cSGregory Neil Shapiro 				req, status);
139840266059SGregory Neil Shapiro 		if (bitset(TLS_S_DHPAR_OK, status))
139940266059SGregory Neil Shapiro 		{
140040266059SGregory Neil Shapiro 			BIO *bio;
140140266059SGregory Neil Shapiro 
140240266059SGregory Neil Shapiro 			if ((bio = BIO_new_file(dhparam, "r")) != NULL)
140340266059SGregory Neil Shapiro 			{
140440266059SGregory Neil Shapiro 				dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
140540266059SGregory Neil Shapiro 				BIO_free(bio);
140640266059SGregory Neil Shapiro 				if (dh == NULL && LogLevel > 7)
140740266059SGregory Neil Shapiro 				{
140840266059SGregory Neil Shapiro 					unsigned long err;
140940266059SGregory Neil Shapiro 
141040266059SGregory Neil Shapiro 					err = ERR_get_error();
141140266059SGregory Neil Shapiro 					sm_syslog(LOG_WARNING, NOQID,
141240266059SGregory Neil Shapiro 						  "STARTTLS=%s, error: cannot read DH parameters(%s): %s",
141340266059SGregory Neil Shapiro 						  who, dhparam,
141440266059SGregory Neil Shapiro 						  ERR_error_string(err, NULL));
14155b0945b5SGregory Neil Shapiro 					tlslogerr(LOG_WARNING, 9, who);
1416da7d7b9cSGregory Neil Shapiro 					SET_DH_DFL;
141740266059SGregory Neil Shapiro 				}
141840266059SGregory Neil Shapiro 			}
141940266059SGregory Neil Shapiro 			else
142040266059SGregory Neil Shapiro 			{
142140266059SGregory Neil Shapiro 				if (LogLevel > 5)
142240266059SGregory Neil Shapiro 				{
142340266059SGregory Neil Shapiro 					sm_syslog(LOG_WARNING, NOQID,
142440266059SGregory Neil Shapiro 						  "STARTTLS=%s, error: BIO_new_file(%s) failed",
142540266059SGregory Neil Shapiro 						  who, dhparam);
14265b0945b5SGregory Neil Shapiro 					tlslogerr(LOG_WARNING, 9, who);
142740266059SGregory Neil Shapiro 				}
142840266059SGregory Neil Shapiro 			}
142940266059SGregory Neil Shapiro 		}
1430*d39bd2c1SGregory Neil Shapiro # if MTA_DH_AUTO
1431*d39bd2c1SGregory Neil Shapiro 		if (dh == NULL && bitset(TLS_I_DHAUTO, req))
1432*d39bd2c1SGregory Neil Shapiro 			SSL_CTX_set_dh_auto(*ctx, 1);
1433*d39bd2c1SGregory Neil Shapiro 		else
1434*d39bd2c1SGregory Neil Shapiro # endif
14355dd76dd0SGregory Neil Shapiro 		if (dh == NULL && bitset(TLS_I_DH1024|TLS_I_DH2048, req))
143640266059SGregory Neil Shapiro 		{
14375dd76dd0SGregory Neil Shapiro 			int bits;
143840266059SGregory Neil Shapiro 			DSA *dsa;
143940266059SGregory Neil Shapiro 
14405dd76dd0SGregory Neil Shapiro 			bits = bitset(TLS_I_DH2048, req) ? 2048 : 1024;
14415dd76dd0SGregory Neil Shapiro 			if (tTd(96, 2))
14425dd76dd0SGregory Neil Shapiro 				sm_dprintf("inittls: Generating %d bit DH parameters\n", bits);
14435dd76dd0SGregory Neil Shapiro 
14445b0945b5SGregory Neil Shapiro #  if MTA_HAVE_DSA_GENERATE_EX
144541451aa3SJung-uk Kim 			dsa = DSA_new();
14465b0945b5SGregory Neil Shapiro 			if (dsa != NULL)
14475b0945b5SGregory Neil Shapiro 			{
14485b0945b5SGregory Neil Shapiro 				r = DSA_generate_parameters_ex(dsa, bits, NULL,
14495b0945b5SGregory Neil Shapiro 							0, NULL, NULL, NULL);
14505b0945b5SGregory Neil Shapiro 				if (r != 0)
145140266059SGregory Neil Shapiro 					dh = DSA_dup_DH(dsa);
14525b0945b5SGregory Neil Shapiro 			}
14535b0945b5SGregory Neil Shapiro #  else
14545b0945b5SGregory Neil Shapiro 			/* this takes a while! */
14555b0945b5SGregory Neil Shapiro 			dsa = DSA_generate_parameters(bits, NULL, 0, NULL,
14565b0945b5SGregory Neil Shapiro 						      NULL, 0, NULL);
14575b0945b5SGregory Neil Shapiro 			dh = DSA_dup_DH(dsa);
14585b0945b5SGregory Neil Shapiro #  endif
145940266059SGregory Neil Shapiro 			DSA_free(dsa);
146040266059SGregory Neil Shapiro 		}
1461da7d7b9cSGregory Neil Shapiro 		else if (dh == NULL && bitset(TLS_I_DHFIXED, req))
1462da7d7b9cSGregory Neil Shapiro 		{
1463da7d7b9cSGregory Neil Shapiro 			if (tTd(96, 2))
1464da7d7b9cSGregory Neil Shapiro 				sm_dprintf("inittls: Using precomputed 2048 bit DH parameters\n");
1465da7d7b9cSGregory Neil Shapiro 			dh = get_dh2048();
1466da7d7b9cSGregory Neil Shapiro 		}
1467da7d7b9cSGregory Neil Shapiro 		else if (dh == NULL && bitset(TLS_I_DH512, req))
14685dd76dd0SGregory Neil Shapiro 		{
14695dd76dd0SGregory Neil Shapiro 			if (tTd(96, 2))
14705dd76dd0SGregory Neil Shapiro 				sm_dprintf("inittls: Using precomputed 512 bit DH parameters\n");
147140266059SGregory Neil Shapiro 			dh = get_dh512();
14725dd76dd0SGregory Neil Shapiro 		}
1473*d39bd2c1SGregory Neil Shapiro 		if (dh == NULL && !bitset(TLS_I_DHAUTO, req))
147440266059SGregory Neil Shapiro 		{
147540266059SGregory Neil Shapiro 			if (LogLevel > 9)
147640266059SGregory Neil Shapiro 			{
147740266059SGregory Neil Shapiro 				unsigned long err;
147840266059SGregory Neil Shapiro 
147940266059SGregory Neil Shapiro 				err = ERR_get_error();
148040266059SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
148140266059SGregory Neil Shapiro 					  "STARTTLS=%s, error: cannot read or set DH parameters(%s): %s",
148240266059SGregory Neil Shapiro 					  who, dhparam,
148340266059SGregory Neil Shapiro 					  ERR_error_string(err, NULL));
148440266059SGregory Neil Shapiro 			}
148540266059SGregory Neil Shapiro 			if (bitset(TLS_I_REQ_DH, req))
148640266059SGregory Neil Shapiro 				return false;
148740266059SGregory Neil Shapiro 		}
1488*d39bd2c1SGregory Neil Shapiro 		else if (dh != NULL)
148940266059SGregory Neil Shapiro 		{
149040266059SGregory Neil Shapiro 			/* important to avoid small subgroup attacks */
149140266059SGregory Neil Shapiro 			SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_DH_USE);
14925dd76dd0SGregory Neil Shapiro 
14935dd76dd0SGregory Neil Shapiro 			SSL_CTX_set_tmp_dh(*ctx, dh);
149440266059SGregory Neil Shapiro 			if (LogLevel > 13)
149540266059SGregory Neil Shapiro 				sm_syslog(LOG_INFO, NOQID,
149640266059SGregory Neil Shapiro 					  "STARTTLS=%s, Diffie-Hellman init, key=%d bit (%c)",
149740266059SGregory Neil Shapiro 					  who, 8 * DH_size(dh), *dhparam);
149840266059SGregory Neil Shapiro 			DH_free(dh);
149940266059SGregory Neil Shapiro 		}
15005dd76dd0SGregory Neil Shapiro 
15015b0945b5SGregory Neil Shapiro #  if TLS_EC == 2
15025b0945b5SGregory Neil Shapiro 		SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_ECDH_USE);
15035b0945b5SGregory Neil Shapiro 		SSL_CTX_set_ecdh_auto(*ctx, 1);
15045b0945b5SGregory Neil Shapiro #  elif TLS_EC == 1
15055dd76dd0SGregory Neil Shapiro 		ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
15065dd76dd0SGregory Neil Shapiro 		if (ecdh != NULL)
15075dd76dd0SGregory Neil Shapiro 		{
15085dd76dd0SGregory Neil Shapiro 			SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_ECDH_USE);
15095dd76dd0SGregory Neil Shapiro 			SSL_CTX_set_tmp_ecdh(*ctx, ecdh);
15105dd76dd0SGregory Neil Shapiro 			EC_KEY_free(ecdh);
15115dd76dd0SGregory Neil Shapiro 		}
15125b0945b5SGregory Neil Shapiro 		else if (LogLevel > 9)
15135b0945b5SGregory Neil Shapiro 		{
15145b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
15155b0945b5SGregory Neil Shapiro 				  "STARTTLS=%s, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)=failed, error=%s",
15165b0945b5SGregory Neil Shapiro 				  who, ERR_error_string(ERR_get_error(), NULL));
15175b0945b5SGregory Neil Shapiro 		}
15185b0945b5SGregory Neil Shapiro #  endif /* TLS_EC */
15195dd76dd0SGregory Neil Shapiro 
152040266059SGregory Neil Shapiro 	}
152140266059SGregory Neil Shapiro # endif /* !NO_DH */
152240266059SGregory Neil Shapiro 
152340266059SGregory Neil Shapiro 	/* XXX do we need this cache here? */
152440266059SGregory Neil Shapiro 	if (bitset(TLS_I_CACHE, req))
15254e4196cbSGregory Neil Shapiro 	{
15264e4196cbSGregory Neil Shapiro 		SSL_CTX_sess_set_cache_size(*ctx, 1);
15274e4196cbSGregory Neil Shapiro 		SSL_CTX_set_timeout(*ctx, 1);
15284e4196cbSGregory Neil Shapiro 		SSL_CTX_set_session_id_context(*ctx,
15294e4196cbSGregory Neil Shapiro 			(void *) &server_session_id_context,
15304e4196cbSGregory Neil Shapiro 			sizeof(server_session_id_context));
15314e4196cbSGregory Neil Shapiro 		(void) SSL_CTX_set_session_cache_mode(*ctx,
15324e4196cbSGregory Neil Shapiro 				SSL_SESS_CACHE_SERVER);
15334e4196cbSGregory Neil Shapiro 	}
15344e4196cbSGregory Neil Shapiro 	else
15354e4196cbSGregory Neil Shapiro 	{
15364e4196cbSGregory Neil Shapiro 		(void) SSL_CTX_set_session_cache_mode(*ctx,
15374e4196cbSGregory Neil Shapiro 				SSL_SESS_CACHE_OFF);
15384e4196cbSGregory Neil Shapiro 	}
153940266059SGregory Neil Shapiro 
154040266059SGregory Neil Shapiro 	/* load certificate locations and default CA paths */
154140266059SGregory Neil Shapiro 	if (bitset(TLS_S_CERTP_EX, status) && bitset(TLS_S_CERTF_EX, status))
154240266059SGregory Neil Shapiro 	{
154340266059SGregory Neil Shapiro 		if ((r = SSL_CTX_load_verify_locations(*ctx, cacertfile,
154440266059SGregory Neil Shapiro 						       cacertpath)) == 1)
154540266059SGregory Neil Shapiro 		{
15465b0945b5SGregory Neil Shapiro # if !TLS_NO_RSA && MTA_RSA_TMP_CB
154740266059SGregory Neil Shapiro 			if (bitset(TLS_I_RSA_TMP, req))
154840266059SGregory Neil Shapiro 				SSL_CTX_set_tmp_rsa_callback(*ctx, tmp_rsa_key);
15495b0945b5SGregory Neil Shapiro # endif
155040266059SGregory Neil Shapiro 
15515b0945b5SGregory Neil Shapiro 			if (srv)
15525b0945b5SGregory Neil Shapiro 			{
155340266059SGregory Neil Shapiro 				SSL_CTX_set_client_CA_list(*ctx,
155440266059SGregory Neil Shapiro 					SSL_load_client_CA_file(cacertfile));
155540266059SGregory Neil Shapiro 			}
15565b0945b5SGregory Neil Shapiro 		}
155740266059SGregory Neil Shapiro 		else
155840266059SGregory Neil Shapiro 		{
155940266059SGregory Neil Shapiro 			/*
156040266059SGregory Neil Shapiro 			**  can't load CA data; do we care?
156140266059SGregory Neil Shapiro 			**  the data is necessary to authenticate the client,
156240266059SGregory Neil Shapiro 			**  which in turn would be necessary
156340266059SGregory Neil Shapiro 			**  if we want to allow relaying based on it.
156440266059SGregory Neil Shapiro 			*/
15655b0945b5SGregory Neil Shapiro 
156640266059SGregory Neil Shapiro 			if (LogLevel > 5)
156740266059SGregory Neil Shapiro 			{
156840266059SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
156940266059SGregory Neil Shapiro 					  "STARTTLS=%s, error: load verify locs %s, %s failed: %d",
157040266059SGregory Neil Shapiro 					  who, cacertpath, cacertfile, r);
15715b0945b5SGregory Neil Shapiro 				tlslogerr(LOG_WARNING,
15725b0945b5SGregory Neil Shapiro 					bitset(TLS_I_VRFY_LOC, req) ? 8 : 9,
15735b0945b5SGregory Neil Shapiro 					who);
157440266059SGregory Neil Shapiro 			}
157540266059SGregory Neil Shapiro 			if (bitset(TLS_I_VRFY_LOC, req))
157640266059SGregory Neil Shapiro 				return false;
157740266059SGregory Neil Shapiro 		}
157840266059SGregory Neil Shapiro 	}
157940266059SGregory Neil Shapiro 
1580*d39bd2c1SGregory Neil Shapiro 	/*
1581*d39bd2c1SGregory Neil Shapiro 	**  XXX currently we could call tls_set_verify()
1582*d39bd2c1SGregory Neil Shapiro 	**  but we hope that that function will later on
1583*d39bd2c1SGregory Neil Shapiro 	**  only set the mode per connection.
1584*d39bd2c1SGregory Neil Shapiro 	*/
1585*d39bd2c1SGregory Neil Shapiro 
1586*d39bd2c1SGregory Neil Shapiro 	SSL_CTX_set_verify(*ctx,
1587*d39bd2c1SGregory Neil Shapiro 		bitset(TLS_I_NO_VRFY, req) ? SSL_VERIFY_NONE
1588*d39bd2c1SGregory Neil Shapiro 					   : SSL_VERIFY_PEER,
1589*d39bd2c1SGregory Neil Shapiro 		NULL);
1590*d39bd2c1SGregory Neil Shapiro 
1591*d39bd2c1SGregory Neil Shapiro 	/*
1592*d39bd2c1SGregory Neil Shapiro 	**  Always use our callback instead of the builtin version.
1593*d39bd2c1SGregory Neil Shapiro 	**  We have to install our own verify callback:
1594*d39bd2c1SGregory Neil Shapiro 	**  SSL_VERIFY_PEER requests a client cert but even
1595*d39bd2c1SGregory Neil Shapiro 	**  though *FAIL_IF* isn't set, the connection
1596*d39bd2c1SGregory Neil Shapiro 	**  will be aborted if the client presents a cert
1597*d39bd2c1SGregory Neil Shapiro 	**  that is not "liked" (can't be verified?) by
1598*d39bd2c1SGregory Neil Shapiro 	**  the TLS library :-(
1599*d39bd2c1SGregory Neil Shapiro 	*/
1600*d39bd2c1SGregory Neil Shapiro 
1601*d39bd2c1SGregory Neil Shapiro 	SSL_CTX_set_cert_verify_callback(*ctx, tls_verify_cb, NULL);
1602*d39bd2c1SGregory Neil Shapiro 
160340266059SGregory Neil Shapiro 	/* XXX: make this dependent on an option? */
160440266059SGregory Neil Shapiro 	if (tTd(96, 9))
160540266059SGregory Neil Shapiro 		SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb);
160640266059SGregory Neil Shapiro 
160740266059SGregory Neil Shapiro 	/* install our own cipher list */
160840266059SGregory Neil Shapiro 	if (CipherList != NULL && *CipherList != '\0')
160940266059SGregory Neil Shapiro 	{
161040266059SGregory Neil Shapiro 		if (SSL_CTX_set_cipher_list(*ctx, CipherList) <= 0)
161140266059SGregory Neil Shapiro 		{
161240266059SGregory Neil Shapiro 			if (LogLevel > 7)
161340266059SGregory Neil Shapiro 			{
161440266059SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
161540266059SGregory Neil Shapiro 					  "STARTTLS=%s, error: SSL_CTX_set_cipher_list(%s) failed, list ignored",
161640266059SGregory Neil Shapiro 					  who, CipherList);
161740266059SGregory Neil Shapiro 
16185b0945b5SGregory Neil Shapiro 				tlslogerr(LOG_WARNING, 9, who);
161940266059SGregory Neil Shapiro 			}
162040266059SGregory Neil Shapiro 			/* failure if setting to this list is required? */
162140266059SGregory Neil Shapiro 		}
162240266059SGregory Neil Shapiro 	}
1623da7d7b9cSGregory Neil Shapiro 
16242fb4f839SGregory Neil Shapiro # if MTA_HAVE_TLSv1_3
16252fb4f839SGregory Neil Shapiro 	/* install our own cipher suites */
16262fb4f839SGregory Neil Shapiro 	if (!SM_IS_EMPTY(CipherSuites))
16272fb4f839SGregory Neil Shapiro 	{
16282fb4f839SGregory Neil Shapiro 		if (SSL_CTX_set_ciphersuites(*ctx, CipherSuites) <= 0)
16292fb4f839SGregory Neil Shapiro 		{
16302fb4f839SGregory Neil Shapiro 			if (LogLevel > 7)
16312fb4f839SGregory Neil Shapiro 			{
16322fb4f839SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
16332fb4f839SGregory Neil Shapiro 					  "STARTTLS=%s, error: SSL_CTX_set_ciphersuites(%s) failed, suites ignored",
16342fb4f839SGregory Neil Shapiro 					  who, CipherSuites);
16352fb4f839SGregory Neil Shapiro 
16362fb4f839SGregory Neil Shapiro 				tlslogerr(LOG_WARNING, 9, who);
16372fb4f839SGregory Neil Shapiro 			}
16382fb4f839SGregory Neil Shapiro 			/* failure if setting to this suites is required? */
16392fb4f839SGregory Neil Shapiro 		}
16402fb4f839SGregory Neil Shapiro 	}
16412fb4f839SGregory Neil Shapiro # endif /* MTA_HAVE_TLSv1_3 */
16422fb4f839SGregory Neil Shapiro 
164340266059SGregory Neil Shapiro 	if (LogLevel > 12)
164440266059SGregory Neil Shapiro 		sm_syslog(LOG_INFO, NOQID, "STARTTLS=%s, init=%d", who, ok);
164540266059SGregory Neil Shapiro 
164640266059SGregory Neil Shapiro # if 0
164740266059SGregory Neil Shapiro 	/*
164840266059SGregory Neil Shapiro 	**  this label is required if we want to have a "clean" exit
164940266059SGregory Neil Shapiro 	**  see the comments above at the initialization of cf2
165040266059SGregory Neil Shapiro 	*/
165140266059SGregory Neil Shapiro 
165240266059SGregory Neil Shapiro     endinittls:
165340266059SGregory Neil Shapiro # endif /* 0 */
165440266059SGregory Neil Shapiro 
165540266059SGregory Neil Shapiro 	/* undo damage to global variables */
165640266059SGregory Neil Shapiro 	if (cf2 != NULL)
165740266059SGregory Neil Shapiro 		*--cf2 = ',';
165840266059SGregory Neil Shapiro 	if (kf2 != NULL)
165940266059SGregory Neil Shapiro 		*--kf2 = ',';
166040266059SGregory Neil Shapiro 
166140266059SGregory Neil Shapiro 	return ok;
166240266059SGregory Neil Shapiro }
1663da7d7b9cSGregory Neil Shapiro 
1664da7d7b9cSGregory Neil Shapiro /*
1665da7d7b9cSGregory Neil Shapiro **  CERT_FP -- get cert fingerprint
1666da7d7b9cSGregory Neil Shapiro **
1667da7d7b9cSGregory Neil Shapiro **	Parameters:
1668da7d7b9cSGregory Neil Shapiro **		cert -- TLS cert
16695b0945b5SGregory Neil Shapiro **		evp_digest -- digest algorithm
1670da7d7b9cSGregory Neil Shapiro **		mac -- macro storage
1671da7d7b9cSGregory Neil Shapiro **		macro -- where to store cert fp
1672da7d7b9cSGregory Neil Shapiro **
1673da7d7b9cSGregory Neil Shapiro **	Returns:
1674da7d7b9cSGregory Neil Shapiro **		<=0: cert fp calculation failed
1675da7d7b9cSGregory Neil Shapiro **		>0: cert fp calculation ok
1676da7d7b9cSGregory Neil Shapiro */
1677da7d7b9cSGregory Neil Shapiro 
1678da7d7b9cSGregory Neil Shapiro static int
1679da7d7b9cSGregory Neil Shapiro cert_fp(cert, evp_digest, mac, macro)
1680da7d7b9cSGregory Neil Shapiro 	X509 *cert;
1681da7d7b9cSGregory Neil Shapiro 	const EVP_MD *evp_digest;
1682da7d7b9cSGregory Neil Shapiro 	MACROS_T *mac;
1683da7d7b9cSGregory Neil Shapiro 	char *macro;
1684da7d7b9cSGregory Neil Shapiro {
1685da7d7b9cSGregory Neil Shapiro 	unsigned int n;
1686da7d7b9cSGregory Neil Shapiro 	int r;
1687da7d7b9cSGregory Neil Shapiro 	unsigned char md[EVP_MAX_MD_SIZE];
1688da7d7b9cSGregory Neil Shapiro 	char md5h[EVP_MAX_MD_SIZE * 3];
1689da7d7b9cSGregory Neil Shapiro 	static const char hexcodes[] = "0123456789ABCDEF";
1690da7d7b9cSGregory Neil Shapiro 
1691da7d7b9cSGregory Neil Shapiro 	n = 0;
1692*d39bd2c1SGregory Neil Shapiro 	if ((r = X509_digest(cert, evp_digest, md, &n)) == 0 || n <= 0)
1693da7d7b9cSGregory Neil Shapiro 	{
1694da7d7b9cSGregory Neil Shapiro 		macdefine(mac, A_TEMP, macid(macro), "");
1695*d39bd2c1SGregory Neil Shapiro 		return (0 == r) ? 0 : n;
1696da7d7b9cSGregory Neil Shapiro 	}
1697da7d7b9cSGregory Neil Shapiro 
1698da7d7b9cSGregory Neil Shapiro 	SM_ASSERT((n * 3) + 2 < sizeof(md5h));
1699da7d7b9cSGregory Neil Shapiro 	for (r = 0; r < (int) n; r++)
1700da7d7b9cSGregory Neil Shapiro 	{
1701da7d7b9cSGregory Neil Shapiro 		md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4];
1702da7d7b9cSGregory Neil Shapiro 		md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)];
1703da7d7b9cSGregory Neil Shapiro 		md5h[(r * 3) + 2] = ':';
1704da7d7b9cSGregory Neil Shapiro 	}
1705da7d7b9cSGregory Neil Shapiro 	md5h[(n * 3) - 1] = '\0';
1706da7d7b9cSGregory Neil Shapiro 	macdefine(mac, A_TEMP, macid(macro), md5h);
1707da7d7b9cSGregory Neil Shapiro 	return 1;
1708da7d7b9cSGregory Neil Shapiro }
1709da7d7b9cSGregory Neil Shapiro 
17105b0945b5SGregory Neil Shapiro /* host for logging */
17115b0945b5SGregory Neil Shapiro #define whichhost	host == NULL ? "local" : host
17125b0945b5SGregory Neil Shapiro 
17135b0945b5SGregory Neil Shapiro # if _FFR_TLS_ALTNAMES
17145b0945b5SGregory Neil Shapiro 
17155b0945b5SGregory Neil Shapiro /*
17165b0945b5SGregory Neil Shapiro **  CLEARCLASS -- clear the specified class (called from stabapply)
17175b0945b5SGregory Neil Shapiro **
17185b0945b5SGregory Neil Shapiro **	Parameters:
17195b0945b5SGregory Neil Shapiro **		s -- STAB
17205b0945b5SGregory Neil Shapiro **		id -- class id
17215b0945b5SGregory Neil Shapiro **
17225b0945b5SGregory Neil Shapiro **	Returns:
17235b0945b5SGregory Neil Shapiro **		none.
17245b0945b5SGregory Neil Shapiro */
17255b0945b5SGregory Neil Shapiro 
17265b0945b5SGregory Neil Shapiro static void
17275b0945b5SGregory Neil Shapiro clearclass(s, id)
17285b0945b5SGregory Neil Shapiro 	STAB *s;
17295b0945b5SGregory Neil Shapiro 	int id;
17305b0945b5SGregory Neil Shapiro {
17315b0945b5SGregory Neil Shapiro 	if (s->s_symtype != ST_CLASS)
17325b0945b5SGregory Neil Shapiro 		return;
17335b0945b5SGregory Neil Shapiro 	if (bitnset(bitidx(id), s->s_class))
17345b0945b5SGregory Neil Shapiro 		clrbitn(bitidx(id), s->s_class);
17355b0945b5SGregory Neil Shapiro }
17365b0945b5SGregory Neil Shapiro 
17375b0945b5SGregory Neil Shapiro /*
17385b0945b5SGregory Neil Shapiro **  GETALTNAMES -- set subject_alt_name
17395b0945b5SGregory Neil Shapiro **
17405b0945b5SGregory Neil Shapiro **	Parameters:
17415b0945b5SGregory Neil Shapiro **		cert -- cert
17425b0945b5SGregory Neil Shapiro **		srv -- server side?
17435b0945b5SGregory Neil Shapiro **		host -- hostname of other side
17445b0945b5SGregory Neil Shapiro **
17455b0945b5SGregory Neil Shapiro **	Returns:
17465b0945b5SGregory Neil Shapiro **		none.
17475b0945b5SGregory Neil Shapiro */
17485b0945b5SGregory Neil Shapiro 
17495b0945b5SGregory Neil Shapiro static void
17505b0945b5SGregory Neil Shapiro getaltnames(cert, srv, host)
17515b0945b5SGregory Neil Shapiro 	X509 *cert;
17525b0945b5SGregory Neil Shapiro 	bool srv;
17535b0945b5SGregory Neil Shapiro 	const char *host;
17545b0945b5SGregory Neil Shapiro {
17555b0945b5SGregory Neil Shapiro 	STACK_OF(GENERAL_NAME) *gens;
17565b0945b5SGregory Neil Shapiro 	int i, j, len, r;
17575b0945b5SGregory Neil Shapiro 	const GENERAL_NAME *gn;
17585b0945b5SGregory Neil Shapiro 	char *dnsname, *who;
17595b0945b5SGregory Neil Shapiro 
17605b0945b5SGregory Neil Shapiro 	if (!SetCertAltnames)
17615b0945b5SGregory Neil Shapiro 		return;
17625b0945b5SGregory Neil Shapiro 	who = srv ? "server" : "client";
17635b0945b5SGregory Neil Shapiro 	gens = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
17645b0945b5SGregory Neil Shapiro 	if (gens == NULL)
17655b0945b5SGregory Neil Shapiro 		return;
17665b0945b5SGregory Neil Shapiro 
17675b0945b5SGregory Neil Shapiro 	r = sk_GENERAL_NAME_num(gens);
17685b0945b5SGregory Neil Shapiro 	for (i = 0; i < r; i++)
17695b0945b5SGregory Neil Shapiro 	{
17705b0945b5SGregory Neil Shapiro 		gn = sk_GENERAL_NAME_value(gens, i);
17715b0945b5SGregory Neil Shapiro 		if (gn == NULL || gn->type != GEN_DNS)
17725b0945b5SGregory Neil Shapiro 			continue;
17735b0945b5SGregory Neil Shapiro 
17745b0945b5SGregory Neil Shapiro 		/* Ensure data is IA5 */
17755b0945b5SGregory Neil Shapiro 		if (ASN1_STRING_type(gn->d.ia5) != V_ASN1_IA5STRING)
17765b0945b5SGregory Neil Shapiro 		{
17775b0945b5SGregory Neil Shapiro 			if (LogLevel > 6)
17785b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_INFO, NOQID,
17795b0945b5SGregory Neil Shapiro 					"STARTTLS=%s, relay=%.100s, field=AltName, status=value contains non IA5",
17805b0945b5SGregory Neil Shapiro 					who, whichhost);
17815b0945b5SGregory Neil Shapiro 			continue;
17825b0945b5SGregory Neil Shapiro 		}
17835b0945b5SGregory Neil Shapiro 		dnsname = (char *) MTA_ASN1_STRING_data(gn->d.ia5);
17845b0945b5SGregory Neil Shapiro 		if (dnsname == NULL)
17855b0945b5SGregory Neil Shapiro 			continue;
17865b0945b5SGregory Neil Shapiro 		len = ASN1_STRING_length(gn->d.ia5);
17875b0945b5SGregory Neil Shapiro 
17885b0945b5SGregory Neil Shapiro 		/*
17895b0945b5SGregory Neil Shapiro 		**  "remove" trailing NULs (except for one of course),
17905b0945b5SGregory Neil Shapiro 		**  those can happen and are OK (not a sign of an attack)
17915b0945b5SGregory Neil Shapiro 		*/
17925b0945b5SGregory Neil Shapiro 
17935b0945b5SGregory Neil Shapiro 		while (len > 0 && '\0' == dnsname[len - 1])
17945b0945b5SGregory Neil Shapiro 			len--;
17955b0945b5SGregory Neil Shapiro 
17965b0945b5SGregory Neil Shapiro #define ISPRINT(c)	(isascii(c) && isprint(c))
17975b0945b5SGregory Neil Shapiro 
17985b0945b5SGregory Neil Shapiro 		/* just check for printable char for now */
17995b0945b5SGregory Neil Shapiro 		for (j = 0; j < len && ISPRINT(dnsname[j]); j++)
18005b0945b5SGregory Neil Shapiro 			;
18015b0945b5SGregory Neil Shapiro 		if (dnsname[j] != '\0' || len != j)
18025b0945b5SGregory Neil Shapiro 			continue;
18035b0945b5SGregory Neil Shapiro 
18045b0945b5SGregory Neil Shapiro 		setclass(macid("{cert_altnames}"), xtextify(dnsname, "<>\")"));
18055b0945b5SGregory Neil Shapiro 		if (LogLevel > 14)
18065b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_DEBUG, NOQID,
18075b0945b5SGregory Neil Shapiro 				"STARTTLS=%s, relay=%.100s, AltName=%s",
18085b0945b5SGregory Neil Shapiro 				who, whichhost, xtextify(dnsname, "<>\")"));
18095b0945b5SGregory Neil Shapiro 	}
18105b0945b5SGregory Neil Shapiro }
18115b0945b5SGregory Neil Shapiro # else
18125b0945b5SGregory Neil Shapiro #  define getaltnames(cert, srv, host)
18135b0945b5SGregory Neil Shapiro # endif /* _FFR_TLS_ALTNAMES */
18145b0945b5SGregory Neil Shapiro 
1815*d39bd2c1SGregory Neil Shapiro # if DANE
1816*d39bd2c1SGregory Neil Shapiro 
1817*d39bd2c1SGregory Neil Shapiro /*
1818*d39bd2c1SGregory Neil Shapiro **  DANE_RES -- get DANE result if possible
1819*d39bd2c1SGregory Neil Shapiro **
1820*d39bd2c1SGregory Neil Shapiro **	Parameters:
1821*d39bd2c1SGregory Neil Shapiro **		ssl -- TLS connection structure
1822*d39bd2c1SGregory Neil Shapiro **		dane_vrfy_ctx -- dane verify context
1823*d39bd2c1SGregory Neil Shapiro **
1824*d39bd2c1SGregory Neil Shapiro **	Returns:
1825*d39bd2c1SGregory Neil Shapiro **		SM_SUCCESS: DANE result dane_vrfy_res is valid
1826*d39bd2c1SGregory Neil Shapiro **		SM_NOTDONE: DANE checking not enabled
1827*d39bd2c1SGregory Neil Shapiro **		<0: some error
1828*d39bd2c1SGregory Neil Shapiro */
1829*d39bd2c1SGregory Neil Shapiro 
1830*d39bd2c1SGregory Neil Shapiro static int dane_res __P((SSL *, dane_vrfy_ctx_P));
1831*d39bd2c1SGregory Neil Shapiro 
1832*d39bd2c1SGregory Neil Shapiro static int
1833*d39bd2c1SGregory Neil Shapiro dane_res(ssl, dane_vrfy_ctx)
1834*d39bd2c1SGregory Neil Shapiro 	SSL *ssl;
1835*d39bd2c1SGregory Neil Shapiro 	dane_vrfy_ctx_P dane_vrfy_ctx;
1836*d39bd2c1SGregory Neil Shapiro {
1837*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable
1838*d39bd2c1SGregory Neil Shapiro 	int depth, r;
1839*d39bd2c1SGregory Neil Shapiro 	EVP_PKEY *mspki;
1840*d39bd2c1SGregory Neil Shapiro 	uint8_t usage, selector, mtype;
1841*d39bd2c1SGregory Neil Shapiro 	unsigned const char *rr;
1842*d39bd2c1SGregory Neil Shapiro 	size_t rrlen;
1843*d39bd2c1SGregory Neil Shapiro #  endif
1844*d39bd2c1SGregory Neil Shapiro 
1845*d39bd2c1SGregory Neil Shapiro 	if (NULL == dane_vrfy_ctx)
1846*d39bd2c1SGregory Neil Shapiro 	{
1847*d39bd2c1SGregory Neil Shapiro 		/* can this happen? should it be logged? */
1848*d39bd2c1SGregory Neil Shapiro 		if (tTd(96, 20))
1849*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("ERROR: dane_res: dane_vrfy_ctx=NULL\n");
1850*d39bd2c1SGregory Neil Shapiro 		return SM_NOTDONE;
1851*d39bd2c1SGregory Neil Shapiro 	}
1852*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 20))
1853*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dane_res: dane_vrfy_dane_enabled=%d, chk=%#x, res=%d\n",
1854*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_dane_enabled,
1855*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_chk,
1856*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_res);
1857*d39bd2c1SGregory Neil Shapiro 	if (!VRFY_DANE(dane_vrfy_ctx->dane_vrfy_chk))
1858*d39bd2c1SGregory Neil Shapiro 	{
1859*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_res = DANE_VRFY_NONE;
1860*d39bd2c1SGregory Neil Shapiro 		return SM_NOTDONE;
1861*d39bd2c1SGregory Neil Shapiro 	}
1862*d39bd2c1SGregory Neil Shapiro 	if (dane_vrfy_ctx->dane_vrfy_chk & TLSAFLTEMPVRFY)
1863*d39bd2c1SGregory Neil Shapiro 	{
1864*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_res = DANE_VRFY_TEMP;
1865*d39bd2c1SGregory Neil Shapiro 		return SM_SUCCESS;
1866*d39bd2c1SGregory Neil Shapiro 	}
1867*d39bd2c1SGregory Neil Shapiro 	if (!dane_vrfy_ctx->dane_vrfy_dane_enabled)
1868*d39bd2c1SGregory Neil Shapiro 	{
1869*d39bd2c1SGregory Neil Shapiro 		if (DANE_VRFY_NONE == dane_vrfy_ctx->dane_vrfy_res)
1870*d39bd2c1SGregory Neil Shapiro 			return SM_NOTDONE;
1871*d39bd2c1SGregory Neil Shapiro 		return SM_SUCCESS;
1872*d39bd2c1SGregory Neil Shapiro 	}
1873*d39bd2c1SGregory Neil Shapiro 
1874*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable
1875*d39bd2c1SGregory Neil Shapiro 	mspki = NULL;
1876*d39bd2c1SGregory Neil Shapiro 	depth = SSL_get0_dane_authority(ssl, NULL, &mspki);
1877*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 20))
1878*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dane_res: SSL_get0_dane_authority() depth=%d\n", depth);
1879*d39bd2c1SGregory Neil Shapiro 
1880*d39bd2c1SGregory Neil Shapiro 	if (depth < 0)
1881*d39bd2c1SGregory Neil Shapiro 	{
1882*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_res = DANE_VRFY_FAIL;
1883*d39bd2c1SGregory Neil Shapiro 		return SM_SUCCESS;
1884*d39bd2c1SGregory Neil Shapiro 	}
1885*d39bd2c1SGregory Neil Shapiro 
1886*d39bd2c1SGregory Neil Shapiro 	dane_vrfy_ctx->dane_vrfy_res = DANE_VRFY_OK;
1887*d39bd2c1SGregory Neil Shapiro 	r = SSL_get0_dane_tlsa(ssl, &usage, &selector, &mtype, &rr, &rrlen);
1888*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 20))
1889*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dane_res: SSL_get0_dane_tlsa=%d, status=%s\n", r,
1890*d39bd2c1SGregory Neil Shapiro 			(mspki != NULL) ? "TA_public_key_verified_certificate"
1891*d39bd2c1SGregory Neil Shapiro 			: (depth > 0) ? "matched_TA_certificate"
1892*d39bd2c1SGregory Neil Shapiro 				: "matched_EE_certificate");
1893*d39bd2c1SGregory Neil Shapiro 
1894*d39bd2c1SGregory Neil Shapiro 	if (LogLevel > 11)
1895*d39bd2c1SGregory Neil Shapiro 	{
1896*d39bd2c1SGregory Neil Shapiro 		/* just for logging */
1897*d39bd2c1SGregory Neil Shapiro 		if (r >= 0 && rr != NULL && rrlen > 0)
1898*d39bd2c1SGregory Neil Shapiro 		{
1899*d39bd2c1SGregory Neil Shapiro 			(void) data2hex((unsigned char *)rr, rrlen,
1900*d39bd2c1SGregory Neil Shapiro 				(unsigned char *)dane_vrfy_ctx->dane_vrfy_fp,
1901*d39bd2c1SGregory Neil Shapiro 				sizeof(dane_vrfy_ctx->dane_vrfy_fp));
1902*d39bd2c1SGregory Neil Shapiro 		}
1903*d39bd2c1SGregory Neil Shapiro 
1904*d39bd2c1SGregory Neil Shapiro 		sm_syslog(LOG_DEBUG, NOQID,
1905*d39bd2c1SGregory Neil Shapiro 			"DANE_depth=%d, DANE_res=%d, SSL_get0_dane_tlsa=%d, fp=%s, status=%s",
1906*d39bd2c1SGregory Neil Shapiro 			depth, dane_vrfy_ctx->dane_vrfy_res, r,
1907*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_fp,
1908*d39bd2c1SGregory Neil Shapiro 			(mspki != NULL) ? "TA_public_key_verified_certificate" :
1909*d39bd2c1SGregory Neil Shapiro 				(depth > 0) ? "matched_TA_certificate" : "matched_EE_certificate"
1910*d39bd2c1SGregory Neil Shapiro 		);
1911*d39bd2c1SGregory Neil Shapiro 	}
1912*d39bd2c1SGregory Neil Shapiro #  else
1913*d39bd2c1SGregory Neil Shapiro 	SM_ASSERT(!dane_vrfy_ctx->dane_vrfy_dane_enabled);
1914*d39bd2c1SGregory Neil Shapiro #  endif /* HAVE_SSL_CTX_dane_enable */
1915*d39bd2c1SGregory Neil Shapiro 	return SM_SUCCESS;
1916*d39bd2c1SGregory Neil Shapiro }
1917*d39bd2c1SGregory Neil Shapiro # endif /* DANE */
1918*d39bd2c1SGregory Neil Shapiro 
191940266059SGregory Neil Shapiro /*
192040266059SGregory Neil Shapiro **  TLS_GET_INFO -- get information about TLS connection
192140266059SGregory Neil Shapiro **
192240266059SGregory Neil Shapiro **	Parameters:
19235b0945b5SGregory Neil Shapiro **		ssl -- TLS session context
19245b0945b5SGregory Neil Shapiro **		srv -- server side?
192540266059SGregory Neil Shapiro **		host -- hostname of other side
192640266059SGregory Neil Shapiro **		mac -- macro storage
192740266059SGregory Neil Shapiro **		certreq -- did we ask for a cert?
192840266059SGregory Neil Shapiro **
192940266059SGregory Neil Shapiro **	Returns:
193040266059SGregory Neil Shapiro **		result of authentication.
193140266059SGregory Neil Shapiro **
193240266059SGregory Neil Shapiro **	Side Effects:
1933da7d7b9cSGregory Neil Shapiro **		sets various TLS related macros.
193440266059SGregory Neil Shapiro */
193540266059SGregory Neil Shapiro 
193640266059SGregory Neil Shapiro int
193740266059SGregory Neil Shapiro tls_get_info(ssl, srv, host, mac, certreq)
193840266059SGregory Neil Shapiro 	SSL *ssl;
193940266059SGregory Neil Shapiro 	bool srv;
194040266059SGregory Neil Shapiro 	char *host;
194140266059SGregory Neil Shapiro 	MACROS_T *mac;
194240266059SGregory Neil Shapiro 	bool certreq;
194340266059SGregory Neil Shapiro {
19446f9c8e5bSGregory Neil Shapiro 	const SSL_CIPHER *c;
194540266059SGregory Neil Shapiro 	int b, r;
1946e92d3f3fSGregory Neil Shapiro 	long verifyok;
194740266059SGregory Neil Shapiro 	char *s, *who;
194840266059SGregory Neil Shapiro 	char bitstr[16];
194940266059SGregory Neil Shapiro 	X509 *cert;
19505b0945b5SGregory Neil Shapiro # if DANE
19515b0945b5SGregory Neil Shapiro 	dane_vrfy_ctx_P dane_vrfy_ctx;
1952*d39bd2c1SGregory Neil Shapiro 	dane_tlsa_P dane_tlsa;
19535b0945b5SGregory Neil Shapiro # endif
195440266059SGregory Neil Shapiro 
195540266059SGregory Neil Shapiro 	c = SSL_get_current_cipher(ssl);
195640266059SGregory Neil Shapiro 
195740266059SGregory Neil Shapiro 	/* cast is just workaround for compiler warning */
195840266059SGregory Neil Shapiro 	macdefine(mac, A_TEMP, macid("{cipher}"),
195940266059SGregory Neil Shapiro 		  (char *) SSL_CIPHER_get_name(c));
196040266059SGregory Neil Shapiro 	b = SSL_CIPHER_get_bits(c, &r);
1961d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(bitstr, sizeof(bitstr), "%d", b);
196240266059SGregory Neil Shapiro 	macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr);
1963d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(bitstr, sizeof(bitstr), "%d", r);
196440266059SGregory Neil Shapiro 	macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr);
1965da7d7b9cSGregory Neil Shapiro 	s = (char *) SSL_get_version(ssl);
196640266059SGregory Neil Shapiro 	if (s == NULL)
196740266059SGregory Neil Shapiro 		s = "UNKNOWN";
196840266059SGregory Neil Shapiro 	macdefine(mac, A_TEMP, macid("{tls_version}"), s);
196940266059SGregory Neil Shapiro 
197040266059SGregory Neil Shapiro 	who = srv ? "server" : "client";
1971*d39bd2c1SGregory Neil Shapiro 	cert = MTA_SSL_get_peer_certificate(ssl);
1972e92d3f3fSGregory Neil Shapiro 	verifyok = SSL_get_verify_result(ssl);
197340266059SGregory Neil Shapiro 	if (LogLevel > 14)
197440266059SGregory Neil Shapiro 		sm_syslog(LOG_INFO, NOQID,
197540266059SGregory Neil Shapiro 			  "STARTTLS=%s, get_verify: %ld get_peer: 0x%lx",
1976e92d3f3fSGregory Neil Shapiro 			  who, verifyok, (unsigned long) cert);
19775b0945b5SGregory Neil Shapiro # if _FFR_TLS_ALTNAMES
19785b0945b5SGregory Neil Shapiro 	stabapply(clearclass, macid("{cert_altnames}"));
19795b0945b5SGregory Neil Shapiro # endif
198040266059SGregory Neil Shapiro 	if (cert != NULL)
198140266059SGregory Neil Shapiro 	{
19829bd497b8SGregory Neil Shapiro 		X509_NAME *subj, *issuer;
19832fb4f839SGregory Neil Shapiro 		char buf[MAXNAME];	/* EAI: not affected */
198440266059SGregory Neil Shapiro 
19859bd497b8SGregory Neil Shapiro 		subj = X509_get_subject_name(cert);
19869bd497b8SGregory Neil Shapiro 		issuer = X509_get_issuer_name(cert);
19879bd497b8SGregory Neil Shapiro 		X509_NAME_oneline(subj, buf, sizeof(buf));
198840266059SGregory Neil Shapiro 		macdefine(mac, A_TEMP, macid("{cert_subject}"),
198940266059SGregory Neil Shapiro 			 xtextify(buf, "<>\")"));
19909bd497b8SGregory Neil Shapiro 		X509_NAME_oneline(issuer, buf, sizeof(buf));
199140266059SGregory Neil Shapiro 		macdefine(mac, A_TEMP, macid("{cert_issuer}"),
199240266059SGregory Neil Shapiro 			 xtextify(buf, "<>\")"));
19939bd497b8SGregory Neil Shapiro 
19946f9c8e5bSGregory Neil Shapiro #  define LL_BADCERT	8
19956f9c8e5bSGregory Neil Shapiro 
1996da7d7b9cSGregory Neil Shapiro #define CERTFPMACRO (CertFingerprintAlgorithm != NULL ? "{cert_fp}" : "{cert_md5}")
1997da7d7b9cSGregory Neil Shapiro 
19989bd497b8SGregory Neil Shapiro #define CHECK_X509_NAME(which)	\
19999bd497b8SGregory Neil Shapiro 	do {	\
20009bd497b8SGregory Neil Shapiro 		if (r == -1)	\
20019bd497b8SGregory Neil Shapiro 		{		\
20029bd497b8SGregory Neil Shapiro 			sm_strlcpy(buf, "BadCertificateUnknown", sizeof(buf)); \
20036f9c8e5bSGregory Neil Shapiro 			if (LogLevel > LL_BADCERT)	\
20049bd497b8SGregory Neil Shapiro 				sm_syslog(LOG_INFO, NOQID,	\
20059bd497b8SGregory Neil Shapiro 					"STARTTLS=%s, relay=%.100s, field=%s, status=failed to extract CN",	\
20065b0945b5SGregory Neil Shapiro 					who, whichhost,	which);	\
20079bd497b8SGregory Neil Shapiro 		}		\
20089bd497b8SGregory Neil Shapiro 		else if ((size_t)r >= sizeof(buf) - 1)	\
20099bd497b8SGregory Neil Shapiro 		{		\
20109bd497b8SGregory Neil Shapiro 			sm_strlcpy(buf, "BadCertificateTooLong", sizeof(buf)); \
20119bd497b8SGregory Neil Shapiro 			if (LogLevel > 7)	\
20129bd497b8SGregory Neil Shapiro 				sm_syslog(LOG_INFO, NOQID,	\
20139bd497b8SGregory Neil Shapiro 					"STARTTLS=%s, relay=%.100s, field=%s, status=CN too long",	\
20145b0945b5SGregory Neil Shapiro 					who, whichhost, which);	\
20159bd497b8SGregory Neil Shapiro 		}		\
20169bd497b8SGregory Neil Shapiro 		else if ((size_t)r > strlen(buf))	\
20179bd497b8SGregory Neil Shapiro 		{		\
20189bd497b8SGregory Neil Shapiro 			sm_strlcpy(buf, "BadCertificateContainsNUL",	\
20199bd497b8SGregory Neil Shapiro 				sizeof(buf));	\
20209bd497b8SGregory Neil Shapiro 			if (LogLevel > 7)	\
20219bd497b8SGregory Neil Shapiro 				sm_syslog(LOG_INFO, NOQID,	\
20229bd497b8SGregory Neil Shapiro 					"STARTTLS=%s, relay=%.100s, field=%s, status=CN contains NUL",	\
20235b0945b5SGregory Neil Shapiro 					who, whichhost, which);	\
20249bd497b8SGregory Neil Shapiro 		}		\
20259bd497b8SGregory Neil Shapiro 	} while (0)
20269bd497b8SGregory Neil Shapiro 
20279bd497b8SGregory Neil Shapiro 		r = X509_NAME_get_text_by_NID(subj, NID_commonName, buf,
20289bd497b8SGregory Neil Shapiro 			sizeof buf);
20299bd497b8SGregory Neil Shapiro 		CHECK_X509_NAME("cn_subject");
203040266059SGregory Neil Shapiro 		macdefine(mac, A_TEMP, macid("{cn_subject}"),
203140266059SGregory Neil Shapiro 			 xtextify(buf, "<>\")"));
20329bd497b8SGregory Neil Shapiro 		r = X509_NAME_get_text_by_NID(issuer, NID_commonName, buf,
20339bd497b8SGregory Neil Shapiro 			sizeof buf);
20349bd497b8SGregory Neil Shapiro 		CHECK_X509_NAME("cn_issuer");
203540266059SGregory Neil Shapiro 		macdefine(mac, A_TEMP, macid("{cn_issuer}"),
203640266059SGregory Neil Shapiro 			 xtextify(buf, "<>\")"));
2037*d39bd2c1SGregory Neil Shapiro 		r = cert_fp(cert, EVP_digest, mac, CERTFPMACRO);
2038*d39bd2c1SGregory Neil Shapiro 		if (r <= 0 && LogLevel > 8)
2039*d39bd2c1SGregory Neil Shapiro 		{
2040*d39bd2c1SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
2041*d39bd2c1SGregory Neil Shapiro 				"STARTTLS=%s, relay=%.100s, X509_digest=%d, CertFingerprintAlgorithm=%s",
2042*d39bd2c1SGregory Neil Shapiro 				who, whichhost, r,
2043*d39bd2c1SGregory Neil Shapiro 				(NULL == CertFingerprintAlgorithm) ? "md5" :
2044*d39bd2c1SGregory Neil Shapiro 				CertFingerprintAlgorithm);
2045*d39bd2c1SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 8, who);
2046*d39bd2c1SGregory Neil Shapiro 		}
20475b0945b5SGregory Neil Shapiro 		getaltnames(cert, srv, host);
204840266059SGregory Neil Shapiro 	}
204940266059SGregory Neil Shapiro 	else
205040266059SGregory Neil Shapiro 	{
205140266059SGregory Neil Shapiro 		macdefine(mac, A_PERM, macid("{cert_subject}"), "");
205240266059SGregory Neil Shapiro 		macdefine(mac, A_PERM, macid("{cert_issuer}"), "");
205340266059SGregory Neil Shapiro 		macdefine(mac, A_PERM, macid("{cn_subject}"), "");
205440266059SGregory Neil Shapiro 		macdefine(mac, A_PERM, macid("{cn_issuer}"), "");
2055da7d7b9cSGregory Neil Shapiro 		macdefine(mac, A_TEMP, macid(CERTFPMACRO), "");
205640266059SGregory Neil Shapiro 	}
20575b0945b5SGregory Neil Shapiro # if DANE
20585b0945b5SGregory Neil Shapiro 	dane_vrfy_ctx = NULL;
2059*d39bd2c1SGregory Neil Shapiro 	dane_tlsa = NULL;
20605b0945b5SGregory Neil Shapiro 	if (TLSsslidx >= 0)
20615b0945b5SGregory Neil Shapiro 	{
20625b0945b5SGregory Neil Shapiro 		tlsi_ctx_T *tlsi_ctx;
20635b0945b5SGregory Neil Shapiro 
20645b0945b5SGregory Neil Shapiro 		tlsi_ctx = (tlsi_ctx_P) SSL_get_ex_data(ssl, TLSsslidx);
20655b0945b5SGregory Neil Shapiro 		if (tlsi_ctx != NULL)
2066*d39bd2c1SGregory Neil Shapiro 		{
20675b0945b5SGregory Neil Shapiro 			dane_vrfy_ctx = &(tlsi_ctx->tlsi_dvc);
2068*d39bd2c1SGregory Neil Shapiro 			dane_tlsa = dane_get_tlsa(dane_vrfy_ctx);
20695b0945b5SGregory Neil Shapiro 		}
2070*d39bd2c1SGregory Neil Shapiro 	}
2071*d39bd2c1SGregory Neil Shapiro 
20725b0945b5SGregory Neil Shapiro #  define DANE_VRFY_RES_IS(r) \
20735b0945b5SGregory Neil Shapiro 	((dane_vrfy_ctx != NULL) && dane_vrfy_ctx->dane_vrfy_res == (r))
2074*d39bd2c1SGregory Neil Shapiro 
2075*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 10))
2076*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("tls_get_info: verifyok=%d, dane_vrfy_res=%d\n",
2077*d39bd2c1SGregory Neil Shapiro 			(int)verifyok,
2078*d39bd2c1SGregory Neil Shapiro 			(dane_vrfy_ctx != NULL) ? dane_vrfy_ctx->dane_vrfy_res : -999);
2079*d39bd2c1SGregory Neil Shapiro 	if (SM_SUCCESS == dane_res(ssl, dane_vrfy_ctx))
2080*d39bd2c1SGregory Neil Shapiro 	{
20815b0945b5SGregory Neil Shapiro 		if (DANE_VRFY_RES_IS(DANE_VRFY_OK))
20825b0945b5SGregory Neil Shapiro 		{
20835b0945b5SGregory Neil Shapiro 			s = "TRUSTED";
20845b0945b5SGregory Neil Shapiro 			r = TLS_AUTH_OK;
20855b0945b5SGregory Neil Shapiro 		}
2086*d39bd2c1SGregory Neil Shapiro 		else if (DANE_VRFY_RES_IS(DANE_VRFY_TEMP))
2087*d39bd2c1SGregory Neil Shapiro 		{
2088*d39bd2c1SGregory Neil Shapiro 			s = "DANE_TEMP";
2089*d39bd2c1SGregory Neil Shapiro 			r = TLS_AUTH_TEMP;
2090*d39bd2c1SGregory Neil Shapiro 		}
20915b0945b5SGregory Neil Shapiro 		else if (DANE_VRFY_RES_IS(DANE_VRFY_FAIL))
20925b0945b5SGregory Neil Shapiro 		{
2093*d39bd2c1SGregory Neil Shapiro 			if (dane_tlsa != NULL &&
2094*d39bd2c1SGregory Neil Shapiro 			    TLSA_IS_FL(dane_tlsa, TLSAFL2MANY))
2095*d39bd2c1SGregory Neil Shapiro 			{
2096*d39bd2c1SGregory Neil Shapiro 				s = "DANE_TEMP";
2097*d39bd2c1SGregory Neil Shapiro 				r = TLS_AUTH_TEMP;
2098*d39bd2c1SGregory Neil Shapiro 			}
2099*d39bd2c1SGregory Neil Shapiro 			else
2100*d39bd2c1SGregory Neil Shapiro 			{
21015b0945b5SGregory Neil Shapiro 				s = "DANE_FAIL";
21025b0945b5SGregory Neil Shapiro 				r = TLS_AUTH_FAIL;
21035b0945b5SGregory Neil Shapiro 			}
2104*d39bd2c1SGregory Neil Shapiro 		}
2105*d39bd2c1SGregory Neil Shapiro 		else {
2106*d39bd2c1SGregory Neil Shapiro 			s = "BOGUS_DANE_RES";
2107*d39bd2c1SGregory Neil Shapiro 			r = TLS_AUTH_FAIL;
2108*d39bd2c1SGregory Neil Shapiro 		}
2109*d39bd2c1SGregory Neil Shapiro 	}
21105b0945b5SGregory Neil Shapiro 	else
21115b0945b5SGregory Neil Shapiro # endif /* if DANE */
21122fb4f839SGregory Neil Shapiro 	/* "else" in #if code above */
2113e92d3f3fSGregory Neil Shapiro 	switch (verifyok)
211440266059SGregory Neil Shapiro 	{
211540266059SGregory Neil Shapiro 	  case X509_V_OK:
211640266059SGregory Neil Shapiro 		if (cert != NULL)
211740266059SGregory Neil Shapiro 		{
211840266059SGregory Neil Shapiro 			s = "OK";
211940266059SGregory Neil Shapiro 			r = TLS_AUTH_OK;
212040266059SGregory Neil Shapiro 		}
212140266059SGregory Neil Shapiro 		else
212240266059SGregory Neil Shapiro 		{
212340266059SGregory Neil Shapiro 			s = certreq ? "NO" : "NOT",
212440266059SGregory Neil Shapiro 			r = TLS_AUTH_NO;
212540266059SGregory Neil Shapiro 		}
212640266059SGregory Neil Shapiro 		break;
2127*d39bd2c1SGregory Neil Shapiro 
212840266059SGregory Neil Shapiro 	  default:
212940266059SGregory Neil Shapiro 		s = "FAIL";
213040266059SGregory Neil Shapiro 		r = TLS_AUTH_FAIL;
213140266059SGregory Neil Shapiro 		break;
213240266059SGregory Neil Shapiro 	}
213340266059SGregory Neil Shapiro 	macdefine(mac, A_PERM, macid("{verify}"), s);
213440266059SGregory Neil Shapiro 	if (cert != NULL)
213540266059SGregory Neil Shapiro 		X509_free(cert);
213640266059SGregory Neil Shapiro 
213740266059SGregory Neil Shapiro 	/* do some logging */
213840266059SGregory Neil Shapiro 	if (LogLevel > 8)
213940266059SGregory Neil Shapiro 	{
214040266059SGregory Neil Shapiro 		char *vers, *s1, *s2, *cbits, *algbits;
214140266059SGregory Neil Shapiro 
214240266059SGregory Neil Shapiro 		vers = macget(mac, macid("{tls_version}"));
214340266059SGregory Neil Shapiro 		cbits = macget(mac, macid("{cipher_bits}"));
214440266059SGregory Neil Shapiro 		algbits = macget(mac, macid("{alg_bits}"));
2145*d39bd2c1SGregory Neil Shapiro 
2146*d39bd2c1SGregory Neil Shapiro 		/* XXX: use s directly? */
214740266059SGregory Neil Shapiro 		s1 = macget(mac, macid("{verify}"));
214840266059SGregory Neil Shapiro 		s2 = macget(mac, macid("{cipher}"));
214940266059SGregory Neil Shapiro 
21505b0945b5SGregory Neil Shapiro # if DANE
21515b0945b5SGregory Neil Shapiro #  define LOG_DANE_FP	\
21525b0945b5SGregory Neil Shapiro 	('\0' != dane_vrfy_ctx->dane_vrfy_fp[0] && DANE_VRFY_RES_IS(DANE_VRFY_FAIL))
21535b0945b5SGregory Neil Shapiro # endif
215440266059SGregory Neil Shapiro 		/* XXX: maybe cut off ident info? */
215540266059SGregory Neil Shapiro 		sm_syslog(LOG_INFO, NOQID,
2156*d39bd2c1SGregory Neil Shapiro 			  "STARTTLS=%s, relay=%.100s, version=%.16s, verify=%.16s, cipher=%.64s, bits=%.6s/%.6s%s%s%s%s",
215740266059SGregory Neil Shapiro 			  who,
215840266059SGregory Neil Shapiro 			  host == NULL ? "local" : host,
215940266059SGregory Neil Shapiro 			  vers, s1, s2, /* sm_snprintf() can deal with NULL */
216040266059SGregory Neil Shapiro 			  algbits == NULL ? "0" : algbits,
21615b0945b5SGregory Neil Shapiro 			  cbits == NULL ? "0" : cbits
21625b0945b5SGregory Neil Shapiro # if DANE
21635b0945b5SGregory Neil Shapiro 			, LOG_DANE_FP ? ", pubkey_fp=" : ""
21645b0945b5SGregory Neil Shapiro 			, LOG_DANE_FP ? dane_vrfy_ctx->dane_vrfy_fp : ""
2165*d39bd2c1SGregory Neil Shapiro 			, (dane_tlsa != NULL
2166*d39bd2c1SGregory Neil Shapiro 			    && TLSA_IS_FL(dane_tlsa, TLSAFLUNS)
2167*d39bd2c1SGregory Neil Shapiro 			    && !TLSA_IS_FL(dane_tlsa, TLSAFLSUP)
2168*d39bd2c1SGregory Neil Shapiro 			   && DANE_VRFY_RES_IS(DANE_VRFY_NONE))
2169*d39bd2c1SGregory Neil Shapiro 			  ? ONLYUNSUPTLSARR : ""
2170*d39bd2c1SGregory Neil Shapiro 			, (dane_tlsa != NULL
2171*d39bd2c1SGregory Neil Shapiro 			   && TLSA_IS_FL(dane_tlsa, TLSAFL2MANY))
2172*d39bd2c1SGregory Neil Shapiro 			  && DANE_VRFY_RES_IS(DANE_VRFY_FAIL)
2173*d39bd2c1SGregory Neil Shapiro 			  ? ", note=too many TLSA RRs" : ""
21745b0945b5SGregory Neil Shapiro # else
2175*d39bd2c1SGregory Neil Shapiro 			, "", "", "", ""
21765b0945b5SGregory Neil Shapiro # endif
21775b0945b5SGregory Neil Shapiro 			);
217840266059SGregory Neil Shapiro 		if (LogLevel > 11)
217940266059SGregory Neil Shapiro 		{
218040266059SGregory Neil Shapiro 			/*
218140266059SGregory Neil Shapiro 			**  Maybe run xuntextify on the strings?
218240266059SGregory Neil Shapiro 			**  That is easier to read but makes it maybe a bit
218340266059SGregory Neil Shapiro 			**  more complicated to figure out the right values
218440266059SGregory Neil Shapiro 			**  for the access map...
218540266059SGregory Neil Shapiro 			*/
218640266059SGregory Neil Shapiro 
218740266059SGregory Neil Shapiro 			s1 = macget(mac, macid("{cert_subject}"));
218840266059SGregory Neil Shapiro 			s2 = macget(mac, macid("{cert_issuer}"));
218940266059SGregory Neil Shapiro 			sm_syslog(LOG_INFO, NOQID,
2190e92d3f3fSGregory Neil Shapiro 				  "STARTTLS=%s, cert-subject=%.256s, cert-issuer=%.256s, verifymsg=%s",
2191e92d3f3fSGregory Neil Shapiro 				  who, s1, s2,
2192e92d3f3fSGregory Neil Shapiro 				  X509_verify_cert_error_string(verifyok));
219340266059SGregory Neil Shapiro 		}
219440266059SGregory Neil Shapiro 	}
219540266059SGregory Neil Shapiro 	return r;
219640266059SGregory Neil Shapiro }
21975b0945b5SGregory Neil Shapiro 
219840266059SGregory Neil Shapiro /*
219940266059SGregory Neil Shapiro **  ENDTLS -- shut down secure connection
220040266059SGregory Neil Shapiro **
220140266059SGregory Neil Shapiro **	Parameters:
22025b0945b5SGregory Neil Shapiro **		pssl -- pointer to TLS session context
22035b0945b5SGregory Neil Shapiro **		who -- server/client (for logging).
220440266059SGregory Neil Shapiro **
220540266059SGregory Neil Shapiro **	Returns:
220640266059SGregory Neil Shapiro **		success? (EX_* code)
220740266059SGregory Neil Shapiro */
220840266059SGregory Neil Shapiro 
220940266059SGregory Neil Shapiro int
22105b0945b5SGregory Neil Shapiro endtls(pssl, who)
22115b0945b5SGregory Neil Shapiro 	SSL **pssl;
22125b0945b5SGregory Neil Shapiro 	const char *who;
22135b0945b5SGregory Neil Shapiro {
221440266059SGregory Neil Shapiro 	SSL *ssl;
22155b0945b5SGregory Neil Shapiro 	int ret, r;
221640266059SGregory Neil Shapiro 
22175b0945b5SGregory Neil Shapiro 	SM_REQUIRE(pssl != NULL);
22185b0945b5SGregory Neil Shapiro 	ret = EX_OK;
22195b0945b5SGregory Neil Shapiro 	ssl = *pssl;
22205b0945b5SGregory Neil Shapiro 	if (ssl == NULL)
22215b0945b5SGregory Neil Shapiro 		return ret;
222240266059SGregory Neil Shapiro 
222340266059SGregory Neil Shapiro 	if ((r = SSL_shutdown(ssl)) < 0)
222440266059SGregory Neil Shapiro 	{
222540266059SGregory Neil Shapiro 		if (LogLevel > 11)
222640266059SGregory Neil Shapiro 		{
222740266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
222840266059SGregory Neil Shapiro 				  "STARTTLS=%s, SSL_shutdown failed: %d",
22295b0945b5SGregory Neil Shapiro 				  who, r);
22305b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 11, who);
223140266059SGregory Neil Shapiro 		}
223240266059SGregory Neil Shapiro 		ret = EX_SOFTWARE;
223340266059SGregory Neil Shapiro 	}
223440266059SGregory Neil Shapiro 
223540266059SGregory Neil Shapiro 	/*
223640266059SGregory Neil Shapiro 	**  Bug in OpenSSL (at least up to 0.9.6b):
223740266059SGregory Neil Shapiro 	**  From: Lutz.Jaenicke@aet.TU-Cottbus.DE
223840266059SGregory Neil Shapiro 	**  Message-ID: <20010723152244.A13122@serv01.aet.tu-cottbus.de>
223940266059SGregory Neil Shapiro 	**  To: openssl-users@openssl.org
224040266059SGregory Neil Shapiro 	**  Subject: Re: SSL_shutdown() woes (fwd)
224140266059SGregory Neil Shapiro 	**
224240266059SGregory Neil Shapiro 	**  The side sending the shutdown alert first will
224340266059SGregory Neil Shapiro 	**  not care about the answer of the peer but will
224440266059SGregory Neil Shapiro 	**  immediately return with a return value of "0"
224540266059SGregory Neil Shapiro 	**  (ssl/s3_lib.c:ssl3_shutdown()). SSL_get_error will evaluate
224640266059SGregory Neil Shapiro 	**  the value of "0" and as the shutdown alert of the peer was
224740266059SGregory Neil Shapiro 	**  not received (actually, the program did not even wait for
224840266059SGregory Neil Shapiro 	**  the answer), an SSL_ERROR_SYSCALL is flagged, because this
224940266059SGregory Neil Shapiro 	**  is the default rule in case everything else does not apply.
225040266059SGregory Neil Shapiro 	**
225140266059SGregory Neil Shapiro 	**  For your server the problem is different, because it
225240266059SGregory Neil Shapiro 	**  receives the shutdown first (setting SSL_RECEIVED_SHUTDOWN),
225340266059SGregory Neil Shapiro 	**  then sends its response (SSL_SENT_SHUTDOWN), so for the
22545b0945b5SGregory Neil Shapiro 	**  server the shutdown was successful.
225540266059SGregory Neil Shapiro 	**
225640266059SGregory Neil Shapiro 	**  As is by know, you would have to call SSL_shutdown() once
225740266059SGregory Neil Shapiro 	**  and ignore an SSL_ERROR_SYSCALL returned. Then call
225840266059SGregory Neil Shapiro 	**  SSL_shutdown() again to actually get the server's response.
225940266059SGregory Neil Shapiro 	**
226040266059SGregory Neil Shapiro 	**  In the last discussion, Bodo Moeller concluded that a
226140266059SGregory Neil Shapiro 	**  rewrite of the shutdown code would be necessary, but
226240266059SGregory Neil Shapiro 	**  probably with another API, as the change would not be
226340266059SGregory Neil Shapiro 	**  compatible to the way it is now.  Things do not become
226440266059SGregory Neil Shapiro 	**  easier as other programs do not follow the shutdown
226540266059SGregory Neil Shapiro 	**  guidelines anyway, so that a lot error conditions and
226640266059SGregory Neil Shapiro 	**  compitibility issues would have to be caught.
226740266059SGregory Neil Shapiro 	**
226840266059SGregory Neil Shapiro 	**  For now the recommondation is to ignore the error message.
226940266059SGregory Neil Shapiro 	*/
227040266059SGregory Neil Shapiro 
227140266059SGregory Neil Shapiro 	else if (r == 0)
227240266059SGregory Neil Shapiro 	{
227340266059SGregory Neil Shapiro 		if (LogLevel > 15)
227440266059SGregory Neil Shapiro 		{
227540266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
227640266059SGregory Neil Shapiro 				  "STARTTLS=%s, SSL_shutdown not done",
22775b0945b5SGregory Neil Shapiro 				  who);
22785b0945b5SGregory Neil Shapiro 			tlslogerr(LOG_WARNING, 15, who);
227940266059SGregory Neil Shapiro 		}
228040266059SGregory Neil Shapiro 		ret = EX_SOFTWARE;
228140266059SGregory Neil Shapiro 	}
22825b0945b5SGregory Neil Shapiro 	SM_SSL_FREE(*pssl);
228340266059SGregory Neil Shapiro 	return ret;
228440266059SGregory Neil Shapiro }
228540266059SGregory Neil Shapiro 
22865b0945b5SGregory Neil Shapiro # if !TLS_NO_RSA && MTA_RSA_TMP_CB
228740266059SGregory Neil Shapiro /*
228840266059SGregory Neil Shapiro **  TMP_RSA_KEY -- return temporary RSA key
228940266059SGregory Neil Shapiro **
229040266059SGregory Neil Shapiro **	Parameters:
22915b0945b5SGregory Neil Shapiro **		ssl -- TLS session context
229240266059SGregory Neil Shapiro **		export --
229340266059SGregory Neil Shapiro **		keylength --
229440266059SGregory Neil Shapiro **
229540266059SGregory Neil Shapiro **	Returns:
229640266059SGregory Neil Shapiro **		temporary RSA key.
229740266059SGregory Neil Shapiro */
229840266059SGregory Neil Shapiro 
229940266059SGregory Neil Shapiro #  ifndef MAX_RSA_TMP_CNT
230040266059SGregory Neil Shapiro #   define MAX_RSA_TMP_CNT	1000	/* XXX better value? */
23015b0945b5SGregory Neil Shapiro #  endif
230240266059SGregory Neil Shapiro 
230340266059SGregory Neil Shapiro /* ARGUSED0 */
230440266059SGregory Neil Shapiro static RSA *
230540266059SGregory Neil Shapiro tmp_rsa_key(s, export, keylength)
230640266059SGregory Neil Shapiro 	SSL *s;
230740266059SGregory Neil Shapiro 	int export;
230840266059SGregory Neil Shapiro 	int keylength;
230940266059SGregory Neil Shapiro {
231040266059SGregory Neil Shapiro #  if SM_CONF_SHM
231140266059SGregory Neil Shapiro 	extern int ShmId;
231240266059SGregory Neil Shapiro 	extern int *PRSATmpCnt;
231340266059SGregory Neil Shapiro 
231440266059SGregory Neil Shapiro 	if (ShmId != SM_SHM_NO_ID && rsa_tmp != NULL &&
231540266059SGregory Neil Shapiro 	    ++(*PRSATmpCnt) < MAX_RSA_TMP_CNT)
231640266059SGregory Neil Shapiro 		return rsa_tmp;
231740266059SGregory Neil Shapiro #  endif /* SM_CONF_SHM */
231840266059SGregory Neil Shapiro 
23199f5609e9SJung-uk Kim 	if (rsa_tmp != NULL)
23209f5609e9SJung-uk Kim 		RSA_free(rsa_tmp);
23215b0945b5SGregory Neil Shapiro 	rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, NULL);
23229f5609e9SJung-uk Kim 	if (rsa_tmp == NULL)
232340266059SGregory Neil Shapiro 	{
232440266059SGregory Neil Shapiro 		if (LogLevel > 0)
232540266059SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID,
232640266059SGregory Neil Shapiro 				  "STARTTLS=server, tmp_rsa_key: RSA_generate_key failed!");
232740266059SGregory Neil Shapiro 	}
232840266059SGregory Neil Shapiro 	else
232940266059SGregory Neil Shapiro 	{
233040266059SGregory Neil Shapiro #  if SM_CONF_SHM
233140266059SGregory Neil Shapiro #   if 0
233240266059SGregory Neil Shapiro 		/*
233340266059SGregory Neil Shapiro 		**  XXX we can't (yet) share the new key...
233440266059SGregory Neil Shapiro 		**	The RSA structure contains pointers hence it can't be
233540266059SGregory Neil Shapiro 		**	easily kept in shared memory.  It must be transformed
23365b0945b5SGregory Neil Shapiro 		**	into a continuous memory region first, then stored,
233740266059SGregory Neil Shapiro 		**	and later read out again (each time re-transformed).
233840266059SGregory Neil Shapiro 		*/
233940266059SGregory Neil Shapiro 
234040266059SGregory Neil Shapiro 		if (ShmId != SM_SHM_NO_ID)
234140266059SGregory Neil Shapiro 			*PRSATmpCnt = 0;
234240266059SGregory Neil Shapiro #   endif /* 0 */
234340266059SGregory Neil Shapiro #  endif /* SM_CONF_SHM */
234440266059SGregory Neil Shapiro 		if (LogLevel > 9)
234540266059SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID,
234640266059SGregory Neil Shapiro 				  "STARTTLS=server, tmp_rsa_key: new temp RSA key");
234740266059SGregory Neil Shapiro 	}
234840266059SGregory Neil Shapiro 	return rsa_tmp;
234940266059SGregory Neil Shapiro }
23505b0945b5SGregory Neil Shapiro # endif /* !TLS_NO_RSA && MTA_RSA_TMP_CB */
23515b0945b5SGregory Neil Shapiro 
235240266059SGregory Neil Shapiro /*
235340266059SGregory Neil Shapiro **  APPS_SSL_INFO_CB -- info callback for TLS connections
235440266059SGregory Neil Shapiro **
235540266059SGregory Neil Shapiro **	Parameters:
23565b0945b5SGregory Neil Shapiro **		ssl -- TLS session context
235740266059SGregory Neil Shapiro **		where -- state in handshake
235840266059SGregory Neil Shapiro **		ret -- return code of last operation
235940266059SGregory Neil Shapiro **
236040266059SGregory Neil Shapiro **	Returns:
236140266059SGregory Neil Shapiro **		none.
236240266059SGregory Neil Shapiro */
236340266059SGregory Neil Shapiro 
236440266059SGregory Neil Shapiro static void
23655b0945b5SGregory Neil Shapiro apps_ssl_info_cb(ssl, where, ret)
23665b0945b5SGregory Neil Shapiro 	const SSL *ssl;
236740266059SGregory Neil Shapiro 	int where;
236840266059SGregory Neil Shapiro 	int ret;
236940266059SGregory Neil Shapiro {
237040266059SGregory Neil Shapiro 	int w;
237140266059SGregory Neil Shapiro 	char *str;
237240266059SGregory Neil Shapiro 	BIO *bio_err = NULL;
237340266059SGregory Neil Shapiro 
237440266059SGregory Neil Shapiro 	if (LogLevel > 14)
237540266059SGregory Neil Shapiro 		sm_syslog(LOG_INFO, NOQID,
237640266059SGregory Neil Shapiro 			  "STARTTLS: info_callback where=0x%x, ret=%d",
237740266059SGregory Neil Shapiro 			  where, ret);
237840266059SGregory Neil Shapiro 
237940266059SGregory Neil Shapiro 	w = where & ~SSL_ST_MASK;
238040266059SGregory Neil Shapiro 	if (bio_err == NULL)
238140266059SGregory Neil Shapiro 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
238240266059SGregory Neil Shapiro 
238340266059SGregory Neil Shapiro 	if (bitset(SSL_ST_CONNECT, w))
238440266059SGregory Neil Shapiro 		str = "SSL_connect";
238540266059SGregory Neil Shapiro 	else if (bitset(SSL_ST_ACCEPT, w))
238640266059SGregory Neil Shapiro 		str = "SSL_accept";
238740266059SGregory Neil Shapiro 	else
238840266059SGregory Neil Shapiro 		str = "undefined";
238940266059SGregory Neil Shapiro 
239040266059SGregory Neil Shapiro 	if (bitset(SSL_CB_LOOP, where))
239140266059SGregory Neil Shapiro 	{
239240266059SGregory Neil Shapiro 		if (LogLevel > 12)
239340266059SGregory Neil Shapiro 			sm_syslog(LOG_NOTICE, NOQID,
239440266059SGregory Neil Shapiro 				"STARTTLS: %s:%s",
23955b0945b5SGregory Neil Shapiro 				str, SSL_state_string_long(ssl));
239640266059SGregory Neil Shapiro 	}
239740266059SGregory Neil Shapiro 	else if (bitset(SSL_CB_ALERT, where))
239840266059SGregory Neil Shapiro 	{
239940266059SGregory Neil Shapiro 		str = bitset(SSL_CB_READ, where) ? "read" : "write";
240040266059SGregory Neil Shapiro 		if (LogLevel > 12)
240140266059SGregory Neil Shapiro 			sm_syslog(LOG_NOTICE, NOQID,
240240266059SGregory Neil Shapiro 				"STARTTLS: SSL3 alert %s:%s:%s",
240340266059SGregory Neil Shapiro 				str, SSL_alert_type_string_long(ret),
240440266059SGregory Neil Shapiro 				SSL_alert_desc_string_long(ret));
240540266059SGregory Neil Shapiro 	}
240640266059SGregory Neil Shapiro 	else if (bitset(SSL_CB_EXIT, where))
240740266059SGregory Neil Shapiro 	{
240840266059SGregory Neil Shapiro 		if (ret == 0)
240940266059SGregory Neil Shapiro 		{
241040266059SGregory Neil Shapiro 			if (LogLevel > 7)
241140266059SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
241240266059SGregory Neil Shapiro 					"STARTTLS: %s:failed in %s",
24135b0945b5SGregory Neil Shapiro 					str, SSL_state_string_long(ssl));
241440266059SGregory Neil Shapiro 		}
241540266059SGregory Neil Shapiro 		else if (ret < 0)
241640266059SGregory Neil Shapiro 		{
241740266059SGregory Neil Shapiro 			if (LogLevel > 7)
241840266059SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
241940266059SGregory Neil Shapiro 					"STARTTLS: %s:error in %s",
24205b0945b5SGregory Neil Shapiro 					str, SSL_state_string_long(ssl));
242140266059SGregory Neil Shapiro 		}
242240266059SGregory Neil Shapiro 	}
242340266059SGregory Neil Shapiro }
24245b0945b5SGregory Neil Shapiro 
242540266059SGregory Neil Shapiro /*
242640266059SGregory Neil Shapiro **  TLS_VERIFY_LOG -- log verify error for TLS certificates
242740266059SGregory Neil Shapiro **
242840266059SGregory Neil Shapiro **	Parameters:
242940266059SGregory Neil Shapiro **		ok -- verify ok?
24305b0945b5SGregory Neil Shapiro **		ctx -- X509 context
2431da7d7b9cSGregory Neil Shapiro **		name -- from where is this called?
243240266059SGregory Neil Shapiro **
243340266059SGregory Neil Shapiro **	Returns:
243440266059SGregory Neil Shapiro **		1 -- ok
243540266059SGregory Neil Shapiro */
243640266059SGregory Neil Shapiro 
243740266059SGregory Neil Shapiro static int
2438e92d3f3fSGregory Neil Shapiro tls_verify_log(ok, ctx, name)
243940266059SGregory Neil Shapiro 	int ok;
244040266059SGregory Neil Shapiro 	X509_STORE_CTX *ctx;
2441da7d7b9cSGregory Neil Shapiro 	const char *name;
244240266059SGregory Neil Shapiro {
244340266059SGregory Neil Shapiro 	X509 *cert;
244440266059SGregory Neil Shapiro 	int reason, depth;
244540266059SGregory Neil Shapiro 	char buf[512];
244640266059SGregory Neil Shapiro 
244740266059SGregory Neil Shapiro 	cert = X509_STORE_CTX_get_current_cert(ctx);
244840266059SGregory Neil Shapiro 	reason = X509_STORE_CTX_get_error(ctx);
244940266059SGregory Neil Shapiro 	depth = X509_STORE_CTX_get_error_depth(ctx);
2450d0cef73dSGregory Neil Shapiro 	X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
245140266059SGregory Neil Shapiro 	sm_syslog(LOG_INFO, NOQID,
2452e92d3f3fSGregory Neil Shapiro 		  "STARTTLS: %s cert verify: depth=%d %s, state=%d, reason=%s",
2453e92d3f3fSGregory Neil Shapiro 		  name, depth, buf, ok, X509_verify_cert_error_string(reason));
245440266059SGregory Neil Shapiro 	return 1;
245540266059SGregory Neil Shapiro }
2456e92d3f3fSGregory Neil Shapiro 
245740266059SGregory Neil Shapiro /*
24585b0945b5SGregory Neil Shapiro **  Declaration and access to tlsi_ctx in callbacks.
24595b0945b5SGregory Neil Shapiro */
24605b0945b5SGregory Neil Shapiro 
24615b0945b5SGregory Neil Shapiro #define SM_DECTLSI	\
24625b0945b5SGregory Neil Shapiro 	tlsi_ctx_T *tlsi_ctx;	\
24635b0945b5SGregory Neil Shapiro 	SSL *ssl
24645b0945b5SGregory Neil Shapiro #define SM_GETTLSI	\
24655b0945b5SGregory Neil Shapiro 	do {		\
24665b0945b5SGregory Neil Shapiro 		tlsi_ctx = NULL;	\
24675b0945b5SGregory Neil Shapiro 		if (TLSsslidx >= 0)	\
24685b0945b5SGregory Neil Shapiro 		{	\
24695b0945b5SGregory Neil Shapiro 			ssl = (SSL *) X509_STORE_CTX_get_ex_data(ctx,	\
24705b0945b5SGregory Neil Shapiro 				SSL_get_ex_data_X509_STORE_CTX_idx());	\
24715b0945b5SGregory Neil Shapiro 			if (ssl != NULL)	\
24725b0945b5SGregory Neil Shapiro 				tlsi_ctx = (tlsi_ctx_P) SSL_get_ex_data(ssl, TLSsslidx);	\
24735b0945b5SGregory Neil Shapiro 		}	\
24745b0945b5SGregory Neil Shapiro 	}	\
24755b0945b5SGregory Neil Shapiro 	while (0)
24765b0945b5SGregory Neil Shapiro 
24775b0945b5SGregory Neil Shapiro # if DANE
24785b0945b5SGregory Neil Shapiro 
24795b0945b5SGregory Neil Shapiro /*
24805b0945b5SGregory Neil Shapiro **  DANE_GET_TLSA -- Retrieve TLSA RR for DANE
24815b0945b5SGregory Neil Shapiro **
24825b0945b5SGregory Neil Shapiro **	Parameters:
2483*d39bd2c1SGregory Neil Shapiro **		dane_vrfy_ctx -- dane verify context
24845b0945b5SGregory Neil Shapiro **
24855b0945b5SGregory Neil Shapiro **	Returns:
24865b0945b5SGregory Neil Shapiro **		dane_tlsa if TLSA RR is available
24875b0945b5SGregory Neil Shapiro **		NULL otherwise
24885b0945b5SGregory Neil Shapiro */
24895b0945b5SGregory Neil Shapiro 
24905b0945b5SGregory Neil Shapiro dane_tlsa_P
24915b0945b5SGregory Neil Shapiro dane_get_tlsa(dane_vrfy_ctx)
24925b0945b5SGregory Neil Shapiro 	dane_vrfy_ctx_P dane_vrfy_ctx;
24935b0945b5SGregory Neil Shapiro {
24945b0945b5SGregory Neil Shapiro 	STAB *s;
24955b0945b5SGregory Neil Shapiro 	dane_tlsa_P dane_tlsa;
24965b0945b5SGregory Neil Shapiro 
24975b0945b5SGregory Neil Shapiro 	dane_tlsa = NULL;
24985b0945b5SGregory Neil Shapiro 	if (NULL == dane_vrfy_ctx)
24995b0945b5SGregory Neil Shapiro 		return NULL;
2500*d39bd2c1SGregory Neil Shapiro 	if (!CHK_DANE(dane_vrfy_ctx->dane_vrfy_chk) ||
25015b0945b5SGregory Neil Shapiro 	    dane_vrfy_ctx->dane_vrfy_host == NULL)
25025b0945b5SGregory Neil Shapiro 		return NULL;
25035b0945b5SGregory Neil Shapiro 
2504*d39bd2c1SGregory Neil Shapiro 	gettlsa(dane_vrfy_ctx->dane_vrfy_host, NULL, &s,
2505*d39bd2c1SGregory Neil Shapiro 		TLSAFLNOEXP, 0, dane_vrfy_ctx->dane_vrfy_port);
25065b0945b5SGregory Neil Shapiro 	if (NULL == s)
25075b0945b5SGregory Neil Shapiro 		goto notfound;
25085b0945b5SGregory Neil Shapiro 	dane_tlsa = s->s_tlsa;
25095b0945b5SGregory Neil Shapiro 	if (NULL == dane_tlsa)
25105b0945b5SGregory Neil Shapiro 		goto notfound;
2511*d39bd2c1SGregory Neil Shapiro 	if (!TLSA_HAS_RRs(dane_tlsa))
25125b0945b5SGregory Neil Shapiro 		goto notfound;
25135b0945b5SGregory Neil Shapiro 	if (tTd(96, 4))
2514*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dane_get_tlsa: chk=%#x, host=%s, n=%d, stat=entry found\n",
25155b0945b5SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_chk,
25165b0945b5SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_host, dane_tlsa->dane_tlsa_n);
25175b0945b5SGregory Neil Shapiro 	return dane_tlsa;
25185b0945b5SGregory Neil Shapiro 
25195b0945b5SGregory Neil Shapiro   notfound:
25205b0945b5SGregory Neil Shapiro 	if (tTd(96, 4))
2521*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dane_get_tlsa: chk=%#x, host=%s, stat=no valid entry found\n",
25225b0945b5SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_chk,
25235b0945b5SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_host);
25245b0945b5SGregory Neil Shapiro 	return NULL;
25255b0945b5SGregory Neil Shapiro }
25265b0945b5SGregory Neil Shapiro 
25275b0945b5SGregory Neil Shapiro /*
25285b0945b5SGregory Neil Shapiro **  DANE_VERIFY -- verify callback for TLS certificates
25295b0945b5SGregory Neil Shapiro **
25305b0945b5SGregory Neil Shapiro **	Parameters:
25315b0945b5SGregory Neil Shapiro **		ctx -- X509 context
25325b0945b5SGregory Neil Shapiro **		dane_vrfy_ctx -- callback context
25335b0945b5SGregory Neil Shapiro **
25345b0945b5SGregory Neil Shapiro **	Returns:
25355b0945b5SGregory Neil Shapiro **		DANE_VRFY_{OK,NONE,FAIL}
25365b0945b5SGregory Neil Shapiro */
25375b0945b5SGregory Neil Shapiro 
25385b0945b5SGregory Neil Shapiro /* NOTE: this only works because the "matching type" is 0, 1, 2 for these! */
25395b0945b5SGregory Neil Shapiro static const char *dane_mdalgs[] = { "", "sha256", "sha512" };
25405b0945b5SGregory Neil Shapiro 
25415b0945b5SGregory Neil Shapiro static int
25425b0945b5SGregory Neil Shapiro dane_verify(ctx, dane_vrfy_ctx)
25435b0945b5SGregory Neil Shapiro 	X509_STORE_CTX *ctx;
25445b0945b5SGregory Neil Shapiro 	dane_vrfy_ctx_P dane_vrfy_ctx;
25455b0945b5SGregory Neil Shapiro {
25465b0945b5SGregory Neil Shapiro 	int r, i, ok, mdalg;
25475b0945b5SGregory Neil Shapiro 	X509 *cert;
25485b0945b5SGregory Neil Shapiro 	dane_tlsa_P dane_tlsa;
2549*d39bd2c1SGregory Neil Shapiro 	unsigned char *fp;
25505b0945b5SGregory Neil Shapiro 
25515b0945b5SGregory Neil Shapiro 	dane_tlsa = dane_get_tlsa(dane_vrfy_ctx);
25525b0945b5SGregory Neil Shapiro 	if (dane_tlsa == NULL)
25535b0945b5SGregory Neil Shapiro 		return DANE_VRFY_NONE;
25545b0945b5SGregory Neil Shapiro 
25555b0945b5SGregory Neil Shapiro 	dane_vrfy_ctx->dane_vrfy_fp[0] = '\0';
25565b0945b5SGregory Neil Shapiro 	cert = X509_STORE_CTX_get0_cert(ctx);
25575b0945b5SGregory Neil Shapiro 	if (tTd(96, 8))
2558*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dane_verify: cert=%p, supported=%d\n",
2559*d39bd2c1SGregory Neil Shapiro 			(void *)cert, TLSA_IS_FL(dane_tlsa, TLSAFLSUP));
25605b0945b5SGregory Neil Shapiro 	if (cert == NULL)
25615b0945b5SGregory Neil Shapiro 		return DANE_VRFY_FAIL;
25625b0945b5SGregory Neil Shapiro 
25635b0945b5SGregory Neil Shapiro 	ok = DANE_VRFY_NONE;
25645b0945b5SGregory Neil Shapiro 	fp = NULL;
25655b0945b5SGregory Neil Shapiro 
25665b0945b5SGregory Neil Shapiro 	/*
25675b0945b5SGregory Neil Shapiro 	**  If the TLSA RRs would be sorted the two loops below could
25685b0945b5SGregory Neil Shapiro 	**  be merged into one and simply change mdalg when it changes
25695b0945b5SGregory Neil Shapiro 	**  in dane_tlsa->dane_tlsa_rr.
25705b0945b5SGregory Neil Shapiro 	*/
25715b0945b5SGregory Neil Shapiro 
25725b0945b5SGregory Neil Shapiro 	/* use a different order? */
25735b0945b5SGregory Neil Shapiro 	for (mdalg = 0; mdalg < SM_ARRAY_SIZE(dane_mdalgs); mdalg++)
25745b0945b5SGregory Neil Shapiro 	{
25755b0945b5SGregory Neil Shapiro 		SM_FREE(fp);
25765b0945b5SGregory Neil Shapiro 		r = 0;
25775b0945b5SGregory Neil Shapiro 		for (i = 0; i < dane_tlsa->dane_tlsa_n; i++)
25785b0945b5SGregory Neil Shapiro 		{
2579*d39bd2c1SGregory Neil Shapiro 			unsigned char *p;
25805b0945b5SGregory Neil Shapiro 			int alg;
25815b0945b5SGregory Neil Shapiro 
25825b0945b5SGregory Neil Shapiro 			p = dane_tlsa->dane_tlsa_rr[i];
25835b0945b5SGregory Neil Shapiro 
25845b0945b5SGregory Neil Shapiro 			/* ignore bogus/unsupported TLSA RRs */
25855b0945b5SGregory Neil Shapiro 			alg = dane_tlsa_chk(p, dane_tlsa->dane_tlsa_len[i],
25865b0945b5SGregory Neil Shapiro 					  dane_vrfy_ctx->dane_vrfy_host, false);
25875b0945b5SGregory Neil Shapiro 			if (tTd(96, 8))
2588*d39bd2c1SGregory Neil Shapiro 				sm_dprintf("dane_verify: alg=%d, mdalg=%d\n",
25895b0945b5SGregory Neil Shapiro 					alg, mdalg);
25905b0945b5SGregory Neil Shapiro 			if (alg != mdalg)
25915b0945b5SGregory Neil Shapiro 				continue;
25925b0945b5SGregory Neil Shapiro 
25935b0945b5SGregory Neil Shapiro 			if (NULL == fp)
25945b0945b5SGregory Neil Shapiro 			{
25955b0945b5SGregory Neil Shapiro 				r = pubkey_fp(cert, dane_mdalgs[mdalg], &fp);
25965b0945b5SGregory Neil Shapiro 				if (NULL == fp)
25975b0945b5SGregory Neil Shapiro 					return DANE_VRFY_FAIL;
25985b0945b5SGregory Neil Shapiro 					/* or continue? */
25995b0945b5SGregory Neil Shapiro 			}
26005b0945b5SGregory Neil Shapiro 
26015b0945b5SGregory Neil Shapiro 			/* just for logging */
26025b0945b5SGregory Neil Shapiro 			if (r > 0 && fp != NULL)
26035b0945b5SGregory Neil Shapiro 			{
26045b0945b5SGregory Neil Shapiro 				(void) data2hex((unsigned char *)fp, r,
26055b0945b5SGregory Neil Shapiro 					(unsigned char *)dane_vrfy_ctx->dane_vrfy_fp,
26065b0945b5SGregory Neil Shapiro 					sizeof(dane_vrfy_ctx->dane_vrfy_fp));
26075b0945b5SGregory Neil Shapiro 			}
26085b0945b5SGregory Neil Shapiro 
26095b0945b5SGregory Neil Shapiro 			if (tTd(96, 4))
2610*d39bd2c1SGregory Neil Shapiro 				sm_dprintf("dane_verify: alg=%d, r=%d, len=%d\n",
26115b0945b5SGregory Neil Shapiro 					alg, r, dane_tlsa->dane_tlsa_len[i]);
26125b0945b5SGregory Neil Shapiro 			if (r != dane_tlsa->dane_tlsa_len[i] - 3)
26135b0945b5SGregory Neil Shapiro 				continue;
26145b0945b5SGregory Neil Shapiro 			ok = DANE_VRFY_FAIL;
26155b0945b5SGregory Neil Shapiro 
26165b0945b5SGregory Neil Shapiro 			/*
26175b0945b5SGregory Neil Shapiro 			**  Note: Type is NOT checked because only 3-1-x
26185b0945b5SGregory Neil Shapiro 			**  is supported.
26195b0945b5SGregory Neil Shapiro 			*/
26205b0945b5SGregory Neil Shapiro 
26215b0945b5SGregory Neil Shapiro 			if (memcmp(p + 3, fp, r) == 0)
26225b0945b5SGregory Neil Shapiro 			{
26235b0945b5SGregory Neil Shapiro 				if (tTd(96, 2))
2624*d39bd2c1SGregory Neil Shapiro 					sm_dprintf("dane_verify: status=match\n");
26255b0945b5SGregory Neil Shapiro 				if (tTd(96, 8))
26265b0945b5SGregory Neil Shapiro 				{
2627*d39bd2c1SGregory Neil Shapiro 					unsigned char hex[DANE_FP_DBG_LEN];
26285b0945b5SGregory Neil Shapiro 
26295b0945b5SGregory Neil Shapiro 					data2hex((unsigned char *)p,
26305b0945b5SGregory Neil Shapiro 						dane_tlsa->dane_tlsa_len[i],
26315b0945b5SGregory Neil Shapiro 						hex, sizeof(hex));
2632*d39bd2c1SGregory Neil Shapiro 					sm_dprintf("dane_verify: pubkey_fp=%s\n"
26335b0945b5SGregory Neil Shapiro 						, hex);
26345b0945b5SGregory Neil Shapiro 				}
26355b0945b5SGregory Neil Shapiro 				dane_vrfy_ctx->dane_vrfy_res = DANE_VRFY_OK;
26365b0945b5SGregory Neil Shapiro 				SM_FREE(fp);
26375b0945b5SGregory Neil Shapiro 				return DANE_VRFY_OK;
26385b0945b5SGregory Neil Shapiro 			}
26395b0945b5SGregory Neil Shapiro 		}
26405b0945b5SGregory Neil Shapiro 	}
26415b0945b5SGregory Neil Shapiro 
26425b0945b5SGregory Neil Shapiro 	SM_FREE(fp);
26435b0945b5SGregory Neil Shapiro 	dane_vrfy_ctx->dane_vrfy_res = ok;
26445b0945b5SGregory Neil Shapiro 	return ok;
26455b0945b5SGregory Neil Shapiro }
2646*d39bd2c1SGregory Neil Shapiro 
2647*d39bd2c1SGregory Neil Shapiro /*
2648*d39bd2c1SGregory Neil Shapiro **  SSL_DANE_ENABLE -- enable using OpenSSL DANE functions for a session
2649*d39bd2c1SGregory Neil Shapiro **
2650*d39bd2c1SGregory Neil Shapiro **	Parameters:
2651*d39bd2c1SGregory Neil Shapiro **		dane_vrfy_ctx -- dane verify context
2652*d39bd2c1SGregory Neil Shapiro **		ssl -- TLS connection structure
2653*d39bd2c1SGregory Neil Shapiro **
2654*d39bd2c1SGregory Neil Shapiro **	Returns:
2655*d39bd2c1SGregory Neil Shapiro **		SM_SUCCESS: OpenSSL DANE checking enabled
2656*d39bd2c1SGregory Neil Shapiro **		SM_NOTDONE: OpenSSL DANE checking not enabled
2657*d39bd2c1SGregory Neil Shapiro **		<0: some error
2658*d39bd2c1SGregory Neil Shapiro */
2659*d39bd2c1SGregory Neil Shapiro 
2660*d39bd2c1SGregory Neil Shapiro int
2661*d39bd2c1SGregory Neil Shapiro ssl_dane_enable(dane_vrfy_ctx, ssl)
2662*d39bd2c1SGregory Neil Shapiro 	dane_vrfy_ctx_P dane_vrfy_ctx;
2663*d39bd2c1SGregory Neil Shapiro 	SSL *ssl;
2664*d39bd2c1SGregory Neil Shapiro {
2665*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable
2666*d39bd2c1SGregory Neil Shapiro 	const char *dane_tlsa_domain;
2667*d39bd2c1SGregory Neil Shapiro 	int r, i, usable;
2668*d39bd2c1SGregory Neil Shapiro #  endif
2669*d39bd2c1SGregory Neil Shapiro 	dane_tlsa_P dane_tlsa;
2670*d39bd2c1SGregory Neil Shapiro 
2671*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 20))
2672*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ssl_dane_enable: dane_vrfy_ctx=%p, dane_vrfy_dane_enabled=%d, dane_vrfy_chk=%#x\n",
2673*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx, dane_vrfy_ctx->dane_vrfy_dane_enabled,
2674*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_chk);
2675*d39bd2c1SGregory Neil Shapiro 
2676*d39bd2c1SGregory Neil Shapiro 	dane_tlsa = dane_get_tlsa(dane_vrfy_ctx);
2677*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 20))
2678*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ssl_dane_enable: dane_tlsa=%p, n=%d, supported=%d\n",
2679*d39bd2c1SGregory Neil Shapiro 			dane_tlsa, dane_tlsa != NULL ? dane_tlsa->dane_tlsa_n : -999,
2680*d39bd2c1SGregory Neil Shapiro 			dane_tlsa != NULL ? TLSA_IS_FL(dane_tlsa, TLSAFLSUP) : -1);
2681*d39bd2c1SGregory Neil Shapiro 	if (NULL == dane_tlsa || !TLSA_IS_FL(dane_tlsa, TLSAFLSUP))
2682*d39bd2c1SGregory Neil Shapiro 	{
2683*d39bd2c1SGregory Neil Shapiro 		/* no DANE verification possible */
2684*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_chk |= TLSAFLNOVRFY;
2685*d39bd2c1SGregory Neil Shapiro 		return SM_SUCCESS;
2686*d39bd2c1SGregory Neil Shapiro 	}
2687*d39bd2c1SGregory Neil Shapiro 	if (0 == (dane_vrfy_ctx->dane_vrfy_chk & TLSAFLADIP))
2688*d39bd2c1SGregory Neil Shapiro 	{
2689*d39bd2c1SGregory Neil Shapiro 		/* no DANE verification possible */
2690*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_chk |= TLSAFLNOVRFY;
2691*d39bd2c1SGregory Neil Shapiro 		return SM_SUCCESS;
2692*d39bd2c1SGregory Neil Shapiro 	}
2693*d39bd2c1SGregory Neil Shapiro 
2694*d39bd2c1SGregory Neil Shapiro 	if (!dane_vrfy_ctx->dane_vrfy_dane_enabled)
2695*d39bd2c1SGregory Neil Shapiro 	{
2696*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable
2697*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_chk |= TLSAFLTEMPVRFY;
2698*d39bd2c1SGregory Neil Shapiro #  endif
2699*d39bd2c1SGregory Neil Shapiro 		return SM_NOTDONE;
2700*d39bd2c1SGregory Neil Shapiro 	}
2701*d39bd2c1SGregory Neil Shapiro 
2702*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable
2703*d39bd2c1SGregory Neil Shapiro 	dane_tlsa_domain = !SM_IS_EMPTY(dane_vrfy_ctx->dane_vrfy_sni)
2704*d39bd2c1SGregory Neil Shapiro 				? dane_vrfy_ctx->dane_vrfy_sni
2705*d39bd2c1SGregory Neil Shapiro 				: dane_vrfy_ctx->dane_vrfy_host;
2706*d39bd2c1SGregory Neil Shapiro 	r = SSL_dane_enable(ssl, dane_tlsa_domain);
2707*d39bd2c1SGregory Neil Shapiro #   if _FFR_TESTS
2708*d39bd2c1SGregory Neil Shapiro 	if (tTd(90, 102))
2709*d39bd2c1SGregory Neil Shapiro 	{
2710*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ssl_dane_enable: test=simulate SSL_dane_enable error\n");
2711*d39bd2c1SGregory Neil Shapiro #    ifdef SSL_F_SSL_DANE_ENABLE
2712*d39bd2c1SGregory Neil Shapiro 		SSLerr(SSL_F_SSL_DANE_ENABLE, ERR_R_MALLOC_FAILURE);
2713*d39bd2c1SGregory Neil Shapiro #    endif
2714*d39bd2c1SGregory Neil Shapiro 		r = -1; /* -ENOMEM; */
2715*d39bd2c1SGregory Neil Shapiro 	}
2716*d39bd2c1SGregory Neil Shapiro #   endif /* _FFR_TESTS */
2717*d39bd2c1SGregory Neil Shapiro 	if (r <= 0)
2718*d39bd2c1SGregory Neil Shapiro 	{
2719*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable
2720*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_chk |= TLSAFLTEMPVRFY;
2721*d39bd2c1SGregory Neil Shapiro #  endif
2722*d39bd2c1SGregory Neil Shapiro 		if (LogLevel > 1)
2723*d39bd2c1SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID,
2724*d39bd2c1SGregory Neil Shapiro 				"STARTTLS=client, SSL_dane_enable=%d", r);
2725*d39bd2c1SGregory Neil Shapiro 		tlslogerr(LOG_ERR, 7, "client");
2726*d39bd2c1SGregory Neil Shapiro 
2727*d39bd2c1SGregory Neil Shapiro 		/* XXX need better error code */
2728*d39bd2c1SGregory Neil Shapiro 		return (r < 0) ? r : -EINVAL;
2729*d39bd2c1SGregory Neil Shapiro 	}
2730*d39bd2c1SGregory Neil Shapiro 	if (LogLevel > 13)
2731*d39bd2c1SGregory Neil Shapiro 		sm_syslog(LOG_DEBUG, NOQID,
2732*d39bd2c1SGregory Neil Shapiro 			"STARTTLS=client, SSL_dane_enable=%d, domain=%s",
2733*d39bd2c1SGregory Neil Shapiro 			r, dane_tlsa_domain);
2734*d39bd2c1SGregory Neil Shapiro 	(void) SSL_dane_set_flags(ssl, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
2735*d39bd2c1SGregory Neil Shapiro 
2736*d39bd2c1SGregory Neil Shapiro 	usable = 0;
2737*d39bd2c1SGregory Neil Shapiro 	for (i = 0; i < dane_tlsa->dane_tlsa_n; i++)
2738*d39bd2c1SGregory Neil Shapiro 	{
2739*d39bd2c1SGregory Neil Shapiro 		const unsigned char *rr;
2740*d39bd2c1SGregory Neil Shapiro 		const char *chk;
2741*d39bd2c1SGregory Neil Shapiro 
2742*d39bd2c1SGregory Neil Shapiro 		rr = (const unsigned char *)dane_tlsa->dane_tlsa_rr[i];
2743*d39bd2c1SGregory Neil Shapiro 		if (NULL == rr)
2744*d39bd2c1SGregory Neil Shapiro 			continue;
2745*d39bd2c1SGregory Neil Shapiro 
2746*d39bd2c1SGregory Neil Shapiro 		/*
2747*d39bd2c1SGregory Neil Shapiro 		**  only DANE-TA(2) or DANE-EE(3)
2748*d39bd2c1SGregory Neil Shapiro 		**  use dane_tlsa_chk() instead?
2749*d39bd2c1SGregory Neil Shapiro 		*/
2750*d39bd2c1SGregory Neil Shapiro 
2751*d39bd2c1SGregory Neil Shapiro # if _FFR_TESTS
2752*d39bd2c1SGregory Neil Shapiro 		if (tTd(90, 101) && 3 == rr[0] && 1 == rr[1])
2753*d39bd2c1SGregory Neil Shapiro 		{
2754*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("TLSA, type=%d-%d-%d:%02x, status=unsupported_due_to_test",
2755*d39bd2c1SGregory Neil Shapiro 				  (int)rr[0], (int)rr[1], (int)rr[2],
2756*d39bd2c1SGregory Neil Shapiro 				  (int)rr[3]);
2757*d39bd2c1SGregory Neil Shapiro 			r = 0;
2758*d39bd2c1SGregory Neil Shapiro 			chk = "tlsa_test";
2759*d39bd2c1SGregory Neil Shapiro 		}
2760*d39bd2c1SGregory Neil Shapiro 		else
2761*d39bd2c1SGregory Neil Shapiro # endif /* _FFR_TESTS */
2762*d39bd2c1SGregory Neil Shapiro 		if (!(2 == rr[0] || 3 == rr[0]))
2763*d39bd2c1SGregory Neil Shapiro 		{
2764*d39bd2c1SGregory Neil Shapiro 			r = 0;
2765*d39bd2c1SGregory Neil Shapiro 			chk = "tlsa_chk";
2766*d39bd2c1SGregory Neil Shapiro 		}
2767*d39bd2c1SGregory Neil Shapiro 		else
2768*d39bd2c1SGregory Neil Shapiro 		{
2769*d39bd2c1SGregory Neil Shapiro 			r = SSL_dane_tlsa_add(ssl, rr[0], rr[1], rr[2], rr + 3,
2770*d39bd2c1SGregory Neil Shapiro 				(size_t) (dane_tlsa->dane_tlsa_len[i] - 3));
2771*d39bd2c1SGregory Neil Shapiro 			chk = "SSL_dane_tlsa_add";
2772*d39bd2c1SGregory Neil Shapiro 		}
2773*d39bd2c1SGregory Neil Shapiro 		if (r > 0)
2774*d39bd2c1SGregory Neil Shapiro 			usable++;
2775*d39bd2c1SGregory Neil Shapiro #  if HAVE_SSL_CTX_dane_enable && 0
2776*d39bd2c1SGregory Neil Shapiro /* should an error be ignored or cause a temporary failure? */
2777*d39bd2c1SGregory Neil Shapiro 		if (r < 0)
2778*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_chk |= TLSAFLTEMPVRFY;
2779*d39bd2c1SGregory Neil Shapiro #  endif
2780*d39bd2c1SGregory Neil Shapiro 		else if (LogLevel > ((r < 0) ? 10 : 13))
2781*d39bd2c1SGregory Neil Shapiro 		{
2782*d39bd2c1SGregory Neil Shapiro 			unsigned char hex[DANE_FP_LOG_LEN];
2783*d39bd2c1SGregory Neil Shapiro 
2784*d39bd2c1SGregory Neil Shapiro 			(void) data2hex((unsigned char *)rr + 3,
2785*d39bd2c1SGregory Neil Shapiro 				dane_tlsa->dane_tlsa_len[i] - 3,
2786*d39bd2c1SGregory Neil Shapiro 				hex, sizeof(hex));
2787*d39bd2c1SGregory Neil Shapiro 			sm_syslog(LOG_DEBUG, NOQID,
2788*d39bd2c1SGregory Neil Shapiro 				"STARTTLS=client, %s=%d, type=%d-%d-%d, fp=%s"
2789*d39bd2c1SGregory Neil Shapiro 				, chk, r, rr[0], rr[1], rr[2], hex);
2790*d39bd2c1SGregory Neil Shapiro 			tlslogerr(LOG_DEBUG, (r < 0) ? 13 : 10, "client");
2791*d39bd2c1SGregory Neil Shapiro 		}
2792*d39bd2c1SGregory Neil Shapiro 		if (tTd(96, 20))
2793*d39bd2c1SGregory Neil Shapiro 		{
2794*d39bd2c1SGregory Neil Shapiro 			unsigned char hex[DANE_FP_DBG_LEN];
2795*d39bd2c1SGregory Neil Shapiro 
2796*d39bd2c1SGregory Neil Shapiro 			(void) data2hex((unsigned char *)rr + 3,
2797*d39bd2c1SGregory Neil Shapiro 				dane_tlsa->dane_tlsa_len[i] - 3,
2798*d39bd2c1SGregory Neil Shapiro 				hex, sizeof(hex));
2799*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("ssl_dane_enable: SSL_dane_tlsa_add=%d, u=%d, s=%d, d=%d, len=%d, fp=%s\n"
2800*d39bd2c1SGregory Neil Shapiro 					, r, rr[0], rr[1], rr[2]
2801*d39bd2c1SGregory Neil Shapiro 					, dane_tlsa->dane_tlsa_len[i]-3, hex
2802*d39bd2c1SGregory Neil Shapiro 					);
2803*d39bd2c1SGregory Neil Shapiro 		}
2804*d39bd2c1SGregory Neil Shapiro 	}
2805*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 20))
2806*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ssl_dane_enable: usable=%d\n", usable);
2807*d39bd2c1SGregory Neil Shapiro 	if (0 == usable)
2808*d39bd2c1SGregory Neil Shapiro 	{
2809*d39bd2c1SGregory Neil Shapiro 		/* shouldn't happen - checked above! */
2810*d39bd2c1SGregory Neil Shapiro 		if (LogLevel > 1)
2811*d39bd2c1SGregory Neil Shapiro 			sm_syslog(LOG_CRIT, NOQID,
2812*d39bd2c1SGregory Neil Shapiro 				"ERROR: ssl_dane_enable() INCONSISTENY: %d usable TLSA RRs found but \"supported\" flag is set (%d)\n",
2813*d39bd2c1SGregory Neil Shapiro 				usable, TLSA_IS_FL(dane_tlsa, TLSAFLSUP));
2814*d39bd2c1SGregory Neil Shapiro 		dane_vrfy_ctx->dane_vrfy_chk |= TLSAFLNOVRFY;
2815*d39bd2c1SGregory Neil Shapiro 		return SM_SUCCESS;
2816*d39bd2c1SGregory Neil Shapiro 	}
2817*d39bd2c1SGregory Neil Shapiro #  endif /* HAVE_SSL_CTX_dane_enable */
2818*d39bd2c1SGregory Neil Shapiro 	return SM_SUCCESS;
2819*d39bd2c1SGregory Neil Shapiro }
28205b0945b5SGregory Neil Shapiro # endif /* DANE */
28215b0945b5SGregory Neil Shapiro 
28225b0945b5SGregory Neil Shapiro /*
282340266059SGregory Neil Shapiro **  TLS_VERIFY_CB -- verify callback for TLS certificates
282440266059SGregory Neil Shapiro **
282540266059SGregory Neil Shapiro **	Parameters:
28265b0945b5SGregory Neil Shapiro **		ctx -- X509 context
28275b0945b5SGregory Neil Shapiro **		cb_ctx -- callback context
282840266059SGregory Neil Shapiro **
282940266059SGregory Neil Shapiro **	Returns:
283040266059SGregory Neil Shapiro **		accept connection?
283140266059SGregory Neil Shapiro **		currently: always yes.
283240266059SGregory Neil Shapiro */
283340266059SGregory Neil Shapiro 
283440266059SGregory Neil Shapiro static int
28355b0945b5SGregory Neil Shapiro tls_verify_cb(ctx, cb_ctx)
283640266059SGregory Neil Shapiro 	X509_STORE_CTX *ctx;
28375b0945b5SGregory Neil Shapiro 	void *cb_ctx;
283840266059SGregory Neil Shapiro {
283940266059SGregory Neil Shapiro 	int ok;
28405b0945b5SGregory Neil Shapiro # if DANE
28415b0945b5SGregory Neil Shapiro 	SM_DECTLSI;
2842*d39bd2c1SGregory Neil Shapiro 	dane_vrfy_ctx_P dane_vrfy_ctx;
28435b0945b5SGregory Neil Shapiro # endif
284440266059SGregory Neil Shapiro 
28459bd497b8SGregory Neil Shapiro 	/*
28465b0945b5SGregory Neil Shapiro 	**  SSL_CTX_set_cert_verify_callback(3):
28479bd497b8SGregory Neil Shapiro 	**  callback should return 1 to indicate verification success
28489bd497b8SGregory Neil Shapiro 	**  and 0 to indicate verification failure.
28499bd497b8SGregory Neil Shapiro 	*/
28509bd497b8SGregory Neil Shapiro 
28515b0945b5SGregory Neil Shapiro # if DANE
28525b0945b5SGregory Neil Shapiro 	SM_GETTLSI;
2853*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 40))
2854*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("tls_verify_cb: tlsi_ctx=%p, vrfy_chk=%#x\n", tlsi_ctx,
2855*d39bd2c1SGregory Neil Shapiro 			(tlsi_ctx != NULL && (dane_vrfy_ctx = &(tlsi_ctx->tlsi_dvc)) != NULL) ?
2856*d39bd2c1SGregory Neil Shapiro 			dane_vrfy_ctx->dane_vrfy_chk : -1);
2857*d39bd2c1SGregory Neil Shapiro 	if (tlsi_ctx != NULL && (dane_vrfy_ctx = &(tlsi_ctx->tlsi_dvc)) != NULL
2858*d39bd2c1SGregory Neil Shapiro 	    && !dane_vrfy_ctx->dane_vrfy_dane_enabled
2859*d39bd2c1SGregory Neil Shapiro 	    && (0 == (dane_vrfy_ctx->dane_vrfy_chk & TLSAFLTEMPVRFY))
2860*d39bd2c1SGregory Neil Shapiro 	    && VRFY_DANE(dane_vrfy_ctx->dane_vrfy_chk)
2861*d39bd2c1SGregory Neil Shapiro 	)
28625b0945b5SGregory Neil Shapiro 	{
2863*d39bd2c1SGregory Neil Shapiro 		int depth;
28645b0945b5SGregory Neil Shapiro 
2865*d39bd2c1SGregory Neil Shapiro 		depth = X509_STORE_CTX_get_error_depth(ctx);
2866*d39bd2c1SGregory Neil Shapiro 		if (tTd(96, 20))
2867*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("tls_verify_cb: enabled=%d, chk=%#x, depth=%d\n",
2868*d39bd2c1SGregory Neil Shapiro 				dane_vrfy_ctx->dane_vrfy_dane_enabled,
2869*d39bd2c1SGregory Neil Shapiro 				dane_vrfy_ctx->dane_vrfy_chk, depth);
2870*d39bd2c1SGregory Neil Shapiro 
2871*d39bd2c1SGregory Neil Shapiro 		if (0 == depth)
2872*d39bd2c1SGregory Neil Shapiro 		{
28735b0945b5SGregory Neil Shapiro 			ok = dane_verify(ctx, dane_vrfy_ctx);
28745b0945b5SGregory Neil Shapiro 			if (tTd(96, 2))
2875*d39bd2c1SGregory Neil Shapiro 				sm_dprintf("tls_verify_cb: dane_verify=%d, res=%d\n", ok,
28765b0945b5SGregory Neil Shapiro 					dane_vrfy_ctx->dane_vrfy_res);
28775b0945b5SGregory Neil Shapiro 			if (ok != DANE_VRFY_NONE)
28785b0945b5SGregory Neil Shapiro 				return 1;
28795b0945b5SGregory Neil Shapiro 		}
2880*d39bd2c1SGregory Neil Shapiro 	}
2881*d39bd2c1SGregory Neil Shapiro 
2882*d39bd2c1SGregory Neil Shapiro 	if (tTd(96, 10))
2883*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("tls_verify_cb: basic check? enabled=%d, chk=%#x\n",
2884*d39bd2c1SGregory Neil Shapiro 			(tlsi_ctx != NULL && dane_vrfy_ctx != NULL) ?
2885*d39bd2c1SGregory Neil Shapiro 				dane_vrfy_ctx->dane_vrfy_dane_enabled : -1,
2886*d39bd2c1SGregory Neil Shapiro 			(tlsi_ctx != NULL && dane_vrfy_ctx != NULL) ?
2887*d39bd2c1SGregory Neil Shapiro 				dane_vrfy_ctx->dane_vrfy_chk : -1);
28885b0945b5SGregory Neil Shapiro # endif /* DANE */
28895b0945b5SGregory Neil Shapiro 
289040266059SGregory Neil Shapiro 	ok = X509_verify_cert(ctx);
2891*d39bd2c1SGregory Neil Shapiro 	if ((LogLevel > 13 && ok <= 0) || LogLevel > 14)
28925b0945b5SGregory Neil Shapiro 		(void) tls_verify_log(ok, ctx, "TLS");
28939bd497b8SGregory Neil Shapiro 	return 1;
289440266059SGregory Neil Shapiro }
28955b0945b5SGregory Neil Shapiro 
289640266059SGregory Neil Shapiro /*
289740266059SGregory Neil Shapiro **  TLSLOGERR -- log the errors from the TLS error stack
289840266059SGregory Neil Shapiro **
289940266059SGregory Neil Shapiro **	Parameters:
29005b0945b5SGregory Neil Shapiro **		priority -- syslog priority
29015b0945b5SGregory Neil Shapiro **		ll -- loglevel
290240266059SGregory Neil Shapiro **		who -- server/client (for logging).
290340266059SGregory Neil Shapiro **
290440266059SGregory Neil Shapiro **	Returns:
290540266059SGregory Neil Shapiro **		none.
290640266059SGregory Neil Shapiro */
290740266059SGregory Neil Shapiro 
290840266059SGregory Neil Shapiro void
29095b0945b5SGregory Neil Shapiro tlslogerr(priority, ll, who)
29105b0945b5SGregory Neil Shapiro 	int priority;
29115b0945b5SGregory Neil Shapiro 	int ll;
29124e4196cbSGregory Neil Shapiro 	const char *who;
291340266059SGregory Neil Shapiro {
291440266059SGregory Neil Shapiro 	unsigned long l;
291540266059SGregory Neil Shapiro 	int line, flags;
291640266059SGregory Neil Shapiro 	char *file, *data;
291740266059SGregory Neil Shapiro 	char buf[256];
291840266059SGregory Neil Shapiro 
29195b0945b5SGregory Neil Shapiro 	if (LogLevel <= ll)
29205b0945b5SGregory Neil Shapiro 		return;
2921*d39bd2c1SGregory Neil Shapiro 	while ((l = MTA_SSL_ERR_get((const char **) &file, &line,
2922*d39bd2c1SGregory Neil Shapiro 				    (const char **) &data, &flags, NULL))
292340266059SGregory Neil Shapiro 		!= 0)
292440266059SGregory Neil Shapiro 	{
29255b0945b5SGregory Neil Shapiro 		sm_syslog(priority, NOQID,
29265b0945b5SGregory Neil Shapiro 			  "STARTTLS=%s: %s:%s:%d:%s", who,
292740266059SGregory Neil Shapiro 			  ERR_error_string(l, buf),
292840266059SGregory Neil Shapiro 			  file, line,
292940266059SGregory Neil Shapiro 			  bitset(ERR_TXT_STRING, flags) ? data : "");
293040266059SGregory Neil Shapiro 	}
293140266059SGregory Neil Shapiro }
2932e92d3f3fSGregory Neil Shapiro 
2933e92d3f3fSGregory Neil Shapiro /*
2934e92d3f3fSGregory Neil Shapiro **  X509_VERIFY_CB -- verify callback
2935e92d3f3fSGregory Neil Shapiro **
2936e92d3f3fSGregory Neil Shapiro **	Parameters:
29375b0945b5SGregory Neil Shapiro **		ok -- current result
29385b0945b5SGregory Neil Shapiro **		ctx -- X509 context
2939e92d3f3fSGregory Neil Shapiro **
2940e92d3f3fSGregory Neil Shapiro **	Returns:
2941e92d3f3fSGregory Neil Shapiro **		accept connection?
2942e92d3f3fSGregory Neil Shapiro **		currently: always yes.
2943e92d3f3fSGregory Neil Shapiro */
2944e92d3f3fSGregory Neil Shapiro 
2945e92d3f3fSGregory Neil Shapiro static int
2946e92d3f3fSGregory Neil Shapiro x509_verify_cb(ok, ctx)
2947e92d3f3fSGregory Neil Shapiro 	int ok;
2948e92d3f3fSGregory Neil Shapiro 	X509_STORE_CTX *ctx;
2949e92d3f3fSGregory Neil Shapiro {
29505b0945b5SGregory Neil Shapiro 	SM_DECTLSI;
29515b0945b5SGregory Neil Shapiro 
29525b0945b5SGregory Neil Shapiro 	if (ok != 0)
29535b0945b5SGregory Neil Shapiro 		return ok;
29545b0945b5SGregory Neil Shapiro 
29555b0945b5SGregory Neil Shapiro 	SM_GETTLSI;
2956e92d3f3fSGregory Neil Shapiro 	if (LogLevel > 13)
29575b0945b5SGregory Neil Shapiro 		tls_verify_log(ok, ctx, "X509");
29585b0945b5SGregory Neil Shapiro 	if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL &&
29595b0945b5SGregory Neil Shapiro 	    !SM_TLSI_IS(tlsi_ctx, TLSI_FL_CRLREQ))
2960e92d3f3fSGregory Neil Shapiro 	{
296141451aa3SJung-uk Kim 		X509_STORE_CTX_set_error(ctx, 0);
2962e92d3f3fSGregory Neil Shapiro 		return 1;	/* override it */
2963e92d3f3fSGregory Neil Shapiro 	}
2964e92d3f3fSGregory Neil Shapiro 	return ok;
2965e92d3f3fSGregory Neil Shapiro }
29665b0945b5SGregory Neil Shapiro 
29672fb4f839SGregory Neil Shapiro # if !USE_OPENSSL_ENGINE && !defined(OPENSSL_NO_ENGINE)
29685b0945b5SGregory Neil Shapiro /*
29695b0945b5SGregory Neil Shapiro **  TLS_SET_ENGINE -- set up ENGINE if needed
29705b0945b5SGregory Neil Shapiro **
29715b0945b5SGregory Neil Shapiro **	Parameters:
29725b0945b5SGregory Neil Shapiro **		id -- id for ENGINE
29735b0945b5SGregory Neil Shapiro **		isprefork -- called before fork()?
29745b0945b5SGregory Neil Shapiro **
29755b0945b5SGregory Neil Shapiro **	Returns: (OpenSSL "semantics", reverse it to allow returning error codes)
29765b0945b5SGregory Neil Shapiro **		0: failure
29775b0945b5SGregory Neil Shapiro **		!=0: ok
29785b0945b5SGregory Neil Shapiro */
29795b0945b5SGregory Neil Shapiro 
29805b0945b5SGregory Neil Shapiro int
29815b0945b5SGregory Neil Shapiro TLS_set_engine(id, isprefork)
29825b0945b5SGregory Neil Shapiro 	const char *id;
29835b0945b5SGregory Neil Shapiro 	bool isprefork;
29845b0945b5SGregory Neil Shapiro {
29855b0945b5SGregory Neil Shapiro 	static bool TLSEngineInitialized = false;
29865b0945b5SGregory Neil Shapiro 	ENGINE *e;
29875b0945b5SGregory Neil Shapiro 	char enginepath[MAXPATHLEN];
29885b0945b5SGregory Neil Shapiro 
29895b0945b5SGregory Neil Shapiro 	/*
29905b0945b5SGregory Neil Shapiro 	**  Todo: put error for logging into a string and log it in error:
29915b0945b5SGregory Neil Shapiro 	*/
29925b0945b5SGregory Neil Shapiro 
29935b0945b5SGregory Neil Shapiro 	if (LogLevel > 13)
29945b0945b5SGregory Neil Shapiro 		sm_syslog(LOG_DEBUG, NOQID,
29955b0945b5SGregory Neil Shapiro 			"engine=%s, path=%s, ispre=%d, pre=%d, initialized=%d",
29965b0945b5SGregory Neil Shapiro 			id, SSLEnginePath, isprefork, SSLEngineprefork,
29975b0945b5SGregory Neil Shapiro 			TLSEngineInitialized);
29985b0945b5SGregory Neil Shapiro 	if (TLSEngineInitialized)
29995b0945b5SGregory Neil Shapiro 		return 1;
30002fb4f839SGregory Neil Shapiro 	if (SM_IS_EMPTY(id))
30015b0945b5SGregory Neil Shapiro 		return 1;
30022fb4f839SGregory Neil Shapiro #  if !defined(ENGINE_METHOD_ALL)
30032fb4f839SGregory Neil Shapiro 	if (LogLevel > 9)
30042fb4f839SGregory Neil Shapiro 		sm_syslog(LOG_NOTICE, NOQID,
30052fb4f839SGregory Neil Shapiro 			"engine=%s, status=engines_not_support", id)
30062fb4f839SGregory Neil Shapiro 	goto error;
30072fb4f839SGregory Neil Shapiro #  endif
30085b0945b5SGregory Neil Shapiro 
30095b0945b5SGregory Neil Shapiro 	/* is this the "right time" to initialize the engine? */
30105b0945b5SGregory Neil Shapiro 	if (isprefork != SSLEngineprefork)
30115b0945b5SGregory Neil Shapiro 		return 1;
30125b0945b5SGregory Neil Shapiro 
30135b0945b5SGregory Neil Shapiro 	e = NULL;
30145b0945b5SGregory Neil Shapiro 	ENGINE_load_builtin_engines();
30155b0945b5SGregory Neil Shapiro 
30165b0945b5SGregory Neil Shapiro 	if (SSLEnginePath != NULL && *SSLEnginePath != '\0')
30175b0945b5SGregory Neil Shapiro 	{
30185b0945b5SGregory Neil Shapiro 		if ((e = ENGINE_by_id("dynamic")) == NULL)
30195b0945b5SGregory Neil Shapiro 		{
30205b0945b5SGregory Neil Shapiro 			if (LogLevel > 1)
30215b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
30225b0945b5SGregory Neil Shapiro 					"engine=%s, by_id=failed", "dynamic");
30235b0945b5SGregory Neil Shapiro 			goto error;
30245b0945b5SGregory Neil Shapiro 		}
30255b0945b5SGregory Neil Shapiro 		(void) sm_snprintf(enginepath, sizeof(enginepath),
30265b0945b5SGregory Neil Shapiro 			"%s/lib%s.so", SSLEnginePath, id);
30275b0945b5SGregory Neil Shapiro 
30285b0945b5SGregory Neil Shapiro 		if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", enginepath, 0))
30295b0945b5SGregory Neil Shapiro 		{
30305b0945b5SGregory Neil Shapiro 			if (LogLevel > 1)
30315b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
30325b0945b5SGregory Neil Shapiro 					"engine=%s, SO_PATH=%s, status=failed",
30335b0945b5SGregory Neil Shapiro 					id, enginepath);
30345b0945b5SGregory Neil Shapiro 			goto error;
30355b0945b5SGregory Neil Shapiro 		}
30365b0945b5SGregory Neil Shapiro 
30375b0945b5SGregory Neil Shapiro 		if (!ENGINE_ctrl_cmd_string(e, "ID", id, 0))
30385b0945b5SGregory Neil Shapiro 		{
30395b0945b5SGregory Neil Shapiro 			if (LogLevel > 1)
30405b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
30415b0945b5SGregory Neil Shapiro 					"engine=%s, ID=failed", id);
30425b0945b5SGregory Neil Shapiro 			goto error;
30435b0945b5SGregory Neil Shapiro 		}
30445b0945b5SGregory Neil Shapiro 
30455b0945b5SGregory Neil Shapiro 		if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
30465b0945b5SGregory Neil Shapiro 		{
30475b0945b5SGregory Neil Shapiro 			if (LogLevel > 1)
30485b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_ERR, NOQID,
30495b0945b5SGregory Neil Shapiro 					"engine=%s, LOAD=failed", id);
30505b0945b5SGregory Neil Shapiro 			goto error;
30515b0945b5SGregory Neil Shapiro 		}
30525b0945b5SGregory Neil Shapiro 	}
30535b0945b5SGregory Neil Shapiro 	else if ((e = ENGINE_by_id(id)) == NULL)
30545b0945b5SGregory Neil Shapiro 	{
30555b0945b5SGregory Neil Shapiro 		if (LogLevel > 1)
30565b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID, "engine=%s, by_id=failed",
30575b0945b5SGregory Neil Shapiro 				id);
30585b0945b5SGregory Neil Shapiro 		return 0;
30595b0945b5SGregory Neil Shapiro 	}
30605b0945b5SGregory Neil Shapiro 
30615b0945b5SGregory Neil Shapiro 	if (!ENGINE_init(e))
30625b0945b5SGregory Neil Shapiro 	{
30635b0945b5SGregory Neil Shapiro 		if (LogLevel > 1)
30645b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID, "engine=%s, init=failed", id);
30655b0945b5SGregory Neil Shapiro 		goto error;
30665b0945b5SGregory Neil Shapiro 	}
30675b0945b5SGregory Neil Shapiro 	if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
30685b0945b5SGregory Neil Shapiro 	{
30695b0945b5SGregory Neil Shapiro 		if (LogLevel > 1)
30705b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_ERR, NOQID,
30715b0945b5SGregory Neil Shapiro 				"engine=%s, set_default=failed", id);
30725b0945b5SGregory Neil Shapiro 		goto error;
30735b0945b5SGregory Neil Shapiro 	}
30745b0945b5SGregory Neil Shapiro #  ifdef ENGINE_CTRL_CHIL_SET_FORKCHECK
30755b0945b5SGregory Neil Shapiro 	if (strcmp(id, "chil") == 0)
30765b0945b5SGregory Neil Shapiro 		ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
30775b0945b5SGregory Neil Shapiro #  endif
30785b0945b5SGregory Neil Shapiro 
30795b0945b5SGregory Neil Shapiro 	/* Free our "structural" reference. */
30805b0945b5SGregory Neil Shapiro 	ENGINE_free(e);
30815b0945b5SGregory Neil Shapiro 	if (LogLevel > 10)
30825b0945b5SGregory Neil Shapiro 		sm_syslog(LOG_INFO, NOQID, "engine=%s, loaded=ok", id);
30835b0945b5SGregory Neil Shapiro 	TLSEngineInitialized = true;
30845b0945b5SGregory Neil Shapiro 	return 1;
30855b0945b5SGregory Neil Shapiro 
30865b0945b5SGregory Neil Shapiro   error:
30875b0945b5SGregory Neil Shapiro 	tlslogerr(LOG_WARNING, 7, "init");
30885b0945b5SGregory Neil Shapiro 	if (e != NULL)
30895b0945b5SGregory Neil Shapiro 		ENGINE_free(e);
30905b0945b5SGregory Neil Shapiro 	return 0;
30915b0945b5SGregory Neil Shapiro }
30922fb4f839SGregory Neil Shapiro # endif /* !USE_OPENSSL_ENGINE && !defined(OPENSSL_NO_ENGINE) */
309340266059SGregory Neil Shapiro #endif /* STARTTLS */
3094