Score:0

Dovecot Can't load SSL certificate (ssl_cert setting): There is no valid PEM certificate

kr flag
Xin

I met an issue while setting up IMAP email server with postfix, so I used letsencrypt to generate the certificates, and sending/receiving email works just fine.

But while I try to setup IMAP protocol with dovecot, I got errors like:

Jul  5 16:00:27 oraclecloud dovecot: imap-login: Error: Failed to initialize SSL server context: Can't load SSL certificate (ssl_cert setting): There is no valid PEM certificate.: user=<>, rip=37.xx.23x.xx, lip=10.0.0.200, session=<nev7qL7//xwl5O0s>
Jul  5 16:00:27 oraclecloud dovecot: auth: Debug: Loading modules from directory: /usr/lib/dovecot/modules/auth
Jul  5 16:00:27 oraclecloud dovecot: auth: Debug: Module loaded: /usr/lib/dovecot/modules/auth/lib20_auth_var_expand_crypt.so
Jul  5 16:00:27 oraclecloud dovecot: auth: Debug: Read auth token secret from /run/dovecot/auth-token-secret.dat

This error Can't load SSL certificate (ssl_cert setting): There is no valid PEM certificate. looks weird to me, because I do have a valid PEM certificate, under

/etc/letsencrypt/live/$mydomain_name/fullchain.pem

Output:

ubuntu@oraclecloud:~$ openssl s_client -servername $mydomain_name -connect $mydomain_name:993
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 314 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

/etc/postfix/main.cf

aaron@oraclecloud:~$ 
ubuntu@oraclecloud:~$ sudo cat /etc/postfix/main.cf

# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 3.6 on
# fresh installs.
compatibility_level = 3.6



# TLS parameters
smtpd_tls_cert_file = /etc/letsencrypt/live/$mydomain/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/$mydomain/privkey.pem
smtpd_tls_security_level = encrypt

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt
smtp_tls_security_level = encrypt
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/password
smtp_sasl_security_options =


smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
myhostname = $mydomain
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = $mydomain, localhost
relayhost =
mynetworks = *0/24
mailbox_size_limit = 0
recipient_delimiter = +                                                                                                                                                                                              

ubuntu@oraclecloud:~$ sudo cat /etc/dovecot/dovecot.conf

disable_plaintext_auth = yes
mail_privileged_group = mail
mail_location = maildir:~/Maildir
#set mailbox location to Maildir style

userdb {
      driver = passwd
}

passdb {
     args = %s
     driver = pam
}

protocols = "imap"

namespace inbox {
  inbox = yes

  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Spam {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Archive {
    auto = subscribe
    special_use = \Archive
  }
}
#create and autosubscribe to some default folders

service auth {
      unix_listener /var/spool/postfix/private/auth {
      mode = 0660
      user = postfix
      group = postfix
    }
}

ssl = required
ssl_cert = /etc/letsencrypt/live/$mydomain/fullchain.pem
ssl_key = /etc/letsencrypt/live/$mydomain/privkey.pem

# debugging
mail_debug = yes
auth_debug = yes
auth_verbose = yes
auth_verbose_passwords = plain
auth_debug_passwords = yes
#

10-ssl.conf

##
## SSL settings
##

# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
ssl = required

# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
# 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 = </etc/dovecot/private/dovecot.pem
# ssl_key = </etc/dovecot/private/dovecot.key
ssl_cert = </etc/letsencrypt/live/$mydomain/fullchain.pem
ssl_key = </etc/letsencrypt/live/$mydomain/privkey.pem

ssl_protocols = !SSLv2 !SSLv3

# If key file is password protected, give the password here. Alternatively
# give it when starting dovecot with -p parameter. Since this file is often
# world-readable, you may want to place this setting instead to a different
# root owned 0600 file by using ssl_key_password = <path.
#ssl_key_password =

# 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 = /etc/ssl/certs/ssl-cert-snakeoil.pem 

# Require that CRL check succeeds for client certificates.
#ssl_require_crl = yes

# Directory and/or file for trusted SSL CA certificates. These are used only
# when Dovecot needs to act as an SSL client (e.g. imapc backend or
# submission service). The directory is usually /etc/ssl/certs in
# Debian-based systems and the file is /etc/pki/tls/cert.pem in
# RedHat-based systems. Note that ssl_client_ca_file isn't recommended with
# large CA bundles, because it leads to excessive memory usage.
#ssl_client_ca_dir =
ssl_client_ca_dir = /etc/ssl/certs
#ssl_client_ca_file =

# Require valid cert when connecting to a remote server
#ssl_client_require_valid_cert = yes

# Request client to send a certificate. If you also want to require it, set
# auth_ssl_require_client_cert=yes in auth section.
#ssl_verify_client_cert = no

# Which field from certificate to use for username. commonName and
# x500UniqueIdentifier are the usual choices. You'll also need to set
# auth_ssl_username_from_cert=yes.
#ssl_cert_username_field = commonName

# SSL DH parameters
# Generate new params with `openssl dhparam -out /etc/dovecot/dh.pem 4096`
# Or migrate from old ssl-parameters.dat file with the command dovecot
# gives on startup when ssl_dh is unset.
ssl_dh = </usr/share/dovecot/dh.pem

# Minimum SSL protocol version to use. Potentially recognized values are SSLv3,
# TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3, depending on the OpenSSL version used.
#
# Dovecot also recognizes values ANY and LATEST. ANY matches with any protocol
# version, and LATEST matches with the latest version supported by library.
#ssl_min_protocol = TLSv1.2

# SSL ciphers to use, the default is:
#ssl_cipher_list = ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH
# To disable non-EC DH, use:
#ssl_cipher_list = ALL:!DH:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH

# Colon separated list of elliptic curves to use. Empty value (the default)
# means use the defaults from the SSL library. P-521:P-384:P-256 would be an
# example of a valid value.
#ssl_curve_list =

# Prefer the server's order of ciphers over client's.
#ssl_prefer_server_ciphers = no

# SSL crypto device to use, for valid values run "openssl engine"
#ssl_crypto_device =

# SSL extra options. Currently supported options are:
#   compression - Enable compression.
#   no_ticket - Disable SSL session tickets.
#ssl_options =
anx avatar
fr flag
anx
If you show your relevant configuration.. maybe even including the comment Dovecot ships in its default configuration right next to where the certificate path is specified, this might be easy to answer.
Xin avatar
kr flag
Xin
@anx just attached the conf files.
Score:0
fr flag
anx

Looks like you have set an option you did not intend to:

# Set this only if you intend to use ssl_verify_client_cert=yes.
ssl_ca = /etc/ssl/certs/ssl-cert-snakeoil.pem 

Also, when you specify a path to a file, you need to say so:

The < is mandatory. It indicates that the variable should contain contents of the file, instead of the file name. Not using it will cause an error.

Also, while postfix does allow you to specify variables like $mydomain, that is not something you can use that way (at least not literally) in dovecot. Specify the actual path.

ssl_cert = </etc/letsencrypt/live/mx.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mx.example.com/privkey.pem
Xin avatar
kr flag
Xin
thanks! I want to apologize for the confusion here, I don't actually use syntax $mydomain in conf for dovecot.
Xin avatar
kr flag
Xin
also, even I commented out ssl_ca, it still fail with the same reason...
anx avatar
fr flag
anx
@Xin After restarting the service, you can dump your non-default settings using the `doveconf -n` command - that should reveal whether all 3 changes are effective (the file path, the `<` prefix, and the extraneous setting)
jp flag
You could always use `example.com` as a placeholder if you don't want to disclose your domain. That'll help avoiding confusion, as variables are variables.
Xin avatar
kr flag
Xin
Hi guys, thank you all for the help! I started to use docker-mailserver and it works like a charm, I will say goodbye to the manual config..
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.