mirror of
https://github.com/ViaVersion/ViaProxy.git
synced 2024-11-14 19:15:08 -05:00
Implemented joining with local minecraft accounts
This commit is contained in:
parent
d036d37bd0
commit
8dd9d0032c
13 changed files with 355 additions and 105 deletions
|
@ -21,6 +21,7 @@ import net.raphimc.viaproxy.protocolhack.ProtocolHack;
|
|||
import net.raphimc.viaproxy.proxy.ProxyConnection;
|
||||
import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyChannelInitializer;
|
||||
import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyHandler;
|
||||
import net.raphimc.viaproxy.saves.SaveManager;
|
||||
import net.raphimc.viaproxy.ui.ViaProxyUI;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
||||
|
@ -31,8 +32,10 @@ public class ViaProxy {
|
|||
|
||||
public static final String VERSION = "${version}";
|
||||
|
||||
public static SaveManager saveManager;
|
||||
public static NetServer currentProxyServer;
|
||||
public static Thread loaderThread;
|
||||
public static Thread accountRefreshThread;
|
||||
public static ChannelGroup c2pChannels;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
@ -49,6 +52,7 @@ public class ViaProxy {
|
|||
Logger.setup();
|
||||
ConsoleHandler.hookConsole();
|
||||
Logger.LOGGER.info("Initializing ViaProxy v" + VERSION + "...");
|
||||
saveManager = new SaveManager();
|
||||
VersionEnum.init();
|
||||
setNettyParameters();
|
||||
MCPipeline.useOptimizedPipeline();
|
||||
|
@ -57,12 +61,17 @@ public class ViaProxy {
|
|||
ProtocolHack.init();
|
||||
PluginManager.loadPlugins();
|
||||
}, "ViaProtocolHack-Loader");
|
||||
accountRefreshThread = new Thread(() -> {
|
||||
saveManager.accountsSave.refreshAccounts();
|
||||
}, "AccountRefresh");
|
||||
|
||||
if (args.length == 0 && !GraphicsEnvironment.isHeadless()) {
|
||||
loaderThread.start();
|
||||
accountRefreshThread.start();
|
||||
final ViaProxyUI[] ui = new ViaProxyUI[1];
|
||||
SwingUtilities.invokeLater(() -> ui[0] = new ViaProxyUI());
|
||||
loaderThread.join();
|
||||
accountRefreshThread.join();
|
||||
ui[0].setReady();
|
||||
Logger.LOGGER.info("ViaProxy started successfully!");
|
||||
return;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.raphimc.viaproxy.cli.options;
|
||||
|
||||
import joptsimple.*;
|
||||
import net.raphimc.mcauth.step.java.StepMCProfile;
|
||||
import net.raphimc.vialegacy.util.VersionEnum;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
||||
|
@ -27,6 +28,9 @@ public class Options {
|
|||
public static boolean LOCAL_SOCKET_AUTH;
|
||||
public static boolean BETACRAFT_AUTH;
|
||||
|
||||
// GUI only config options
|
||||
public static StepMCProfile.MCProfile MC_ACCOUNT;
|
||||
|
||||
public static void parse(final String[] args) throws IOException {
|
||||
final OptionParser parser = new OptionParser();
|
||||
final OptionSpec<Void> help = parser.acceptsAll(asList("help", "h", "?"), "Get a list of all arguments").forHelp();
|
||||
|
|
|
@ -2,14 +2,14 @@ package net.raphimc.viaproxy.protocolhack.providers;
|
|||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider;
|
||||
import net.raphimc.viaproxy.proxy.CustomPayloadInterface;
|
||||
import net.raphimc.viaproxy.proxy.ExternalInterface;
|
||||
import net.raphimc.viaproxy.proxy.ProxyConnection;
|
||||
|
||||
public class ViaProxyOldAuthProvider extends OldAuthProvider {
|
||||
|
||||
@Override
|
||||
public void sendAuthRequest(final UserConnection user, final String serverId) throws Throwable {
|
||||
CustomPayloadInterface.joinServer(serverId, ProxyConnection.fromUserConnection(user));
|
||||
ExternalInterface.joinServer(serverId, ProxyConnection.fromUserConnection(user));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
package net.raphimc.viaproxy.proxy;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.raphimc.netminecraft.packet.PacketTypes;
|
||||
import net.raphimc.netminecraft.packet.impl.login.C2SLoginKeyPacket1_19;
|
||||
import net.raphimc.viaproxy.cli.options.Options;
|
||||
import net.raphimc.viaproxy.util.LocalSocketClient;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class CustomPayloadInterface {
|
||||
|
||||
public static final String OPENAUTHMOD_BASE_CHANNEL = "oam:";
|
||||
public static final byte[] OPENAUTHMOD_LEGACY_MAGIC_BYTES = new byte[]{2, 20, 12, 3}; // 1.8 - 1.12.2
|
||||
public static final String OPENAUTHMOD_LEGACY_MAGIC_STRING = new String(OPENAUTHMOD_LEGACY_MAGIC_BYTES, StandardCharsets.UTF_8); // 1.8 - 1.12.2
|
||||
public static final int OPENAUTHMOD_LEGACY_MAGIC_INT = new BigInteger(OPENAUTHMOD_LEGACY_MAGIC_BYTES).intValueExact(); // 1.8 - 1.12.2
|
||||
|
||||
// Request
|
||||
public static final String OPENAUTHMOD_JOIN_CHANNEL = OPENAUTHMOD_BASE_CHANNEL + "join"; // 1.8 - latest
|
||||
public static final String OPENAUTHMOD_SIGN_NONCE_CHANNEL = OPENAUTHMOD_BASE_CHANNEL + "sign_nonce"; // 1.19 - latest
|
||||
|
||||
// Response
|
||||
public static final String OPENAUTHMOD_DATA_CHANNEL = OPENAUTHMOD_BASE_CHANNEL + "data"; // 1.8 - latest
|
||||
|
||||
public static void joinServer(final String serverIdHash, final ProxyConnection proxyConnection) throws InterruptedException, ExecutionException {
|
||||
Logger.u_info("auth", proxyConnection.getC2P().remoteAddress(), proxyConnection.getGameProfile(), "Trying to join online mode server");
|
||||
if (Options.OPENAUTHMOD_AUTH) {
|
||||
try {
|
||||
final ByteBuf response = proxyConnection.sendCustomPayload(OPENAUTHMOD_JOIN_CHANNEL, PacketTypes.writeString(Unpooled.buffer(), serverIdHash)).get(6, TimeUnit.SECONDS);
|
||||
if (response == null) throw new TimeoutException();
|
||||
if (response.isReadable() && !response.readBoolean()) throw new TimeoutException();
|
||||
} catch (TimeoutException e) {
|
||||
proxyConnection.kickClient("§cAuthentication cancelled! You need to install OpenAuthMod in order to join this server.");
|
||||
}
|
||||
} else if (Options.LOCAL_SOCKET_AUTH) {
|
||||
new LocalSocketClient(48941).request("authenticate", serverIdHash);
|
||||
}
|
||||
}
|
||||
|
||||
public static void signNonce(final byte[] nonce, final C2SLoginKeyPacket1_19 packet, final ProxyConnection proxyConnection) throws InterruptedException, ExecutionException {
|
||||
Logger.u_info("auth", proxyConnection.getC2P().remoteAddress(), proxyConnection.getGameProfile(), "Requesting nonce signature");
|
||||
if (Options.OPENAUTHMOD_AUTH) {
|
||||
try {
|
||||
final ByteBuf response = proxyConnection.sendCustomPayload(OPENAUTHMOD_SIGN_NONCE_CHANNEL, PacketTypes.writeByteArray(Unpooled.buffer(), nonce)).get(4, TimeUnit.SECONDS);
|
||||
if (response == null) throw new TimeoutException();
|
||||
if (!response.readBoolean()) throw new TimeoutException();
|
||||
packet.salt = response.readLong();
|
||||
packet.signature = PacketTypes.readByteArray(response);
|
||||
} catch (TimeoutException e) {
|
||||
proxyConnection.kickClient("§cAuthentication cancelled! You need to install OpenAuthMod in order to join this server.");
|
||||
}
|
||||
} else if (Options.LOCAL_SOCKET_AUTH) {
|
||||
final String[] response = new LocalSocketClient(48941).request("sign_nonce", Base64.getEncoder().encodeToString(nonce));
|
||||
if (response != null && response[0].equals("success")) {
|
||||
packet.salt = Long.valueOf(response[1]);
|
||||
packet.signature = Base64.getDecoder().decode(response[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
123
src/main/java/net/raphimc/viaproxy/proxy/ExternalInterface.java
Normal file
123
src/main/java/net/raphimc/viaproxy/proxy/ExternalInterface.java
Normal file
|
@ -0,0 +1,123 @@
|
|||
package net.raphimc.viaproxy.proxy;
|
||||
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.auth.util.UUIDSerializer;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.raphimc.netminecraft.packet.PacketTypes;
|
||||
import net.raphimc.netminecraft.packet.impl.login.*;
|
||||
import net.raphimc.viaproxy.cli.options.Options;
|
||||
import net.raphimc.viaproxy.protocolhack.providers.ViaProxyGameProfileFetcher;
|
||||
import net.raphimc.viaproxy.util.LocalSocketClient;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class ExternalInterface {
|
||||
|
||||
public static final String OPENAUTHMOD_BASE_CHANNEL = "oam:";
|
||||
public static final byte[] OPENAUTHMOD_LEGACY_MAGIC_BYTES = new byte[]{2, 20, 12, 3}; // 1.8 - 1.12.2
|
||||
public static final String OPENAUTHMOD_LEGACY_MAGIC_STRING = new String(OPENAUTHMOD_LEGACY_MAGIC_BYTES, StandardCharsets.UTF_8); // 1.8 - 1.12.2
|
||||
public static final int OPENAUTHMOD_LEGACY_MAGIC_INT = new BigInteger(OPENAUTHMOD_LEGACY_MAGIC_BYTES).intValueExact(); // 1.8 - 1.12.2
|
||||
|
||||
// Request
|
||||
public static final String OPENAUTHMOD_JOIN_CHANNEL = OPENAUTHMOD_BASE_CHANNEL + "join"; // 1.8 - latest
|
||||
public static final String OPENAUTHMOD_SIGN_NONCE_CHANNEL = OPENAUTHMOD_BASE_CHANNEL + "sign_nonce"; // 1.19 - latest
|
||||
|
||||
// Response
|
||||
public static final String OPENAUTHMOD_DATA_CHANNEL = OPENAUTHMOD_BASE_CHANNEL + "data"; // 1.8 - latest
|
||||
|
||||
|
||||
public static void fillPlayerData(final C2SLoginHelloPacket1_7 loginHello, final ProxyConnection proxyConnection) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
proxyConnection.setLoginHelloPacket(loginHello);
|
||||
if (proxyConnection.getLoginHelloPacket() instanceof C2SLoginHelloPacket1_19_3) {
|
||||
proxyConnection.setGameProfile(new GameProfile(((C2SLoginHelloPacket1_19_3) proxyConnection.getLoginHelloPacket()).uuid, proxyConnection.getLoginHelloPacket().name));
|
||||
} else {
|
||||
proxyConnection.setGameProfile(new GameProfile((UUID) null, loginHello.name));
|
||||
}
|
||||
|
||||
if (Options.LOCAL_SOCKET_AUTH) {
|
||||
String[] response = new LocalSocketClient(48941).request("getusername");
|
||||
if (response != null && response[0].equals("success")) {
|
||||
proxyConnection.setGameProfile(new GameProfile((UUID) null, response[1]));
|
||||
}
|
||||
|
||||
response = new LocalSocketClient(48941).request("get_public_key_data");
|
||||
if (response != null && response[0].equals("success")) {
|
||||
final String name = proxyConnection.getGameProfile().getName();
|
||||
final UUID uuid = UUIDSerializer.fromString(response[1].replaceFirst("(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"));
|
||||
final PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(response[2])));
|
||||
final byte[] keySignature = Base64.getDecoder().decode(response[3]);
|
||||
final Instant expiresAt = Instant.ofEpochMilli(Long.parseLong(response[4]));
|
||||
|
||||
proxyConnection.setGameProfile(new GameProfile(uuid, name));
|
||||
proxyConnection.setLoginHelloPacket(new C2SLoginHelloPacket1_19_3(name, expiresAt, publicKey, keySignature, uuid));
|
||||
}
|
||||
} else if (Options.MC_ACCOUNT != null) {
|
||||
proxyConnection.setGameProfile(new GameProfile(Options.MC_ACCOUNT.id(), Options.MC_ACCOUNT.name()));
|
||||
// TODO: Key
|
||||
}
|
||||
|
||||
proxyConnection.getLoginHelloPacket().name = proxyConnection.getGameProfile().getName();
|
||||
if (proxyConnection.getLoginHelloPacket() instanceof C2SLoginHelloPacket1_19_3) {
|
||||
((C2SLoginHelloPacket1_19_3) proxyConnection.getLoginHelloPacket()).uuid = proxyConnection.getGameProfile().getId();
|
||||
}
|
||||
}
|
||||
|
||||
public static void joinServer(final String serverIdHash, final ProxyConnection proxyConnection) throws InterruptedException, ExecutionException {
|
||||
Logger.u_info("auth", proxyConnection.getC2P().remoteAddress(), proxyConnection.getGameProfile(), "Trying to join online mode server");
|
||||
if (Options.OPENAUTHMOD_AUTH) {
|
||||
try {
|
||||
final ByteBuf response = proxyConnection.sendCustomPayload(OPENAUTHMOD_JOIN_CHANNEL, PacketTypes.writeString(Unpooled.buffer(), serverIdHash)).get(6, TimeUnit.SECONDS);
|
||||
if (response == null) throw new TimeoutException();
|
||||
if (response.isReadable() && !response.readBoolean()) throw new TimeoutException();
|
||||
} catch (TimeoutException e) {
|
||||
proxyConnection.kickClient("§cAuthentication cancelled! You need to install OpenAuthMod in order to join this server.");
|
||||
}
|
||||
} else if (Options.LOCAL_SOCKET_AUTH) {
|
||||
new LocalSocketClient(48941).request("authenticate", serverIdHash);
|
||||
} else if (Options.MC_ACCOUNT != null) {
|
||||
try {
|
||||
ViaProxyGameProfileFetcher.sessionService.joinServer(new GameProfile(Options.MC_ACCOUNT.id(), Options.MC_ACCOUNT.name()), Options.MC_ACCOUNT.prevResult().prevResult().access_token(), serverIdHash);
|
||||
} catch (Throwable e) {
|
||||
proxyConnection.kickClient("§cFailed to authenticate with Mojang servers! Please try again later.");
|
||||
}
|
||||
} else {
|
||||
proxyConnection.kickClient("§cThis server is in online mode and requires a valid authentication mode.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void signNonce(final byte[] nonce, final C2SLoginKeyPacket1_19 packet, final ProxyConnection proxyConnection) throws InterruptedException, ExecutionException {
|
||||
Logger.u_info("auth", proxyConnection.getC2P().remoteAddress(), proxyConnection.getGameProfile(), "Requesting nonce signature");
|
||||
if (Options.OPENAUTHMOD_AUTH) {
|
||||
try {
|
||||
final ByteBuf response = proxyConnection.sendCustomPayload(OPENAUTHMOD_SIGN_NONCE_CHANNEL, PacketTypes.writeByteArray(Unpooled.buffer(), nonce)).get(4, TimeUnit.SECONDS);
|
||||
if (response == null) throw new TimeoutException();
|
||||
if (!response.readBoolean()) throw new TimeoutException();
|
||||
packet.salt = response.readLong();
|
||||
packet.signature = PacketTypes.readByteArray(response);
|
||||
} catch (TimeoutException e) {
|
||||
proxyConnection.kickClient("§cAuthentication cancelled! You need to install OpenAuthMod in order to join this server.");
|
||||
}
|
||||
} else if (Options.LOCAL_SOCKET_AUTH) {
|
||||
final String[] response = new LocalSocketClient(48941).request("sign_nonce", Base64.getEncoder().encodeToString(nonce));
|
||||
if (response != null && response[0].equals("success")) {
|
||||
packet.salt = Long.valueOf(response[1]);
|
||||
packet.signature = Base64.getDecoder().decode(response[2]);
|
||||
}
|
||||
} else if (Options.MC_ACCOUNT != null) { // TODO: Key
|
||||
proxyConnection.kickClient("§cJoining servers which requires a signed nonce is not yet supported.");
|
||||
} else {
|
||||
proxyConnection.kickClient("§cThis server is in online mode and requires a valid authentication mode.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -179,7 +179,7 @@ public class ProxyConnection extends NetClient {
|
|||
PacketTypes.writeString(disconnectPacketData, channel);
|
||||
PacketTypes.writeVarInt(disconnectPacketData, id);
|
||||
disconnectPacketData.writeBytes(data);
|
||||
this.c2p.writeAndFlush(new S2CLoginDisconnectPacket(messageToJson("§cYou need to install OpenAuthMod in order to join this server.§k\n" + Base64.getEncoder().encodeToString(ByteBufUtil.getBytes(disconnectPacketData)) + "\n" + CustomPayloadInterface.OPENAUTHMOD_LEGACY_MAGIC_STRING))).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
this.c2p.writeAndFlush(new S2CLoginDisconnectPacket(messageToJson("§cYou need to install OpenAuthMod in order to join this server.§k\n" + Base64.getEncoder().encodeToString(ByteBufUtil.getBytes(disconnectPacketData)) + "\n" + ExternalInterface.OPENAUTHMOD_LEGACY_MAGIC_STRING))).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
}
|
||||
break;
|
||||
case PLAY:
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package net.raphimc.viaproxy.proxy.client2proxy;
|
||||
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.auth.util.UUIDSerializer;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
@ -26,7 +24,6 @@ import net.raphimc.viaproxy.proxy.proxy2server.Proxy2ServerHandler;
|
|||
import net.raphimc.viaproxy.proxy.util.CloseAndReturn;
|
||||
import net.raphimc.viaproxy.proxy.util.ExceptionUtil;
|
||||
import net.raphimc.viaproxy.util.ArrayHelper;
|
||||
import net.raphimc.viaproxy.util.LocalSocketClient;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
@ -34,9 +31,9 @@ import java.math.BigInteger;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> {
|
||||
|
@ -208,31 +205,17 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> {
|
|||
}
|
||||
}
|
||||
|
||||
this.proxyConnection.setLoginHelloPacket(packet);
|
||||
this.proxyConnection.setGameProfile(new GameProfile((UUID) null, packet.name));
|
||||
ExternalInterface.fillPlayerData(packet, this.proxyConnection);
|
||||
|
||||
if (Options.ONLINE_MODE) {
|
||||
this.proxyConnection.getC2P().writeAndFlush(new S2CLoginKeyPacket1_8("", KEY_PAIR.getPublic().getEncoded(), this.verifyToken)).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
} else {
|
||||
if (Options.LOCAL_SOCKET_AUTH) {
|
||||
String[] response = new LocalSocketClient(48941).request("getusername");
|
||||
if (response != null && response[0].equals("success")) {
|
||||
this.proxyConnection.setGameProfile(new GameProfile((UUID) null, response[1]));
|
||||
}
|
||||
response = new LocalSocketClient(48941).request("get_public_key_data");
|
||||
if (response != null && response[0].equals("success")) {
|
||||
final UUID uuid = UUIDSerializer.fromString(response[1].replaceFirst("(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"));
|
||||
final PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(response[2])));
|
||||
packet = new C2SLoginHelloPacket1_19_3(packet.name, Instant.ofEpochMilli(Long.parseLong(response[4])), publicKey, Base64.getDecoder().decode(response[3]), uuid);
|
||||
}
|
||||
}
|
||||
|
||||
this.proxyConnection.getChannel().writeAndFlush(packet).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
this.proxyConnection.getChannel().writeAndFlush(this.proxyConnection.getLoginHelloPacket()).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLoginKey(final C2SLoginKeyPacket1_7 packet) throws GeneralSecurityException, InterruptedException {
|
||||
if (this.proxyConnection.getClientVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2) && new String(packet.encryptedNonce, StandardCharsets.UTF_8).equals(CustomPayloadInterface.OPENAUTHMOD_DATA_CHANNEL)) { // 1.8-1.12.2 OpenAuthMod response handling
|
||||
if (this.proxyConnection.getClientVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2) && new String(packet.encryptedNonce, StandardCharsets.UTF_8).equals(ExternalInterface.OPENAUTHMOD_DATA_CHANNEL)) { // 1.8-1.12.2 OpenAuthMod response handling
|
||||
final ByteBuf byteBuf = Unpooled.wrappedBuffer(packet.encryptedSecretKey);
|
||||
this.proxyConnection.handleCustomPayload(PacketTypes.readVarInt(byteBuf), byteBuf);
|
||||
return;
|
||||
|
@ -283,7 +266,7 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> {
|
|||
|
||||
private boolean handlePlayCustomPayload(final ByteBuf packet) {
|
||||
final String channel = PacketTypes.readString(packet, Short.MAX_VALUE); // channel
|
||||
if (channel.equals(CustomPayloadInterface.OPENAUTHMOD_DATA_CHANNEL)) {
|
||||
if (channel.equals(ExternalInterface.OPENAUTHMOD_DATA_CHANNEL)) {
|
||||
return this.proxyConnection.handleCustomPayload(PacketTypes.readVarInt(packet), packet);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -11,7 +11,7 @@ import net.raphimc.netminecraft.packet.impl.login.*;
|
|||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.ProtocolMetadataStorage;
|
||||
import net.raphimc.vialegacy.util.VersionEnum;
|
||||
import net.raphimc.viaproxy.cli.options.Options;
|
||||
import net.raphimc.viaproxy.proxy.CustomPayloadInterface;
|
||||
import net.raphimc.viaproxy.proxy.ExternalInterface;
|
||||
import net.raphimc.viaproxy.proxy.ProxyConnection;
|
||||
import net.raphimc.viaproxy.proxy.util.ExceptionUtil;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
@ -76,7 +76,7 @@ public class Proxy2ServerHandler extends SimpleChannelInboundHandler<IPacket> {
|
|||
auth = this.proxyConnection.getUserConnection().get(ProtocolMetadataStorage.class).authenticate;
|
||||
}
|
||||
if (auth) {
|
||||
CustomPayloadInterface.joinServer(serverHash, this.proxyConnection);
|
||||
ExternalInterface.joinServer(serverHash, this.proxyConnection);
|
||||
}
|
||||
|
||||
final byte[] encryptedSecretKey = CryptUtil.encryptData(publicKey, secretKey.getEncoded());
|
||||
|
@ -84,7 +84,7 @@ public class Proxy2ServerHandler extends SimpleChannelInboundHandler<IPacket> {
|
|||
|
||||
final C2SLoginKeyPacket1_19_3 loginKey = new C2SLoginKeyPacket1_19_3(encryptedSecretKey, encryptedNonce);
|
||||
if (this.proxyConnection.getLoginHelloPacket() instanceof C2SLoginHelloPacket1_19 && ((C2SLoginHelloPacket1_19) this.proxyConnection.getLoginHelloPacket()).key != null) {
|
||||
CustomPayloadInterface.signNonce(packet.nonce, loginKey, this.proxyConnection);
|
||||
ExternalInterface.signNonce(packet.nonce, loginKey, this.proxyConnection);
|
||||
}
|
||||
this.proxyConnection.getChannel().writeAndFlush(loginKey).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
|
||||
|
|
21
src/main/java/net/raphimc/viaproxy/saves/AbstractSave.java
Normal file
21
src/main/java/net/raphimc/viaproxy/saves/AbstractSave.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package net.raphimc.viaproxy.saves;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
public abstract class AbstractSave {
|
||||
|
||||
private final String name;
|
||||
|
||||
public AbstractSave(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract void load(final JsonElement jsonElement) throws Throwable;
|
||||
|
||||
public abstract JsonElement save() throws Throwable;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
76
src/main/java/net/raphimc/viaproxy/saves/SaveManager.java
Normal file
76
src/main/java/net/raphimc/viaproxy/saves/SaveManager.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
package net.raphimc.viaproxy.saves;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.lenni0451.reflect.stream.RStream;
|
||||
import net.raphimc.viaproxy.saves.impl.AccountsSave;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class SaveManager {
|
||||
|
||||
private static final File SAVE_FILE = new File("saves.json");
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
public final AccountsSave accountsSave = new AccountsSave();
|
||||
|
||||
public SaveManager() {
|
||||
this.load();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
try {
|
||||
if (!SAVE_FILE.exists()) {
|
||||
SAVE_FILE.createNewFile();
|
||||
this.save();
|
||||
}
|
||||
|
||||
final FileReader reader = new FileReader(SAVE_FILE);
|
||||
final JsonObject saveObject = GSON.fromJson(reader, JsonObject.class);
|
||||
reader.close();
|
||||
|
||||
RStream
|
||||
.of(this)
|
||||
.fields()
|
||||
.filter(field -> AbstractSave.class.isAssignableFrom(field.type()))
|
||||
.forEach(field -> {
|
||||
final AbstractSave save = field.get();
|
||||
try {
|
||||
if (saveObject.has(save.getName())) {
|
||||
save.load(saveObject.get(save.getName()));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Logger.LOGGER.error("Failed to load save " + save.getName(), e);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Logger.LOGGER.error("Failed to load saves from file", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
final JsonObject saveObject = new JsonObject();
|
||||
RStream
|
||||
.of(this)
|
||||
.fields()
|
||||
.filter(field -> AbstractSave.class.isAssignableFrom(field.type()))
|
||||
.forEach(field -> {
|
||||
final AbstractSave save = field.get();
|
||||
try {
|
||||
saveObject.add(save.getName(), save.save());
|
||||
} catch (Throwable e) {
|
||||
Logger.LOGGER.error("Failed to save save " + save.getName(), e);
|
||||
}
|
||||
});
|
||||
|
||||
final FileWriter writer = new FileWriter(SAVE_FILE);
|
||||
GSON.toJson(saveObject, writer);
|
||||
writer.close();
|
||||
} catch (Throwable e) {
|
||||
Logger.LOGGER.error("Failed to save saves to file", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package net.raphimc.viaproxy.saves.impl;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import net.raphimc.mcauth.MinecraftAuth;
|
||||
import net.raphimc.mcauth.step.java.StepMCProfile;
|
||||
import net.raphimc.mcauth.util.MicrosoftConstants;
|
||||
import net.raphimc.viaproxy.saves.AbstractSave;
|
||||
import net.raphimc.viaproxy.util.logging.Logger;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AccountsSave extends AbstractSave {
|
||||
|
||||
private List<StepMCProfile.MCProfile> accounts = new ArrayList<>();
|
||||
|
||||
public AccountsSave() {
|
||||
super("accounts");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(JsonElement jsonElement) throws Exception {
|
||||
this.accounts = new ArrayList<>();
|
||||
for (JsonElement element : jsonElement.getAsJsonArray()) {
|
||||
this.accounts.add(MinecraftAuth.Java.Title.MC_PROFILE.fromJson(element.getAsJsonObject()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement save() {
|
||||
final JsonArray array = new JsonArray();
|
||||
for (StepMCProfile.MCProfile account : this.accounts) {
|
||||
array.add(account.toJson());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void addAccount(final StepMCProfile.MCProfile profile) {
|
||||
this.accounts.add(profile);
|
||||
}
|
||||
|
||||
public void removeAccount(final StepMCProfile.MCProfile profile) {
|
||||
this.accounts.remove(profile);
|
||||
}
|
||||
|
||||
public void refreshAccounts() {
|
||||
final List<StepMCProfile.MCProfile> accounts = new ArrayList<>();
|
||||
for (StepMCProfile.MCProfile account : this.accounts) {
|
||||
try (final CloseableHttpClient httpClient = MicrosoftConstants.createHttpClient()) {
|
||||
accounts.add(MinecraftAuth.Java.Title.MC_PROFILE.refresh(httpClient, account));
|
||||
} catch (Throwable e) {
|
||||
Logger.LOGGER.error("Failed to refresh account " + account.name() + ", removing it from the list.", e);
|
||||
}
|
||||
}
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
public List<StepMCProfile.MCProfile> getAccounts() {
|
||||
return Collections.unmodifiableList(this.accounts);
|
||||
}
|
||||
|
||||
}
|
|
@ -94,7 +94,7 @@ public class GeneralTab extends AUITab {
|
|||
authMethodLabel.setBounds(10, 200, 400, 20);
|
||||
contentPane.add(authMethodLabel);
|
||||
|
||||
this.authMethod = new JComboBox<>(new String[]{"Use OpenAuthMod"});
|
||||
this.authMethod = new JComboBox<>(new String[]{"Use stored account", "Use OpenAuthMod"});
|
||||
this.authMethod.setBounds(10, 220, 465, 20);
|
||||
contentPane.add(this.authMethod);
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ public class GeneralTab extends AUITab {
|
|||
final String serverAddress = this.serverAddress.getText();
|
||||
final VersionEnum serverVersion = (VersionEnum) this.serverVersion.getSelectedItem();
|
||||
final int bindPort = (int) this.bindPort.getValue();
|
||||
final String authMethod = (String) this.authMethod.getSelectedItem();
|
||||
final int authMethod = this.authMethod.getSelectedIndex();
|
||||
final boolean betaCraftAuth = this.betaCraftAuth.isSelected();
|
||||
final boolean proxyOnlineMode = this.proxyOnlineMode.isSelected();
|
||||
|
||||
|
@ -162,10 +162,14 @@ public class GeneralTab extends AUITab {
|
|||
Options.CONNECT_ADDRESS = hostAndPort.getHost();
|
||||
Options.CONNECT_PORT = hostAndPort.getPortOrDefault(25565);
|
||||
Options.PROTOCOL_VERSION = serverVersion;
|
||||
|
||||
Options.OPENAUTHMOD_AUTH = true;
|
||||
Options.BETACRAFT_AUTH = betaCraftAuth;
|
||||
|
||||
if (authMethod == 0 && Options.MC_ACCOUNT == null && !ViaProxy.saveManager.accountsSave.getAccounts().isEmpty()) {
|
||||
Options.MC_ACCOUNT = ViaProxy.saveManager.accountsSave.getAccounts().get(0);
|
||||
} else if (authMethod == 1) {
|
||||
Options.OPENAUTHMOD_AUTH = true;
|
||||
}
|
||||
|
||||
ViaProxy.startProxy();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.raphimc.viaproxy.ui.impl;
|
|||
|
||||
import net.raphimc.mcauth.MinecraftAuth;
|
||||
import net.raphimc.mcauth.step.java.StepMCProfile;
|
||||
import net.raphimc.viaproxy.ViaProxy;
|
||||
import net.raphimc.viaproxy.cli.options.Options;
|
||||
import net.raphimc.viaproxy.ui.AUITab;
|
||||
import net.raphimc.viaproxy.ui.ViaProxyUI;
|
||||
import net.raphimc.viaproxy.ui.popups.AddAccountPopup;
|
||||
|
@ -30,17 +32,22 @@ public class OnlineModeTab extends AUITab {
|
|||
infoLabel.setBounds(10, 10, 500, 20);
|
||||
contentPane.add(infoLabel);
|
||||
}
|
||||
{
|
||||
JLabel info2Label = new JLabel("You can select the account to use by right clicking it. By default the first one will be used.");
|
||||
info2Label.setBounds(10, 30, 500, 20);
|
||||
contentPane.add(info2Label);
|
||||
}
|
||||
{
|
||||
JLabel infoLabel = new JLabel("<html>If you change your account frequently, you might want to install <a href=\"\">OpenAuthMod</a> on your</html>");
|
||||
infoLabel.setBounds(10, 40, 500, 20);
|
||||
infoLabel.setBounds(10, 60, 500, 20);
|
||||
contentPane.add(infoLabel);
|
||||
|
||||
JLabel infoLabel2 = new JLabel("client. This allows ViaProxy to use the account you are logged in with on the client.");
|
||||
infoLabel2.setBounds(10, 60, 500, 20);
|
||||
infoLabel2.setBounds(10, 80, 500, 20);
|
||||
contentPane.add(infoLabel2);
|
||||
|
||||
JLabel clickRect = new JLabel();
|
||||
clickRect.setBounds(353, 40, 80, 20);
|
||||
clickRect.setBounds(353, 60, 80, 20);
|
||||
clickRect.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
|
@ -51,7 +58,7 @@ public class OnlineModeTab extends AUITab {
|
|||
}
|
||||
{
|
||||
JScrollPane scrollPane = new JScrollPane();
|
||||
scrollPane.setBounds(10, 85, 465, 205);
|
||||
scrollPane.setBounds(10, 105, 465, 185);
|
||||
contentPane.add(scrollPane);
|
||||
|
||||
DefaultListModel<String> model = new DefaultListModel<>();
|
||||
|
@ -59,12 +66,31 @@ public class OnlineModeTab extends AUITab {
|
|||
scrollPane.setViewportView(this.accountsList);
|
||||
|
||||
JPopupMenu contextMenu = new JPopupMenu();
|
||||
JMenuItem selectItem = new JMenuItem("Use to join online mode servers");
|
||||
selectItem.addActionListener(e -> {
|
||||
int index = this.accountsList.getSelectedIndex();
|
||||
if (index != -1) {
|
||||
final StepMCProfile.MCProfile account = ViaProxy.saveManager.accountsSave.getAccounts().get(index);
|
||||
if (account != null) {
|
||||
Options.MC_ACCOUNT = account;
|
||||
} else {
|
||||
throw new IllegalStateException("Account is null");
|
||||
}
|
||||
}
|
||||
});
|
||||
contextMenu.add(selectItem);
|
||||
JMenuItem removeItem = new JMenuItem("Remove");
|
||||
removeItem.addActionListener(e -> {
|
||||
int index = this.accountsList.getSelectedIndex();
|
||||
if (index != -1) {
|
||||
model.remove(index);
|
||||
//TODO: Remove from save
|
||||
final StepMCProfile.MCProfile account = ViaProxy.saveManager.accountsSave.getAccounts().get(index);
|
||||
if (account != null) {
|
||||
ViaProxy.saveManager.accountsSave.removeAccount(account);
|
||||
ViaProxy.saveManager.save();
|
||||
} else {
|
||||
throw new IllegalStateException("Account is null");
|
||||
}
|
||||
}
|
||||
if (index < model.getSize()) this.accountsList.setSelectedIndex(index);
|
||||
else if (index > 0) this.accountsList.setSelectedIndex(index - 1);
|
||||
|
@ -89,10 +115,11 @@ public class OnlineModeTab extends AUITab {
|
|||
});
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
this.closePopup();
|
||||
ViaProxy.saveManager.accountsSave.addAccount(profile);
|
||||
ViaProxy.saveManager.save();
|
||||
DefaultListModel<String> model = (DefaultListModel<String>) this.accountsList.getModel();
|
||||
model.addElement(profile.name());
|
||||
this.frame.showInfo("The account " + profile.name() + " was added successfully.");
|
||||
//TODO: Add to save
|
||||
});
|
||||
} catch (InterruptedException ignored) {
|
||||
} catch (TimeoutException e) {
|
||||
|
@ -114,6 +141,12 @@ public class OnlineModeTab extends AUITab {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReady() {
|
||||
final DefaultListModel<String> model = (DefaultListModel<String>) this.accountsList.getModel();
|
||||
ViaProxy.saveManager.accountsSave.getAccounts().forEach(account -> model.addElement(account.name()));
|
||||
}
|
||||
|
||||
private void closePopup() {
|
||||
this.addAccountPopup.markExternalClose();
|
||||
this.addAccountPopup.setVisible(false);
|
||||
|
|
Loading…
Reference in a new issue