ssl-proxy-gnutls.c revision 7536dca18968a279b69c685eedda205bee228fd4
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
#include "login-common.h"
#include "ioloop.h"
#include "network.h"
#include "hash.h"
#include "ssl-proxy.h"
#ifdef HAVE_GNUTLS
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <gcrypt.h>
struct ssl_proxy {
int refcount;
int io_ssl_dir;
unsigned char outbuf_plain[1024];
unsigned int outbuf_pos_plain;
};
const int protocol_priority[] =
{ GNUTLS_TLS1, GNUTLS_SSL3, 0 };
const int kx_priority[] =
const int cipher_priority[] =
const int comp_priority[] =
const int mac_priority[] =
{ GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
const int cert_type_priority[] =
{ GNUTLS_CRT_X509, 0 };
static struct hash_table *ssl_proxies;
static gnutls_dh_params dh_params;
static gnutls_rsa_params rsa_params;
{
}
{
if (!gnutls_error_is_fatal(error)) {
if (!verbose_ssl)
return 0;
if (error == GNUTLS_E_WARNING_ALERT_RECEIVED) {
i_warning("Received SSL warning alert: %s [%s]",
} else {
i_warning("Non-fatal SSL error: %s: %s",
}
return 0;
}
if (verbose_ssl) {
/* fatal error occurred */
if (error == GNUTLS_E_FATAL_ALERT_RECEIVED) {
i_warning("Received SSL fatal alert: %s [%s]",
} else {
i_warning("Error reading from SSL client: %s [%s]",
}
}
return -1;
}
{
int rcvd;
if (rcvd > 0)
return rcvd;
/* disconnected, either by nicely telling us that we'll
close the connection, or by simply killing the
connection which gives us the packet length error. */
return -1;
}
}
{
int sent;
if (sent >= 0)
return sent;
/* don't warn about errors related to unexpected
disconnection */
return -1;
}
}
{
return TRUE;
main_unref();
return FALSE;
}
{
int sent;
if (sent < 0) {
/* disconnected */
return;
}
if (proxy->send_left_plain > 0)
return;
/* everything is sent, start reading again */
}
{
sizeof(proxy->outbuf_plain));
if (rcvd <= 0)
return;
return;
if (sent < 0) {
/* disconnected */
return;
}
/* everything wasn't sent - don't read anything until we've
sent it all */
proxy->outbuf_pos_plain = 0;
}
{
int sent;
if (sent <= 0)
return;
if (proxy->send_left_ssl > 0)
return;
/* everything is sent, start reading again */
}
{
char buf[1024];
if (rcvd < 0) {
/* disconnected */
return;
}
return;
/* everything wasn't sent - don't read anything until we've
sent it all */
}
{
if (ret >= 0) {
/* handshake done, now we can start reading */
plain_input, proxy);
return;
}
return;
/* i/o interrupted */
}
}
static gnutls_session initialize_state(void)
{
return session;
}
{
int sfd[2];
if (!ssl_initialized) {
i_error("SSL support not enabled in configuration");
return -1;
}
session = initialize_state();
i_error("socketpair() failed: %m");
return -1;
}
if (!ssl_proxy_destroy(proxy)) {
/* handshake failed. return the disconnected socket anyway
so the caller doesn't try to use the old closed fd */
return sfd[1];
}
main_ref();
return sfd[1];
}
const char *fname, const char *field_name)
{
/* get size */
if (ret < 0)
i_fatal("Corrupted SSL parameter file %s: File too small",
fname);
}
i_fatal("Corrupted SSL parameter file %s: "
"Field '%s' too large (%u)",
}
/* read the actual data */
if (ret < 0)
i_fatal("Corrupted SSL parameter file %s: "
"Field '%s' not fully in file (%u < %u)",
}
}
{
i_fatal("gnutls_dh_params_init() failed: %s",
}
/* read until bits field is 0 */
for (;;) {
i_fatal("Corrupted SSL parameter file %s: "
"Field 'DH bits' has invalid size %u",
}
if (bits == 0)
break;
if (ret < 0) {
i_fatal("gnutls_dh_params_set() failed: %s",
}
}
}
{
gnutls_datum m, e, d, p, q, u;
int ret;
i_fatal("gnutls_rsa_params_init() failed: %s",
}
/* only 512bit is allowed */
if (ret < 0) {
i_fatal("gnutls_rsa_params_set() failed: %s",
}
}
static void read_parameters(const char *fname)
{
int fd;
/* we'll wait until parameter file exists */
for (;;) {
if (fd != -1)
break;
sleep(1);
}
i_close_fd(&fd);
}
{
if (level != GCRY_LOG_FATAL)
return;
T_BEGIN {
} T_END;
}
void ssl_proxy_init(void)
{
unsigned char buf[4];
int ret;
/* SSL support is disabled */
return;
}
if ((ret = gnutls_global_init() < 0)) {
i_fatal("gnu_tls_global_init() failed: %s",
}
/* gcrypt initialization - set log handler and make sure randomizer
i_fatal("gnutls_certificate_allocate_credentials() failed: %s",
}
if (ret < 0) {
i_fatal("Can't load certificate files %s and %s: %s",
}
}
void ssl_proxy_deinit(void)
{
struct hash_iterate_context *iter;
if (!ssl_initialized)
return;
}
#endif