mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-03-18 13:05:57 +00:00
fix(mail): check if smime certificate matches sender address
Fixes #5407
This commit is contained in:
@@ -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>
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user