mirror of https://github.com/n1nj4sec/pupy.git
Remove circuit thing for obfs3/scramblesuit. Fix logic
This commit is contained in:
parent
026bd189b0
commit
d6d9a33c83
|
@ -8,30 +8,10 @@ class ReleaseChainedTransport(Exception):
|
|||
class TransportSetupFailed(Exception):
|
||||
__slots__ = ()
|
||||
|
||||
class Circuit(object):
|
||||
""" alias for obfsproxy style syntax"""
|
||||
|
||||
__slots__ = ('downstream', 'upstream', 'stream', 'transport')
|
||||
|
||||
def __init__(self, stream, transport, downstream=None, upstream=None):
|
||||
if stream is None:
|
||||
self.downstream = downstream
|
||||
self.upstream = upstream
|
||||
self.stream = None
|
||||
else:
|
||||
self.downstream = stream.downstream
|
||||
self.upstream = stream.upstream
|
||||
self.stream = stream
|
||||
self.transport = transport
|
||||
|
||||
def close(self):
|
||||
self.transport.on_close()
|
||||
self.stream.close()
|
||||
|
||||
class BasePupyTransport(object):
|
||||
__slots__ = (
|
||||
'downstream', 'upstream', 'stream',
|
||||
'cookie', 'closed', 'circuit'
|
||||
'cookie', 'closed'
|
||||
)
|
||||
|
||||
def __init__(self, stream, **kwargs):
|
||||
|
@ -47,12 +27,6 @@ class BasePupyTransport(object):
|
|||
self.upstream = stream.upstream
|
||||
self.stream = stream
|
||||
|
||||
self.circuit = Circuit(
|
||||
self.stream,
|
||||
self,
|
||||
downstream = self.downstream,
|
||||
upstream = self.upstream)
|
||||
|
||||
self.cookie = None
|
||||
self.closed = False
|
||||
|
||||
|
@ -60,7 +34,7 @@ class BasePupyTransport(object):
|
|||
def customize(cls, **kwargs):
|
||||
""" return a class with some existing attributes customized """
|
||||
for name, value in kwargs.iteritems():
|
||||
if name in ["cookie", "circuit", "upstream", "downstream", "stream"]:
|
||||
if name in ["cookie", "upstream", "downstream", "stream"]:
|
||||
raise TransportError("you cannot customize the protected attribute %s"%name)
|
||||
if not hasattr(cls, name):
|
||||
raise TransportError("Transport has no attribute %s"%name)
|
||||
|
|
|
@ -15,6 +15,7 @@ from ...base import BaseTransport
|
|||
from ..obfscommon import hmac_sha256
|
||||
from ..obfscommon import rand
|
||||
|
||||
from network.lib.buffer import Buffer
|
||||
from network.lib import getLogger
|
||||
logger = getLogger('obfs3')
|
||||
|
||||
|
@ -27,7 +28,7 @@ HASHLEN = 32 # length of output of sha256
|
|||
ST_WAIT_FOR_KEY = 0 # Waiting for public key from the other party
|
||||
ST_WAIT_FOR_HANDSHAKE = 1 # Waiting for the DH handshake
|
||||
ST_SEARCHING_MAGIC = 2 # Waiting for magic strings from the other party
|
||||
ST_OPEN = 3 # obfs3 handshake is complete. Sending application data.
|
||||
ST_OPEN = 3 # Sending application data.
|
||||
|
||||
class Obfs3Transport(BaseTransport):
|
||||
"""
|
||||
|
@ -70,7 +71,7 @@ class Obfs3Transport(BaseTransport):
|
|||
|
||||
# Buffer for the first data, Tor is trying to send but can't right now
|
||||
# because we have to handle the DH handshake first.
|
||||
self.queued_data = ''
|
||||
self.queued_data = Buffer()
|
||||
|
||||
# Attributes below are filled by classes that inherit Obfs3Transport.
|
||||
self.send_keytype = None
|
||||
|
@ -96,26 +97,33 @@ class Obfs3Transport(BaseTransport):
|
|||
"initiator" if self.we_are_initiator else "responder",
|
||||
len(handshake_message), padding_length, repr(public_key))
|
||||
|
||||
self.circuit.downstream.write(handshake_message)
|
||||
self.downstream.write(handshake_message)
|
||||
|
||||
def receivedUpstream(self, data):
|
||||
"""
|
||||
Got data from upstream. We need to obfuscated and proxy them downstream.
|
||||
"""
|
||||
if not self.send_crypto:
|
||||
if __debug__:
|
||||
logger.debug("Got upstream data before doing handshake. Caching.")
|
||||
|
||||
self.queued_data += data.read()
|
||||
if self.state != ST_OPEN:
|
||||
if __debug__:
|
||||
logger.debug(
|
||||
"Got upstream data before doing handshake [STATE=%d]. Caching.",
|
||||
self.state)
|
||||
|
||||
data.write_to(self.queued_data)
|
||||
return
|
||||
|
||||
message = self.send_crypto.crypt(data.read())
|
||||
|
||||
if __debug__:
|
||||
logger.debug("obfs3 receivedUpstream: Transmitting %d bytes.", len(message))
|
||||
logger.debug("obfs3 receivedUpstream: Transmitting %d bytes.", len(data))
|
||||
|
||||
if self.queued_data:
|
||||
if __debug__:
|
||||
logger.debug("Flush %d bytes of queued data (???) ", len(self.queued_data))
|
||||
|
||||
self.queued_data.write_to(self.downstream, modificator=self.send_crypto.crypt)
|
||||
|
||||
# Proxy encrypted message.
|
||||
self.circuit.downstream.write(message)
|
||||
data.write_to(self.downstream, modificator=self.send_crypto.crypt)
|
||||
|
||||
def receivedDownstream(self, data):
|
||||
"""
|
||||
|
@ -139,17 +147,21 @@ class Obfs3Transport(BaseTransport):
|
|||
if __debug__:
|
||||
logger.debug("Search magic")
|
||||
|
||||
self._scan_for_magic(data)
|
||||
if self._scan_for_magic(data) and self.queued_data:
|
||||
if __debug__:
|
||||
logger.debug('Flush queued data: %d', len(self.queued_data))
|
||||
|
||||
self.queued_data.write_to(self.downstream, modificator=self.send_crypto.crypt)
|
||||
|
||||
if self.state == ST_OPEN: # Handshake is done. Just decrypt and read application data.
|
||||
if __debug__:
|
||||
logger.debug("obfs3 receivedDownstream: Processing %d bytes of application data." %
|
||||
(len(data)))
|
||||
(len(data)))
|
||||
|
||||
if len(data) == 0:
|
||||
if not data:
|
||||
return
|
||||
|
||||
self.circuit.upstream.write(self.recv_crypto.crypt(data.read()))
|
||||
data.write_to(self.upstream, modificator=self.recv_crypto.crypt)
|
||||
|
||||
def _read_handshake(self, data):
|
||||
"""
|
||||
|
@ -187,11 +199,12 @@ class Obfs3Transport(BaseTransport):
|
|||
call it from a defered so that it does not block the main event loop.
|
||||
"""
|
||||
|
||||
self.circuit.close()
|
||||
#e = failure.trap(ValueError)
|
||||
if __debug__:
|
||||
logger.warning("obfs3: Corrupted public key '%s'" % repr(other_pubkey))
|
||||
|
||||
raise EOFError('Corrupted public key ({})'.format(failure))
|
||||
|
||||
def _read_handshake_post_dh(self, shared_secret, data):
|
||||
"""
|
||||
Setup the crypto from the calculated shared secret, and complete the
|
||||
|
@ -206,10 +219,10 @@ class Obfs3Transport(BaseTransport):
|
|||
# Set up our crypto.
|
||||
self.send_crypto = self._derive_crypto(self.send_keytype)
|
||||
self.recv_crypto = self._derive_crypto(self.recv_keytype)
|
||||
self.other_magic_value = hmac_sha256.hmac_sha256_digest(self.shared_secret,
|
||||
self.recv_magic_const)
|
||||
self.other_magic_value = hmac_sha256.hmac_sha256_digest(
|
||||
self.shared_secret, self.recv_magic_const)
|
||||
|
||||
# Send our magic value to the remote end and append the queued outgoing data.
|
||||
# Send our magic value to the remote end
|
||||
# Padding is prepended so that the server does not just send the 32-byte magic
|
||||
# in a single TCP segment.
|
||||
padding_length = random.randint(0, MAX_PADDING/2)
|
||||
|
@ -217,18 +230,10 @@ class Obfs3Transport(BaseTransport):
|
|||
logger.debug('Padding length: %d', padding_length)
|
||||
|
||||
magic = hmac_sha256.hmac_sha256_digest(self.shared_secret, self.send_magic_const)
|
||||
message = rand.random_bytes(padding_length) + magic + self.send_crypto.crypt(self.queued_data)
|
||||
self.queued_data = ''
|
||||
message = rand.random_bytes(padding_length) + magic
|
||||
|
||||
self.state = ST_SEARCHING_MAGIC
|
||||
|
||||
if __debug__:
|
||||
logger.debug('Scan for magic data / remain data: %d', len(data))
|
||||
|
||||
if len(data) > 0:
|
||||
self._scan_for_magic(data)
|
||||
|
||||
self.circuit.downstream.write(message)
|
||||
self.downstream.write(message)
|
||||
|
||||
def _scan_for_magic(self, data):
|
||||
"""
|
||||
|
@ -237,7 +242,7 @@ class Obfs3Transport(BaseTransport):
|
|||
"""
|
||||
|
||||
assert(self.other_magic_value)
|
||||
chunk = data.peek()
|
||||
chunk = data.peek(MAX_PADDING+HASHLEN)
|
||||
|
||||
index = chunk.find(self.other_magic_value)
|
||||
if index < 0:
|
||||
|
@ -245,8 +250,9 @@ class Obfs3Transport(BaseTransport):
|
|||
logger.debug('Magic not found / chunk len: %d', len(chunk))
|
||||
|
||||
if (len(data) > MAX_PADDING+HASHLEN):
|
||||
raise Exception("obfs3: Too much padding (%d)!" % len(data))
|
||||
return
|
||||
raise EOFError("obfs3: Too much padding (%d)!" % len(data))
|
||||
|
||||
return False
|
||||
|
||||
if __debug__:
|
||||
logger.debug('Magic (len=%d) found at: %d',
|
||||
|
@ -256,11 +262,7 @@ class Obfs3Transport(BaseTransport):
|
|||
data.drain(index)
|
||||
|
||||
self.state = ST_OPEN
|
||||
if len(data) > 0:
|
||||
if __debug__:
|
||||
logger.debug('Connection ready, write rest of data: %d', len(data))
|
||||
|
||||
self.circuit.upstream.write(self.recv_crypto.crypt(data.read()))
|
||||
return True
|
||||
|
||||
def _derive_crypto(self, pad_string):
|
||||
"""
|
||||
|
|
|
@ -220,11 +220,11 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
if self.uniformDHSecret is None:
|
||||
#log.warning("A UniformDH password is not set, most likely " \
|
||||
# "a missing 'password' argument.")
|
||||
self.circuit.close()
|
||||
return
|
||||
|
||||
raise EOFError('A UniformDH password is not set')
|
||||
#log.debug("No session ticket to redeem. Running UniformDH.")
|
||||
|
||||
self.circuit.downstream.write(self.uniformdh.createHandshake())
|
||||
self.downstream.write(self.uniformdh.createHandshake())
|
||||
|
||||
def sendRemote(self, data, flags=const.FLAG_PAYLOAD):
|
||||
"""
|
||||
|
@ -258,7 +258,7 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
padBlurb = self.pktMorpher.getPadding(self.sendCrypter,
|
||||
self.sendHMAC,
|
||||
len(blurb))
|
||||
self.circuit.downstream.write(blurb + padBlurb)
|
||||
self.downstream.write(blurb + padBlurb)
|
||||
|
||||
def flushPieces(self):
|
||||
"""
|
||||
|
@ -274,7 +274,7 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
# Drain and send an MTU-sized chunk from the chopping buffer.
|
||||
if len(self.choppingBuf) > const.MTU:
|
||||
|
||||
self.circuit.downstream.write(self.choppingBuf.read(const.MTU))
|
||||
self.downstream.write(self.choppingBuf.read(const.MTU))
|
||||
|
||||
# Drain and send whatever is left in the output buffer.
|
||||
else:
|
||||
|
@ -282,7 +282,7 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
padBlurb = self.pktMorpher.getPadding(self.sendCrypter,
|
||||
self.sendHMAC,
|
||||
len(blurb))
|
||||
self.circuit.downstream.write(blurb + padBlurb)
|
||||
self.downstream.write(blurb + padBlurb)
|
||||
return
|
||||
|
||||
time.sleep(self.iatMorpher.randomSample())
|
||||
|
@ -309,7 +309,7 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
for msg in msgs:
|
||||
# Forward data to the application.
|
||||
if msg.flags == const.FLAG_PAYLOAD:
|
||||
self.circuit.upstream.write(msg.payload)
|
||||
self.upstream.write(msg.payload)
|
||||
|
||||
# Store newly received ticket.
|
||||
elif self.weAreClient and (msg.flags == const.FLAG_NEW_TICKET):
|
||||
|
@ -478,8 +478,8 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
#log.info("Terminating connection after having received >= %d"
|
||||
# " bytes because client could not "
|
||||
# "authenticate." % self.srvState.closingThreshold)
|
||||
self.circuit.close()
|
||||
return
|
||||
|
||||
raise EOFError('Authentication still was not completed')
|
||||
|
||||
elif self.weAreServer and (self.protoState == const.ST_WAIT_FOR_AUTH):
|
||||
|
||||
|
@ -499,7 +499,7 @@ class ScrambleSuitTransport(base.BaseTransport):
|
|||
#log.debug("Sending %d bytes of UniformDH handshake and "
|
||||
# "session ticket." % len(handshakeMsg))
|
||||
|
||||
self.circuit.downstream.write(handshakeMsg)
|
||||
self.downstream.write(handshakeMsg)
|
||||
#log.debug("UniformDH authentication succeeded.")
|
||||
|
||||
#log.debug("Switching to state ST_CONNECTED.")
|
||||
|
|
Loading…
Reference in New Issue