Skip to content

Commit

Permalink
Added KSon to locklogin.json
Browse files Browse the repository at this point in the history
  • Loading branch information
KarmaDeb committed Jan 8, 2024
1 parent 06be0e5 commit 4a695f5
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 25 deletions.
5 changes: 5 additions & 0 deletions LockLoginBungee/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
<groupId>es.karmadev</groupId>
<artifactId>KSon</artifactId>
</dependency>
<dependency>
<groupId>es.karmadev</groupId>
<artifactId>Collect</artifactId>
</dependency>

<dependency>
<groupId>es.karmadev</groupId>
<artifactId>KarmaAPI-Core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@
import es.karmadev.api.core.source.exception.AlreadyRegisteredException;
import es.karmadev.api.logger.log.console.LogLevel;
import es.karmadev.locklogin.bungee.command.TestCommand;
import es.karmadev.locklogin.bungee.packet.CustomPacket;
import es.karmadev.locklogin.bungee.packet.PacketDataHandler;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class BungeePlugin extends KarmaPlugin implements Listener {

LockLoginBungee bungee;

private final Map<String, BiConsumer<Server, byte[]>> channelListeners = new ConcurrentHashMap<>();

public BungeePlugin() throws NoSuchFieldException, IllegalAccessException, AlreadyRegisteredException {
super(false);
bungee = new LockLoginBungee(this);
Expand All @@ -40,8 +47,31 @@ public void disable() {

}

/**
* Add a channel listener
*
* @param channel the channel name to listen at
* @param dataHandler the data handler
*/
public void addChannelListener(final String channel, final BiConsumer<Server, byte[]> dataHandler) {
this.channelListeners.put(channel, dataHandler);
}

@EventHandler(priority = EventPriority.LOWEST)
public void onMessageReceive(final PluginMessageEvent e) { //I feel bad for having a single class just for this...
CustomPacket.handle(e);
String tag = e.getTag();
if (PacketDataHandler.tagExists(tag)) {
Server server = (Server) e.getSender();

BiConsumer<Server, byte[]> handler = channelListeners.get(e.getTag());
if (handler == null) {
logger().send(LogLevel.WARNING, "Unhandled plugin message at {0}", tag);
return;
}

handler.accept(server, e.getData());
}

//CustomPacket.handle(e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import es.karmadev.api.kson.io.JsonReader;
import es.karmadev.api.logger.log.console.LogLevel;
import es.karmadev.api.minecraft.text.Colorize;
import es.karmadev.api.object.ObjectUtils;
import es.karmadev.api.strings.StringUtils;
import es.karmadev.api.version.Version;
import es.karmadev.locklogin.api.BuildType;
Expand Down Expand Up @@ -97,10 +98,7 @@
import java.security.spec.X509EncodedKeySpec;
import java.sql.*;
import java.time.Instant;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
Expand All @@ -127,6 +125,8 @@ public class LockLoginBungee implements LockLogin, NetworkServer {
@Getter
private final TotpGlobalHandler totpHandler = new TotpGlobalHandler();

private final Set<NetworkChannel> channels = ConcurrentHashMap.newKeySet();

private CAccountFactory default_account_factory;
private CSessionFactory default_session_factory;
private CUserFactory default_user_factory;
Expand Down Expand Up @@ -1088,7 +1088,9 @@ public Collection<LocalNetworkClient> getOfflineClients() {
*/
@Override
public NetworkChannel getChannel(final String name) {
return null;
if (ObjectUtils.isNullOrEmpty(name)) return null;
return channels.stream().filter((channel) -> channel.getChannel().equals(name))
.findAny().orElse(null);
}

/**
Expand All @@ -1098,7 +1100,10 @@ public NetworkChannel getChannel(final String name) {
*/
@Override
public void registerChannel(final NetworkChannel channel) {
if (channel == null) return;

channels.removeIf((ch) -> ch.getChannel().equals(channel.getChannel()));
channels.add(channel);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
* compatible with multi-bungee instances, but it's recommended
* to use Redis or Channels instead.
*/
@RequiredArgsConstructor
public class BungeeChannel implements NetworkChannel {

private final String channel;
private final BungeeMessagingQue que = new BungeeMessagingQue();
private final BungeeMessagingQue que;

private final GenericHandlerList handlerList = new GenericHandlerList();

BungeeChannel(final String channel) {
this.channel = channel;
this.que = new BungeeMessagingQue(this);
}

/**
* Get the channel name this
* network channel works at
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,130 @@
package es.karmadev.locklogin.bungee.network;

import es.karmadev.api.collect.model.PriorityCollection;
import es.karmadev.api.collect.priority.PriorityArray;
import es.karmadev.api.kson.JsonObject;
import es.karmadev.api.strings.StringUtils;
import es.karmadev.locklogin.api.CurrentPlugin;
import es.karmadev.locklogin.api.network.communication.data.DataType;
import es.karmadev.locklogin.api.network.communication.exception.InvalidPacketDataException;
import es.karmadev.locklogin.api.network.communication.packet.IncomingPacket;
import es.karmadev.locklogin.api.network.communication.packet.OutgoingPacket;
import es.karmadev.locklogin.api.network.communication.packet.frame.FrameBuilder;
import es.karmadev.locklogin.api.network.communication.packet.frame.PacketFrame;
import es.karmadev.locklogin.api.network.communication.packet.listener.event.PacketReceiveEvent;
import es.karmadev.locklogin.api.network.server.packet.NetworkChannelQue;
import es.karmadev.locklogin.api.network.server.packet.NetworkPacket;
import es.karmadev.locklogin.bungee.LockLoginBungee;
import es.karmadev.locklogin.bungee.packet.PacketDataHandler;
import es.karmadev.locklogin.common.api.packet.CInPacket;
import es.karmadev.locklogin.common.api.packet.frame.CFrameBuilder;
import net.md_5.bungee.api.ProxyServer;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Represents the BungeeCord messaging que
*/
public class BungeeMessagingQue implements NetworkChannelQue {

private final static LockLoginBungee plugin = (LockLoginBungee) CurrentPlugin.getPlugin();

private final PriorityCollection<NetworkPacket> packets = new PriorityArray<>(NetworkPacket.class);
private final Map<String, FrameBuilder> frames = new ConcurrentHashMap<>();

private NetworkPacket current;

/**
* Initialize the messaging que
*/
BungeeMessagingQue(final BungeeChannel channel) {
String tag = channel.getChannel();

plugin.plugin().addChannelListener(tag, (server, rawData) -> {
if (rawData == null) return;
String rawPacketData = new String(rawData, StandardCharsets.UTF_8);

Object packetObject = StringUtils.load(rawPacketData).orElse(null);
if (packetObject instanceof PacketFrame) {
PacketFrame frame = (PacketFrame) packetObject;
FrameBuilder builder = frames.computeIfAbsent(tag, (b) -> new CFrameBuilder((rawPacket) -> {
KeyPair pair = plugin.getCommunicationKeys();
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
return cipher.doFinal(rawPacket);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
IllegalBlockSizeException |
BadPaddingException ex) {
ex.printStackTrace();
}

return null;
}));
builder.append(frame);

int position = frame.position();
int max = frame.frames();

if (position == max) {
ProxyServer.getInstance().getScheduler().runAsync(plugin.plugin(), () -> {
try {
byte[] rawPacket = builder.build();

String raw = new String(rawPacket, StandardCharsets.UTF_8);
Object packet = StringUtils.load(raw).orElse(null);

if (packet instanceof OutgoingPacket) {
OutgoingPacket out = (OutgoingPacket) packet;
DataType type = out.getType();

if (!type.equals(DataType.HELLO)) {
JsonObject object = out.build();
if (object.hasChild(tag)) {
byte[] sharedBytes = Base64.getDecoder().decode(object.getChild(tag)
.asNative().getAsString());
byte[] currentBytes = plugin.getSharedSecret().getEncoded();

if (!compare(sharedBytes, currentBytes)) {
plugin.err("Received invalid packet (invalid shared)");
return;
}
} else {
plugin.err("Received unverified packet (missing shared)");
return;
}
}

if (PacketDataHandler.validatePacket(server, tag, out)) {
JsonObject object = out.build();
object.put("server", server.getInfo().getName());

String rawJson = object.toString(false);

IncomingPacket incoming = new CInPacket(rawJson);
channel.handle(new PacketReceiveEvent(channel, incoming));
}
}
} catch (InvalidPacketDataException ex) {
plugin.log(ex, "Failed to handle packet under tag {0}", tag);
}
});
}
}
});
}

/**
* Append a packet
*
Expand All @@ -16,7 +133,7 @@ public class BungeeMessagingQue implements NetworkChannelQue {
*/
@Override
public void appendPacket(final NetworkPacket packet) throws SecurityException {

packets.add(packet, packet.priority());
}

/**
Expand All @@ -26,7 +143,10 @@ public void appendPacket(final NetworkPacket packet) throws SecurityException {
*/
@Override
public NetworkPacket nextPacket() {
return null;
if (packets.isEmpty()) return null;

current = packets.next();
return current;
}

/**
Expand All @@ -36,7 +156,10 @@ public NetworkPacket nextPacket() {
*/
@Override
public NetworkPacket previousPacket() {
return null;
if (packets.size() < 2) return null;

current = packets.previous();
return current;
}

/**
Expand All @@ -46,7 +169,7 @@ public NetworkPacket previousPacket() {
*/
@Override
public boolean processing() {
return false;
return current != null;
}

/**
Expand All @@ -55,15 +178,23 @@ public boolean processing() {
*/
@Override
public void shiftPacket() {
if (current != null) {
packets.consume();
packets.add(current, current.priority());

current = null;
}
}

/**
* Consume the current packet
*/
@Override
public void consumePacket() {

if (current != null) {
packets.consume();
current = null;
}
}

/**
Expand All @@ -72,6 +203,31 @@ public void consumePacket() {
*/
@Override
public void cancelPacket() {
current = null;
}

private static boolean compare(final byte[] b1, final byte[] b2) {
String b1Hex = digest(b1);
String b2Hex = digest(b2);

return b1Hex.equals(b2Hex);
}

private static String digest(final byte[] b) {
try {
MessageDigest hasher = MessageDigest.getInstance("md5");
hasher.update(b);

byte[] result = hasher.digest();
StringBuilder hexBuilder = new StringBuilder();
for (byte data : result) {
int i = Byte.toUnsignedInt(data);
hexBuilder.append(Integer.toString(i, 16));
}

return hexBuilder.toString();
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
}
}
Loading

0 comments on commit 4a695f5

Please sign in to comment.