def _serialize_frame(self, opcode, payload=b'', fin=True): rsv = (False, False, False) for extension in reversed(self.extensions): if not extension.enabled(): continue rsv, payload = extension.frame_outbound( self, opcode, rsv, payload, fin) fin_rsv = 0 for bit in rsv: fin_rsv <<= 1 fin_rsv |= int(bit) fin_rsv |= (int(fin) << 3) fin_rsv_opcode = fin_rsv << 4 | opcode payload_length = len(payload) quad_payload = False if payload_length <= MAX_PAYLOAD_NORMAL: first_payload = payload_length second_payload = None elif payload_length <= MAX_PAYLOAD_TWO_BYTE: first_payload = PAYLOAD_LENGTH_TWO_BYTE second_payload = payload_length else: first_payload = PAYLOAD_LENGTH_EIGHT_BYTE second_payload = payload_length quad_payload = True if self.client: first_payload |= 1 << 7 header = bytes([fin_rsv_opcode, first_payload]) if second_payload is not None: if opcode.iscontrol(): raise ValueError("payload too long for control frame") if quad_payload: header += struct.pack('!Q', second_payload) else: header += struct.pack('!H', second_payload) if self.client: # "The masking key is a 32-bit value chosen at random by the # client. When preparing a masked frame, the client MUST pick a # fresh masking key from the set of allowed 32-bit values. The # masking key needs to be unpredictable; thus, the masking key # MUST be derived from a strong source of entropy, and the masking # key for a given frame MUST NOT make it simple for a server/proxy # to predict the masking key for a subsequent frame. The # unpredictability of the masking key is essential to prevent # authors of malicious applications from selecting the bytes that # appear on the wire." # -- https://tools.ietf.org/html/rfc6455#section-5.3 masking_key = os.urandom(4) masker = XorMaskerSimple(masking_key) return header + masking_key + masker.process(payload) else: return header + payload
def _serialize_frame(self, opcode, payload=b'', fin=True): rsv = RsvBits(False, False, False) for extension in reversed(self.extensions): rsv, payload = extension.frame_outbound(self, opcode, rsv, payload, fin) fin_rsv_opcode = self._make_fin_rsv_opcode(fin, rsv, opcode) payload_length = len(payload) quad_payload = False if payload_length <= MAX_PAYLOAD_NORMAL: first_payload = payload_length second_payload = None elif payload_length <= MAX_PAYLOAD_TWO_BYTE: first_payload = PAYLOAD_LENGTH_TWO_BYTE second_payload = payload_length else: first_payload = PAYLOAD_LENGTH_EIGHT_BYTE second_payload = payload_length quad_payload = True if self.client: first_payload |= 1 << 7 header = bytearray([fin_rsv_opcode, first_payload]) if second_payload is not None: if opcode.iscontrol(): raise ValueError("payload too long for control frame") if quad_payload: header += bytearray(struct.pack('!Q', second_payload)) else: header += bytearray(struct.pack('!H', second_payload)) if self.client: # "The masking key is a 32-bit value chosen at random by the # client. When preparing a masked frame, the client MUST pick a # fresh masking key from the set of allowed 32-bit values. The # masking key needs to be unpredictable; thus, the masking key # MUST be derived from a strong source of entropy, and the masking # key for a given frame MUST NOT make it simple for a server/proxy # to predict the masking key for a subsequent frame. The # unpredictability of the masking key is essential to prevent # authors of malicious applications from selecting the bytes that # appear on the wire." # -- https://tools.ietf.org/html/rfc6455#section-5.3 masking_key = os.urandom(4) masker = XorMaskerSimple(masking_key) return header + masking_key + masker.process(payload) return header + payload
def parse_more_gen(self): # Consume as much as we can from self._buffer, yielding events, and # then yield None when we need more data. Or raise ParseFailed. # XX FIXME this should probably be refactored so that we never see # disabled extensions in the first place... self.extensions = [ext for ext in self.extensions if ext.enabled()] unfinished_message_opcode = None unfinished_message_decoder = None effective_opcode = None while effective_opcode is not Opcode.CLOSE: header = yield from self._parse_header() if unfinished_message_opcode is None: if header.opcode is Opcode.CONTINUATION: raise ParseFailed("unexpected CONTINUATION") elif not header.opcode.iscontrol(): # Neither CONTINUATION nor control -> starting a new # unfinished message unfinished_message_opcode = header.opcode elif not header.opcode.iscontrol(): # We're in the middle of an unfinished message if header.opcode is not Opcode.CONTINUATION: raise ParseFailed("expected CONTINUATION, not {!r}" .format(header.opcode)) effective_opcode = header.opcode if effective_opcode is Opcode.CONTINUATION: effective_opcode = unfinished_message_opcode if header.masking_key == NULL_MASK: masker = XorMaskerNull() else: masker = XorMaskerSimple(header.masking_key) if unfinished_message_opcode is Opcode.TEXT and \ unfinished_message_decoder is None: unfinished_message_decoder = getincrementaldecoder("utf-8")() message_finished = yield from self._parse_frame_payload( opcode=effective_opcode, remaining=header.payload_len, message_decoder=unfinished_message_decoder, masker=masker, fin_flag=header.fin ) if message_finished and not effective_opcode.iscontrol(): # This isn't a control, so if this message is finished # then the unfinished message is also finished. unfinished_message_opcode = None unfinished_message_decoder = None
def parse_header(self) -> bool: data = self.buffer.consume_exactly(2) if data is None: self.buffer.rollback() return False fin = bool(data[0] & FIN_MASK) rsv = RsvBits( bool(data[0] & RSV1_MASK), bool(data[0] & RSV2_MASK), bool(data[0] & RSV3_MASK), ) opcode = data[0] & OPCODE_MASK try: opcode = Opcode(opcode) except ValueError: raise ParseFailed("Invalid opcode {:#x}".format(opcode)) if opcode.iscontrol() and not fin: raise ParseFailed("Invalid attempt to fragment control frame") has_mask = bool(data[1] & MASK_MASK) payload_len = data[1] & PAYLOAD_LEN_MASK payload_len = self.parse_extended_payload_length(opcode, payload_len) if payload_len is None: self.buffer.rollback() return False self.extension_processing(opcode, rsv, payload_len) if has_mask and self.client: raise ParseFailed("client received unexpected masked frame") if not has_mask and not self.client: raise ParseFailed("server received unexpected unmasked frame") if has_mask: masking_key = self.buffer.consume_exactly(4) if masking_key is None: self.buffer.rollback() return False self.masker = XorMaskerSimple(masking_key) else: self.masker = XorMaskerNull() self.buffer.commit() self.header = Header(fin, rsv, opcode, payload_len, None) self.effective_opcode = self.header.opcode if self.header.opcode.iscontrol(): self.payload_required = payload_len else: self.payload_required = 0 self.payload_consumed = 0 return True
def _mask(_m, _d): return XorMaskerSimple(_m).process(_d)
def mask2(mask, data): return XorMaskerSimple(mask).process(data)
def _apply_mask(self, mask, data): masker = XorMaskerSimple(mask) return masker.process(data)
def mask(self, data): if self.masking_key: masker = XorMaskerSimple(self.masking_key) return masker.process(data) return data
def test_xormasker(): masker = XorMaskerSimple(b'\xf0\xf0\x0f\x0f') assert b'\xf0\xf0\x0f\x0f\xf0\xf0' == masker.process(b'\x00'*6) assert masker.pointer() == 6 assert b'\x0f\x0f\xf0\xf0\x0f\x0f' == masker.process(b'\x00'*6) assert masker.pointer() == 12
def mask(masking_key, data): return XorMaskerSimple(masking_key).process(data)