1/*++
2/* NAME
3/*	tls_certkey 3
4/* SUMMARY
5/*	public key certificate and private key loader
6/* SYNOPSIS
7/*	#define TLS_INTERNAL
8/*	#include <tls.h>
9/*
10/*	int	tls_set_ca_certificate_info(ctx, CAfile, CApath)
11/*	SSL_CTX	*ctx;
12/*	const char *CAfile;
13/*	const char *CApath;
14/*
15/*	int	tls_set_my_certificate_key_info(ctx, cert_file, key_file,
16/*						dcert_file, dkey_file,
17/*						eccert_file, eckey_file)
18/*	SSL_CTX	*ctx;
19/*	const char *cert_file;
20/*	const char *key_file;
21/*	const char *dcert_file;
22/*	const char *dkey_file;
23/*	const char *eccert_file;
24/*	const char *eckey_file;
25/* DESCRIPTION
26/*	OpenSSL supports two options to specify CA certificates:
27/*	either one file CAfile that contains all CA certificates,
28/*	or a directory CApath with separate files for each
29/*	individual CA, with symbolic links named after the hash
30/*	values of the certificates. The second option is not
31/*	convenient with a chrooted process.
32/*
33/*	tls_set_ca_certificate_info() loads the CA certificate
34/*	information for the specified TLS server or client context.
35/*	The result is -1 on failure, 0 on success.
36/*
37/*	tls_set_my_certificate_key_info() loads the public key
38/*	certificates and private keys for the specified TLS server
39/*	or client context. Up to 3 pairs of key pairs (RSA, DSA and
40/*	ECDSA) may be specified; each certificate and key pair must
41/*	match.  The result is -1 on failure, 0 on success.
42/* LICENSE
43/* .ad
44/* .fi
45/*	This software is free. You can do with it whatever you want.
46/*	The original author kindly requests that you acknowledge
47/*	the use of his software.
48/* AUTHOR(S)
49/*	Originally written by:
50/*	Lutz Jaenicke
51/*	BTU Cottbus
52/*	Allgemeine Elektrotechnik
53/*	Universitaetsplatz 3-4
54/*	D-03044 Cottbus, Germany
55/*
56/*	Updated by:
57/*	Wietse Venema
58/*	IBM T.J. Watson Research
59/*	P.O. Box 704
60/*	Yorktown Heights, NY 10598, USA
61/*--*/
62
63/* System library. */
64
65#include <sys_defs.h>
66
67#ifdef USE_TLS
68
69/* Utility library. */
70
71#include <msg.h>
72
73/* Global library. */
74
75#include <mail_params.h>
76
77/* TLS library. */
78
79#define TLS_INTERNAL
80#include <tls.h>
81
82/* tls_set_ca_certificate_info - load certificate authority certificates */
83
84int     tls_set_ca_certificate_info(SSL_CTX *ctx, const char *CAfile,
85				            const char *CApath)
86{
87    if (*CAfile == 0)
88	CAfile = 0;
89    if (*CApath == 0)
90	CApath = 0;
91    if (CAfile || CApath) {
92	if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
93	    msg_info("cannot load Certificate Authority data: "
94		     "disabling TLS support");
95	    tls_print_errors();
96	    return (-1);
97	}
98	if (var_tls_append_def_CA && !SSL_CTX_set_default_verify_paths(ctx)) {
99	    msg_info("cannot set certificate verification paths: "
100		     "disabling TLS support");
101	    tls_print_errors();
102	    return (-1);
103	}
104    }
105    return (0);
106}
107
108/* set_cert_stuff - specify certificate and key information */
109
110static int set_cert_stuff(SSL_CTX *ctx, const char *cert_type,
111			          const char *cert_file,
112			          const char *key_file)
113{
114
115    /*
116     * We need both the private key (in key_file) and the public key
117     * certificate (in cert_file). Both may specify the same file.
118     *
119     * Code adapted from OpenSSL apps/s_cb.c.
120     */
121    ERR_clear_error();
122    if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
123	msg_warn("cannot get %s certificate from file %s: "
124		 "disabling TLS support", cert_type, cert_file);
125	tls_print_errors();
126	return (0);
127    }
128    if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
129	msg_warn("cannot get %s private key from file %s: "
130		 "disabling TLS support", cert_type, key_file);
131	tls_print_errors();
132	return (0);
133    }
134
135    /*
136     * Sanity check.
137     */
138    if (!SSL_CTX_check_private_key(ctx)) {
139	msg_warn("%s private key in %s does not match public key in %s: "
140		 "disabling TLS support", cert_type, key_file, cert_file);
141	return (0);
142    }
143    return (1);
144}
145
146/* tls_set_my_certificate_key_info - load client or server certificates/keys */
147
148int     tls_set_my_certificate_key_info(SSL_CTX *ctx,
149					        const char *cert_file,
150					        const char *key_file,
151					        const char *dcert_file,
152					        const char *dkey_file,
153					        const char *eccert_file,
154					        const char *eckey_file)
155{
156
157    /*
158     * Lack of certificates is fine so long as we are prepared to use
159     * anonymous ciphers.
160     */
161    if (*cert_file && !set_cert_stuff(ctx, "RSA", cert_file, key_file))
162	return (-1);			/* logged */
163    if (*dcert_file && !set_cert_stuff(ctx, "DSA", dcert_file, dkey_file))
164	return (-1);				/* logged */
165#if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH)
166    if (*eccert_file && !set_cert_stuff(ctx, "ECDSA", eccert_file, eckey_file))
167	return (-1);				/* logged */
168#else
169    if (*eccert_file)
170	msg_warn("ECDSA not supported. Ignoring ECDSA certificate file \"%s\"",
171		 eccert_file);
172#endif
173    return (0);
174}
175
176#endif
177