[Pkg-privacy-commits] [obfsproxy] 77/353: Revive the b64 transport.

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 13:01:42 UTC 2015


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository obfsproxy.

commit ec51fbc409a661f004e920982197b94d49d551a9
Author: George Kadianakis <desnacked at riseup.net>
Date:   Sun Oct 28 20:18:02 2012 +0200

    Revive the b64 transport.
---
 obfsproxy/network/network.py          |  7 +---
 obfsproxy/test/tester.py              | 10 +++++
 obfsproxy/test/transports/b64_test.py | 62 +++++++++++++++++++++++++++
 obfsproxy/transports/b64.py           | 79 +++++++++++++++++++++++------------
 4 files changed, 127 insertions(+), 31 deletions(-)

diff --git a/obfsproxy/network/network.py b/obfsproxy/network/network.py
index 1e41bca..819518f 100644
--- a/obfsproxy/network/network.py
+++ b/obfsproxy/network/network.py
@@ -140,15 +140,15 @@ class Circuit(Protocol):
 
         Requires both downstream and upstream connections to be set.
         """
-        log.debug("%s: Received %d bytes." % (self.name, len(data)))
-
         assert(self.downstream and self.upstream)
         assert((conn is self.downstream) or (conn is self.upstream))
 
         try:
             if conn is self.downstream:
+                log.debug("%s: downstream: Received %d bytes." % (self.name, len(data)))
                 self.transport.receivedDownstream(data, self)
             else:
+                log.debug("%s: upstream: Received %d bytes." % (self.name, len(data)))
                 self.transport.receivedUpstream(data, self)
         except base.PluggableTransportError, err: # Our transport didn't like that data.
             log.info("%s: %s: Closing circuit." % (self.name, str(err)))
@@ -246,9 +246,6 @@ class StaticDestinationProtocol(Protocol):
             log.debug("%s: dataReceived called without a reason.", self.name)
             return
 
-        log.debug("%s: Received %d bytes (and %d cached):\n%s" \
-                  % (self.name, len(data), len(self.buffer), repr(data)))
-
         # Add the received data to the buffer.
         self.buffer.write(data)
 
diff --git a/obfsproxy/test/tester.py b/obfsproxy/test/tester.py
index b2d9ea5..8b67b9c 100644
--- a/obfsproxy/test/tester.py
+++ b/obfsproxy/test/tester.py
@@ -185,6 +185,7 @@ class DirectTest(object):
     def setUp(self):
         self.output_reader = ReadWorker(("127.0.0.1", EXIT_PORT))
         self.obfs_server = Obfsproxy(self.server_args)
+        time.sleep(0.1)
         self.obfs_client = Obfsproxy(self.client_args)
         self.input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
         self.input_chan.settimeout(SOCKET_TIMEOUT)
@@ -237,6 +238,15 @@ class DirectObfs2(DirectTest, unittest.TestCase):
                    "127.0.0.1:%d" % ENTRY_PORT,
                    "--dest=127.0.0.1:%d" % SERVER_PORT)
 
+class DirectB64(DirectTest, unittest.TestCase):
+    transport = "b64"
+    server_args = ("b64", "server",
+                   "127.0.0.1:%d" % SERVER_PORT,
+                   "--dest=127.0.0.1:%d" % EXIT_PORT)
+    client_args = ("b64", "client",
+                   "127.0.0.1:%d" % ENTRY_PORT,
+                   "--dest=127.0.0.1:%d" % SERVER_PORT)
+
 
 TEST_FILE = """\
 THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
diff --git a/obfsproxy/test/transports/b64_test.py b/obfsproxy/test/transports/b64_test.py
new file mode 100644
index 0000000..cb85e69
--- /dev/null
+++ b/obfsproxy/test/transports/b64_test.py
@@ -0,0 +1,62 @@
+import unittest
+
+import obfsproxy.transports.b64 as b64
+
+class test_b64_splitting(unittest.TestCase):
+    def _helper_splitter(self, string, expected_chunks):
+        chunks = b64._get_b64_chunks_from_str(string)
+        self.assertEqual(chunks, expected_chunks)
+
+    def test_1(self):
+        string = "on==the==left==hand==side=="
+        expected = ["on==", "the==", "left==", "hand==", "side=="]
+        self._helper_splitter(string, expected)
+
+    def test_2(self):
+        string = "on=the=left=hand=side="
+        expected = ["on=", "the=", "left=", "hand=", "side="]
+        self._helper_splitter(string, expected)
+
+    def test_3(self):
+        string = "on==the=left==hand=side=="
+        expected = ["on==", "the=", "left==", "hand=", "side=="]
+        self._helper_splitter(string, expected)
+
+    def test_4(self):
+        string = "on==the==left=hand=side"
+        expected = ["on==", "the==", "left=", "hand=", "side"]
+        self._helper_splitter(string, expected)
+
+    def test_5(self):
+        string = "onthelefthandside=="
+        expected = ["onthelefthandside=="]
+        self._helper_splitter(string, expected)
+
+    def test_6(self):
+        string = "onthelefthandside"
+        expected = ["onthelefthandside"]
+        self._helper_splitter(string, expected)
+
+    def test_7(self):
+        string = "onthelefthandside="
+        expected = ["onthelefthandside="]
+        self._helper_splitter(string, expected)
+
+    def test_8(self):
+        string = "side=="
+        expected = ["side=="]
+        self._helper_splitter(string, expected)
+
+    def test_9(self):
+        string = "side="
+        expected = ["side="]
+        self._helper_splitter(string, expected)
+
+    def test_10(self):
+        string = "side"
+        expected = ["side"]
+        self._helper_splitter(string, expected)
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/obfsproxy/transports/b64.py b/obfsproxy/transports/b64.py
index bd7c5d4..9a83b73 100644
--- a/obfsproxy/transports/b64.py
+++ b/obfsproxy/transports/b64.py
@@ -9,51 +9,78 @@ import base64
 
 import obfsproxy.common.log as log
 
-class B64Daemon(BaseDaemon):
+def _get_b64_chunks_from_str(string):
+    """
+    Given a 'string' of concatenated base64 objects, return a list
+    with the objects.
 
+    Assumes that the objects are well-formed base64 strings. Also
+    assumes that the padding character of base64 is '='.
     """
-    B64Daemon is the base class for B64Client and B64Server.
-    Since the protocol is so simple, B64Daemon provides all of the functionality for the b64 protocol implementation.
+    chunks = []
+
+    while True:
+        pad_loc = string.find('=')
+        if pad_loc < 0 or pad_loc == len(string)-1 or pad_loc == len(string)-2:
+            # If there is no padding, or it's the last chunk: append
+            # it to chunks and return.
+            chunks.append(string)
+            return chunks
+
+        if pad_loc != len(string)-1 and string[pad_loc+1] == '=': # double padding
+            pad_loc += 1
+
+        # Append the object to the chunks, and prepare the string for
+        # the next iteration.
+        chunks.append(string[:pad_loc+1])
+        string = string[pad_loc+1:]
+
+    return chunks
+
+class B64Daemon(BaseDaemon):
+    """
+    Implements the b64 protocol. A protocol that encodes data with
+    base64 before pushing them to the network.
     """
 
     def receivedDownstream(self, data, circuit):
-        """ XXX DOCDOC
-        receivedDownstream is the event which is called when bytes are received from the downstream socket.
-        The b64 protocol encodes them with the b64 function and then writes the result to the upstream socket.
         """
+        Got data from downstream; relay them upstream.
+        """
+
+        decoded_data = ''
 
-        log.warning("downstream: Received '''%s'''" % (str(data)))
-        circuit.upstream.write(base64.b64decode(data))
-        return ''
+        # TCP is a stream protocol: the data we received might contain
+        # more than one b64 chunk. We should inspect the data and
+        # split it into multiple chunks.
+        b64_chunks = _get_b64_chunks_from_str(data.peek())
+
+        # Now b64 decode each chunk and append it to the our decoded
+        # data.
+        for chunk in b64_chunks:
+            try:
+                decoded_data += base64.b64decode(chunk)
+            except TypeError:
+                log.info("We got corrupted b64 ('%s')." % chunk)
+                return
+
+        data.drain()
+        circuit.upstream.write(decoded_data)
 
     def receivedUpstream(self, data, circuit):
         """
-        receivedUpstream is the event which is called when bytes are received from the upstream socket.
-        The b64 protocol encodes them with the b64 function and then writes the result to the downstream socket.
+        Got data from upstream; relay them downstream.
         """
 
-        log.warning("upstream: Received '''%s'''" % (str(data)))
-        circuit.downstream.write(base64.b64encode(data))
-        return ''
+        circuit.downstream.write(base64.b64encode(data.read()))
+        return
 
 
 class B64Client(B64Daemon):
-
-    """
-    B64Client is a client for the 'b64' protocol.
-    Since this protocol is so simple, the client and the server are identical and both just trivially subclass B64Daemon.
-    """
-
     pass
 
 
 class B64Server(B64Daemon):
-
-    """
-    B64Server is a server for the 'b64' protocol.
-    Since this protocol is so simple, the client and the server are identical and both just trivially subclass B64Daemon.
-    """
-
     pass
 
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/obfsproxy.git



More information about the Pkg-privacy-commits mailing list