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