dovecot-2.0: *-login: ssl_ca_file setting changed to ssl_ca.
dovecot at dovecot.org
dovecot at dovecot.org
Tue Dec 8 22:08:47 EET 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/0da209ff80d5
changeset: 10428:0da209ff80d5
user: Timo Sirainen <tss at iki.fi>
date: Tue Dec 08 15:06:45 2009 -0500
description:
*-login: ssl_ca_file setting changed to ssl_ca.
diffstat:
4 files changed, 71 insertions(+), 36 deletions(-)
doc/example-config/conf.d/ssl.conf | 8 +--
src/login-common/login-settings.c | 20 ++------
src/login-common/login-settings.h | 2
src/login-common/ssl-proxy-openssl.c | 77 ++++++++++++++++++++++++++--------
diffs (228 lines):
diff -r 3a1f6c1a8485 -r 0da209ff80d5 doc/example-config/conf.d/ssl.conf
--- a/doc/example-config/conf.d/ssl.conf Tue Dec 08 13:51:49 2009 -0500
+++ b/doc/example-config/conf.d/ssl.conf Tue Dec 08 15:06:45 2009 -0500
@@ -18,10 +18,10 @@ ssl_key = </etc/ssl/private/dovecot.pem
# root owned 0600 file by using !include_try <path>.
#ssl_key_password =
-# File containing trusted SSL certificate authorities. Set this only if you
-# intend to use ssl_verify_client_cert=yes. The CAfile should contain the
-# CA-certificate(s) followed by the matching CRL(s).
-#ssl_ca_file =
+# PEM encoded trusted certificate authority. Set this only if you intend to use
+# ssl_verify_client_cert=yes. The file should contain the CA certificate(s)
+# followed by the matching CRL(s). (e.g. ssl_ca = </etc/ssl/certs/ca.pem)
+#ssl_ca =
# Request client to send a certificate. If you also want to require it, set
# auth_ssl_require_client_cert=yes in auth section.
diff -r 3a1f6c1a8485 -r 0da209ff80d5 src/login-common/login-settings.c
--- a/src/login-common/login-settings.c Tue Dec 08 13:51:49 2009 -0500
+++ b/src/login-common/login-settings.c Tue Dec 08 15:06:45 2009 -0500
@@ -23,7 +23,7 @@ static const struct setting_define login
DEF(SET_STR, login_log_format),
DEF(SET_ENUM, ssl),
- DEF(SET_STR, ssl_ca_file),
+ DEF(SET_STR, ssl_ca),
DEF(SET_STR, ssl_cert),
DEF(SET_STR, ssl_key),
DEF(SET_STR, ssl_key_password),
@@ -52,7 +52,7 @@ static const struct login_settings login
.login_log_format = "%$: %s",
.ssl = "yes:no:required",
- .ssl_ca_file = "",
+ .ssl_ca = "",
.ssl_cert = "",
.ssl_key = "",
.ssl_key_password = "",
@@ -110,18 +110,10 @@ static int ssl_settings_check(void *_set
*error_r = "ssl enabled, but ssl_key not set";
return FALSE;
}
- if (set->ssl_verify_client_cert && *set->ssl_ca_file == '\0') {
- *error_r = "ssl_verify_client_cert set, but ssl_ca_file not";
- return FALSE;
- }
-
-#ifndef CONFIG_BINARY
- if (*set->ssl_ca_file != '\0' && access(set->ssl_ca_file, R_OK) < 0) {
- *error_r = t_strdup_printf("ssl_ca_file: access(%s) failed: %m",
- set->ssl_ca_file);
- return FALSE;
- }
-#endif
+ if (set->ssl_verify_client_cert && *set->ssl_ca == '\0') {
+ *error_r = "ssl_verify_client_cert set, but ssl_ca not";
+ return FALSE;
+ }
return TRUE;
#endif
}
diff -r 3a1f6c1a8485 -r 0da209ff80d5 src/login-common/login-settings.h
--- a/src/login-common/login-settings.h Tue Dec 08 13:51:49 2009 -0500
+++ b/src/login-common/login-settings.h Tue Dec 08 15:06:45 2009 -0500
@@ -9,7 +9,7 @@ struct login_settings {
const char *login_log_format_elements, *login_log_format;
const char *ssl;
- const char *ssl_ca_file;
+ const char *ssl_ca;
const char *ssl_cert;
const char *ssl_key;
const char *ssl_key_password;
diff -r 3a1f6c1a8485 -r 0da209ff80d5 src/login-common/ssl-proxy-openssl.c
--- a/src/login-common/ssl-proxy-openssl.c Tue Dec 08 13:51:49 2009 -0500
+++ b/src/login-common/ssl-proxy-openssl.c Tue Dec 08 15:06:45 2009 -0500
@@ -82,7 +82,7 @@ struct ssl_server_context {
const char *cert;
const char *key;
- const char *ca_file;
+ const char *ca;
const char *cipher_list;
bool verify_client_cert;
};
@@ -598,7 +598,7 @@ ssl_server_context_get(const struct logi
memset(&lookup_ctx, 0, sizeof(lookup_ctx));
lookup_ctx.cert = set->ssl_cert;
lookup_ctx.key = set->ssl_key;
- lookup_ctx.ca_file = set->ssl_ca_file;
+ lookup_ctx.ca = set->ssl_ca;
lookup_ctx.cipher_list = set->ssl_cipher_list;
lookup_ctx.verify_client_cert = set->ssl_verify_client_cert;
@@ -869,26 +869,65 @@ static bool is_pem_key(const char *cert)
return strstr(cert, "PRIVATE KEY---") != NULL;
}
-static void
+static STACK_OF(X509_NAME) *load_ca(X509_STORE *store, const char *ca)
+{
+ /* mostly just copy&pasted from X509_load_cert_crl_file() */
+ STACK_OF(X509_INFO) *inf;
+ STACK_OF(X509_NAME) *xnames;
+ X509_INFO *itmp;
+ X509_NAME *xname;
+ BIO *bio;
+ int i;
+
+ bio = BIO_new_mem_buf(t_strdup_noconst(ca), strlen(ca));
+ if (bio == NULL)
+ i_fatal("BIO_new_mem_buf() failed");
+ inf = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
+ if (inf == NULL)
+ i_fatal("Couldn't parse ssl_ca: %s", ssl_last_error());
+ BIO_free(bio);
+
+ xnames = sk_X509_NAME_new_null();
+ if (xnames == NULL)
+ i_fatal("sk_X509_NAME_new_null() failed");
+ for(i = 0; i < sk_X509_INFO_num(inf); i++) {
+ itmp = sk_X509_INFO_value(inf, i);
+ if(itmp->x509) {
+ X509_STORE_add_cert(store, itmp->x509);
+ xname = X509_get_subject_name(itmp->x509);
+ if (xname != NULL)
+ xname = X509_NAME_dup(xname);
+ if (xname != NULL)
+ sk_X509_NAME_push(xnames, xname);
+ }
+ if(itmp->crl)
+ X509_STORE_add_crl(store, itmp->crl);
+ }
+ sk_X509_INFO_pop_free(inf, X509_INFO_free);
+ return xnames;
+}
+
+static STACK_OF(X509_NAME) *
ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set)
{
+ X509_STORE *store;
+ STACK_OF(X509_NAME) *xnames = NULL;
+
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
-
- if (*set->ssl_ca_file != '\0') {
- if (SSL_CTX_load_verify_locations(ssl_ctx, set->ssl_ca_file,
- NULL) != 1) {
- i_fatal("Can't load CA file %s: %s",
- set->ssl_ca_file, ssl_last_error());
- }
+ if (*set->ssl_ca != '\0') {
+ /* set trusted CA certs */
+ store = SSL_CTX_get_cert_store(ssl_ctx);
+ xnames = load_ca(store, set->ssl_ca);
}
SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback);
if (SSL_CTX_need_tmp_RSA(ssl_ctx))
SSL_CTX_set_tmp_rsa_callback(ssl_ctx, ssl_gen_rsa_key);
SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_tmp_dh_callback);
+ return xnames;
}
static void
-ssl_proxy_ctx_verify_client(SSL_CTX *ssl_ctx, const char *ca_file)
+ssl_proxy_ctx_verify_client(SSL_CTX *ssl_ctx, STACK_OF(X509_NAME) *ca_names)
{
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
X509_STORE *store;
@@ -899,7 +938,8 @@ ssl_proxy_ctx_verify_client(SSL_CTX *ssl
#endif
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
ssl_verify_client_cert);
- SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(ca_file));
+ /* set list of CA names that are sent to client */
+ SSL_CTX_set_client_CA_list(ssl_ctx, ca_names);
}
static const char *ssl_proxy_get_use_certificate_error(const char *cert)
@@ -1043,20 +1083,21 @@ ssl_server_context_init(const struct log
struct ssl_server_context *ctx;
SSL_CTX *ssl_ctx;
pool_t pool;
+ STACK_OF(X509_NAME) *xnames;
pool = pool_alloconly_create("ssl server context", 2048);
ctx = i_new(struct ssl_server_context, 1);
ctx->pool = pool;
ctx->cert = p_strdup(pool, set->ssl_cert);
ctx->key = p_strdup(pool, set->ssl_key);
- ctx->ca_file = p_strdup(pool, set->ssl_ca_file);
+ ctx->ca = p_strdup(pool, set->ssl_ca);
ctx->cipher_list = p_strdup(pool, set->ssl_cipher_list);
ctx->verify_client_cert = set->ssl_verify_client_cert;
ctx->ctx = ssl_ctx = SSL_CTX_new(SSLv23_server_method());
if (ssl_ctx == NULL)
i_fatal("SSL_CTX_new() failed");
- ssl_proxy_ctx_init(ssl_ctx, set);
+ xnames = ssl_proxy_ctx_init(ssl_ctx, set);
if (SSL_CTX_set_cipher_list(ssl_ctx, ctx->cipher_list) != 1) {
i_fatal("Can't set cipher list to '%s': %s",
@@ -1080,7 +1121,7 @@ ssl_server_context_init(const struct log
SSL_CTX_set_info_callback(ctx->ctx, ssl_info_callback);
if (ctx->verify_client_cert)
- ssl_proxy_ctx_verify_client(ctx->ctx, ctx->ca_file);
+ ssl_proxy_ctx_verify_client(ctx->ctx, xnames);
hash_table_insert(ssl_servers, ctx, ctx);
return ctx;
@@ -1096,10 +1137,12 @@ static void ssl_server_context_deinit(st
static void ssl_proxy_init_client(const struct login_settings *set)
{
+ STACK_OF(X509_NAME) *xnames;
+
if ((ssl_client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
i_fatal("SSL_CTX_new() failed");
- ssl_proxy_ctx_init(ssl_client_ctx, set);
- ssl_proxy_ctx_verify_client(ssl_client_ctx, set->ssl_ca_file);
+ xnames = ssl_proxy_ctx_init(ssl_client_ctx, set);
+ ssl_proxy_ctx_verify_client(ssl_client_ctx, xnames);
}
void ssl_proxy_init(void)
More information about the dovecot-cvs
mailing list