src/login-common/ssl-proxy-openssl.c
author Timo Sirainen <tss@iki.fi>
Tue Oct 06 10:53:34 2009 -0400 (2009-10-06)
branchHEAD
changeset 9416 4add5c3f13ea
parent 9394 e7a973c0101b
child 9435 0aa7357761a5
permissions -rw-r--r--
Compiling fix for OpenSSL 0.9.7 and older.
     1 /* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
     2 
     3 #include "common.h"
     4 #include "array.h"
     5 #include "ioloop.h"
     6 #include "network.h"
     7 #include "ostream.h"
     8 #include "read-full.h"
     9 #include "llist.h"
    10 #include "ssl-proxy.h"
    11 
    12 #include <fcntl.h>
    13 #include <unistd.h>
    14 #include <sys/stat.h>
    15 
    16 #ifdef HAVE_OPENSSL
    17 
    18 #include <openssl/crypto.h>
    19 #include <openssl/x509.h>
    20 #include <openssl/pem.h>
    21 #include <openssl/ssl.h>
    22 #include <openssl/err.h>
    23 #include <openssl/rand.h>
    24 
    25 #define DOVECOT_SSL_DEFAULT_CIPHER_LIST "ALL:!LOW:!SSLv2"
    26 /* Check every 30 minutes if parameters file has been updated */
    27 #define SSL_PARAMFILE_CHECK_INTERVAL (60*30)
    28 
    29 enum ssl_io_action {
    30 	SSL_ADD_INPUT,
    31 	SSL_REMOVE_INPUT,
    32 	SSL_ADD_OUTPUT,
    33 	SSL_REMOVE_OUTPUT
    34 };
    35 
    36 struct ssl_proxy {
    37 	int refcount;
    38 	struct ssl_proxy *prev, *next;
    39 
    40 	SSL *ssl;
    41 	struct ip_addr ip;
    42 
    43 	int fd_ssl, fd_plain;
    44 	struct io *io_ssl_read, *io_ssl_write, *io_plain_read, *io_plain_write;
    45 
    46 	unsigned char plainout_buf[1024];
    47 	unsigned int plainout_size;
    48 
    49 	unsigned char sslout_buf[1024];
    50 	unsigned int sslout_size;
    51 
    52 	ssl_handshake_callback_t *handshake_callback;
    53 	void *handshake_context;
    54 
    55 	char *last_error;
    56 	unsigned int handshaked:1;
    57 	unsigned int destroyed:1;
    58 	unsigned int cert_received:1;
    59 	unsigned int cert_broken:1;
    60 	unsigned int client:1;
    61 };
    62 
    63 struct ssl_parameters {
    64 	const char *fname;
    65 	time_t last_mtime, last_check;
    66 	int fd;
    67 
    68 	DH *dh_512, *dh_1024;
    69 };
    70 
    71 static int extdata_index;
    72 static SSL_CTX *ssl_server_ctx;
    73 static SSL_CTX *ssl_client_ctx;
    74 static unsigned int ssl_proxy_count;
    75 static struct ssl_proxy *ssl_proxies;
    76 static struct ssl_parameters ssl_params;
    77 static int ssl_username_nid;
    78 
    79 static void plain_read(struct ssl_proxy *proxy);
    80 static void ssl_read(struct ssl_proxy *proxy);
    81 static void ssl_write(struct ssl_proxy *proxy);
    82 static void ssl_step(struct ssl_proxy *proxy);
    83 static void ssl_proxy_destroy(struct ssl_proxy *proxy);
    84 static void ssl_proxy_unref(struct ssl_proxy *proxy);
    85 
    86 static void ssl_params_corrupted(const char *path)
    87 {
    88 	i_fatal("Corrupted SSL parameters file: %s/%s "
    89 		"(delete it and also the one in %s)",
    90 		getenv("LOGIN_DIR"), path, PKG_STATEDIR);
    91 }
    92 
    93 static void read_next(struct ssl_parameters *params, void *data, size_t size)
    94 {
    95 	int ret;
    96 
    97 	if ((ret = read_full(params->fd, data, size)) < 0)
    98 		i_fatal("read(%s) failed: %m", params->fname);
    99 	if (ret == 0)
   100 		ssl_params_corrupted(params->fname);
   101 }
   102 
   103 static bool read_dh_parameters_next(struct ssl_parameters *params)
   104 {
   105 	unsigned char *buf;
   106 	const unsigned char *cbuf;
   107 	unsigned int len;
   108 	int bits;
   109 
   110 	/* read bit size. 0 ends the DH parameters list. */
   111 	read_next(params, &bits, sizeof(bits));
   112 
   113 	if (bits == 0)
   114 		return FALSE;
   115 
   116 	/* read data size. */
   117 	read_next(params, &len, sizeof(len));
   118 	if (len > 1024*100) /* should be enough? */
   119 		ssl_params_corrupted(params->fname);
   120 
   121 	buf = i_malloc(len);
   122 	read_next(params, buf, len);
   123 
   124 	cbuf = buf;
   125 	switch (bits) {
   126 	case 512:
   127 		params->dh_512 = d2i_DHparams(NULL, &cbuf, len);
   128 		break;
   129 	case 1024:
   130 		params->dh_1024 = d2i_DHparams(NULL, &cbuf, len);
   131 		break;
   132 	default:
   133 		ssl_params_corrupted(params->fname);
   134 	}
   135 
   136 	i_free(buf);
   137 	return TRUE;
   138 }
   139 
   140 static void ssl_free_parameters(struct ssl_parameters *params)
   141 {
   142 	if (params->dh_512 != NULL) {
   143 		DH_free(params->dh_512);
   144                 params->dh_512 = NULL;
   145 	}
   146 	if (params->dh_1024 != NULL) {
   147 		DH_free(params->dh_1024);
   148                 params->dh_1024 = NULL;
   149 	}
   150 }
   151 
   152 static void ssl_read_parameters(struct ssl_parameters *params)
   153 {
   154 	struct stat st;
   155 	ssize_t ret;
   156 	char c;
   157 	bool warned = FALSE;
   158 
   159 	/* we'll wait until parameter file exists */
   160 	for (;;) {
   161 		params->fd = open(params->fname, O_RDONLY);
   162 		if (params->fd != -1)
   163 			break;
   164 
   165 		if (errno != ENOENT) {
   166 			i_fatal("Can't open SSL parameter file %s: %m",
   167 				params->fname);
   168 		}
   169 
   170 		if (!warned) {
   171 			i_warning("Waiting for SSL parameter file %s",
   172 				  params->fname);
   173 			warned = TRUE;
   174 		}
   175 		sleep(1);
   176 	}
   177 
   178 	if (fstat(params->fd, &st) < 0)
   179 		i_error("fstat(%s) failed: %m", params->fname);
   180 	else
   181 		params->last_mtime = st.st_mtime;
   182 
   183 	ssl_free_parameters(params);
   184 	while (read_dh_parameters_next(params)) ;
   185 
   186 	if ((ret = read_full(params->fd, &c, 1)) < 0)
   187 		i_fatal("read(%s) failed: %m", params->fname);
   188 	else if (ret != 0) {
   189 		/* more data than expected */
   190 		ssl_params_corrupted(params->fname);
   191 	}
   192 
   193 	if (close(params->fd) < 0)
   194 		i_error("close() failed: %m");
   195 	params->fd = -1;
   196 }
   197 
   198 static void ssl_refresh_parameters(struct ssl_parameters *params)
   199 {
   200 	struct stat st;
   201 
   202 	if (params->last_check > ioloop_time - SSL_PARAMFILE_CHECK_INTERVAL)
   203 		return;
   204 	params->last_check = ioloop_time;
   205 
   206 	if (params->last_mtime == 0)
   207 		ssl_read_parameters(params);
   208 	else {
   209 		if (stat(params->fname, &st) < 0)
   210 			i_error("stat(%s) failed: %m", params->fname);
   211 		else if (st.st_mtime != params->last_mtime)
   212 			ssl_read_parameters(params);
   213 	}
   214 }
   215 
   216 static void ssl_set_io(struct ssl_proxy *proxy, enum ssl_io_action action)
   217 {
   218 	switch (action) {
   219 	case SSL_ADD_INPUT:
   220 		if (proxy->io_ssl_read != NULL)
   221 			break;
   222 		proxy->io_ssl_read = io_add(proxy->fd_ssl, IO_READ,
   223 					    ssl_step, proxy);
   224 		break;
   225 	case SSL_REMOVE_INPUT:
   226 		if (proxy->io_ssl_read != NULL)
   227 			io_remove(&proxy->io_ssl_read);
   228 		break;
   229 	case SSL_ADD_OUTPUT:
   230 		if (proxy->io_ssl_write != NULL)
   231 			break;
   232 		proxy->io_ssl_write = io_add(proxy->fd_ssl, IO_WRITE,
   233 					     ssl_step, proxy);
   234 		break;
   235 	case SSL_REMOVE_OUTPUT:
   236 		if (proxy->io_ssl_write != NULL)
   237 			io_remove(&proxy->io_ssl_write);
   238 		break;
   239 	}
   240 }
   241 
   242 static void plain_block_input(struct ssl_proxy *proxy, bool block)
   243 {
   244 	if (block) {
   245 		if (proxy->io_plain_read != NULL)
   246 			io_remove(&proxy->io_plain_read);
   247 	} else {
   248 		if (proxy->io_plain_read == NULL) {
   249 			proxy->io_plain_read = io_add(proxy->fd_plain, IO_READ,
   250 						      plain_read, proxy);
   251 		}
   252 	}
   253 }
   254 
   255 static void plain_read(struct ssl_proxy *proxy)
   256 {
   257 	ssize_t ret;
   258 	bool corked = FALSE;
   259 
   260 	if (proxy->sslout_size == sizeof(proxy->sslout_buf)) {
   261 		/* buffer full, block input until it's written */
   262 		plain_block_input(proxy, TRUE);
   263 		return;
   264 	}
   265 
   266 	proxy->refcount++;
   267 
   268 	while (proxy->sslout_size < sizeof(proxy->sslout_buf) &&
   269 	       !proxy->destroyed) {
   270 		ret = net_receive(proxy->fd_plain,
   271 				  proxy->sslout_buf + proxy->sslout_size,
   272 				  sizeof(proxy->sslout_buf) -
   273 				  proxy->sslout_size);
   274 		if (ret <= 0) {
   275 			if (ret < 0)
   276 				ssl_proxy_destroy(proxy);
   277 			break;
   278 		} else {
   279 			proxy->sslout_size += ret;
   280 			if (!corked) {
   281 				net_set_cork(proxy->fd_ssl, TRUE);
   282 				corked = TRUE;
   283 			}
   284 			ssl_write(proxy);
   285 		}
   286 	}
   287 
   288 	if (corked)
   289 		net_set_cork(proxy->fd_ssl, FALSE);
   290 
   291 	ssl_proxy_unref(proxy);
   292 }
   293 
   294 static void plain_write(struct ssl_proxy *proxy)
   295 {
   296 	ssize_t ret;
   297 
   298 	proxy->refcount++;
   299 
   300 	ret = net_transmit(proxy->fd_plain, proxy->plainout_buf,
   301 			   proxy->plainout_size);
   302 	if (ret < 0)
   303 		ssl_proxy_destroy(proxy);
   304 	else {
   305 		proxy->plainout_size -= ret;
   306 		memmove(proxy->plainout_buf, proxy->plainout_buf + ret,
   307 			proxy->plainout_size);
   308 
   309 		if (proxy->plainout_size > 0) {
   310 			if (proxy->io_plain_write == NULL) {
   311 				proxy->io_plain_write =
   312 					io_add(proxy->fd_plain, IO_WRITE,
   313 					       plain_write, proxy);
   314 			}
   315 		} else {
   316 			if (proxy->io_plain_write != NULL)
   317 				io_remove(&proxy->io_plain_write);
   318 		}
   319 
   320 		ssl_set_io(proxy, SSL_ADD_INPUT);
   321 		if (SSL_pending(proxy->ssl) > 0)
   322 			ssl_read(proxy);
   323 	}
   324 
   325 	ssl_proxy_unref(proxy);
   326 }
   327 
   328 static const char *ssl_last_error(void)
   329 {
   330 	unsigned long err;
   331 	char *buf;
   332 	size_t err_size = 256;
   333 
   334 	err = ERR_get_error();
   335 	if (err == 0) {
   336 		if (errno != 0)
   337 			return strerror(errno);
   338 		return "Unknown error";
   339 	}
   340 
   341 	buf = t_malloc(err_size);
   342 	buf[err_size-1] = '\0';
   343 	ERR_error_string_n(err, buf, err_size-1);
   344 	return buf;
   345 }
   346 
   347 static void ssl_handle_error(struct ssl_proxy *proxy, int ret,
   348 			     const char *func_name)
   349 {
   350 	const char *errstr = NULL;
   351 	int err;
   352 
   353 	proxy->refcount++;
   354 
   355 	i_free_and_null(proxy->last_error);
   356 	err = SSL_get_error(proxy->ssl, ret);
   357 
   358 	switch (err) {
   359 	case SSL_ERROR_WANT_READ:
   360 		ssl_set_io(proxy, SSL_ADD_INPUT);
   361 		break;
   362 	case SSL_ERROR_WANT_WRITE:
   363 		ssl_set_io(proxy, SSL_ADD_OUTPUT);
   364 		break;
   365 	case SSL_ERROR_SYSCALL:
   366 		/* eat up the error queue */
   367 		if (ERR_peek_error() != 0)
   368 			errstr = ssl_last_error();
   369 		else if (ret != 0)
   370 			errstr = strerror(errno);
   371 		else {
   372 			/* EOF. */
   373 			errstr = "Disconnected";
   374 			break;
   375 		}
   376 		errstr = t_strdup_printf("%s syscall failed: %s",
   377 					 func_name, errstr);
   378 		break;
   379 	case SSL_ERROR_ZERO_RETURN:
   380 		/* clean connection closing */
   381 		ssl_proxy_destroy(proxy);
   382 		break;
   383 	case SSL_ERROR_SSL:
   384 		if (ERR_GET_REASON(ERR_peek_error()) == ERR_R_MALLOC_FAILURE) {
   385 			i_error("OpenSSL malloc() failed. "
   386 				"You may need to increase login_process_size");
   387 		}
   388 		errstr = t_strdup_printf("%s failed: %s",
   389 					 func_name, ssl_last_error());
   390 		break;
   391 	default:
   392 		errstr = t_strdup_printf("%s failed: unknown failure %d (%s)",
   393 					 func_name, err, ssl_last_error());
   394 		break;
   395 	}
   396 
   397 	if (errstr != NULL) {
   398 		proxy->last_error = i_strdup(errstr);
   399 		ssl_proxy_destroy(proxy);
   400 	}
   401 	ssl_proxy_unref(proxy);
   402 }
   403 
   404 static void ssl_handshake(struct ssl_proxy *proxy)
   405 {
   406 	int ret;
   407 
   408 	if (proxy->client) {
   409 		ret = SSL_connect(proxy->ssl);
   410 		if (ret != 1) {
   411 			ssl_handle_error(proxy, ret, "SSL_connect()");
   412 			return;
   413 		}
   414 	} else {
   415 		ret = SSL_accept(proxy->ssl);
   416 		if (ret != 1) {
   417 			ssl_handle_error(proxy, ret, "SSL_accept()");
   418 			return;
   419 		}
   420 	}
   421 	i_free_and_null(proxy->last_error);
   422 	proxy->handshaked = TRUE;
   423 
   424 	ssl_set_io(proxy, SSL_ADD_INPUT);
   425 	plain_block_input(proxy, FALSE);
   426 
   427 	if (proxy->handshake_callback != NULL) {
   428 		if (proxy->handshake_callback(proxy->handshake_context) < 0)
   429 			ssl_proxy_destroy(proxy);
   430 	}
   431 }
   432 
   433 static void ssl_read(struct ssl_proxy *proxy)
   434 {
   435 	int ret;
   436 
   437 	while (proxy->plainout_size < sizeof(proxy->plainout_buf) &&
   438 	       !proxy->destroyed) {
   439 		ret = SSL_read(proxy->ssl,
   440 			       proxy->plainout_buf + proxy->plainout_size,
   441 			       sizeof(proxy->plainout_buf) -
   442 			       proxy->plainout_size);
   443 		if (ret <= 0) {
   444 			ssl_handle_error(proxy, ret, "SSL_read()");
   445 			break;
   446 		} else {
   447 			i_free_and_null(proxy->last_error);
   448 			proxy->plainout_size += ret;
   449 			plain_write(proxy);
   450 		}
   451 	}
   452 }
   453 
   454 static void ssl_write(struct ssl_proxy *proxy)
   455 {
   456 	int ret;
   457 
   458 	ret = SSL_write(proxy->ssl, proxy->sslout_buf, proxy->sslout_size);
   459 	if (ret <= 0)
   460 		ssl_handle_error(proxy, ret, "SSL_write()");
   461 	else {
   462 		i_free_and_null(proxy->last_error);
   463 		proxy->sslout_size -= ret;
   464 		memmove(proxy->sslout_buf, proxy->sslout_buf + ret,
   465 			proxy->sslout_size);
   466 
   467 		ssl_set_io(proxy, proxy->sslout_size > 0 ?
   468 			   SSL_ADD_OUTPUT : SSL_REMOVE_OUTPUT);
   469 		plain_block_input(proxy, FALSE);
   470 	}
   471 }
   472 
   473 static void ssl_step(struct ssl_proxy *proxy)
   474 {
   475 	proxy->refcount++;
   476 
   477 	if (!proxy->handshaked)
   478 		ssl_handshake(proxy);
   479 
   480 	if (proxy->handshaked) {
   481 		if (proxy->plainout_size == sizeof(proxy->plainout_buf))
   482 			ssl_set_io(proxy, SSL_REMOVE_INPUT);
   483 		else
   484 			ssl_read(proxy);
   485 
   486 		if (proxy->sslout_size == 0)
   487 			ssl_set_io(proxy, SSL_REMOVE_OUTPUT);
   488 		else {
   489 			net_set_cork(proxy->fd_ssl, TRUE);
   490 			ssl_write(proxy);
   491 			net_set_cork(proxy->fd_ssl, FALSE);
   492 		}
   493 	}
   494 
   495 	ssl_proxy_unref(proxy);
   496 }
   497 
   498 static int ssl_proxy_new_common(SSL_CTX *ssl_ctx, int fd, struct ip_addr *ip,
   499 				struct ssl_proxy **proxy_r)
   500 {
   501 	struct ssl_proxy *proxy;
   502 	SSL *ssl;
   503 	int sfd[2];
   504 
   505 	i_assert(fd != -1);
   506 
   507 	*proxy_r = NULL;
   508 
   509 	if (!ssl_initialized) {
   510 		i_error("SSL support not enabled in configuration");
   511 		return -1;
   512 	}
   513 
   514 	ssl_refresh_parameters(&ssl_params);
   515 
   516 	ssl = SSL_new(ssl_ctx);
   517 	if (ssl == NULL) {
   518 		i_error("SSL_new() failed: %s", ssl_last_error());
   519 		return -1;
   520 	}
   521 
   522 	if (SSL_set_fd(ssl, fd) != 1) {
   523 		i_error("SSL_set_fd() failed: %s", ssl_last_error());
   524 		SSL_free(ssl);
   525 		return -1;
   526 	}
   527 
   528 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0) {
   529 		i_error("socketpair() failed: %m");
   530 		SSL_free(ssl);
   531 		return -1;
   532 	}
   533 
   534 	net_set_nonblock(sfd[0], TRUE);
   535 	net_set_nonblock(sfd[1], TRUE);
   536 	net_set_nonblock(fd, TRUE);
   537 
   538 	proxy = i_new(struct ssl_proxy, 1);
   539 	proxy->refcount = 2;
   540 	proxy->ssl = ssl;
   541 	proxy->fd_ssl = fd;
   542 	proxy->fd_plain = sfd[0];
   543 	proxy->ip = *ip;
   544         SSL_set_ex_data(ssl, extdata_index, proxy);
   545 
   546 	ssl_proxy_count++;
   547 	DLLIST_PREPEND(&ssl_proxies, proxy);
   548 
   549 	main_ref();
   550 
   551 	*proxy_r = proxy;
   552 	return sfd[1];
   553 }
   554 
   555 int ssl_proxy_new(int fd, struct ip_addr *ip, struct ssl_proxy **proxy_r)
   556 {
   557 	int ret;
   558 
   559 	if ((ret = ssl_proxy_new_common(ssl_server_ctx, fd, ip, proxy_r)) < 0)
   560 		return -1;
   561 
   562 	ssl_step(*proxy_r);
   563 	return ret;
   564 }
   565 
   566 int ssl_proxy_client_new(int fd, struct ip_addr *ip,
   567 			 ssl_handshake_callback_t *callback, void *context,
   568 			 struct ssl_proxy **proxy_r)
   569 {
   570 	int ret;
   571 
   572 	if ((ret = ssl_proxy_new_common(ssl_client_ctx, fd, ip, proxy_r)) < 0)
   573 		return -1;
   574 
   575 	(*proxy_r)->handshake_callback = callback;
   576 	(*proxy_r)->handshake_context = context;
   577 	(*proxy_r)->client = TRUE;
   578 	ssl_step(*proxy_r);
   579 	return ret;
   580 }
   581 
   582 bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy)
   583 {
   584 	return proxy->cert_received && !proxy->cert_broken;
   585 }
   586 
   587 bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy)
   588 {
   589 	return proxy->cert_received && proxy->cert_broken;
   590 }
   591 
   592 const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy)
   593 {
   594 	X509 *x509;
   595 	char *name;
   596 	int len;
   597 
   598 	if (!ssl_proxy_has_valid_client_cert(proxy))
   599 		return NULL;
   600 
   601 	x509 = SSL_get_peer_certificate(proxy->ssl);
   602 	if (x509 == NULL)
   603 		return NULL; /* we should have had it.. */
   604 
   605 	len = X509_NAME_get_text_by_NID(X509_get_subject_name(x509),
   606 					ssl_username_nid, NULL, 0);
   607 	if (len < 0)
   608 		name = "";
   609 	else {
   610 		name = t_malloc(len + 1);
   611 		if (X509_NAME_get_text_by_NID(X509_get_subject_name(x509),
   612 					ssl_username_nid, name, len + 1) < 0)
   613 			name = "";
   614 		else if (strlen(name) != (size_t)len) {
   615 			/* NUL characters in name. Someone's trying to fake
   616 			   being another user? Don't allow it. */
   617 			name = "";
   618 		}
   619 	}
   620 	X509_free(x509);
   621 	
   622 	return *name == '\0' ? NULL : name;
   623 }
   624 
   625 bool ssl_proxy_is_handshaked(const struct ssl_proxy *proxy)
   626 {
   627 	return proxy->handshaked;
   628 }
   629 
   630 const char *ssl_proxy_get_last_error(const struct ssl_proxy *proxy)
   631 {
   632 	return proxy->last_error;
   633 }
   634 
   635 const char *ssl_proxy_get_security_string(struct ssl_proxy *proxy)
   636 {
   637 	SSL_CIPHER *cipher;
   638 #ifdef HAVE_SSL_COMPRESSION
   639 	const COMP_METHOD *comp;
   640 #endif
   641 	int bits, alg_bits;
   642 	const char *comp_str;
   643 
   644 	if (!proxy->handshaked)
   645 		return "";
   646 
   647 	cipher = SSL_get_current_cipher(proxy->ssl);
   648 	bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
   649 #ifdef HAVE_SSL_COMPRESSION
   650 	comp = SSL_get_current_compression(proxy->ssl);
   651 	comp_str = comp == NULL ? "" :
   652 		t_strconcat(" ", SSL_COMP_get_name(comp), NULL);
   653 #else
   654 	comp_str = NULL;
   655 #endif
   656 	return t_strdup_printf("%s with cipher %s (%d/%d bits)%s",
   657 			       SSL_get_version(proxy->ssl),
   658 			       SSL_CIPHER_get_name(cipher),
   659 			       bits, alg_bits, comp_str);
   660 }
   661 
   662 void ssl_proxy_free(struct ssl_proxy *proxy)
   663 {
   664 	ssl_proxy_unref(proxy);
   665 }
   666 
   667 static void ssl_proxy_unref(struct ssl_proxy *proxy)
   668 {
   669 	if (--proxy->refcount > 0)
   670 		return;
   671 	i_assert(proxy->refcount == 0);
   672 
   673 	SSL_free(proxy->ssl);
   674 	i_free(proxy);
   675 
   676 	main_unref();
   677 }
   678 
   679 static void ssl_proxy_destroy(struct ssl_proxy *proxy)
   680 {
   681 	if (proxy->destroyed)
   682 		return;
   683 	proxy->destroyed = TRUE;
   684 
   685 	ssl_proxy_count--;
   686 	DLLIST_REMOVE(&ssl_proxies, proxy);
   687 
   688 	if (proxy->io_ssl_read != NULL)
   689 		io_remove(&proxy->io_ssl_read);
   690 	if (proxy->io_ssl_write != NULL)
   691 		io_remove(&proxy->io_ssl_write);
   692 	if (proxy->io_plain_read != NULL)
   693 		io_remove(&proxy->io_plain_read);
   694 	if (proxy->io_plain_write != NULL)
   695 		io_remove(&proxy->io_plain_write);
   696 
   697 	(void)SSL_shutdown(proxy->ssl);
   698 
   699 	(void)net_disconnect(proxy->fd_ssl);
   700 	(void)net_disconnect(proxy->fd_plain);
   701 
   702 	ssl_proxy_unref(proxy);
   703 
   704 	main_listen_start();
   705 }
   706 
   707 static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED,
   708 			    int is_export ATTR_UNUSED, int keylength)
   709 {
   710 	return RSA_generate_key(keylength, RSA_F4, NULL, NULL);
   711 }
   712 
   713 static DH *ssl_tmp_dh_callback(SSL *ssl ATTR_UNUSED,
   714 			       int is_export, int keylength)
   715 {
   716 	/* Well, I'm not exactly sure why the logic in here is this.
   717 	   It's the same as in Postfix, so it can't be too wrong. */
   718 	if (is_export && keylength == 512 && ssl_params.dh_512 != NULL)
   719 		return ssl_params.dh_512;
   720 
   721 	return ssl_params.dh_1024;
   722 }
   723 
   724 static void ssl_info_callback(const SSL *ssl, int where, int ret)
   725 {
   726 	struct ssl_proxy *proxy;
   727 
   728 	proxy = SSL_get_ex_data(ssl, extdata_index);
   729 
   730 	if ((where & SSL_CB_ALERT) != 0) {
   731 		i_warning("SSL alert: where=0x%x, ret=%d: %s %s [%s]",
   732 			  where, ret, SSL_alert_type_string_long(ret),
   733 			  SSL_alert_desc_string_long(ret),
   734 			  net_ip2addr(&proxy->ip));
   735 	} else {
   736 		i_warning("SSL BIO failed: where=0x%x, ret=%d: %s [%s]",
   737 			  where, ret, SSL_state_string_long(ssl),
   738 			  net_ip2addr(&proxy->ip));
   739 	}
   740 }
   741 
   742 static int ssl_verify_client_cert(int preverify_ok, X509_STORE_CTX *ctx)
   743 {
   744 	SSL *ssl;
   745         struct ssl_proxy *proxy;
   746 
   747 	ssl = X509_STORE_CTX_get_ex_data(ctx,
   748 					 SSL_get_ex_data_X509_STORE_CTX_idx());
   749 	proxy = SSL_get_ex_data(ssl, extdata_index);
   750 	proxy->cert_received = TRUE;
   751 
   752 	if (verbose_ssl || (verbose_auth && !preverify_ok)) {
   753 		char buf[1024];
   754 		X509_NAME *subject;
   755 
   756 		subject = X509_get_subject_name(ctx->current_cert);
   757 		(void)X509_NAME_oneline(subject, buf, sizeof(buf));
   758 		buf[sizeof(buf)-1] = '\0'; /* just in case.. */
   759 		if (!preverify_ok)
   760 			i_info("Invalid certificate: %s: %s", X509_verify_cert_error_string(ctx->error),buf);
   761 		else
   762 			i_info("Valid certificate: %s", buf);
   763 	}
   764 	if (!preverify_ok)
   765 		proxy->cert_broken = TRUE;
   766 
   767 	/* Return success anyway, because if ssl_require_client_cert=no we
   768 	   could still allow authentication. */
   769 	return 1;
   770 }
   771 
   772 static int
   773 pem_password_callback(char *buf, int size, int rwflag ATTR_UNUSED,
   774 		      void *userdata)
   775 {
   776 	if (userdata == NULL) {
   777 		i_error("SSL private key file is password protected, "
   778 			"but password isn't given");
   779 		return 0;
   780 	}
   781 
   782 	if (i_strocpy(buf, userdata, size) < 0)
   783 		return 0;
   784 	return strlen(buf);
   785 }
   786 
   787 unsigned int ssl_proxy_get_count(void)
   788 {
   789 	return ssl_proxy_count;
   790 }
   791 
   792 static bool is_pem_key_file(const char *path)
   793 {
   794 	char buf[4096];
   795 	int fd, ret;
   796 
   797 	/* this code is used only for giving a better error message,
   798 	   so it needs to catch only the normal key files */
   799 	fd = open(path, O_RDONLY);
   800 	if (fd == -1)
   801 		return FALSE;
   802 	ret = read(fd, buf, sizeof(buf)-1);
   803 	close(fd);
   804 	if (ret <= 0)
   805 		return FALSE;
   806 	buf[ret] = '\0';
   807 	return strstr(buf, "PRIVATE KEY---") != NULL;
   808 }
   809 
   810 static void ssl_proxy_ctx_init(SSL_CTX *ssl_ctx)
   811 {
   812 	const char *cafile;
   813 
   814 	SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
   815 
   816 	cafile = getenv("SSL_CA_FILE");
   817 	if (cafile != NULL) {
   818 		if (SSL_CTX_load_verify_locations(ssl_ctx, cafile, NULL) != 1) {
   819 			i_fatal("Can't load CA file %s: %s",
   820 				cafile, ssl_last_error());
   821 		}
   822 	}
   823 	if (verbose_ssl)
   824 		SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback);
   825 	if (SSL_CTX_need_tmp_RSA(ssl_ctx))
   826 		SSL_CTX_set_tmp_rsa_callback(ssl_ctx, ssl_gen_rsa_key);
   827 	SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_tmp_dh_callback);
   828 }
   829 
   830 static void ssl_proxy_ctx_verify_client(SSL_CTX *ssl_ctx)
   831 {
   832 	const char *cafile;
   833 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
   834 	X509_STORE *store;
   835 
   836 	store = SSL_CTX_get_cert_store(ssl_ctx);
   837 	X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
   838 			     X509_V_FLAG_CRL_CHECK_ALL);
   839 #endif
   840 	cafile = getenv("SSL_CA_FILE");
   841 	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
   842 			   ssl_verify_client_cert);
   843 	SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(cafile));
   844 }
   845 
   846 static void ssl_proxy_init_server(const char *certfile, const char *keyfile)
   847 {
   848 	const char *cipher_list, *username_field;
   849 	char *password;
   850 	unsigned long err;
   851 
   852 	password = getenv("SSL_KEY_PASSWORD");
   853 
   854 	if ((ssl_server_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL)
   855 		i_fatal("SSL_CTX_new() failed");
   856 	ssl_proxy_ctx_init(ssl_server_ctx);
   857 
   858 	cipher_list = getenv("SSL_CIPHER_LIST");
   859 	if (cipher_list == NULL)
   860 		cipher_list = DOVECOT_SSL_DEFAULT_CIPHER_LIST;
   861 	if (SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list) != 1) {
   862 		i_fatal("Can't set cipher list to '%s': %s",
   863 			cipher_list, ssl_last_error());
   864 	}
   865 
   866 	if (SSL_CTX_use_certificate_chain_file(ssl_server_ctx, certfile) != 1) {
   867 		err = ERR_peek_error();
   868 		if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
   869 		    ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
   870 			i_fatal("Can't load certificate file %s: %s",
   871 				certfile, ssl_last_error());
   872 		} else if (is_pem_key_file(certfile)) {
   873 			i_fatal("Can't load certificate file %s: "
   874 				"The file contains a private key "
   875 				"(you've mixed ssl_cert_file and ssl_key_file settings)",
   876 				certfile);
   877 		} else {
   878 			i_fatal("Can't load certificate file %s: "
   879 				"The file doesn't contain a certificate.",
   880 				certfile);
   881 		}
   882 	}
   883 
   884         SSL_CTX_set_default_passwd_cb(ssl_server_ctx, pem_password_callback);
   885         SSL_CTX_set_default_passwd_cb_userdata(ssl_server_ctx, password);
   886 	if (SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile,
   887 					SSL_FILETYPE_PEM) != 1) {
   888 		err = ERR_peek_error();
   889 		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
   890 		    ERR_GET_REASON(err) == X509_R_KEY_VALUES_MISMATCH) {
   891 			i_fatal("Can't load private key file %s: "
   892 				"Key is for a different cert than %s",
   893 				keyfile, certfile);
   894 		} else {
   895 			i_fatal("Can't load private key file %s: %s",
   896 				keyfile, ssl_last_error());
   897 		}
   898 	}
   899 
   900 	if (getenv("SSL_VERIFY_CLIENT_CERT") != NULL)
   901 		ssl_proxy_ctx_verify_client(ssl_server_ctx);
   902 
   903 	username_field = getenv("SSL_CERT_USERNAME_FIELD");
   904 	if (username_field == NULL)
   905 		ssl_username_nid = NID_commonName;
   906 	else {
   907 		ssl_username_nid = OBJ_txt2nid(username_field);
   908 		if (ssl_username_nid == NID_undef) {
   909 			i_fatal("Invalid ssl_cert_username_field: %s",
   910 				username_field);
   911 		}
   912 	}
   913 }
   914 
   915 static void ssl_proxy_init_client(void)
   916 {
   917 	if ((ssl_client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
   918 		i_fatal("SSL_CTX_new() failed");
   919 	ssl_proxy_ctx_init(ssl_client_ctx);
   920 	ssl_proxy_ctx_verify_client(ssl_client_ctx);
   921 }
   922 
   923 void ssl_proxy_init(void)
   924 {
   925 	static char dovecot[] = "dovecot";
   926 	const char *certfile, *keyfile;
   927 	unsigned char buf;
   928 
   929 	memset(&ssl_params, 0, sizeof(ssl_params));
   930 
   931 	certfile = getenv("SSL_CERT_FILE");
   932 	keyfile = getenv("SSL_KEY_FILE");
   933 	ssl_params.fname = getenv("SSL_PARAM_FILE");
   934 
   935 	if (certfile == NULL || keyfile == NULL || ssl_params.fname == NULL) {
   936 		/* SSL support is disabled */
   937 		return;
   938 	}
   939 
   940 	SSL_library_init();
   941 	SSL_load_error_strings();
   942 
   943 	extdata_index = SSL_get_ex_new_index(0, dovecot, NULL, NULL, NULL);
   944 	ssl_proxy_init_server(certfile, keyfile);
   945 	ssl_proxy_init_client();
   946 
   947 	/* PRNG initialization might want to use /dev/urandom, make sure it
   948 	   does it before chrooting. We might not have enough entropy at
   949 	   the first try, so this function may fail. It's still been
   950 	   initialized though. */
   951 	(void)RAND_bytes(&buf, 1);
   952 
   953 	ssl_proxy_count = 0;
   954         ssl_proxies = NULL;
   955 	ssl_initialized = TRUE;
   956 }
   957 
   958 void ssl_proxy_deinit(void)
   959 {
   960 	if (!ssl_initialized)
   961 		return;
   962 
   963 	while (ssl_proxies != NULL)
   964 		ssl_proxy_destroy(ssl_proxies);
   965 
   966 	ssl_free_parameters(&ssl_params);
   967 	SSL_CTX_free(ssl_server_ctx);
   968 	SSL_CTX_free(ssl_client_ctx);
   969 	EVP_cleanup();
   970 	ERR_free_strings();
   971 }
   972 
   973 #endif