Mercurial > dovecot > core-2.2
changeset 15379:68d21f872fd7
lib-ssl-iostream now dynamically loads openssl library instead of linking to it.
This allowed removing the separate libdovecot-ssl library. In future if
GnuTLS/NSS support is added it would also allow switching between them
dynamically.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 06 Nov 2012 01:04:24 +0200 |
parents | 94778985bb6a |
children | 7c75559cd8f6 |
files | configure.ac src/auth/Makefile.am src/lib-dovecot/Makefile.am src/lib-master/Makefile.am src/lib-ssl-iostream/Makefile.am src/lib-ssl-iostream/iostream-openssl-common.c src/lib-ssl-iostream/iostream-openssl-context.c src/lib-ssl-iostream/iostream-openssl-params.c src/lib-ssl-iostream/iostream-openssl.c src/lib-ssl-iostream/iostream-openssl.h src/lib-ssl-iostream/iostream-ssl-private.h src/lib-ssl-iostream/iostream-ssl.c src/lib-ssl-iostream/istream-openssl.c src/lib-ssl-iostream/ostream-openssl.c src/login-common/Makefile.am |
diffstat | 15 files changed, 520 insertions(+), 303 deletions(-) [+] |
line wrap: on
line diff
--- a/configure.ac Mon Nov 05 18:16:56 2012 +0200 +++ b/configure.ac Tue Nov 06 01:04:24 2012 +0200 @@ -2499,17 +2499,15 @@ LIBDOVECOT="$LIBDOVECOT_DEPS" LIBDOVECOT_STORAGE_DEPS='$(top_builddir)/src/lib-storage/libdovecot-storage.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la' LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/libdovecot-login.la' - LIBDOVECOT_SSL='$(top_builddir)/src/lib-master/libmaster_ssl.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la' LIBDOVECOT_COMPRESS='$(top_builddir)/src/lib-compression/libcompression.la' LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/libdovecot-lda.la' else - LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la' + LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la' LIBDOVECOT="$LIBDOVECOT_DEPS \$(LIBICONV)" LIBDOVECOT_STORAGE_LAST='$(top_builddir)/src/lib-storage/list/libstorage_list.la $(top_builddir)/src/lib-storage/index/libstorage_index.la $(top_builddir)/src/lib-storage/libstorage.la $(top_builddir)/src/lib-index/libindex.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la' LIBDOVECOT_STORAGE_FIRST='$(top_builddir)/src/lib-storage/libstorage_service.la $(top_builddir)/src/lib-storage/register/libstorage_register.la' LIBDOVECOT_STORAGE_DEPS="$LIBDOVECOT_STORAGE_FIRST $LINKED_STORAGE_LIBS $LIBDOVECOT_STORAGE_LAST" - LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/liblogin.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la' - LIBDOVECOT_SSL='$(top_builddir)/src/lib-master/libmaster_ssl.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la' + LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/liblogin.la' LIBDOVECOT_COMPRESS='$(top_builddir)/src/lib-compression/libcompression.la' LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/liblda.la' fi
--- a/src/auth/Makefile.am Mon Nov 05 18:16:56 2012 +0200 +++ b/src/auth/Makefile.am Tue Nov 06 01:04:24 2012 +0200 @@ -176,8 +176,7 @@ libauthdb_imap_la_LDFLAGS = -module -avoid-version libauthdb_imap_la_LIBADD = \ ../lib-imap-client/libimap_client.la \ - ../lib-ssl-iostream/libssl_iostream.la \ - $(LIBDOVECOT) $(SSL_LIBS) + $(LIBDOVECOT) libauthdb_imap_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/lib-imap \
--- a/src/lib-dovecot/Makefile.am Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-dovecot/Makefile.am Tue Nov 06 01:04:24 2012 +0200 @@ -8,32 +8,18 @@ ../lib-fs/libfs.la \ ../lib-charset/libcharset.la \ ../lib-master/libmaster.la \ + ../lib-ssl-iostream/libssl_iostream.la ../lib-test/libtest.la \ ../lib/liblib.la -ssl_libs = \ - ../lib-master/libmaster_ssl.la \ - ../lib-ssl-iostream/libssl_iostream.la - -pkglib_LTLIBRARIES = libdovecot.la libdovecot-ssl.la +pkglib_LTLIBRARIES = libdovecot.la libdovecot_la_SOURCES = -libdovecot_ssl_la_SOURCES = libdovecot_la_LIBADD = \ $(libs) \ $(MODULE_LIBS) \ $(LTLIBICONV) -libdovecot_ssl_la_LIBADD = \ - libdovecot.la \ - ../lib/liblib.la \ - $(MODULE_LIBS) \ - $(ssl_libs) \ - $(SSL_LIBS) - libdovecot_la_DEPENDENCIES = $(libs) -libdovecot_ssl_la_DEPENDENCIES = $(ssl_libs) libdovecot.la - libdovecot_la_LDFLAGS = -export-dynamic -libdovecot_ssl_la_LDFLAGS = -export-dynamic
--- a/src/lib-master/Makefile.am Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-master/Makefile.am Tue Nov 06 01:04:24 2012 +0200 @@ -1,6 +1,6 @@ pkgsysconfdir = $(sysconfdir)/dovecot -noinst_LTLIBRARIES = libmaster.la libmaster_ssl.la +noinst_LTLIBRARIES = libmaster.la AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ @@ -22,13 +22,11 @@ master-service.c \ master-service-settings.c \ master-service-settings-cache.c \ + master-service-ssl.c \ master-service-ssl-settings.c \ mountpoint-list.c \ syslog-util.c -libmaster_ssl_la_SOURCES = \ - master-service-ssl.c - headers = \ anvil-client.h \ ipc-client.h \
--- a/src/lib-ssl-iostream/Makefile.am Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/Makefile.am Tue Nov 06 01:04:24 2012 +0200 @@ -1,29 +1,34 @@ noinst_LTLIBRARIES = libssl_iostream.la +NOPLUGIN_LDFLAGS = + AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-test + -I$(top_srcdir)/src/lib-test \ + -DMODULE_DIR=\""$(moduledir)"\" if BUILD_OPENSSL -ssl_sources = \ +module_LTLIBRARIES = libssl_iostream_openssl.la + +libssl_iostream_openssl_la_LDFLAGS = -module -avoid-version +libssl_iostream_openssl_la_LIBADD = $(SSL_LIBS) +libssl_iostream_openssl_la_SOURCES = \ iostream-openssl.c \ + iostream-openssl-common.c \ iostream-openssl-context.c \ iostream-openssl-params.c \ istream-openssl.c \ ostream-openssl.c -else -ssl_sources = \ - iostream-ssl-none.c endif libssl_iostream_la_SOURCES = \ + iostream-ssl.c \ $(ssl_sources) -libssl_iostream_la_LIBADD = \ - $(SSL_LIBS) headers = \ iostream-openssl.h \ - iostream-ssl.h + iostream-ssl.h \ + iostream-ssl-private.h pkginc_libdir=$(pkgincludedir) pkginc_lib_HEADERS = $(headers)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-ssl-iostream/iostream-openssl-common.c Tue Nov 06 01:04:24 2012 +0200 @@ -0,0 +1,135 @@ +/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "iostream-openssl.h" + +#include <openssl/x509v3.h> + +enum { + DOVECOT_SSL_PROTO_SSLv2 = 0x01, + DOVECOT_SSL_PROTO_SSLv3 = 0x02, + DOVECOT_SSL_PROTO_TLSv1 = 0x04, + DOVECOT_SSL_PROTO_ALL = 0x07 +}; + +int openssl_get_protocol_options(const char *protocols) +{ + const char *const *tmp; + int proto, op = 0, include = 0, exclude = 0; + bool neg; + + tmp = t_strsplit_spaces(protocols, " "); + for (; *tmp != NULL; tmp++) { + const char *name = *tmp; + + if (*name != '!') + neg = FALSE; + else { + name++; + neg = TRUE; + } + if (strcasecmp(name, SSL_TXT_SSLV2) == 0) + proto = DOVECOT_SSL_PROTO_SSLv2; + else if (strcasecmp(name, SSL_TXT_SSLV3) == 0) + proto = DOVECOT_SSL_PROTO_SSLv3; + else if (strcasecmp(name, SSL_TXT_TLSV1) == 0) + proto = DOVECOT_SSL_PROTO_TLSv1; + else { + i_fatal("Invalid ssl_protocols setting: " + "Unknown protocol '%s'", name); + } + if (neg) + exclude |= proto; + else + include |= proto; + } + if (include != 0) { + /* exclude everything, except those that are included + (and let excludes still override those) */ + exclude |= DOVECOT_SSL_PROTO_ALL & ~include; + } + if ((exclude & DOVECOT_SSL_PROTO_SSLv2) != 0) op |= SSL_OP_NO_SSLv2; + if ((exclude & DOVECOT_SSL_PROTO_SSLv3) != 0) op |= SSL_OP_NO_SSLv3; + if ((exclude & DOVECOT_SSL_PROTO_TLSv1) != 0) op |= SSL_OP_NO_TLSv1; + return op; +} + +static const char *asn1_string_to_c(ASN1_STRING *asn_str) +{ + const char *cstr; + unsigned int len; + + len = ASN1_STRING_length(asn_str); + cstr = t_strndup(ASN1_STRING_data(asn_str), len); + if (strlen(cstr) != len) { + /* NULs in the name - could be some MITM attack. + never allow. */ + return ""; + } + return cstr; +} + +static const char *get_general_dns_name(const GENERAL_NAME *name) +{ + if (ASN1_STRING_type(name->d.ia5) != V_ASN1_IA5STRING) + return ""; + + return asn1_string_to_c(name->d.ia5); +} + +static const char *get_cname(X509 *cert) +{ + X509_NAME *name; + X509_NAME_ENTRY *entry; + ASN1_STRING *str; + int cn_idx; + + name = X509_get_subject_name(cert); + if (name == NULL) + return ""; + cn_idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + if (cn_idx == -1) + return ""; + entry = X509_NAME_get_entry(name, cn_idx); + i_assert(entry != NULL); + str = X509_NAME_ENTRY_get_data(entry); + i_assert(str != NULL); + return asn1_string_to_c(str); +} + +int openssl_cert_match_name(SSL *ssl, const char *verify_name) +{ + X509 *cert; + STACK_OF(GENERAL_NAME) *gnames; + const GENERAL_NAME *gn; + const char *dnsname; + bool dns_names = FALSE; + unsigned int i, count; + int ret; + + cert = SSL_get_peer_certificate(ssl); + i_assert(cert != NULL); + + /* verify against SubjectAltNames */ + gnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + count = gnames == NULL ? 0 : sk_GENERAL_NAME_num(gnames); + for (i = 0; i < count; i++) { + gn = sk_GENERAL_NAME_value(gnames, i); + if (gn->type == GEN_DNS) { + dns_names = TRUE; + dnsname = get_general_dns_name(gn); + if (strcmp(dnsname, verify_name) == 0) + break; + } + } + sk_GENERAL_NAME_pop_free(gnames, GENERAL_NAME_free); + + /* verify against CommonName only when there wasn't any DNS + SubjectAltNames */ + if (dns_names) + ret = i < count ? 0 : -1; + else + ret = strcmp(get_cname(cert), verify_name) == 0 ? 0 : -1; + X509_free(cert); + return ret; +}
--- a/src/lib-ssl-iostream/iostream-openssl-context.c Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/iostream-openssl-context.c Tue Nov 06 01:04:24 2012 +0200 @@ -23,7 +23,7 @@ static void ssl_iostream_init_global(const struct ssl_iostream_settings *set); -const char *ssl_iostream_error(void) +const char *openssl_iostream_error(void) { unsigned long err; char *buf; @@ -44,7 +44,7 @@ return buf; } -const char *ssl_iostream_key_load_error(void) +const char *openssl_iostream_key_load_error(void) { unsigned long err = ERR_peek_error(); @@ -52,7 +52,7 @@ ERR_GET_REASON(err) == X509_R_KEY_VALUES_MISMATCH) return "Key is for a different cert than ssl_cert"; else - return ssl_iostream_error(); + return openssl_iostream_error(); } static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED, @@ -95,8 +95,8 @@ return strlen(buf); } -int ssl_iostream_load_key(const struct ssl_iostream_settings *set, - const char *key_source, EVP_PKEY **pkey_r) +int openssl_iostream_load_key(const struct ssl_iostream_settings *set, + const char *key_source, EVP_PKEY **pkey_r) { struct ssl_iostream_password_context ctx; EVP_PKEY *pkey; @@ -106,7 +106,7 @@ key = t_strdup_noconst(set->key); bio = BIO_new_mem_buf(key, strlen(key)); if (bio == NULL) { - i_error("BIO_new_mem_buf() failed: %s", ssl_iostream_error()); + i_error("BIO_new_mem_buf() failed: %s", openssl_iostream_error()); safe_memset(key, 0, strlen(key)); return -1; } @@ -117,7 +117,7 @@ pkey = PEM_read_bio_PrivateKey(bio, NULL, pem_password_callback, &ctx); if (pkey == NULL) { i_error("%s: Couldn't parse private SSL key: %s", - key_source, ssl_iostream_error()); + key_source, openssl_iostream_error()); } BIO_free(bio); @@ -133,11 +133,11 @@ EVP_PKEY *pkey; int ret = 0; - if (ssl_iostream_load_key(set, ctx->source, &pkey) < 0) + if (openssl_iostream_load_key(set, ctx->source, &pkey) < 0) return -1; if (!SSL_CTX_use_PrivateKey(ctx->ssl_ctx, pkey)) { i_error("%s: Can't load SSL private key: %s", - ctx->source, ssl_iostream_key_load_error()); + ctx->source, openssl_iostream_key_load_error()); ret = -1; } EVP_PKEY_free(pkey); @@ -156,7 +156,7 @@ err = ERR_peek_error(); if (ERR_GET_LIB(err) != ERR_LIB_PEM || ERR_GET_REASON(err) != PEM_R_NO_START_LINE) - return ssl_iostream_error(); + return openssl_iostream_error(); else if (is_pem_key(cert)) { return "The file contains a private key " "(you've mixed ssl_cert and ssl_key settings)"; @@ -288,55 +288,6 @@ return new_set; } -enum { - DOVECOT_SSL_PROTO_SSLv2 = 0x01, - DOVECOT_SSL_PROTO_SSLv3 = 0x02, - DOVECOT_SSL_PROTO_TLSv1 = 0x04, - DOVECOT_SSL_PROTO_ALL = 0x07 -}; - -int openssl_get_protocol_options(const char *protocols) -{ - const char *const *tmp; - int proto, op = 0, include = 0, exclude = 0; - bool neg; - - tmp = t_strsplit_spaces(protocols, " "); - for (; *tmp != NULL; tmp++) { - const char *name = *tmp; - - if (*name != '!') - neg = FALSE; - else { - name++; - neg = TRUE; - } - if (strcasecmp(name, SSL_TXT_SSLV2) == 0) - proto = DOVECOT_SSL_PROTO_SSLv2; - else if (strcasecmp(name, SSL_TXT_SSLV3) == 0) - proto = DOVECOT_SSL_PROTO_SSLv3; - else if (strcasecmp(name, SSL_TXT_TLSV1) == 0) - proto = DOVECOT_SSL_PROTO_TLSv1; - else { - i_fatal("Invalid ssl_protocols setting: " - "Unknown protocol '%s'", name); - } - if (neg) - exclude |= proto; - else - include |= proto; - } - if (include != 0) { - /* exclude everything, except those that are included - (and let excludes still override those) */ - exclude |= DOVECOT_SSL_PROTO_ALL & ~include; - } - if ((exclude & DOVECOT_SSL_PROTO_SSLv2) != 0) op |= SSL_OP_NO_SSLv2; - if ((exclude & DOVECOT_SSL_PROTO_SSLv3) != 0) op |= SSL_OP_NO_SSLv3; - if ((exclude & DOVECOT_SSL_PROTO_TLSv1) != 0) op |= SSL_OP_NO_TLSv1; - return op; -} - static int ssl_iostream_context_set(struct ssl_iostream_context *ctx, const struct ssl_iostream_settings *set) @@ -349,7 +300,7 @@ !SSL_CTX_set_cipher_list(ctx->ssl_ctx, set->cipher_list)) { i_error("%s: Can't set cipher list to '%s': %s", ctx->source, set->cipher_list, - ssl_iostream_error()); + openssl_iostream_error()); return -1; } if (ctx->set->protocols != NULL) { @@ -374,7 +325,7 @@ store = SSL_CTX_get_cert_store(ctx->ssl_ctx); if (load_ca(store, set->ca, &xnames) < 0) { i_error("%s: Couldn't parse ssl_ca: %s", ctx->source, - ssl_iostream_error()); + openssl_iostream_error()); return -1; } if (ssl_iostream_ctx_verify_remote_cert(ctx, xnames) < 0) @@ -383,7 +334,7 @@ if (!SSL_CTX_load_verify_locations(ctx->ssl_ctx, NULL, set->ca_dir)) { i_error("%s: Can't load CA certs from directory %s: %s", - ctx->source, set->ca_dir, ssl_iostream_error()); + ctx->source, set->ca_dir, openssl_iostream_error()); return -1; } } else { @@ -421,16 +372,16 @@ return ssl_iostream_context_set(ctx, set); } -int ssl_iostream_context_init_client(const char *source, - const struct ssl_iostream_settings *set, - struct ssl_iostream_context **ctx_r) +int openssl_iostream_context_init_client(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r) { struct ssl_iostream_context *ctx; SSL_CTX *ssl_ctx; ssl_iostream_init_global(set); if ((ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { - i_error("SSL_CTX_new() failed: %s", ssl_iostream_error()); + i_error("SSL_CTX_new() failed: %s", openssl_iostream_error()); return -1; } @@ -445,16 +396,16 @@ return 0; } -int ssl_iostream_context_init_server(const char *source, - const struct ssl_iostream_settings *set, - struct ssl_iostream_context **ctx_r) +int openssl_iostream_context_init_server(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r) { struct ssl_iostream_context *ctx; SSL_CTX *ssl_ctx; ssl_iostream_init_global(set); if ((ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { - i_error("SSL_CTX_new() failed: %s", ssl_iostream_error()); + i_error("SSL_CTX_new() failed: %s", openssl_iostream_error()); return -1; } @@ -468,13 +419,10 @@ return 0; } -void ssl_iostream_context_deinit(struct ssl_iostream_context **_ctx) +void openssl_iostream_context_deinit(struct ssl_iostream_context *ctx) { - struct ssl_iostream_context *ctx = *_ctx; - - *_ctx = NULL; SSL_CTX_free(ctx->ssl_ctx); - ssl_iostream_context_free_params(ctx); + openssl_iostream_context_free_params(ctx); pool_unref(&ctx->pool); i_free(ctx); }
--- a/src/lib-ssl-iostream/iostream-openssl-params.c Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/iostream-openssl-params.c Tue Nov 06 01:04:24 2012 +0200 @@ -19,13 +19,13 @@ dh = DH_generate_parameters(bitsize, DH_GENERATOR, NULL, NULL); if (dh == NULL) { i_error("DH_generate_parameters(bits=%d, gen=%d) failed: %s", - bitsize, DH_GENERATOR, ssl_iostream_error()); + bitsize, DH_GENERATOR, openssl_iostream_error()); return -1; } len = i2d_DHparams(dh, NULL); if (len < 0) { - i_error("i2d_DHparams() failed: %s", ssl_iostream_error()); + i_error("i2d_DHparams() failed: %s", openssl_iostream_error()); DH_free(dh); return -1; } @@ -40,7 +40,7 @@ return 0; } -int ssl_iostream_generate_params(buffer_t *output) +int openssl_iostream_generate_params(buffer_t *output) { unsigned int i; @@ -101,13 +101,13 @@ return ret; } -int ssl_iostream_context_import_params(struct ssl_iostream_context *ctx, - const buffer_t *input) +int openssl_iostream_context_import_params(struct ssl_iostream_context *ctx, + const buffer_t *input) { const unsigned char *data, *end; int ret; - ssl_iostream_context_free_params(ctx); + openssl_iostream_context_free_params(ctx); data = input->data; end = data + input->used; @@ -116,7 +116,7 @@ return ret < 0 || data != end ? -1 : 0; } -void ssl_iostream_context_free_params(struct ssl_iostream_context *ctx) +void openssl_iostream_context_free_params(struct ssl_iostream_context *ctx) { if (ctx->dh_512 != NULL) { DH_free(ctx->dh_512);
--- a/src/lib-ssl-iostream/iostream-openssl.c Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/iostream-openssl.c Tue Nov 06 01:04:24 2012 +0200 @@ -6,11 +6,10 @@ #include "iostream-openssl.h" #include <openssl/err.h> -#include <openssl/x509v3.h> -static void ssl_iostream_free(struct ssl_iostream *ssl_io); +static void openssl_iostream_free(struct ssl_iostream *ssl_io); -static void ssl_info_callback(const SSL *ssl, int where, int ret) +static void openssl_info_callback(const SSL *ssl, int where, int ret) { struct ssl_iostream *ssl_io; @@ -31,7 +30,7 @@ } static int -ssl_iostream_use_certificate(struct ssl_iostream *ssl_io, const char *cert) +openssl_iostream_use_certificate(struct ssl_iostream *ssl_io, const char *cert) { BIO *in; X509 *x; @@ -39,7 +38,7 @@ in = BIO_new_mem_buf(t_strdup_noconst(cert), strlen(cert)); if (in == NULL) { - i_error("BIO_new_mem_buf() failed: %s", ssl_iostream_error()); + i_error("BIO_new_mem_buf() failed: %s", openssl_iostream_error()); return -1; } @@ -61,17 +60,17 @@ } static int -ssl_iostream_use_key(struct ssl_iostream *ssl_io, - const struct ssl_iostream_settings *set) +openssl_iostream_use_key(struct ssl_iostream *ssl_io, + const struct ssl_iostream_settings *set) { EVP_PKEY *pkey; int ret = 0; - if (ssl_iostream_load_key(set, ssl_io->source, &pkey) < 0) + if (openssl_iostream_load_key(set, ssl_io->source, &pkey) < 0) return -1; if (SSL_use_PrivateKey(ssl_io->ssl, pkey) != 1) { i_error("%s: Can't load SSL private key: %s", - ssl_io->source, ssl_iostream_key_load_error()); + ssl_io->source, openssl_iostream_key_load_error()); ret = -1; } EVP_PKEY_free(pkey); @@ -79,7 +78,7 @@ } static int -ssl_iostream_verify_client_cert(int preverify_ok, X509_STORE_CTX *ctx) +openssl_iostream_verify_client_cert(int preverify_ok, X509_STORE_CTX *ctx) { int ssl_extidx = SSL_get_ex_data_X509_STORE_CTX_idx(); SSL *ssl; @@ -116,21 +115,21 @@ } static int -ssl_iostream_set(struct ssl_iostream *ssl_io, - const struct ssl_iostream_settings *set) +openssl_iostream_set(struct ssl_iostream *ssl_io, + const struct ssl_iostream_settings *set) { const struct ssl_iostream_settings *ctx_set = ssl_io->ctx->set; int verify_flags; if (set->verbose) - SSL_set_info_callback(ssl_io->ssl, ssl_info_callback); + SSL_set_info_callback(ssl_io->ssl, openssl_info_callback); if (set->cipher_list != NULL && strcmp(ctx_set->cipher_list, set->cipher_list) != 0) { if (!SSL_set_cipher_list(ssl_io->ssl, set->cipher_list)) { i_error("%s: Can't set cipher list to '%s': %s", ssl_io->source, set->cipher_list, - ssl_iostream_error()); + openssl_iostream_error()); } return -1; } @@ -141,11 +140,11 @@ } if (set->cert != NULL && strcmp(ctx_set->cert, set->cert) != 0) { - if (ssl_iostream_use_certificate(ssl_io, set->cert) < 0) + if (openssl_iostream_use_certificate(ssl_io, set->cert) < 0) return -1; } if (set->key != NULL && strcmp(ctx_set->key, set->key) != 0) { - if (ssl_iostream_use_key(ssl_io, set) < 0) + if (openssl_iostream_use_key(ssl_io, set) < 0) return -1; } if (set->verify_remote_cert) { @@ -154,7 +153,7 @@ else verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; SSL_set_verify(ssl_io->ssl, verify_flags, - ssl_iostream_verify_client_cert); + openssl_iostream_verify_client_cert); } if (set->cert_username_field != NULL) { @@ -173,10 +172,11 @@ return 0; } -int io_stream_create_ssl(struct ssl_iostream_context *ctx, const char *source, - const struct ssl_iostream_settings *set, - struct istream **input, struct ostream **output, - struct ssl_iostream **iostream_r) +static int +openssl_iostream_create(struct ssl_iostream_context *ctx, const char *source, + const struct ssl_iostream_settings *set, + struct istream **input, struct ostream **output, + struct ssl_iostream **iostream_r) { struct ssl_iostream *ssl_io; SSL *ssl; @@ -185,7 +185,7 @@ ssl = SSL_new(ctx->ssl_ctx); if (ssl == NULL) { - i_error("SSL_new() failed: %s", ssl_iostream_error()); + i_error("SSL_new() failed: %s", openssl_iostream_error()); return -1; } @@ -195,7 +195,8 @@ into the given buffer. The bio_int is used by OpenSSL and bio_ext is used by this library. */ if (BIO_new_bio_pair(&bio_int, 0, &bio_ext, 0) != 1) { - i_error("BIO_new_bio_pair() failed: %s", ssl_iostream_error()); + i_error("BIO_new_bio_pair() failed: %s", + openssl_iostream_error()); SSL_free(ssl); return -1; } @@ -213,17 +214,17 @@ SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io); T_BEGIN { - ret = ssl_iostream_set(ssl_io, set); + ret = openssl_iostream_set(ssl_io, set); } T_END; if (ret < 0) { - ssl_iostream_free(ssl_io); + openssl_iostream_free(ssl_io); return -1; } o_stream_uncork(ssl_io->plain_output); - *input = i_stream_create_ssl(ssl_io); - *output = o_stream_create_ssl(ssl_io); + *input = openssl_i_stream_create_ssl(ssl_io); + *output = openssl_o_stream_create_ssl(ssl_io); i_stream_set_name(*input, t_strconcat("SSL ", i_stream_get_name(ssl_io->plain_input), NULL)); o_stream_set_name(*output, t_strconcat("SSL ", @@ -237,7 +238,7 @@ return 0; } -static void ssl_iostream_free(struct ssl_iostream *ssl_io) +static void openssl_iostream_free(struct ssl_iostream *ssl_io) { i_stream_unref(&ssl_io->plain_input); o_stream_unref(&ssl_io->plain_output); @@ -248,33 +249,25 @@ i_free(ssl_io); } -void ssl_iostream_unref(struct ssl_iostream **_ssl_io) +static void openssl_iostream_unref(struct ssl_iostream *ssl_io) { - struct ssl_iostream *ssl_io = *_ssl_io; - - *_ssl_io = NULL; - i_assert(ssl_io->refcount > 0); if (--ssl_io->refcount > 0) return; - ssl_iostream_free(ssl_io); + openssl_iostream_free(ssl_io); } -void ssl_iostream_destroy(struct ssl_iostream **_ssl_io) +static void openssl_iostream_destroy(struct ssl_iostream *ssl_io) { - struct ssl_iostream *ssl_io = *_ssl_io; - - *_ssl_io = NULL; - (void)SSL_shutdown(ssl_io->ssl); - (void)ssl_iostream_more(ssl_io); + (void)openssl_iostream_more(ssl_io); (void)o_stream_flush(ssl_io->plain_output); ssl_iostream_unref(&ssl_io); } -static bool ssl_iostream_bio_output(struct ssl_iostream *ssl_io) +static bool openssl_iostream_bio_output(struct ssl_iostream *ssl_io) { size_t bytes, max_bytes; ssize_t sent; @@ -324,8 +317,8 @@ } static ssize_t -ssl_iostream_read_more(struct ssl_iostream *ssl_io, - const unsigned char **data_r, size_t *size_r) +openssl_iostream_read_more(struct ssl_iostream *ssl_io, + const unsigned char **data_r, size_t *size_r) { *data_r = i_stream_get_data(ssl_io->plain_input, size_r); if (*size_r > 0) @@ -343,7 +336,7 @@ return 0; } -static bool ssl_iostream_bio_input(struct ssl_iostream *ssl_io) +static bool openssl_iostream_bio_input(struct ssl_iostream *ssl_io) { const unsigned char *data; size_t bytes, size; @@ -353,7 +346,7 @@ while ((bytes = BIO_ctrl_get_write_guarantee(ssl_io->bio_ext)) > 0) { /* bytes contains how many bytes we can write to bio_ext */ ssl_io->plain_input->real_stream->try_alloc_limit = bytes; - ret = ssl_iostream_read_more(ssl_io, &data, &size); + ret = openssl_iostream_read_more(ssl_io, &data, &size); ssl_io->plain_input->real_stream->try_alloc_limit = 0; if (ret == -1 && size == 0 && !bytes_read) { ssl_io->plain_stream_errno = @@ -397,17 +390,17 @@ return bytes_read; } -bool ssl_iostream_bio_sync(struct ssl_iostream *ssl_io) +bool openssl_iostream_bio_sync(struct ssl_iostream *ssl_io) { bool ret; - ret = ssl_iostream_bio_output(ssl_io); - if (ssl_iostream_bio_input(ssl_io)) + ret = openssl_iostream_bio_output(ssl_io); + if (openssl_iostream_bio_input(ssl_io)) ret = TRUE; return ret; } -int ssl_iostream_more(struct ssl_iostream *ssl_io) +int openssl_iostream_more(struct ssl_iostream *ssl_io) { int ret; @@ -415,19 +408,20 @@ if ((ret = ssl_iostream_handshake(ssl_io)) <= 0) return ret; } - (void)ssl_iostream_bio_sync(ssl_io); + (void)openssl_iostream_bio_sync(ssl_io); return 1; } -static void ssl_iostream_set_error(struct ssl_iostream *ssl_io, const char *str) +static void +openssl_iostream_set_error(struct ssl_iostream *ssl_io, const char *str) { i_free(ssl_io->last_error); ssl_io->last_error = i_strdup(str); } static int -ssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret, - const char *func_name, bool write_error) +openssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret, + const char *func_name, bool write_error) { const char *errstr = NULL; int err; @@ -435,7 +429,7 @@ err = SSL_get_error(ssl_io->ssl, ret); switch (err) { case SSL_ERROR_WANT_WRITE: - if (!ssl_iostream_bio_sync(ssl_io)) { + if (!openssl_iostream_bio_sync(ssl_io)) { if (!write_error) i_panic("SSL ostream buffer size not unlimited"); return 0; @@ -448,7 +442,7 @@ return 1; case SSL_ERROR_WANT_READ: ssl_io->want_read = TRUE; - (void)ssl_iostream_bio_sync(ssl_io); + (void)openssl_iostream_bio_sync(ssl_io); if (ssl_io->closed) { errno = ssl_io->plain_stream_errno != 0 ? ssl_io->plain_stream_errno : EPIPE; @@ -458,7 +452,7 @@ case SSL_ERROR_SYSCALL: /* eat up the error queue */ if (ERR_peek_error() != 0) { - errstr = ssl_iostream_error(); + errstr = openssl_iostream_error(); errno = EINVAL; } else if (ret != 0) { i_assert(errno != 0); @@ -478,114 +472,36 @@ break; case SSL_ERROR_SSL: errstr = t_strdup_printf("%s failed: %s", - func_name, ssl_iostream_error()); + func_name, openssl_iostream_error()); errno = EINVAL; break; default: errstr = t_strdup_printf("%s failed: unknown failure %d (%s)", - func_name, err, ssl_iostream_error()); + func_name, err, + openssl_iostream_error()); errno = EINVAL; break; } if (errstr != NULL) - ssl_iostream_set_error(ssl_io, errstr); + openssl_iostream_set_error(ssl_io, errstr); return -1; } -int ssl_iostream_handle_error(struct ssl_iostream *ssl_io, int ret, - const char *func_name) -{ - return ssl_iostream_handle_error_full(ssl_io, ret, func_name, FALSE); -} - -int ssl_iostream_handle_write_error(struct ssl_iostream *ssl_io, int ret, - const char *func_name) -{ - return ssl_iostream_handle_error_full(ssl_io, ret, func_name, TRUE); -} - -static const char *asn1_string_to_c(ASN1_STRING *asn_str) +int openssl_iostream_handle_error(struct ssl_iostream *ssl_io, int ret, + const char *func_name) { - const char *cstr; - unsigned int len; - - len = ASN1_STRING_length(asn_str); - cstr = t_strndup(ASN1_STRING_data(asn_str), len); - if (strlen(cstr) != len) { - /* NULs in the name - could be some MITM attack. - never allow. */ - return ""; - } - return cstr; -} - -static const char *get_general_dns_name(const GENERAL_NAME *name) -{ - if (ASN1_STRING_type(name->d.ia5) != V_ASN1_IA5STRING) - return ""; - - return asn1_string_to_c(name->d.ia5); + return openssl_iostream_handle_error_full(ssl_io, ret, func_name, FALSE); } -static const char *get_cname(X509 *cert) +int openssl_iostream_handle_write_error(struct ssl_iostream *ssl_io, int ret, + const char *func_name) { - X509_NAME *name; - X509_NAME_ENTRY *entry; - ASN1_STRING *str; - int cn_idx; - - name = X509_get_subject_name(cert); - if (name == NULL) - return ""; - cn_idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); - if (cn_idx == -1) - return ""; - entry = X509_NAME_get_entry(name, cn_idx); - i_assert(entry != NULL); - str = X509_NAME_ENTRY_get_data(entry); - i_assert(str != NULL); - return asn1_string_to_c(str); + return openssl_iostream_handle_error_full(ssl_io, ret, func_name, TRUE); } -int openssl_cert_match_name(SSL *ssl, const char *verify_name) -{ - X509 *cert; - STACK_OF(GENERAL_NAME) *gnames; - const GENERAL_NAME *gn; - const char *dnsname; - bool dns_names = FALSE; - unsigned int i, count; - int ret; - - cert = SSL_get_peer_certificate(ssl); - i_assert(cert != NULL); - - /* verify against SubjectAltNames */ - gnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - count = gnames == NULL ? 0 : sk_GENERAL_NAME_num(gnames); - for (i = 0; i < count; i++) { - gn = sk_GENERAL_NAME_value(gnames, i); - if (gn->type == GEN_DNS) { - dns_names = TRUE; - dnsname = get_general_dns_name(gn); - if (strcmp(dnsname, verify_name) == 0) - break; - } - } - sk_GENERAL_NAME_pop_free(gnames, GENERAL_NAME_free); - - /* verify against CommonName only when there wasn't any DNS - SubjectAltNames */ - if (dns_names) - ret = i < count ? 0 : -1; - else - ret = strcmp(get_cname(cert), verify_name) == 0 ? 0 : -1; - X509_free(cert); - return ret; -} - -int ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, +static int +openssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *verify_name) { if (!ssl_iostream_has_valid_client_cert(ssl_io)) @@ -594,7 +510,7 @@ return openssl_cert_match_name(ssl_io->ssl, verify_name); } -int ssl_iostream_handshake(struct ssl_iostream *ssl_io) +static int openssl_iostream_handshake(struct ssl_iostream *ssl_io) { int ret; @@ -602,21 +518,21 @@ if (ssl_io->ctx->client_ctx) { while ((ret = SSL_connect(ssl_io->ssl)) <= 0) { - ret = ssl_iostream_handle_error(ssl_io, ret, - "SSL_connect()"); + ret = openssl_iostream_handle_error(ssl_io, ret, + "SSL_connect()"); if (ret <= 0) return ret; } } else { while ((ret = SSL_accept(ssl_io->ssl)) <= 0) { - ret = ssl_iostream_handle_error(ssl_io, ret, - "SSL_accept()"); + ret = openssl_iostream_handle_error(ssl_io, ret, + "SSL_accept()"); if (ret <= 0) return ret; } } /* handshake finished */ - (void)ssl_iostream_bio_sync(ssl_io); + (void)openssl_iostream_bio_sync(ssl_io); i_free_and_null(ssl_io->last_error); ssl_io->handshaked = TRUE; @@ -632,30 +548,34 @@ return 1; } -void ssl_iostream_set_handshake_callback(struct ssl_iostream *ssl_io, - int (*callback)(void *context), - void *context) +static void +openssl_iostream_set_handshake_callback(struct ssl_iostream *ssl_io, + int (*callback)(void *context), + void *context) { ssl_io->handshake_callback = callback; ssl_io->handshake_context = context; } -bool ssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io) +static bool openssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io) { return ssl_io->handshaked; } -bool ssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io) +static bool +openssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io) { return ssl_io->cert_received && !ssl_io->cert_broken; } -bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io) +static bool +openssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io) { return ssl_io->cert_received && ssl_io->cert_broken; } -const char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io) +static const char * +openssl_iostream_get_peer_name(struct ssl_iostream *ssl_io) { X509 *x509; char *name; @@ -688,7 +608,8 @@ return *name == '\0' ? NULL : name; } -const char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io) +static const char * +openssl_iostream_get_security_string(struct ssl_iostream *ssl_io) { const SSL_CIPHER *cipher; #ifdef HAVE_SSL_COMPRESSION @@ -715,7 +636,32 @@ bits, alg_bits, comp_str); } -const char *ssl_iostream_get_last_error(struct ssl_iostream *ssl_io) +static const char * +openssl_iostream_get_last_error(struct ssl_iostream *ssl_io) { return ssl_io->last_error; } + +const struct iostream_ssl_vfuncs ssl_vfuncs = { + openssl_iostream_context_init_client, + openssl_iostream_context_init_server, + openssl_iostream_context_deinit, + + openssl_iostream_generate_params, + openssl_iostream_context_import_params, + + openssl_iostream_create, + openssl_iostream_unref, + openssl_iostream_destroy, + + openssl_iostream_handshake, + openssl_iostream_set_handshake_callback, + + openssl_iostream_is_handshaked, + openssl_iostream_has_valid_client_cert, + openssl_iostream_has_broken_client_cert, + openssl_iostream_cert_match_name, + openssl_iostream_get_peer_name, + openssl_iostream_get_security_string, + openssl_iostream_get_last_error +};
--- a/src/lib-ssl-iostream/iostream-openssl.h Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/iostream-openssl.h Tue Nov 06 01:04:24 2012 +0200 @@ -1,7 +1,7 @@ #ifndef IOSTREAM_OPENSSL_H #define IOSTREAM_OPENSSL_H -#include "iostream-ssl.h" +#include "iostream-ssl-private.h" #include <openssl/ssl.h> @@ -54,12 +54,19 @@ extern int dovecot_ssl_extdata_index; -struct istream *i_stream_create_ssl(struct ssl_iostream *ssl_io); -struct ostream *o_stream_create_ssl(struct ssl_iostream *ssl_io); -void ssl_iostream_unref(struct ssl_iostream **ssl_io); +struct istream *openssl_i_stream_create_ssl(struct ssl_iostream *ssl_io); +struct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io); -int ssl_iostream_load_key(const struct ssl_iostream_settings *set, - const char *key_source, EVP_PKEY **pkey_r); +int openssl_iostream_context_init_client(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r); +int openssl_iostream_context_init_server(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r); +void openssl_iostream_context_deinit(struct ssl_iostream_context *ctx); + +int openssl_iostream_load_key(const struct ssl_iostream_settings *set, + const char *key_source, EVP_PKEY **pkey_r); const char *ssl_iostream_get_use_certificate_error(const char *cert); int openssl_cert_match_name(SSL *ssl, const char *verify_name); int openssl_get_protocol_options(const char *protocols); @@ -68,23 +75,26 @@ /* Sync plain_input/plain_output streams with BIOs. Returns TRUE if at least one byte was read/written. */ -bool ssl_iostream_bio_sync(struct ssl_iostream *ssl_io); +bool openssl_iostream_bio_sync(struct ssl_iostream *ssl_io); /* Call when there's more data available in plain_input/plain_output. Returns 1 if it's ok to continue with SSL_read/SSL_write, 0 if not (still handshaking), -1 if error occurred. */ -int ssl_iostream_more(struct ssl_iostream *ssl_io); +int openssl_iostream_more(struct ssl_iostream *ssl_io); /* Returns 1 if the operation should be retried (we read/wrote more data), 0 if the operation should retried later once more data has been read/written, -1 if a fatal error occurred (errno is set). */ -int ssl_iostream_handle_error(struct ssl_iostream *ssl_io, int ret, - const char *func_name); -int ssl_iostream_handle_write_error(struct ssl_iostream *ssl_io, int ret, - const char *func_name); +int openssl_iostream_handle_error(struct ssl_iostream *ssl_io, int ret, + const char *func_name); +int openssl_iostream_handle_write_error(struct ssl_iostream *ssl_io, int ret, + const char *func_name); -const char *ssl_iostream_error(void); -const char *ssl_iostream_key_load_error(void); +const char *openssl_iostream_error(void); +const char *openssl_iostream_key_load_error(void); -void ssl_iostream_context_free_params(struct ssl_iostream_context *ctx); +int openssl_iostream_generate_params(buffer_t *output); +int openssl_iostream_context_import_params(struct ssl_iostream_context *ctx, + const buffer_t *input); +void openssl_iostream_context_free_params(struct ssl_iostream_context *ctx); #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-ssl-iostream/iostream-ssl-private.h Tue Nov 06 01:04:24 2012 +0200 @@ -0,0 +1,40 @@ +#ifndef IOSTREAM_SSL_PRIVATE_H +#define IOSTREAM_SSL_PRIVATE_H + +#include "iostream-ssl.h" + +struct iostream_ssl_vfuncs { + int (*context_init_client)(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r); + int (*context_init_server)(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r); + void (*context_deinit)(struct ssl_iostream_context *ctx); + + int (*generate_params)(buffer_t *output); + int (*context_import_params)(struct ssl_iostream_context *ctx, + const buffer_t *input); + + int (*create)(struct ssl_iostream_context *ctx, const char *source, + const struct ssl_iostream_settings *set, + struct istream **input, struct ostream **output, + struct ssl_iostream **iostream_r); + void (*unref)(struct ssl_iostream *ssl_io); + void (*destroy)(struct ssl_iostream *ssl_io); + + int (*handshake)(struct ssl_iostream *ssl_io); + void (*set_handshake_callback)(struct ssl_iostream *ssl_io, + int (*callback)(void *context), + void *context); + + bool (*is_handshaked)(const struct ssl_iostream *ssl_io); + bool (*has_valid_client_cert)(const struct ssl_iostream *ssl_io); + bool (*has_broken_client_cert)(struct ssl_iostream *ssl_io); + int (*cert_match_name)(struct ssl_iostream *ssl_io, const char *name); + const char *(*get_peer_name)(struct ssl_iostream *ssl_io); + const char *(*get_security_string)(struct ssl_iostream *ssl_io); + const char *(*get_last_error)(struct ssl_iostream *ssl_io); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-ssl-iostream/iostream-ssl.c Tue Nov 06 01:04:24 2012 +0200 @@ -0,0 +1,147 @@ +/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "module-dir.h" +#include "iostream-ssl-private.h" + +static bool ssl_module_loaded = FALSE; +static struct module *ssl_module = NULL; +static const struct iostream_ssl_vfuncs *ssl_vfuncs = NULL; + +static int ssl_module_load(void) +{ +#ifdef HAVE_SSL + const char *plugin_name = "ssl_iostream_openssl"; + struct module_dir_load_settings mod_set; + + memset(&mod_set, 0, sizeof(mod_set)); + mod_set.abi_version = DOVECOT_ABI_VERSION; + mod_set.setting_name = "<built-in lib-ssl-iostream lookup>"; + ssl_module = module_dir_load(MODULE_DIR, plugin_name, &mod_set); + + ssl_vfuncs = module_get_symbol(ssl_module, "ssl_vfuncs"); + if (ssl_vfuncs == NULL) + i_fatal("%s: ssl_vfuncs symbol not found", plugin_name); + ssl_module_loaded = TRUE; + return 0; +#else + /* SSL not enabled */ + return -1; +#endif +} + +int ssl_iostream_context_init_client(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r) +{ + if (!ssl_module_loaded) { + if (ssl_module_load() < 0) + return -1; + } + return ssl_vfuncs->context_init_client(source, set, ctx_r); +} + +int ssl_iostream_context_init_server(const char *source, + const struct ssl_iostream_settings *set, + struct ssl_iostream_context **ctx_r) +{ + if (!ssl_module_loaded) { + if (ssl_module_load() < 0) + return -1; + } + return ssl_vfuncs->context_init_server(source, set, ctx_r); +} + +void ssl_iostream_context_deinit(struct ssl_iostream_context **_ctx) +{ + struct ssl_iostream_context *ctx = *_ctx; + + *_ctx = NULL; + ssl_vfuncs->context_deinit(ctx); +} + +int ssl_iostream_generate_params(buffer_t *output) +{ + if (!ssl_module_loaded) { + if (ssl_module_load() < 0) + return -1; + } + return ssl_vfuncs->generate_params(output); +} + +int ssl_iostream_context_import_params(struct ssl_iostream_context *ctx, + const buffer_t *input) +{ + return ssl_vfuncs->context_import_params(ctx, input); +} + +int io_stream_create_ssl(struct ssl_iostream_context *ctx, const char *source, + const struct ssl_iostream_settings *set, + struct istream **input, struct ostream **output, + struct ssl_iostream **iostream_r) +{ + return ssl_vfuncs->create(ctx, source, set, input, output, iostream_r); +} + +void ssl_iostream_unref(struct ssl_iostream **_ssl_io) +{ + struct ssl_iostream *ssl_io = *_ssl_io; + + *_ssl_io = NULL; + ssl_vfuncs->unref(ssl_io); +} + +void ssl_iostream_destroy(struct ssl_iostream **_ssl_io) +{ + struct ssl_iostream *ssl_io = *_ssl_io; + + *_ssl_io = NULL; + ssl_vfuncs->destroy(ssl_io); +} + +int ssl_iostream_handshake(struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->handshake(ssl_io); +} + +void ssl_iostream_set_handshake_callback(struct ssl_iostream *ssl_io, + int (*callback)(void *context), + void *context) +{ + ssl_vfuncs->set_handshake_callback(ssl_io, callback, context); +} + +bool ssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->is_handshaked(ssl_io); +} + +bool ssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->has_valid_client_cert(ssl_io); +} + +bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->has_broken_client_cert(ssl_io); +} + +int ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name) +{ + return ssl_vfuncs->cert_match_name(ssl_io, name); +} + +const char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->get_peer_name(ssl_io); +} + +const char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->get_security_string(ssl_io); +} + +const char *ssl_iostream_get_last_error(struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->get_last_error(ssl_io); +}
--- a/src/lib-ssl-iostream/istream-openssl.c Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/istream-openssl.c Tue Nov 06 01:04:24 2012 +0200 @@ -45,7 +45,7 @@ return -2; } - ret = ssl_iostream_more(ssl_io); + ret = openssl_iostream_more(ssl_io); if (ret <= 0) { if (ret < 0) { /* handshake failed */ @@ -65,7 +65,7 @@ while ((ret = SSL_read(ssl_io->ssl, stream->w_buffer + stream->pos, size)) <= 0) { /* failed to read anything */ - ret = ssl_iostream_handle_error(ssl_io, ret, "SSL_read"); + ret = openssl_iostream_handle_error(ssl_io, ret, "SSL_read"); if (ret <= 0) { if (ret < 0) { stream->istream.stream_errno = errno; @@ -108,7 +108,7 @@ return ret; } -struct istream *i_stream_create_ssl(struct ssl_iostream *ssl_io) +struct istream *openssl_i_stream_create_ssl(struct ssl_iostream *ssl_io) { struct ssl_istream *sstream;
--- a/src/lib-ssl-iostream/ostream-openssl.c Mon Nov 05 18:16:56 2012 +0200 +++ b/src/lib-ssl-iostream/ostream-openssl.c Tue Nov 06 01:04:24 2012 +0200 @@ -87,8 +87,8 @@ CONST_PTR_OFFSET(sstream->buffer->data, pos), sstream->buffer->used - pos); if (ret <= 0) { - ret = ssl_iostream_handle_write_error(sstream->ssl_io, - ret, "SSL_write"); + ret = openssl_iostream_handle_write_error(sstream->ssl_io, + ret, "SSL_write"); if (ret < 0) { sstream->ostream.ostream.stream_errno = errno; break; @@ -97,7 +97,7 @@ break; } else { pos += ret; - (void)ssl_iostream_bio_sync(sstream->ssl_io); + (void)openssl_iostream_bio_sync(sstream->ssl_io); } } buffer_delete(sstream->buffer, 0, pos); @@ -109,7 +109,7 @@ struct ssl_ostream *sstream = (struct ssl_ostream *)stream; int ret; - if ((ret = ssl_iostream_more(sstream->ssl_io)) < 0) { + if ((ret = openssl_iostream_more(sstream->ssl_io)) < 0) { /* handshake failed */ stream->ostream.stream_errno = errno; } else if (ret > 0 && sstream->buffer != NULL && @@ -143,8 +143,8 @@ CONST_PTR_OFFSET(iov[i].iov_base, pos), iov[i].iov_len - pos); if (ret <= 0) { - ret = ssl_iostream_handle_write_error(sstream->ssl_io, - ret, "SSL_write"); + ret = openssl_iostream_handle_write_error(sstream->ssl_io, + ret, "SSL_write"); if (ret < 0) { sstream->ostream.ostream.stream_errno = errno; break; @@ -159,7 +159,7 @@ i++; pos = 0; } - (void)ssl_iostream_bio_sync(sstream->ssl_io); + (void)openssl_iostream_bio_sync(sstream->ssl_io); } } return ret < 0 ? -1 : 0; @@ -231,7 +231,7 @@ o_stream_set_max_buffer_size(sstream->ssl_io->plain_output, max_size); } -struct ostream *o_stream_create_ssl(struct ssl_iostream *ssl_io) +struct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io) { struct ssl_ostream *sstream;
--- a/src/login-common/Makefile.am Mon Nov 05 18:16:56 2012 +0200 +++ b/src/login-common/Makefile.am Tue Nov 06 01:04:24 2012 +0200 @@ -22,7 +22,12 @@ ssl-proxy-gnutls.c \ ssl-proxy-openssl.c +if BUILD_OPENSSL +openssl_obj = ../lib-ssl-iostream/iostream-openssl-common.lo +endif + liblogin_la_LIBADD = \ + $(openssl_obj) \ $(SSL_LIBS) headers = \