diff --git a/External/Pearl b/External/Pearl index b7872ed1..efe1b532 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit b7872ed1e7fb4ffa8dbe051dbe3ea6d809113a36 +Subproject commit efe1b532952a2cdc725b489160114a135d1ca939 diff --git a/MasterPassword-Mac.xcodeproj/project.pbxproj b/MasterPassword-Mac.xcodeproj/project.pbxproj index 12a0b6fd..b144446e 100644 --- a/MasterPassword-Mac.xcodeproj/project.pbxproj +++ b/MasterPassword-Mac.xcodeproj/project.pbxproj @@ -574,7 +574,6 @@ DA60111515057F10008E9AB6 /* icon_wrench.png in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9115057F10008E9AB6 /* icon_wrench.png */; }; DA60111615057F10008E9AB6 /* icon_wrench@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9215057F10008E9AB6 /* icon_wrench@2x.png */; }; DA60111715057F10008E9AB6 /* iTunesArtwork.png in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9315057F10008E9AB6 /* iTunesArtwork.png */; }; - DA60111915057F10008E9AB6 /* jquery-1.6.1.min.js in Sources */ = {isa = PBXBuildFile; fileRef = DA600E9515057F10008E9AB6 /* jquery-1.6.1.min.js */; }; DA60111B15057F10008E9AB6 /* lock_blue.png in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9815057F10008E9AB6 /* lock_blue.png */; }; DA60111C15057F10008E9AB6 /* lock_blue@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9915057F10008E9AB6 /* lock_blue@2x.png */; }; DA60111D15057F10008E9AB6 /* lock_green.png in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9A15057F10008E9AB6 /* lock_green.png */; }; @@ -705,6 +704,7 @@ DAB8DA391503972100CED3BC /* PearlRSAKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB8DA0F1503972100CED3BC /* PearlRSAKey.m */; }; DAB8DA3A1503972100CED3BC /* PearlSCrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = DAB8DA101503972100CED3BC /* PearlSCrypt.h */; }; DAB8DA3B1503972100CED3BC /* PearlSCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB8DA111503972100CED3BC /* PearlSCrypt.m */; }; + DAC0F184150D643C00D4AB0A /* jquery-1.6.1.min.js in Resources */ = {isa = PBXBuildFile; fileRef = DA600E9515057F10008E9AB6 /* jquery-1.6.1.min.js */; }; DADEA5A61503C9DD00FD084E /* e_os.h in Headers */ = {isa = PBXBuildFile; fileRef = DADEA5A41503C9DD00FD084E /* e_os.h */; }; DADEA5A71503C9DD00FD084E /* e_os2.h in Headers */ = {isa = PBXBuildFile; fileRef = DADEA5A51503C9DD00FD084E /* e_os2.h */; }; DADEA5BB1503CE3000FD084E /* _MWERKS_GUSI_prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = DADEA5A91503CE3000FD084E /* _MWERKS_GUSI_prefix.h */; }; @@ -6160,6 +6160,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + DAC0F184150D643C00D4AB0A /* jquery-1.6.1.min.js in Resources */, DAB8D9C9150375C800CED3BC /* Credits.rtf in Resources */, DAB8D9CA150375C800CED3BC /* InfoPlist.strings in Resources */, DAB8D9CB150375C800CED3BC /* MainMenu.xib in Resources */, @@ -6823,7 +6824,6 @@ DA600BEB150420AC008E9AB6 /* MPPasswordWindowController.m in Sources */, DA600C2D150565FC008E9AB6 /* MPConfig.m in Sources */, DA600C2E150565FC008E9AB6 /* MPAppDelegate_Key.m in Sources */, - DA60111915057F10008E9AB6 /* jquery-1.6.1.min.js in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MasterPassword/MPElementStoredEntity.m b/MasterPassword/MPElementStoredEntity.m index 81b97cfd..68565e3a 100644 --- a/MasterPassword/MPElementStoredEntity.m +++ b/MasterPassword/MPElementStoredEntity.m @@ -40,14 +40,14 @@ encryptedContent = self.contentObject; NSData *decryptedContent = [encryptedContent decryptWithSymmetricKey:[[MPAppDelegate get] keyWithLength:PearlCryptKeySize] - usePadding:YES]; + padding:YES]; return [[NSString alloc] initWithBytes:decryptedContent.bytes length:decryptedContent.length encoding:NSUTF8StringEncoding]; } - (void)setContent:(id)content { NSData *encryptedContent = [[content description] encryptWithSymmetricKey:[[MPAppDelegate get] keyWithLength:PearlCryptKeySize] - usePadding:YES]; + padding:YES]; if (self.type == MPElementTypeStoredDevicePrivate) { [PearlKeyChain addOrUpdateItemForQuery:[MPElementStoredEntity queryForDevicePrivateElementNamed:self.name] diff --git a/MasterPassword/Mac/MPAppDelegate.h b/MasterPassword/Mac/MPAppDelegate.h index 782fb65a..45b2ac92 100644 --- a/MasterPassword/Mac/MPAppDelegate.h +++ b/MasterPassword/Mac/MPAppDelegate.h @@ -9,7 +9,7 @@ #import #import "MPPasswordWindowController.h" -@interface MPAppDelegate : NSObject +@interface MPAppDelegate : NSObject @property (assign) IBOutlet NSWindow *window; @@ -17,6 +17,8 @@ @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; +@property (readonly, strong, nonatomic) NSNetService *netService; + + (NSManagedObjectModel *)managedObjectModel; + (NSManagedObjectContext *)managedObjectContext; diff --git a/MasterPassword/Mac/MPAppDelegate.m b/MasterPassword/Mac/MPAppDelegate.m index 5b594e15..b90cee7a 100644 --- a/MasterPassword/Mac/MPAppDelegate.m +++ b/MasterPassword/Mac/MPAppDelegate.m @@ -9,9 +9,17 @@ #import "MPAppDelegate_Key.h" #import "MPConfig.h" +#import +#import + + @interface MPAppDelegate () @property (readwrite, strong, nonatomic) MPPasswordWindowController *passwordWindow; +@property (readwrite, strong, nonatomic) NSNetService *netService; +@property (readwrite, assign, nonatomic) CFSocketRef listeningSocket; + +- (void)connectionEstablishedOnHandle:(CFSocketNativeHandle)handle; @end @@ -20,12 +28,18 @@ @synthesize persistentStoreCoordinator = __persistentStoreCoordinator; @synthesize managedObjectModel = __managedObjectModel; @synthesize managedObjectContext = __managedObjectContext; +@synthesize netService, listeningSocket; @synthesize passwordWindow; @synthesize key; @synthesize keyHash; @synthesize keyHashHex; +static void ListeningSocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { + + [[MPAppDelegate get] connectionEstablishedOnHandle:*(const CFSocketNativeHandle *)data]; +} + + (void)initialize { [MPConfig get]; @@ -47,8 +61,120 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + [self setupNetworkListener]; } +- (void)setupNetworkListener { + + struct sockaddr_in6 serverAddress6; + socklen_t serverAddress6_len = sizeof(serverAddress6); + memset(&serverAddress6, 0, serverAddress6_len); + serverAddress6.sin6_len = serverAddress6_len; + serverAddress6.sin6_family = AF_INET6; + + NSSocketNativeHandle socketHandle; + if (0 > (socketHandle = socket(AF_INET6, SOCK_STREAM, 0))) { + err(@"Couldn't create socket: %@", errstr()); + return; + } + if (0 > bind(socketHandle, (const struct sockaddr *) &serverAddress6, serverAddress6_len)) { + err(@"Couldn't bind socket: %@", errstr()); + close(socketHandle); + return; + } + if (0 > getsockname(socketHandle, (struct sockaddr *) &serverAddress6, &serverAddress6_len)) { + err(@"Couldn't get socket info: %@", errstr()); + close(socketHandle); + return; + } + if (0 > listen(socketHandle, 5)) { + err(@"Couldn't get socket info: %@", errstr()); + close(socketHandle); + return; + } + if (!(self.listeningSocket = CFSocketCreateWithNative(NULL, socketHandle, kCFSocketAcceptCallBack, ListeningSocketCallback, NULL))) { + err(@"Couldn't start listening on the socket: %@", errstr()); + return; + } + + CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(NULL, self.listeningSocket, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); + CFRelease(runLoopSource); + + int chosenPort = ntohs(serverAddress6.sin6_port); + inf(@"Master Password bound to port %d", chosenPort); + self.netService = [[NSNetService alloc] initWithDomain:@"" type:@"_masterpassword._tcp." name:@"Master Password" port:chosenPort]; + if(!self.netService) { + err(@"Couldn't initialize the Bonjour service."); + return; + } + + self.netService.delegate = self; + [self.netService publish]; +} + +- (void)connectionEstablishedOnHandle:(CFSocketNativeHandle)handle { + + dbg(@"%@%d", NSStringFromSelector(_cmd), handle); +} + +/* Sent to the NSNetService instance's delegate prior to advertising the service on the network. If for some reason the service cannot be published, the delegate will not receive this message, and an error will be delivered to the delegate via the delegate's -netService:didNotPublish: method. + */ +- (void)netServiceWillPublish:(NSNetService *)sender { + + dbg(@"%@", NSStringFromSelector(_cmd)); +} + +/* Sent to the NSNetService instance's delegate when the publication of the instance is complete and successful. + */ +- (void)netServiceDidPublish:(NSNetService *)sender { + + dbg(@"%@", NSStringFromSelector(_cmd)); +} + +/* Sent to the NSNetService instance's delegate when an error in publishing the instance occurs. The error dictionary will contain two key/value pairs representing the error domain and code (see the NSNetServicesError enumeration above for error code constants). It is possible for an error to occur after a successful publication. + */ +- (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict { + + dbg(@"%@%@", NSStringFromSelector(_cmd), errorDict); +} + +/* Sent to the NSNetService instance's delegate prior to resolving a service on the network. If for some reason the resolution cannot occur, the delegate will not receive this message, and an error will be delivered to the delegate via the delegate's -netService:didNotResolve: method. + */ +- (void)netServiceWillResolve:(NSNetService *)sender { + + dbg(@"%@", NSStringFromSelector(_cmd)); +} + +/* Sent to the NSNetService instance's delegate when one or more addresses have been resolved for an NSNetService instance. Some NSNetService methods will return different results before and after a successful resolution. An NSNetService instance may get resolved more than once; truly robust clients may wish to resolve again after an error, or to resolve more than once. + */ +- (void)netServiceDidResolveAddress:(NSNetService *)sender { + + dbg(@"%@", NSStringFromSelector(_cmd)); +} + +/* Sent to the NSNetService instance's delegate when an error in resolving the instance occurs. The error dictionary will contain two key/value pairs representing the error domain and code (see the NSNetServicesError enumeration above for error code constants). + */ +- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict { + + dbg(@"%@%@", NSStringFromSelector(_cmd), errorDict); +} + +/* Sent to the NSNetService instance's delegate when the instance's previously running publication or resolution request has stopped. + */ +- (void)netServiceDidStop:(NSNetService *)sender { + + dbg(@"%@", NSStringFromSelector(_cmd)); +} + +/* Sent to the NSNetService instance's delegate when the instance is being monitored and the instance's TXT record has been updated. The new record is contained in the data parameter. + */ +- (void)netService:(NSNetService *)sender didUpdateTXTRecordData:(NSData *)data { + + dbg(@"%@%@", NSStringFromSelector(_cmd), data); +} + + - (void)applicationDidBecomeActive:(NSNotification *)notification { if (!self.passwordWindow)