aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SSHTunnel.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2009-05-28 01:14:26 +0000
committerrowanbeentje <rowan@beent.je>2009-05-28 01:14:26 +0000
commit1979b7c94813e8278b4b7616aeafecd5a406f7a1 (patch)
tree108669de904ec9ee85806e5f91ec17b23cda1f7e /Source/SSHTunnel.m
parenta316ba498cf3300d05c8c2ba3223fa2c625d1717 (diff)
downloadsequelpro-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.m531
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