예제 #1
0
    def __init__( self ):
        """
        Initialise a ScrambleSuitTransport object.
        """

        log.error("\n\n################################################\n"
                  "Do NOT rely on ScrambleSuit for strong security!\n"
                  "################################################\n")

        log.debug("Initialising %s." % const.TRANSPORT_NAME)

        super(ScrambleSuitTransport, self).__init__()

        # Load the server's persistent state from file.
        if self.weAreServer:
            self.srvState = state.load()

        # Initialise the protocol's state machine.
        log.debug("Switching to state ST_WAIT_FOR_AUTH.")
        self.protoState = const.ST_WAIT_FOR_AUTH

        # Buffer for outgoing data.
        self.sendBuf = ""

        # Buffer for inter-arrival time obfuscation.
        self.choppingBuf = fifobuf.Buffer()

        # AES instances to decrypt incoming and encrypt outgoing data.
        self.sendCrypter = mycrypto.PayloadCrypter()
        self.recvCrypter = mycrypto.PayloadCrypter()

        # Packet morpher to modify the protocol's packet length distribution.
        self.pktMorpher = packetmorpher.new(self.srvState.pktDist
                                            if self.weAreServer else None)

        # Inter-arrival time morpher to obfuscate inter arrival times.
        self.iatMorpher = self.srvState.iatDist if self.weAreServer else \
                          probdist.new(lambda: random.random() %
                                       const.MAX_PACKET_DELAY)

        # Used to extract protocol messages from encrypted data.
        self.protoMsg = message.MessageExtractor()

        # Used by the server-side: `True' if the ticket is already
        # decrypted but not yet authenticated.
        self.decryptedTicket = False

        # If we are in external mode we should already have a shared
        # secret set up because of validate_external_mode_cli().
        if self.weAreExternal:
            assert(self.uniformDHSecret)

        if self.weAreClient and not self.weAreExternal:
            # As a client in managed mode, we get the shared secret
            # from callback `handle_socks_args()' per-connection. Set
            # the shared secret to None for now.
            self.uniformDHSecret = None

        self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
예제 #2
0
    def handle_socks_args(self, args):
        """
        Receive arguments `args' passed over a SOCKS connection.

        The SOCKS authentication mechanism is (ab)used to pass arguments to
        pluggable transports.  This method receives these arguments and parses
        them.  As argument, we only expect a UniformDH shared secret.
        """

        log.debug("Received the following arguments over SOCKS: %s." % args)

        if len(args) != 1:
            raise base.SOCKSArgsError("Too many SOCKS arguments "
                                      "(expected 1 but got %d)." % len(args))

        # The ScrambleSuit specification defines that the shared secret is
        # called "password".
        if not args[0].startswith("password="******"The SOCKS argument must start with "
                                      "`password='******'=')[1].strip()))
        except TypeError as error:
            log.error(error.message)
            raise base.PluggableTransportError("Given password '%s' is not " \
                    "valid Base32!  Run 'generate_password.py' to generate " \
                    "a good password." % args[0].split('=')[1].strip())

        rawLength = len(self.uniformDHSecret)
        if rawLength != const.SHARED_SECRET_LENGTH:
            raise base.PluggableTransportError(
                "The UniformDH password "
                "must be %d bytes in length but %d bytes are given." %
                (const.SHARED_SECRET_LENGTH, rawLength))

        self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
예제 #3
0
    def handle_socks_args(self, args):
        """
        Receive arguments `args' passed over a SOCKS connection.

        The SOCKS authentication mechanism is (ab)used to pass arguments to
        pluggable transports.  This method receives these arguments and parses
        them.  As argument, we only expect a UniformDH shared secret.
        """

        log.debug("Received the following arguments over SOCKS: %s." % args)

        if len(args) != 1:
            raise base.SOCKSArgsError("Too many SOCKS arguments " "(expected 1 but got %d)." % len(args))

        # The ScrambleSuit specification defines that the shared secret is
        # called "password".
        if not args[0].startswith("password="******"The SOCKS argument must start with " "`password='******'%s' is not "
                "valid Base32!  Run 'generate_password.py' to generate "
                "a good password." % args[0].split("=")[1].strip()
            )

        rawLength = len(self.uniformDHSecret)
        if rawLength != const.SHARED_SECRET_LENGTH:
            raise base.PluggableTransportError(
                "The UniformDH password "
                "must be %d bytes in length but %d bytes are given." % (const.SHARED_SECRET_LENGTH, rawLength)
            )

        self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
예제 #4
0
    def test4_extractPublicKey( self ):

        # Create UniformDH authentication message.
        sharedSecret = "A" * const.SHARED_SECRET_LENGTH

        realEpoch = util.getEpoch

        # Try three valid and one invalid epoch value.
        for epoch in util.expandedEpoch() + ["000000"]:
            udh = uniformdh.new(sharedSecret, True)

            util.getEpoch = lambda: epoch
            authMsg = udh.createHandshake()
            util.getEpoch = realEpoch

            buf = obfs_buf.Buffer()
            buf.write(authMsg)

            if epoch == "000000":
                self.assertFalse(udh.extractPublicKey(buf))
            else:
                self.assertTrue(udh.extractPublicKey(buf))
예제 #5
0
 def setUp( self ):
     weAreServer = True
     self.udh = uniformdh.new("A" * const.SHARED_SECRET_LENGTH, weAreServer)
예제 #6
0
    def __init__( self, transportConfig ):
        """
        Initialise a ScrambleSuitTransport object.
        """

        log.error("\n\n################################################\n"
                  "Do NOT rely on ScrambleSuit for strong security!\n"
                  "################################################\n")

        log.debug("Initialising %s." % const.TRANSPORT_NAME)

        util.setStateLocation(transportConfig.getStateLocation())

        # Load the server's persistent state from file.
        if self.weAreServer:
            self.srvState = state.load()

        # Initialise the protocol's state machine.
        log.debug("Switching to state ST_WAIT_FOR_AUTH.")
        self.protoState = const.ST_WAIT_FOR_AUTH

        # Buffers for incoming and outgoing data.
        self.sendBuf = self.recvBuf = ""

        # Buffer for inter-arrival time obfuscation.
        self.choppingBuf = ""

        # AES instances to decrypt incoming and encrypt outgoing data.
        self.sendCrypter = mycrypto.PayloadCrypter()
        self.recvCrypter = mycrypto.PayloadCrypter()

        # Packet morpher to modify the protocol's packet length distribution.
        self.pktMorpher = packetmorpher.new(self.srvState.pktDist
                                            if self.weAreServer else None)

        # Inter-arrival time morpher to obfuscate inter arrival times.
        self.iatMorpher = self.srvState.iatDist if self.weAreServer else \
                          probdist.new(lambda: random.random() %
                                       const.MAX_PACKET_DELAY)

        if self.weAreServer:
            # `True' if the ticket is already decrypted but not yet
            # authenticated.
            self.decryptedTicket = False

            if not hasattr(self, 'uniformDHSecret'):

                # As the server, we get the shared secret from the constructor.
                cfg  = transportConfig.getServerTransportOptions()
                self.uniformDHSecret = base64.b32decode(cfg["password"])
                self.uniformDHSecret = self.uniformDHSecret.strip()

        else:
            # As the client, we get the shared secret from obfsproxy calling
            # `handle_socks_args()'.
            if not hasattr(self, 'uniformDHSecret'):
                self.uniformDHSecret = None

        self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)

        # Variables used to unpack protocol messages.
        self.totalLen = self.payloadLen = self.flags = None