From 4a7150797650e1991d966a33fa5b10c8dc629982 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:04:56 -0700 Subject: [PATCH 01/17] Fix whitespace --- twisted/test/test_socks.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/twisted/test/test_socks.py b/twisted/test/test_socks.py index f4543d622f4..c7747b37ec8 100644 --- a/twisted/test/test_socks.py +++ b/twisted/test/test_socks.py @@ -22,9 +22,11 @@ class StringTCPTransport(proto_helpers.StringTransport): def getPeer(self): return self.peer + def getHost(self): return address.IPv4Address('TCP', '2.3.4.5', 42) + def loseConnection(self): self.stringTCPTransport_closing = True @@ -71,6 +73,7 @@ def connectClass(self, host, port, klass, *args): self.driver_outgoing = proto return defer.succeed(proto) + def listenClass(self, port, klass, *args): # fake it factory = klass(*args) @@ -268,6 +271,7 @@ def setUp(self): ## self.assert_(incoming.transport.stringTCPTransport_closing, ## "Incoming SOCKS connections need to be closed.") + def test_simple(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) @@ -410,6 +414,7 @@ def test_accessDenied(self): self.assertTrue(self.sock.transport.stringTCPTransport_closing) self.assertIsNone(self.sock.driver_listen) + def test_eofRemote(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) @@ -442,6 +447,7 @@ def test_eofRemote(self): incoming.transport.loseConnection() incoming.connectionLost('fake reason') + def test_eofLocal(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) @@ -473,6 +479,7 @@ def test_eofLocal(self): # now close it from the client side self.sock.connectionLost('fake reason') + def test_badSource(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) From 11a5fb25b429eef6ba9a65e40e129367ff7d2711 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:11:10 -0700 Subject: [PATCH 02/17] Re-order imports --- twisted/test/test_socks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/twisted/test/test_socks.py b/twisted/test/test_socks.py index c7747b37ec8..eda2d267c0b 100644 --- a/twisted/test/test_socks.py +++ b/twisted/test/test_socks.py @@ -8,11 +8,11 @@ import struct, socket -from twisted.trial import unittest -from twisted.test import proto_helpers from twisted.internet import defer, address from twisted.internet.error import DNSLookupError from twisted.protocols import socks +from twisted.test import proto_helpers +from twisted.trial import unittest class StringTCPTransport(proto_helpers.StringTransport): From a3f4283960bee48c30194226e7506760a79753a0 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:11:42 -0700 Subject: [PATCH 03/17] Fix docstring references --- twisted/test/test_socks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twisted/test/test_socks.py b/twisted/test/test_socks.py index eda2d267c0b..6cec74a4530 100644 --- a/twisted/test/test_socks.py +++ b/twisted/test/test_socks.py @@ -38,7 +38,7 @@ class FakeResolverReactor: """ def __init__(self, names): """ - @type names: C{dict} containing C{str} keys and C{str} values. + @type names: L{dict} containing L{str} keys and L{str} values. @param names: A hostname to IP address mapping. The IP addresses are stringified dotted quads. """ From 1bf4e7e678b9e83d884f291d38fee86acb20d028 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:16:29 -0700 Subject: [PATCH 04/17] Use twisted.python.compat iterbytes to iterate over bytes --- twisted/test/test_socks.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/twisted/test/test_socks.py b/twisted/test/test_socks.py index 6cec74a4530..5c8035fd865 100644 --- a/twisted/test/test_socks.py +++ b/twisted/test/test_socks.py @@ -10,6 +10,7 @@ from twisted.internet import defer, address from twisted.internet.error import DNSLookupError +from twisted.python.compat import iterbytes from twisted.protocols import socks from twisted.test import proto_helpers from twisted.trial import unittest @@ -147,7 +148,7 @@ def test_socks4aSuccessfulResolution(self): # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" # the hostname. - for byte in clientRequest: + for byte in iterbytes(clientRequest): self.sock.dataReceived(byte) sent = self.sock.transport.value() @@ -190,7 +191,7 @@ def test_socks4aFailedResolution(self): # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" # the hostname. - for byte in clientRequest: + for byte in iterbytes(clientRequest): self.sock.dataReceived(byte) # Verify that the server responds with a 91 error. @@ -331,7 +332,7 @@ def test_socks4a(self): # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" # the hostname. - for byte in clientRequest: + for byte in iterbytes(clientRequest): self.sock.dataReceived(byte) sent = self.sock.transport.value() @@ -387,7 +388,7 @@ def test_socks4aFailedResolution(self): # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" # the hostname. - for byte in clientRequest: + for byte in iterbytes(clientRequest): self.sock.dataReceived(byte) # Verify that the server responds with a 91 error. From 664ad39ebc6ec4b2155ff0f44989de0534a90b35 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:39:23 -0700 Subject: [PATCH 05/17] Use byte strings --- twisted/test/test_socks.py | 105 ++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/twisted/test/test_socks.py b/twisted/test/test_socks.py index 5c8035fd865..31f222357b9 100644 --- a/twisted/test/test_socks.py +++ b/twisted/test/test_socks.py @@ -93,7 +93,7 @@ def setUp(self): self.sock = SOCKSv4Driver() self.sock.transport = StringTCPTransport() self.sock.connectionMade() - self.sock.reactor = FakeResolverReactor({"localhost":"127.0.0.1"}) + self.sock.reactor = FakeResolverReactor({b"localhost":"127.0.0.1"}) def tearDown(self): @@ -107,8 +107,8 @@ def test_simple(self): self.sock.dataReceived( struct.pack('!BBH', 4, 1, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') sent = self.sock.transport.value() self.sock.transport.clear() self.assertEqual(sent, @@ -118,13 +118,13 @@ def test_simple(self): self.assertIsNotNone(self.sock.driver_outgoing) # pass some data through - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual(self.sock.driver_outgoing.transport.value(), - 'hello, world') + b'hello, world') # the other way around - self.sock.driver_outgoing.dataReceived('hi there') - self.assertEqual(self.sock.transport.value(), 'hi there') + self.sock.driver_outgoing.dataReceived(b'hi there') + self.assertEqual(self.sock.transport.value(), b'hi there') self.sock.connectionLost('fake reason') @@ -142,8 +142,8 @@ def test_socks4aSuccessfulResolution(self): clientRequest = ( struct.pack('!BBH', 4, 1, 34) + socket.inet_aton('0.0.0.1') - + 'fooBAZ\0' - + 'localhost\0') + + b'fooBAZ\0' + + b'localhost\0') # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" @@ -164,14 +164,14 @@ def test_socks4aSuccessfulResolution(self): # Pass some data through and verify it is forwarded to the outgoing # connection. - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual( - self.sock.driver_outgoing.transport.value(), 'hello, world') + self.sock.driver_outgoing.transport.value(), b'hello, world') # Deliver some data from the output connection and verify it is # passed along to the incoming side. - self.sock.driver_outgoing.dataReceived('hi there') - self.assertEqual(self.sock.transport.value(), 'hi there') + self.sock.driver_outgoing.dataReceived(b'hi there') + self.assertEqual(self.sock.transport.value(), b'hi there') self.sock.connectionLost('fake reason') @@ -185,8 +185,8 @@ def test_socks4aFailedResolution(self): clientRequest = ( struct.pack('!BBH', 4, 1, 34) + socket.inet_aton('0.0.0.1') - + 'fooBAZ\0' - + 'failinghost\0') + + b'fooBAZ\0' + + b'failinghost\0') # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" @@ -210,8 +210,8 @@ def test_accessDenied(self): self.sock.dataReceived( struct.pack('!BBH', 4, 1, 4242) + socket.inet_aton('10.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') self.assertEqual(self.sock.transport.value(), struct.pack('!BBH', 0, 91, 0) + socket.inet_aton('0.0.0.0')) @@ -223,14 +223,14 @@ def test_eofRemote(self): self.sock.dataReceived( struct.pack('!BBH', 4, 1, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') self.sock.transport.clear() # pass some data through - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual(self.sock.driver_outgoing.transport.value(), - 'hello, world') + b'hello, world') # now close it from the server side self.sock.driver_outgoing.transport.loseConnection() @@ -241,14 +241,14 @@ def test_eofLocal(self): self.sock.dataReceived( struct.pack('!BBH', 4, 1, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') self.sock.transport.clear() # pass some data through - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual(self.sock.driver_outgoing.transport.value(), - 'hello, world') + b'hello, world') # now close it from the client side self.sock.connectionLost('fake reason') @@ -263,7 +263,7 @@ def setUp(self): self.sock = SOCKSv4Driver() self.sock.transport = StringTCPTransport() self.sock.connectionMade() - self.sock.reactor = FakeResolverReactor({"localhost":"127.0.0.1"}) + self.sock.reactor = FakeResolverReactor({b"localhost":"127.0.0.1"}) ## def tearDown(self): ## # TODO ensure the listen port is closed @@ -272,13 +272,12 @@ def setUp(self): ## self.assert_(incoming.transport.stringTCPTransport_closing, ## "Incoming SOCKS connections need to be closed.") - def test_simple(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') sent = self.sock.transport.value() self.sock.transport.clear() self.assertEqual(sent, @@ -302,13 +301,13 @@ def test_simple(self): self.assertFalse(self.sock.transport.stringTCPTransport_closing) # pass some data through - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual(incoming.transport.value(), - 'hello, world') + b'hello, world') # the other way around - incoming.dataReceived('hi there') - self.assertEqual(self.sock.transport.value(), 'hi there') + incoming.dataReceived(b'hi there') + self.assertEqual(self.sock.transport.value(), b'hi there') self.sock.connectionLost('fake reason') @@ -326,8 +325,8 @@ def test_socks4a(self): clientRequest = ( struct.pack('!BBH', 4, 2, 34) + socket.inet_aton('0.0.0.1') - + 'fooBAZ\0' - + 'localhost\0') + + b'fooBAZ\0' + + b'localhost\0') # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" @@ -363,12 +362,12 @@ def test_socks4a(self): # Deliver some data from the output connection and verify it is # passed along to the incoming side. - self.sock.dataReceived('hi there') - self.assertEqual(incoming.transport.value(), 'hi there') + self.sock.dataReceived(b'hi there') + self.assertEqual(incoming.transport.value(), b'hi there') # the other way around - incoming.dataReceived('hi there') - self.assertEqual(self.sock.transport.value(), 'hi there') + incoming.dataReceived(b'hi there') + self.assertEqual(self.sock.transport.value(), b'hi there') self.sock.connectionLost('fake reason') @@ -382,8 +381,8 @@ def test_socks4aFailedResolution(self): clientRequest = ( struct.pack('!BBH', 4, 2, 34) + socket.inet_aton('0.0.0.1') - + 'fooBAZ\0' - + 'failinghost\0') + + b'fooBAZ\0' + + b'failinghost\0') # Deliver the bytes one by one to exercise the protocol's buffering # logic. FakeResolverReactor's resolve method is invoked to "resolve" @@ -407,8 +406,8 @@ def test_accessDenied(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 4242) + socket.inet_aton('10.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') self.assertEqual(self.sock.transport.value(), struct.pack('!BBH', 0, 91, 0) + socket.inet_aton('0.0.0.0')) @@ -420,8 +419,8 @@ def test_eofRemote(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') sent = self.sock.transport.value() self.sock.transport.clear() @@ -440,9 +439,9 @@ def test_eofRemote(self): self.assertFalse(self.sock.transport.stringTCPTransport_closing) # pass some data through - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual(incoming.transport.value(), - 'hello, world') + b'hello, world') # now close it from the server side incoming.transport.loseConnection() @@ -453,8 +452,8 @@ def test_eofLocal(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') sent = self.sock.transport.value() self.sock.transport.clear() @@ -473,9 +472,9 @@ def test_eofLocal(self): self.assertFalse(self.sock.transport.stringTCPTransport_closing) # pass some data through - self.sock.dataReceived('hello, world') + self.sock.dataReceived(b'hello, world') self.assertEqual(incoming.transport.value(), - 'hello, world') + b'hello, world') # now close it from the client side self.sock.connectionLost('fake reason') @@ -485,8 +484,8 @@ def test_badSource(self): self.sock.dataReceived( struct.pack('!BBH', 4, 2, 34) + socket.inet_aton('1.2.3.4') - + 'fooBAR' - + '\0') + + b'fooBAR' + + b'\0') sent = self.sock.transport.value() self.sock.transport.clear() From b0d8257abb05b20d42f4da64d66a924feec2315f Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:42:35 -0700 Subject: [PATCH 06/17] Decode hostname from bytes to string, to put in error message --- twisted/test/test_socks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/twisted/test/test_socks.py b/twisted/test/test_socks.py index 31f222357b9..38283ef88a3 100644 --- a/twisted/test/test_socks.py +++ b/twisted/test/test_socks.py @@ -54,7 +54,8 @@ def resolve(self, hostname): return defer.succeed(self.names[hostname]) except KeyError: return defer.fail( - DNSLookupError("FakeResolverReactor couldn't find " + hostname)) + DNSLookupError("FakeResolverReactor couldn't find " + + hostname.decode("utf-8"))) From 27e71c7d87d463c3733dde011cb33fec0d22237d Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:47:37 -0700 Subject: [PATCH 07/17] Fix whitespace --- twisted/protocols/socks.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/twisted/protocols/socks.py b/twisted/protocols/socks.py index 332f77385b7..29978268cb8 100644 --- a/twisted/protocols/socks.py +++ b/twisted/protocols/socks.py @@ -18,21 +18,24 @@ class SOCKSv4Outgoing(protocol.Protocol): - def __init__(self,socks): self.socks=socks + def connectionMade(self): peer = self.transport.getPeer() self.socks.makeReply(90, 0, port=peer.port, ip=peer.host) self.socks.otherConn=self + def connectionLost(self, reason): self.socks.transport.loseConnection() + def dataReceived(self,data): self.socks.write(data) + def write(self,data): self.socks.log(self,data) self.transport.write(data) @@ -40,22 +43,25 @@ def write(self,data): class SOCKSv4Incoming(protocol.Protocol): - def __init__(self,socks): self.socks=socks self.socks.otherConn=self + def connectionLost(self, reason): self.socks.transport.loseConnection() + def dataReceived(self,data): self.socks.write(data) + def write(self,data): self.socks.log(self,data) self.transport.write(data) + class SOCKSv4(protocol.Protocol): """ An implementation of the SOCKSv4 protocol. @@ -79,10 +85,12 @@ def __init__(self, logging=None, reactor=reactor): self.logging = logging self.reactor = reactor + def connectionMade(self): self.buf = "" self.otherConn = None + def dataReceived(self, data): """ Called whenever data is received. @@ -118,6 +126,7 @@ def dataReceived(self, data): self._dataReceived2(server, user, version, code, port) + def _dataReceived2(self, server, user, version, code, port): """ The second half of the SOCKS connection setup. For a SOCKSv4 packet this @@ -157,29 +166,36 @@ def _dataReceived2(self, server, user, version, code, port): assert self.buf == "", "hmm, still stuff in buffer... %s" % repr( self.buf) + def connectionLost(self, reason): if self.otherConn: self.otherConn.transport.loseConnection() + def authorize(self,code,server,port,user): log.msg("code %s connection to %s:%s (user %s) authorized" % (code,server,port,user)) return 1 + def connectClass(self, host, port, klass, *args): return protocol.ClientCreator(reactor, klass, *args).connectTCP(host,port) + def listenClass(self, port, klass, *args): serv = reactor.listenTCP(port, klass(*args)) return defer.succeed(serv.getHost()[1:]) + def makeReply(self,reply,version=0,port=0,ip="0.0.0.0"): self.transport.write(struct.pack("!BBH",version,reply,port)+socket.inet_aton(ip)) if reply!=90: self.transport.loseConnection() + def write(self,data): self.log(self,data) self.transport.write(data) + def log(self,proto,data): if not self.logging: return peer = self.transport.getPeer() @@ -208,10 +224,10 @@ class SOCKSv4Factory(protocol.Factory): Constructor accepts one argument, a log file name. """ - def __init__(self, log): self.logging = log + def buildProtocol(self, addr): return SOCKSv4(self.logging, reactor) @@ -221,7 +237,6 @@ class SOCKSv4IncomingFactory(protocol.Factory): """ A utility class for building protocols for incoming connections. """ - def __init__(self, socks, ip): self.socks = socks self.ip = ip From babb3b2e688afd58a9c1079aaa76617e33230d70 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:52:23 -0700 Subject: [PATCH 08/17] Fix whitespace and fix docstring references --- twisted/protocols/socks.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/twisted/protocols/socks.py b/twisted/protocols/socks.py index 29978268cb8..7b8116f4484 100644 --- a/twisted/protocols/socks.py +++ b/twisted/protocols/socks.py @@ -18,7 +18,7 @@ class SOCKSv4Outgoing(protocol.Protocol): - def __init__(self,socks): + def __init__(self, socks): self.socks=socks @@ -32,7 +32,7 @@ def connectionLost(self, reason): self.socks.transport.loseConnection() - def dataReceived(self,data): + def dataReceived(self, data): self.socks.write(data) @@ -56,7 +56,7 @@ def dataReceived(self,data): self.socks.write(data) - def write(self,data): + def write(self, data): self.socks.log(self,data) self.transport.write(data) @@ -66,14 +66,14 @@ class SOCKSv4(protocol.Protocol): """ An implementation of the SOCKSv4 protocol. - @type logging: C{str} or L{None} + @type logging: L{str} or L{None} @ivar logging: If not L{None}, the name of the logfile to which connection information will be written. @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP} @ivar reactor: The reactor used to create connections. - @type buf: C{str} + @type buf: L{str} @ivar buf: Part of a SOCKSv4 connection request. @type otherConn: C{SOCKSv4Incoming}, C{SOCKSv4Outgoing} or L{None} @@ -133,21 +133,21 @@ def _dataReceived2(self, server, user, version, code, port): is after the server address has been extracted from the header. For a SOCKSv4a packet this is after the host name has been resolved. - @type server: C{str} + @type server: L{str} @param server: The IP address of the destination, represented as a dotted quad. - @type user: C{str} + @type user: L{str} @param user: The username associated with the connection. - @type version: C{int} + @type version: L{int} @param version: The SOCKS protocol version number. - @type code: C{int} + @type code: L{int} @param code: The comand code. 1 means establish a TCP/IP stream connection, and 2 means establish a TCP/IP port binding. - @type port: C{int} + @type port: L{int} @param port: The port number associated with the connection. """ assert version == 4, "Bad version code: %s" % version From 4734921e7f682f8b3848787b7ed4c3a412d2b887 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 06:53:17 -0700 Subject: [PATCH 09/17] Change docstring of dataReceived() to take a bytes argument. This improves compatibility with Python 3 --- twisted/protocols/socks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twisted/protocols/socks.py b/twisted/protocols/socks.py index 7b8116f4484..227364c12c2 100644 --- a/twisted/protocols/socks.py +++ b/twisted/protocols/socks.py @@ -95,7 +95,7 @@ def dataReceived(self, data): """ Called whenever data is received. - @type data: C{str} + @type data: L{bytes} @param data: Part or all of a SOCKSv4 packet. """ if self.otherConn: From 5229d18d281eb1f7c0dde4bcfaeee6ab1b766537 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 07:03:26 -0700 Subject: [PATCH 10/17] Use byte strings --- twisted/protocols/socks.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/twisted/protocols/socks.py b/twisted/protocols/socks.py index 227364c12c2..81681bd36b5 100644 --- a/twisted/protocols/socks.py +++ b/twisted/protocols/socks.py @@ -87,7 +87,7 @@ def __init__(self, logging=None, reactor=reactor): def connectionMade(self): - self.buf = "" + self.buf = b"" self.otherConn = None @@ -103,19 +103,19 @@ def dataReceived(self, data): return self.buf = self.buf + data completeBuffer = self.buf - if "\000" in self.buf[8:]: + if b"\000" in self.buf[8:]: head, self.buf = self.buf[:8], self.buf[8:] version, code, port = struct.unpack("!BBH", head[:4]) - user, self.buf = self.buf.split("\000", 1) - if head[4:7] == "\000\000\000" and head[7] != "\000": + user, self.buf = self.buf.split(b"\000", 1) + if head[4:7] == b"\000\000\000" and head[7] != b"\000": # An IP address of the form 0.0.0.X, where X is non-zero, # signifies that this is a SOCKSv4a packet. # If the complete packet hasn't been received, restore the # buffer and wait for it. - if "\000" not in self.buf: + if b"\000" not in self.buf: self.buf = completeBuffer return - server, self.buf = self.buf.split("\000", 1) + server, self.buf = self.buf.split(b"\000", 1) d = self.reactor.resolve(server) d.addCallback(self._dataReceived2, user, version, code, port) @@ -163,7 +163,7 @@ def _dataReceived2(self, server, user, version, code, port): self = self: self.makeReply(90, 0, x[1], x[0])) else: raise RuntimeError("Bad Connect Code: %s" % (code,)) - assert self.buf == "", "hmm, still stuff in buffer... %s" % repr( + assert self.buf == b"", "hmm, still stuff in buffer... %s" % repr( self.buf) From da36a82686cf180bc6ffd3d33efc7ac8abbd648d Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 07:08:50 -0700 Subject: [PATCH 11/17] Add twisted.protocols.socks to list of Python 3 ported modules --- twisted/python/dist3.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/twisted/python/dist3.py b/twisted/python/dist3.py index ac52e89452e..d3e186b2336 100644 --- a/twisted/python/dist3.py +++ b/twisted/python/dist3.py @@ -224,6 +224,7 @@ "twisted.protocols.haproxy.test.test_v2parser", "twisted.protocols.haproxy.test.test_wrapper", "twisted.protocols.haproxy.test.test_parser", + "twisted.protocols.socks", "twisted.protocols.tls", "twisted.python.__init__", "twisted.python._appdirs", @@ -494,6 +495,7 @@ "twisted.test.test_reflect", "twisted.test.test_roots", "twisted.test.test_sob", + "twisted.test.test_socks", "twisted.test.test_ssl", "twisted.test.test_sslverify", "twisted.test.test_stdio", From 2ac0d238d0f04ced91f68d88513e8c6badbf7436 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Sun, 24 Jul 2016 07:11:22 -0700 Subject: [PATCH 12/17] Add topfile --- twisted/topfiles/8665.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 twisted/topfiles/8665.feature diff --git a/twisted/topfiles/8665.feature b/twisted/topfiles/8665.feature new file mode 100644 index 00000000000..ae33200b114 --- /dev/null +++ b/twisted/topfiles/8665.feature @@ -0,0 +1 @@ +twisted.protocols.socks has been ported to Python 3 From a47a4c5c0e9107efcf2cbaf823f577c83d778f61 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Mon, 25 Jul 2016 07:52:07 -0700 Subject: [PATCH 13/17] Use slice notation for getting a single byte out of byte string --- twisted/protocols/socks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twisted/protocols/socks.py b/twisted/protocols/socks.py index 81681bd36b5..a52c09b6697 100644 --- a/twisted/protocols/socks.py +++ b/twisted/protocols/socks.py @@ -107,7 +107,7 @@ def dataReceived(self, data): head, self.buf = self.buf[:8], self.buf[8:] version, code, port = struct.unpack("!BBH", head[:4]) user, self.buf = self.buf.split(b"\000", 1) - if head[4:7] == b"\000\000\000" and head[7] != b"\000": + if head[4:7] == b"\000\000\000" and head[7:8] != b"\000": # An IP address of the form 0.0.0.X, where X is non-zero, # signifies that this is a SOCKSv4a packet. # If the complete packet hasn't been received, restore the From 7784c1736dc00d99e37c77cab057fc8d4ecf77e4 Mon Sep 17 00:00:00 2001 From: achatterjee Date: Wed, 27 Jul 2016 10:48:34 +0000 Subject: [PATCH 14/17] Updated the tests to reflect that hugeWrite fails when using TLSv1_1 protocol. reduced bufferSize in write of TLSMemoryBIOProtocol to fix issue. --- twisted/protocols/test/test_tls.py | 23 ++++++++++++++++------- twisted/protocols/tls.py | 2 +- twisted/test/ssl_helpers.py | 5 +++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/twisted/protocols/test/test_tls.py b/twisted/protocols/test/test_tls.py index b6c95515f8e..d3d43e7c278 100644 --- a/twisted/protocols/test/test_tls.py +++ b/twisted/protocols/test/test_tls.py @@ -21,7 +21,7 @@ # Otherwise, the pyOpenSSL dependency must be satisfied, so all these # imports will work. from OpenSSL.crypto import X509Type - from OpenSSL.SSL import (TLSv1_METHOD, Error, Context, ConnectionType, + from OpenSSL.SSL import (TLSv1_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD, Error, Context, ConnectionType, WantReadError) from twisted.internet.ssl import PrivateCertificate, optionsForClientTLS from twisted.test.ssl_helpers import (ClientTLSContext, ServerTLSContext, @@ -62,8 +62,9 @@ class HandshakeCallbackContextFactory: # https://bugs.launchpad.net/pyopenssl/+bug/372832 SSL_CB_HANDSHAKE_DONE = 0x20 - def __init__(self): + def __init__(self, method=TLSv1_METHOD): self._finished = Deferred() + self._method = method def factoryAndDeferred(cls): @@ -93,7 +94,7 @@ def getContext(self): Create and return an SSL context configured to use L{self._info} as the info callback. """ - context = Context(TLSv1_METHOD) + context = Context(self._method) context.set_info_callback(self._info) return context @@ -704,14 +705,14 @@ def cbConnectionDone(ignored): return connectionDeferred - def test_hugeWrite(self): + def hugeWrite(self, method=TLSv1_METHOD): """ If a very long string is passed to L{TLSMemoryBIOProtocol.write}, any trailing part of it which cannot be send immediately is buffered and sent later. """ bytes = b"some bytes" - factor = 8192 + factor = 2 ** 20 class SimpleSendingProtocol(Protocol): def connectionMade(self): self.transport.write(bytes * factor) @@ -719,7 +720,7 @@ def connectionMade(self): clientFactory = ClientFactory() clientFactory.protocol = SimpleSendingProtocol - clientContextFactory = HandshakeCallbackContextFactory() + clientContextFactory = HandshakeCallbackContextFactory(method=method) wrapperFactory = TLSMemoryBIOFactory( clientContextFactory, True, clientFactory) sslClientProtocol = wrapperFactory.buildProtocol(None) @@ -728,7 +729,7 @@ def connectionMade(self): serverFactory = ServerFactory() serverFactory.protocol = lambda: serverProtocol - serverContextFactory = ServerTLSContext() + serverContextFactory = ServerTLSContext(method=method) wrapperFactory = TLSMemoryBIOFactory( serverContextFactory, False, serverFactory) sslServerProtocol = wrapperFactory.buildProtocol(None) @@ -742,6 +743,14 @@ def cbConnectionDone(ignored): connectionDeferred.addCallback(cbConnectionDone) return connectionDeferred + def test_hugeWrite_TLSv1(self): + return self.hugeWrite() + + def test_hugeWrite_TLSv1_1(self): + return self.hugeWrite(method=TLSv1_1_METHOD) + + def test_hugeWrite_TLSv1_(self): + return self.hugeWrite(method=TLSv1_2_METHOD) def test_disorderlyShutdown(self): """ diff --git a/twisted/protocols/tls.py b/twisted/protocols/tls.py index 423b5fe0b2c..0bb9fdf6b3e 100644 --- a/twisted/protocols/tls.py +++ b/twisted/protocols/tls.py @@ -614,7 +614,7 @@ def _write(self, bytes): return # A TLS payload is 16kB max - bufferSize = 2 ** 16 + bufferSize = 2 ** 14 # How far into the input we've gotten so far alreadySent = 0 diff --git a/twisted/test/ssl_helpers.py b/twisted/test/ssl_helpers.py index 04a55d7b888..fdf27152fde 100644 --- a/twisted/test/ssl_helpers.py +++ b/twisted/test/ssl_helpers.py @@ -27,11 +27,12 @@ def getContext(self): class ServerTLSContext: isClient = 0 - def __init__(self, filename=certPath): + def __init__(self, filename=certPath, method=SSL.TLSv1_METHOD): self.filename = filename + self._method = method def getContext(self): - ctx = SSL.Context(SSL.TLSv1_METHOD) + ctx = SSL.Context(self._method) ctx.use_certificate_file(self.filename) ctx.use_privatekey_file(self.filename) return ctx From 2913beaca32d34175eb64b7cbd3bd887adc7e528 Mon Sep 17 00:00:00 2001 From: achatterjee Date: Wed, 27 Jul 2016 13:46:31 +0000 Subject: [PATCH 15/17] renamed hugeWrite test for TLSv1_2 appropriately --- twisted/protocols/test/test_tls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twisted/protocols/test/test_tls.py b/twisted/protocols/test/test_tls.py index d3d43e7c278..29463743ea5 100644 --- a/twisted/protocols/test/test_tls.py +++ b/twisted/protocols/test/test_tls.py @@ -749,7 +749,7 @@ def test_hugeWrite_TLSv1(self): def test_hugeWrite_TLSv1_1(self): return self.hugeWrite(method=TLSv1_1_METHOD) - def test_hugeWrite_TLSv1_(self): + def test_hugeWrite_TLSv1_2(self): return self.hugeWrite(method=TLSv1_2_METHOD) def test_disorderlyShutdown(self): From 33cfc57df874ca6e92aa807a55a5eb79994ebfa4 Mon Sep 17 00:00:00 2001 From: achatterjee Date: Thu, 28 Jul 2016 08:37:30 +0000 Subject: [PATCH 16/17] added release note fragment. --- twisted/topfiles/8693.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 twisted/topfiles/8693.bugfix diff --git a/twisted/topfiles/8693.bugfix b/twisted/topfiles/8693.bugfix new file mode 100644 index 00000000000..7b7347676db --- /dev/null +++ b/twisted/topfiles/8693.bugfix @@ -0,0 +1 @@ +Reduced buffersize for writing of a string to 2^14 bytes so as to avoid exceeding the maximum TLS payload. From 0a43470c74c25f4c053c502124c6e42b0d6f69d7 Mon Sep 17 00:00:00 2001 From: achatterjee Date: Thu, 28 Jul 2016 08:44:32 +0000 Subject: [PATCH 17/17] added file details --- twisted/topfiles/8693.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twisted/topfiles/8693.bugfix b/twisted/topfiles/8693.bugfix index 7b7347676db..7db368722c5 100644 --- a/twisted/topfiles/8693.bugfix +++ b/twisted/topfiles/8693.bugfix @@ -1 +1 @@ -Reduced buffersize for writing of a string to 2^14 bytes so as to avoid exceeding the maximum TLS payload. +Reduced buffersize to 2^14 bytes in _write method of twisted.protocols.tls so as to avoid exceeding the maximum TLS payload.