You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

129 lines
4.7 KiB

//
// PEPPassphraseUtil.m
// pEpObjCAdapterTests
//
// Created by Dirk Zimmermann on 06.08.20.
// Copyright © 2020 p≡p. All rights reserved.
//
#import "PEPPassphraseUtil.h"
#import "pEpEngine.h"
#import "PEPPassphraseCache.h"
#import "PEPObjCAdapter+Internal.h"
#import "NSString+NormalizePassphrase.h"
@implementation PEPPassphraseUtil
+ (PEPStatus)runWithPasswordsSession:(PEP_SESSION)session
block:(PEP_STATUS (^)(PEP_SESSION session))block
{
PEP_STATUS lastStatus = PEP_UNKNOWN_ERROR;
NSMutableArray *passphrases = [NSMutableArray
arrayWithArray:[[PEPPassphraseCache sharedInstance] passphrases]];
[passphrases insertObject:@"" atIndex:0];
if ([[PEPPassphraseCache sharedInstance] storedPassphrase]) {
[passphrases insertObject:[[PEPPassphraseCache sharedInstance] storedPassphrase] atIndex:1];
}
for (NSString *passphrase in passphrases) {
PEP_STATUS status = config_passphrase(session, [passphrase UTF8String]);
if (status != PEPStatusOK) {
return (PEPStatus) status;
}
lastStatus = block(session);
if (lastStatus != PEP_PASSPHRASE_REQUIRED && lastStatus != PEP_WRONG_PASSPHRASE) {
// The passphrase worked, so reset its timeout
[[PEPPassphraseCache sharedInstance] resetTimeoutForPassphrase:passphrase];
return (PEPStatus) lastStatus;
}
}
// If execution lands here, it means we ran out of passwords to set while
// receiving password-related error codes.
return [self tryPassphraseProviderSession:session
lastStatus:lastStatus block:block];
}
#pragma mark - Private
/// Invokes the given block while setting passphrases requested from the
/// passphrase provider, if set.
+ (PEPStatus)tryPassphraseProviderSession:(PEP_SESSION)session
lastStatus:(PEP_STATUS)lastStatus
block:(PEP_STATUS (^)(PEP_SESSION session))block
{
id<PEPPassphraseProviderProtocol> passphraseProvider = [PEPObjCAdapter passphraseProvider];
if (passphraseProvider) {
dispatch_group_t group = dispatch_group_create();
__block PEP_STATUS lastPassphraseProviderStatus = lastStatus;
__block NSString *lastPassphrase = nil;
PEPPassphraseProviderCallback passphraseCallback = ^(NSString * _Nullable passphrase) {
lastPassphrase = passphrase;
dispatch_group_leave(group);
};
while (YES) {
if (lastPassphraseProviderStatus == PEP_PASSPHRASE_REQUIRED) {
dispatch_group_enter(group);
[passphraseProvider passphraseRequired:passphraseCallback];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
} else if (lastPassphraseProviderStatus == PEP_WRONG_PASSPHRASE) {
dispatch_group_enter(group);
[passphraseProvider wrongPassphrase:passphraseCallback];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
if (lastPassphrase == nil) {
return (PEPStatus) lastPassphraseProviderStatus;
}
NSString *normalizedPassphrase = [lastPassphrase normalizedPassphraseWithError:nil];
//Add the new passphrase to our cache to not having to bother the client again.
[[PEPPassphraseCache sharedInstance] addPassphrase:normalizedPassphrase];
if (normalizedPassphrase == nil) {
// Assume excessively long passphrase means PEP_WRONG_PASSPHRASE
lastPassphraseProviderStatus = PEP_WRONG_PASSPHRASE;
dispatch_group_enter(group);
[passphraseProvider passphraseTooLong:passphraseCallback];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
continue;
}
lastPassphraseProviderStatus = config_passphrase(session,
[lastPassphrase UTF8String]);
if (lastPassphraseProviderStatus != PEPStatusOK) {
return (PEPStatus) lastPassphraseProviderStatus;
}
lastPassphraseProviderStatus = block(session);
if (lastPassphraseProviderStatus != PEP_PASSPHRASE_REQUIRED &&
lastPassphraseProviderStatus != PEP_WRONG_PASSPHRASE) {
// The passphrase worked, so reset its timeout
[[PEPPassphraseCache sharedInstance] resetTimeoutForPassphrase:lastPassphrase];
return (PEPStatus) lastPassphraseProviderStatus;
}
}
return (PEPStatus) lastPassphraseProviderStatus;
} else {
// no passphrase provider
return (PEPStatus) lastStatus;
}
}
@end