xref: /netbsd-src/usr.sbin/syslogd/tls.c (revision b1c7adf12fc8ba9f15d7d0452af71327d27edfc7)
1*b1c7adf1Suwe /*	$NetBSD: tls.c,v 1.21 2022/11/08 01:05:10 uwe Exp $	*/
21c6aec20Schristos 
31c6aec20Schristos /*-
41c6aec20Schristos  * Copyright (c) 2008 The NetBSD Foundation, Inc.
51c6aec20Schristos  * All rights reserved.
61c6aec20Schristos  *
71c6aec20Schristos  * This code is derived from software contributed to The NetBSD Foundation
81c6aec20Schristos  * by Martin Sch�tte.
91c6aec20Schristos  *
101c6aec20Schristos  * Redistribution and use in source and binary forms, with or without
111c6aec20Schristos  * modification, are permitted provided that the following conditions
121c6aec20Schristos  * are met:
131c6aec20Schristos  * 1. Redistributions of source code must retain the above copyright
141c6aec20Schristos  *    notice, this list of conditions and the following disclaimer.
151c6aec20Schristos  * 2. Redistributions in binary form must reproduce the above copyright
161c6aec20Schristos  *    notice, this list of conditions and the following disclaimer in the
171c6aec20Schristos  *    documentation and/or other materials provided with the distribution.
181c6aec20Schristos  * 3. All advertising materials mentioning features or use of this software
191c6aec20Schristos  *    must display the following acknowledgement:
201c6aec20Schristos  *        This product includes software developed by the NetBSD
211c6aec20Schristos  *        Foundation, Inc. and its contributors.
221c6aec20Schristos  * 4. Neither the name of The NetBSD Foundation nor the names of its
231c6aec20Schristos  *    contributors may be used to endorse or promote products derived
241c6aec20Schristos  *    from this software without specific prior written permission.
251c6aec20Schristos  *
261c6aec20Schristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
271c6aec20Schristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
281c6aec20Schristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
291c6aec20Schristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
301c6aec20Schristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
311c6aec20Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
321c6aec20Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
331c6aec20Schristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
341c6aec20Schristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
351c6aec20Schristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
361c6aec20Schristos  * POSSIBILITY OF SUCH DAMAGE.
371c6aec20Schristos  */
381c6aec20Schristos /*
391c6aec20Schristos  * tls.c TLS related code for syslogd
401c6aec20Schristos  *
411c6aec20Schristos  * implements the TLS init and handshake callbacks with all required
421c6aec20Schristos  * checks from http://tools.ietf.org/html/draft-ietf-syslog-transport-tls-13
431c6aec20Schristos  *
441c6aec20Schristos  * Martin Sch�tte
451c6aec20Schristos  */
461c6aec20Schristos 
471c6aec20Schristos #include <sys/cdefs.h>
48*b1c7adf1Suwe __RCSID("$NetBSD: tls.c,v 1.21 2022/11/08 01:05:10 uwe Exp $");
491c6aec20Schristos 
501c6aec20Schristos #ifndef DISABLE_TLS
519009c648Schristos #include <sys/stat.h>
521c6aec20Schristos #include "syslogd.h"
531c6aec20Schristos #include "tls.h"
541c6aec20Schristos #include <netinet/in.h>
551c6aec20Schristos #include <ifaddrs.h>
561c6aec20Schristos #include "extern.h"
571c6aec20Schristos 
581c6aec20Schristos static unsigned getVerifySetting(const char *x509verifystring);
591c6aec20Schristos 
60*b1c7adf1Suwe #ifndef NDEBUG
611c6aec20Schristos /* to output SSL error codes */
621c6aec20Schristos static const char *SSL_ERRCODE[] = {
631c6aec20Schristos 	"SSL_ERROR_NONE",
641c6aec20Schristos 	"SSL_ERROR_SSL",
651c6aec20Schristos 	"SSL_ERROR_WANT_READ",
661c6aec20Schristos 	"SSL_ERROR_WANT_WRITE",
671c6aec20Schristos 	"SSL_ERROR_WANT_X509_LOOKUP",
681c6aec20Schristos 	"SSL_ERROR_SYSCALL",
691c6aec20Schristos 	"SSL_ERROR_ZERO_RETURN",
701c6aec20Schristos 	"SSL_ERROR_WANT_CONNECT",
711c6aec20Schristos 	"SSL_ERROR_WANT_ACCEPT"};
721c6aec20Schristos /* TLS connection states -- keep in sync with symbols in .h */
731c6aec20Schristos static const char *TLS_CONN_STATES[] = {
741c6aec20Schristos 	"ST_NONE",
751c6aec20Schristos 	"ST_TLS_EST",
761c6aec20Schristos 	"ST_TCP_EST",
771c6aec20Schristos 	"ST_CONNECTING",
781c6aec20Schristos 	"ST_ACCEPTING",
791c6aec20Schristos 	"ST_READING",
801c6aec20Schristos 	"ST_WRITING",
811c6aec20Schristos 	"ST_EOF",
821c6aec20Schristos 	"ST_CLOSING0",
831c6aec20Schristos 	"ST_CLOSING1",
841c6aec20Schristos 	"ST_CLOSING2"};
85*b1c7adf1Suwe #endif	/* !NDEBUG */
861c6aec20Schristos 
871c6aec20Schristos DH *get_dh1024(void);
881c6aec20Schristos /* DH parameter precomputed with "openssl dhparam -C -2 1024" */
891c6aec20Schristos DH *
get_dh1024(void)901c6aec20Schristos get_dh1024(void)
911c6aec20Schristos {
921c6aec20Schristos 	static const unsigned char dh1024_p[]={
931c6aec20Schristos 		0x94,0xBC,0xC4,0x71,0xD4,0xD3,0x2B,0x17,0x69,0xEA,0x82,0x1B,
941c6aec20Schristos 		0x0F,0x86,0x45,0x57,0xF8,0x86,0x2C,0xC8,0xF5,0x37,0x1F,0x1F,
951c6aec20Schristos 		0x12,0xDA,0x2C,0x62,0x4C,0xF6,0x95,0xF0,0xE4,0x6A,0x63,0x00,
961c6aec20Schristos 		0x32,0x54,0x5F,0xA9,0xAA,0x2E,0xD2,0xD3,0xA5,0x7A,0x4E,0xCF,
971c6aec20Schristos 		0xE8,0x2A,0xF6,0xAB,0xAF,0xD3,0x71,0x3E,0x75,0x9E,0x6B,0xF3,
981c6aec20Schristos 		0x2E,0x6D,0x97,0x42,0xC2,0x45,0xC0,0x03,0xE1,0x17,0xA4,0x39,
991c6aec20Schristos 		0xF6,0x36,0xA7,0x11,0xBD,0x30,0xF6,0x6F,0x21,0xBF,0x28,0xE4,
1001c6aec20Schristos 		0xF9,0xE1,0x1E,0x48,0x72,0x58,0xA9,0xC8,0x61,0x65,0xDB,0x66,
1011c6aec20Schristos 		0x36,0xA3,0x77,0x0A,0x81,0x79,0x2C,0x45,0x1E,0x97,0xA6,0xB1,
1021c6aec20Schristos 		0xD9,0x25,0x9C,0x28,0x96,0x91,0x40,0xF8,0xF6,0x86,0x11,0x9C,
1031c6aec20Schristos 		0x88,0xEC,0xA6,0xBA,0x9F,0x4F,0x85,0x43 };
1041c6aec20Schristos 	static const unsigned char dh1024_g[]={ 0x02 };
1051c6aec20Schristos 	DH *dh;
1064d91e676Schristos 	BIGNUM *p, *g;
1071c6aec20Schristos 
1081c6aec20Schristos 	if ((dh = DH_new()) == NULL)
1091c6aec20Schristos 		return NULL;
1104d91e676Schristos 	p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
1114d91e676Schristos 	g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
1124d91e676Schristos 	if (p == NULL || g == NULL)
1134d91e676Schristos 		goto out;
1144d91e676Schristos 	if (!DH_set0_pqg(dh, p, NULL, g))
1154d91e676Schristos 		goto out;
1164d91e676Schristos 	return dh;
1174d91e676Schristos out:
1181c6aec20Schristos 	DH_free(dh);
1191c6aec20Schristos 	return NULL;
1201c6aec20Schristos }
1211c6aec20Schristos 
1221c6aec20Schristos #define ST_CHANGE(x, y) do {					\
1231c6aec20Schristos 	if ((x) != (y)) { 					\
1241c6aec20Schristos 		DPRINTF(D_TLS, "Change state: %s --> %s\n",	\
1251c6aec20Schristos 		    TLS_CONN_STATES[x], TLS_CONN_STATES[y]);	\
1261c6aec20Schristos 		(x) = (y);					\
1271c6aec20Schristos 	}							\
1286f4965e0Srillig } while (0)
1291c6aec20Schristos 
1301c6aec20Schristos static unsigned
getVerifySetting(const char * x509verifystring)1311c6aec20Schristos getVerifySetting(const char *x509verifystring)
1321c6aec20Schristos {
1331c6aec20Schristos 	if (!x509verifystring)
1341c6aec20Schristos 		return X509VERIFY_ALWAYS;
1351c6aec20Schristos 
1361c6aec20Schristos 	if (!strcasecmp(x509verifystring, "off"))
1371c6aec20Schristos 		return X509VERIFY_NONE;
1381c6aec20Schristos 	else if (!strcasecmp(x509verifystring, "opt"))
1391c6aec20Schristos 		return X509VERIFY_IFPRESENT;
1401c6aec20Schristos 	else
1411c6aec20Schristos 		return X509VERIFY_ALWAYS;
1421c6aec20Schristos }
1431c6aec20Schristos /*
1441c6aec20Schristos  * init OpenSSL lib and one context.
1451c6aec20Schristos  * returns NULL if global context already exists.
146b5860281Sandvar  * returns a status message on successful init (to be free()d by caller).
1471c6aec20Schristos  * calls die() on serious error.
1481c6aec20Schristos  */
1491c6aec20Schristos char*
init_global_TLS_CTX(void)15092dd0698Schristos init_global_TLS_CTX(void)
1511c6aec20Schristos {
1521c6aec20Schristos 	const char *keyfilename	  = tls_opt.keyfile;
1531c6aec20Schristos 	const char *certfilename  = tls_opt.certfile;
1541c6aec20Schristos 	const char *CAfile	  = tls_opt.CAfile;
1551c6aec20Schristos 	const char *CApath	  = tls_opt.CAdir;
1561c6aec20Schristos 
1571c6aec20Schristos 	SSL_CTX *ctx;
1581c6aec20Schristos 	unsigned x509verify = X509VERIFY_ALWAYS;
1591c6aec20Schristos 	EVP_PKEY *pkey = NULL;
1601c6aec20Schristos 	X509	 *cert = NULL;
1611c6aec20Schristos 	FILE *certfile = NULL;
1621c6aec20Schristos 	FILE  *keyfile = NULL;
1631c6aec20Schristos 	unsigned long err;
1641c6aec20Schristos 	char *fp = NULL, *cn = NULL;
1651c6aec20Schristos 
1661c6aec20Schristos 	char statusmsg[1024];
1671c6aec20Schristos 
1681c6aec20Schristos 	if (tls_opt.global_TLS_CTX) /* already initialized */
1691c6aec20Schristos 		return NULL;
1701c6aec20Schristos 
1711c6aec20Schristos 	x509verify = getVerifySetting(tls_opt.x509verify);
1721c6aec20Schristos 	if (x509verify != X509VERIFY_ALWAYS)
1731c6aec20Schristos 		loginfo("insecure configuration, peer authentication disabled");
1741c6aec20Schristos 
1751c6aec20Schristos 	if (!(ctx = SSL_CTX_new(SSLv23_method()))) {
1761c6aec20Schristos 		logerror("Unable to initialize OpenSSL: %s",
1771c6aec20Schristos 		    ERR_error_string(ERR_get_error(), NULL));
1781c6aec20Schristos 		die(0,0,NULL);
1791c6aec20Schristos 	}
1801c6aec20Schristos 
1811c6aec20Schristos 	if (!keyfilename)
1821c6aec20Schristos 		keyfilename = DEFAULT_X509_KEYFILE;
1831c6aec20Schristos 	if (!certfilename)
1841c6aec20Schristos 		certfilename = DEFAULT_X509_CERTFILE;
1851c6aec20Schristos 
1861c6aec20Schristos 	/* TODO: would it be better to use stat() for access checking? */
1871c6aec20Schristos 	if (!(keyfile  = fopen(keyfilename,  "r"))
1881c6aec20Schristos 	 && !(certfile = fopen(certfilename, "r"))) {
1891c6aec20Schristos 		errno = 0;
1901c6aec20Schristos 		if (!tls_opt.gen_cert) {
1911c6aec20Schristos 			logerror("TLS certificate files \"%s\" and \"%s\""
1921c6aec20Schristos 			    "not readable. Please configure them with "
1931c6aec20Schristos 			    "\"tls_cert\" and \"tls_key\" or set "
1941c6aec20Schristos 			    "\"tls_gen_cert=1\" to generate a new "
1951c6aec20Schristos 			    "certificate", keyfilename, certfilename);
1961c6aec20Schristos 			die(0,0,NULL);
1971c6aec20Schristos 		}
1981c6aec20Schristos 
1991c6aec20Schristos 		loginfo("Generating a self-signed certificate and writing "
2001c6aec20Schristos 		    "files \"%s\" and \"%s\"", keyfilename, certfilename);
2011c6aec20Schristos 		if (!mk_x509_cert(&cert, &pkey, TLS_GENCERT_BITS,
2021c6aec20Schristos 		    TLS_GENCERT_SERIAL, TLS_GENCERT_DAYS)) {
2031c6aec20Schristos 			logerror("Unable to generate new certificate.");
2041c6aec20Schristos 			die(0,0,NULL);
2051c6aec20Schristos 		}
2061c6aec20Schristos 		if (!write_x509files(pkey, cert,
2071c6aec20Schristos 		    keyfilename, certfilename)) {
2081c6aec20Schristos 			logerror("Unable to write certificate to files \"%s\""
2091c6aec20Schristos 			    " and \"%s\"", keyfilename, certfilename);
2101c6aec20Schristos 			/* not fatal */
2111c6aec20Schristos 		}
2121c6aec20Schristos 	}
2131c6aec20Schristos 	if (keyfile)
2141c6aec20Schristos 		(void)fclose(keyfile);
2151c6aec20Schristos 	if (certfile)
2161c6aec20Schristos 		(void)fclose(certfile);
2171c6aec20Schristos 	errno = 0;
2181c6aec20Schristos 
2191c6aec20Schristos 	/* if generated, then use directly */
2201c6aec20Schristos 	if (cert && pkey) {
2211c6aec20Schristos 		if (!SSL_CTX_use_PrivateKey(ctx, pkey)
2221c6aec20Schristos 		    || !SSL_CTX_use_certificate(ctx, cert)) {
2231c6aec20Schristos 			logerror("Unable to use generated private "
2241c6aec20Schristos 			    "key and certificate: %s",
2251c6aec20Schristos 			    ERR_error_string(ERR_get_error(), NULL));
2261c6aec20Schristos 			die(0,0,NULL);	/* any better reaction? */
2271c6aec20Schristos 		 }
2281c6aec20Schristos 	} else {
2291c6aec20Schristos 		/* load keys and certs from files */
2301c6aec20Schristos 		if (!SSL_CTX_use_PrivateKey_file(ctx, keyfilename,
2311c6aec20Schristos 							SSL_FILETYPE_PEM)
2321c6aec20Schristos 		    || !SSL_CTX_use_certificate_chain_file(ctx, certfilename)) {
2331c6aec20Schristos 			logerror("Unable to load private key and "
2341c6aec20Schristos 			    "certificate from files \"%s\" and \"%s\": %s",
2351c6aec20Schristos 			    keyfilename, certfilename,
2361c6aec20Schristos 			    ERR_error_string(ERR_get_error(), NULL));
2371c6aec20Schristos 			die(0,0,NULL);	/* any better reaction? */
2381c6aec20Schristos 		}
2391c6aec20Schristos 	}
2401c6aec20Schristos 	if (!SSL_CTX_check_private_key(ctx)) {
2411c6aec20Schristos 		logerror("Private key \"%s\" does not match "
2421c6aec20Schristos 		    "certificate \"%s\": %s",
2431c6aec20Schristos 		    keyfilename, certfilename,
2441c6aec20Schristos 		    ERR_error_string(ERR_get_error(), NULL));
2451c6aec20Schristos 		die(0,0,NULL);
2461c6aec20Schristos 	}
2471c6aec20Schristos 
2481c6aec20Schristos 	if (CAfile || CApath) {
2491c6aec20Schristos 		if (SSL_CTX_load_verify_locations(ctx, CAfile, CApath) != 1) {
2501c6aec20Schristos 			if (CAfile && CApath)
2511c6aec20Schristos 				logerror("unable to load trust anchors from "
2521c6aec20Schristos 				    "\"%s\" and \"%s\": %s\n",
2531c6aec20Schristos 				    CAfile, CApath, ERR_error_string(
2541c6aec20Schristos 				    ERR_get_error(), NULL));
2551c6aec20Schristos 			else
2561c6aec20Schristos 				logerror("unable to load trust anchors from "
2571c6aec20Schristos 				    "\"%s\": %s\n", (CAfile?CAfile:CApath),
2581c6aec20Schristos 				    ERR_error_string(
2591c6aec20Schristos 				    ERR_get_error(), NULL));
2601c6aec20Schristos 		} else {
2611c6aec20Schristos 			DPRINTF(D_TLS, "loaded trust anchors\n");
2621c6aec20Schristos 		}
2631c6aec20Schristos 	}
2641c6aec20Schristos 
2651c6aec20Schristos 	/* options */
2661c6aec20Schristos 	(void)SSL_CTX_set_options(ctx,
2671c6aec20Schristos 	    SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE);
2681c6aec20Schristos 	(void)SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
2691c6aec20Schristos 
2701c6aec20Schristos 	/* peer verification */
2711c6aec20Schristos 	if ((x509verify == X509VERIFY_NONE)
2721c6aec20Schristos 	    || (x509verify == X509VERIFY_IFPRESENT))
2731c6aec20Schristos 		/* ask for cert, but a client does not have to send one */
2741c6aec20Schristos 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, check_peer_cert);
2751c6aec20Schristos 	else
2761c6aec20Schristos 		/* default: ask for cert and check it */
2771c6aec20Schristos 		SSL_CTX_set_verify(ctx,
2781c6aec20Schristos 			SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2791c6aec20Schristos 			check_peer_cert);
2801c6aec20Schristos 
2811c6aec20Schristos 	if (SSL_CTX_set_tmp_dh(ctx, get_dh1024()) != 1)
2821c6aec20Schristos 		logerror("SSL_CTX_set_tmp_dh() failed: %s",
2831c6aec20Schristos 		    ERR_error_string(ERR_get_error(), NULL));
2841c6aec20Schristos 
2851c6aec20Schristos 	/* make sure the OpenSSL error queue is empty */
2861c6aec20Schristos 	while ((err = ERR_get_error()) != 0)
2871c6aec20Schristos 		logerror("Unexpected OpenSSL error: %s",
2881c6aec20Schristos 		    ERR_error_string(err, NULL));
2891c6aec20Schristos 
2901c6aec20Schristos 
2911c6aec20Schristos 	/* On successful init the status message is not logged immediately
2921c6aec20Schristos 	 * but passed to the caller. The reason is that init() can continue
2931c6aec20Schristos 	 * to initialize syslog-sign. When the status message is logged
2941c6aec20Schristos 	 * after that it will get a valid signature and not cause errors
2951c6aec20Schristos 	 * with signature verification.
2961c6aec20Schristos 	 */
2971c6aec20Schristos 	if (cert || read_certfile(&cert, certfilename)) {
2981c6aec20Schristos 		get_fingerprint(cert, &fp, NULL);
2991c6aec20Schristos 		get_commonname(cert, &cn);
3001c6aec20Schristos 	}
3011c6aec20Schristos 	DPRINTF(D_TLS, "loaded and checked own certificate\n");
3021c6aec20Schristos 	snprintf(statusmsg, sizeof(statusmsg),
3031c6aec20Schristos 	    "Initialized TLS settings using library \"%s\". "
3041c6aec20Schristos 	    "Use certificate from file \"%s\" with CN \"%s\" "
3051c6aec20Schristos 	    "and fingerprint \"%s\"", SSLeay_version(SSLEAY_VERSION),
3061c6aec20Schristos 	    certfilename, cn, fp);
3071c6aec20Schristos 	free(cn);
3081c6aec20Schristos 	free(fp);
3091c6aec20Schristos 
3101c6aec20Schristos 	tls_opt.global_TLS_CTX = ctx;
3111c6aec20Schristos 	return strdup(statusmsg);
3121c6aec20Schristos }
3131c6aec20Schristos 
3141c6aec20Schristos 
3151c6aec20Schristos /*
3161c6aec20Schristos  * get fingerprint of cert
3171c6aec20Schristos  * returnstring will be allocated and should be free()d by the caller
3181c6aec20Schristos  * alg_name selects an algorithm, if it is NULL then DEFAULT_FINGERPRINT_ALG
3191c6aec20Schristos  * (should be "sha-1") will be used
3201c6aec20Schristos  * return value and non-NULL *returnstring indicate success
3211c6aec20Schristos  */
3221c6aec20Schristos bool
get_fingerprint(const X509 * cert,char ** returnstring,const char * alg_name)3231c6aec20Schristos get_fingerprint(const X509 *cert, char **returnstring, const char *alg_name)
3241c6aec20Schristos {
3251c6aec20Schristos #define MAX_ALG_NAME_LENGTH 8
3261c6aec20Schristos 	unsigned char md[EVP_MAX_MD_SIZE];
3271c6aec20Schristos 	char fp_val[4];
3281c6aec20Schristos 	size_t memsize, i;
3291c6aec20Schristos 	unsigned len;
3301c6aec20Schristos 	const EVP_MD *digest;
3311c6aec20Schristos 	const char *openssl_algname;
3321c6aec20Schristos 	/* RFC nnnn uses hash function names from
3331c6aec20Schristos 	 * http://www.iana.org/assignments/hash-function-text-names/
3341c6aec20Schristos 	 * in certificate fingerprints.
3351c6aec20Schristos 	 * We have to map them to the hash function names used by OpenSSL.
3361c6aec20Schristos 	 * Actually we use the union of both namespaces to be RFC compliant
3371c6aec20Schristos 	 * and to let the user use "openssl -fingerprint ..."
3381c6aec20Schristos 	 *
3391c6aec20Schristos 	 * Intended behaviour is to prefer the IANA names,
3401c6aec20Schristos 	 * but allow the user to use OpenSSL names as well
341a5c1e399Sandvar 	 * (e.g. for "RIPEMD160" which has no IANA name)
3421c6aec20Schristos 	 */
3431c6aec20Schristos 	static const struct hash_alg_namemap {
3441c6aec20Schristos 		const char *iana;
3451c6aec20Schristos 		const char *openssl;
3461c6aec20Schristos 	} hash_alg_namemap[] = {
3471c6aec20Schristos 		{"md2",	    "MD2"   },
3481c6aec20Schristos 		{"md5",	    "MD5"   },
3491c6aec20Schristos 		{"sha-1",   "SHA1"  },
3501c6aec20Schristos 		{"sha-224", "SHA224"},
3511c6aec20Schristos 		{"sha-256", "SHA256"},
3521c6aec20Schristos 		{"sha-384", "SHA384"},
3531c6aec20Schristos 		{"sha-512", "SHA512"}
3541c6aec20Schristos 	};
3551c6aec20Schristos 
3561c6aec20Schristos 	DPRINTF(D_TLS, "get_fingerprint(cert@%p, return@%p, alg \"%s\")\n",
3571c6aec20Schristos 	    cert, returnstring, alg_name);
3581c6aec20Schristos 	*returnstring = NULL;
3591c6aec20Schristos 
3601c6aec20Schristos 	if (!alg_name)
3611c6aec20Schristos 		alg_name = DEFAULT_FINGERPRINT_ALG;
3621c6aec20Schristos 	openssl_algname = alg_name;
3631c6aec20Schristos 	for (i = 0; i < A_CNT(hash_alg_namemap); i++)
3641c6aec20Schristos 		if (!strcasecmp(alg_name, hash_alg_namemap[i].iana))
3651c6aec20Schristos 			openssl_algname = hash_alg_namemap[i].openssl;
3661c6aec20Schristos 
3671c6aec20Schristos 	if (!(digest = (const EVP_MD *) EVP_get_digestbyname(
3681c6aec20Schristos 	    __UNCONST(openssl_algname)))) {
3691c6aec20Schristos 		DPRINTF(D_TLS, "unknown digest algorithm %s\n",
3701c6aec20Schristos 		    openssl_algname);
3711c6aec20Schristos 		return false;
3721c6aec20Schristos 	}
3731c6aec20Schristos 	if (!X509_digest(cert, digest, md, &len)) {
3741c6aec20Schristos 		DPRINTF(D_TLS, "cannot get %s digest\n", openssl_algname);
3751c6aec20Schristos 		return false;
3761c6aec20Schristos 	}
3771c6aec20Schristos 
3781c6aec20Schristos 	/* 'normalise' and translate back to IANA name */
3791c6aec20Schristos 	alg_name = openssl_algname = OBJ_nid2sn(EVP_MD_type(digest));
3801c6aec20Schristos 	for (i = 0; i < A_CNT(hash_alg_namemap); i++)
3811c6aec20Schristos 		if (!strcasecmp(openssl_algname, hash_alg_namemap[i].openssl))
3821c6aec20Schristos 			alg_name = hash_alg_namemap[i].iana;
3831c6aec20Schristos 
3841c6aec20Schristos 	/* needed memory: 3 string bytes for every binary byte with delimiter
3851c6aec20Schristos 	 *		  + max_iana_strlen with delimiter  */
3861c6aec20Schristos 	memsize = (len * 3) + strlen(alg_name) + 1;
3871c6aec20Schristos 	MALLOC(*returnstring, memsize);
3881c6aec20Schristos 	(void)strlcpy(*returnstring, alg_name, memsize);
3891c6aec20Schristos 	(void)strlcat(*returnstring, ":", memsize);
3901c6aec20Schristos 	/* append the fingeprint data */
3911c6aec20Schristos 	for (i = 0; i < len; i++) {
3921c6aec20Schristos 		(void)snprintf(fp_val, sizeof(fp_val),
3931c6aec20Schristos 			"%02X:", (unsigned) md[i]);
3941c6aec20Schristos 		(void)strlcat(*returnstring, fp_val, memsize);
3951c6aec20Schristos 	}
3961c6aec20Schristos 	return true;
3971c6aec20Schristos }
3981c6aec20Schristos 
3991c6aec20Schristos /*
4001c6aec20Schristos  * gets first CN from cert in returnstring (has to be freed by caller)
4011c6aec20Schristos  * on failure it returns false and *returnstring is NULL
4021c6aec20Schristos  */
4031c6aec20Schristos bool
get_commonname(X509 * cert,char ** returnstring)4041c6aec20Schristos get_commonname(X509 *cert, char **returnstring)
4051c6aec20Schristos {
4061c6aec20Schristos 	X509_NAME *x509name;
4071c6aec20Schristos 	X509_NAME_ENTRY *entry;
4081c6aec20Schristos 	unsigned char *ubuf;
4091c6aec20Schristos 	int len, i;
4101c6aec20Schristos 
4111c6aec20Schristos 	x509name = X509_get_subject_name(cert);
4121c6aec20Schristos 	i = X509_NAME_get_index_by_NID(x509name, NID_commonName, -1);
4131c6aec20Schristos 	if (i != -1) {
4141c6aec20Schristos 		entry = X509_NAME_get_entry(x509name, i);
4151c6aec20Schristos 		len = ASN1_STRING_to_UTF8(&ubuf,
4161c6aec20Schristos 		    X509_NAME_ENTRY_get_data(entry));
4171c6aec20Schristos 		if (len > 0) {
4181c6aec20Schristos 			MALLOC(*returnstring, (size_t)len+1);
4191c6aec20Schristos 			strlcpy(*returnstring, (const char*)ubuf, len+1);
4201c6aec20Schristos 			OPENSSL_free(ubuf);
4211c6aec20Schristos 			return true;
4221c6aec20Schristos 		}
4231c6aec20Schristos 		OPENSSL_free(ubuf);
4241c6aec20Schristos 	}
4251c6aec20Schristos 	*returnstring = NULL;
4261c6aec20Schristos 	return false;
4271c6aec20Schristos }
4281c6aec20Schristos /*
4291c6aec20Schristos  * test if cert matches as configured hostname or IP
4301c6aec20Schristos  * checks a 'really used' hostname and optionally a second expected subject
4311c6aec20Schristos  * against iPAddresses, dnsNames and commonNames
4321c6aec20Schristos  *
4331c6aec20Schristos  * TODO: wildcard matching for dnsNames is not implemented.
4341c6aec20Schristos  *	 in transport-tls that is a MAY, and I do not trust them anyway.
4351c6aec20Schristos  *	 but there might be demand for, so it's a todo item.
4361c6aec20Schristos  */
4371c6aec20Schristos bool
match_hostnames(X509 * cert,const char * hostname,const char * subject)4381c6aec20Schristos match_hostnames(X509 *cert, const char *hostname, const char *subject)
4391c6aec20Schristos {
4401c6aec20Schristos 	int i, len, num;
4411c6aec20Schristos 	unsigned char *ubuf;
4421c6aec20Schristos 	GENERAL_NAMES *gennames;
4431c6aec20Schristos 	GENERAL_NAME *gn;
4441c6aec20Schristos 	X509_NAME *x509name;
4451c6aec20Schristos 	X509_NAME_ENTRY *entry;
4461c6aec20Schristos 	ASN1_OCTET_STRING *asn1_ip, *asn1_cn_ip;
4471c6aec20Schristos 	int crit, idx;
4481c6aec20Schristos 
4491c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "match_hostnames(%p, \"%s\", \"%s\")\n",
4501c6aec20Schristos 	    cert, hostname, subject);
4511c6aec20Schristos 
4521c6aec20Schristos 	/* see if hostname is an IP */
4531c6aec20Schristos 	if ((subject  && (asn1_ip = a2i_IPADDRESS(subject )))
4541c6aec20Schristos 	 || (hostname && (asn1_ip = a2i_IPADDRESS(hostname))))
4551c6aec20Schristos 		/* nothing */;
4561c6aec20Schristos 	else
4571c6aec20Schristos 		asn1_ip = NULL;
4581c6aec20Schristos 
4591c6aec20Schristos 	if (!(gennames = X509_get_ext_d2i(cert, NID_subject_alt_name,
4601c6aec20Schristos 	    &crit, &idx))) {
4611c6aec20Schristos 		DPRINTF(D_TLS, "X509_get_ext_d2i() returned (%p,%d,%d) "
4621c6aec20Schristos 		    "--> no subjectAltName\n", gennames, crit, idx);
4631c6aec20Schristos 	} else {
4641c6aec20Schristos 		num = sk_GENERAL_NAME_num(gennames);
4651c6aec20Schristos 		if (asn1_ip) {
4661c6aec20Schristos 			/* first loop: check IPs */
4671c6aec20Schristos 			for (i = 0; i < num; ++i) {
4681c6aec20Schristos 				gn = sk_GENERAL_NAME_value(gennames, i);
4691c6aec20Schristos 				if (gn->type == GEN_IPADD
4701c6aec20Schristos 				    && !ASN1_OCTET_STRING_cmp(asn1_ip,
4711c6aec20Schristos 					gn->d.iPAddress))
4721c6aec20Schristos 					return true;
4731c6aec20Schristos 			}
4741c6aec20Schristos 		}
4751c6aec20Schristos 		/* second loop: check DNS names */
4761c6aec20Schristos 		for (i = 0; i < num; ++i) {
4771c6aec20Schristos 			gn = sk_GENERAL_NAME_value(gennames, i);
4781c6aec20Schristos 			if (gn->type == GEN_DNS) {
4794d91e676Schristos 				const char *str = (const char *)
4804d91e676Schristos 				    ASN1_STRING_get0_data(gn->d.ia5);
4811c6aec20Schristos 				len = ASN1_STRING_length(gn->d.ia5);
4824d91e676Schristos 				if (!strncasecmp(subject, str, len)
4834d91e676Schristos 				    || !strncasecmp(hostname, str, len))
4841c6aec20Schristos 					return true;
4851c6aec20Schristos 			}
4861c6aec20Schristos 		}
4871c6aec20Schristos 	}
4881c6aec20Schristos 
4891c6aec20Schristos 	/* check commonName; not sure if more than one CNs possible, but we
4901c6aec20Schristos 	 * will look at all of them */
4911c6aec20Schristos 	x509name = X509_get_subject_name(cert);
4921c6aec20Schristos 	i = X509_NAME_get_index_by_NID(x509name, NID_commonName, -1);
4931c6aec20Schristos 	while (i != -1) {
4941c6aec20Schristos 		entry = X509_NAME_get_entry(x509name, i);
4951c6aec20Schristos 		len = ASN1_STRING_to_UTF8(&ubuf,
4961c6aec20Schristos 		    X509_NAME_ENTRY_get_data(entry));
4971c6aec20Schristos 		if (len > 0) {
4981c6aec20Schristos 			DPRINTF(D_TLS, "found CN: %.*s\n", len, ubuf);
4991c6aec20Schristos 			/* hostname */
5001c6aec20Schristos 			if ((subject && !strncasecmp(subject,
5011c6aec20Schristos 			    (const char*)ubuf, len))
5021c6aec20Schristos 			    || (hostname && !strncasecmp(hostname,
5031c6aec20Schristos 			    (const char*)ubuf, len))) {
5041c6aec20Schristos 				OPENSSL_free(ubuf);
5051c6aec20Schristos 				return true;
5061c6aec20Schristos 			}
5071c6aec20Schristos 			OPENSSL_free(ubuf);
5081c6aec20Schristos 			/* IP -- convert to ASN1_OCTET_STRING and compare then
5091c6aec20Schristos 			 * so that "10.1.2.3" and "10.01.02.03" are equal */
5101c6aec20Schristos 			if ((asn1_ip)
5111c6aec20Schristos 			    && subject
5121c6aec20Schristos 			    && (asn1_cn_ip = a2i_IPADDRESS(subject))
5131c6aec20Schristos 			    && !ASN1_OCTET_STRING_cmp(asn1_ip, asn1_cn_ip)) {
5141c6aec20Schristos 				return true;
5151c6aec20Schristos 			}
5161c6aec20Schristos 		}
5171c6aec20Schristos 		i = X509_NAME_get_index_by_NID(x509name, NID_commonName, i);
5181c6aec20Schristos 	}
5191c6aec20Schristos 	return false;
5201c6aec20Schristos }
5211c6aec20Schristos 
5221c6aec20Schristos /*
5231c6aec20Schristos  * check if certificate matches given fingerprint
5241c6aec20Schristos  */
5251c6aec20Schristos bool
match_fingerprint(const X509 * cert,const char * fingerprint)5261c6aec20Schristos match_fingerprint(const X509 *cert, const char *fingerprint)
5271c6aec20Schristos {
5281c6aec20Schristos #define MAX_ALG_NAME_LENGTH 8
5291c6aec20Schristos 	char alg[MAX_ALG_NAME_LENGTH];
5301c6aec20Schristos 	char *certfingerprint;
5311c6aec20Schristos 	char *p;
5321c6aec20Schristos 	const char *q;
5331c6aec20Schristos 
5341c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "match_fingerprint(cert@%p, fp \"%s\")\n",
5351c6aec20Schristos 		cert, fingerprint);
5361c6aec20Schristos 	if (!fingerprint)
5371c6aec20Schristos 		return false;
5381c6aec20Schristos 
5391c6aec20Schristos 	/* get algorithm */
5401c6aec20Schristos 	p = alg;
5411c6aec20Schristos 	q = fingerprint;
5421c6aec20Schristos 	while (*q != ':' && *q != '\0' && p < alg + MAX_ALG_NAME_LENGTH)
5431c6aec20Schristos 		*p++ = *q++;
5441c6aec20Schristos 	*p = '\0';
5451c6aec20Schristos 
5461c6aec20Schristos 	if (!get_fingerprint(cert, &certfingerprint, alg)) {
5471c6aec20Schristos 		DPRINTF(D_TLS, "cannot get %s digest\n", alg);
5481c6aec20Schristos 		return false;
5491c6aec20Schristos 	}
5501c6aec20Schristos 	if (strncmp(certfingerprint, fingerprint, strlen(certfingerprint))) {
5511c6aec20Schristos 		DPRINTF(D_TLS, "fail: fingerprints do not match\n");
5521c6aec20Schristos 		free(certfingerprint);
5531c6aec20Schristos 		return false;
5541c6aec20Schristos 	}
5551c6aec20Schristos 	DPRINTF(D_TLS, "accepted: fingerprints match\n");
5561c6aec20Schristos 	free(certfingerprint);
5571c6aec20Schristos 	return true;
5581c6aec20Schristos }
5591c6aec20Schristos 
5601c6aec20Schristos /*
5611c6aec20Schristos  * check if certificate matches given certificate file
5621c6aec20Schristos  */
5631c6aec20Schristos bool
match_certfile(const X509 * cert1,const char * certfilename)5641c6aec20Schristos match_certfile(const X509 *cert1, const char *certfilename)
5651c6aec20Schristos {
5661c6aec20Schristos 	X509 *cert2;
5671c6aec20Schristos 	char *fp1, *fp2;
5681c6aec20Schristos 	bool rc = false;
5691c6aec20Schristos 	errno = 0;
5701c6aec20Schristos 
5711c6aec20Schristos 	if (read_certfile(&cert2, certfilename)
5721c6aec20Schristos 	    && get_fingerprint(cert1, &fp1, NULL)
5731c6aec20Schristos 	    && get_fingerprint(cert2, &fp2, NULL)) {
5741c6aec20Schristos 		if (!strcmp(fp1, fp2))
5751c6aec20Schristos 			rc = true;
5761c6aec20Schristos 		FREEPTR(fp1);
5771c6aec20Schristos 		FREEPTR(fp2);
5781c6aec20Schristos 	 }
5791c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "match_certfile(cert@%p, file \"%s\") "
5801c6aec20Schristos 	    "returns %d\n", cert1, certfilename, rc);
5811c6aec20Schristos 	return rc;
5821c6aec20Schristos }
5831c6aec20Schristos 
5841c6aec20Schristos /*
5851c6aec20Schristos  * reads X.509 certificate from file
5861c6aec20Schristos  * caller has to free it later with 'OPENSSL_free(cert);'
5871c6aec20Schristos  */
5881c6aec20Schristos bool
read_certfile(X509 ** cert,const char * certfilename)5891c6aec20Schristos read_certfile(X509 **cert, const char *certfilename)
5901c6aec20Schristos {
5911c6aec20Schristos 	FILE *certfile;
5921c6aec20Schristos 	errno = 0;
5931c6aec20Schristos 
5941c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "read_certfile(%p, \"%s\")\n",
5951c6aec20Schristos 		cert, certfilename);
5961c6aec20Schristos 	if (!cert || !certfilename)
5971c6aec20Schristos 		return false;
5981c6aec20Schristos 
5991c6aec20Schristos 	if (!(certfile = fopen(certfilename, "rb"))) {
6001c6aec20Schristos 		logerror("Unable to open certificate file: %s", certfilename);
6011c6aec20Schristos 		return false;
6021c6aec20Schristos 	}
6031c6aec20Schristos 
6041c6aec20Schristos 	/* either PEM or DER */
6051c6aec20Schristos 	if (!(*cert = PEM_read_X509(certfile, NULL, NULL, NULL))
6061c6aec20Schristos 	    && !(*cert = d2i_X509_fp(certfile, NULL))) {
6071c6aec20Schristos 		DPRINTF((D_TLS), "Unable to read certificate from %s\n",
6081c6aec20Schristos 			certfilename);
6091c6aec20Schristos 		(void)fclose(certfile);
6101c6aec20Schristos 		return false;
6111c6aec20Schristos 	}
6121c6aec20Schristos 	else {
6131c6aec20Schristos 		DPRINTF((D_TLS), "Read certificate from %s\n", certfilename);
6141c6aec20Schristos 		(void)fclose(certfile);
6151c6aec20Schristos 		return true;
6161c6aec20Schristos 	}
6171c6aec20Schristos }
6181c6aec20Schristos 
6191c6aec20Schristos /* used for incoming connections in check_peer_cert() */
6201c6aec20Schristos int
accept_cert(const char * reason,struct tls_conn_settings * conn_info,char * cur_fingerprint,char * cur_subjectline)6211c6aec20Schristos accept_cert(const char* reason, struct tls_conn_settings *conn_info,
6221c6aec20Schristos 	char *cur_fingerprint, char *cur_subjectline)
6231c6aec20Schristos {
6241c6aec20Schristos 	/* When using DSA keys the callback gets called twice.
6251c6aec20Schristos 	 * This flag avoids multiple log messages for the same connection.
6261c6aec20Schristos 	 */
6271c6aec20Schristos 	if (!conn_info->accepted)
6281c6aec20Schristos 		loginfo("Established connection and accepted %s certificate "
6291c6aec20Schristos 		    "from %s due to %s. Subject is \"%s\", fingerprint is"
6301c6aec20Schristos 		    " \"%s\"", conn_info->incoming ? "server" : "client",
6311c6aec20Schristos 		    conn_info->hostname, reason, cur_subjectline,
6321c6aec20Schristos 		    cur_fingerprint);
6331c6aec20Schristos 
6341c6aec20Schristos 	if (cur_fingerprint && !conn_info->fingerprint)
6351c6aec20Schristos 		conn_info->fingerprint = cur_fingerprint;
6361c6aec20Schristos 	else
6371c6aec20Schristos 		FREEPTR(cur_fingerprint);
6381c6aec20Schristos 
6391c6aec20Schristos 	if (cur_subjectline && !conn_info->subject)
6401c6aec20Schristos 		conn_info->subject = cur_subjectline;
6411c6aec20Schristos 	else
6421c6aec20Schristos 		FREEPTR(cur_subjectline);
6431c6aec20Schristos 
6441c6aec20Schristos 	conn_info->accepted = true;
6451c6aec20Schristos 	return 1;
6461c6aec20Schristos }
6471c6aec20Schristos int
deny_cert(struct tls_conn_settings * conn_info,char * cur_fingerprint,char * cur_subjectline)6481c6aec20Schristos deny_cert(struct tls_conn_settings *conn_info,
6491c6aec20Schristos 	char *cur_fingerprint, char *cur_subjectline)
6501c6aec20Schristos {
6511c6aec20Schristos 	if (!conn_info->accepted)
6521c6aec20Schristos 		loginfo("Deny %s certificate from %s. "
6531c6aec20Schristos 		    "Subject is \"%s\", fingerprint is \"%s\"",
6541c6aec20Schristos 		    conn_info->incoming ? "client" : "server",
6551c6aec20Schristos 		    conn_info->hostname,
6561c6aec20Schristos 		    cur_subjectline, cur_fingerprint);
6571c6aec20Schristos 	else
6581c6aec20Schristos 		logerror("Error with TLS %s certificate authentication, "
6591c6aec20Schristos 		    "already approved certificate became invalid. "
6601c6aec20Schristos 		    "Subject is \"%s\", fingerprint is \"%s\"",
6611c6aec20Schristos 		    conn_info->incoming ? "client" : "server",
6621c6aec20Schristos 		    cur_subjectline, cur_fingerprint);
6631c6aec20Schristos 	FREEPTR(cur_fingerprint);
6641c6aec20Schristos 	FREEPTR(cur_subjectline);
6651c6aec20Schristos 	return 0;
6661c6aec20Schristos }
6671c6aec20Schristos 
6681c6aec20Schristos /*
6691c6aec20Schristos  * Callback after OpenSSL has verified a peer certificate,
6701c6aec20Schristos  * gets called for every certificate in a chain (starting with root CA).
6711c6aec20Schristos  * preverify_ok indicates a valid trust path (necessary),
672631d5867Smbalmer  * then we check whether the hostname or configured subject matches the cert.
6731c6aec20Schristos  */
6741c6aec20Schristos int
check_peer_cert(int preverify_ok,X509_STORE_CTX * ctx)6751c6aec20Schristos check_peer_cert(int preverify_ok, X509_STORE_CTX *ctx)
6761c6aec20Schristos {
6771c6aec20Schristos 	char *cur_subjectline = NULL;
6781c6aec20Schristos 	char *cur_fingerprint = NULL;
6791c6aec20Schristos 	char cur_issuerline[256];
6801c6aec20Schristos 	SSL *ssl;
6811c6aec20Schristos 	X509 *cur_cert;
6821c6aec20Schristos 	int cur_err, cur_depth;
6831c6aec20Schristos 	struct tls_conn_settings *conn_info;
6841c6aec20Schristos 	struct peer_cred *cred, *tmp_cred;
6851c6aec20Schristos 
6861c6aec20Schristos 	/* read context info */
6871c6aec20Schristos 	cur_cert = X509_STORE_CTX_get_current_cert(ctx);
6881c6aec20Schristos 	cur_err = X509_STORE_CTX_get_error(ctx);
6891c6aec20Schristos 	cur_depth = X509_STORE_CTX_get_error_depth(ctx);
6901c6aec20Schristos 	ssl = X509_STORE_CTX_get_ex_data(ctx,
6911c6aec20Schristos 	    SSL_get_ex_data_X509_STORE_CTX_idx());
6921c6aec20Schristos 	conn_info = SSL_get_app_data(ssl);
6931c6aec20Schristos 
6941c6aec20Schristos 	/* some info */
6951c6aec20Schristos 	(void)get_commonname(cur_cert, &cur_subjectline);
6961c6aec20Schristos 	(void)get_fingerprint(cur_cert, &cur_fingerprint, NULL);
6971c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "check cert for connection with %s. "
6981c6aec20Schristos 	    "depth is %d, preverify is %d, subject is %s, fingerprint "
6991c6aec20Schristos 	    "is %s, conn_info@%p%s\n", conn_info->hostname, cur_depth,
7001c6aec20Schristos 	    preverify_ok, cur_subjectline, cur_fingerprint, conn_info,
7011c6aec20Schristos 	    (conn_info->accepted ? ", cb was already called" : ""));
7021c6aec20Schristos 
7031c6aec20Schristos 	if (Debug && !preverify_ok) {
7041c6aec20Schristos 		DPRINTF(D_TLS, "openssl verify error:"
7051c6aec20Schristos 		    "num=%d:%s:depth=%d:%s\t\n", cur_err,
7061c6aec20Schristos 		    X509_verify_cert_error_string(cur_err),
7071c6aec20Schristos 		    cur_depth, cur_subjectline);
7081c6aec20Schristos 		if (cur_err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) {
7094d91e676Schristos 			X509 *current_cert =
7104d91e676Schristos 			    X509_STORE_CTX_get_current_cert(ctx);
7111c6aec20Schristos 			X509_NAME_oneline(
7124d91e676Schristos 			    X509_get_issuer_name(current_cert),
7131c6aec20Schristos 			    cur_issuerline, sizeof(cur_issuerline));
7141c6aec20Schristos 			DPRINTF(D_TLS, "openssl verify error:missing "
7151c6aec20Schristos 			    "cert for issuer=%s\n", cur_issuerline);
7161c6aec20Schristos 		}
7171c6aec20Schristos 	}
7181c6aec20Schristos 
7191c6aec20Schristos 	/*
7201c6aec20Schristos 	 * quite a lot of variables here,
7211c6aec20Schristos 	 * the big if/elseif covers all possible combinations.
7221c6aec20Schristos 	 *
7231c6aec20Schristos 	 * here is a list, ordered like the conditions below:
7241c6aec20Schristos 	 * - conn_info->x509verify
7251c6aec20Schristos 	 *   X509VERIFY_NONE:	   do not verify certificates,
7261c6aec20Schristos 	 *			   only log its subject and fingerprint
7271c6aec20Schristos 	 *   X509VERIFY_IFPRESENT: if we got her, then a cert is present,
7281c6aec20Schristos 	 *			   so check it normally
7291c6aec20Schristos 	 *   X509VERIFY_ALWAYS:	   normal certificate check
7301c6aec20Schristos 	 * - cur_depth:
7311c6aec20Schristos 	 *   > 0:  peer provided CA cert. remember if its valid,
7321c6aec20Schristos 	 *	   but always accept, because most checks work on depth 0
7331c6aec20Schristos 	 *   == 0: the peer's own cert. check this for final decision
7341c6aec20Schristos 	 * - preverify_ok:
7351c6aec20Schristos 	 *   true:  valid certificate chain from a trust anchor to this cert
7361c6aec20Schristos 	 *   false: no valid and trusted certificate chain
7371c6aec20Schristos 	 * - conn_info->incoming:
7381c6aec20Schristos 	 *   true:  we are the server, means we authenticate against all
7391c6aec20Schristos 	 *	    allowed attributes in tls_opt
7401c6aec20Schristos 	 *   false: otherwise we are client and conn_info has all attributes
7411c6aec20Schristos 	 *	    to check
7421c6aec20Schristos 	 * - conn_info->fingerprint (only if !conn_info->incoming)
7431c6aec20Schristos 	 *   NULL:  no fingerprint configured, only check certificate chain
7441c6aec20Schristos 	 *   !NULL: a peer cert with this fingerprint is trusted
7451c6aec20Schristos 	 *
7461c6aec20Schristos 	 */
7471c6aec20Schristos 	/* shortcut */
7481c6aec20Schristos 	if (cur_depth != 0) {
7491c6aec20Schristos 		FREEPTR(cur_fingerprint);
7501c6aec20Schristos 		FREEPTR(cur_subjectline);
7511c6aec20Schristos 		return 1;
7521c6aec20Schristos 	}
7531c6aec20Schristos 
7541c6aec20Schristos 	if (conn_info->x509verify == X509VERIFY_NONE)
7551c6aec20Schristos 		return accept_cert("disabled verification", conn_info,
7561c6aec20Schristos 		    cur_fingerprint, cur_subjectline);
7571c6aec20Schristos 
7581c6aec20Schristos 	/* implicit: (cur_depth == 0)
7591c6aec20Schristos 	 *	  && (conn_info->x509verify != X509VERIFY_NONE) */
7601c6aec20Schristos 	if (conn_info->incoming) {
7611c6aec20Schristos 		if (preverify_ok)
7621c6aec20Schristos 			return accept_cert("valid certificate chain",
7631c6aec20Schristos 			    conn_info, cur_fingerprint, cur_subjectline);
7641c6aec20Schristos 
7651c6aec20Schristos 		/* else: now check allowed client fingerprints/certs */
7661c6aec20Schristos 		SLIST_FOREACH(cred, &tls_opt.fprint_head, entries) {
7671c6aec20Schristos 			if (match_fingerprint(cur_cert, cred->data)) {
7681c6aec20Schristos 				return accept_cert("matching fingerprint",
7691c6aec20Schristos 				    conn_info, cur_fingerprint,
7701c6aec20Schristos 				    cur_subjectline);
7711c6aec20Schristos 			}
7721c6aec20Schristos 		}
7731c6aec20Schristos 		SLIST_FOREACH_SAFE(cred, &tls_opt.cert_head,
7741c6aec20Schristos 			entries, tmp_cred) {
7751c6aec20Schristos 			if (match_certfile(cur_cert, cred->data))
7761c6aec20Schristos 				return accept_cert("matching certfile",
7771c6aec20Schristos 				    conn_info, cur_fingerprint,
7781c6aec20Schristos 				    cur_subjectline);
7791c6aec20Schristos 		}
7801c6aec20Schristos 		return deny_cert(conn_info, cur_fingerprint, cur_subjectline);
7811c6aec20Schristos 	}
7821c6aec20Schristos 
7831c6aec20Schristos 	/* implicit: (cur_depth == 0)
7841c6aec20Schristos 	 *	  && (conn_info->x509verify != X509VERIFY_NONE)
7851c6aec20Schristos 	 *	  && !conn_info->incoming */
7861c6aec20Schristos 	if (!conn_info->incoming && preverify_ok) {
7871c6aec20Schristos 		/* certificate chain OK. check subject/hostname */
7881c6aec20Schristos 		if (match_hostnames(cur_cert, conn_info->hostname,
7891c6aec20Schristos 		    conn_info->subject))
7901c6aec20Schristos 			return accept_cert("matching hostname/subject",
7911c6aec20Schristos 			    conn_info, cur_fingerprint, cur_subjectline);
7921c6aec20Schristos 		else
7931c6aec20Schristos 			return deny_cert(conn_info, cur_fingerprint,
7941c6aec20Schristos 			    cur_subjectline);
7951c6aec20Schristos 	} else if (!conn_info->incoming && !preverify_ok) {
7961c6aec20Schristos 		/* chain not OK. check fingerprint/subject/hostname */
7971c6aec20Schristos 		if (match_fingerprint(cur_cert, conn_info->fingerprint))
7981c6aec20Schristos 			return accept_cert("matching fingerprint", conn_info,
7991c6aec20Schristos 			    cur_fingerprint, cur_subjectline);
8001c6aec20Schristos 		else if (match_certfile(cur_cert, conn_info->certfile))
8011c6aec20Schristos 			return accept_cert("matching certfile", conn_info,
8021c6aec20Schristos 			    cur_fingerprint, cur_subjectline);
8031c6aec20Schristos 		else
8041c6aec20Schristos 			return deny_cert(conn_info, cur_fingerprint,
8051c6aec20Schristos 			    cur_subjectline);
8061c6aec20Schristos 	}
8071c6aec20Schristos 
8081c6aec20Schristos 	FREEPTR(cur_fingerprint);
8091c6aec20Schristos 	FREEPTR(cur_subjectline);
8101c6aec20Schristos 	return 0;
8111c6aec20Schristos }
8121c6aec20Schristos 
8131c6aec20Schristos /*
8141c6aec20Schristos  * Create TCP sockets for incoming TLS connections.
8151c6aec20Schristos  * To be used like socksetup(), hostname and port are optional,
8161c6aec20Schristos  * returns bound stream sockets.
8171c6aec20Schristos  */
8181c6aec20Schristos struct socketEvent *
socksetup_tls(const int af,const char * bindhostname,const char * port)8191c6aec20Schristos socksetup_tls(const int af, const char *bindhostname, const char *port)
8201c6aec20Schristos {
8211c6aec20Schristos 	struct addrinfo hints, *res, *r;
8221c6aec20Schristos 	int error, maxs;
8231c6aec20Schristos 	const int on = 1;
8241c6aec20Schristos 	struct socketEvent *s, *socks;
8251c6aec20Schristos 
8261c6aec20Schristos 	if(!tls_opt.server
8271c6aec20Schristos 	|| !tls_opt.global_TLS_CTX)
8281c6aec20Schristos 		return NULL;
8291c6aec20Schristos 
8301c6aec20Schristos 	memset(&hints, 0, sizeof(hints));
8311c6aec20Schristos 	hints.ai_flags = AI_PASSIVE;
8321c6aec20Schristos 	hints.ai_family = af;
8331c6aec20Schristos 	hints.ai_socktype = SOCK_STREAM;
8341c6aec20Schristos 
8351c6aec20Schristos 	error = getaddrinfo(bindhostname, (port ? port : "syslog-tls"),
8361c6aec20Schristos 	    &hints, &res);
8371c6aec20Schristos 	if (error) {
8389d62088aSjoerg 		logerror("%s", gai_strerror(error));
8391c6aec20Schristos 		errno = 0;
8401c6aec20Schristos 		die(0, 0, NULL);
8411c6aec20Schristos 	}
8421c6aec20Schristos 
8431c6aec20Schristos 	/* Count max number of sockets we may open */
8441c6aec20Schristos 	for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
8451c6aec20Schristos 		continue;
8461c6aec20Schristos 	socks = malloc((maxs+1) * sizeof(*socks));
8471c6aec20Schristos 	if (!socks) {
8481c6aec20Schristos 		logerror("Unable to allocate memory for sockets");
8491c6aec20Schristos 		die(0, 0, NULL);
8501c6aec20Schristos 	}
8511c6aec20Schristos 
8521c6aec20Schristos 	socks->fd = 0;	 /* num of sockets counter at start of array */
8531c6aec20Schristos 	s = socks + 1;
8541c6aec20Schristos 	for (r = res; r; r = r->ai_next) {
8551c6aec20Schristos 		if ((s->fd = socket(r->ai_family, r->ai_socktype,
8561c6aec20Schristos 			r->ai_protocol)) == -1) {
8571c6aec20Schristos 			logerror("socket() failed: %s", strerror(errno));
8581c6aec20Schristos 			continue;
8591c6aec20Schristos 		}
860c68a8e00Schristos 		s->af = r->ai_family;
8611c6aec20Schristos 		if (r->ai_family == AF_INET6
8621c6aec20Schristos 		 && setsockopt(s->fd, IPPROTO_IPV6, IPV6_V6ONLY,
8631c6aec20Schristos 			&on, sizeof(on)) == -1) {
8641c6aec20Schristos 			logerror("setsockopt(IPV6_V6ONLY) failed: %s",
8651c6aec20Schristos 			    strerror(errno));
8661c6aec20Schristos 			close(s->fd);
8671c6aec20Schristos 			continue;
8681c6aec20Schristos 		}
8691c6aec20Schristos 		if (setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR,
8701c6aec20Schristos 			&on, sizeof(on)) == -1) {
8711c6aec20Schristos 			DPRINTF(D_NET, "Unable to setsockopt(): %s\n",
8721c6aec20Schristos 			    strerror(errno));
8731c6aec20Schristos 		}
8741c6aec20Schristos 		if ((error = bind(s->fd, r->ai_addr, r->ai_addrlen)) == -1) {
8751c6aec20Schristos 			logerror("bind() failed: %s", strerror(errno));
8761c6aec20Schristos 			/* is there a better way to handle a EADDRINUSE? */
8771c6aec20Schristos 			close(s->fd);
8781c6aec20Schristos 			continue;
8791c6aec20Schristos 		}
8801c6aec20Schristos 		if (listen(s->fd, TLSBACKLOG) == -1) {
8811c6aec20Schristos 			logerror("listen() failed: %s", strerror(errno));
8821c6aec20Schristos 			close(s->fd);
8831c6aec20Schristos 			continue;
8841c6aec20Schristos 		}
8851c6aec20Schristos 		s->ev = allocev();
8861c6aec20Schristos 		event_set(s->ev, s->fd, EV_READ | EV_PERSIST,
8871c6aec20Schristos 		    dispatch_socket_accept, s->ev);
8881c6aec20Schristos 		EVENT_ADD(s->ev);
8891c6aec20Schristos 
8901c6aec20Schristos 		socks->fd = socks->fd + 1;  /* num counter */
8911c6aec20Schristos 		s++;
8921c6aec20Schristos 	}
8931c6aec20Schristos 
8941c6aec20Schristos 	if (socks->fd == 0) {
8951c6aec20Schristos 		free (socks);
8961c6aec20Schristos 		if(Debug)
8971c6aec20Schristos 			return NULL;
8981c6aec20Schristos 		else
8991c6aec20Schristos 			die(0, 0, NULL);
9001c6aec20Schristos 	}
9011c6aec20Schristos 	if (res)
9021c6aec20Schristos 		freeaddrinfo(res);
9031c6aec20Schristos 
9041c6aec20Schristos 	return socks;
9051c6aec20Schristos }
9061c6aec20Schristos 
9071c6aec20Schristos /*
9081c6aec20Schristos  * Dispatch routine for non-blocking SSL_connect()
9091c6aec20Schristos  * Has to be idempotent in case of TLS_RETRY (~ EAGAIN),
9101c6aec20Schristos  * so we can continue a slow handshake.
9111c6aec20Schristos  */
9121c6aec20Schristos /*ARGSUSED*/
9131c6aec20Schristos void
dispatch_SSL_connect(int fd,short event,void * arg)9141c6aec20Schristos dispatch_SSL_connect(int fd, short event, void *arg)
9151c6aec20Schristos {
9161c6aec20Schristos 	struct tls_conn_settings *conn_info = (struct tls_conn_settings *) arg;
9171c6aec20Schristos 	SSL *ssl = conn_info->sslptr;
9181c6aec20Schristos 	int rc, error;
9191c6aec20Schristos 	sigset_t newmask, omask;
9201c6aec20Schristos 	struct timeval tv;
9211c6aec20Schristos 
9221c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
9231c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "dispatch_SSL_connect(conn_info@%p, fd %d)\n",
9241c6aec20Schristos 	    conn_info, fd);
9251c6aec20Schristos 	assert(conn_info->state == ST_TCP_EST
9261c6aec20Schristos 	    || conn_info->state == ST_CONNECTING);
9271c6aec20Schristos 
9281c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_CONNECTING);
9291c6aec20Schristos 	rc = SSL_connect(ssl);
9301c6aec20Schristos 	if (0 >= rc) {
9311c6aec20Schristos 		error = tls_examine_error("SSL_connect()",
9321c6aec20Schristos 		    conn_info->sslptr, NULL, rc);
9331c6aec20Schristos 		switch (error) {
9341c6aec20Schristos 		case TLS_RETRY_READ:
9351c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_READ,
9361c6aec20Schristos 			    dispatch_SSL_connect, conn_info);
9371c6aec20Schristos 			EVENT_ADD(conn_info->retryevent);
9381c6aec20Schristos 			break;
9391c6aec20Schristos 		case TLS_RETRY_WRITE:
9401c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_WRITE,
9411c6aec20Schristos 			    dispatch_SSL_connect, conn_info);
9421c6aec20Schristos 			EVENT_ADD(conn_info->retryevent);
9431c6aec20Schristos 			break;
9441c6aec20Schristos 		default: /* should not happen,
9451c6aec20Schristos 			  * ... but does if the cert is not accepted */
9461c6aec20Schristos 			logerror("Cannot establish TLS connection "
9471c6aec20Schristos 			    "to \"%s\" -- TLS handshake aborted "
9481c6aec20Schristos 			    "before certificate authentication.",
9491c6aec20Schristos 			    conn_info->hostname);
9501c6aec20Schristos 			ST_CHANGE(conn_info->state, ST_NONE);
9511c6aec20Schristos 			conn_info->reconnect = 5 * TLS_RECONNECT_SEC;
9521c6aec20Schristos 			tv.tv_sec = conn_info->reconnect;
9531c6aec20Schristos 			tv.tv_usec = 0;
9541c6aec20Schristos 			schedule_event(&conn_info->event, &tv,
9551c6aec20Schristos 			    tls_reconnect, conn_info);
9561c6aec20Schristos 			break;
9571c6aec20Schristos 		}
9581c6aec20Schristos 		RESTORE_SIGNALS(omask);
9591c6aec20Schristos 		return;
9601c6aec20Schristos 	}
9611c6aec20Schristos 	/* else */
9621c6aec20Schristos 	conn_info->reconnect = TLS_RECONNECT_SEC;
9631c6aec20Schristos 	event_set(conn_info->event, fd, EV_READ, dispatch_tls_eof, conn_info);
9641c6aec20Schristos 	EVENT_ADD(conn_info->event);
9651c6aec20Schristos 
9661c6aec20Schristos 	DPRINTF(D_TLS, "TLS connection established.\n");
9671c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_TLS_EST);
9681c6aec20Schristos 
9691c6aec20Schristos 	send_queue(0, 0, get_f_by_conninfo(conn_info));
9701c6aec20Schristos 	RESTORE_SIGNALS(omask);
9711c6aec20Schristos }
9721c6aec20Schristos 
9731c6aec20Schristos /*
9741c6aec20Schristos  * establish TLS connection
9751c6aec20Schristos  */
9761c6aec20Schristos bool
tls_connect(struct tls_conn_settings * conn_info)9771c6aec20Schristos tls_connect(struct tls_conn_settings *conn_info)
9781c6aec20Schristos {
9791c6aec20Schristos 	struct addrinfo hints, *res, *res1;
9801c6aec20Schristos 	int    error, rc, sock;
9811c6aec20Schristos 	const int one = 1;
9821c6aec20Schristos 	char   buf[MAXLINE];
9831c6aec20Schristos 	SSL    *ssl = NULL;
9841c6aec20Schristos 
9851c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "tls_connect(conn_info@%p)\n", conn_info);
9861c6aec20Schristos 	assert(conn_info->state == ST_NONE);
9871c6aec20Schristos 
9881c6aec20Schristos 	if(!tls_opt.global_TLS_CTX)
9891c6aec20Schristos 		return false;
9901c6aec20Schristos 
9911c6aec20Schristos 	memset(&hints, 0, sizeof(hints));
9921c6aec20Schristos 	hints.ai_family = AF_UNSPEC;
9931c6aec20Schristos 	hints.ai_socktype = SOCK_STREAM;
9941c6aec20Schristos 	hints.ai_protocol = 0;
9951c6aec20Schristos 	hints.ai_flags = AI_CANONNAME;
9961c6aec20Schristos 	error = getaddrinfo(conn_info->hostname,
9971c6aec20Schristos 	    (conn_info->port ? conn_info->port : "syslog-tls"), &hints, &res);
9981c6aec20Schristos 	if (error) {
9999d62088aSjoerg 		logerror("%s", gai_strerror(error));
10001c6aec20Schristos 		return false;
10011c6aec20Schristos 	}
10021c6aec20Schristos 
10031c6aec20Schristos 	sock = -1;
10041c6aec20Schristos 	for (res1 = res; res1; res1 = res1->ai_next) {
10051c6aec20Schristos 		if ((sock = socket(res1->ai_family, res1->ai_socktype,
10061c6aec20Schristos 		    res1->ai_protocol)) == -1) {
10071c6aec20Schristos 			DPRINTF(D_NET, "Unable to open socket.\n");
10081c6aec20Schristos 			continue;
10091c6aec20Schristos 		}
10101c6aec20Schristos 		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
10111c6aec20Schristos 			&one, sizeof(one)) == -1) {
10121c6aec20Schristos 			DPRINTF(D_NET, "Unable to setsockopt(): %s\n",
10131c6aec20Schristos 			    strerror(errno));
10141c6aec20Schristos 		}
10151c6aec20Schristos 		if (connect(sock, res1->ai_addr, res1->ai_addrlen) == -1) {
10161c6aec20Schristos 			DPRINTF(D_NET, "Unable to connect() to %s: %s\n",
10171c6aec20Schristos 			    res1->ai_canonname, strerror(errno));
10181c6aec20Schristos 			close(sock);
10191c6aec20Schristos 			sock = -1;
10201c6aec20Schristos 			continue;
10211c6aec20Schristos 		}
10221c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_TCP_EST);
10231c6aec20Schristos 
10241c6aec20Schristos 		if (!(ssl = SSL_new(tls_opt.global_TLS_CTX))) {
10251c6aec20Schristos 			ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
10261c6aec20Schristos 			DPRINTF(D_TLS, "Unable to establish TLS: %s\n", buf);
10271c6aec20Schristos 			close(sock);
10281c6aec20Schristos 			sock = -1;
10291c6aec20Schristos 			ST_CHANGE(conn_info->state, ST_NONE);
10301c6aec20Schristos 			continue;
10311c6aec20Schristos 		}
10321c6aec20Schristos 		if (!SSL_set_fd(ssl, sock)) {
10331c6aec20Schristos 			ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
10341c6aec20Schristos 			DPRINTF(D_TLS, "Unable to connect TLS to socket: %s\n",
10351c6aec20Schristos 			    buf);
10361c6aec20Schristos 			FREE_SSL(ssl);
10371c6aec20Schristos 			close(sock);
10381c6aec20Schristos 			sock = -1;
10391c6aec20Schristos 			ST_CHANGE(conn_info->state, ST_NONE);
10401c6aec20Schristos 			continue;
10411c6aec20Schristos 		}
10421c6aec20Schristos 
10431c6aec20Schristos 		SSL_set_app_data(ssl, conn_info);
10441c6aec20Schristos 		SSL_set_connect_state(ssl);
10451c6aec20Schristos 		while ((rc = ERR_get_error()) != 0) {
10461c6aec20Schristos 			ERR_error_string_n(rc, buf, sizeof(buf));
10471c6aec20Schristos 			DPRINTF(D_TLS, "Found SSL error in queue: %s\n", buf);
10481c6aec20Schristos 		}
10491c6aec20Schristos 		errno = 0;  /* reset to be sure we get the right one later on */
10501c6aec20Schristos 
10511c6aec20Schristos 		if ((fcntl(sock, F_SETFL, O_NONBLOCK)) == -1) {
10521c6aec20Schristos 			DPRINTF(D_NET, "Unable to fcntl(sock, O_NONBLOCK): "
10531c6aec20Schristos 			    "%s\n", strerror(errno));
10541c6aec20Schristos 		}
10551c6aec20Schristos 
10561c6aec20Schristos 		/* now we have a TCP connection, so assume we can
10571c6aec20Schristos 		 * use that and do not have to try another res */
10581c6aec20Schristos 		conn_info->sslptr = ssl;
10591c6aec20Schristos 
10601c6aec20Schristos 		assert(conn_info->state == ST_TCP_EST);
10611c6aec20Schristos 		assert(conn_info->event);
10621c6aec20Schristos 		assert(conn_info->retryevent);
10631c6aec20Schristos 
10641c6aec20Schristos 		freeaddrinfo(res);
10651c6aec20Schristos 		dispatch_SSL_connect(sock, 0, conn_info);
10661c6aec20Schristos 		return true;
10671c6aec20Schristos 	}
10681c6aec20Schristos 	/* still no connection after for loop */
10691c6aec20Schristos 	DPRINTF((D_TLS|D_NET), "Unable to establish a TCP connection to %s\n",
10701c6aec20Schristos 	    conn_info->hostname);
10711c6aec20Schristos 	freeaddrinfo(res);
10721c6aec20Schristos 
10731c6aec20Schristos 	assert(conn_info->state == ST_NONE);
10741c6aec20Schristos 	if (sock != -1)
10751c6aec20Schristos 		close(sock);
10761c6aec20Schristos 	if (ssl) {
10771c6aec20Schristos 		SSL_shutdown(ssl);
10781c6aec20Schristos 		SSL_free(ssl);
10791c6aec20Schristos 	}
10801c6aec20Schristos 	return false;
10811c6aec20Schristos }
10821c6aec20Schristos 
10831c6aec20Schristos int
tls_examine_error(const char * functionname,const SSL * ssl,struct tls_conn_settings * tls_conn,const int rc)10841c6aec20Schristos tls_examine_error(const char *functionname, const SSL *ssl,
10851c6aec20Schristos 	struct tls_conn_settings *tls_conn, const int rc)
10861c6aec20Schristos {
10871c6aec20Schristos 	int ssl_error, err_error;
10881c6aec20Schristos 
10891c6aec20Schristos 	ssl_error = SSL_get_error(ssl, rc);
10901c6aec20Schristos 	DPRINTF(D_TLS, "%s returned rc %d and error %s: %s\n", functionname,
10911c6aec20Schristos 		rc, SSL_ERRCODE[ssl_error], ERR_error_string(ssl_error, NULL));
10921c6aec20Schristos 	switch (ssl_error) {
10931c6aec20Schristos 	case SSL_ERROR_WANT_READ:
10941c6aec20Schristos 		return TLS_RETRY_READ;
10951c6aec20Schristos 	case SSL_ERROR_WANT_WRITE:
10961c6aec20Schristos 		return TLS_RETRY_WRITE;
10971c6aec20Schristos 	case SSL_ERROR_SYSCALL:
10981c6aec20Schristos 		DPRINTF(D_TLS, "SSL_ERROR_SYSCALL: ");
10991c6aec20Schristos 		err_error = ERR_get_error();
11001c6aec20Schristos 		if ((rc == -1) && (err_error == 0)) {
11011c6aec20Schristos 			DPRINTF(D_TLS, "socket I/O error: %s\n",
11021c6aec20Schristos 			    strerror(errno));
11031c6aec20Schristos 		} else if ((rc == 0) && (err_error == 0)) {
11041c6aec20Schristos 			DPRINTF(D_TLS, "unexpected EOF from %s\n",
11051c6aec20Schristos 			    tls_conn ? tls_conn->hostname : NULL);
11061c6aec20Schristos 		} else {
11071c6aec20Schristos 			DPRINTF(D_TLS, "no further info\n");
11081c6aec20Schristos 		}
11091c6aec20Schristos 		return TLS_PERM_ERROR;
11101c6aec20Schristos 	case SSL_ERROR_ZERO_RETURN:
11111c6aec20Schristos 		logerror("TLS connection closed by %s",
11121c6aec20Schristos 		    tls_conn ? tls_conn->hostname : NULL);
11131c6aec20Schristos 		return TLS_PERM_ERROR;
11141c6aec20Schristos 	case SSL_ERROR_SSL:
11151c6aec20Schristos 		logerror("internal SSL error, error queue gives %s",
11161c6aec20Schristos 		    ERR_error_string(ERR_get_error(), NULL));
11171c6aec20Schristos 		return TLS_PERM_ERROR;
11181c6aec20Schristos 	default:
11191c6aec20Schristos 		break;
11201c6aec20Schristos 	}
11211c6aec20Schristos 	if (tls_conn)
11221c6aec20Schristos 		tls_conn->errorcount++;
11231c6aec20Schristos 	/* TODO: is this ever reached? */
11241c6aec20Schristos 	return TLS_TEMP_ERROR;
11251c6aec20Schristos }
11261c6aec20Schristos 
11271c6aec20Schristos 
11281c6aec20Schristos bool
parse_tls_destination(const char * p,struct filed * f,size_t linenum)11291c6aec20Schristos parse_tls_destination(const char *p, struct filed *f, size_t linenum)
11301c6aec20Schristos {
11311c6aec20Schristos 	const char *q;
11321c6aec20Schristos 
11331c6aec20Schristos 	if ((*p++ != '@') || *p++ != '[') {
11341c6aec20Schristos 		logerror("parse_tls_destination() on non-TLS action "
11351c6aec20Schristos 		    "in config line %zu", linenum);
11361c6aec20Schristos 		return false;
11371c6aec20Schristos 	}
11381c6aec20Schristos 
11391c6aec20Schristos 	if (!(q = strchr(p, ']'))) {
11401c6aec20Schristos 		logerror("Unterminated [ "
11411c6aec20Schristos 		    "in config line %zu", linenum);
11421c6aec20Schristos 		return false;
11431c6aec20Schristos 	}
11441c6aec20Schristos 
11451c6aec20Schristos 	if (!(f->f_un.f_tls.tls_conn =
11461c6aec20Schristos 		calloc(1, sizeof(*f->f_un.f_tls.tls_conn)))
11471c6aec20Schristos 	 || !(f->f_un.f_tls.tls_conn->event = allocev())
11481c6aec20Schristos 	 || !(f->f_un.f_tls.tls_conn->retryevent = allocev())) {
11495091f368Sspz 		if (f->f_un.f_tls.tls_conn)
11501c6aec20Schristos 			free(f->f_un.f_tls.tls_conn->event);
11511c6aec20Schristos 		free(f->f_un.f_tls.tls_conn);
11521c6aec20Schristos 		logerror("Couldn't allocate memory for TLS config");
11531c6aec20Schristos 		return false;
11541c6aec20Schristos 	}
11551c6aec20Schristos 	/* default values */
11561c6aec20Schristos 	f->f_un.f_tls.tls_conn->x509verify = X509VERIFY_ALWAYS;
11571c6aec20Schristos 	f->f_un.f_tls.tls_conn->reconnect = TLS_RECONNECT_SEC;
11581c6aec20Schristos 
11591c6aec20Schristos 	if (!(copy_string(&(f->f_un.f_tls.tls_conn->hostname), p, q))) {
11601c6aec20Schristos 		logerror("Unable to read TLS server name"
11611c6aec20Schristos 		    "in config line %zu", linenum);
11621c6aec20Schristos 		free_tls_conn(f->f_un.f_tls.tls_conn);
11631c6aec20Schristos 		return false;
11641c6aec20Schristos 	}
11651c6aec20Schristos 	p = ++q;
11661c6aec20Schristos 
11671c6aec20Schristos 	if (*p == ':') {
11681c6aec20Schristos 		p++; q++;
11691c6aec20Schristos 		while (isalnum((unsigned char)*q))
11701c6aec20Schristos 			q++;
11711c6aec20Schristos 		if (!(copy_string(&(f->f_un.f_tls.tls_conn->port), p, q))) {
11721c6aec20Schristos 			logerror("Unable to read TLS port or service name"
11731c6aec20Schristos 				" after ':' in config line %zu", linenum);
11741c6aec20Schristos 			free_tls_conn(f->f_un.f_tls.tls_conn);
11751c6aec20Schristos 			return false;
11761c6aec20Schristos 		}
11771c6aec20Schristos 		p = q;
11781c6aec20Schristos 	}
11791c6aec20Schristos 	/* allow whitespace for readability? */
11801c6aec20Schristos 	while (isblank((unsigned char)*p))
11811c6aec20Schristos 		p++;
11821c6aec20Schristos 	if (*p == '(') {
11831c6aec20Schristos 		p++;
11841c6aec20Schristos 		while (*p != ')') {
11851c6aec20Schristos 			if (copy_config_value_quoted("subject=\"",
11861c6aec20Schristos 			    &(f->f_un.f_tls.tls_conn->subject), &p)
11871c6aec20Schristos 			    || copy_config_value_quoted("fingerprint=\"",
11881c6aec20Schristos 			    &(f->f_un.f_tls.tls_conn->fingerprint), &p)
11891c6aec20Schristos 			    || copy_config_value_quoted("cert=\"",
11901c6aec20Schristos 			    &(f->f_un.f_tls.tls_conn->certfile), &p)) {
11911c6aec20Schristos 			/* nothing */
11921c6aec20Schristos 			} else if (!strcmp(p, "verify=")) {
11931c6aec20Schristos 				q = p += sizeof("verify=")-1;
11941c6aec20Schristos 				/* "" are optional */
11951c6aec20Schristos 				if (*p == '\"') { p++; q++; }
11961c6aec20Schristos 				while (isalpha((unsigned char)*q)) q++;
11971c6aec20Schristos 				f->f_un.f_tls.tls_conn->x509verify =
11981c6aec20Schristos 				    getVerifySetting(p);
11991c6aec20Schristos 				if (*q == '\"') q++;  /* "" are optional */
12001c6aec20Schristos 				p = q;
12011c6aec20Schristos 			} else {
12021c6aec20Schristos 				logerror("unknown keyword %s "
12031c6aec20Schristos 				    "in config line %zu", p, linenum);
12041c6aec20Schristos 			}
120550eb6aadStnozaki 			while (*p == ',' || isblank((unsigned char)*p))
12061c6aec20Schristos 				p++;
12071c6aec20Schristos 			if (*p == '\0') {
12081c6aec20Schristos 				logerror("unterminated ("
12091c6aec20Schristos 				    "in config line %zu", linenum);
12101c6aec20Schristos 			}
12111c6aec20Schristos 		}
12121c6aec20Schristos 	}
12131c6aec20Schristos 
12141c6aec20Schristos 	DPRINTF((D_TLS|D_PARSE),
12151c6aec20Schristos 	    "got TLS config: host %s, port %s, "
12161c6aec20Schristos 	    "subject: %s, certfile: %s, fingerprint: %s\n",
12171c6aec20Schristos 	    f->f_un.f_tls.tls_conn->hostname,
12181c6aec20Schristos 	    f->f_un.f_tls.tls_conn->port,
12191c6aec20Schristos 	    f->f_un.f_tls.tls_conn->subject,
12201c6aec20Schristos 	    f->f_un.f_tls.tls_conn->certfile,
12211c6aec20Schristos 	    f->f_un.f_tls.tls_conn->fingerprint);
12221c6aec20Schristos 	return true;
12231c6aec20Schristos }
12241c6aec20Schristos 
12251c6aec20Schristos /*
12261c6aec20Schristos  * Dispatch routine (triggered by timer) to reconnect to a lost TLS server
12271c6aec20Schristos  */
12281c6aec20Schristos /*ARGSUSED*/
12291c6aec20Schristos void
tls_reconnect(int fd,short event,void * arg)12301c6aec20Schristos tls_reconnect(int fd, short event, void *arg)
12311c6aec20Schristos {
12321c6aec20Schristos 	struct tls_conn_settings *conn_info = (struct tls_conn_settings *) arg;
12331c6aec20Schristos 
12341c6aec20Schristos 	DPRINTF((D_TLS|D_CALL|D_EVENT), "tls_reconnect(conn_info@%p, "
12351c6aec20Schristos 	    "server %s)\n", conn_info, conn_info->hostname);
12361c6aec20Schristos 	if (conn_info->sslptr) {
12371c6aec20Schristos 		conn_info->shutdown = true;
12381c6aec20Schristos 		free_tls_sslptr(conn_info);
12391c6aec20Schristos 	}
12401c6aec20Schristos 	assert(conn_info->state == ST_NONE);
12411c6aec20Schristos 
12421c6aec20Schristos 	if (!tls_connect(conn_info)) {
12431c6aec20Schristos 		if (conn_info->reconnect > TLS_RECONNECT_GIVEUP) {
12441c6aec20Schristos 			logerror("Unable to connect to TLS server %s, "
12451c6aec20Schristos 			    "giving up now", conn_info->hostname);
12461c6aec20Schristos 			message_queue_freeall(get_f_by_conninfo(conn_info));
12471c6aec20Schristos 			/* free the message queue; but do not free the
12481c6aec20Schristos 			 * tls_conn_settings nor change the f_type to F_UNUSED.
12491c6aec20Schristos 			 * that way one can still trigger a reconnect
12501c6aec20Schristos 			 * with a SIGUSR1
12511c6aec20Schristos 			 */
12521c6aec20Schristos 		} else {
12531c6aec20Schristos 			struct timeval tv;
12541c6aec20Schristos 			logerror("Unable to connect to TLS server %s, "
12551c6aec20Schristos 			    "try again in %d sec", conn_info->hostname,
12561c6aec20Schristos 			    conn_info->reconnect);
12571c6aec20Schristos 			tv.tv_sec = conn_info->reconnect;
12581c6aec20Schristos 			tv.tv_usec = 0;
12591c6aec20Schristos 			schedule_event(&conn_info->event, &tv,
12601c6aec20Schristos 			    tls_reconnect, conn_info);
12611c6aec20Schristos 			TLS_RECONNECT_BACKOFF(conn_info->reconnect);
12621c6aec20Schristos 		}
12631c6aec20Schristos 	} else {
12641c6aec20Schristos 		assert(conn_info->state == ST_TLS_EST
12651c6aec20Schristos 		    || conn_info->state == ST_CONNECTING
12661c6aec20Schristos 		    || conn_info->state == ST_NONE);
12671c6aec20Schristos 	}
12681c6aec20Schristos }
12691c6aec20Schristos /*
12701c6aec20Schristos  * Dispatch routine for accepting TLS connections.
12711c6aec20Schristos  * Has to be idempotent in case of TLS_RETRY (~ EAGAIN),
12721c6aec20Schristos  * so we can continue a slow handshake.
12731c6aec20Schristos  */
12741c6aec20Schristos /*ARGSUSED*/
12751c6aec20Schristos void
dispatch_tls_accept(int fd,short event,void * arg)12761c6aec20Schristos dispatch_tls_accept(int fd, short event, void *arg)
12771c6aec20Schristos {
12781c6aec20Schristos 	struct tls_conn_settings *conn_info = (struct tls_conn_settings *) arg;
12791c6aec20Schristos 	int rc, error;
12801c6aec20Schristos 	struct TLS_Incoming_Conn *tls_in;
12811c6aec20Schristos 	sigset_t newmask, omask;
12821c6aec20Schristos 
12831c6aec20Schristos 	DPRINTF((D_TLS|D_CALL),
12841c6aec20Schristos 		"dispatch_tls_accept(conn_info@%p, fd %d)\n", conn_info, fd);
12851c6aec20Schristos 	assert(conn_info->event);
12861c6aec20Schristos 	assert(conn_info->retryevent);
12871c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
12881c6aec20Schristos 
12891c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_ACCEPTING);
12901c6aec20Schristos 	rc = SSL_accept(conn_info->sslptr);
12911c6aec20Schristos 	if (0 >= rc) {
12921c6aec20Schristos 		error = tls_examine_error("SSL_accept()",
12931c6aec20Schristos 		    conn_info->sslptr, NULL, rc);
12941c6aec20Schristos 		switch (error) {
12951c6aec20Schristos 		case TLS_RETRY_READ:
12961c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_READ,
12971c6aec20Schristos 			    dispatch_tls_accept, conn_info);
12981c6aec20Schristos 			EVENT_ADD(conn_info->retryevent);
12991c6aec20Schristos 			break;
13001c6aec20Schristos 		case TLS_RETRY_WRITE:
13011c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_WRITE,
13021c6aec20Schristos 			    dispatch_tls_accept, conn_info);
13031c6aec20Schristos 			EVENT_ADD(conn_info->retryevent);
13041c6aec20Schristos 			break;
13051c6aec20Schristos 		default: /* should not happen */
13061c6aec20Schristos 			free_tls_conn(conn_info);
13071c6aec20Schristos 			break;
13081c6aec20Schristos 		}
13091c6aec20Schristos 		RESTORE_SIGNALS(omask);
13101c6aec20Schristos 		return;
13111c6aec20Schristos 	}
13121c6aec20Schristos 	/* else */
13131c6aec20Schristos 	CALLOC(tls_in, sizeof(*tls_in));
13141c6aec20Schristos 	CALLOC(tls_in->inbuf, (size_t)TLS_MIN_LINELENGTH);
13151c6aec20Schristos 
13161c6aec20Schristos 	tls_in->tls_conn = conn_info;
13171c6aec20Schristos 	tls_in->socket = SSL_get_fd(conn_info->sslptr);
13181c6aec20Schristos 	tls_in->inbuf[0] = '\0';
13191c6aec20Schristos 	tls_in->inbuflen = TLS_MIN_LINELENGTH;
13201c6aec20Schristos 	SLIST_INSERT_HEAD(&TLS_Incoming_Head, tls_in, entries);
13211c6aec20Schristos 
13221c6aec20Schristos 	event_set(conn_info->event, tls_in->socket, EV_READ | EV_PERSIST,
13231c6aec20Schristos 	    dispatch_tls_read, tls_in);
13241c6aec20Schristos 	EVENT_ADD(conn_info->event);
13251c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_TLS_EST);
13261c6aec20Schristos 
13271c6aec20Schristos 	loginfo("established TLS connection from %s with certificate "
13281c6aec20Schristos 	    "%s (%s)", conn_info->hostname, conn_info->subject,
13291c6aec20Schristos 	    conn_info->fingerprint);
13301c6aec20Schristos 	RESTORE_SIGNALS(omask);
13311c6aec20Schristos 	/*
13321c6aec20Schristos 	 * We could also listen to EOF kevents -- but I do not think
13331c6aec20Schristos 	 * that would be useful, because we still had to read() the buffer
13341c6aec20Schristos 	 * before closing the socket.
13351c6aec20Schristos 	 */
13361c6aec20Schristos }
13371c6aec20Schristos 
13381c6aec20Schristos /*
13391c6aec20Schristos  * Dispatch routine for accepting TCP connections and preparing
13401c6aec20Schristos  * the tls_conn_settings object for a following SSL_accept().
13411c6aec20Schristos  */
13421c6aec20Schristos /*ARGSUSED*/
13431c6aec20Schristos void
dispatch_socket_accept(int fd,short event,void * ev)13441c6aec20Schristos dispatch_socket_accept(int fd, short event, void *ev)
13451c6aec20Schristos {
13461c6aec20Schristos #ifdef LIBWRAP
13471c6aec20Schristos 	struct request_info req;
13481c6aec20Schristos #endif
13491c6aec20Schristos 	struct sockaddr_storage frominet;
13501c6aec20Schristos 	socklen_t addrlen;
13511c6aec20Schristos 	int newsock, rc;
13521c6aec20Schristos 	sigset_t newmask, omask;
13531c6aec20Schristos 	SSL *ssl;
13541c6aec20Schristos 	struct tls_conn_settings *conn_info;
13551c6aec20Schristos 	char hbuf[NI_MAXHOST];
13561c6aec20Schristos 	char *peername;
13571c6aec20Schristos 
13581c6aec20Schristos 	DPRINTF((D_TLS|D_NET), "incoming TCP connection\n");
13591c6aec20Schristos 	if (!tls_opt.global_TLS_CTX) {
13601c6aec20Schristos 		logerror("global_TLS_CTX not initialized!");
13611c6aec20Schristos 		return;
13621c6aec20Schristos 	}
13631c6aec20Schristos 
13641c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
13651c6aec20Schristos 	addrlen = sizeof(frominet);
13661c6aec20Schristos 	if ((newsock = accept(fd, (struct sockaddr *)&frominet,
13671c6aec20Schristos 	    &addrlen)) == -1) {
13681c6aec20Schristos 		logerror("Error in accept(): %s", strerror(errno));
13691c6aec20Schristos 		RESTORE_SIGNALS(omask);
13701c6aec20Schristos 		return;
13711c6aec20Schristos 	}
13721c6aec20Schristos 	/* TODO: do we want an IP or a hostname? maybe even both? */
13731c6aec20Schristos 	if ((rc = getnameinfo((struct sockaddr *)&frominet, addrlen,
13741c6aec20Schristos 	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
13751c6aec20Schristos 		DPRINTF(D_NET, "could not get peername: %s", gai_strerror(rc));
13761c6aec20Schristos 		peername = NULL;
13771c6aec20Schristos 	}
13781c6aec20Schristos 	else {
137970f70a63Sjoerg 		size_t len = strlen(hbuf) + 1;
138070f70a63Sjoerg 		MALLOC(peername, len);
138170f70a63Sjoerg 		(void)memcpy(peername, hbuf, len);
13821c6aec20Schristos 	}
13831c6aec20Schristos 
13841c6aec20Schristos #ifdef LIBWRAP
13851c6aec20Schristos 	request_init(&req, RQ_DAEMON, appname, RQ_FILE, newsock, NULL);
13861c6aec20Schristos 	fromhost(&req);
13871c6aec20Schristos 	if (!hosts_access(&req)) {
13881c6aec20Schristos 		logerror("access from %s denied by hosts_access", peername);
13891c6aec20Schristos 		shutdown(newsock, SHUT_RDWR);
13901c6aec20Schristos 		close(newsock);
13911c6aec20Schristos 		RESTORE_SIGNALS(omask);
13921c6aec20Schristos 		return;
13931c6aec20Schristos 	}
13941c6aec20Schristos #endif
13951c6aec20Schristos 
13961c6aec20Schristos 	if ((fcntl(newsock, F_SETFL, O_NONBLOCK)) == -1) {
13971c6aec20Schristos 		DPRINTF(D_NET, "Unable to fcntl(sock, O_NONBLOCK): %s\n",
13981c6aec20Schristos 		    strerror(errno));
13991c6aec20Schristos 	}
14001c6aec20Schristos 
14011c6aec20Schristos 	if (!(ssl = SSL_new(tls_opt.global_TLS_CTX))) {
14021c6aec20Schristos 		DPRINTF(D_TLS, "Unable to establish TLS: %s\n",
14031c6aec20Schristos 		    ERR_error_string(ERR_get_error(), NULL));
14041c6aec20Schristos 		close(newsock);
14051c6aec20Schristos 		RESTORE_SIGNALS(omask);
14061c6aec20Schristos 		return;
14071c6aec20Schristos 	}
14081c6aec20Schristos 	if (!SSL_set_fd(ssl, newsock)) {
14091c6aec20Schristos 		DPRINTF(D_TLS, "Unable to connect TLS to socket %d: %s\n",
14101c6aec20Schristos 			newsock, ERR_error_string(ERR_get_error(), NULL));
14111c6aec20Schristos 		SSL_free(ssl);
14121c6aec20Schristos 		close(newsock);
14131c6aec20Schristos 		RESTORE_SIGNALS(omask);
14141c6aec20Schristos 		return;
14151c6aec20Schristos 	}
14161c6aec20Schristos 
14171c6aec20Schristos 	if (!(conn_info = calloc(1, sizeof(*conn_info)))
14181c6aec20Schristos 	    || !(conn_info->event = allocev())
14191c6aec20Schristos 	    || !(conn_info->retryevent = allocev())) {
14205091f368Sspz 		if (conn_info)
14211c6aec20Schristos 			free(conn_info->event);
14221c6aec20Schristos 		free(conn_info);
14231c6aec20Schristos 		SSL_free(ssl);
14241c6aec20Schristos 		close(newsock);
14251c6aec20Schristos 		logerror("Unable to allocate memory to accept incoming "
14261c6aec20Schristos 		    "TLS connection from %s", peername);
14271c6aec20Schristos 		RESTORE_SIGNALS(omask);
14281c6aec20Schristos 		return;
14291c6aec20Schristos 	}
14301c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_NONE);
14311c6aec20Schristos 	/* store connection details inside ssl object, used to verify
14321c6aec20Schristos 	 * cert and immediately match against hostname */
14331c6aec20Schristos 	conn_info->hostname = peername;
14341c6aec20Schristos 	conn_info->sslptr = ssl;
14351c6aec20Schristos 	conn_info->x509verify = getVerifySetting(tls_opt.x509verify);
14361c6aec20Schristos 	conn_info->incoming = true;
14371c6aec20Schristos 	SSL_set_app_data(ssl, conn_info);
14381c6aec20Schristos 	SSL_set_accept_state(ssl);
14391c6aec20Schristos 
14401c6aec20Schristos 	assert(conn_info->event);
14411c6aec20Schristos 	assert(conn_info->retryevent);
14421c6aec20Schristos 
14431c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_TCP_EST);
14441c6aec20Schristos 	DPRINTF(D_TLS, "socket connection from %s accept()ed with fd %d, "
14451c6aec20Schristos 		"calling SSL_accept()...\n",  peername, newsock);
14461c6aec20Schristos 	dispatch_tls_accept(newsock, 0, conn_info);
14471c6aec20Schristos 	RESTORE_SIGNALS(omask);
14481c6aec20Schristos }
14491c6aec20Schristos 
14501c6aec20Schristos /*
14511c6aec20Schristos  * Dispatch routine to read from outgoing TCP/TLS sockets.
14521c6aec20Schristos  *
14531c6aec20Schristos  * I do not know if libevent can tell us the difference
14541c6aec20Schristos  * between available data and an EOF. But it does not matter
14553576a6daShannken  * because there should not be any incoming data beside metadata.
14561c6aec20Schristos  * So we close the connection either because the peer closed its
14571c6aec20Schristos  * side or because the peer broke the protocol by sending us stuff  ;-)
14581c6aec20Schristos  */
14591c6aec20Schristos void
dispatch_tls_eof(int fd,short event,void * arg)14601c6aec20Schristos dispatch_tls_eof(int fd, short event, void *arg)
14611c6aec20Schristos {
14621c6aec20Schristos 	struct tls_conn_settings *conn_info = (struct tls_conn_settings *) arg;
14631c6aec20Schristos 	sigset_t newmask, omask;
14641c6aec20Schristos 	struct timeval tv;
14653576a6daShannken 	int rc;
14663576a6daShannken 	char buf[1];
14671c6aec20Schristos 
14681c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
14691c6aec20Schristos 	DPRINTF((D_TLS|D_EVENT|D_CALL), "dispatch_eof_tls(%d, %d, %p)\n",
14701c6aec20Schristos 	    fd, event, arg);
14711c6aec20Schristos 	assert(conn_info->state == ST_TLS_EST);
14723576a6daShannken 
14733576a6daShannken 	/* First check for incoming metadata. */
14743576a6daShannken 	ST_CHANGE(conn_info->state, ST_READING);
14753576a6daShannken 	rc = SSL_read(conn_info->sslptr, buf, sizeof(buf));
14763576a6daShannken 	ST_CHANGE(conn_info->state, ST_TLS_EST);
14773576a6daShannken 	if (rc <= 0 && tls_examine_error("SSL_read()", conn_info->sslptr,
14783576a6daShannken 	    conn_info, rc) == TLS_RETRY_READ) {
14793576a6daShannken 		/* Connection is still alive, rearm and return. */
14803576a6daShannken 		EVENT_ADD(conn_info->event);
14813576a6daShannken 		RESTORE_SIGNALS(omask);
14823576a6daShannken 		return;
14833576a6daShannken 	}
14843576a6daShannken 
14851c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_EOF);
14861c6aec20Schristos 	DEL_EVENT(conn_info->event);
14871c6aec20Schristos 
14881c6aec20Schristos 	free_tls_sslptr(conn_info);
14891c6aec20Schristos 
14901c6aec20Schristos 	/* this overwrites the EV_READ event */
14911c6aec20Schristos 	tv.tv_sec = conn_info->reconnect;
14921c6aec20Schristos 	tv.tv_usec = 0;
14931c6aec20Schristos 	schedule_event(&conn_info->event, &tv, tls_reconnect, conn_info);
14941c6aec20Schristos 	TLS_RECONNECT_BACKOFF(conn_info->reconnect);
14951c6aec20Schristos 	RESTORE_SIGNALS(omask);
14961c6aec20Schristos }
14971c6aec20Schristos 
14981c6aec20Schristos /*
14991c6aec20Schristos  * Dispatch routine to read from TCP/TLS sockets.
15001c6aec20Schristos  * NB: This gets called when the TCP socket has data available, thus
15011c6aec20Schristos  *     we can call SSL_read() on it. But that does not mean the SSL buffer
15021c6aec20Schristos  *     holds a complete record and SSL_read() lets us read any data now.
15031c6aec20Schristos  */
15041c6aec20Schristos /*ARGSUSED*/
15051c6aec20Schristos void
dispatch_tls_read(int fd_lib,short event,void * arg)15061c6aec20Schristos dispatch_tls_read(int fd_lib, short event, void *arg)
15071c6aec20Schristos {
15081c6aec20Schristos 	struct TLS_Incoming_Conn *c = (struct TLS_Incoming_Conn *) arg;
15091c6aec20Schristos 	int fd = c->socket;
15101c6aec20Schristos 	int error;
151188283dd7Schristos 	int rc;
15121c6aec20Schristos 	sigset_t newmask, omask;
15131c6aec20Schristos 	bool retrying;
15141c6aec20Schristos 
15151c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
15161c6aec20Schristos 	DPRINTF((D_TLS|D_EVENT|D_CALL), "active TLS socket %d\n", fd);
15171c6aec20Schristos 	DPRINTF(D_TLS, "calling SSL_read(%p, %p, %zu)\n", c->tls_conn->sslptr,
15181c6aec20Schristos 		&(c->inbuf[c->read_pos]), c->inbuflen - c->read_pos);
15191c6aec20Schristos 	retrying = (c->tls_conn->state == ST_READING);
15201c6aec20Schristos 	ST_CHANGE(c->tls_conn->state, ST_READING);
15211c6aec20Schristos 	rc = SSL_read(c->tls_conn->sslptr, &(c->inbuf[c->read_pos]),
15221c6aec20Schristos 		c->inbuflen - c->read_pos);
15231c6aec20Schristos 	if (rc <= 0) {
15241c6aec20Schristos 		error = tls_examine_error("SSL_read()", c->tls_conn->sslptr,
15251c6aec20Schristos 		    c->tls_conn, rc);
15261c6aec20Schristos 		switch (error) {
15271c6aec20Schristos 		case TLS_RETRY_READ:
15281c6aec20Schristos 			/* normal event loop will call us again */
15291c6aec20Schristos 			break;
15301c6aec20Schristos 		case TLS_RETRY_WRITE:
15311c6aec20Schristos 			if (!retrying)
15321c6aec20Schristos 				event_del(c->tls_conn->event);
15331c6aec20Schristos 			event_set(c->tls_conn->retryevent, fd,
15341c6aec20Schristos 				EV_WRITE, dispatch_tls_read, c);
15351c6aec20Schristos 			EVENT_ADD(c->tls_conn->retryevent);
15361c6aec20Schristos 			RESTORE_SIGNALS(omask);
15371c6aec20Schristos 			return;
15381c6aec20Schristos 		case TLS_TEMP_ERROR:
15391c6aec20Schristos 			if (c->tls_conn->errorcount < TLS_MAXERRORCOUNT)
15401c6aec20Schristos 				break;
15411c6aec20Schristos 			/* FALLTHROUGH */
15421c6aec20Schristos 		case TLS_PERM_ERROR:
15431c6aec20Schristos 			/* there might be data in the inbuf, so only
15441c6aec20Schristos 			 * mark for closing after message retrieval */
15451c6aec20Schristos 			c->closenow = true;
15461c6aec20Schristos 			break;
15471c6aec20Schristos 		default:
15481c6aec20Schristos 			break;
15491c6aec20Schristos 		}
15501c6aec20Schristos 	} else {
15511c6aec20Schristos 		DPRINTF(D_TLS, "SSL_read() returned %d\n", rc);
15521c6aec20Schristos 		c->errorcount = 0;
15531c6aec20Schristos 		c->read_pos += rc;
15541c6aec20Schristos 	}
15551c6aec20Schristos 	if (retrying)
15561c6aec20Schristos 		EVENT_ADD(c->tls_conn->event);
15571c6aec20Schristos 	tls_split_messages(c);
15581c6aec20Schristos 	if (c->closenow) {
15591c6aec20Schristos 		free_tls_conn(c->tls_conn);
15601c6aec20Schristos 		FREEPTR(c->inbuf);
15611c6aec20Schristos 		SLIST_REMOVE(&TLS_Incoming_Head, c, TLS_Incoming_Conn, entries);
15621c6aec20Schristos 		free(c);
15631c6aec20Schristos 	} else
15641c6aec20Schristos 		ST_CHANGE(c->tls_conn->state, ST_TLS_EST);
15651c6aec20Schristos 	RESTORE_SIGNALS(omask);
15661c6aec20Schristos }
15671c6aec20Schristos 
15681c6aec20Schristos /* moved message splitting out of dispatching function.
15691c6aec20Schristos  * now we can call it recursively.
15701c6aec20Schristos  *
15711c6aec20Schristos  * TODO: the code for oversized messages still needs testing,
15721c6aec20Schristos  * especially for the skipping case.
15731c6aec20Schristos  */
15741c6aec20Schristos void
tls_split_messages(struct TLS_Incoming_Conn * c)15751c6aec20Schristos tls_split_messages(struct TLS_Incoming_Conn *c)
15761c6aec20Schristos {
15771c6aec20Schristos /* define only to make it better readable */
15781c6aec20Schristos #define MSG_END_OFFSET (c->cur_msg_start + c->cur_msg_len)
15791c6aec20Schristos 	size_t offset = 0;
15801c6aec20Schristos 	size_t msglen = 0;
15811c6aec20Schristos 	char *newbuf;
15821c6aec20Schristos 	char buf_char;
15831c6aec20Schristos 
15841c6aec20Schristos 	DPRINTF((D_TLS|D_CALL|D_DATA), "tls_split_messages() -- "
15851c6aec20Schristos 		"incoming status is msg_start %zu, msg_len %zu, pos %zu\n",
15861c6aec20Schristos 		c->cur_msg_start, c->cur_msg_len, c->read_pos);
15871c6aec20Schristos 
15881c6aec20Schristos 	if (!c->read_pos)
15891c6aec20Schristos 		return;
15901c6aec20Schristos 
15911c6aec20Schristos 	if (c->dontsave && c->read_pos < MSG_END_OFFSET) {
15921c6aec20Schristos 		c->cur_msg_len -= c->read_pos;
15931c6aec20Schristos 		c->read_pos = 0;
15941c6aec20Schristos 	} else if (c->dontsave && c->read_pos == MSG_END_OFFSET) {
15951c6aec20Schristos 		c->cur_msg_start = c->cur_msg_len = c->read_pos = 0;
15961c6aec20Schristos 		c->dontsave = false;
15971c6aec20Schristos 	} else if (c->dontsave && c->read_pos > MSG_END_OFFSET) {
15981c6aec20Schristos 		/* move remaining input to start of buffer */
15991c6aec20Schristos 		DPRINTF(D_DATA, "move inbuf of length %zu by %zu chars\n",
16001c6aec20Schristos 		    c->read_pos - (MSG_END_OFFSET),
16011c6aec20Schristos 		    MSG_END_OFFSET);
16021c6aec20Schristos 		memmove(&c->inbuf[0],
16031c6aec20Schristos 		    &c->inbuf[MSG_END_OFFSET],
16041c6aec20Schristos 		    c->read_pos - (MSG_END_OFFSET));
16051c6aec20Schristos 		c->read_pos -= (MSG_END_OFFSET);
16061c6aec20Schristos 		c->cur_msg_start = c->cur_msg_len = 0;
16071c6aec20Schristos 		c->dontsave = false;
16081c6aec20Schristos 	}
16091c6aec20Schristos 	if (c->read_pos < MSG_END_OFFSET) {
16101c6aec20Schristos 		return;
16111c6aec20Schristos 	}
16121c6aec20Schristos 
16131c6aec20Schristos 	/* read length prefix, always at start of buffer */
1614e612b1d7Schristos 	while (offset < c->read_pos && isdigit((unsigned char)c->inbuf[offset]))
1615e612b1d7Schristos 	{
16161c6aec20Schristos 		msglen *= 10;
16171c6aec20Schristos 		msglen += c->inbuf[offset] - '0';
16181c6aec20Schristos 		offset++;
16191c6aec20Schristos 	}
16201c6aec20Schristos 	if (offset == c->read_pos) {
16211c6aec20Schristos 		/* next invocation will have more data */
16221c6aec20Schristos 		return;
16231c6aec20Schristos 	}
16241c6aec20Schristos 	if (c->inbuf[offset] == ' ') {
16251c6aec20Schristos 		c->cur_msg_len = msglen;
16261c6aec20Schristos 		c->cur_msg_start = offset + 1;
16271c6aec20Schristos 		if (MSG_END_OFFSET+1 > c->inbuflen) {  /* +1 for the '\0' */
16281c6aec20Schristos 			newbuf = realloc(c->inbuf, MSG_END_OFFSET+1);
16291c6aec20Schristos 			if (newbuf) {
16301c6aec20Schristos 				DPRINTF(D_DATA, "Reallocated inbuf\n");
16311c6aec20Schristos 				c->inbuflen = MSG_END_OFFSET+1;
16321c6aec20Schristos 				c->inbuf = newbuf;
16331c6aec20Schristos 			} else {
16341c6aec20Schristos 				logerror("Couldn't reallocate buffer, "
16351c6aec20Schristos 				    "will skip this message");
16361c6aec20Schristos 				c->dontsave = true;
16371c6aec20Schristos 				c->cur_msg_len -= c->read_pos;
16381c6aec20Schristos 				c->cur_msg_start = 0;
16391c6aec20Schristos 				c->read_pos = 0;
16401c6aec20Schristos 			}
16411c6aec20Schristos 		}
16421c6aec20Schristos 	} else {
16431c6aec20Schristos 		/* found non-digit in prefix */
16441c6aec20Schristos 		/* Question: would it be useful to skip this message and
16451c6aec20Schristos 		 * try to find next message by looking for its beginning?
16461c6aec20Schristos 		 * IMHO not.
16471c6aec20Schristos 		 */
16481c6aec20Schristos 		logerror("Unable to handle TLS length prefix. "
16491c6aec20Schristos 		    "Protocol error? Closing connection now.");
16501c6aec20Schristos 		/* only set flag -- caller has to close then */
16511c6aec20Schristos 		c->closenow = true;
16521c6aec20Schristos 		return;
16531c6aec20Schristos 	}
16541c6aec20Schristos 	/* read one syslog message */
16551c6aec20Schristos 	if (c->read_pos >= MSG_END_OFFSET) {
16561c6aec20Schristos 		/* process complete msg */
16571c6aec20Schristos 		assert(MSG_END_OFFSET+1 <= c->inbuflen);
16581c6aec20Schristos 		/* message in c->inbuf is not NULL-terminated,
16591c6aec20Schristos 		 * so this avoids a complete copy */
16601c6aec20Schristos 		buf_char = c->inbuf[MSG_END_OFFSET];
16611c6aec20Schristos 		c->inbuf[MSG_END_OFFSET] = '\0';
16621c6aec20Schristos 		printline(c->tls_conn->hostname, &c->inbuf[c->cur_msg_start],
16631c6aec20Schristos 		    RemoteAddDate ? ADDDATE : 0);
16641c6aec20Schristos 		c->inbuf[MSG_END_OFFSET] = buf_char;
16651c6aec20Schristos 
16661c6aec20Schristos 		if (MSG_END_OFFSET == c->read_pos) {
16671c6aec20Schristos 			/* no unprocessed data in buffer --> reset to empty */
16681c6aec20Schristos 			c->cur_msg_start = c->cur_msg_len = c->read_pos = 0;
16691c6aec20Schristos 		} else {
16701c6aec20Schristos 			/* move remaining input to start of buffer */
16711c6aec20Schristos 			DPRINTF(D_DATA, "move inbuf of length %zu by %zu "
16721c6aec20Schristos 			    "chars\n", c->read_pos - (MSG_END_OFFSET),
16731c6aec20Schristos 			    MSG_END_OFFSET);
16741c6aec20Schristos 			memmove(&c->inbuf[0], &c->inbuf[MSG_END_OFFSET],
16751c6aec20Schristos 			    c->read_pos - (MSG_END_OFFSET));
16761c6aec20Schristos 			c->read_pos -= (MSG_END_OFFSET);
16771c6aec20Schristos 			c->cur_msg_start = c->cur_msg_len = 0;
16781c6aec20Schristos 		}
16791c6aec20Schristos 	}
16801c6aec20Schristos 
16811c6aec20Schristos 	/* shrink inbuf if too large */
16821c6aec20Schristos 	if ((c->inbuflen > TLS_PERSIST_LINELENGTH)
16831c6aec20Schristos 	 && (c->read_pos < TLS_LARGE_LINELENGTH)) {
16841c6aec20Schristos 		newbuf = realloc(c->inbuf, TLS_LARGE_LINELENGTH);
16851c6aec20Schristos 		if (newbuf) {
16861c6aec20Schristos 			DPRINTF(D_DATA, "Shrink inbuf\n");
16871c6aec20Schristos 			c->inbuflen = TLS_LARGE_LINELENGTH;
16881c6aec20Schristos 			c->inbuf = newbuf;
16891c6aec20Schristos 		} else {
16901c6aec20Schristos 			logerror("Couldn't shrink inbuf");
16911c6aec20Schristos 			/* no change necessary */
16921c6aec20Schristos 		}
16931c6aec20Schristos 	}
16941c6aec20Schristos 	DPRINTF(D_DATA, "return with status: msg_start %zu, msg_len %zu, "
16951c6aec20Schristos 	    "pos %zu\n", c->cur_msg_start, c->cur_msg_len, c->read_pos);
16961c6aec20Schristos 
16971c6aec20Schristos 	/* try to read another message */
16981c6aec20Schristos 	if (c->read_pos > 10)
16991c6aec20Schristos 		tls_split_messages(c);
17001c6aec20Schristos 	return;
17011c6aec20Schristos }
17021c6aec20Schristos 
17031c6aec20Schristos /*
17041c6aec20Schristos  * wrapper for dispatch_tls_send()
17051c6aec20Schristos  *
17061c6aec20Schristos  * send one line with tls
17071c6aec20Schristos  * f has to be of typ TLS
17081c6aec20Schristos  *
17091c6aec20Schristos  * returns false if message cannot be sent right now,
17101c6aec20Schristos  *	caller is responsible to enqueue it
17111c6aec20Schristos  * returns true if message passed to dispatch_tls_send()
17121c6aec20Schristos  *	delivery is not garantueed, but likely
17131c6aec20Schristos  */
17141c6aec20Schristos #define DEBUG_LINELENGTH 40
17151c6aec20Schristos bool
tls_send(struct filed * f,char * line,size_t len,struct buf_queue * qentry)17161c6aec20Schristos tls_send(struct filed *f, char *line, size_t len, struct buf_queue *qentry)
17171c6aec20Schristos {
17181c6aec20Schristos 	struct tls_send_msg *smsg;
17191c6aec20Schristos 
17201c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "tls_send(f=%p, line=\"%.*s%s\", "
17211c6aec20Schristos 	    "len=%zu) to %sconnected dest.\n", f,
17221c6aec20Schristos 	    (int)(len > DEBUG_LINELENGTH ? DEBUG_LINELENGTH : len),
17231c6aec20Schristos 	    line, (len > DEBUG_LINELENGTH ? "..." : ""),
17241c6aec20Schristos 	    len, f->f_un.f_tls.tls_conn->sslptr ? "" : "un");
17251c6aec20Schristos 
17261c6aec20Schristos 	if(f->f_un.f_tls.tls_conn->state == ST_TLS_EST) {
17271c6aec20Schristos 		/* send now */
17281c6aec20Schristos 		if (!(smsg = calloc(1, sizeof(*smsg)))) {
17291c6aec20Schristos 			logerror("Unable to allocate memory, drop message");
17301c6aec20Schristos 			return false;
17311c6aec20Schristos 		}
17321c6aec20Schristos 		smsg->f = f;
17331c6aec20Schristos 		smsg->line = line;
17341c6aec20Schristos 		smsg->linelen = len;
17351c6aec20Schristos 		(void)NEWREF(qentry->msg);
17361c6aec20Schristos 		smsg->qentry = qentry;
17371c6aec20Schristos 		DPRINTF(D_DATA, "now sending line: \"%.*s\"\n",
17381c6aec20Schristos 		    (int)smsg->linelen, smsg->line);
17391c6aec20Schristos 		dispatch_tls_send(0, 0, smsg);
17401c6aec20Schristos 		return true;
17411c6aec20Schristos 	} else {
17421c6aec20Schristos 		/* other socket operation active, send later  */
17431c6aec20Schristos 		DPRINTF(D_DATA, "connection not ready to send: \"%.*s\"\n",
17441c6aec20Schristos 		    (int)len, line);
17451c6aec20Schristos 		return false;
17461c6aec20Schristos 	}
17471c6aec20Schristos }
17481c6aec20Schristos 
17491c6aec20Schristos /*ARGSUSED*/
17501c6aec20Schristos void
dispatch_tls_send(int fd,short event,void * arg)17511c6aec20Schristos dispatch_tls_send(int fd, short event, void *arg)
17521c6aec20Schristos {
17531c6aec20Schristos 	struct tls_send_msg *smsg = (struct tls_send_msg *) arg;
17541c6aec20Schristos 	struct tls_conn_settings *conn_info = smsg->f->f_un.f_tls.tls_conn;
17551c6aec20Schristos 	struct filed *f = smsg->f;
17561c6aec20Schristos 	int rc, error;
17571c6aec20Schristos 	sigset_t newmask, omask;
17581c6aec20Schristos 	bool retrying;
17591c6aec20Schristos 	struct timeval tv;
17601c6aec20Schristos 
17611c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
17621c6aec20Schristos 	DPRINTF((D_TLS|D_CALL), "dispatch_tls_send(f=%p, buffer=%p, "
17631c6aec20Schristos 	    "line@%p, len=%zu, offset=%zu) to %sconnected dest.\n",
17641c6aec20Schristos 	    smsg->f, smsg->qentry->msg, smsg->line,
17651c6aec20Schristos 	    smsg->linelen, smsg->offset,
17661c6aec20Schristos 		conn_info->sslptr ? "" : "un");
17671c6aec20Schristos 	assert(conn_info->state == ST_TLS_EST
17681c6aec20Schristos 	    || conn_info->state == ST_WRITING);
17691c6aec20Schristos 
17701c6aec20Schristos 	retrying = (conn_info->state == ST_WRITING);
17711c6aec20Schristos 	ST_CHANGE(conn_info->state, ST_WRITING);
17721c6aec20Schristos 	rc = SSL_write(conn_info->sslptr,
17731c6aec20Schristos 	    (smsg->line + smsg->offset),
17741c6aec20Schristos 	    (smsg->linelen - smsg->offset));
17751c6aec20Schristos 	if (0 >= rc) {
17761c6aec20Schristos 		error = tls_examine_error("SSL_write()",
17771c6aec20Schristos 		    conn_info->sslptr,
17781c6aec20Schristos 		    conn_info, rc);
17791c6aec20Schristos 		switch (error) {
17801c6aec20Schristos 		case TLS_RETRY_READ:
17811c6aec20Schristos 			/* collides with eof event */
17821c6aec20Schristos 			if (!retrying)
17831c6aec20Schristos 				event_del(conn_info->event);
17841c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_READ,
17851c6aec20Schristos 				dispatch_tls_send, smsg);
17861c6aec20Schristos 			RETRYEVENT_ADD(conn_info->retryevent);
17871c6aec20Schristos 			break;
17881c6aec20Schristos 		case TLS_RETRY_WRITE:
17891c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_WRITE,
17901c6aec20Schristos 			    dispatch_tls_send, smsg);
17911c6aec20Schristos 			RETRYEVENT_ADD(conn_info->retryevent);
17921c6aec20Schristos 			break;
17931c6aec20Schristos 		case TLS_PERM_ERROR:
17941c6aec20Schristos 			/* no need to check active events */
17951c6aec20Schristos 			free_tls_send_msg(smsg);
17961c6aec20Schristos 			free_tls_sslptr(conn_info);
17971c6aec20Schristos 			tv.tv_sec = conn_info->reconnect;
17981c6aec20Schristos 			tv.tv_usec = 0;
17991c6aec20Schristos 			schedule_event(&conn_info->event, &tv,
18001c6aec20Schristos 			    tls_reconnect, conn_info);
18011c6aec20Schristos 			TLS_RECONNECT_BACKOFF(conn_info->reconnect);
18021c6aec20Schristos 			break;
18031c6aec20Schristos 		default:
18041c6aec20Schristos 			break;
18051c6aec20Schristos 		}
18061c6aec20Schristos 		RESTORE_SIGNALS(omask);
18071c6aec20Schristos 		return;
18087e0b2295Slukem 	} else if ((size_t)rc < smsg->linelen) {
18091c6aec20Schristos 		DPRINTF((D_TLS|D_DATA), "TLS: SSL_write() wrote %d out of %zu "
18101c6aec20Schristos 		    "bytes\n", rc, (smsg->linelen - smsg->offset));
18111c6aec20Schristos 		smsg->offset += rc;
18121c6aec20Schristos 		/* try again */
18131c6aec20Schristos 		if (retrying)
18141c6aec20Schristos 			EVENT_ADD(conn_info->event);
18151c6aec20Schristos 		dispatch_tls_send(0, 0, smsg);
18161c6aec20Schristos 		return;
18177e0b2295Slukem 	} else if ((size_t)rc == (smsg->linelen - smsg->offset)) {
18181c6aec20Schristos 		DPRINTF((D_TLS|D_DATA), "TLS: SSL_write() complete\n");
18191c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_TLS_EST);
18201c6aec20Schristos 		free_tls_send_msg(smsg);
18211c6aec20Schristos 		send_queue(0, 0, f);
18221c6aec20Schristos 
18231c6aec20Schristos 	} else {
18241c6aec20Schristos 		/* should not be reached */
18251c6aec20Schristos 		/*LINTED constcond */
18261c6aec20Schristos 		assert(0);
18271c6aec20Schristos 		DPRINTF((D_TLS|D_DATA), "unreachable code after SSL_write()\n");
18281c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_TLS_EST);
18291c6aec20Schristos 		free_tls_send_msg(smsg);
18301c6aec20Schristos 		send_queue(0, 0, f);
18311c6aec20Schristos 	}
18321c6aec20Schristos 	if (retrying && conn_info->event->ev_events)
18331c6aec20Schristos 		EVENT_ADD(conn_info->event);
18341c6aec20Schristos 	RESTORE_SIGNALS(omask);
18351c6aec20Schristos }
18361c6aec20Schristos 
18371c6aec20Schristos /*
18381c6aec20Schristos  * Close a SSL connection and its queue and its tls_conn.
18391c6aec20Schristos  */
18401c6aec20Schristos void
free_tls_conn(struct tls_conn_settings * conn_info)18411c6aec20Schristos free_tls_conn(struct tls_conn_settings *conn_info)
18421c6aec20Schristos {
18431c6aec20Schristos 	DPRINTF(D_MEM, "free_tls_conn(conn_info@%p) with sslptr@%p\n",
18441c6aec20Schristos 		conn_info, conn_info->sslptr);
18451c6aec20Schristos 
18461c6aec20Schristos 	if (conn_info->sslptr) {
18471c6aec20Schristos 		conn_info->shutdown = true;
18481c6aec20Schristos 		free_tls_sslptr(conn_info);
18491c6aec20Schristos 	}
18501c6aec20Schristos 	assert(conn_info->state == ST_NONE);
18511c6aec20Schristos 
18521c6aec20Schristos 	FREEPTR(conn_info->port);
18531c6aec20Schristos 	FREEPTR(conn_info->subject);
18541c6aec20Schristos 	FREEPTR(conn_info->hostname);
18551c6aec20Schristos 	FREEPTR(conn_info->certfile);
18561c6aec20Schristos 	FREEPTR(conn_info->fingerprint);
18571c6aec20Schristos 	DEL_EVENT(conn_info->event);
18581c6aec20Schristos 	DEL_EVENT(conn_info->retryevent);
18591c6aec20Schristos 	FREEPTR(conn_info->event);
18601c6aec20Schristos 	FREEPTR(conn_info->retryevent);
18611c6aec20Schristos 	FREEPTR(conn_info);
18621c6aec20Schristos 	DPRINTF(D_MEM2, "free_tls_conn(conn_info@%p) returns\n", conn_info);
18631c6aec20Schristos }
18641c6aec20Schristos 
18651c6aec20Schristos /*
18661c6aec20Schristos  * Dispatch routine for non-blocking TLS shutdown
18671c6aec20Schristos  */
18681c6aec20Schristos /*ARGSUSED*/
18691c6aec20Schristos void
dispatch_SSL_shutdown(int fd,short event,void * arg)18701c6aec20Schristos dispatch_SSL_shutdown(int fd, short event, void *arg)
18711c6aec20Schristos {
18721c6aec20Schristos 	struct tls_conn_settings *conn_info = (struct tls_conn_settings *) arg;
18731c6aec20Schristos 	int rc, error;
18741c6aec20Schristos 	sigset_t newmask, omask;
18751c6aec20Schristos 	bool retrying;
18761c6aec20Schristos 
18771c6aec20Schristos 	BLOCK_SIGNALS(omask, newmask);
18781c6aec20Schristos 	DPRINTF((D_TLS|D_CALL),
18791c6aec20Schristos 	    "dispatch_SSL_shutdown(conn_info@%p, fd %d)\n", conn_info, fd);
18801c6aec20Schristos 	retrying = ((conn_info->state == ST_CLOSING0)
18811c6aec20Schristos 	     || (conn_info->state == ST_CLOSING1)
18821c6aec20Schristos 	     || (conn_info->state == ST_CLOSING2));
18831c6aec20Schristos 	if (!retrying)
18841c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_CLOSING0);
18851c6aec20Schristos 
18861c6aec20Schristos 	rc = SSL_shutdown(conn_info->sslptr);
18871c6aec20Schristos 	if (rc == 1) {	/* shutdown complete */
18881c6aec20Schristos 		DPRINTF((D_TLS|D_NET), "Closed TLS connection to %s\n",
18891c6aec20Schristos 		    conn_info->hostname);
18901c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_TCP_EST);  /* check this */
18911c6aec20Schristos 		conn_info->accepted = false;
18921c6aec20Schristos 		/* closing TCP comes below */
18931c6aec20Schristos 	} else if (rc == 0) { /* unidirectional, now call a 2nd time */
18941c6aec20Schristos 		/* problem: when connecting as a client to rsyslogd this
18951c6aec20Schristos 		 * loops and I keep getting rc == 0
18961c6aec20Schristos 		 * maybe I hit this bug?
18971c6aec20Schristos 		 * http://www.mail-archive.com/openssl-dev@openssl.org/msg24105.html
18981c6aec20Schristos 		 *
18991c6aec20Schristos 		 * anyway, now I use three closing states to make sure I abort
19001c6aec20Schristos 		 * after two rc = 0.
19011c6aec20Schristos 		 */
19021c6aec20Schristos 		if (conn_info->state == ST_CLOSING0) {
19031c6aec20Schristos 			ST_CHANGE(conn_info->state, ST_CLOSING1);
19041c6aec20Schristos 			dispatch_SSL_shutdown(fd, 0, conn_info);
19051c6aec20Schristos 		} else if (conn_info->state == ST_CLOSING1) {
19061c6aec20Schristos 			ST_CHANGE(conn_info->state, ST_CLOSING2);
19071c6aec20Schristos 			dispatch_SSL_shutdown(fd, 0, conn_info);
19081c6aec20Schristos 		} else if (conn_info->state == ST_CLOSING2) {
19091c6aec20Schristos 			/* abort shutdown, jump to close TCP below */
19101c6aec20Schristos 		} else
19111c6aec20Schristos 			DPRINTF(D_TLS, "Unexpected connection state %d\n",
19121c6aec20Schristos 				conn_info->state);
19131c6aec20Schristos 			/* and abort here too*/
19141c6aec20Schristos 	} else if (rc == -1 && conn_info->shutdown ) {
19151c6aec20Schristos 		(void)tls_examine_error("SSL_shutdown()",
19161c6aec20Schristos 			conn_info->sslptr, NULL, rc);
19171c6aec20Schristos 		DPRINTF((D_TLS|D_NET), "Ignore error in SSL_shutdown()"
19181c6aec20Schristos 			" and force connection shutdown.");
19191c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_TCP_EST);
19201c6aec20Schristos 		conn_info->accepted = false;
19211c6aec20Schristos 	} else if (rc == -1 && !conn_info->shutdown ) {
19221c6aec20Schristos 		error = tls_examine_error("SSL_shutdown()",
19231c6aec20Schristos 			conn_info->sslptr, NULL, rc);
19241c6aec20Schristos 		switch (error) {
19251c6aec20Schristos 		case TLS_RETRY_READ:
19261c6aec20Schristos 			if (!retrying)
19271c6aec20Schristos 				event_del(conn_info->event);
19281c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_READ,
19291c6aec20Schristos 			    dispatch_SSL_shutdown, conn_info);
19301c6aec20Schristos 			EVENT_ADD(conn_info->retryevent);
19311c6aec20Schristos 			RESTORE_SIGNALS(omask);
19321c6aec20Schristos 			return;
19331c6aec20Schristos 		case TLS_RETRY_WRITE:
19341c6aec20Schristos 			if (!retrying)
19351c6aec20Schristos 				event_del(conn_info->event);
19361c6aec20Schristos 			event_set(conn_info->retryevent, fd, EV_WRITE,
19371c6aec20Schristos 			    dispatch_SSL_shutdown, conn_info);
19381c6aec20Schristos 			EVENT_ADD(conn_info->retryevent);
19391c6aec20Schristos 			RESTORE_SIGNALS(omask);
19401c6aec20Schristos 			return;
19411c6aec20Schristos 		default:
19421c6aec20Schristos 			/* force close() on the TCP connection */
19431c6aec20Schristos 			ST_CHANGE(conn_info->state, ST_TCP_EST);
19441c6aec20Schristos 			conn_info->accepted = false;
19451c6aec20Schristos 			break;
19461c6aec20Schristos 		}
19471c6aec20Schristos 	}
19481c6aec20Schristos 	if ((conn_info->state != ST_TLS_EST)
19491c6aec20Schristos 	    && (conn_info->state != ST_NONE)
19501c6aec20Schristos 	    && (conn_info->state != ST_CLOSING0)
19511c6aec20Schristos 	    && (conn_info->state != ST_CLOSING1)) {
19521c6aec20Schristos 		int sock = SSL_get_fd(conn_info->sslptr);
19531c6aec20Schristos 
19541c6aec20Schristos 		if (shutdown(sock, SHUT_RDWR) == -1)
19551c6aec20Schristos 			logerror("Cannot shutdown socket");
19561c6aec20Schristos 		DEL_EVENT(conn_info->retryevent);
19571c6aec20Schristos 		DEL_EVENT(conn_info->event);
19581c6aec20Schristos 
19591c6aec20Schristos 		if (close(sock) == -1)
19601c6aec20Schristos 			logerror("Cannot close socket");
19611c6aec20Schristos 		DPRINTF((D_TLS|D_NET), "Closed TCP connection to %s\n",
19621c6aec20Schristos 		    conn_info->hostname);
19631c6aec20Schristos 		ST_CHANGE(conn_info->state, ST_NONE);
19641c6aec20Schristos 		FREE_SSL(conn_info->sslptr);
19651c6aec20Schristos 	 }
19661c6aec20Schristos 	RESTORE_SIGNALS(omask);
19671c6aec20Schristos }
19681c6aec20Schristos 
19691c6aec20Schristos /*
19701c6aec20Schristos  * Close a SSL object
19711c6aec20Schristos  */
19721c6aec20Schristos void
free_tls_sslptr(struct tls_conn_settings * conn_info)19731c6aec20Schristos free_tls_sslptr(struct tls_conn_settings *conn_info)
19741c6aec20Schristos {
19751c6aec20Schristos 	int sock;
19761c6aec20Schristos 	DPRINTF(D_MEM, "free_tls_sslptr(conn_info@%p)\n", conn_info);
19771c6aec20Schristos 
19781c6aec20Schristos 	if (!conn_info->sslptr) {
19791c6aec20Schristos 		assert(conn_info->incoming == 1
19801c6aec20Schristos 		    || conn_info->state == ST_NONE);
19811c6aec20Schristos 		return;
19821c6aec20Schristos 	} else {
19831c6aec20Schristos 		sock = SSL_get_fd(conn_info->sslptr);
19841c6aec20Schristos 		dispatch_SSL_shutdown(sock, 0, conn_info);
19851c6aec20Schristos 	}
19861c6aec20Schristos }
19871c6aec20Schristos 
19881c6aec20Schristos /* write self-generated certificates */
19891c6aec20Schristos bool
write_x509files(EVP_PKEY * pkey,X509 * cert,const char * keyfilename,const char * certfilename)19901c6aec20Schristos write_x509files(EVP_PKEY *pkey, X509 *cert,
19911c6aec20Schristos 	const char *keyfilename, const char *certfilename)
19921c6aec20Schristos {
19931c6aec20Schristos 	FILE *certfile, *keyfile;
19941c6aec20Schristos 
19955091f368Sspz 	if (!(umask(0177),(keyfile  = fopen(keyfilename,  "a")))) {
19965091f368Sspz 		logerror("Unable to write to file \"%s\"", keyfilename);
19975091f368Sspz 		return false;
19985091f368Sspz 	}
19995091f368Sspz 	if (!(umask(0122),(certfile = fopen(certfilename, "a")))) {
20005091f368Sspz 		logerror("Unable to write to file \"%s\"", certfilename);
20015091f368Sspz 		(void)fclose(keyfile);
20021c6aec20Schristos 		return false;
20031c6aec20Schristos 	}
20041c6aec20Schristos 	if (!PEM_write_PrivateKey(keyfile, pkey, NULL, NULL, 0, NULL, NULL))
20051c6aec20Schristos 		logerror("Unable to write key to \"%s\"", keyfilename);
20061c6aec20Schristos 	if (!X509_print_fp(certfile, cert)
20071c6aec20Schristos 	    || !PEM_write_X509(certfile, cert))
20081c6aec20Schristos 		logerror("Unable to write certificate to \"%s\"",
20091c6aec20Schristos 		    certfilename);
20101c6aec20Schristos 
20111c6aec20Schristos 	(void)fclose(keyfile);
20121c6aec20Schristos 	(void)fclose(certfile);
20131c6aec20Schristos 	return true;
20141c6aec20Schristos }
20151c6aec20Schristos 
20161c6aec20Schristos 
20171c6aec20Schristos /* adds all local IP addresses as subjectAltNames to cert x.
20181c6aec20Schristos  * getifaddrs() should be quite portable among BSDs and Linux
20191c6aec20Schristos  * but if not available the whole function can simply be removed.
20201c6aec20Schristos  */
20211c6aec20Schristos bool
x509_cert_add_subjectAltName(X509 * cert,X509V3_CTX * ctx)20221c6aec20Schristos x509_cert_add_subjectAltName(X509 *cert, X509V3_CTX *ctx)
20231c6aec20Schristos {
20241c6aec20Schristos 	struct ifaddrs *ifa = NULL, *ifp = NULL;
20251c6aec20Schristos 	char ip[100];
20261c6aec20Schristos 	char subjectAltName[2048];
20271c6aec20Schristos 	int idx = 0;
20281c6aec20Schristos 	socklen_t salen;
20291c6aec20Schristos 	X509_EXTENSION *ext;
20301c6aec20Schristos #ifdef notdef
20311c6aec20Schristos 	STACK_OF(X509_EXTENSION) *extlist;
20321c6aec20Schristos 	extlist = sk_X509_EXTENSION_new_null();
20331c6aec20Schristos #endif
20341c6aec20Schristos 
20351c6aec20Schristos 	if (getifaddrs (&ifp) == -1) {
20361c6aec20Schristos 		logerror("Unable to get list of local interfaces");
20371c6aec20Schristos 		return false;
20381c6aec20Schristos 	}
20391c6aec20Schristos 
20401c6aec20Schristos 	idx = snprintf(subjectAltName, sizeof(subjectAltName),
20411c6aec20Schristos 	    "DNS:%s", LocalFQDN);
20421c6aec20Schristos 
20431c6aec20Schristos 	for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
20441c6aec20Schristos 		if(!ifa->ifa_addr)
20451c6aec20Schristos 			continue;
20461c6aec20Schristos 
20471c6aec20Schristos 		/* only IP4 and IP6 addresses, but filter loopbacks */
20481c6aec20Schristos 		if (ifa->ifa_addr->sa_family == AF_INET) {
20491c6aec20Schristos 			struct sockaddr_in *addr =
20501c6aec20Schristos 			    (struct sockaddr_in *)ifa->ifa_addr;
20511c6aec20Schristos 			if (addr->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
20521c6aec20Schristos 				continue;
20531c6aec20Schristos 			salen = sizeof(struct sockaddr_in);
20541c6aec20Schristos 		} else if (ifa->ifa_addr->sa_family == AF_INET6) {
20551c6aec20Schristos 			struct in6_addr *addr6 =
20561c6aec20Schristos 			    &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
20571c6aec20Schristos 			if (IN6_IS_ADDR_LOOPBACK(addr6))
20581c6aec20Schristos 				continue;
20591c6aec20Schristos 			salen = sizeof(struct sockaddr_in6);
20601c6aec20Schristos 		} else
20611c6aec20Schristos 			continue;
20621c6aec20Schristos 
20631c6aec20Schristos 		if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip),
20641c6aec20Schristos 		    NULL, 0, NI_NUMERICHOST)) {
20651c6aec20Schristos 			continue;
20661c6aec20Schristos 		}
20671c6aec20Schristos 
20681c6aec20Schristos 		/* add IP to list */
20691c6aec20Schristos 		idx += snprintf(&subjectAltName[idx],
20701c6aec20Schristos 		    sizeof(subjectAltName)-idx, ", IP:%s", ip);
20711c6aec20Schristos 	}
20721c6aec20Schristos 	freeifaddrs (ifp);
20731c6aec20Schristos 
20741c6aec20Schristos 	ext = X509V3_EXT_conf_nid(NULL, ctx,
20751c6aec20Schristos 	    NID_subject_alt_name, subjectAltName);
20761c6aec20Schristos 	X509_add_ext(cert, ext, -1);
20771c6aec20Schristos 	X509_EXTENSION_free(ext);
20781c6aec20Schristos 
20791c6aec20Schristos 	return true;
20801c6aec20Schristos }
20811c6aec20Schristos 
20821c6aec20Schristos /*
20831c6aec20Schristos  * generates a private key and a X.509 certificate
20841c6aec20Schristos  */
20851c6aec20Schristos bool
mk_x509_cert(X509 ** x509p,EVP_PKEY ** pkeyp,int bits,int serial,int days)20861c6aec20Schristos mk_x509_cert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
20871c6aec20Schristos {
20881c6aec20Schristos 	X509	       *cert;
20891c6aec20Schristos 	EVP_PKEY       *pk;
20901c6aec20Schristos 	DSA	       *dsa;
20911c6aec20Schristos 	X509_NAME      *name = NULL;
20921c6aec20Schristos 	X509_EXTENSION *ex = NULL;
20931c6aec20Schristos 	X509V3_CTX	ctx;
20941c6aec20Schristos 
20951c6aec20Schristos 	DPRINTF((D_CALL|D_TLS), "mk_x509_cert(%p, %p, %d, %d, %d)\n",
20961c6aec20Schristos 	    x509p, pkeyp, bits, serial, days);
20971c6aec20Schristos 
20981c6aec20Schristos 	if (pkeyp && *pkeyp)
20991c6aec20Schristos 		pk = *pkeyp;
21001c6aec20Schristos 	else if ((pk = EVP_PKEY_new()) == NULL) {
21011c6aec20Schristos 		DPRINTF(D_TLS, "EVP_PKEY_new() failed\n");
21021c6aec20Schristos 		return false;
21031c6aec20Schristos 	}
21041c6aec20Schristos 
21051c6aec20Schristos 	if (x509p && *x509p)
21061c6aec20Schristos 		cert = *x509p;
21071c6aec20Schristos 	else if ((cert = X509_new()) == NULL) {
21081c6aec20Schristos 		DPRINTF(D_TLS, "X509_new() failed\n");
21091c6aec20Schristos 		return false;
21101c6aec20Schristos 	}
21111c6aec20Schristos 
21124d91e676Schristos 	dsa = DSA_new();
21134d91e676Schristos 	if (dsa == NULL) {
21144d91e676Schristos 		DPRINTF(D_TLS, "DSA_new() failed\n");
21154d91e676Schristos 		return false;
21164d91e676Schristos 	}
21174d91e676Schristos 
21184d91e676Schristos 	if (!DSA_generate_parameters_ex(dsa, bits, NULL, 0, NULL, NULL, NULL)) {
21194d91e676Schristos 		DPRINTF(D_TLS, "DSA_generate_parameters_ex() failed\n");
21204d91e676Schristos 		return false;
21214d91e676Schristos 	}
21221c6aec20Schristos 	if (!DSA_generate_key(dsa)) {
21231c6aec20Schristos 		DPRINTF(D_TLS, "DSA_generate_key() failed\n");
21241c6aec20Schristos 		return false;
21251c6aec20Schristos 	}
21261c6aec20Schristos 	if (!EVP_PKEY_assign_DSA(pk, dsa)) {
21271c6aec20Schristos 		DPRINTF(D_TLS, "EVP_PKEY_assign_DSA() failed\n");
21281c6aec20Schristos 		return false;
21291c6aec20Schristos 	}
21301c6aec20Schristos 
21311c6aec20Schristos 	X509_set_version(cert, 3);
21321c6aec20Schristos 	ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
21331c6aec20Schristos 	X509_gmtime_adj(X509_get_notBefore(cert), 0);
21341c6aec20Schristos 	X509_gmtime_adj(X509_get_notAfter(cert), (long)60 * 60 * 24 * days);
21351c6aec20Schristos 
21361c6aec20Schristos 	if (!X509_set_pubkey(cert, pk)) {
21371c6aec20Schristos 		DPRINTF(D_TLS, "X509_set_pubkey() failed\n");
21381c6aec20Schristos 		return false;
21391c6aec20Schristos 	}
21401c6aec20Schristos 
21411c6aec20Schristos 	/*
21421c6aec20Schristos 	 * This function creates and adds the entry, working out the correct
21431c6aec20Schristos 	 * string type and performing checks on its length. Normally we'd check
21441c6aec20Schristos 	 * the return value for errors...
21451c6aec20Schristos 	 */
21461c6aec20Schristos 	name = X509_get_subject_name(cert);
21471c6aec20Schristos 	/*
21481c6aec20Schristos 	X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
21491c6aec20Schristos 	    (unsigned char *)"The NetBSD Project", -1, -1, 0);
21501c6aec20Schristos 	X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC,
21511c6aec20Schristos 	    (unsigned char *)"syslogd", -1, -1, 0);
21521c6aec20Schristos 	*/
21531c6aec20Schristos 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
21541c6aec20Schristos 	    (unsigned char *) LocalFQDN, -1, -1, 0);
21551c6aec20Schristos 	X509_set_issuer_name(cert, name);
21561c6aec20Schristos 
21571c6aec20Schristos 	/*
21581c6aec20Schristos 	 * Add extension using V3 code: we can set the config file as NULL
21591c6aec20Schristos 	 * because we wont reference any other sections.
21601c6aec20Schristos 	 */
21611c6aec20Schristos 	X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
21621c6aec20Schristos 
21631c6aec20Schristos 	ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_netscape_comment,
21641c6aec20Schristos 	    __UNCONST("auto-generated by the NetBSD syslogd"));
21651c6aec20Schristos 	X509_add_ext(cert, ex, -1);
21661c6aec20Schristos 	X509_EXTENSION_free(ex);
21671c6aec20Schristos 
21681c6aec20Schristos 	ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_netscape_ssl_server_name,
21691c6aec20Schristos 	    LocalFQDN);
21701c6aec20Schristos 	X509_add_ext(cert, ex, -1);
21711c6aec20Schristos 	X509_EXTENSION_free(ex);
21721c6aec20Schristos 
21731c6aec20Schristos 	ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_netscape_cert_type,
21741c6aec20Schristos 	    __UNCONST("server, client"));
21751c6aec20Schristos 	X509_add_ext(cert, ex, -1);
21761c6aec20Schristos 	X509_EXTENSION_free(ex);
21771c6aec20Schristos 
21781c6aec20Schristos 	ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_key_usage,
21791c6aec20Schristos 	    __UNCONST("keyAgreement, keyEncipherment, "
21801c6aec20Schristos 	    "nonRepudiation, digitalSignature"));
21811c6aec20Schristos 	X509_add_ext(cert, ex, -1);
21821c6aec20Schristos 	X509_EXTENSION_free(ex);
21831c6aec20Schristos 
21841c6aec20Schristos 	ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints,
21851c6aec20Schristos 	    __UNCONST("critical,CA:FALSE"));
21861c6aec20Schristos 	X509_add_ext(cert, ex, -1);
21871c6aec20Schristos 	X509_EXTENSION_free(ex);
21881c6aec20Schristos 
21891c6aec20Schristos 	(void)x509_cert_add_subjectAltName(cert, &ctx);
21901c6aec20Schristos 
21914d91e676Schristos 	if (!X509_sign(cert, pk, EVP_sha1())) {
21921c6aec20Schristos 		DPRINTF(D_TLS, "X509_sign() failed\n");
21931c6aec20Schristos 		return false;
21941c6aec20Schristos 	}
21951c6aec20Schristos 	if (X509_verify(cert, pk) != 1) {
21961c6aec20Schristos 		DPRINTF(D_TLS, "X509_verify() failed\n");
21971c6aec20Schristos 		return false;
21981c6aec20Schristos 	}
21991c6aec20Schristos 
22001c6aec20Schristos 	*x509p = cert;
22011c6aec20Schristos 	*pkeyp = pk;
22021c6aec20Schristos 	return true;
22031c6aec20Schristos }
22041c6aec20Schristos 
22051c6aec20Schristos void
free_tls_send_msg(struct tls_send_msg * msg)22061c6aec20Schristos free_tls_send_msg(struct tls_send_msg *msg)
22071c6aec20Schristos {
22081c6aec20Schristos 	if (!msg) {
22091c6aec20Schristos 		DPRINTF((D_DATA), "invalid tls_send_msg_free(NULL)\n");
22101c6aec20Schristos 		return;
22111c6aec20Schristos 	}
22121c6aec20Schristos 	DELREF(msg->qentry->msg);
22131c6aec20Schristos 	(void)message_queue_remove(msg->f, msg->qentry);
22141c6aec20Schristos 	FREEPTR(msg->line);
22151c6aec20Schristos 	FREEPTR(msg);
22161c6aec20Schristos }
22171c6aec20Schristos #endif /* !DISABLE_TLS */
2218