2
0

Adapt macOS for new APIs.

This commit is contained in:
Maarten Billemont 2017-08-12 22:26:48 -04:00
parent f5c7d11f0e
commit d7193f7753
9 changed files with 105 additions and 96 deletions

View File

@ -23,11 +23,11 @@
#include <stdint.h>
#include <stdbool.h>
//#ifdef NS_ENUM
//#define enum(_type, _name) NS_ENUM(_type, _name)
//#else
#ifdef NS_ENUM
#define enum(_type, _name) NS_ENUM(_type, _name)
#else
#define enum(_type, _name) _type _name; enum
//#endif
#endif
//// Types.

View File

@ -64,10 +64,10 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key;
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
withCounter:(NSUInteger)counter usingKey:(MPKey *)key;
withCounter:(MPCounterValue)counter usingKey:(MPKey *)key;
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key;
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
withCounter:(NSUInteger)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key;
withCounter:(MPCounterValue)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key;
- (BOOL)savePassword:(NSString *)clearPassword toSite:(MPSiteEntity *)site usingKey:(MPKey *)key;

View File

@ -180,6 +180,9 @@ static NSOperationQueue *_mpwQueue = nil;
case MPResultTypeStatefulDevice:
return @"Device Private Password";
case MPResultTypeDeriveKey:
return @"Crypto Key";
}
Throw( @"Type not supported: %lu", (long)type );
@ -220,6 +223,9 @@ static NSOperationQueue *_mpwQueue = nil;
case MPResultTypeStatefulDevice:
return @"Device";
case MPResultTypeDeriveKey:
return @"Key";
}
Throw( @"Type not supported: %lu", (long)type );
@ -265,6 +271,9 @@ static NSOperationQueue *_mpwQueue = nil;
case MPResultTypeStatefulDevice:
return [MPStoredSiteEntity class];
case MPResultTypeDeriveKey:
break;
}
Throw( @"Type not supported: %lu", (long)type );
@ -314,6 +323,8 @@ static NSOperationQueue *_mpwQueue = nil;
return MPResultTypeStatefulDevice;
case MPResultTypeStatefulDevice:
return MPResultTypeTemplatePhrase;
case MPResultTypeDeriveKey:
break;
}
return [self defaultType];
@ -330,12 +341,12 @@ static NSOperationQueue *_mpwQueue = nil;
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplateName parameter:nil withCounter:1
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplateName parameter:nil withCounter:MPCounterValueInitial
variant:MPKeyPurposeIdentification context:nil usingKey:key];
}
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
withCounter:(NSUInteger)counter usingKey:(MPKey *)key {
withCounter:(MPCounterValue)counter usingKey:(MPKey *)key {
return [self mpwResultForSiteNamed:name ofType:type parameter:nil withCounter:counter
variant:MPKeyPurposeAuthentication context:nil usingKey:key];
@ -343,17 +354,18 @@ static NSOperationQueue *_mpwQueue = nil;
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key {
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplatePhrase parameter:nil withCounter:1
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplatePhrase parameter:nil withCounter:MPCounterValueInitial
variant:MPKeyPurposeRecovery context:question usingKey:key];
}
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
withCounter:(NSUInteger)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key {
withCounter:(MPCounterValue)counter variant:(MPKeyPurpose)purpose context:(NSString *)context
usingKey:(MPKey *)key {
__block NSString *result = nil;
[self mpw_perform:^{
char const *resultBytes = mpw_siteResult( [key keyForAlgorithm:self],
name.UTF8String, (uint32_t)counter, purpose, context.UTF8String, type, parameter.UTF8String, [self version] );
name.UTF8String, counter, purpose, context.UTF8String, type, parameter.UTF8String, [self version] );
if (resultBytes) {
result = [NSString stringWithCString:resultBytes encoding:NSUTF8StringEncoding];
mpw_free_string( resultBytes );
@ -393,11 +405,11 @@ static NSOperationQueue *_mpwQueue = nil;
[PearlKeyChain deleteItemForQuery:siteQuery];
else
[PearlKeyChain addOrUpdateItemForQuery:siteQuery withAttributes:@{
(__bridge id)kSecValueData : state,
(__bridge id)kSecValueData: state,
#if TARGET_OS_IPHONE
(__bridge id)kSecAttrAccessible:
site.type & MPSiteFeatureDevicePrivate? (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly
: (__bridge id)kSecAttrAccessibleWhenUnlocked,
(__bridge id)kSecAttrAccessible:
site.type & MPSiteFeatureDevicePrivate? (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly
: (__bridge id)kSecAttrAccessibleWhenUnlocked,
#endif
}];
((MPStoredSiteEntity *)site).contentObject = nil;
@ -490,7 +502,7 @@ static NSOperationQueue *_mpwQueue = nil;
break;
}
NSUInteger counter = ((MPGeneratedSiteEntity *)site).counter;
MPCounterValue counter = ((MPGeneratedSiteEntity *)site).counter;
PearlNotMainQueue( ^{
resultBlock( [algorithm mpwTemplateForSiteNamed:name ofType:type withCounter:counter usingKey:key] );
@ -517,7 +529,12 @@ static NSOperationQueue *_mpwQueue = nil;
} );
break;
}
case MPResultTypeDeriveKey:
break;
}
Throw( @"Type not supported: %lu", (long)type );
}
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key result:(void ( ^ )(NSString *result))resultBlock {
@ -563,8 +580,8 @@ static NSOperationQueue *_mpwQueue = nil;
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
if (cipherText && cipherText.length && site.type & MPResultTypeClassStateful) {
NSString *plainText = [self mpwResultForSiteNamed:site.name ofType:site.type parameter:cipherText
withCounter:MPCounterValueInitial variant:MPKeyPurposeAuthentication context:nil
usingKey:importKey];
withCounter:MPCounterValueInitial variant:MPKeyPurposeAuthentication context:nil
usingKey:importKey];
if (plainText)
[self savePassword:plainText toSite:site usingKey:key];
}

View File

@ -49,13 +49,16 @@ __END_DECLS
} \
error; \
})
#else
#define MPError(error_, message, ...) ({ \
NSError *error = error_; \
err( message @"%@%@", ##__VA_ARGS__, error? @"\n": @"", [error fullDescription]?: @"" ); \
error; \
})
#endif
#define MPMakeError(message, ...) ({ \
MPError( [NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{ \
NSLocalizedDescriptionKey: strf( message, ##__VA_ARGS__ ) \
}], @"" ); \
})
#else
#define MPError(error_, message, ...) ({ \
err( message @"%@%@", ##__VA_ARGS__, error_? @"\n": @"", [error_ fullDescription]?: @"" ); \
})
#endif

View File

@ -269,23 +269,22 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
[openPanel close];
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
if (error)
MPError( error, @"While reading imported sites from %@.", url );
^(NSData *importedSitesData, NSURLResponse *response, NSError *urlError) {
if (urlError)
[[NSAlert alertWithError:MPError( urlError, @"While reading imported sites from %@.", url )] runModal];
if (!importedSitesData)
return;
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
[self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
__block NSString *masterPassword = nil;
PearlMainQueueWait( ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Unlock"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = @"Import File's Master Password";
alert.informativeText = strf( @"%@'s export was done using a different master password.\n"
@"Enter that master password to unlock the exported data.", userName );
alert.messageText = strf( @"Importing Sites For\n%@", userName );
alert.informativeText = @"Enter the master password used to create this export file.";
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
@ -293,16 +292,15 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
} );
return masterPassword;
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
} askUserPassword:^NSString *(NSString *userName) {
__block NSString *masterPassword = nil;
PearlMainQueueWait( ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Import"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = strf( @"Master Password for\n%@", userName );
alert.informativeText = strf( @"Imports %lu sites, overwriting %lu.",
(unsigned long)importCount, (unsigned long)deleteCount );
alert.messageText = strf( @"Master Password For\n%@", userName );
alert.informativeText = @"Enter the current master password for this user.";
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
@ -310,37 +308,12 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
} );
return masterPassword;
} result:^(NSError *error) {
[self updateUsers];
if (error && !(error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError))
[[NSAlert alertWithError:error] runModal];
}];
PearlMainQueue( ^{
switch (result) {
case MPImportResultSuccess: {
[self updateUsers];
NSAlert *alert = [NSAlert new];
alert.messageText = @"Successfully imported sites.";
[alert runModal];
break;
}
case MPImportResultCancelled:
break;
case MPImportResultInternalError:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Import failed because of an internal error."
}]] runModal];
break;
case MPImportResultMalformedInput:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"The import doesn't look like a Master Password export."
}]] runModal];
break;
case MPImportResultInvalidPassword:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Incorrect master password for the import sites."
}]] runModal];
break;
}
} );
}] resume];
}
@ -509,25 +482,43 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
return;
NSError *coordinateError = nil;
NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords];
[[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:savePanel.URL options:0
error:&coordinateError byAccessor:
^(NSURL *newURL) {
NSError *writeError = nil;
if (![exportedSites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
MPError( writeError, @"Could not write to the export file." );
[self exportSitesRevealPasswords:revealPasswords
askExportPassword:^NSString *(NSString *userName) {
return PearlMainQueueAwait( ^id {
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Import"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = strf( @"Master Password For\n%@", userName );
alert.informativeText = @"Enter the current master password for this user.";
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
return ((NSTextField *)alert.accessoryView).stringValue;
else
return nil;
} );
} result:^(NSString *mpsites, NSError *error) {
if (!mpsites || error) {
PearlMainQueue( ^{
[[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal];
} );
return;
}
NSError *coordinateError = nil;
[[[NSFileCoordinator alloc] initWithFilePresenter:nil]
coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) {
NSError *writeError = nil;
if (![mpsites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
PearlMainQueue( ^{
[[NSAlert alertWithError:writeError] runModal];
[[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal];
} );
}];
if (coordinateError) {
MPError( coordinateError, @"Write access to the export file could not be obtained." );
PearlMainQueue( ^{
[[NSAlert alertWithError:coordinateError] runModal];
} );
}
}];
if (coordinateError)
PearlMainQueue( ^{
[[NSAlert alertWithError:MPError( coordinateError, @"Could not gain access to the export file." )] runModal];
} );
}];
}
- (void)updateUsers {

View File

@ -27,7 +27,7 @@
@property(nonatomic) NSString *name;
@property(nonatomic) NSAttributedString *displayedName;
@property(nonatomic) MPSiteType type;
@property(nonatomic) MPResultType type;
@property(nonatomic) NSString *typeName;
@property(nonatomic) NSString *content;
@property(nonatomic) NSString *displayedContent;
@ -36,7 +36,7 @@
@property(nonatomic) NSString *loginName;
@property(nonatomic) BOOL loginGenerated;
@property(nonatomic) NSNumber *uses;
@property(nonatomic) NSUInteger counter;
@property(nonatomic) MPCounterValue counter;
@property(nonatomic) NSDate *lastUsed;
@property(nonatomic) id<MPAlgorithm> algorithm;
@property(nonatomic) MPAlgorithmVersion algorithmVersion;

View File

@ -81,7 +81,7 @@
self.type = entity.type;
self.typeName = entity.typeName;
self.uses = entity.uses_;
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: 0;
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: MPCounterValueInitial;
self.loginGenerated = entity.loginGenerated;
// Find all password types and the index of the current type amongst them.
@ -104,7 +104,7 @@
self.type = user.defaultType;
self.typeName = [self.algorithm nameOfType:self.type];
self.uses = @0;
self.counter = 1;
self.counter = MPCounterValueDefault;
// Find all password types and the index of the current type amongst them.
[self updateContent];
@ -116,14 +116,14 @@
return nil;
NSError *error;
MPSiteEntity *entity = (MPSiteEntity *)[moc existingObjectWithID:self.entityOID error:&error];
MPSiteEntity *entity = [moc existingObjectWithID:self.entityOID error:&error];
if (!entity)
MPError( error, @"Couldn't retrieve active site." );
return entity;
}
- (void)setCounter:(NSUInteger)counter {
- (void)setCounter:(MPCounterValue)counter {
if (self.counter == counter)
return;
@ -210,12 +210,12 @@
- (BOOL)generated {
return self.type & MPSiteTypeClassGenerated;
return self.type & MPResultTypeClassTemplate;
}
- (BOOL)stored {
return self.type & MPSiteTypeClassStored;
return self.type & MPResultTypeClassStateful;
}
- (BOOL)transient {

View File

@ -373,9 +373,9 @@
NSArray *types = [site.algorithm allTypes];
[self.passwordTypesMatrix renewRows:(NSInteger)[types count] columns:1];
for (NSUInteger t = 0; t < [types count]; ++t) {
MPSiteType type = (MPSiteType)[types[t] unsignedIntegerValue];
MPResultType type = (MPResultType)[types[t] unsignedIntegerValue];
NSString *title = [site.algorithm nameOfType:type];
if (type & MPSiteTypeClassGenerated)
if (type & MPResultTypeClassTemplate)
title = strf( @"%@ %@", [site.algorithm mpwTemplateForSiteNamed:site.name ofType:type withCounter:site.counter
usingKey:[MPMacAppDelegate get].key], title );
@ -397,7 +397,7 @@
switch (returnCode) {
case NSAlertFirstButtonReturn: {
// "Save" button.
MPSiteType type = (MPSiteType)[self.passwordTypesMatrix.selectedCell tag];
MPResultType type = (MPResultType)[self.passwordTypesMatrix.selectedCell tag];
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *entity = [[MPMacAppDelegate get] changeSite:[self.selectedSite entityInContext:context]
saveInContext:context toType:type];

View File

@ -436,17 +436,15 @@
[self exportSitesRevealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) {
return PearlAwait( ^(void (^setResult)(id)) {
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
message:strf( @"%@'s export was done using a different master password.\n"
@"Enter that master password to unlock the exported data.", userName )
[PearlAlert showAlertWithTitle:strf( @"Master Password For:\n%@", userName )
message:@"Enter the user's master password to create an export file."
viewStyle:UIAlertViewStyleSecureTextInput
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
if (buttonIndex_ == [alert_ cancelButtonIndex])
setResult( nil );
else
setResult( [alert_ textFieldAtIndex:0].text );
}
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock Import", nil];
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Export", nil];
} );
} result:^(NSString *mpsites, NSError *error) {
if (!mpsites || error) {