From e85576cbb7514876ac72fb60fd9da2e1b7545331 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Mon, 22 Nov 2021 15:31:39 -0500 Subject: [PATCH] fix(mail): check if smime certificate matches sender address Fixes #5407 --- .../UIxMailPartEncryptedViewer.m | 45 +++++------------- UI/MailPartViewers/UIxMailPartSignedViewer.m | 47 +++++-------------- UI/MailerUI/English.lproj/Localizable.strings | 3 -- 3 files changed, 26 insertions(+), 69 deletions(-) diff --git a/UI/MailPartViewers/UIxMailPartEncryptedViewer.m b/UI/MailPartViewers/UIxMailPartEncryptedViewer.m index a35400bc1..d4c1554dd 100644 --- a/UI/MailPartViewers/UIxMailPartEncryptedViewer.m +++ b/UI/MailPartViewers/UIxMailPartEncryptedViewer.m @@ -25,6 +25,7 @@ #include #include #include +#include #endif #import @@ -96,6 +97,7 @@ - (NSData *) _processMessageWith: (NSData *) signedData { NSData *output; + NSMutableArray *emails; STACK_OF(X509) *certs; X509_STORE *x509Store; @@ -112,6 +114,7 @@ certs = NULL; certificates = [NSMutableArray array]; + emails = [NSMutableArray array]; validationMessage = nil; if (p7) @@ -127,9 +130,16 @@ { BIO *buf; char p[1024]; + int j; + STACK_OF(OPENSSL_STRING) *emlst; x = sk_X509_value(certs, i); + emlst = X509_get1_email(x); + for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) + [emails addObject: [[NSString stringWithUTF8String: sk_OPENSSL_STRING_value(emlst, j)] lowercaseString]]; + X509_email_free(emlst); + memset(p, 0, 1024); buf = BIO_new(BIO_s_mem()); X509_NAME_print_ex(buf, X509_get_subject_name(x), 0, @@ -210,42 +220,13 @@ if (validSignature) { - BOOL hasMatchingAddress; - NSArray *pair; - NSDictionary *certificate, *values; - NSEnumerator *certificatesList, *subjectList; - NSString *senderAddress, *label, *value; + NSString *senderAddress; validationMessage = [self labelForKey: @"Message is signed"]; - hasMatchingAddress = NO; - value = nil; senderAddress = [[[[[self clientObject] fromEnvelopeAddresses] lastObject] baseEMail] lowercaseString]; - certificatesList = [certificates objectEnumerator]; - while ((certificate = [certificatesList nextObject]) && !hasMatchingAddress) + if (![emails containsObject: senderAddress]) { - subjectList = [[certificate objectForKey: @"subject"] objectEnumerator]; - while ((pair = [subjectList nextObject]) && !hasMatchingAddress) - { - label = [[pair objectAtIndex: 0] lowercaseString]; - value = [[pair objectAtIndex: 1] lowercaseString]; - if ([label isEqualToString: @"commonname"] && [value isEqualToString: senderAddress]) - { - hasMatchingAddress = 1; - } - } - } - - if (!hasMatchingAddress) - { - if (value) - { - values = [NSDictionary dictionaryWithObjectsAndKeys: value, @"certificateCn", nil]; - validationMessage = [values keysWithFormat: [self labelForKey: @"Message is signed but the certificate (%{certificateCn}) doesn't match the sender email address"]]; - } - else - { - validationMessage = [self labelForKey: @"Message is signed but the certificate doesn't match the sender email address"]; - } + validationMessage = [self labelForKey: @"Message is signed but the certificate doesn't match the sender email address"]; } } else if (!validationMessage) diff --git a/UI/MailPartViewers/UIxMailPartSignedViewer.m b/UI/MailPartViewers/UIxMailPartSignedViewer.m index e0364269e..6347040be 100644 --- a/UI/MailPartViewers/UIxMailPartSignedViewer.m +++ b/UI/MailPartViewers/UIxMailPartSignedViewer.m @@ -23,6 +23,7 @@ #include #include #include +#include #endif #import @@ -93,6 +94,7 @@ - (void) _processMessage { NSData *signedData; + NSMutableArray *emails; STACK_OF(X509) *certs; X509_STORE *x509Store; @@ -114,6 +116,7 @@ certs = NULL; certificates = [NSMutableArray array]; + emails = [NSMutableArray array]; validationMessage = nil; if (p7) @@ -129,9 +132,16 @@ { BIO *buf; char p[1024]; + int j; + STACK_OF(OPENSSL_STRING) *emlst; x = sk_X509_value(certs, i); + emlst = X509_get1_email(x); + for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) + [emails addObject: [[NSString stringWithUTF8String: sk_OPENSSL_STRING_value(emlst, j)] lowercaseString]]; + X509_email_free(emlst); + memset(p, 0, 1024); buf = BIO_new(BIO_s_mem()); X509_NAME_print_ex(buf, X509_get_subject_name(x), 0, @@ -201,46 +211,15 @@ if (validSignature) { - BOOL hasMatchingAddress; - NSArray *pair, *attributes; - NSDictionary *certificate, *values; - NSEnumerator *certificatesList, *subjectList; - NSString *senderAddress, *label, *value; + NSString *senderAddress; // See https://datatracker.ietf.org/doc/html/rfc8550#section-3 // See https://datatracker.ietf.org/doc/html/rfc8550#section-4.4.3 - // TODO: handle multiple email addresses in SubjectAltName - attributes = [NSArray arrayWithObjects: @"commonname", @"subjectaltname", @"emailaddress", nil]; validationMessage = [self labelForKey: @"Message is signed"]; - hasMatchingAddress = NO; - value = nil; senderAddress = [[[[[self clientObject] fromEnvelopeAddresses] lastObject] baseEMail] lowercaseString]; - certificatesList = [certificates objectEnumerator]; - while ((certificate = [certificatesList nextObject]) && !hasMatchingAddress) + if (![emails containsObject: senderAddress]) { - subjectList = [[certificate objectForKey: @"subject"] objectEnumerator]; - while ((pair = [subjectList nextObject]) && !hasMatchingAddress) - { - label = [[pair objectAtIndex: 0] lowercaseString]; - value = [[pair objectAtIndex: 1] lowercaseString]; - if ([attributes containsObject: label] && [value isEqualToString: senderAddress]) - { - hasMatchingAddress = 1; - } - } - } - - if (!hasMatchingAddress) - { - if (value) - { - values = [NSDictionary dictionaryWithObjectsAndKeys: value, @"certificateCn", nil]; - validationMessage = [values keysWithFormat: [self labelForKey: @"Message is signed but the certificate (%{certificateCn}) doesn't match the sender email address"]]; - } - else - { - validationMessage = [self labelForKey: @"Message is signed but the certificate doesn't match the sender email address"]; - } + validationMessage = [self labelForKey: @"Message is signed but the certificate doesn't match the sender email address"]; } } else if (!validationMessage) diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index e04d278ed..86a521014 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -302,9 +302,6 @@ /* Valid S/MIME signature */ "Message is signed" = "Message is signed"; -/* Valid S/MIME signature but common name doesn't match */ -"Message is signed but the certificate (%{certificateCn}) doesn't match the sender email address" = "Message is signed but the certificate (%{certificateCn}) doesn't match the sender email address"; - /* Valid S/MIME signature but common name not found */ "Message is signed but the certificate doesn't match the sender email address" = "Message is signed but the certificate doesn't match the sender email address";