diff options
Diffstat (limited to 'contrib/dma/crypto.c')
-rw-r--r-- | contrib/dma/crypto.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/contrib/dma/crypto.c b/contrib/dma/crypto.c index 37b255c18310..368238b9d632 100644 --- a/contrib/dma/crypto.c +++ b/contrib/dma/crypto.c @@ -40,6 +40,7 @@ #include <openssl/pem.h> #include <openssl/rand.h> +#include <strings.h> #include <string.h> #include <syslog.h> @@ -77,8 +78,31 @@ init_cert_file(SSL_CTX *ctx, const char *path) return (0); } +static int +verify_server_fingerprint(const X509 *cert) +{ + unsigned char fingerprint[EVP_MAX_MD_SIZE] = {0}; + unsigned int fingerprint_len = 0; + if(!X509_digest(cert, EVP_sha256(), fingerprint, &fingerprint_len)) { + syslog(LOG_WARNING, "failed to load fingerprint of server certicate: %s", + ssl_errstr()); + return (1); + } + if(fingerprint_len != SHA256_DIGEST_LENGTH) { + syslog(LOG_WARNING, "sha256 fingerprint has unexpected length of %d bytes", + fingerprint_len); + return (1); + } + if(memcmp(fingerprint, config.fingerprint, SHA256_DIGEST_LENGTH) != 0) { + syslog(LOG_WARNING, "fingerprints do not match"); + return (1); + } + syslog(LOG_DEBUG, "successfully verified server certificate fingerprint"); + return (0); +} + int -smtp_init_crypto(int fd, int feature) +smtp_init_crypto(int fd, int feature, struct smtp_features* features) { SSL_CTX *ctx = NULL; #if (OPENSSL_VERSION_NUMBER >= 0x00909000L) @@ -119,13 +143,12 @@ smtp_init_crypto(int fd, int feature) /* * If the user wants STARTTLS, we have to send EHLO here */ - if (((feature & SECURETRANS) != 0) && + if (((feature & SECURETRANSFER) != 0) && (feature & STARTTLS) != 0) { /* TLS init phase, disable SSL_write */ config.features |= NOSSL; - send_remote_command(fd, "EHLO %s", hostname()); - if (read_remote(fd, 0, NULL) == 2) { + if (perform_server_greeting(fd, features) == 0) { send_remote_command(fd, "STARTTLS"); if (read_remote(fd, 0, NULL) != 2) { if ((feature & TLS_OPP) == 0) { @@ -136,7 +159,12 @@ smtp_init_crypto(int fd, int feature) return (0); } } + } else { + syslog(LOG_ERR, "remote delivery deferred: could not perform server greeting: %s", + neterr); + return (1); } + /* End of TLS init phase, enable SSL_write/read */ config.features &= ~NOSSL; } @@ -161,7 +189,7 @@ smtp_init_crypto(int fd, int feature) /* Open SSL connection */ error = SSL_connect(config.ssl); - if (error < 0) { + if (error != 1) { syslog(LOG_ERR, "remote delivery deferred: SSL handshake failed fatally: %s", ssl_errstr()); return (1); @@ -172,6 +200,11 @@ smtp_init_crypto(int fd, int feature) if (cert == NULL) { syslog(LOG_WARNING, "remote delivery deferred: Peer did not provide certificate: %s", ssl_errstr()); + return (1); + } + if(config.fingerprint != NULL && verify_server_fingerprint(cert)) { + X509_free(cert); + return (1); } X509_free(cert); |