Skip to content

Commit

Permalink
v0.8.2
Browse files Browse the repository at this point in the history
  • Loading branch information
zyxkad committed Feb 7, 2025
1 parent e3ff9c0 commit 2f7a525
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
9 changes: 7 additions & 2 deletions loginproxy/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def recv_varint2(c) -> tuple[int, int]:
if n & 0x80 == 0:
break
i += 7
if i >= 32:
if i > 35:
raise DecodeError('VarInt too big', '32-bit', str(i) + '-bit')
return num, leng

Expand Down Expand Up @@ -126,6 +126,10 @@ def id(self) -> int:
def remain(self) -> int:
return len(self._data) - self._reader.seek(0, io.SEEK_CUR)

@property
def remain_data(self) -> bytes:
return self._data[self._reader.seek(0, io.SEEK_CUR):]

def reset(self) -> None:
self._reader.seek(self._read_id, io.SEEK_SET)

Expand Down Expand Up @@ -190,7 +194,8 @@ def read_varint(self) -> int:
if bt & 0x80 == 0:
break
i += 7
if i > 32:
if i > 35:
print(self.data)
raise DecodeError('VarInt too big', '32-bit', str(i) + '-bit')
return n

Expand Down
2 changes: 1 addition & 1 deletion loginproxy/mojang.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def get_has_joined(username: str, serverid: str, ip: str | None = None, retry: i
data = get_has_joined0(username, serverid, ip)
if data is not None:
return data
time.sleep(0.5)
time.sleep(0.2)
return None

def get_has_joined0(username: str, serverid: str, ip: str | None = None) -> dict | None:
Expand Down
41 changes: 29 additions & 12 deletions loginproxy/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
'ProxyServer',
]

DEBUG_PACKET = False

class ConnStatus(int, enum.Enum):
HANDSHAKING = 0
STATUS = 1
Expand Down Expand Up @@ -155,7 +157,8 @@ def _recvpkt(self, conn: IConnection, *, compress_threshold_getter) -> PacketRea
debug(f'Incorrect compressed data: {repr(data)}')
raise
packet = PacketReader(data)
debug(f'Received packet; leng={leng + size}; compressed={compressed}; data_leng={data_leng}; id={packet.id}')
if DEBUG_PACKET:
debug(f'Received packet; leng={leng + size}; compressed={compressed}; data_leng={data_leng}; id={packet.id}')
return packet

def recv_client(self) -> PacketReader:
Expand All @@ -179,7 +182,8 @@ def _sendpkt(self, conn: IConnection, data: bytes, *, lock: threading.Lock, comp
data = zlib.compress(data)
data = encode_varint(data_leng) + data
with lock:
debug(f'Sending packet; leng={len(data)}; compressed={compress_threshold >= 0}; data_leng={data_leng}; id={did}; side={side}')
if DEBUG_PACKET:
debug(f'Sending packet; leng={len(data)}; compressed={compress_threshold >= 0}; data_leng={data_leng}; id={did}; side={side}')
conn.sendall(encode_varint(len(data)) + data)

def send_client(self, data: bytes, pid: int | None = None):
Expand Down Expand Up @@ -265,7 +269,17 @@ def register_packet(self, packet_name: str, callback: Callable[[PacketEvent], No
if slient_fail:
return False
raise ValueError(f'{repr(packet_name)} does not exists in protocol {idset.version} (include {self.protocol})')
self.register(packet_id, callback, priority)
if idset.is_c2s[packet_name]:
@functools.wraps(callback)
def cb(event: PacketEvent):
if event.is_client:
callback(event)
else:
@functools.wraps(callback)
def cb(event: PacketEvent):
if event.is_server:
callback(event)
self.register(packet_id, cb, priority)
return True

class ProxyServer:
Expand Down Expand Up @@ -760,7 +774,6 @@ def calc_server_hash(self, sid: str, secret: bytes) -> str:
assert self._enabled_packet_proxy
h = hashlib.sha1()
h.update(sid.encode('utf8'))
print('secret:', secret)
h.update(secret)
h.update(self._private_key.publickey().export_key('DER'))
d = int(h.hexdigest(), base=16) - (1 << 160)
Expand Down Expand Up @@ -835,6 +848,12 @@ def handle_login_packet_c2s(c: Conn, event: PacketEvent, event_dispatcher):
encrypted_verify_token = reader.read_bytearray()
secret = c.server._cipher.decrypt(encrypted_secret, None)
assert secret is not None

debug(f'encrypted client {repr(secret)}')
encryptor = Encryptor(secret)
assert not isinstance(c._wrapped_conn_client, EncryptedConn)
c._wrapped_conn_client = EncryptedConn(c._wrapped_conn_client, encryptor)

if encrypted_verify_token is not None:
# TODO: salt-signature verify version
verify_token = c.server._cipher.decrypt(encrypted_verify_token, None)
Expand All @@ -854,10 +873,6 @@ def handle_login_packet_c2s(c: Conn, event: PacketEvent, event_dispatcher):
c._custom_data['name'] = data['name']
if 'properties' in data:
c._custom_data['properties'] = data['properties']
debug(f'encrypted client {repr(secret)}')
encryptor = Encryptor(secret)
assert not isinstance(c._wrapped_conn_client, EncryptedConn)
c._wrapped_conn_client = EncryptedConn(c._wrapped_conn_client, encryptor)
buf = PacketBuffer()
buf.write_varint(0x02)
buf.write_uuid(c._custom_data['uuid'])
Expand All @@ -874,6 +889,8 @@ def handle_login_packet_c2s(c: Conn, event: PacketEvent, event_dispatcher):
buf.write_string(prop['signature'])
c.send_client(buf.data)
c._client_status = ConnStatus.PLAY
if c.server_status == ConnStatus.PLAY:
event_dispatcher(ON_POST_LOGIN, (c, ), on_executor_thread=False)

def handle_login_packet_s2c(c: Conn, event: PacketEvent, event_dispatcher):
reader = event.reader
Expand Down Expand Up @@ -902,11 +919,12 @@ def handle_login_packet_s2c(c: Conn, event: PacketEvent, event_dispatcher):
c.kick('minecraft server enabled authorization, please disable first')
elif reader.id == 0x02: # Login Success
event.cancel()
debug('Login success', c)
debug('Serverside login success', c)
c._server_status = ConnStatus.PLAY
if 'client_verify_token' in c._custom_data:
return
if c.client_status == ConnStatus.PLAY:
event_dispatcher(ON_POST_LOGIN, (c, ), on_executor_thread=False)
if 'client_verify_token' in c._custom_data:
return
if 'uuid' in c._custom_data:
buf = PacketBuffer()
Expand All @@ -927,8 +945,7 @@ def handle_login_packet_s2c(c: Conn, event: PacketEvent, event_dispatcher):
else:
c.send_client(reader.data)
c._client_status = ConnStatus.PLAY
if c.server_status == ConnStatus.PLAY:
event_dispatcher(ON_POST_LOGIN, (c, ), on_executor_thread=False)
event_dispatcher(ON_POST_LOGIN, (c, ), on_executor_thread=False)
elif reader.id == 0x03: # Set compression
event.cancel()
compress_threshold = reader.read_varint()
Expand Down
2 changes: 1 addition & 1 deletion mcdreforged.plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "loginproxy",
"version": "0.8.1",
"version": "0.8.2",
"name": "LoginProxy",
"description": {
"en_us": "A Minecraft login proxy Plugin",
Expand Down

0 comments on commit 2f7a525

Please sign in to comment.