Skip to content

Commit

Permalink
fix(mail): check if smime certificate matches sender address
Browse files Browse the repository at this point in the history
Fixes #5407
  • Loading branch information
cgx committed Nov 22, 2021
1 parent 28b9224 commit e85576c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 69 deletions.
45 changes: 13 additions & 32 deletions UI/MailPartViewers/UIxMailPartEncryptedViewer.m
Expand Up @@ -25,6 +25,7 @@
#include <openssl/err.h>
#include <openssl/pkcs7.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#endif

#import <Foundation/NSDictionary.h>
Expand Down Expand Up @@ -96,6 +97,7 @@ - (X509_STORE *) _setupVerify
- (NSData *) _processMessageWith: (NSData *) signedData
{
NSData *output;
NSMutableArray *emails;

STACK_OF(X509) *certs;
X509_STORE *x509Store;
Expand All @@ -112,6 +114,7 @@ - (NSData *) _processMessageWith: (NSData *) signedData

certs = NULL;
certificates = [NSMutableArray array];
emails = [NSMutableArray array];
validationMessage = nil;

if (p7)
Expand All @@ -127,9 +130,16 @@ - (NSData *) _processMessageWith: (NSData *) signedData
{
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,
Expand Down Expand Up @@ -210,42 +220,13 @@ - (NSData *) _processMessageWith: (NSData *) signedData

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)
{
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 (![emails containsObject: senderAddress])
{
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)
Expand Down
47 changes: 13 additions & 34 deletions UI/MailPartViewers/UIxMailPartSignedViewer.m
Expand Up @@ -23,6 +23,7 @@
#include <openssl/err.h>
#include <openssl/pkcs7.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#endif

#import <Foundation/NSData.h>
Expand Down Expand Up @@ -93,6 +94,7 @@ - (X509_STORE *) _setupVerify
- (void) _processMessage
{
NSData *signedData;
NSMutableArray *emails;

STACK_OF(X509) *certs;
X509_STORE *x509Store;
Expand All @@ -114,6 +116,7 @@ - (void) _processMessage

certs = NULL;
certificates = [NSMutableArray array];
emails = [NSMutableArray array];
validationMessage = nil;

if (p7)
Expand All @@ -129,9 +132,16 @@ - (void) _processMessage
{
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,
Expand Down Expand Up @@ -201,46 +211,15 @@ - (void) _processMessage

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)
{
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 (![emails containsObject: senderAddress])
{
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)
Expand Down
3 changes: 0 additions & 3 deletions UI/MailerUI/English.lproj/Localizable.strings
Expand Up @@ -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";

Expand Down

0 comments on commit e85576c

Please sign in to comment.