def receivedDownstream(self, data): """ Got data from downstream. We need to de-obfuscate them and proxy them upstream. """ log_prefix = "obfs2 receivedDownstream" # used in logs if self.state == ST_WAIT_FOR_KEY: log.debug("%s: Waiting for key." % log_prefix) if len(data) < SEED_LENGTH + 8: log.debug("%s: Not enough bytes for key (%d)." % (log_prefix, len(data))) return data # incomplete if self.we_are_initiator: self.responder_seed = data.read(SEED_LENGTH) else: self.initiator_seed = data.read(SEED_LENGTH) # Now that we got the other seed, let's set up our crypto. self.send_crypto = self._derive_crypto(self.send_keytype) self.recv_crypto = self._derive_crypto(self.recv_keytype) self.recv_padding_crypto = \ self._derive_padding_crypto(self.responder_seed if self.we_are_initiator else self.initiator_seed, self.recv_pad_keytype) # XXX maybe faster with a single d() instead of two. magic = srlz.ntohl(self.recv_padding_crypto.crypt(data.read(4))) padding_length = srlz.ntohl(self.recv_padding_crypto.crypt(data.read(4))) log.debug("%s: Got %d bytes of handshake data (padding_length: %d, magic: %s)" % \ (log_prefix, len(data), padding_length, hex(magic))) if magic != MAGIC_VALUE: raise base.PluggableTransportError("obfs2: Corrupted magic value '%s'" % hex(magic)) if padding_length > MAX_PADDING: raise base.PluggableTransportError("obfs2: Too big padding length '%s'" % padding_length) self.padding_left_to_read = padding_length self.state = ST_WAIT_FOR_PADDING while self.padding_left_to_read: if not data: return n_to_drain = self.padding_left_to_read if (self.padding_left_to_read > len(data)): n_to_drain = len(data) data.drain(n_to_drain) self.padding_left_to_read -= n_to_drain log.debug("%s: Consumed %d bytes of padding, %d still to come (%d).", log_prefix, n_to_drain, self.padding_left_to_read, len(data)) self.state = ST_OPEN log.debug("%s: Processing %d bytes of application data.", log_prefix, len(data)) if self.pending_data_to_send: log.debug("%s: We got pending data to send and our crypto is ready. Pushing!" % log_prefix) self.receivedUpstream(self.circuit.upstream.buffer) # XXX touching guts of network.py self.pending_data_to_send = False self.circuit.upstream.write(self.recv_crypto.crypt(data.read()))