dovecot-2.0: Renamed ssl_cert_file to ssl_cert and ssl_key_file ...

dovecot at dovecot.org dovecot at dovecot.org
Thu May 14 02:52:43 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/c38f3fb4c6b6
changeset: 9275:c38f3fb4c6b6
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 13 19:52:25 2009 -0400
description:
Renamed ssl_cert_file to ssl_cert and ssl_key_file to ssl_key.
Instead of pointing to files they now contain the certs directly.

diffstat:

4 files changed, 88 insertions(+), 55 deletions(-)
dovecot-example.conf                 |    6 -
src/login-common/login-settings.c    |   26 ++------
src/login-common/login-settings.h    |    4 -
src/login-common/ssl-proxy-openssl.c |  107 +++++++++++++++++++++++-----------

diffs (240 lines):

diff -r 39c2db5f1fcc -r c38f3fb4c6b6 dovecot-example.conf
--- a/dovecot-example.conf	Wed May 13 19:51:34 2009 -0400
+++ b/dovecot-example.conf	Wed May 13 19:52:25 2009 -0400
@@ -15,7 +15,7 @@
 # or plugin settings are added by default, they're listed only as examples.
 # Paths are also just examples with the real defaults being based on configure
 # options. The paths listed here are for configure --prefix=/usr
-# --sysconfdir=/etc --localstatedir=/var --with-ssldir=/etc/ssl
+# --sysconfdir=/etc --localstatedir=/var
 
 # Base directory where to store runtime data.
 #base_dir = /var/run/dovecot/
@@ -93,8 +93,8 @@
 # dropping root privileges, so keep the key file unreadable by anyone but
 # root. Included doc/mkcert.sh can be used to easily generate self-signed
 # certificate, just make sure to update the domains in dovecot-openssl.cnf
-#ssl_cert_file = /etc/ssl/certs/dovecot.pem
-#ssl_key_file = /etc/ssl/private/dovecot.pem
+ssl_cert_file = </etc/ssl/certs/dovecot.pem
+ssl_key_file = </etc/ssl/private/dovecot.pem
 
 # If key file is password protected, give the password here. Alternatively
 # give it when starting dovecot with -p parameter. Since this file is often
diff -r 39c2db5f1fcc -r c38f3fb4c6b6 src/login-common/login-settings.c
--- a/src/login-common/login-settings.c	Wed May 13 19:51:34 2009 -0400
+++ b/src/login-common/login-settings.c	Wed May 13 19:52:25 2009 -0400
@@ -26,8 +26,8 @@ static struct setting_define login_setti
 
 	DEF(SET_ENUM, ssl),
 	DEF(SET_STR, ssl_ca_file),
-	DEF(SET_STR, ssl_cert_file),
-	DEF(SET_STR, ssl_key_file),
+	DEF(SET_STR, ssl_cert),
+	DEF(SET_STR, ssl_key),
 	DEF(SET_STR, ssl_key_password),
 	DEF(SET_STR, ssl_parameters_file),
 	DEF(SET_STR, ssl_cipher_list),
@@ -60,8 +60,8 @@ static struct login_settings login_defau
 
 	MEMBER(ssl) "yes:no:required",
 	MEMBER(ssl_ca_file) "",
-	MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
-	MEMBER(ssl_key_file) SSLDIR"/private/dovecot.pem",
+	MEMBER(ssl_cert) "",
+	MEMBER(ssl_key) "",
 	MEMBER(ssl_key_password) "",
 	MEMBER(ssl_parameters_file) "ssl-parameters.dat",
 	MEMBER(ssl_cipher_list) "ALL:!LOW:!SSLv2",
@@ -103,12 +103,12 @@ static int ssl_settings_check(void *_set
 				   set->ssl);
 	return FALSE;
 #else
-	if (*set->ssl_cert_file == '\0') {
-		*error_r = "ssl_cert_file not set";
+	if (*set->ssl_cert == '\0') {
+		*error_r = "ssl enabled, but ssl_cert not set";
 		return FALSE;
 	}
-	if (*set->ssl_key_file == '\0') {
-		*error_r = "ssl_key_file not set";
+	if (*set->ssl_key == '\0') {
+		*error_r = "ssl enabled, but ssl_key not set";
 		return FALSE;
 	}
 	if (set->ssl_verify_client_cert && *set->ssl_ca_file == '\0') {
@@ -117,16 +117,6 @@ static int ssl_settings_check(void *_set
 	}
 
 #ifndef CONFIG_BINARY
-	if (access(set->ssl_cert_file, R_OK) < 0) {
-		*error_r = t_strdup_printf("ssl_cert_file: access(%s) failed: %m",
-					   set->ssl_cert_file);
-		return FALSE;
-	}
-	if (access(set->ssl_key_file, R_OK) < 0) {
-		*error_r = t_strdup_printf("ssl_key_file: access(%s) failed: %m",
-					   set->ssl_key_file);
-		return FALSE;
-	}
 	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);
diff -r 39c2db5f1fcc -r c38f3fb4c6b6 src/login-common/login-settings.h
--- a/src/login-common/login-settings.h	Wed May 13 19:51:34 2009 -0400
+++ b/src/login-common/login-settings.h	Wed May 13 19:52:25 2009 -0400
@@ -14,8 +14,8 @@ struct login_settings {
 
 	const char *ssl;
 	const char *ssl_ca_file;
-	const char *ssl_cert_file;
-	const char *ssl_key_file;
+	const char *ssl_cert;
+	const char *ssl_key;
 	const char *ssl_key_password;
 	const char *ssl_parameters_file;
 	const char *ssl_cipher_list;
diff -r 39c2db5f1fcc -r c38f3fb4c6b6 src/login-common/ssl-proxy-openssl.c
--- a/src/login-common/ssl-proxy-openssl.c	Wed May 13 19:51:34 2009 -0400
+++ b/src/login-common/ssl-proxy-openssl.c	Wed May 13 19:52:25 2009 -0400
@@ -765,22 +765,9 @@ unsigned int ssl_proxy_get_count(void)
 	return ssl_proxy_count;
 }
 
-static bool is_pem_key_file(const char *path)
-{
-	char buf[4096];
-	int fd, ret;
-
-	/* this code is used only for giving a better error message,
-	   so it needs to catch only the normal key files */
-	fd = open(path, O_RDONLY);
-	if (fd == -1)
-		return FALSE;
-	ret = read(fd, buf, sizeof(buf)-1);
-	close(fd);
-	if (ret <= 0)
-		return FALSE;
-	buf[ret] = '\0';
-	return strstr(buf, "PRIVATE KEY---") != NULL;
+static bool is_pem_key(const char *cert)
+{
+	return strstr(cert, "PRIVATE KEY---") != NULL;
 }
 
 static void
@@ -818,8 +805,60 @@ ssl_proxy_ctx_verify_client(SSL_CTX *ssl
 				   SSL_load_client_CA_file(set->ssl_ca_file));
 }
 
+static int
+ssl_proxy_ctx_use_certificate_chain(SSL_CTX *ctx, const char *cert)
+{
+	/* mostly just copy&pasted from SSL_CTX_use_certificate_chain_file() */
+	BIO *in;
+	int ret = 0;
+	X509 *x;
+
+	in = BIO_new_mem_buf(t_strdup_noconst(cert), strlen(cert));
+	if (in == NULL)
+		i_fatal("BIO_new_mem_buf() failed");
+
+	x = PEM_read_bio_X509(in, NULL, NULL, NULL);
+	if (x == NULL)
+		goto end;
+
+	ret = SSL_CTX_use_certificate(ctx, x);
+	if (ERR_peek_error() != 0)
+		ret = 0;
+
+	if (ret != 0) {
+		/* If we could set up our certificate, now proceed to
+		 * the CA certificates.
+		 */
+		X509 *ca;
+		int r;
+		unsigned long err;
+		
+		while ((ca = PEM_read_bio_X509(in,NULL,NULL,NULL)) != NULL) {
+			r = SSL_CTX_add_extra_chain_cert(ctx, ca);
+			if (!r) {
+				X509_free(ca);
+				ret = 0;
+				goto end;
+			}
+		}
+		/* When the while loop ends, it's usually just EOF. */
+		err = ERR_peek_last_error();
+		if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
+			ERR_clear_error();
+		else 
+			ret = 0; /* some real error */
+		}
+
+end:
+	if (x != NULL) X509_free(x);
+	if (in != NULL) BIO_free(in);
+	return ret;
+}
+
 static void ssl_proxy_init_server(const struct login_settings *set)
 {
+	BIO *bio;
+	EVP_PKEY *pkey;
 	char *password;
 	unsigned long err;
 
@@ -832,33 +871,37 @@ static void ssl_proxy_init_server(const 
 			set->ssl_cipher_list, ssl_last_error());
 	}
 
-	if (SSL_CTX_use_certificate_chain_file(ssl_server_ctx,
-					       set->ssl_cert_file) != 1) {
+	if (ssl_proxy_ctx_use_certificate_chain(ssl_server_ctx,
+						set->ssl_cert) != 1) {
 		err = ERR_peek_error();
 		if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
 		    ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
-			i_fatal("Can't load certificate file %s: %s",
-			set->ssl_cert_file, ssl_last_error());
-		} else if (is_pem_key_file(set->ssl_cert_file)) {
-			i_fatal("Can't load certificate file %s: "
+			i_fatal("Can't load ssl_cert: %s", ssl_last_error());
+		} else if (is_pem_key(set->ssl_cert)) {
+			i_fatal("Can't load ssl_cert: "
 				"The file contains a private key "
-				"(you've mixed ssl_cert_file and ssl_key_file settings)",
-				set->ssl_cert_file);
+				"(you've mixed ssl_cert and ssl_key settings)");
 		} else {
-			i_fatal("Can't load certificate file %s: "
-				"The file doesn't contain a certificate.",
-				set->ssl_cert_file);
+			i_fatal("Can't load ssl_cert: There is no certificate.");
 		}
 	}
 
 	password = t_strdup_noconst(set->ssl_key_password);
         SSL_CTX_set_default_passwd_cb(ssl_server_ctx, pem_password_callback);
         SSL_CTX_set_default_passwd_cb_userdata(ssl_server_ctx, password);
-	if (SSL_CTX_use_PrivateKey_file(ssl_server_ctx, set->ssl_key_file,
-					SSL_FILETYPE_PEM) != 1) {
-		i_fatal("Can't load private key file %s: %s",
-			set->ssl_key_file, ssl_last_error());
-	}
+
+	bio = BIO_new_mem_buf(t_strdup_noconst(set->ssl_key),
+			      strlen(set->ssl_key));
+	if (bio == NULL)
+		i_fatal("BIO_new_mem_buf() failed");
+	pkey = PEM_read_bio_PrivateKey(bio, NULL, pem_password_callback,
+				       password);
+	if (pkey == NULL)
+		i_fatal("Couldn't parse private ssl_key");
+	if (SSL_CTX_use_PrivateKey(ssl_server_ctx, pkey) != 1)
+		i_fatal("Can't load private ssl_key: %s", ssl_last_error());
+	EVP_PKEY_free(pkey);
+
 	safe_memset(password, 0, strlen(password));
 
 	if (set->verbose_ssl)


More information about the dovecot-cvs mailing list