# 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/
# 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
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),
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",
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') {
}
#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);
return ssl_proxy_count;
}
-static bool is_pem_key_file(const char *path)
+static bool is_pem_key(const char *cert)
{
- 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;
+ return strstr(cert, "PRIVATE KEY---") != NULL;
}
static void
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;
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)