Esempio n. 1
0
def client(auth, target_addr):
    parser = yield from iofree.get_parser()
    parser.respond(data=socks5.Handshake(
        ..., [socks5.AuthMethod.no_auth, socks5.AuthMethod.user_auth]).binary)
    server_selection = yield from socks5.ServerSelection.get_value()
    if server_selection.method not in (
            socks5.AuthMethod.no_auth,
            socks5.AuthMethod.user_auth,
    ):
        parser.respond(close=True, exc=ProtocolError("no method to choose"))
    if auth and (server_selection.method is socks5.AuthMethod.user_auth):
        parser.respond(data=socks5.UsernameAuth(..., auth[0].decode(),
                                                auth[1].decode()).binary)
        yield from socks5.UsernameAuthReply.get_value()
    parser.respond(
        data=socks5.ClientRequest(..., socks5.Cmd.connect, ...,
                                  socks5.Addr.from_tuple(target_addr)).binary)
    reply = yield from socks5.Reply.get_value()
    if reply.rep is not socks5.Rep.succeeded:
        parser.respond(close=True, exc=ProtocolError(f"bad reply: {reply}"))
    parser.respond(result=reply)
Esempio n. 2
0
def socks5_request(auth=False):
    parser = yield from iofree.get_parser()
    ver, nmethods = yield from iofree.read_struct("!BB")
    assert ver == 5, f"bad socks version: {ver}"
    assert nmethods != 0, f"nmethods can't be 0"
    methods = yield from iofree.read(nmethods)
    if auth and b"\x02" not in methods:
        parser.write(b"\x05\x02")
        raise Exception("server needs authentication")
    elif b"\x00" not in methods:
        parser.write(b"\x05\x00")
        raise Exception("method not support")
    if auth:
        parser.write(b"\x05\x02")
        auth_ver, username_length = yield from iofree.read_struct("!BB")
        assert auth_ver == 1, f"invalid auth version {auth_ver}"
        username = yield from iofree.read(username_length)
        password_length = (yield from iofree.read(1))[0]
        password = yield from iofree.read(password_length)
        if (username, password) != auth:
            parser.write(b"\x01\x01")
            raise Exception("authenticate failed")
        else:
            parser.write(b"\x01\x00")
    else:
        parser.write(b"\x05\x00")
    ver, cmd, rsv = yield from iofree.read_struct("!BBB")
    if cmd == 1:  # connect
        pass
    elif cmd == 2:  # bind
        raise Exception("doesn't support bind yet")
    elif cmd == 3:  # associate
        raise Exception("doesn't support associate yes")
    else:
        raise Exception(f"unknown cmd: {cmd}")
    target_addr = yield from read_addr()
    return target_addr, cmd
Esempio n. 3
0
def simple():
    parser = yield from iofree.get_parser()
    yield from iofree.read(1)
    assert parser.has_more_data()
    assert not parser.finished()
    raise Exception("special")
Esempio n. 4
0
def second():
    parser = yield from iofree.get_parser()
    for i in range(10):
        a = yield from schema.Group(x=schema.uint16be, y=schema.uint8)
        parser.respond(result=a)
Esempio n. 5
0
def first():
    parser = yield from iofree.get_parser()
    for i in range(10):
        a = yield from schema.Group(x=schema.uint8, y=schema.uint16be)
        parser.respond(result=a.binary[1:] + a.binary[:1])
    return b""
Esempio n. 6
0
    def _client(self):
        parser = yield from iofree.get_parser()
        parser.respond(data=self.client_hello())
        plain_text = yield from models.TLSPlaintext.get_value()
        assert plain_text.content_type is models.ContentType.handshake
        self.peer_handshake = models.Handshake.parse(plain_text.fragment)
        self.handshake_context.extend(plain_text.fragment)
        print("plaintext handshake:", self.peer_handshake.msg_type)
        server_hello = self.peer_handshake.msg
        peer_pk = server_hello.extensions_dict[
            models.ExtensionType.key_share].key_exchange
        shared_key = crypto_scalarmult(bytes(self.private_key), peer_pk)
        self.TLSCipher = server_hello.get_cipher()
        key_index = server_hello.extensions_dict.get(
            models.ExtensionType.pre_shared_key)
        psk = None if key_index is None else self.psk_list[key_index]
        self.key_scheduler = self.TLSCipher.tls_hash.scheduler(shared_key, psk)
        secret = self.key_scheduler.server_handshake_traffic_secret(
            self.handshake_context)
        # server handshake cipher
        self.peer_cipher = self.TLSCipher(secret)
        self.client_handshake_traffic_secret = self.key_scheduler.client_handshake_traffic_secret(
            self.handshake_context)
        plain_text = yield from models.TLSPlaintext.get_value()
        assert plain_text.content_type is models.ContentType.change_cipher_spec
        print("plaintext:", plain_text.content_type)
        server_finished = False
        while not server_finished:
            plain_text = yield from models.TLSPlaintext.get_value()
            assert plain_text.content_type is models.ContentType.application_data
            content = self.peer_cipher.decrypt(plain_text.fragment,
                                               plain_text.binary[:5])
            inner_text = models.TLSInnerPlaintext.parse(content)
            assert inner_text.content_type is models.ContentType.handshake
            handshake = models.Handshake.parse(inner_text.content)
            print("inner_text:", handshake.msg_type)
            if handshake.msg_type is models.HandshakeType.finished:
                assert handshake.msg == self.peer_cipher.verify_data(
                    self.handshake_context
                ), "server handshake finished does not match"
                server_finished = True
            self.handshake_context.extend(inner_text.content)
        # server application cipher
        self.server_secret = self.key_scheduler.server_application_traffic_secret_0(
            self.handshake_context)
        self.peer_cipher = self.TLSCipher(self.server_secret)
        parser.respond(data=self.client_finish(), result=True)
        print("connected")

        while True:
            plain_text = yield from models.TLSPlaintext.get_value()
            if plain_text.is_overflow():
                parser.respond(
                    data=self.pack_fatal(
                        models.AlertDescription.record_overflow),
                    close=True,
                    exc=ProtocolError("text overflow"),
                )
                return
            if plain_text.content_type is models.ContentType.application_data:
                content = self.peer_cipher.decrypt(
                    plain_text.fragment,
                    plain_text.binary[:5])  # .rstrip(b"\x00")
                inner_text = models.TLSInnerPlaintext.parse(content)
                if inner_text.content_type is models.ContentType.handshake:
                    handshake = models.Handshake.parse(inner_text.content)
                    print("inner_text:", handshake.msg_type)
                    if handshake.msg_type is models.HandshakeType.key_update:
                        self.server_secret = self.key_scheduler.application_traffic_secret_N(
                            self.server_secret)
                        self.peer_cipher = self.TLSCipher(self.server_secret)
                    self.handshake_context.extend(inner_text.content)
                elif inner_text.content_type is models.ContentType.application_data:
                    parser.respond(result=inner_text.content)
                else:
                    print(inner_text)
            elif plain_text.content_type is models.ContentType.alert:
                print(models.Alert.parse(plain_text.fragment))
            else:
                print(plain_text.content_type)
Esempio n. 7
0
    def tls_response(self):
        parser = yield from iofree.get_parser()
        while True:
            head = yield from iofree.read(5)
            assert head[
                1:3] == b"\x03\x03", f"bad legacy_record_version {head[1:3]}"
            length = int.from_bytes(head[3:], "big")
            if (head[0] == ContentType.application_data and length >
                (16384 + 256)) or (head[0] != ContentType.application_data
                                   and length > 16384):
                parser.write(self.pack_fatal(AlertDescription.record_overflow))
                raise Alert(AlertLevel.fatal, AlertDescription.record_overflow)
            content = memoryview((yield from iofree.read(length)))
            if head[0] == ContentType.alert:
                level = AlertLevel.from_value(content[0])
                description = AlertDescription.from_value(content[1])
                raise Alert(level, description)
            elif head[0] == ContentType.handshake:
                self.peer_handshake = self.unpack_handshake(content)
                assert (self.peer_handshake.handshake_type ==
                        HandshakeType.server_hello), "expect server hello"
                peer_pk = self.peer_handshake.extensions[
                    ExtensionType.key_share].key_exchange
                shared_key = crypto_scalarmult(bytes(self.private_key),
                                               peer_pk)
                TLSCipher = self.peer_handshake.cipher_suite
                self.TLSCipher = TLSCipher
                key_index = self.peer_handshake.extensions.get(
                    ExtensionType.pre_shared_key)
                psk = None if key_index is None else self.psk_list[key_index]
                key_scheduler = TLSCipher.tls_hash.scheduler(shared_key, psk)
                self.key_scheduler = key_scheduler
                secret = key_scheduler.server_handshake_traffic_secret(
                    self.handshake_context)
                # server handshake cipher
                self.peer_cipher = TLSCipher(secret)
                client_handshake_traffic_secret = key_scheduler.client_handshake_traffic_secret(
                    self.handshake_context)
            elif head[0] == ContentType.application_data:
                plaintext = self.peer_cipher.decrypt(content,
                                                     head).rstrip(b"\x00")
                content_type = ContentType.from_value(plaintext[-1])
                if content_type == ContentType.handshake:
                    self.unpack_handshake(plaintext[:-1])
                    if self.server_finished:
                        if self.early_data:
                            eoe_data = HandshakeType.end_of_early_data.pack_data(
                                b"")
                            # self.handshake_context.extend(eoe_data)
                            inner_plaintext = ContentType.handshake.tls_inner_plaintext(
                                eoe_data)
                            record = self.cipher.tls_ciphertext(
                                inner_plaintext)
                            parser.write(record)

                        # client handshake cipher
                        cipher = TLSCipher(client_handshake_traffic_secret)
                        client_finished = cipher.verify_data(
                            self.handshake_context)
                        client_finished_data = HandshakeType.finished.pack_data(
                            client_finished)
                        inner_plaintext = ContentType.handshake.tls_inner_plaintext(
                            client_finished_data)
                        record = cipher.tls_ciphertext(inner_plaintext)
                        change_cipher_spec = ContentType.change_cipher_spec.tls_plaintext(
                            b"\x01")
                        parser.write(change_cipher_spec + record)
                        # server application cipher
                        server_secret = key_scheduler.server_application_traffic_secret_0(
                            self.handshake_context)
                        self.peer_cipher = TLSCipher(server_secret)
                        self.server_finished = False

                        # client application cipher
                        client_secret = key_scheduler.client_application_traffic_secret_0(
                            self.handshake_context)
                        self.cipher = TLSCipher(client_secret)
                        self.handshake_context.extend(client_finished_data)
                elif content_type == ContentType.application_data:
                    self.data_callback(plaintext[:-1])
                elif content_type == ContentType.alert:
                    level = AlertLevel.from_value(plaintext[0])
                    description = AlertDescription.from_value(plaintext[1])
                    raise Alert(level, description)
                elif content_type == ContentType.invalid:
                    raise Exception("invalid content type")
                else:
                    raise Exception(f"unexpected content type {content_type}")
            elif head[0] == ContentType.change_cipher_spec:
                assert content == b"\x01", "change_cipher should be 0x01"
            else:
                raise Exception(f"Unknown content type: {head[0]}")