Skip to content

Commit

Permalink
[FIX] Always use the specific PGP key selected from the „From“ dropdo…
Browse files Browse the repository at this point in the history
…wn menu [#895 state:fixed]

- Adds option to GMComposeMessagePreferredSecurityProperties to set a specific PGP key which is used, instead of querying the keyring for a key matching the email address.
   This is especially important if multiple private keys are available for the same email address.
  • Loading branch information
lukele committed Aug 24, 2017
1 parent fe78272 commit c1f2cbd
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 14 deletions.
3 changes: 2 additions & 1 deletion Source/ComposeBackEnd+GPGMail.m
Expand Up @@ -1025,7 +1025,8 @@ - (void)MAUpdateSMIMEStatus:(CDUnknownBlockType)onComplete {
// If there are already preferredSecurityProperties determined, copy the userShouldSignMessage and
// userShouldEncryptMessage on to the new security properties.
GMComposeMessagePreferredSecurityProperties *currentSecurityProperties = self.preferredSecurityProperties;
GMComposeMessagePreferredSecurityProperties *preferredSecurityProperties = [[GMComposeMessagePreferredSecurityProperties alloc] initWithSender:sender recipients:recipients userShouldSignMessage:currentSecurityProperties ? currentSecurityProperties.userShouldSignMessage : ThreeStateBooleanUndetermined userShouldEncryptMessage:currentSecurityProperties ? currentSecurityProperties.userShouldEncryptMessage : ThreeStateBooleanUndetermined];
GPGKey *signingKey = [currentSecurityProperties.signingSender isEqualToString:sender] ? currentSecurityProperties.signingKey : nil;
GMComposeMessagePreferredSecurityProperties *preferredSecurityProperties = [[GMComposeMessagePreferredSecurityProperties alloc] initWithSender:sender signingKey:signingKey recipients:recipients userShouldSignMessage:currentSecurityProperties ? currentSecurityProperties.userShouldSignMessage : ThreeStateBooleanUndetermined userShouldEncryptMessage:currentSecurityProperties ? currentSecurityProperties.userShouldEncryptMessage : ThreeStateBooleanUndetermined];
preferredSecurityProperties.cachedSigningIdentities = [self valueForKey:@"_signingIdentities"];
preferredSecurityProperties.cachedEncryptionCertificates = [self valueForKey:@"_encryptionCertificates"];

Expand Down
10 changes: 9 additions & 1 deletion Source/GMComposeMessagePreferredSecurityProperties.h
Expand Up @@ -34,17 +34,22 @@ typedef enum {

ThreeStateBoolean _userShouldSignMessage;
ThreeStateBoolean _userShouldEncryptMessage;

GPGKey *_signingKey;
NSString *_signingSender;
}

+ (GPGMAIL_SECURITY_METHOD)defaultSecurityMethod;

- (id)initWithSender:(NSString *)sender recipients:(NSArray *)recipients;
- (id)initWithSender:(NSString *)sender recipients:(NSArray *)recipients userShouldSignMessage:(ThreeStateBoolean)userShouldSignMessage userShouldEncryptMessage:(ThreeStateBoolean)userShouldEncryptMessage;
- (id)initWithSender:(NSString *)sender signingKey:(GPGKey *)signingKey recipients:(NSArray *)recipients userShouldSignMessage:(ThreeStateBoolean)userShouldSignMessage userShouldEncryptMessage:(ThreeStateBoolean)userShouldEncryptMessage;

- (void)addHintsFromBackEnd:(ComposeBackEnd *)backEnd;

- (void)computePreferredSecurityPropertiesForSecurityMethod:(GPGMAIL_SECURITY_METHOD)securityMethod;

- (void)updateSigningKey:(GPGKey *)signingKey forSender:(NSString *)sender;

- (GPGKey *)encryptionKeyForDraft;

@property (nonatomic, readonly, assign) BOOL canPGPSign;
Expand Down Expand Up @@ -81,6 +86,9 @@ typedef enum {
@property (nonatomic, copy) NSString *sender;
@property (nonatomic, copy) NSArray *recipients;

@property (nonatomic, readonly, retain) GPGKey *signingKey;
@property (nonatomic, readonly, retain) NSString *signingSender;

@property (nonatomic, copy) NSDictionary *cachedSigningIdentities;
@property (nonatomic, copy) NSDictionary *cachedEncryptionCertificates;

Expand Down
36 changes: 27 additions & 9 deletions Source/GMComposeMessagePreferredSecurityProperties.m
Expand Up @@ -57,10 +57,12 @@ - (id)initWithSender:(NSString *)sender recipients:(NSArray *)recipients {
return self;
}

- (id)initWithSender:(NSString *)sender recipients:(NSArray *)recipients userShouldSignMessage:(ThreeStateBoolean)userShouldSign userShouldEncryptMessage:(ThreeStateBoolean)userShouldEncrypt {
- (id)initWithSender:(NSString *)sender signingKey:(GPGKey *)signingKey recipients:(NSArray *)recipients userShouldSignMessage:(ThreeStateBoolean)userShouldSign userShouldEncryptMessage:(ThreeStateBoolean)userShouldEncrypt {
if((self = [self initWithSender:sender recipients:recipients])) {
_userShouldSignMessage = userShouldSign;
_userShouldEncryptMessage = userShouldEncrypt;
_signingKey = [signingKey copy];
_signingSender = [sender copy];
}

return self;
Expand Down Expand Up @@ -125,6 +127,13 @@ - (GPGKey *)encryptionKeyForDraft {
return [[GPGMailBundle sharedInstance] anyPersonalPublicKeyWithPreferenceAddress:senderAddress];
}

- (void)updateSigningKey:(GPGKey *)signingKey forSender:(NSString *)sender {
// Once a signing key is set, the keyring is no longer queried for a key matching
// the signer address, but the set signing key is always used. (#895)
_signingKey = [signingKey copy];
_signingSender = [sender copy];
}

- (void)computePreferredSecurityPropertiesForSecurityMethod:(GPGMAIL_SECURITY_METHOD)securityMethod {
// Load signing identity and certificates for S/MIME.
NSMutableDictionary *signingIdentities = [self.cachedSigningIdentities mutableCopy];
Expand Down Expand Up @@ -187,14 +196,23 @@ - (void)computePreferredSecurityPropertiesForSecurityMethod:(GPGMAIL_SECURITY_ME
signingKey = nil;
}
if(!signingKey) {
NSArray *signingKeyList = [[[GPGMailBundle sharedInstance] signingKeyListForAddress:senderAddress] allObjects];
// TODO: Consider pereferring the default key if one is configured.
signingKeys[senderAddress] = [signingKeyList count] > 0 ? signingKeyList[0] : [NSNull null];
// In order to trick mail into accepting the key, it has to be added under the sender
// with email and full name as well. Otherwise, the last check before calling
// -[ComposeBackEnd _makeMessageWithContents:isDraft:shouldSign:shouldEncrypt:shouldSkipSignature:shouldBePlainText:]
// will disable signing, since no key for the full address can be found in the _signingIdentities dictionary.
signingKeys[sender] = signingKeys[senderAddress];
// If a particular signing key has been chosen from the "From" field,
// always use that key. Otherwise query all signing keys matching the address.
// (#895)
if(_signingKey && [_signingSender isEqualToString:sender]) {
signingKeys[senderAddress] = _signingKey;
signingKeys[sender] = signingKeys[senderAddress];
}
else {
NSArray *signingKeyList = [[[GPGMailBundle sharedInstance] signingKeyListForAddress:senderAddress] allObjects];
// TODO: Consider pereferring the default key if one is configured.
signingKeys[senderAddress] = [signingKeyList count] > 0 ? signingKeyList[0] : [NSNull null];
// In order to trick mail into accepting the key, it has to be added under the sender
// with email and full name as well. Otherwise, the last check before calling
// -[ComposeBackEnd _makeMessageWithContents:isDraft:shouldSign:shouldEncrypt:shouldSkipSignature:shouldBePlainText:]
// will disable signing, since no key for the full address can be found in the _signingIdentities dictionary.
signingKeys[sender] = signingKeys[senderAddress];
}
}
canPGPSign = signingKeys[senderAddress] && signingKeys[senderAddress] != [NSNull null] ? YES : NO;
}
Expand Down
13 changes: 10 additions & 3 deletions Source/HeadersEditor+GPGMail.m
Expand Up @@ -704,9 +704,16 @@ - (void)MAChangeFromHeader:(NSPopUpButton *)sender {
else
[button addItemWithTitle:(parentItem ? parentItem : item).title];

// Set the selected key in the back-end.
ComposeBackEnd *backEnd = [GPGMailBundle backEndFromObject:self];
[backEnd setIvar:@"gpgKeyForSigning" value:[item getIvar:kHeadersEditorFromControlGPGKeyKey]];
ComposeBackEnd *backEnd = [GPGMailBundle backEndFromObject:self];
GMComposeMessagePreferredSecurityProperties *securityProperties = [(ComposeBackEnd_GPGMail *)backEnd preferredSecurityProperties];
GPGKey *signingKey = [item getIvar:kHeadersEditorFromControlGPGKeyKey];
if(signingKey) {
// Configure the security properties to always used the specified key for signing,
// instead of looking up a matching key using the signers email address.
// This is especially necessary in case multiple signing keys are available for the
// same email address. (#895)
[securityProperties updateSigningKey:signingKey forSender:item.representedObject];
}

[self MAChangeFromHeader:button];
}
Expand Down

0 comments on commit c1f2cbd

Please sign in to comment.