Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added option to verify server's cert fingerprint #71

Merged
merged 2 commits into from
Dec 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,22 @@ parse_conf(const char *config_path)
config.masquerade_user = user;
} else if (strcmp(word, "STARTTLS") == 0 && data == NULL)
config.features |= STARTTLS;
else if (strcmp(word, "OPPORTUNISTIC_TLS") == 0 && data == NULL)
else if (strcmp(word, "FINGERPRINT") == 0) {
if (strlen(data) != SHA256_DIGEST_LENGTH * 2) {
errlogx(EX_CONFIG, "invalid sha256 fingerprint length");
}
unsigned char *fingerprint = malloc(SHA256_DIGEST_LENGTH);
if (fingerprint == NULL) {
errlogx(EX_CONFIG, "fingerprint allocation failed");
}
for (unsigned int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
if(sscanf(data + 2 * i, "%02hhx", &fingerprint[i]) != 1) {
errlogx(EX_CONFIG, "failed to read fingerprint");
}
}
free(data);
config.fingerprint = fingerprint;
} else if (strcmp(word, "OPPORTUNISTIC_TLS") == 0 && data == NULL)
config.features |= TLS_OPP;
else if (strcmp(word, "SECURETRANSFER") == 0 && data == NULL)
config.features |= SECURETRANS;
Expand Down
28 changes: 28 additions & 0 deletions crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,29 @@ init_cert_file(SSL_CTX *ctx, const char *path)
return (0);
}

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, struct smtp_features* features)
{
Expand Down Expand Up @@ -173,6 +196,11 @@ smtp_init_crypto(int fd, int feature, struct smtp_features* features)
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);

Expand Down
3 changes: 3 additions & 0 deletions dma.8
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ Uncomment if you want TLS/SSL secured transfer.
Uncomment if you want to use STARTTLS.
Only useful together with
.Sq SECURETRANS .
.It Ic FINGERPRINT Xo
Pin the server certificate by specifying its SHA256 fingerprint.
Only makes sense if you use a smarthost.
.It Ic OPPORTUNISTIC_TLS Xo
(boolean, default=commented)
.Xc
Expand Down
1 change: 1 addition & 0 deletions dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct config config = {
.mailname = NULL,
.masquerade_host = NULL,
.masquerade_user = NULL,
.fingerprint = NULL,
};


Expand Down
4 changes: 4 additions & 0 deletions dma.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
# SECURETRANSFER)
#STARTTLS

# Pin the server certificate by specifying its SHA256 fingerprint.
# Only makes sense if you use a smarthost.
#FINGERPRINT 1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF

# Uncomment if you have specified STARTTLS above and it should be allowed
# to fail ("opportunistic TLS", use an encrypted connection when available
# but allow an unencrypted one to servers that do not support it)
Expand Down
1 change: 1 addition & 0 deletions dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ struct config {
const char *mailname;
const char *masquerade_host;
const char *masquerade_user;
const unsigned char *fingerprint;

/* XXX does not belong into config */
SSL *ssl;
Expand Down