diff options
-rw-r--r-- | Interfaces/SSHQuestionDialog.xib | 149 | ||||
-rw-r--r-- | Source/CMMCPConnection.m | 8 | ||||
-rw-r--r-- | Source/KeyChain.h | 1 | ||||
-rw-r--r-- | Source/KeyChain.m | 14 | ||||
-rw-r--r-- | Source/SPSSHTunnel.h | 5 | ||||
-rw-r--r-- | Source/SPSSHTunnel.m | 58 | ||||
-rw-r--r-- | Source/TunnelPassphraseRequester.m | 19 | ||||
-rw-r--r-- | sequel-pro.xcodeproj/project.pbxproj | 4 |
8 files changed, 209 insertions, 49 deletions
diff --git a/Interfaces/SSHQuestionDialog.xib b/Interfaces/SSHQuestionDialog.xib index d0c4e2e3..1697b41d 100644 --- a/Interfaces/SSHQuestionDialog.xib +++ b/Interfaces/SSHQuestionDialog.xib @@ -8,6 +8,7 @@ <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="469"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -44,7 +45,7 @@ <nil key="NSViewClass"/> <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string> <object class="NSView" key="NSWindowView" id="414427165"> - <reference key="NSNextResponder"/> + <nil key="NSNextResponder"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -53,13 +54,12 @@ <int key="NSvFlags">274</int> <string key="NSFrame">{{126, 60}, {477, 129}}</string> <reference key="NSSuperview" ref="414427165"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="296218965"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">272891904</int> <string key="NSContents"/> - <object class="NSFont" key="NSSupport" id="535233726"> + <object class="NSFont" key="NSSupport"> <string key="NSName">LucidaGrande</string> <double key="NSSize">1.300000e+01</double> <int key="NSfFlags">16</int> @@ -90,7 +90,6 @@ <int key="NSvFlags">289</int> <string key="NSFrame">{{510, 12}, {96, 32}}</string> <reference key="NSSuperview" ref="414427165"/> - <reference key="NSWindow"/> <int key="NSTag">1</int> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="915366670"> @@ -128,7 +127,6 @@ </object> <string key="NSFrame">{{20, 115}, {75, 74}}</string> <reference key="NSSuperview" ref="414427165"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSImageCell" key="NSCell" id="490596046"> <int key="NSCellFlags">130560</int> @@ -149,7 +147,6 @@ <int key="NSvFlags">289</int> <string key="NSFrame">{{414, 12}, {96, 32}}</string> <reference key="NSSuperview" ref="414427165"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="382904691"> <int key="NSCellFlags">67239424</int> @@ -182,12 +179,11 @@ </object> <string key="NSFrame">{{68, 113}, {32, 32}}</string> <reference key="NSSuperview" ref="414427165"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSImageCell" key="NSCell" id="406303847"> <int key="NSCellFlags">130560</int> <int key="NSCellFlags2">33554432</int> - <object class="NSCustomResource" key="NSContents"> + <object class="NSCustomResource" key="NSContents" id="127199858"> <string key="NSClassName">NSImage</string> <string key="NSResourceName">toolbar-preferences-network</string> </object> @@ -200,8 +196,6 @@ </object> </object> <string key="NSFrameSize">{620, 209}</string> - <reference key="NSSuperview"/> - <reference key="NSWindow"/> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string> @@ -209,7 +203,7 @@ <object class="NSWindowTemplate" id="317330000"> <int key="NSWindowStyleMask">1</int> <int key="NSWindowBacking">2</int> - <string key="NSWindowRect">{{196, 301}, {620, 209}}</string> + <string key="NSWindowRect">{{196, 301}, {471, 209}}</string> <int key="NSWTFlags">603979776</int> <string key="NSWindowTitle">SSH Tunnel Password Query</string> <string key="NSWindowClass">NSWindow</string> @@ -222,16 +216,19 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSTextField" id="882917083"> <reference key="NSNextResponder" ref="800993241"/> - <int key="NSvFlags">274</int> - <string key="NSFrame">{{126, 113}, {477, 76}}</string> + <int key="NSvFlags">278</int> + <string key="NSFrame">{{126, 113}, {328, 76}}</string> <reference key="NSSuperview" ref="800993241"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="324489195"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">272891904</int> <string key="NSContents"/> - <reference key="NSSupport" ref="535233726"/> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande-Bold</string> + <double key="NSSize">1.300000e+01</double> + <int key="NSfFlags">16</int> + </object> <reference key="NSControlView" ref="882917083"/> <reference key="NSBackgroundColor" ref="759566909"/> <reference key="NSTextColor" ref="1062846423"/> @@ -240,9 +237,8 @@ <object class="NSButton" id="881553485"> <reference key="NSNextResponder" ref="800993241"/> <int key="NSvFlags">289</int> - <string key="NSFrame">{{510, 12}, {96, 32}}</string> + <string key="NSFrame">{{361, 12}, {96, 32}}</string> <reference key="NSSuperview" ref="800993241"/> - <reference key="NSWindow"/> <int key="NSTag">1</int> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="171126067"> @@ -276,7 +272,6 @@ </object> <string key="NSFrame">{{20, 115}, {75, 74}}</string> <reference key="NSSuperview" ref="800993241"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSImageCell" key="NSCell" id="70636684"> <int key="NSCellFlags">130560</int> @@ -292,9 +287,8 @@ <object class="NSButton" id="920337090"> <reference key="NSNextResponder" ref="800993241"/> <int key="NSvFlags">289</int> - <string key="NSFrame">{{414, 12}, {96, 32}}</string> + <string key="NSFrame">{{265, 12}, {96, 32}}</string> <reference key="NSSuperview" ref="800993241"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="811201853"> <int key="NSCellFlags">67239424</int> @@ -327,15 +321,11 @@ </object> <string key="NSFrame">{{68, 113}, {32, 32}}</string> <reference key="NSSuperview" ref="800993241"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSImageCell" key="NSCell" id="169063774"> <int key="NSCellFlags">130560</int> <int key="NSCellFlags2">33554432</int> - <object class="NSCustomResource" key="NSContents"> - <string key="NSClassName">NSImage</string> - <string key="NSResourceName">toolbar-preferences-network</string> - </object> + <reference key="NSContents" ref="127199858"/> <int key="NSAlign">0</int> <int key="NSScale">0</int> <int key="NSStyle">0</int> @@ -345,10 +335,9 @@ </object> <object class="NSSecureTextField" id="951010250"> <reference key="NSNextResponder" ref="800993241"/> - <int key="NSvFlags">294</int> - <string key="NSFrame">{{129, 70}, {261, 22}}</string> + <int key="NSvFlags">291</int> + <string key="NSFrame">{{199, 83}, {252, 22}}</string> <reference key="NSSuperview" ref="800993241"/> - <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSSecureTextFieldCell" key="NSCell" id="709544507"> <int key="NSCellFlags">343014976</int> @@ -378,10 +367,52 @@ </object> </object> </object> + <object class="NSTextField" id="11923336"> + <reference key="NSNextResponder" ref="800993241"/> + <int key="NSvFlags">292</int> + <string key="NSFrame">{{126, 85}, {68, 17}}</string> + <reference key="NSSuperview" ref="800993241"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="613771853"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents">Password:</string> + <reference key="NSSupport" ref="313221240"/> + <reference key="NSControlView" ref="11923336"/> + <reference key="NSBackgroundColor" ref="759566909"/> + <reference key="NSTextColor" ref="1062846423"/> + </object> + </object> + <object class="NSButton" id="107237198"> + <reference key="NSNextResponder" ref="800993241"/> + <int key="NSvFlags">289</int> + <string key="NSFrame">{{197, 59}, {253, 18}}</string> + <reference key="NSSuperview" ref="800993241"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="680760632"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">Remember password in my keychain</string> + <reference key="NSSupport" ref="313221240"/> + <reference key="NSControlView" ref="107237198"/> + <int key="NSButtonFlags">1211912703</int> + <int key="NSButtonFlags2">130</int> + <object class="NSCustomResource" key="NSNormalImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSSwitch</string> + </object> + <object class="NSButtonImageSource" key="NSAlternateImage"> + <string key="NSImageName">NSSwitch</string> + </object> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> </object> - <string key="NSFrameSize">{620, 209}</string> + <string key="NSFrameSize">{471, 209}</string> <reference key="NSSuperview"/> - <reference key="NSWindow"/> </object> <string key="NSScreenRect">{{0, 0}, {1440, 878}}</string> <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string> @@ -462,6 +493,14 @@ </object> <int key="connectionID">488</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">sshPasswordKeychainCheckbox</string> + <reference key="source" ref="1021"/> + <reference key="destination" ref="107237198"/> + </object> + <int key="connectionID">493</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -598,12 +637,14 @@ <reference key="object" ref="800993241"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="920337090"/> - <reference ref="881553485"/> <reference ref="823624076"/> <reference ref="882917083"/> <reference ref="736278290"/> + <reference ref="881553485"/> + <reference ref="920337090"/> <reference ref="951010250"/> + <reference ref="11923336"/> + <reference ref="107237198"/> </object> <reference key="parent" ref="317330000"/> </object> @@ -691,6 +732,34 @@ <reference key="object" ref="709544507"/> <reference key="parent" ref="951010250"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">489</int> + <reference key="object" ref="11923336"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="613771853"/> + </object> + <reference key="parent" ref="800993241"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">490</int> + <reference key="object" ref="613771853"/> + <reference key="parent" ref="11923336"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">491</int> + <reference key="object" ref="107237198"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="680760632"/> + </object> + <reference key="parent" ref="800993241"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">492</int> + <reference key="object" ref="680760632"/> + <reference key="parent" ref="107237198"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -724,6 +793,10 @@ <string>479.IBPluginDependency</string> <string>484.IBPluginDependency</string> <string>485.IBPluginDependency</string> + <string>489.IBPluginDependency</string> + <string>490.IBPluginDependency</string> + <string>491.IBPluginDependency</string> + <string>492.IBPluginDependency</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -741,8 +814,8 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{187, 404}, {620, 209}}</string> - <string>{{187, 404}, {620, 209}}</string> + <string>{{218, 467}, {471, 209}}</string> + <string>{{218, 467}, {471, 209}}</string> <reference ref="6"/> <string>{{11, 666}, {480, 270}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -754,6 +827,10 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> @@ -776,7 +853,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">488</int> + <int key="maxID">493</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -828,6 +905,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>sshPasswordDialog</string> <string>sshPasswordField</string> + <string>sshPasswordKeychainCheckbox</string> <string>sshPasswordText</string> <string>sshQuestionDialog</string> <string>sshQuestionText</string> @@ -836,6 +914,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>NSWindow</string> <string>NSSecureTextField</string> + <string>NSButton</string> <string>NSTextField</string> <string>NSWindow</string> <string>NSTextField</string> diff --git a/Source/CMMCPConnection.m b/Source/CMMCPConnection.m index 478d5684..8fbf948d 100644 --- a/Source/CMMCPConnection.m +++ b/Source/CMMCPConnection.m @@ -355,7 +355,7 @@ static void forcePingTimeout(int signalNumber); [connectionTunnel setConnectionStateChangeSelector:nil delegate:nil]; if ([connectionTunnel state] != SPSSH_STATE_IDLE) [connectionTunnel disconnect]; [connectionTunnel connect]; - NSDate *tunnelStartDate = [NSDate date]; + NSDate *tunnelStartDate = [NSDate date], *interfaceInteractionTimer; // Allow the tunnel to attempt to connect in a loop while (1) { @@ -367,7 +367,11 @@ static void forcePingTimeout(int signalNumber); [connectionTunnel disconnect]; break; } - [NSThread sleepForTimeInterval:0.25]; + + // Process events for a short time, allowing dialogs to be shown but waiting for the tunnel + interfaceInteractionTimer = [NSDate date]; + [[NSRunLoop currentRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.25]]; + tunnelStartDate = [tunnelStartDate addTimeInterval:([[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer] - 0.25)]; } currentSSHTunnelState = [connectionTunnel state]; [connectionTunnel setConnectionStateChangeSelector:@selector(sshTunnelStateChange:) delegate:self]; diff --git a/Source/KeyChain.h b/Source/KeyChain.h index 966a8c04..ca95d09f 100644 --- a/Source/KeyChain.h +++ b/Source/KeyChain.h @@ -29,6 +29,7 @@ @interface KeyChain : NSObject - (void)addPassword:(NSString *)password forName:(NSString *)name account:(NSString *)account; +- (void)addPassword:(NSString *)password forName:(NSString *)name account:(NSString *)account withLabel:(NSString *)label; - (NSString *)getPasswordForName:(NSString *)name account:(NSString *)account; - (void)deletePasswordForName:(NSString *)name account:(NSString *)account; - (BOOL)passwordExistsForName:(NSString *)name account:(NSString *)account; diff --git a/Source/KeyChain.m b/Source/KeyChain.m index ec5ee03f..ad0251f7 100644 --- a/Source/KeyChain.m +++ b/Source/KeyChain.m @@ -34,6 +34,14 @@ */ - (void)addPassword:(NSString *)password forName:(NSString *)name account:(NSString *)account { + [self addPassword:password forName:name account:account withLabel:name]; +} + +/** + * Add the supplied password to the user's Keychain using the supplied name, account, and label. + */ +- (void)addPassword:(NSString *)password forName:(NSString *)name account:(NSString *)account withLabel:(NSString *)label; +{ OSStatus status; SecTrustedApplicationRef sequelProRef, sequelProHelperRef; SecAccessRef passwordAccessRef; @@ -61,8 +69,8 @@ attributes[0].data = "application password"; attributes[0].length = 20; attributes[1].tag = kSecLabelItemAttr; - attributes[1].data = (unichar *)[name UTF8String]; - attributes[1].length = strlen([name UTF8String]); + attributes[1].data = (unichar *)[label UTF8String]; + attributes[1].length = strlen([label UTF8String]); attributes[2].tag = kSecAccountItemAttr; attributes[2].data = (unichar *)[account UTF8String]; attributes[2].length = strlen([account UTF8String]); @@ -173,7 +181,7 @@ attributes[0].data = (void *)[account UTF8String]; attributes[0].length = [account length]; - attributes[1].tag = kSecLabelItemAttr; + attributes[1].tag = kSecServiceItemAttr; attributes[1].data = (void *)[name UTF8String]; attributes[1].length = [name length]; diff --git a/Source/SPSSHTunnel.h b/Source/SPSSHTunnel.h index 4486685a..0c34f4f9 100644 --- a/Source/SPSSHTunnel.h +++ b/Source/SPSSHTunnel.h @@ -19,6 +19,7 @@ enum spsshtunnel_password_modes { IBOutlet NSWindow *sshQuestionDialog; IBOutlet NSTextField *sshQuestionText; + IBOutlet NSButton *sshPasswordKeychainCheckbox; IBOutlet NSWindow *sshPasswordDialog; IBOutlet NSTextField *sshPasswordText; IBOutlet NSSecureTextField *sshPasswordField; @@ -38,6 +39,8 @@ enum spsshtunnel_password_modes NSString *password; NSString *keychainName; NSString *keychainAccount; + NSString *requestedPassphrase; + BOOL requestedResponse; BOOL passwordInKeychain; int sshPort; int remotePort; @@ -59,7 +62,9 @@ enum spsshtunnel_password_modes - (void) standardErrorHandler:(NSNotification*)aNotification; - (NSString *) getPasswordWithVerificationHash:(NSString *)theHash; - (BOOL) getResponseForQuestion:(NSString *)theQuestion; +- (void) workerGetResponseForQuestion:(NSString *)theQuestion; - (NSString *) getPasswordForQuery:(NSString *)theQuery verificationHash:(NSString *)theHash; +- (void) workerGetPasswordForQuery:(NSString *)theQuery; - (IBAction) closeSheet:(id)sender; @end diff --git a/Source/SPSSHTunnel.m b/Source/SPSSHTunnel.m index d8332c14..6df20d2e 100644 --- a/Source/SPSSHTunnel.m +++ b/Source/SPSSHTunnel.m @@ -22,6 +22,8 @@ // More info at <http://code.google.com/p/sequel-pro/> #import "SPSSHTunnel.h" +#import "RegexKitLite.h" +#import "KeyChain.h" #import <netinet/in.h> @@ -69,6 +71,8 @@ keychainName = nil; keychainAccount = nil; passwordInKeychain = NO; + requestedPassphrase = nil; + requestedResponse = NO; task = nil; localPort = 0; connectionState = SPSSH_STATE_IDLE; @@ -226,7 +230,7 @@ // [taskArguments addObject:@"-C"]; // TODO: compression? [taskArguments addObject:@"-o ExitOnForwardFailure=yes"]; [taskArguments addObject:[NSString stringWithFormat:@"-o ConnectTimeout=%i", connectionTimeout]]; - [taskArguments addObject:@"-o NumberOfPasswordPrompts=1"]; + [taskArguments addObject:@"-o NumberOfPasswordPrompts=3"]; if (useKeepAlive && keepAliveInterval) { [taskArguments addObject:@"-o TCPKeepAlive=no"]; [taskArguments addObject:[NSString stringWithFormat:@"-o ServerAliveInterval=%i", (int)ceil(keepAliveInterval)]]; @@ -403,6 +407,13 @@ */ - (BOOL) getResponseForQuestion:(NSString *)theQuestion { + [self performSelectorOnMainThread:@selector(workerGetResponseForQuestion:) withObject:theQuestion waitUntilDone:YES]; + + return requestedResponse; +} +- (void) workerGetResponseForQuestion:(NSString *)theQuestion +{ + NSSize questionTextSize; NSRect windowFrameRect; @@ -410,7 +421,7 @@ [sshQuestionText setStringValue:theQuestion]; questionTextSize = [[sshQuestionText cell] cellSizeForBounds:NSMakeRect(0, 0, [sshQuestionText bounds].size.width, 500)]; windowFrameRect = [sshQuestionDialog frame]; - windowFrameRect.size.height = ((questionTextSize.height < 100)?100:questionTextSize.height) + 90; + windowFrameRect.size.height = ((questionTextSize.height < 100)?100:questionTextSize.height) + 70 + ([sshPasswordDialog isSheet]?0:22); [sshQuestionDialog setFrame:windowFrameRect display:NO]; [NSApp beginSheet:sshQuestionDialog modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil]; int sshQueryResponseCode = [NSApp runModalForWindow:sshQuestionDialog]; @@ -421,11 +432,13 @@ // Yes case 1: - return YES; + requestedResponse = YES; + return; // No default: - return NO; + requestedResponse = NO; + return; } } @@ -437,15 +450,36 @@ { if (![theHash isEqualToString:tunnelConnectionVerifyHash]) return nil; + NSString *thePassword; + + [self performSelectorOnMainThread:@selector(workerGetPasswordForQuery:) withObject:theQuery waitUntilDone:YES]; + + if (!requestedPassphrase) return nil; + thePassword = [NSString stringWithString:requestedPassphrase]; + [requestedPassphrase release], requestedPassphrase = nil; + return thePassword; +} +- (void) workerGetPasswordForQuery:(NSString *)theQuery +{ NSSize queryTextSize; NSRect windowFrameRect; NSString *thePassword; + KeyChain *keychain; + + // Work out whether a passphrase is being requested, extracting the key name + NSString *keyName = [theQuery stringByMatching:@"^\\s*Enter passphrase for key \\'(.*)\\':\\s*$" capture:1L]; + if (keyName) { + [sshPasswordText setStringValue:[NSString stringWithFormat:@"Enter your password for the SSH key\n\"%@\"", keyName]]; + [sshPasswordKeychainCheckbox setHidden:NO]; + } else { + [sshPasswordText setStringValue:theQuery]; + [sshPasswordKeychainCheckbox setHidden:YES]; + } // Request the password, sizing the window appropriately to fit the query - [sshPasswordText setStringValue:theQuery]; queryTextSize = [[sshPasswordText cell] cellSizeForBounds:NSMakeRect(0, 0, [sshPasswordText bounds].size.width, 500)]; windowFrameRect = [sshPasswordDialog frame]; - windowFrameRect.size.height = ((queryTextSize.height < 40)?40:queryTextSize.height) + 143; + windowFrameRect.size.height = ((queryTextSize.height < 40)?40:queryTextSize.height) + 140 + ([sshPasswordDialog isSheet]?0:22); [sshPasswordDialog setFrame:windowFrameRect display:NO]; [NSApp beginSheet:sshPasswordDialog modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil]; int sshQueryResponseCode = [NSApp runModalForWindow:sshPasswordDialog]; @@ -459,11 +493,19 @@ thePassword = [NSString stringWithString:[sshPasswordField stringValue]]; [sshPasswordField setStringValue:@""]; [[delegate undoManager] removeAllActionsWithTarget:sshPasswordField]; - return thePassword; + requestedPassphrase = [[NSString alloc] initWithString:thePassword]; + + // Add to keychain if appropriate + if (keyName && [sshPasswordKeychainCheckbox state] == NSOnState) { + keychain = [[KeyChain alloc] init]; + [keychain addPassword:thePassword forName:@"SSH" account:keyName withLabel:[NSString stringWithFormat:@"SSH: %@", keyName]]; + [keychain release]; + } + return; // Cancel default: - return nil; + return; } } diff --git a/Source/TunnelPassphraseRequester.m b/Source/TunnelPassphraseRequester.m index 31c4b54a..11665449 100644 --- a/Source/TunnelPassphraseRequester.m +++ b/Source/TunnelPassphraseRequester.m @@ -23,6 +23,7 @@ #import <Cocoa/Cocoa.h> #import "KeyChain.h" #import "SPSSHTunnel.h" +#import "RegexKitLite.h" int main(int argc, const char *argv[]) { @@ -120,9 +121,25 @@ int main(int argc, const char *argv[]) } } - // Check whether we're being asked for a SSH key passphrase, forward requests to the GUI + // Check whether we're being asked for a SSH key passphrase if (argument && [[argument lowercaseString] rangeOfString:@"enter passphrase for"].location != NSNotFound ) { NSString *passphrase; + NSString *keyName = [argument stringByMatching:@"^\\s*Enter passphrase for key \\'(.*)\\':\\s*$" capture:1L]; + + if (keyName) { + + // Check whether the passphrase is in the keychain, using standard OS X sshagent name and account + KeyChain *keychain = [[KeyChain alloc] init]; + if ([keychain passwordExistsForName:@"SSH" account:keyName]) { + printf("%s\n", [[keychain getPasswordForName:@"SSH" account:keyName] UTF8String]); + [keychain release]; + [pool release]; + return 0; + } + [keychain release]; + } + + // Not found in the keychain - we need to ask the GUI. if (!verificationHash) { NSLog(@"SSH Tunnel: key passphrase authentication required but insufficient details supplied to connect to GUI"); diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 0a8ce9f2..4a7fdf16 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -88,6 +88,8 @@ 5841423F0F97E11000A34B47 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */; }; 584F5F8F0F50ACD800036517 /* table-view-small.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 584F5F8E0F50ACD800036517 /* table-view-small.tiff */; }; 586F432B0FD74CFC00B428D7 /* SSHQuestionDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = 586F432A0FD74CFC00B428D7 /* SSHQuestionDialog.xib */; }; + 586F457B0FDB269E00B428D7 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AB0F909194002A3258 /* RegexKitLite.m */; }; + 586F457E0FDB280100B428D7 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 296DC8BE0F9091DF002A3258 /* libicucore.dylib */; }; 5885940F0F7AEE6000ED0E67 /* sparkle-public-key.pem in Resources */ = {isa = PBXBuildFile; fileRef = 5885940E0F7AEE6000ED0E67 /* sparkle-public-key.pem */; }; 58C56EF50F438E120035701E /* SPDataCellFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C56EF40F438E120035701E /* SPDataCellFormatter.m */; }; 58CB20ED0F79A75D005EA204 /* button_edit_mode_selected.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 58CB20EC0F79A75D005EA204 /* button_edit_mode_selected.tiff */; }; @@ -409,6 +411,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 586F457E0FDB280100B428D7 /* libicucore.dylib in Frameworks */, 58CDB3400FCE13EF00F8ACA3 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1075,6 +1078,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 586F457B0FDB269E00B428D7 /* RegexKitLite.m in Sources */, 58CDB3410FCE141900F8ACA3 /* TunnelPassphraseRequester.m in Sources */, 58CDB3420FCE142500F8ACA3 /* KeyChain.m in Sources */, ); |