diff options
author | rowanbeentje <rowan@beent.je> | 2009-05-28 01:14:26 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2009-05-28 01:14:26 +0000 |
commit | 1979b7c94813e8278b4b7616aeafecd5a406f7a1 (patch) | |
tree | 108669de904ec9ee85806e5f91ec17b23cda1f7e /Source/SSHTunnel.m | |
parent | a316ba498cf3300d05c8c2ba3223fa2c625d1717 (diff) | |
download | sequelpro-1979b7c94813e8278b4b7616aeafecd5a406f7a1.tar.gz sequelpro-1979b7c94813e8278b4b7616aeafecd5a406f7a1.tar.bz2 sequelpro-1979b7c94813e8278b4b7616aeafecd5a406f7a1.zip |
Add support for SSH tunnels, improve password security, and tweaks:
- Implementation of a new SPSSHTunnel class, designed to closely integrate SSH tunnels within Sequel Pro.
- Integration of SPSSHTunnel - new connection methods using callbacks, and CMMCPConnection integration
- Keychain class upgrade to include the new SPSSHTunnel keychain password helper on the trusted access list for new passwords
- Keychain passwords are now held in memory/UI for only as long as necessary, increasing password security
- Updated interface to enable/add SSH tunnel functionality
- Remove old SSHTunnel class
- Addition of new target for the SSH Tunnel password assistant, addition as a dependency of the main target, and addition to build script to copy into resources directory
- Fix a keychain password deletion crash
Diffstat (limited to 'Source/SSHTunnel.m')
-rw-r--r-- | Source/SSHTunnel.m | 531 |
1 files changed, 0 insertions, 531 deletions
diff --git a/Source/SSHTunnel.m b/Source/SSHTunnel.m deleted file mode 100644 index 617db8a7..00000000 --- a/Source/SSHTunnel.m +++ /dev/null @@ -1,531 +0,0 @@ -// -// SSHTunnel.m -// SSH Tunnel Manager 2 -// -// Created by Yann Bizeul on Wed Nov 19 2003. -// Copyright (c) 2003 __MyCompanyName__. All rights reserved. -// - -#import "SSHTunnel.h" -#include <unistd.h> - -// start diff lorenz textor -/* -#define T_START NSLocalizedString(@"T_START",@"") -#define T_STOP NSLocalizedString(@"T_STOP",@"") -#define S_IDLE NSLocalizedString(@"S_IDLE",@"") -#define S_CONNECTING NSLocalizedString(@"S_CONNECTING",@"") -#define S_CONNECTED NSLocalizedString(@"S_CONNECTED",@"") -#define S_AUTH NSLocalizedString(@"S_AUTH",@"") -#define S_PORT NSLocalizedString(@"S_PORT",@"") -*/ -#define T_START @"START: %@" -#define T_STOP @"STOP: %@" -#define S_IDLE @"Idle" -#define S_CONNECTING @"Connecting..." -#define S_CONNECTED @"Connected" -#define S_AUTH @"Authenticated" -#define S_PORT "Port %@ forwarded" -// end diff lorenz textor - -@implementation SSHTunnel - -#pragma mark - -#pragma mark Initialization --(id)init -{ - return [ self initWithName:@"New Tunnel"]; -} --(id)initWithName:(NSString*)aName -{ - NSDictionary *dictionary = [ NSDictionary dictionaryWithObjectsAndKeys: - [ NSNumber numberWithBool: NO ],@"compression", - [ NSNumber numberWithBool: YES ],@"connAuth", - @"", @"connHost", - aName, @"connName", - @"", @"connPort", - [ NSNumber numberWithBool: NO ],@"connRemote", - @"", @"connUser", - @"3des", @"encryption", - [ NSNumber numberWithBool: NO ],@"socks4", - [ NSNumber numberWithInt: 1080 ], @"socks4p", - [ NSArray array ], @"tunnelsLocal", - [ NSArray array ], @"tunnelsRemote", - [ NSNumber numberWithBool: NO ],@"v1", nil - ]; - return [ self initWithDictionary: dictionary ]; -} --(id)initWithDictionary:(NSDictionary*)aDictionary -{ - NSEnumerator *e; - NSString *key; - - self = [ super init ]; - e = [[ aDictionary allKeys ] objectEnumerator ]; - while (key = [ e nextObject ]) - { - [ self setValue: [ aDictionary objectForKey: key ] forKey: key ]; - } - code = 0; - if ([[ self valueForKey: @"autoConnect" ] boolValue ]) - [ self startTunnel ]; - return self; -} -+(id)tunnelWithName:(NSString*)aName -{ - return [[ SSHTunnel alloc ] initWithName: aName ]; -} -+(SSHTunnel*)tunnelFromDictionary:(NSDictionary*)aDictionary -{ - return [[ SSHTunnel alloc ] initWithDictionary: aDictionary ]; -} -+(NSArray*)tunnelsFromArray:(NSArray*)anArray -{ - NSMutableArray *newArray; - SSHTunnel *currentTunnel; - NSEnumerator *e; - NSDictionary *currentTunnelDictionary; - - newArray = [ NSMutableArray array ]; - e = [ anArray objectEnumerator ]; - while (currentTunnelDictionary = [ e nextObject ]) - { - currentTunnel = [ SSHTunnel tunnelFromDictionary: currentTunnelDictionary ]; - [ newArray addObject: currentTunnel ]; - } - return [[ newArray copy ] autorelease ]; -} - -#pragma mark - -#pragma mark Adding and removing port redir. --(void)addLocalTunnel:(NSDictionary*)aDictionary; -{ - NSMutableArray *tempTunnelsLocal = [ NSMutableArray arrayWithArray: tunnelsLocal ]; - [ tempTunnelsLocal addObject: aDictionary ]; - [ tunnelsLocal release ]; - tunnelsLocal = [ tempTunnelsLocal copy ]; -} -- (void)removeLocal:(int)index -{ - NSMutableArray *tempLocalTunnels = [ tunnelsLocal mutableCopy ]; - [ tempLocalTunnels removeObjectAtIndex: index ]; - [ tunnelsLocal release ]; - tunnelsLocal = [ tempLocalTunnels copy ]; - [ tempLocalTunnels release ]; -} --(void)addRemoteTunnel:(NSDictionary*)aDictionary; -{ - NSMutableArray *tempTunnelsRemote = [ NSMutableArray arrayWithArray: tunnelsRemote ]; - [ tempTunnelsRemote addObject: aDictionary ]; - [ tunnelsRemote release ]; - tunnelsRemote = [ tempTunnelsRemote copy ]; -} -- (void)removeRemote:(int)index -{ - NSMutableArray *tempRemoteTunnels = [ tunnelsRemote mutableCopy ]; - [ tempRemoteTunnels removeObjectAtIndex: index ]; - [ tunnelsRemote release ]; - tunnelsRemote = [ tempRemoteTunnels copy ]; - [ tempRemoteTunnels release ]; -} -- (void)setLocalValue:(NSString*)aValue ofTunnel:(int)index forKey:(NSString*)key -{ - NSMutableArray *tempLocalTunnel; - NSMutableDictionary *tempCurrentTunnel; - - tempLocalTunnel = [tunnelsLocal mutableCopy]; - tempCurrentTunnel = [[ tempLocalTunnel objectAtIndex: index ] mutableCopy ]; - - [ tempCurrentTunnel setObject: aValue forKey: key ]; - [ tempLocalTunnel replaceObjectAtIndex:index withObject:[tempCurrentTunnel copy ]]; - [ tempCurrentTunnel release ]; - [ tunnelsLocal release ]; - tunnelsLocal = [ tempLocalTunnel copy ]; -} -- (void)setRemoteValue:(NSString*)aValue ofTunnel:(int)index forKey:(NSString*)key -{ - NSMutableArray *tempRemoteTunnel; - NSMutableDictionary *tempCurrentTunnel; - - tempRemoteTunnel = [tunnelsRemote mutableCopy]; - tempCurrentTunnel = [[ tempRemoteTunnel objectAtIndex: index ] mutableCopy ]; - - [ tempCurrentTunnel setObject: aValue forKey: key ]; - [ tempRemoteTunnel replaceObjectAtIndex:index withObject:[tempCurrentTunnel copy ]]; - [ tempCurrentTunnel release ]; - [ tunnelsRemote release ]; - tunnelsRemote = [ tempRemoteTunnel copy ]; -} - -#pragma mark - -#pragma mark Execution related -- (void)startTunnel -{ -// NSDictionary *t; -// NSEnumerator *e; -// BOOL asRoot = NO; - - if ([ self isRunning ]) - return; - - shouldStop = NO; - /* - [ arguments addObject: @"-N" ]; - [ arguments addObject: @"-v" ]; - [ arguments addObject: @"-p" ]; - if ([ connPort length ]) - [ arguments addObject: connPort]; - else - [ arguments addObject: @"22" ]; - - if (connRemote) - [ arguments addObject: @"-g" ]; - if (compression) - [ arguments addObject: @"-C" ]; - if (v1) - [ arguments addObject: @"-1" ]; - - [ arguments addObject: @"-c"]; - if (encryption) - [ arguments addObject: encryption]; - else - [ arguments addObject: @"3des"]; - - if (socks4 && socks4p != nil) - { - [ arguments addObject: @"-D" ]; - [ arguments addObject: [ socks4p stringValue ]]; - } - [ arguments addObject: [ NSString stringWithFormat: @"%@@%@", - connUser, connHost ] - ]; - - NSString *hostPort; - e = [ tunnelsLocal objectEnumerator ]; - while (t = [ e nextObject ]) - { - [ arguments addObject: @"-L" ]; - if ([[ t objectForKey:@"hostport"] isEqualTo: @"" ]) - hostPort = [ t objectForKey:@"port" ]; - else - hostPort = [ t objectForKey:@"hostport" ]; - [ arguments addObject: [NSString stringWithFormat:@"%@/%@/%@", - [ t objectForKey:@"port"], - [ t objectForKey:@"host"], - hostPort - ] ]; - if ([[ t objectForKey:@"port"] intValue] < 1024) - asRoot=YES; - } - - e = [ tunnelsRemote objectEnumerator ]; - while (t = [ e nextObject ]) - { - [ arguments addObject: @"-R" ]; - if ([[ t objectForKey:@"hostport"] isEqualTo: @"" ]) - hostPort = [ t objectForKey:@"port" ]; - else - hostPort = [ t objectForKey:@"hostport" ]; - [ arguments addObject: [NSString stringWithFormat:@"%@/%@/%@", - [ t objectForKey:@"port"], - [ t objectForKey:@"host"], - hostPort - ]]; - } - args = [ NSMutableDictionary dictionary ]; - [ args setObject: arguments forKey:@"arguments" ]; - [ args setObject: [ NSNumber numberWithBool: connAuth ] forKey: @"handleAuth" ]; - [ args setObject: connName forKey:@"tunnelName" ]; - [ args setObject: [ NSNumber numberWithBool: asRoot ] forKey: @"asRoot" ]; - - - [ NSThread detachNewThreadSelector:@selector(launchTunnel:) - toTarget: self - withObject: args ]; - */ - [ NSThread detachNewThreadSelector:@selector(launchTunnel:) - toTarget: self - withObject: nil ]; -// [ arguments release ]; - -} -- (void)stopTunnel -{ - if (! [ self isRunning ]) - return; - shouldStop=YES; - [ self setValue: nil forKey: @"status" ]; - [ task terminate ]; - code = 0; - [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; -} - -- (void)toggleTunnel -{ - if ([ self isRunning ]) - [ self stopTunnel ]; - else - [ self startTunnel ]; -} - -- (void)launchTunnel:(id)foo; -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - if (task) - [ task release ]; - task = [[ NSTask alloc ] init ]; - NSMutableDictionary *environment = [ NSMutableDictionary dictionaryWithDictionary: [[ NSProcessInfo processInfo ] environment ]]; - NSString *pathToAuthentifier = [[ NSBundle mainBundle ] pathForResource: @"askForPass" ofType: @"sh" ]; - if (socks4) - [ task setLaunchPath: [[ NSBundle mainBundle ] pathForResource: @"ssh" ofType: @"" ]]; - else - [ task setLaunchPath: @"/usr/bin/ssh" ]; - [ task setArguments: [ self arguments ]]; - if (connAuth) - { - [ environment removeObjectForKey: @"SSH_AGENT_PID" ]; - [ environment removeObjectForKey: @"SSH_AUTH_SOCK" ]; - [ environment setObject: pathToAuthentifier forKey: @"SSH_ASKPASS" ]; - [ environment setObject:@":0" forKey:@"DISPLAY" ]; - } - [ environment setObject: connName forKey: @"TUNNEL_NAME" ]; - [ task setEnvironment: environment ]; - - stdErrPipe = [[ NSPipe alloc ] init ]; - [ task setStandardError: stdErrPipe ]; - - [[ NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(stdErr:) - name: @"NSFileHandleDataAvailableNotification" - object:[ stdErrPipe fileHandleForReading]]; - - [[ stdErrPipe fileHandleForReading] waitForDataInBackgroundAndNotify ]; - - NSLog(T_START,connName); - [ self setValue: S_CONNECTING forKey: @"status" ]; - code = 1; - [ task launch ]; - [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; - [ task waitUntilExit ]; - sleep(1); - code = 0; - [ self setValue: S_IDLE forKey: @"status" ]; - NSLog(T_STOP,connName); - [[ NSNotificationCenter defaultCenter] removeObserver:self - name: @"NSFileHandleDataAvailableNotification" - object:[ stdErrPipe fileHandleForReading]]; - [ task release ]; - task = nil; - [ stdErrPipe release ]; - stdErrPipe = nil; - [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; - if (! shouldStop) - [ self startTunnel ]; - [ pool release ]; -} - -- (void)stdErr:(NSNotification*)aNotification -{ - NSData *data = [[ aNotification object ] availableData ]; - NSString *log = [[ NSString alloc ] initWithData: data encoding: NSASCIIStringEncoding ]; - BOOL wait = YES; - if ([ log length ]) - { - //NSLog(log); - NSArray *lines = [ log componentsSeparatedByString:@"\n" ]; - NSEnumerator *e = [ lines objectEnumerator ]; - NSString *line; - while (line = [ e nextObject ]) - { - if ([ line rangeOfString:@"Entering interactive session." ].location != NSNotFound) - { - code = 2; - [ self setValue: S_CONNECTED forKey: @"status"]; - } - if ([ line rangeOfString:@"Authentication succeeded" ].location != NSNotFound) - [ self setValue: S_AUTH forKey: @"status"]; - if ([ line rangeOfString:@"Connections to local port" ].location != NSNotFound) - { - NSScanner *s; - NSString *port; - s = [ NSScanner scannerWithString:log]; - [ s scanUpToString: @"Connections to local port " intoString: nil ]; - [ s scanString: @"Connections to local port " intoString: nil ]; - [ s scanUpToString: @"forwarded" intoString:&port]; - [ self setValue: [ NSString stringWithFormat: @"Port %@ forwarded", port ] forKey: @"status"]; - } - if ([ line rangeOfString:@"closed by remote host." ].location != NSNotFound) - { - [ task terminate]; - [ self setValue: @"Connection closed" forKey: @"status"]; - wait = NO; - } - [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; - } - if (wait) - [[ stdErrPipe fileHandleForReading ] waitForDataInBackgroundAndNotify ]; - } - [ log release] ; -} - -- (BOOL)isRunning -{ - if ([ task isRunning ]) - return YES; - return NO; -} - -#pragma mark - -#pragma mark Getting tunnel informations -- (NSString *)status -{ - if (status) - return status; - return S_IDLE; -} -- (NSArray*)arguments -{ - NSMutableArray *arguments; - NSEnumerator *e; - NSDictionary *t; - BOOL asRoot; - - arguments = [ NSMutableArray array ]; - [ arguments addObject: @"-N" ]; - [ arguments addObject: @"-v" ]; - [ arguments addObject: @"-p" ]; - if ([ connPort length ]) - [ arguments addObject: connPort]; - else - [ arguments addObject: @"22" ]; - - if (connRemote) - [ arguments addObject: @"-g" ]; - if (compression) - [ arguments addObject: @"-C" ]; - if (v1) - [ arguments addObject: @"-1" ]; - - [ arguments addObject: @"-c"]; - if (encryption) - [ arguments addObject: encryption]; - else - [ arguments addObject: @"3des"]; - - if (socks4 && socks4p != nil) - { - [ arguments addObject: @"-D" ]; - [ arguments addObject: [ socks4p stringValue ]]; - } - [ arguments addObject: [ NSString stringWithFormat: @"%@@%@", - connUser, connHost ] - ]; - - NSString *hostPort; - e = [ tunnelsLocal objectEnumerator ]; - while (t = [ e nextObject ]) - { - [ arguments addObject: @"-L" ]; - if ([[ t objectForKey:@"hostport"] isEqualTo: @"" ]) - hostPort = [ t objectForKey:@"port" ]; - else - hostPort = [ t objectForKey:@"hostport" ]; - [ arguments addObject: [NSString stringWithFormat:@"%@/%@/%@", - [ t objectForKey:@"port"], - [ t objectForKey:@"host"], - hostPort - ] ]; - if ([[ t objectForKey:@"port"] intValue] < 1024) - asRoot=YES; - } - - e = [ tunnelsRemote objectEnumerator ]; - while (t = [ e nextObject ]) - { - [ arguments addObject: @"-R" ]; - if ([[ t objectForKey:@"hostport"] isEqualTo: @"" ]) - hostPort = [ t objectForKey:@"port" ]; - else - hostPort = [ t objectForKey:@"hostport" ]; - [ arguments addObject: [NSString stringWithFormat:@"%@/%@/%@", - [ t objectForKey:@"port"], - [ t objectForKey:@"host"], - hostPort - ]]; - } - - return [[ arguments copy ] autorelease ]; -} - -- (NSDictionary*)dictionary -{ - return [ NSDictionary dictionaryWithObjectsAndKeys: - [ NSNumber numberWithBool: compression ],@"compression", - [ NSNumber numberWithBool: connAuth ],@"connAuth", - [ NSNumber numberWithBool: autoConnect ],@"autoConnect", - connHost, @"connHost", - connName, @"connName", - connPort, @"connPort", - [ NSNumber numberWithBool: connRemote ],@"connRemote", - connUser, @"connUser", - encryption, @"encryption", - [ NSNumber numberWithBool: socks4 ],@"socks4", - socks4p, @"socks4p", - tunnelsLocal, @"tunnelsLocal", - tunnelsRemote, @"tunnelsRemote", - [ NSNumber numberWithBool: v1 ],@"v1", nil - ]; -} - - -#pragma mark - -#pragma mark Key/Value coding -- (NSImage*)icon -{ - switch (code) - { - case 0: - return [ NSImage imageNamed: @"offState" ]; - break; - case 1: - return [ NSImage imageNamed: @"middleState" ]; - break; - case 2: - return [ NSImage imageNamed: @"onState" ]; - break; - } - return [ NSImage imageNamed: @"offState" ]; -} -- (void)setValue:(id)value forUndefinedKey:(NSString *)key -{ - NSLog(@"key %@ undefined",key); -} -- (id)valueForUndefinedKey:(NSString *)key -{ - return nil; -} - -#pragma mark - -#pragma mark Misc. --(void)dealloc -{ - [ self stopTunnel ]; - [ tunnelsLocal release ]; - [ tunnelsRemote release ]; - - [ task release ]; - [ stdErrPipe release ]; - [ connName release ]; - [ status release ]; - [ connPort release ]; - [ encryption release ]; - [ socks4p release ]; - [ connUser release ]; - [ connHost release ]; - - // start diff lorenz textor - [super dealloc]; - // end diff lorenz textor -} -@end |