xref: /openbsd/usr.sbin/smtpd/ssl.c (revision 898184e3)
1 /*	$OpenBSD: ssl.c,v 1.52 2013/01/26 09:37:24 gilles Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org>
6  * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 #include <sys/tree.h>
24 #include <sys/param.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 
28 #include <ctype.h>
29 #include <event.h>
30 #include <fcntl.h>
31 #include <imsg.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include <openssl/ssl.h>
39 #include <openssl/engine.h>
40 #include <openssl/err.h>
41 
42 #include "log.h"
43 #include "ssl.h"
44 
45 void
46 ssl_init(void)
47 {
48 	static int	inited = 0;
49 
50 	if (inited)
51 		return;
52 
53 	SSL_library_init();
54 	SSL_load_error_strings();
55 
56 	OpenSSL_add_all_algorithms();
57 
58 	/* Init hardware crypto engines. */
59 	ENGINE_load_builtin_engines();
60 	ENGINE_register_all_complete();
61 	inited = 1;
62 }
63 
64 int
65 ssl_setup(SSL_CTX **ctxp, struct ssl *ssl)
66 {
67 	DH	*dh;
68 	SSL_CTX	*ctx;
69 
70 	ctx = ssl_ctx_create();
71 
72 	if (!ssl_ctx_use_certificate_chain(ctx,
73 		ssl->ssl_cert, ssl->ssl_cert_len))
74 		goto err;
75 	if (!ssl_ctx_use_private_key(ctx,
76 		ssl->ssl_key, ssl->ssl_key_len))
77 		goto err;
78 
79 	if (!SSL_CTX_check_private_key(ctx))
80 		goto err;
81 	if (!SSL_CTX_set_session_id_context(ctx,
82 		(const unsigned char *)ssl->ssl_name,
83 		strlen(ssl->ssl_name) + 1))
84 		goto err;
85 
86 	if (ssl->ssl_dhparams_len == 0)
87 		dh = get_dh1024();
88 	else
89 		dh = get_dh_from_memory(ssl->ssl_dhparams,
90 		    ssl->ssl_dhparams_len);
91 	ssl_set_ephemeral_key_exchange(ctx, dh);
92 	DH_free(dh);
93 
94 	*ctxp = ctx;
95 	return 1;
96 
97 err:
98 	SSL_CTX_free(ctx);
99 	ssl_error("ssl_setup");
100 	return 0;
101 }
102 
103 char *
104 ssl_load_file(const char *name, off_t *len, mode_t perm)
105 {
106 	struct stat	 st;
107 	off_t		 size;
108 	char		*buf = NULL;
109 	int		 fd, saved_errno;
110 	char		 mode[12];
111 
112 	if ((fd = open(name, O_RDONLY)) == -1)
113 		return (NULL);
114 	if (fstat(fd, &st) != 0)
115 		goto fail;
116 	if (st.st_uid != 0) {
117 		log_warnx("warn:  %s: not owned by uid 0", name);
118 		errno = EACCES;
119 		goto fail;
120 	}
121 	if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) {
122 		strmode(perm, mode);
123 		log_warnx("warn:  %s: insecure permissions: must be at most %s",
124 		    name, &mode[1]);
125 		errno = EACCES;
126 		goto fail;
127 	}
128 	size = st.st_size;
129 	if ((buf = calloc(1, size + 1)) == NULL)
130 		goto fail;
131 	if (read(fd, buf, size) != size)
132 		goto fail;
133 	close(fd);
134 
135 	*len = size + 1;
136 	return (buf);
137 
138 fail:
139 	if (buf != NULL)
140 		free(buf);
141 	saved_errno = errno;
142 	close(fd);
143 	errno = saved_errno;
144 	return (NULL);
145 }
146 
147 static int
148 ssl_password_cb(char *buf, int size, int rwflag, void *u)
149 {
150 	size_t	len;
151 	if (u == NULL) {
152 		bzero(buf, size);
153 		return (0);
154 	}
155 	if ((len = strlcpy(buf, u, size)) >= (size_t)size)
156 		return (0);
157 	return (len);
158 }
159 
160 char *
161 ssl_load_key(const char *name, off_t *len, char *pass)
162 {
163 	FILE		*fp;
164 	EVP_PKEY	*key = NULL;
165 	BIO		*bio = NULL;
166 	long		 size;
167 	char		*data, *buf = NULL;
168 
169 	/* Initialize SSL library once */
170 	ssl_init();
171 
172 	/*
173 	 * Read (possibly) encrypted key from file
174 	 */
175 	if ((fp = fopen(name, "r")) == NULL)
176 		return (NULL);
177 
178 	key = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, pass);
179 	fclose(fp);
180 	if (key == NULL)
181 		goto fail;
182 
183 	/*
184 	 * Write unencrypted key to memory buffer
185 	 */
186 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
187 		goto fail;
188 	if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL))
189 		goto fail;
190 	if ((size = BIO_get_mem_data(bio, &data)) <= 0)
191 		goto fail;
192 	if ((buf = calloc(1, size)) == NULL)
193 		goto fail;
194 	memcpy(buf, data, size);
195 
196 	BIO_free_all(bio);
197 	*len = (off_t)size;
198 	return (buf);
199 
200 fail:
201 	ssl_error("ssl_load_key");
202 
203 	free(buf);
204 	if (bio != NULL)
205 		BIO_free_all(bio);
206 	return (NULL);
207 }
208 
209 SSL_CTX *
210 ssl_ctx_create(void)
211 {
212 	SSL_CTX	*ctx;
213 
214 	ctx = SSL_CTX_new(SSLv23_method());
215 	if (ctx == NULL) {
216 		ssl_error("ssl_ctx_create");
217 		fatal("ssl_ctx_create: could not create SSL context");
218 	}
219 
220 	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
221 	SSL_CTX_set_timeout(ctx, SSL_SESSION_TIMEOUT);
222 	SSL_CTX_set_options(ctx,
223 	    SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_TICKET);
224 	SSL_CTX_set_options(ctx,
225 	    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
226 
227 	if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) {
228 		ssl_error("ssl_ctx_create");
229 		fatal("ssl_ctx_create: could not set cipher list");
230 	}
231 
232 	return (ctx);
233 }
234 
235 int
236 ssl_load_certfile(struct ssl **sp, const char *path, const char *name, uint8_t flags)
237 {
238 	struct ssl     *s;
239 	char		pathname[PATH_MAX];
240 	int		ret;
241 
242 	if ((s = calloc(1, sizeof(*s))) == NULL)
243 		fatal(NULL);
244 
245 	s->flags = flags;
246 	(void)strlcpy(s->ssl_name, name, sizeof(s->ssl_name));
247 
248 	ret =  snprintf(pathname, sizeof(pathname), "%s/%s.crt",
249 	    path ? path : "/etc/ssl", name);
250 	if (ret == -1 || (size_t)ret >= sizeof pathname)
251 		goto err;
252 	s->ssl_cert = ssl_load_file(pathname, &s->ssl_cert_len, 0755);
253 	if (s->ssl_cert == NULL)
254 		goto err;
255 
256 	ret = snprintf(pathname, sizeof(pathname), "%s/%s.key",
257 	    path ? path : "/etc/ssl/private", name);
258 	if (ret == -1 || (size_t)ret >= sizeof pathname)
259 		goto err;
260 	s->ssl_key = ssl_load_file(pathname, &s->ssl_key_len, 0700);
261 	if (s->ssl_key == NULL)
262 		goto err;
263 
264 	ret = snprintf(pathname, sizeof(pathname), "%s/%s.ca",
265 	    path ? path : "/etc/ssl", name);
266 	if (ret == -1 || (size_t)ret >= sizeof pathname)
267 		goto err;
268 	s->ssl_ca = ssl_load_file(pathname, &s->ssl_ca_len, 0755);
269 	if (s->ssl_ca == NULL) {
270 		if (errno == EACCES)
271 			goto err;
272 		log_info("info: No CA found in %s", pathname);
273 	}
274 
275 	ret = snprintf(pathname, sizeof(pathname), "%s/%s.dh",
276 	    path ? path : "/etc/ssl", name);
277 	if (ret == -1 || (size_t)ret >= sizeof pathname)
278 		goto err;
279 	s->ssl_dhparams = ssl_load_file(pathname, &s->ssl_dhparams_len, 0755);
280 	if (s->ssl_dhparams == NULL) {
281 		if (errno == EACCES)
282 			goto err;
283 		log_info("info: No DH parameters found in %s: "
284 		    "using built-in parameters", pathname);
285 	}
286 
287 	*sp = s;
288 	return (1);
289 
290 err:
291 	if (s->ssl_cert != NULL)
292 		free(s->ssl_cert);
293 	if (s->ssl_key != NULL)
294 		free(s->ssl_key);
295 	if (s->ssl_ca != NULL)
296 		free(s->ssl_ca);
297 	if (s->ssl_dhparams != NULL)
298 		free(s->ssl_dhparams);
299 	if (s != NULL)
300 		free(s);
301 	return (0);
302 }
303 
304 
305 const char *
306 ssl_to_text(const SSL *ssl)
307 {
308 	static char buf[256];
309 
310 	snprintf(buf, sizeof buf, "version=%s, cipher=%s, bits=%i",
311 	    SSL_get_cipher_version(ssl),
312 	    SSL_get_cipher_name(ssl),
313 	    SSL_get_cipher_bits(ssl, NULL));
314 
315 	return (buf);
316 }
317 
318 void
319 ssl_error(const char *where)
320 {
321 	unsigned long	code;
322 	char		errbuf[128];
323 	extern int	debug;
324 
325 	for (; (code = ERR_get_error()) != 0 ;) {
326 		if (!debug)
327 			continue;
328 		ERR_error_string_n(code, errbuf, sizeof(errbuf));
329 		log_debug("debug: SSL library error: %s: %s", where, errbuf);
330 	}
331 }
332 
333 /* From OpenSSL's documentation:
334  *
335  * If "strong" primes were used to generate the DH parameters, it is
336  * not strictly necessary to generate a new key for each handshake
337  * but it does improve forward secrecy.
338  *
339  * -- gilles@
340  */
341 DH *
342 get_dh1024(void)
343 {
344 	DH *dh;
345 	unsigned char dh1024_p[] = {
346 		0xAD,0x37,0xBB,0x26,0x75,0x01,0x27,0x75,
347 		0x06,0xB5,0xE7,0x1E,0x1F,0x2B,0xBC,0x51,
348 		0xC0,0xF4,0xEB,0x42,0x7A,0x2A,0x83,0x1E,
349 		0xE8,0xD1,0xD8,0xCC,0x9E,0xE6,0x15,0x1D,
350 		0x06,0x46,0x50,0x94,0xB9,0xEE,0xB6,0x89,
351 		0xB7,0x3C,0xAC,0x07,0x5E,0x29,0x37,0xCC,
352 		0x8F,0xDF,0x48,0x56,0x85,0x83,0x26,0x02,
353 		0xB8,0xB6,0x63,0xAF,0x2D,0x4A,0x57,0x93,
354 		0x6B,0x54,0xE1,0x8F,0x28,0x76,0x9C,0x5D,
355 		0x90,0x65,0xD1,0x07,0xFE,0x5B,0x05,0x65,
356 		0xDA,0xD2,0xE2,0xAF,0x23,0xCA,0x2F,0xD6,
357 		0x4B,0xD2,0x04,0xFE,0xDF,0x21,0x2A,0xE1,
358 		0xCD,0x1B,0x70,0x76,0xB3,0x51,0xA4,0xC9,
359 		0x2B,0x68,0xE3,0xDD,0xCB,0x97,0xDA,0x59,
360 		0x50,0x93,0xEE,0xDB,0xBF,0xC7,0xFA,0xA7,
361 		0x47,0xC4,0x4D,0xF0,0xC6,0x09,0x4A,0x4B
362 	};
363 	unsigned char dh1024_g[] = {
364 		0x02
365 	};
366 
367 	if ((dh = DH_new()) == NULL)
368 		return NULL;
369 
370 	dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
371 	dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
372 	if (dh->p == NULL || dh->g == NULL) {
373 		DH_free(dh);
374 		return NULL;
375 	}
376 
377 	return dh;
378 }
379 
380 DH *
381 get_dh_from_memory(char *params, size_t len)
382 {
383 	BIO *mem;
384 	DH *dh;
385 
386 	mem = BIO_new_mem_buf(params, len);
387 	if (mem == NULL)
388 		return NULL;
389 	dh = PEM_read_bio_DHparams(mem, NULL, NULL, NULL);
390 	if (dh == NULL)
391 		goto err;
392 	if (dh->p == NULL || dh->g == NULL)
393 		goto err;
394 	return dh;
395 
396 err:
397 	if (mem != NULL)
398 		BIO_free(mem);
399 	if (dh != NULL)
400 		DH_free(dh);
401 	return NULL;
402 }
403 
404 
405 void
406 ssl_set_ephemeral_key_exchange(SSL_CTX *ctx, DH *dh)
407 {
408 	if (dh == NULL || !SSL_CTX_set_tmp_dh(ctx, dh)) {
409 		ssl_error("ssl_set_ephemeral_key_exchange");
410 		fatal("ssl_set_ephemeral_key_exchange: cannot set tmp dh");
411 	}
412 }
413