diff --git a/bungee/src/main/resources/plugin.yml b/bungee/src/main/resources/plugin.yml
index e5edac3c..8068498d 100644
--- a/bungee/src/main/resources/plugin.yml
+++ b/bungee/src/main/resources/plugin.yml
@@ -1,4 +1,4 @@
-name: ${outputName}
+name: ${project.parent.version}
description: ${project.description}
version: ${project.version}
author: ${project.organization.name}
diff --git a/common/src/main/java/org/geysermc/floodgate/FloodgatePlayerImpl.java b/common/src/main/java/org/geysermc/floodgate/FloodgatePlayerImpl.java
index dcc28cad..a0c16ed2 100644
--- a/common/src/main/java/org/geysermc/floodgate/FloodgatePlayerImpl.java
+++ b/common/src/main/java/org/geysermc/floodgate/FloodgatePlayerImpl.java
@@ -60,7 +60,7 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
@Setter
private boolean login = true;
- FloodgatePlayerImpl(BedrockData data, String prefix, boolean replaceSpaces) {
+ FloodgatePlayerImpl(BedrockData data, RawSkin skin, String prefix, boolean replaceSpaces) {
FloodgateApi api = FloodgateApi.getInstance();
version = data.getVersion();
username = data.getUsername();
diff --git a/common/src/main/java/org/geysermc/floodgate/HandshakeHandler.java b/common/src/main/java/org/geysermc/floodgate/HandshakeHandler.java
index ba13d1fe..e1dcfda2 100644
--- a/common/src/main/java/org/geysermc/floodgate/HandshakeHandler.java
+++ b/common/src/main/java/org/geysermc/floodgate/HandshakeHandler.java
@@ -26,16 +26,17 @@
package org.geysermc.floodgate;
+import com.google.common.base.Charsets;
import com.google.inject.Inject;
import lombok.*;
import org.geysermc.floodgate.api.SimpleFloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.config.FloodgateConfig;
+import org.geysermc.floodgate.crypto.AesCipher;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.util.BedrockData;
-import org.geysermc.floodgate.util.InvalidHeaderException;
-
-import java.util.Base64;
+import org.geysermc.floodgate.util.InvalidFormatException;
+import org.geysermc.floodgate.util.RawSkin;
import static org.geysermc.floodgate.util.BedrockData.EXPECTED_LENGTH;
@@ -57,35 +58,67 @@ public final class HandshakeHandler {
public HandshakeResult handle(@NonNull String handshakeData) {
try {
- String[] data = handshakeData.split("\0");
+ String[] dataArray = handshakeData.split("\0");
- boolean isBungeeData = data.length == 5;
+ boolean isBungeeData = dataArray.length == 5;
// this can be Bungee data (without skin) or Floodgate data
- if (data.length == 4) {
- isBungeeData = FloodgateCipher.hasHeader(data[3]);
+ if (dataArray.length == 4) {
+ isBungeeData = FloodgateCipher.hasHeader(dataArray[3]);
}
- if (proxy && isBungeeData || !isBungeeData && data.length != 2) {
+ if (proxy && isBungeeData || !isBungeeData && dataArray.length != 2) {
return ResultType.NOT_FLOODGATE_DATA.getCachedResult();
}
- String decrypted = cipher.decryptToString(Base64.getDecoder().decode(data[1]));
+ // calculate the expected Base64 encoded IV length.
+ int expectedIvLength = 4 * ((AesCipher.IV_LENGTH + 2) / 3);
+ int lastSplitIndex = dataArray[1].lastIndexOf(0x21);
+
+ byte[] floodgateData;
+ byte[] rawSkinData = null;
+
+ // if it has a RawSkin
+ if (lastSplitIndex - expectedIvLength != 0) {
+ floodgateData = dataArray[1].substring(0, lastSplitIndex).getBytes(Charsets.UTF_8);
+ rawSkinData = dataArray[1].substring(lastSplitIndex + 1).getBytes(Charsets.UTF_8);
+ } else {
+ floodgateData = dataArray[1].getBytes(Charsets.UTF_8);
+ }
+
+ // actual decryption
+ String decrypted = cipher.decryptToString(floodgateData);
BedrockData bedrockData = BedrockData.fromString(decrypted);
if (bedrockData.getDataLength() != EXPECTED_LENGTH) {
return ResultType.INVALID_DATA_LENGTH.getCachedResult();
}
+ RawSkin rawSkin = null;
+ // only decompile the skin after knowing that the floodgateData is legit
+ // note that we don't store a hash or anything in the BedrockData,
+ // so a mitm can change skins
+ if (rawSkinData != null) {
+ rawSkin = RawSkin.decode(rawSkinData);
+ }
+
+ System.out.println(rawSkin);
+
FloodgatePlayer player =
- new FloodgatePlayerImpl(bedrockData, usernamePrefix, replaceSpaces);
+ new FloodgatePlayerImpl(bedrockData, rawSkin, usernamePrefix, replaceSpaces);
api.addPlayer(player.getJavaUniqueId(), player);
- return new HandshakeResult(ResultType.SUCCESS, data, bedrockData, player);
- } catch (InvalidHeaderException headerException) {
- return ResultType.NOT_FLOODGATE_DATA.getCachedResult();
+ return new HandshakeResult(ResultType.SUCCESS, dataArray, bedrockData, player);
+ } catch (InvalidFormatException formatException) {
+ // only header exceptions should return 'not floodgate data',
+ // all the other format exceptions are because of invalid/tempered Floodgate data
+ if (formatException.isHeader()) {
+ return ResultType.NOT_FLOODGATE_DATA.getCachedResult();
+ }
+
+ formatException.printStackTrace();
+ return ResultType.EXCEPTION.getCachedResult();
} catch (Exception exception) {
exception.printStackTrace();
- System.out.println(handshakeData);
return ResultType.EXCEPTION.getCachedResult();
}
}
diff --git a/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java b/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java
index 08af75eb..ddc3e9b7 100644
--- a/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java
+++ b/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java
@@ -42,10 +42,7 @@ import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.config.loader.ConfigLoader;
import org.geysermc.floodgate.config.updater.ConfigFileUpdater;
import org.geysermc.floodgate.config.updater.ConfigUpdater;
-import org.geysermc.floodgate.crypto.AesCipher;
-import org.geysermc.floodgate.crypto.AesKeyProducer;
-import org.geysermc.floodgate.crypto.FloodgateCipher;
-import org.geysermc.floodgate.crypto.KeyProducer;
+import org.geysermc.floodgate.crypto.*;
import org.geysermc.floodgate.inject.CommonPlatformInjector;
import org.geysermc.floodgate.link.PlayerLinkLoader;
@@ -70,7 +67,7 @@ public final class CommonModule extends AbstractModule {
@Provides
@Singleton
public FloodgateCipher cipher() {
- return new AesCipher();
+ return new AesCipher(new Base64Topping());
}
@Provides
diff --git a/pom.xml b/pom.xml
index f892bb3a..5ca6af6f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
https://github.com/GeyserMC/Floodgate
- 1.0.0
+ 1.1.0
1.8.8-R0.1-SNAPSHOT
1.15-SNAPSHOT
1.1.0-SNAPSHOT
diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml
index 36dc6876..aa216a9d 100644
--- a/spigot/src/main/resources/plugin.yml
+++ b/spigot/src/main/resources/plugin.yml
@@ -1,4 +1,4 @@
-name: ${outputName}
+name: ${project.parent.name}
description: ${project.description}
version: ${project.version}
author: ${project.organization.name}
diff --git a/velocity/src/main/resources/velocity-plugin.json b/velocity/src/main/resources/velocity-plugin.json
index 872b82e7..bf949f5e 100644
--- a/velocity/src/main/resources/velocity-plugin.json
+++ b/velocity/src/main/resources/velocity-plugin.json
@@ -1 +1 @@
-{"id": "${project.parent.name}", "name": "${outputName}", "version": "${project.version}", "description": "${project.description}", "url": "${project.url}", "authors": ["${project.organization.name}"], "main": "org.geysermc.floodgate.VelocityPlugin"}
\ No newline at end of file
+{"id": "${project.parent.name}", "name": "${project.parent.name}", "version": "${project.version}", "description": "${project.description}", "url": "${project.url}", "authors": ["${project.organization.name}"], "main": "org.geysermc.floodgate.VelocityPlugin"}
\ No newline at end of file