Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -40,10 +40,11 @@ OFObject+Serialization.m \ ${OFPLUGIN_M} \ OFSeekableStream.m \ OFSet.m \ OFSHA1Hash.m \ + OFSOCKS5Socket.m \ OFStream.m \ OFStreamObserver.m \ OFStreamSocket.m \ OFString.m \ OFString+Hashing.m \ ADDED src/OFSOCKS5Socket.h Index: src/OFSOCKS5Socket.h ================================================================== --- src/OFSOCKS5Socket.h +++ src/OFSOCKS5Socket.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFTCPSocket.h" + +/** + * \brief A class which provides functions to create and use TCP sockets using a + * SOCKS5 proxy. + */ +@interface OFSOCKS5Socket: OFTCPSocket +{ + OFString *proxyHost; + uint16_t proxyPort; +} + +/** + * \brief Creates a new, autoreleased OFSOCKS5Socket which uses the specified + * SOCKS5 proxy. + * + * \param proxyHost The host of the SOCKS5 proxy + * \param proxyPort The port of the SOCKS5 proxy + * \return A new, autoreleased OFSOCKS5Socket + */ ++ socketWithProxyHost: (OFString*)proxyHost + port: (uint16_t)proxyPort; + +/** + * \brief Initializes an already allocated OFSOCKS5Socket with the specified + * SOCKS5 proxy. + * + * \param proxyHost The host of the SOCKS5 proxy + * \param proxyPort The port of the SOCKS5 proxy + * \return An initialized OFSOCKS5Socket + */ +- initWithProxyHost: (OFString*)proxyHost + port: (uint16_t)proxyPort; +@end ADDED src/OFSOCKS5Socket.m Index: src/OFSOCKS5Socket.m ================================================================== --- src/OFSOCKS5Socket.m +++ src/OFSOCKS5Socket.m @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFSOCKS5Socket.h" + +#import "OFConnectionFailedException.h" +#import "OFNotImplementedException.h" + +@implementation OFSOCKS5Socket ++ socketWithProxyHost: (OFString*)host + port: (uint16_t)port +{ + return [[[self alloc] initWithProxyHost: host + port: port] autorelease]; +} + +- init +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithProxyHost: (OFString*)host + port: (uint16_t)port +{ + self = [super init]; + + @try { + proxyHost = [host copy]; + proxyPort = port; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [proxyHost release]; + + [super dealloc]; +} + +- (void)connectToHost: (OFString*)host + port: (uint16_t)port +{ + const char request[] = { 5, 1, 0, 3 }; + char reply[256]; + BOOL oldBuffersWrites; + + [super connectToHost: proxyHost + port: proxyPort]; + + /* 5 1 0 -> no authentication */ + [self writeNBytes: 3 + fromBuffer: request]; + + [self readExactlyNBytes: 2 + intoBuffer: reply]; + + if (reply[0] != 5 || reply[1] != 0) { + [self close]; + @throw [OFConnectionFailedException newWithClass: isa + socket: self + host: proxyHost + port: proxyPort]; + } + + oldBuffersWrites = [self buffersWrites]; + [self setBuffersWrites: YES]; + + /* CONNECT request */ + [self writeNBytes: 4 + fromBuffer: request]; + [self writeInt8: [host cStringLength]]; + [self writeString: host]; + [self writeBigEndianInt16: port]; + + [self flushWriteBuffer]; + [self setBuffersWrites: oldBuffersWrites]; + + [self readExactlyNBytes: 4 + intoBuffer: reply]; + + if (reply[0] != 5 || reply[1] != 0 || reply[2] != 0) { + [self close]; + @throw [OFConnectionFailedException newWithClass: isa + socket: self + host: host + port: port]; + } + + /* Skip the rest of the reply */ + switch (reply[3]) { + case 1: /* IPv4 */ + [self readExactlyNBytes: 4 + intoBuffer: reply]; + break; + case 3: /* Domainname */ + [self readExactlyNBytes: [self readInt8] + intoBuffer: reply]; + break; + case 4: /* IPv6 */ + [self readExactlyNBytes: 16 + intoBuffer: reply]; + break; + default: + [self close]; + @throw [OFConnectionFailedException newWithClass: isa + socket: self + host: host + port: port]; + } + + [self readBigEndianInt16]; +} +@end Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -44,10 +44,11 @@ #import "OFStream.h" #import "OFFile.h" #import "OFStreamSocket.h" #import "OFTCPSocket.h" +#import "OFSOCKS5Socket.h" #import "OFStreamObserver.h" #import "OFHTTPRequest.h" #import "OFHash.h"