ssl-proxy-openssl.c revision cca4ba2a504d70a9fe9fee37f8433997359de52c
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen/* Check every 30 minutes if parameters file has been updated */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME /* FIXME: this may be unnecessary.. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct master_service_ssl_settings *ssl_set;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct io *io_ssl_read, *io_ssl_write, *io_plain_read, *io_plain_write;
894987bf45718f8849cc3898afdfb1ac3cfa2445Timo Sirainen const char *key;
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainen const char *ca;
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainenstatic unsigned int ssl_proxy_count;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void plain_read(struct ssl_proxy *proxy);
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainenstatic void ssl_write(struct ssl_proxy *proxy);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void ssl_proxy_destroy(struct ssl_proxy *proxy);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void ssl_proxy_unref(struct ssl_proxy *proxy);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenssl_server_context_init(const struct login_settings *login_set,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct master_service_ssl_settings *ssl_set);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void ssl_server_context_deinit(struct ssl_server_context **_ctx);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic unsigned int ssl_server_context_hash(const struct ssl_server_context *ctx)
a928e7efabb1672b1476e597106d4b4b81ac6f3cTimo Sirainen unsigned int i, g, h = 0;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen /* checking for different certs is typically good enough,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen and it should be enough to check only the first few bytes. */
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen for (i = 0; i < 16 && ctx->cert[i] != '\0'; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((g = h & 0xf0000000UL)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen h = h ^ (g >> 24);
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainenstatic int ssl_server_context_cmp(const struct ssl_server_context *ctx1,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (null_strcmp(ctx1->cipher_list, ctx2->cipher_list) != 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (null_strcmp(ctx1->protocols, ctx2->protocols) != 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return ctx1->verify_client_cert == ctx2->verify_client_cert ? 0 : 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_fatal("Corrupted SSL parameters file in state_dir: ssl-parameters.dat");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void read_next(struct ssl_parameters *params, void *data, size_t size)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if ((ret = read_full(params->fd, data, size)) < 0)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenstatic bool read_dh_parameters_next(struct ssl_parameters *params)
c680a6b35b459045e92814778908da5a93922107Timo Sirainen unsigned char *buf;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen const unsigned char *cbuf;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen unsigned int len;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* read bit size. 0 ends the DH parameters list. */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen /* read data size. */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen params->dh_512 = d2i_DHparams(NULL, &cbuf, len);
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen params->dh_1024 = d2i_DHparams(NULL, &cbuf, len);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenstatic void ssl_free_parameters(struct ssl_parameters *params)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void ssl_refresh_parameters(struct ssl_parameters *params)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (params->last_refresh > ioloop_time - SSL_PARAMFILE_CHECK_INTERVAL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_error("connect(%s) failed: %m", params->path);
else if (ret != 0) {
switch (action) {
case SSL_ADD_INPUT:
case SSL_REMOVE_INPUT:
case SSL_ADD_OUTPUT:
case SSL_REMOVE_OUTPUT:
if (block) {
if (ret <= 0) {
if (ret < 0)
if (!corked) {
if (corked)
if (ret < 0)
const char *ret;
char *buf;
return ret;
static const char *ssl_last_error(void)
unsigned long err;
const char *data;
int flags;
if (err == 0) {
if (errno != 0)
const char *func_name)
int err;
switch (err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_SYSCALL:
if (ERR_peek_error() != 0)
else if (ret != 0)
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_SSL:
int ret;
int ret;
if (ret <= 0) {
int ret;
if (ret <= 0)
if (!ssl_initialized) {
static struct ssl_server_context *
return ctx;
int ret;
if (ret < 0)
return ret;
char *name;
int len;
return NULL;
if (len < 0)
const char *comp_str;
#ifdef HAVE_SSL_COMPRESSION
return NULL;
} else if (ret == 0) {
if (!preverify_ok)
if (preverify_ok)
void *userdata)
unsigned int ssl_proxy_get_count(void)
return ssl_proxy_count;
bool load_xnames)
#ifdef SSL_MODE_RELEASE_BUFFERS
return xnames;
unsigned long err;
return ssl_last_error();
static const char *ssl_key_load_error(void)
return ssl_last_error();
char *dup_password;
return pkey;
const char *password;
X509 *x;
int ret = 0;
if (x == NULL)
goto end;
if (ERR_peek_error() != 0)
ret = 0;
if (ret != 0) {
unsigned long err;
ret = 0;
goto end;
end:
return ret;
#ifdef HAVE_SSL_GET_SERVERNAME
const char *host;
void **other_sets;
&other_sets);
static struct ssl_server_context *
#ifdef HAVE_SSL_GET_SERVERNAME
return ctx;
void ssl_proxy_init(void)
unsigned char buf;
ssl_proxy_count = 0;
void ssl_proxy_deinit(void)
if (!ssl_initialized)
EVP_cleanup();