diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index ac1a229bf..86822e2ee 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -2503,6 +2503,18 @@ Defaults to `NO` when unset. |Parameter used to enable S/MIME certificate management from the account editor of the preferences window. +When a S/MIME signed message is displayed, the sender's certificate is +saved in the matching contact of the user's address books (and replaces any +existing one) only if the signature is valid and every signer certificate +is issued for the sender's email address. A signature is valid only if the +signer certificate chains to a certificate authority trusted by the system +(OpenSSL default CA store, for example `/etc/ssl/certs`). Certificates that +are self-signed or issued by a private CA are therefore not imported unless +that CA is added to the system trust store (for example in +`/usr/local/share/ca-certificates` followed by `update-ca-certificates` on +Debian/Ubuntu). Note that some distributions only ship the CAs trusted for +TLS servers, so the root CAs dedicated to S/MIME may also need to be added. + Defaults to `YES` when unset. |U |SOGoSelectedAddressBook diff --git a/UI/MailPartViewers/UIxMailPartSignedViewer.h b/UI/MailPartViewers/UIxMailPartSignedViewer.h index b9f8e2585..0a759135e 100644 --- a/UI/MailPartViewers/UIxMailPartSignedViewer.h +++ b/UI/MailPartViewers/UIxMailPartSignedViewer.h @@ -30,11 +30,13 @@ { BOOL processed; BOOL validSignature; + BOOL signersMatchSender; NSMutableArray *certificates; NSString *validationMessage; } - (BOOL) validSignature; +- (BOOL) signersMatchSender; - (NSString *) validationMessage; - (NSArray *) smimeCertificates; - (NSDictionary *) certificateForSubject: (NSString *) subject diff --git a/UI/MailPartViewers/UIxMailPartSignedViewer.m b/UI/MailPartViewers/UIxMailPartSignedViewer.m index 397be6d5d..f45dd89c7 100644 --- a/UI/MailPartViewers/UIxMailPartSignedViewer.m +++ b/UI/MailPartViewers/UIxMailPartSignedViewer.m @@ -94,8 +94,8 @@ - (void) _processMessage { NSData *signedData; - NSMutableArray *emails; - + NSMutableArray *emails, *signersEmails; + STACK_OF(X509) *certs; X509_STORE *x509Store; BIO *msgBio, *inData; @@ -117,6 +117,8 @@ certs = NULL; certificates = [NSMutableArray array]; emails = [NSMutableArray array]; + signersEmails = [NSMutableArray array]; + signersMatchSender = NO; validationMessage = nil; if (cms) @@ -138,13 +140,21 @@ char p[1024]; int j; STACK_OF(OPENSSL_STRING) *emlst; + NSMutableArray *signerEmails; + NSString *email; x = sk_X509_value(certs, i); + signerEmails = [NSMutableArray array]; 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]]; + { + email = [[NSString stringWithUTF8String: sk_OPENSSL_STRING_value(emlst, j)] lowercaseString]; + [emails addObject: email]; + [signerEmails addObject: email]; + } X509_email_free(emlst); + [signersEmails addObject: signerEmails]; memset(p, 0, 1024); buf = BIO_new(BIO_s_mem()); @@ -227,6 +237,15 @@ { validationMessage = [self labelForKey: @"Message is signed but the certificate doesn't match the sender email address"]; } + + // Every signer certificate must be issued for the sender address + if ([senderAddress length] && [signersEmails count]) + { + signersMatchSender = YES; + for (i = 0; i < [signersEmails count]; i++) + if (![[signersEmails objectAtIndex: i] containsObject: senderAddress]) + signersMatchSender = NO; + } } else if (!validationMessage) { @@ -244,6 +263,14 @@ return validSignature; } +- (BOOL) signersMatchSender +{ + if (!processed) + [self _processMessage]; + + return signersMatchSender; +} + - (NSDictionary *) certificateForSubject: (NSString *) subject andIssuer: (NSString *) issuer withEmails: (NSArray *) emails @@ -283,6 +310,11 @@ return NO; } +- (BOOL) signersMatchSender +{ + return NO; +} + - (NSString *) validationMessage { return nil; diff --git a/UI/MailerUI/UIxMailView.m b/UI/MailerUI/UIxMailView.m index 99660edc9..28587ef93 100644 --- a/UI/MailerUI/UIxMailView.m +++ b/UI/MailerUI/UIxMailView.m @@ -54,6 +54,7 @@ #import // cyclic #import #import +#import #import "WOContext+UIxMailer.h" #import "UIxMailFormatter.h" @@ -244,11 +245,16 @@ static NSString *mailETag = nil; // If we are looking at a S/MIME signed mail which wasn't sent // by our actual active user, we update the certificate of that - // sender in the user's address book + // sender in the user's address book. Only do so if the signature + // is valid (trusted chain) and every signer certificate is issued + // for the sender address. from = [[[[self clientObject] fromEnvelopeAddresses] lastObject] baseEMail]; if (![[context activeUser] hasEmail: from] && - [[self clientObject] isSigned]) + [[self clientObject] isSigned] && + [viewer isKindOfClass: NSClassFromString(@"UIxMailPartSignedViewer")] && + [viewer validSignature] && + [viewer signersMatchSender]) { SOGoContactFolders *contactFolders; NSData *p7s;