ssl-proxy-openssl.c revision 4ead43ecc06d10047998966c4dc0b142ecce4b66
/* Copyright (C) 2002 Timo Sirainen */
#include "common.h"
#include "array.h"
#include "ioloop.h"
#include "network.h"
#include "ostream.h"
#include "read-full.h"
#include "hash.h"
#include "ssl-proxy.h"
#include <fcntl.h>
#include <unistd.h>
#ifdef HAVE_OPENSSL
#define DOVECOT_SSL_DEFAULT_CIPHER_LIST "ALL:!LOW"
/* Check every 30 minutes if parameters file has been updated */
enum ssl_io_action {
};
struct ssl_proxy {
int refcount;
unsigned char plainout_buf[1024];
unsigned int plainout_size;
unsigned char sslout_buf[1024];
unsigned int sslout_size;
unsigned int handshaked:1;
unsigned int destroyed:1;
unsigned int cert_received:1;
unsigned int cert_broken:1;
};
struct ssl_parameters {
const char *fname;
int fd;
};
static int extdata_index;
static struct hash_table *ssl_proxies;
static struct ssl_parameters ssl_params;
static void plain_read(void *context);
{
int ret;
if (ret == 0)
}
{
unsigned char *buf;
const unsigned char *cbuf;
unsigned int len;
int bits;
/* read bit size. 0 ends the DH parameters list. */
if (bits == 0)
return FALSE;
/* read data size. */
switch (bits) {
case 512:
break;
case 1024:
break;
}
return TRUE;
}
{
}
}
}
{
/* we'll wait until parameter file exists */
for (;;) {
break;
i_fatal("Can't open SSL parameter file %s: %m",
}
if (!warned) {
i_warning("Waiting for SSL parameter file %s",
}
sleep(1);
}
else
while (read_dh_parameters_next(params)) ;
i_error("close() failed: %m");
}
{
return;
if (params->last_mtime == 0)
else {
}
}
{
switch (action) {
case SSL_ADD_INPUT:
break;
break;
case SSL_REMOVE_INPUT:
break;
case SSL_ADD_OUTPUT:
break;
break;
case SSL_REMOVE_OUTPUT:
break;
}
}
{
if (block) {
} else {
plain_read, proxy);
}
}
}
static void plain_read(void *context)
{
/* buffer full, block input until it's written */
return;
}
sizeof(proxy->sslout_buf) -
proxy->sslout_size);
if (ret <= 0) {
if (ret < 0)
break;
} else {
if (!corked) {
}
}
}
if (corked)
}
static void plain_write(void *context)
{
if (ret < 0)
else {
if (proxy->plainout_size > 0) {
plain_write, proxy);
}
} else {
}
}
}
static const char *ssl_last_error(void)
{
unsigned long err;
char *buf;
err = ERR_get_error();
if (err == 0)
return buf;
}
const char *func_name)
{
const char *errstr;
int err;
switch (err) {
case SSL_ERROR_WANT_READ:
break;
case SSL_ERROR_WANT_WRITE:
break;
case SSL_ERROR_SYSCALL:
/* eat up the error queue */
if (verbose_ssl) {
if (ERR_peek_error() != 0)
errstr = ssl_last_error();
else {
if (ret == 0)
errstr = "EOF";
else
}
i_warning("%s syscall failed: %s [%s]",
}
break;
case SSL_ERROR_ZERO_RETURN:
/* clean connection closing */
break;
case SSL_ERROR_SSL:
if (verbose_ssl) {
}
break;
default:
i_warning("%s failed: unknown failure %d (%s) [%s]",
break;
}
}
{
int ret;
if (ret != 1)
else {
}
}
{
int ret;
sizeof(proxy->plainout_buf) -
if (ret <= 0) {
break;
} else {
}
}
}
{
int ret;
if (ret <= 0)
else {
proxy->sslout_size);
}
}
{
if (!proxy->handshaked)
if (proxy->handshaked) {
else
if (proxy->sslout_size == 0)
else {
}
}
}
{
int sfd[2];
if (!ssl_initialized) {
i_error("SSL support not enabled in configuration");
return -1;
}
return -1;
}
return -1;
}
i_error("socketpair() failed: %m");
return -1;
}
main_ref();
return sfd[1];
}
{
}
{
char buf[1024];
const char *name;
return NULL;
return NULL; /* we should have had it.. */
name = "";
else
}
{
return proxy->handshaked;
}
{
}
{
return;
main_unref();
}
{
return;
}
{
}
{
/* Well, I'm not exactly sure why the logic in here is this.
It's the same as in Postfix, so it can't be too wrong. */
return ssl_params.dh_512;
return ssl_params.dh_1024;
}
{
if ((where & SSL_CB_ALERT) != 0) {
i_warning("SSL alert: where=0x%x, ret=%d: %s %s [%s]",
} else {
i_warning("SSL BIO failed: where=0x%x, ret=%d: %s [%s]",
}
}
{
char buf[1024];
if (!preverify_ok)
else
}
if (!preverify_ok)
/* Return success anyway, because if ssl_require_client_cert=no we
could still allow authentication. */
return 1;
}
static int
void *userdata)
{
i_error("SSL private key file is password protected, "
"but password isn't given");
return 0;
}
return 0;
}
unsigned int ssl_proxy_get_count(void)
{
}
void ssl_proxy_init(void)
{
char *password;
unsigned char buf;
/* SSL support is disabled */
return;
}
i_fatal("SSL_CTX_new() failed");
if (cipher_list == NULL)
i_fatal("Can't set cipher list to '%s': %s",
}
i_fatal("Can't load CA file %s: %s",
cafile, ssl_last_error());
}
}
i_fatal("Can't load certificate file %s: %s",
certfile, ssl_last_error());
}
SSL_FILETYPE_PEM) != 1) {
i_fatal("Can't load private key file %s: %s",
keyfile, ssl_last_error());
}
if (SSL_CTX_need_tmp_RSA(ssl_ctx))
if (verbose_ssl)
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
#endif
}
does it before chrooting. We might not have enough entropy at
the first try, so this function may fail. It's still been
initialized though. */
}
void ssl_proxy_deinit(void)
{
struct hash_iterate_context *iter;
if (!ssl_initialized)
return;
}
#endif