Skip to content

Commit 4b2acfc

Browse files
committed
Added code
1 parent 5ff8949 commit 4b2acfc

File tree

4 files changed

+179
-0
lines changed

4 files changed

+179
-0
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
11
# ViaProxyOpenAuthMod
2+
[ViaProxy](https://github.com/RaphiMC/ViaProxy) plugin which implements the [OpenAuthMod](https://github.com/RaphiMC/OpenAuthMod) protocol.
3+
4+
This plugin allows clients to authenticate with online mode servers using the OpenAuthMod mod.
5+
6+
## Installation and Usage
7+
1. Download the latest version from [GitHub Actions](https://github.com/ViaVersionAddons/ViaProxyOpenAuthMod/actions).
8+
2. Put the jar file into the plugins folder of ViaProxy
9+
3. Install [OpenAuthMod](https://modrinth.com/mod/openauthmod) on your client.
10+
4. Run ViaProxy. You can now switch the authentication mode to OpenAuthMod (Use `OPENAUTHMOD` for CLI or config file).
11+
12+
## Contact
13+
If you encounter any issues, please report them on the
14+
[issue tracker](https://github.com/ViaVersionAddons/ViaProxyOpenAuthMod/issues).
15+
If you just want to talk or need help using ViaProxyOpenAuthMod feel free to join my
16+
[Discord](https://discord.gg/dCzT9XHEWu).

gradlew

100644100755
File mode changed.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* This file is part of ViaProxyOpenAuthMod - https://github.com/ViaVersionAddons/ViaProxyOpenAuthMod
3+
* Copyright (C) 2024-2024 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.openauthmodplugin;
19+
20+
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
21+
import io.netty.buffer.ByteBuf;
22+
import io.netty.buffer.ByteBufUtil;
23+
import io.netty.buffer.Unpooled;
24+
import io.netty.channel.ChannelFutureListener;
25+
import net.lenni0451.mcstructs.text.components.StringComponent;
26+
import net.raphimc.netminecraft.packet.Packet;
27+
import net.raphimc.netminecraft.packet.PacketTypes;
28+
import net.raphimc.netminecraft.packet.impl.common.C2SCustomPayloadPacket;
29+
import net.raphimc.netminecraft.packet.impl.login.C2SLoginCustomQueryAnswerPacket;
30+
import net.raphimc.netminecraft.packet.impl.login.C2SLoginKeyPacket;
31+
import net.raphimc.netminecraft.packet.impl.login.S2CLoginCustomQueryPacket;
32+
import net.raphimc.netminecraft.packet.impl.login.S2CLoginDisconnectPacket;
33+
import net.raphimc.netminecraft.packet.impl.play.S2CPlayCustomPayloadPacket;
34+
import net.raphimc.viaproxy.proxy.external_interface.OpenAuthModConstants;
35+
import net.raphimc.viaproxy.proxy.packethandler.PacketHandler;
36+
import net.raphimc.viaproxy.proxy.session.ProxyConnection;
37+
38+
import java.nio.charset.StandardCharsets;
39+
import java.util.Base64;
40+
import java.util.List;
41+
import java.util.Map;
42+
import java.util.concurrent.CompletableFuture;
43+
import java.util.concurrent.ConcurrentHashMap;
44+
import java.util.concurrent.atomic.AtomicInteger;
45+
46+
public class OpenAuthModPacketHandler extends PacketHandler {
47+
48+
private final AtomicInteger id = new AtomicInteger(0);
49+
private final Map<Integer, CompletableFuture<ByteBuf>> customPayloadListener = new ConcurrentHashMap<>();
50+
51+
public OpenAuthModPacketHandler(ProxyConnection proxyConnection) {
52+
super(proxyConnection);
53+
}
54+
55+
@Override
56+
public boolean handleC2P(Packet packet, List<ChannelFutureListener> listeners) {
57+
if (packet instanceof C2SCustomPayloadPacket customPayloadPacket) {
58+
final ByteBuf data = Unpooled.wrappedBuffer(customPayloadPacket.data);
59+
if (customPayloadPacket.channel.equals(OpenAuthModConstants.DATA_CHANNEL) && this.handleCustomPayload(PacketTypes.readVarInt(data), data)) {
60+
return false;
61+
}
62+
} else if (packet instanceof C2SLoginCustomQueryAnswerPacket loginCustomQueryAnswer) {
63+
if (loginCustomQueryAnswer.response != null && this.handleCustomPayload(loginCustomQueryAnswer.queryId, Unpooled.wrappedBuffer(loginCustomQueryAnswer.response))) {
64+
return false;
65+
}
66+
} else if (packet instanceof C2SLoginKeyPacket loginKeyPacket) {
67+
if (this.proxyConnection.getClientVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && new String(loginKeyPacket.encryptedNonce, StandardCharsets.UTF_8).equals(OpenAuthModConstants.DATA_CHANNEL)) { // 1.8-1.12.2 OpenAuthMod response handling
68+
final ByteBuf byteBuf = Unpooled.wrappedBuffer(loginKeyPacket.encryptedSecretKey);
69+
this.handleCustomPayload(PacketTypes.readVarInt(byteBuf), byteBuf);
70+
return false;
71+
}
72+
}
73+
74+
return true;
75+
}
76+
77+
public CompletableFuture<ByteBuf> sendCustomPayload(final String channel, final ByteBuf data) {
78+
if (channel.length() > 20) throw new IllegalStateException("Channel name can't be longer than 20 characters");
79+
final CompletableFuture<ByteBuf> future = new CompletableFuture<>();
80+
final int id = this.id.getAndIncrement();
81+
82+
switch (this.proxyConnection.getC2pConnectionState()) {
83+
case LOGIN:
84+
if (this.proxyConnection.getClientVersion().newerThanOrEqualTo(ProtocolVersion.v1_13)) {
85+
this.proxyConnection.getC2P().writeAndFlush(new S2CLoginCustomQueryPacket(id, channel, PacketTypes.readReadableBytes(data))).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
86+
} else {
87+
final ByteBuf disconnectPacketData = Unpooled.buffer();
88+
PacketTypes.writeString(disconnectPacketData, channel);
89+
PacketTypes.writeVarInt(disconnectPacketData, id);
90+
disconnectPacketData.writeBytes(data);
91+
this.proxyConnection.getC2P().writeAndFlush(new S2CLoginDisconnectPacket(new StringComponent("§cYou need to install OpenAuthMod in order to join this server.§k\n" + Base64.getEncoder().encodeToString(ByteBufUtil.getBytes(disconnectPacketData)) + "\n" + OpenAuthModConstants.LEGACY_MAGIC_STRING))).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
92+
}
93+
break;
94+
case PLAY:
95+
final ByteBuf responseData = Unpooled.buffer();
96+
PacketTypes.writeVarInt(responseData, id);
97+
responseData.writeBytes(data);
98+
this.proxyConnection.getC2P().writeAndFlush(new S2CPlayCustomPayloadPacket(channel, ByteBufUtil.getBytes(responseData))).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
99+
break;
100+
default:
101+
throw new IllegalStateException("Can't send a custom payload packet during " + this.proxyConnection.getC2pConnectionState());
102+
}
103+
104+
this.customPayloadListener.put(id, future);
105+
return future;
106+
}
107+
108+
private boolean handleCustomPayload(final int id, final ByteBuf data) {
109+
if (this.customPayloadListener.containsKey(id)) {
110+
this.customPayloadListener.remove(id).complete(data);
111+
return true;
112+
}
113+
return false;
114+
}
115+
116+
}

src/main/java/net/raphimc/openauthmodplugin/OpenAuthModPlugin.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,62 @@
1717
*/
1818
package net.raphimc.openauthmodplugin;
1919

20+
import io.netty.buffer.ByteBuf;
21+
import io.netty.buffer.Unpooled;
22+
import net.lenni0451.lambdaevents.EventHandler;
23+
import net.lenni0451.reflect.Enums;
24+
import net.lenni0451.reflect.stream.RStream;
25+
import net.raphimc.netminecraft.packet.PacketTypes;
2026
import net.raphimc.viaproxy.ViaProxy;
2127
import net.raphimc.viaproxy.plugins.ViaProxyPlugin;
28+
import net.raphimc.viaproxy.plugins.events.ConnectEvent;
29+
import net.raphimc.viaproxy.plugins.events.JoinServerRequestEvent;
30+
import net.raphimc.viaproxy.plugins.events.ViaProxyLoadedEvent;
31+
import net.raphimc.viaproxy.protocoltranslator.viaproxy.ViaProxyConfig;
32+
import net.raphimc.viaproxy.proxy.external_interface.OpenAuthModConstants;
33+
import net.raphimc.viaproxy.ui.I18n;
34+
35+
import java.util.Map;
36+
import java.util.Properties;
37+
import java.util.concurrent.ExecutionException;
38+
import java.util.concurrent.TimeUnit;
39+
import java.util.concurrent.TimeoutException;
2240

2341
public class OpenAuthModPlugin extends ViaProxyPlugin {
2442

43+
private static ViaProxyConfig.AuthMethod OPENAUTHMOD;
44+
2545
@Override
2646
public void onEnable() {
2747
ViaProxy.EVENT_MANAGER.register(this);
48+
49+
OPENAUTHMOD = Enums.newInstance(ViaProxyConfig.AuthMethod.class, "OPENAUTHMOD", ViaProxyConfig.AuthMethod.values().length, new Class[]{String.class}, new Object[]{"openauthmod.auth_method.name"});
50+
Enums.addEnumInstance(ViaProxyConfig.AuthMethod.class, OPENAUTHMOD);
51+
}
52+
53+
@EventHandler
54+
private void onViaProxyLoaded(ViaProxyLoadedEvent event) {
55+
final Map<String, Properties> locales = RStream.of(I18n.class).fields().by("LOCALES").get();
56+
locales.get("en_US").setProperty(OPENAUTHMOD.getGuiTranslationKey(), "Use OpenAuthMod");
57+
}
58+
59+
@EventHandler
60+
private void onConnect(ConnectEvent event) {
61+
event.getProxyConnection().getPacketHandlers().add(0, new OpenAuthModPacketHandler(event.getProxyConnection()));
62+
}
63+
64+
@EventHandler
65+
private void onJoinServerRequest(JoinServerRequestEvent event) throws ExecutionException, InterruptedException {
66+
if (ViaProxy.getConfig().getAuthMethod() == OPENAUTHMOD) {
67+
try {
68+
final ByteBuf response = event.getProxyConnection().getPacketHandler(OpenAuthModPacketHandler.class).sendCustomPayload(OpenAuthModConstants.JOIN_CHANNEL, PacketTypes.writeString(Unpooled.buffer(), event.getServerIdHash())).get(6, TimeUnit.SECONDS);
69+
if (response == null) throw new TimeoutException();
70+
if (response.isReadable() && !response.readBoolean()) throw new TimeoutException();
71+
event.setCancelled(true);
72+
} catch (TimeoutException e) {
73+
event.getProxyConnection().kickClient("§cAuthentication cancelled! You need to install the OpenAuthMod client mod in order to join this server.");
74+
}
75+
}
2876
}
2977

3078
}

0 commit comments

Comments
 (0)