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