Minor cleanup.

This commit is contained in:
Steven Smith 2015-08-13 19:34:42 -07:00
parent 08ab590e07
commit 0a2926dada
4 changed files with 51 additions and 75 deletions

View file

@ -1,10 +1,10 @@
package org.spacehq.mc.protocol; package org.spacehq.mc.protocol;
import org.spacehq.mc.auth.data.GameProfile; import org.spacehq.mc.auth.data.GameProfile;
import org.spacehq.mc.auth.service.SessionService; import org.spacehq.mc.auth.exception.request.InvalidCredentialsException;
import org.spacehq.mc.auth.exception.request.RequestException; import org.spacehq.mc.auth.exception.request.RequestException;
import org.spacehq.mc.auth.exception.request.ServiceUnavailableException; import org.spacehq.mc.auth.exception.request.ServiceUnavailableException;
import org.spacehq.mc.auth.exception.request.InvalidCredentialsException; import org.spacehq.mc.auth.service.SessionService;
import org.spacehq.mc.protocol.data.SubProtocol; import org.spacehq.mc.protocol.data.SubProtocol;
import org.spacehq.mc.protocol.data.game.values.HandshakeIntent; import org.spacehq.mc.protocol.data.game.values.HandshakeIntent;
import org.spacehq.mc.protocol.data.status.ServerStatusInfo; import org.spacehq.mc.protocol.data.status.ServerStatusInfo;
@ -28,7 +28,6 @@ import org.spacehq.mc.protocol.packet.status.server.StatusResponsePacket;
import org.spacehq.mc.protocol.util.CryptUtil; import org.spacehq.mc.protocol.util.CryptUtil;
import org.spacehq.packetlib.event.session.ConnectedEvent; import org.spacehq.packetlib.event.session.ConnectedEvent;
import org.spacehq.packetlib.event.session.PacketReceivedEvent; import org.spacehq.packetlib.event.session.PacketReceivedEvent;
import org.spacehq.packetlib.event.session.PacketSentEvent;
import org.spacehq.packetlib.event.session.SessionAdapter; import org.spacehq.packetlib.event.session.SessionAdapter;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
@ -36,16 +35,13 @@ import java.math.BigInteger;
import java.net.Proxy; import java.net.Proxy;
public class ClientListener extends SessionAdapter { public class ClientListener extends SessionAdapter {
private SecretKey key;
@Override @Override
public void packetReceived(PacketReceivedEvent event) { public void packetReceived(PacketReceivedEvent event) {
MinecraftProtocol protocol = (MinecraftProtocol) event.getSession().getPacketProtocol(); MinecraftProtocol protocol = (MinecraftProtocol) event.getSession().getPacketProtocol();
if(protocol.getSubProtocol() == SubProtocol.LOGIN) { if(protocol.getSubProtocol() == SubProtocol.LOGIN) {
if(event.getPacket() instanceof EncryptionRequestPacket) { if(event.getPacket() instanceof EncryptionRequestPacket) {
EncryptionRequestPacket packet = event.getPacket(); EncryptionRequestPacket packet = event.getPacket();
this.key = CryptUtil.generateSharedKey(); SecretKey key = CryptUtil.generateSharedKey();
Proxy proxy = event.getSession().<Proxy>getFlag(MinecraftConstants.AUTH_PROXY_KEY); Proxy proxy = event.getSession().<Proxy>getFlag(MinecraftConstants.AUTH_PROXY_KEY);
if(proxy == null) { if(proxy == null) {
@ -53,7 +49,7 @@ public class ClientListener extends SessionAdapter {
} }
GameProfile profile = event.getSession().getFlag(MinecraftConstants.PROFILE_KEY); GameProfile profile = event.getSession().getFlag(MinecraftConstants.PROFILE_KEY);
String serverHash = new BigInteger(CryptUtil.getServerIdHash(packet.getServerId(), packet.getPublicKey(), this.key)).toString(16); String serverHash = new BigInteger(CryptUtil.getServerIdHash(packet.getServerId(), packet.getPublicKey(), key)).toString(16);
String accessToken = event.getSession().getFlag(MinecraftConstants.ACCESS_TOKEN_KEY); String accessToken = event.getSession().getFlag(MinecraftConstants.ACCESS_TOKEN_KEY);
try { try {
new SessionService(proxy).joinServer(profile, accessToken, serverHash); new SessionService(proxy).joinServer(profile, accessToken, serverHash);
@ -68,7 +64,8 @@ public class ClientListener extends SessionAdapter {
return; return;
} }
event.getSession().send(new EncryptionResponsePacket(this.key, packet.getPublicKey(), packet.getVerifyToken())); event.getSession().send(new EncryptionResponsePacket(key, packet.getPublicKey(), packet.getVerifyToken()));
protocol.enableEncryption(key);
} else if(event.getPacket() instanceof LoginSuccessPacket) { } else if(event.getPacket() instanceof LoginSuccessPacket) {
LoginSuccessPacket packet = event.getPacket(); LoginSuccessPacket packet = event.getPacket();
event.getSession().setFlag(MinecraftConstants.PROFILE_KEY, packet.getProfile()); event.getSession().setFlag(MinecraftConstants.PROFILE_KEY, packet.getProfile());
@ -108,14 +105,6 @@ public class ClientListener extends SessionAdapter {
} }
} }
@Override
public void packetSent(PacketSentEvent event) {
MinecraftProtocol protocol = (MinecraftProtocol) event.getSession().getPacketProtocol();
if(protocol.getSubProtocol() == SubProtocol.LOGIN && event.getPacket() instanceof EncryptionResponsePacket) {
protocol.enableEncryption(this.key);
}
}
@Override @Override
public void connected(ConnectedEvent event) { public void connected(ConnectedEvent event) {
MinecraftProtocol protocol = (MinecraftProtocol) event.getSession().getPacketProtocol(); MinecraftProtocol protocol = (MinecraftProtocol) event.getSession().getPacketProtocol();
@ -132,5 +121,4 @@ public class ClientListener extends SessionAdapter {
event.getSession().send(new StatusQueryPacket()); event.getSession().send(new StatusQueryPacket());
} }
} }
} }

View file

@ -138,7 +138,6 @@ public class MinecraftProtocol extends PacketProtocol {
private GameProfile profile; private GameProfile profile;
private String accessToken = ""; private String accessToken = "";
private ClientListener clientListener;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private MinecraftProtocol() { private MinecraftProtocol() {
@ -153,8 +152,6 @@ public class MinecraftProtocol extends PacketProtocol {
if(subProtocol == SubProtocol.LOGIN) { if(subProtocol == SubProtocol.LOGIN) {
this.profile = new GameProfile((UUID) null, "Player"); this.profile = new GameProfile((UUID) null, "Player");
} }
this.clientListener = new ClientListener();
} }
public MinecraftProtocol(String username) { public MinecraftProtocol(String username) {
@ -190,7 +187,6 @@ public class MinecraftProtocol extends PacketProtocol {
this(SubProtocol.LOGIN); this(SubProtocol.LOGIN);
this.profile = profile; this.profile = profile;
this.accessToken = accessToken; this.accessToken = accessToken;
} }
public GameProfile getProfile() { public GameProfile getProfile() {
@ -224,7 +220,7 @@ public class MinecraftProtocol extends PacketProtocol {
} }
this.setSubProtocol(this.subProtocol, true, session); this.setSubProtocol(this.subProtocol, true, session);
session.addListener(this.clientListener); session.addListener(new ClientListener());
} }
@Override @Override

View file

@ -37,8 +37,7 @@ import java.util.Random;
import java.util.UUID; import java.util.UUID;
public class ServerListener extends SessionAdapter { public class ServerListener extends SessionAdapter {
private static final KeyPair KEY_PAIR = CryptUtil.generateKeyPair();
private static KeyPair pair = CryptUtil.generateKeyPair();
private byte verifyToken[] = new byte[4]; private byte verifyToken[] = new byte[4];
private String serverId = ""; private String serverId = "";
@ -84,34 +83,24 @@ public class ServerListener extends SessionAdapter {
if(protocol.getSubProtocol() == SubProtocol.LOGIN) { if(protocol.getSubProtocol() == SubProtocol.LOGIN) {
if(event.getPacket() instanceof LoginStartPacket) { if(event.getPacket() instanceof LoginStartPacket) {
this.username = event.<LoginStartPacket>getPacket().getUsername(); this.username = event.<LoginStartPacket>getPacket().getUsername();
boolean verify = event.getSession().hasFlag(MinecraftConstants.VERIFY_USERS_KEY) ? event.getSession().<Boolean>getFlag(MinecraftConstants.VERIFY_USERS_KEY) : true; boolean verify = event.getSession().hasFlag(MinecraftConstants.VERIFY_USERS_KEY) ? event.getSession().<Boolean>getFlag(MinecraftConstants.VERIFY_USERS_KEY) : true;
if(verify) { if(verify) {
event.getSession().send(new EncryptionRequestPacket(this.serverId, pair.getPublic(), this.verifyToken)); event.getSession().send(new EncryptionRequestPacket(this.serverId, KEY_PAIR.getPublic(), this.verifyToken));
} else { } else {
GameProfile profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + this.username).getBytes()), this.username); new Thread(new UserAuthTask(event.getSession(), null)).start();
int threshold = event.getSession().getFlag(MinecraftConstants.SERVER_COMPRESSION_THRESHOLD);
event.getSession().send(new LoginSetCompressionPacket(threshold));
event.getSession().setCompressionThreshold(threshold);
event.getSession().send(new LoginSuccessPacket(profile));
event.getSession().setFlag(MinecraftConstants.PROFILE_KEY, profile);
protocol.setSubProtocol(SubProtocol.GAME, false, event.getSession());
ServerLoginHandler handler = event.getSession().getFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY);
if(handler != null) {
handler.loggedIn(event.getSession());
}
new Thread(new KeepAlive(event.getSession())).start();
} }
} else if(event.getPacket() instanceof EncryptionResponsePacket) { } else if(event.getPacket() instanceof EncryptionResponsePacket) {
EncryptionResponsePacket packet = event.getPacket(); EncryptionResponsePacket packet = event.getPacket();
PrivateKey privateKey = pair.getPrivate(); PrivateKey privateKey = KEY_PAIR.getPrivate();
if(!Arrays.equals(this.verifyToken, packet.getVerifyToken(privateKey))) { if(!Arrays.equals(this.verifyToken, packet.getVerifyToken(privateKey))) {
throw new IllegalStateException("Invalid nonce!"); event.getSession().disconnect("Invalid nonce!");
} else { return;
SecretKey key = packet.getSecretKey(privateKey);
protocol.enableEncryption(key);
new UserAuthThread(event.getSession(), key).start();
} }
SecretKey key = packet.getSecretKey(privateKey);
protocol.enableEncryption(key);
new Thread(new UserAuthTask(event.getSession(), key)).start();
} }
} }
@ -151,53 +140,59 @@ public class ServerListener extends SessionAdapter {
} }
} }
private class UserAuthThread extends Thread { private class UserAuthTask implements Runnable {
private Session session; private Session session;
private SecretKey key; private SecretKey key;
public UserAuthThread(Session session, SecretKey key) { public UserAuthTask(Session session, SecretKey key) {
this.key = key; this.key = key;
this.session = session; this.session = session;
} }
@Override @Override
public void run() { public void run() {
Proxy proxy = this.session.<Proxy>getFlag(MinecraftConstants.AUTH_PROXY_KEY); boolean verify = this.session.hasFlag(MinecraftConstants.VERIFY_USERS_KEY) ? this.session.<Boolean>getFlag(MinecraftConstants.VERIFY_USERS_KEY) : true;
if(proxy == null) {
proxy = Proxy.NO_PROXY;
}
GameProfile profile = null; GameProfile profile = null;
try { if(verify && this.key != null) {
profile = new SessionService(proxy).getProfileByServer(username, new BigInteger(CryptUtil.getServerIdHash(serverId, pair.getPublic(), this.key)).toString(16)); Proxy proxy = this.session.<Proxy>getFlag(MinecraftConstants.AUTH_PROXY_KEY);
} catch(RequestException e) { if(proxy == null) {
this.session.disconnect("Failed to make session service request.", e); proxy = Proxy.NO_PROXY;
return;
}
if(profile != null) {
int threshold = this.session.getFlag(MinecraftConstants.SERVER_COMPRESSION_THRESHOLD);
this.session.send(new LoginSetCompressionPacket(threshold));
this.session.setCompressionThreshold(threshold);
this.session.send(new LoginSuccessPacket(profile));
this.session.setFlag(MinecraftConstants.PROFILE_KEY, profile);
((MinecraftProtocol) this.session.getPacketProtocol()).setSubProtocol(SubProtocol.GAME, false, this.session);
ServerLoginHandler handler = this.session.getFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY);
if(handler != null) {
handler.loggedIn(this.session);
} }
new Thread(new KeepAlive(this.session)).start(); try {
profile = new SessionService(proxy).getProfileByServer(username, new BigInteger(CryptUtil.getServerIdHash(serverId, KEY_PAIR.getPublic(), this.key)).toString(16));
} catch(RequestException e) {
this.session.disconnect("Failed to make session service request.", e);
return;
}
if(profile == null) {
this.session.disconnect("Failed to verify username.");
}
} else { } else {
this.session.disconnect("Failed to verify username."); profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes()), username);
} }
int threshold = this.session.getFlag(MinecraftConstants.SERVER_COMPRESSION_THRESHOLD);
this.session.send(new LoginSetCompressionPacket(threshold));
this.session.setCompressionThreshold(threshold);
this.session.send(new LoginSuccessPacket(profile));
this.session.setFlag(MinecraftConstants.PROFILE_KEY, profile);
((MinecraftProtocol) this.session.getPacketProtocol()).setSubProtocol(SubProtocol.GAME, false, this.session);
ServerLoginHandler handler = this.session.getFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY);
if(handler != null) {
handler.loggedIn(this.session);
}
new Thread(new KeepAliveTask(this.session)).start();
} }
} }
private class KeepAlive implements Runnable { private class KeepAliveTask implements Runnable {
private Session session; private Session session;
public KeepAlive(Session session) { public KeepAliveTask(Session session) {
this.session = session; this.session = session;
} }
@ -216,5 +211,4 @@ public class ServerListener extends SessionAdapter {
} }
} }
} }
} }

View file

@ -3,7 +3,5 @@ package org.spacehq.mc.protocol;
import org.spacehq.packetlib.Session; import org.spacehq.packetlib.Session;
public interface ServerLoginHandler { public interface ServerLoginHandler {
public void loggedIn(Session session); public void loggedIn(Session session);
} }