changeset 3889:c7462001227b HEAD

Added support for password protected SSL private keys. The password can be given in dovecot.conf, or when dovecot is started with -p parameter.
author Timo Sirainen <tss@iki.fi>
date Sun, 15 Jan 2006 15:16:53 +0200
parents 650701d41cdf
children 6658a000051d
files dovecot-example.conf src/login-common/ssl-proxy-openssl.c src/master/Makefile.am src/master/common.h src/master/login-process.c src/master/main.c src/master/master-settings.c src/master/master-settings.h
diffstat 8 files changed, 54 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Sun Jan 15 14:35:01 2006 +0200
+++ b/dovecot-example.conf	Sun Jan 15 15:16:53 2006 +0200
@@ -40,6 +40,10 @@
 #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.
+#ssl_key_password =
+
 # File containing trusted SSL certificate authorities. Usually not needed.
 #ssl_ca_file = 
 
--- a/src/login-common/ssl-proxy-openssl.c	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/login-common/ssl-proxy-openssl.c	Sun Jan 15 15:16:53 2006 +0200
@@ -588,9 +588,25 @@
 	return 1;
 }
 
+static int
+pem_password_callback(char *buf, int size, int rwflag __attr_unused__,
+		      void *userdata)
+{
+	if (userdata == NULL) {
+		i_error("SSL private key file is password protected, "
+			"but password isn't given");
+		return 0;
+	}
+
+	if (strocpy(buf, userdata, size) < 0)
+		return 0;
+	return strlen(buf);
+}
+
 void ssl_proxy_init(void)
 {
 	const char *cafile, *certfile, *keyfile, *cipher_list;
+	char *password;
 	unsigned char buf;
 
 	memset(&ssl_params, 0, sizeof(ssl_params));
@@ -599,6 +615,7 @@
 	certfile = getenv("SSL_CERT_FILE");
 	keyfile = getenv("SSL_KEY_FILE");
 	ssl_params.fname = getenv("SSL_PARAM_FILE");
+	password = getenv("SSL_KEY_PASSWORD");
 
 	if (certfile == NULL || keyfile == NULL || ssl_params.fname == NULL) {
 		/* SSL support is disabled */
@@ -635,6 +652,8 @@
 			certfile, ssl_last_error());
 	}
 
+        SSL_CTX_set_default_passwd_cb(ssl_ctx, pem_password_callback);
+        SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, password);
 	if (SSL_CTX_use_PrivateKey_file(ssl_ctx, keyfile,
 					SSL_FILETYPE_PEM) != 1) {
 		i_fatal("Can't load private key file %s: %s",
--- a/src/master/Makefile.am	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/master/Makefile.am	Sun Jan 15 15:16:53 2006 +0200
@@ -18,6 +18,7 @@
 
 dovecot_SOURCES = \
 	auth-process.c \
+	askpass.c \
 	dict-process.c \
 	log.c \
 	login-process.c \
@@ -31,6 +32,7 @@
 
 noinst_HEADERS = \
 	auth-process.h \
+	askpass.h \
 	dict-process.h \
 	common.h \
 	log.h \
--- a/src/master/common.h	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/master/common.h	Sun Jan 15 15:16:53 2006 +0200
@@ -25,6 +25,7 @@
 extern int null_fd, inetd_login_fd;
 extern uid_t master_uid;
 extern const char *process_names[];
+extern char ssl_manual_key_password[];
 
 #define IS_INETD() \
 	(inetd_login_fd != -1)
--- a/src/master/login-process.c	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/master/login-process.c	Sun Jan 15 15:16:53 2006 +0200
@@ -404,6 +404,11 @@
 	env_put("DOVECOT_MASTER=1");
 
 	if (!set->ssl_disable) {
+		const char *ssl_key_password = NULL;
+
+		ssl_key_password = set->ssl_key_password != NULL ?
+			set->ssl_key_password : ssl_manual_key_password;
+
 		if (set->ssl_ca_file != NULL) {
 			env_put(t_strconcat("SSL_CA_FILE=",
 					    set->ssl_ca_file, NULL));
@@ -412,6 +417,8 @@
 				    set->ssl_cert_file, NULL));
 		env_put(t_strconcat("SSL_KEY_FILE=",
 				    set->ssl_key_file, NULL));
+		env_put(t_strconcat("SSL_KEY_PASSWORD=",
+				    ssl_key_password, NULL));
 		env_put(t_strconcat("SSL_PARAM_FILE=",
 				    set->ssl_parameters_file, NULL));
 		if (set->ssl_cipher_list != NULL) {
--- a/src/master/main.c	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/master/main.c	Sun Jan 15 15:16:53 2006 +0200
@@ -8,6 +8,7 @@
 #include "fd-close-on-exec.h"
 #include "write-full.h"
 
+#include "askpass.h"
 #include "auth-process.h"
 #include "dict-process.h"
 #include "login-process.h"
@@ -42,6 +43,7 @@
 struct hash_table *pids;
 int null_fd, inetd_login_fd;
 uid_t master_uid;
+char ssl_manual_key_password[100];
 #ifdef DEBUG
 static bool gdb;
 #endif
@@ -697,7 +699,7 @@
 {
 	/* parse arguments */
 	const char *exec_protocol = NULL, *exec_section = NULL;
-	bool foreground = FALSE;
+	bool foreground = FALSE, ask_key_pass = FALSE;
 	int i;
 
 #ifdef DEBUG
@@ -716,6 +718,9 @@
 			i++;
 			if (i == argc) i_fatal("Missing config file argument");
 			configfile = argv[i];
+		} else if (strcmp(argv[i], "-p") == 0) {
+			/* Ask SSL private key password */
+			ask_key_pass = TRUE;
 		} else if (strcmp(argv[i], "--exec-mail") == 0) {
 			/* <protocol> [<server section>]
 			   read configuration and execute mail process */
@@ -750,6 +755,18 @@
 	if (!master_settings_read(configfile, exec_protocol != NULL))
 		exit(FATAL_DEFAULT);
 
+	if (ask_key_pass) {
+		const char *prompt;
+
+		t_push();
+		prompt = t_strdup_printf("Give the password for SSL key file "
+					 "%s: ",
+					 settings_root->defaults->ssl_key_file);
+		askpass(prompt, ssl_manual_key_password,
+			sizeof(ssl_manual_key_password));
+		t_pop();
+	}
+
 	if (exec_protocol != NULL)
 		mail_process_exec(exec_protocol, exec_section);
 
--- a/src/master/master-settings.c	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/master/master-settings.c	Sun Jan 15 15:16:53 2006 +0200
@@ -60,6 +60,7 @@
 	DEF(SET_STR, ssl_ca_file),
 	DEF(SET_STR, ssl_cert_file),
 	DEF(SET_STR, ssl_key_file),
+	DEF(SET_STR, ssl_key_password),
 	DEF(SET_STR, ssl_parameters_file),
 	DEF(SET_STR, ssl_parameters_regenerate),
 	DEF(SET_STR, ssl_cipher_list),
@@ -256,6 +257,7 @@
 	MEMBER(ssl_ca_file) NULL,
 	MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
 	MEMBER(ssl_key_file) SSLDIR"/private/dovecot.pem",
+	MEMBER(ssl_key_password) NULL,
 	MEMBER(ssl_parameters_file) "ssl-parameters.dat",
 	MEMBER(ssl_parameters_regenerate) 168,
 	MEMBER(ssl_cipher_list) NULL,
--- a/src/master/master-settings.h	Sun Jan 15 14:35:01 2006 +0200
+++ b/src/master/master-settings.h	Sun Jan 15 15:16:53 2006 +0200
@@ -30,6 +30,7 @@
 	const char *ssl_ca_file;
 	const char *ssl_cert_file;
 	const char *ssl_key_file;
+	const char *ssl_key_password;
 	const char *ssl_parameters_file;
 	unsigned int ssl_parameters_regenerate;
 	const char *ssl_cipher_list;