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