mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-12-23 07:12:39 +01:00
Compare commits
99 Commits
debug-prot
...
database-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4abd6b9134 | ||
|
|
4717bf82f7 | ||
|
|
0214827266 | ||
|
|
55adbaa58b | ||
|
|
7603da0b6b | ||
|
|
e5d61101ae | ||
|
|
c12a88966c | ||
|
|
7d7d91f4da | ||
|
|
8447285ef8 | ||
|
|
edae388b37 | ||
|
|
7c41b8a5e8 | ||
|
|
dfbfe9c4e5 | ||
|
|
2fa6700666 | ||
|
|
0db205691b | ||
|
|
d13414097a | ||
|
|
d6389f0474 | ||
|
|
d153b5e2d5 | ||
|
|
b21d73e9dc | ||
|
|
730520fd77 | ||
|
|
652653bc45 | ||
|
|
010f9b3827 | ||
|
|
42911e978f | ||
|
|
46bfbb9ca0 | ||
|
|
546bbede0b | ||
|
|
487bc24a8a | ||
|
|
23d7594b67 | ||
|
|
87121979ce | ||
|
|
a42b824c3d | ||
|
|
a50f8b7210 | ||
|
|
598d384516 | ||
|
|
48d4a4861a | ||
|
|
6b4a6cb66c | ||
|
|
43e507d032 | ||
|
|
40b70c367c | ||
|
|
e7208e6a5d | ||
|
|
2646ebac40 | ||
|
|
b20000cae8 | ||
|
|
0adadd02a1 | ||
|
|
28cf02129f | ||
|
|
b4ea6f19b5 | ||
|
|
06c0e64073 | ||
|
|
984ad723d2 | ||
|
|
acdd0d577a | ||
|
|
f4e098589b | ||
|
|
f706f428a3 | ||
|
|
971b0e1f09 | ||
|
|
c63712a949 | ||
|
|
cb5598f2f4 | ||
|
|
b242a7b3ce | ||
|
|
889cabb9e1 | ||
|
|
7cbcf5b465 | ||
|
|
9d99e1e6e0 | ||
|
|
85f7f9262b | ||
|
|
020291271a | ||
|
|
96be14cc73 | ||
|
|
1038453469 | ||
|
|
ca17c3f377 | ||
|
|
c56d55f23d | ||
|
|
19af059538 | ||
|
|
2989d9a62d | ||
|
|
84bfce9f84 | ||
|
|
2fae5060dc | ||
|
|
5a29eede69 | ||
|
|
7425df86b5 | ||
|
|
2e60f9bc15 | ||
|
|
ee6aeafafc | ||
|
|
47644afa19 | ||
|
|
9441d6551d | ||
|
|
0867719878 | ||
|
|
ace180976d | ||
|
|
749974bca7 | ||
|
|
feb46399da | ||
|
|
18b0c427c4 | ||
|
|
520bb0d761 | ||
|
|
6fe7eb2c24 | ||
|
|
ed9e295c1b | ||
|
|
c8c4aa522d | ||
|
|
649ce8cb1a | ||
|
|
61f949cf97 | ||
|
|
8571feef6d | ||
|
|
bf86042c52 | ||
|
|
55e3531718 | ||
|
|
1694a7a4f3 | ||
|
|
ba7613c32a | ||
|
|
3244a3ab64 | ||
|
|
833177933a | ||
|
|
091b558826 | ||
|
|
df5e6db183 | ||
|
|
845d16dd04 | ||
|
|
6beaf194ce | ||
|
|
62d7320a6e | ||
|
|
c1207d884d | ||
|
|
4a8e903773 | ||
|
|
e53c4f89f0 | ||
|
|
ed45fada59 | ||
|
|
045f980f38 | ||
|
|
25c8be65ed | ||
|
|
e3778c865c | ||
|
|
4765d6d4ef |
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: 🐞 Bug Report
|
||||
description: Something isn't working, broken, not expected behavior
|
||||
labels: [bug]
|
||||
labels: [ bug ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -8,18 +8,23 @@ assignees: ''
|
||||
---
|
||||
|
||||
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||
|
||||
[//]: # (Before reporting make sure you're running the **latest build** of the plugin and checked for existing issues!)
|
||||
|
||||
[//]: # (This ticket is about suggestions for a feature or particular enhancement)
|
||||
|
||||
### Is your feature request related to a problem? Please describe.
|
||||
|
||||
[//]: # (A clear and concise description of what the problem is. Ex. I'm always frustrated when [...])
|
||||
|
||||
### Describe the solution you'd like
|
||||
|
||||
[//]: # (A clear and concise description of what you want to happen.)
|
||||
|
||||
### Describe alternatives you've considered
|
||||
|
||||
[//]: # (A clear and concise description of any alternative solutions or features you've considered.)
|
||||
|
||||
### Additional context
|
||||
|
||||
[//]: # (Add any other context or screenshots about the feature request here.)
|
||||
|
||||
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@@ -1,8 +1,11 @@
|
||||
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||
|
||||
[//]: # (If your work is in progress, please consider making a draft pull request.)
|
||||
|
||||
### Summary of your change
|
||||
|
||||
[//]: # (Example: motivation, enhancement)
|
||||
|
||||
### Related issue
|
||||
|
||||
[//]: # (Reference it using '#NUMBER'. Ex: Fixes/Related #...)
|
||||
|
||||
92
.github/workflows/codeql-analysis.yml
vendored
92
.github/workflows/codeql-analysis.yml
vendored
@@ -4,63 +4,57 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
# Scan only for push on the primary branch for now
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
# Scan only for push on the primary branch for now
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
# job i
|
||||
analyze:
|
||||
# job i
|
||||
analyze:
|
||||
|
||||
# Display name
|
||||
name: Analyze
|
||||
# Display name
|
||||
name: Analyze
|
||||
|
||||
# Environment
|
||||
runs-on: ubuntu-latest
|
||||
# Environment
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Languages to scan
|
||||
language: [ 'java' ]
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
# Languages to scan
|
||||
language: [ 'java' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 18
|
||||
cache: 'maven'
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 19
|
||||
cache: 'maven'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
# Cache build process too like in the maven config
|
||||
- uses: actions/cache@v3.0.4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
# Auto build attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# Auto build attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
57
.github/workflows/maven.yml
vendored
57
.github/workflows/maven.yml
vendored
@@ -2,41 +2,42 @@
|
||||
# including making pull requests review easier
|
||||
|
||||
# Human-readable name in the actions tab
|
||||
name: Java CI
|
||||
name: Maven Build
|
||||
|
||||
# Build on every pull request regardless of the branch
|
||||
# Wiki: https://help.github.com/en/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# job id
|
||||
build_and_test:
|
||||
# job id
|
||||
build_and_test:
|
||||
|
||||
# Environment image - always use the newest OS
|
||||
runs-on: ubuntu-latest
|
||||
# Environment image - always use the newest OS
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Run steps
|
||||
steps:
|
||||
# Pull changes
|
||||
- uses: actions/checkout@v3
|
||||
# Run steps
|
||||
steps:
|
||||
# Pull changes
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 18
|
||||
cache: 'maven'
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 19
|
||||
cache: 'maven'
|
||||
|
||||
# Build and test (included in package)
|
||||
- name: Build with Maven and test
|
||||
# Run non-interactive, package (with compile+test),
|
||||
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
|
||||
# possible errors in dependencies
|
||||
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
|
||||
# Build and test (included in package)
|
||||
- name: Build with Maven and test
|
||||
# Run non-interactive, package (with compile+test),
|
||||
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums
|
||||
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
|
||||
|
||||
@@ -112,7 +112,7 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
|
||||
* This is often found in `spigot.yml` or `paper.yml`
|
||||
2. Restart the backend server
|
||||
3. Now there is `allowed-proxies.txt` file in the FastLogin folder of the restarted server
|
||||
* BungeeCord: Put your `stats-id` from the BungeeCord config into this file
|
||||
* BungeeCord: Put your `stats`-id from the BungeeCord config into this file
|
||||
* Velocity: On plugin startup the plugin generates a `proxyId.txt` inside the plugins folder of the proxy
|
||||
4. Activate ip forwarding in your proxy config
|
||||
5. Check your database settings in the config of FastLogin on your proxy
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<properties>
|
||||
<nettyVersion>4.1.77.Final</nettyVersion>
|
||||
<nettyVersion>4.1.79.Final</nettyVersion>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
@@ -50,7 +50,7 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
@@ -86,7 +86,8 @@
|
||||
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
||||
<!-- Located in META-INF/services -->
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<filters>
|
||||
@@ -164,7 +165,7 @@
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<version>1.19.4-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<!-- Use our own newer api version -->
|
||||
<exclusions>
|
||||
@@ -179,7 +180,7 @@
|
||||
<dependency>
|
||||
<groupId>io.papermc</groupId>
|
||||
<artifactId>paperlib</artifactId>
|
||||
<version>1.0.7</version>
|
||||
<version>1.0.8</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -228,15 +229,11 @@
|
||||
<dependency>
|
||||
<groupId>org.geysermc.floodgate</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>2.2.0-SNAPSHOT</version>
|
||||
<version>${floodgate.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
@@ -244,7 +241,7 @@
|
||||
|
||||
<!-- Bedrock player bridge -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<groupId>org.geysermc.geyser</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
@@ -258,17 +255,23 @@
|
||||
|
||||
<!-- We need the API, but it was excluded above -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<groupId>org.geysermc.geyser</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Provide premium placeholders-->
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.11.2</version>
|
||||
<version>2.11.3</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
@@ -297,7 +300,7 @@
|
||||
<dependency>
|
||||
<groupId>com.lenis0012.bukkit</groupId>
|
||||
<artifactId>loginsecurity</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>3.1.1</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
@@ -368,7 +371,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
<version>1.71</version>
|
||||
<version>1.72</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -376,9 +379,9 @@
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<version>${nettyVersion}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec</artifactId>
|
||||
|
||||
@@ -32,11 +32,11 @@ import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a client connecting to the server.
|
||||
*
|
||||
* <p>
|
||||
* This session is invalid if the player disconnects or the login was successful
|
||||
*/
|
||||
public class BukkitLoginSession extends LoginSession {
|
||||
@@ -76,7 +76,7 @@ public class BukkitLoginSession extends LoginSession {
|
||||
|
||||
/**
|
||||
* Gets the verify-token the server sent to the client.
|
||||
*
|
||||
* <p>
|
||||
* Empty if it's a BungeeCord connection
|
||||
*
|
||||
* @return verify token from the server
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
||||
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
||||
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ManualNameChange;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
||||
@@ -60,6 +59,7 @@ import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
@@ -119,10 +119,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
||||
ProtocolLibListener.register(this, core.getAntiBot(), core.getConfig().getBoolean("verifyClientKeys"));
|
||||
|
||||
if (isPluginInstalled("floodgate")) {
|
||||
printFloodgateWarning();
|
||||
}
|
||||
|
||||
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
||||
if (!PaperLib.isPaper() && getConfig().getBoolean("forwardSkin")) {
|
||||
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
||||
@@ -152,23 +148,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
premiumPlaceholder = new PremiumPlaceholder(this);
|
||||
premiumPlaceholder.register();
|
||||
}
|
||||
|
||||
dependencyWarnings();
|
||||
}
|
||||
|
||||
private void printFloodgateWarning() {
|
||||
if (getConfig().getBoolean("floodgatePrefixWorkaround")) {
|
||||
ManualNameChange.register(this, floodgateService);
|
||||
logger.info("Floodgate prefix injection workaround has been enabled.");
|
||||
logger.info("If you have problems joining the server, try disabling it in the configuration.");
|
||||
} else {
|
||||
logger.warn("We have detected that you are running FastLogin alongside Floodgate and ProtocolLib.");
|
||||
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from "
|
||||
+ "showing up when it is together used with ProtocolLib.");
|
||||
logger.warn("If you would like to use Floodgate name prefixes, you can enable an experimental "
|
||||
+ "workaround by changing the value 'floodgatePrefixWorkaround' to true in config.yml.");
|
||||
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initializeFloodgate() {
|
||||
@@ -208,7 +187,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
}
|
||||
}
|
||||
|
||||
if (isPluginInstalled("ProtocolLib")) {
|
||||
if (getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(this);
|
||||
}
|
||||
}
|
||||
@@ -257,7 +236,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
* @return the online status or unknown if an error happened, the player isn't online or BungeeCord doesn't send
|
||||
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
|
||||
*/
|
||||
public PremiumStatus getStatus(UUID onlinePlayer) {
|
||||
public @NotNull PremiumStatus getStatus(@NotNull UUID onlinePlayer) {
|
||||
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
@@ -326,18 +305,4 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
}
|
||||
return geyserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send warning messages to log if incompatible plugins are used
|
||||
*/
|
||||
private void dependencyWarnings() {
|
||||
if (isPluginInstalled("floodgate-bukkit")) {
|
||||
logger.warn("We have detected that you are running Floodgate 1.0 which is not supported by the Bukkit "
|
||||
+ "version of FastLogin.");
|
||||
logger.warn("If you would like to use FastLogin with Floodgate, you can download development builds of "
|
||||
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
|
||||
logger.warn("Don't forget to update Geyser to a supported version as well from "
|
||||
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
||||
this.plugin = plugin;
|
||||
this.authmeAPI = AuthMeApi.getInstance();
|
||||
|
||||
if (plugin.getConfig().getBoolean("respectIpLimit", false)) {
|
||||
if (plugin.getCore().getConfig().getBoolean("respectIpLimit", false)) {
|
||||
try {
|
||||
Field managementField = this.authmeAPI.getClass().getDeclaredField("management");
|
||||
managementField.setAccessible(true);
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Responsible for receiving messages from a BungeeCord instance.
|
||||
*
|
||||
* <p>
|
||||
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
|
||||
* the connection is in online mode.
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.common.primitives.Longs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
@@ -51,6 +52,7 @@ import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Base64.Encoder;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
@@ -77,6 +79,8 @@ final class EncryptionUtil {
|
||||
private static final Encoder KEY_ENCODER = Base64.getMimeEncoder(
|
||||
LINE_LENGTH, "\n".getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
private static final int MILLISECOND_SIZE = 8;
|
||||
private static final int UUID_SIZE = 2 * MILLISECOND_SIZE;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -146,7 +150,7 @@ final class EncryptionUtil {
|
||||
return new SecretKeySpec(decrypt(privateKey, sharedKey), "AES");
|
||||
}
|
||||
|
||||
public static boolean verifyClientKey(ClientPublicKey clientKey, Instant verifyTimestamp)
|
||||
public static boolean verifyClientKey(ClientPublicKey clientKey, Instant verifyTimestamp, UUID premiumId)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
||||
if (clientKey.isExpired(verifyTimestamp)) {
|
||||
return false;
|
||||
@@ -155,10 +159,27 @@ final class EncryptionUtil {
|
||||
Signature verifier = Signature.getInstance("SHA1withRSA");
|
||||
// key of the signer
|
||||
verifier.initVerify(MOJANG_SESSION_KEY);
|
||||
verifier.update(toSignable(clientKey).getBytes(StandardCharsets.US_ASCII));
|
||||
verifier.update(toSignable(clientKey, premiumId));
|
||||
return verifier.verify(clientKey.signature());
|
||||
}
|
||||
|
||||
private static byte[] toSignable(ClientPublicKey clientPublicKey, UUID ownerPremiumId) {
|
||||
if (ownerPremiumId == null) {
|
||||
long expiry = clientPublicKey.expiry().toEpochMilli();
|
||||
String encoded = KEY_ENCODER.encodeToString(clientPublicKey.key().getEncoded());
|
||||
return (expiry + "-----BEGIN RSA PUBLIC KEY-----\n" + encoded + "\n-----END RSA PUBLIC KEY-----\n")
|
||||
.getBytes(StandardCharsets.US_ASCII);
|
||||
}
|
||||
|
||||
byte[] keyData = clientPublicKey.key().getEncoded();
|
||||
return ByteBuffer.allocate(keyData.length + UUID_SIZE + MILLISECOND_SIZE)
|
||||
.putLong(ownerPremiumId.getMostSignificantBits())
|
||||
.putLong(ownerPremiumId.getLeastSignificantBits())
|
||||
.putLong(clientPublicKey.expiry().toEpochMilli())
|
||||
.put(keyData)
|
||||
.array();
|
||||
}
|
||||
|
||||
public static boolean verifyNonce(byte[] expected, PrivateKey decryptionKey, byte[] encryptedNonce)
|
||||
throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException,
|
||||
BadPaddingException, InvalidKeyException {
|
||||
@@ -186,12 +207,6 @@ final class EncryptionUtil {
|
||||
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
|
||||
}
|
||||
|
||||
private static String toSignable(ClientPublicKey clientPublicKey) {
|
||||
long expiry = clientPublicKey.expiry().toEpochMilli();
|
||||
String encoded = KEY_ENCODER.encodeToString(clientPublicKey.key().getEncoded());
|
||||
return expiry + "-----BEGIN RSA PUBLIC KEY-----\n" + encoded + "\n-----END RSA PUBLIC KEY-----\n";
|
||||
}
|
||||
|
||||
private static byte[] decrypt(PrivateKey key, byte[] data)
|
||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||
|
||||
/**
|
||||
* Manually inject Floodgate player name prefixes.
|
||||
* <br>
|
||||
* This is used as a workaround, because Floodgate fails to inject
|
||||
* the prefixes when it's used together with ProtocolLib and FastLogin.
|
||||
* <br>
|
||||
* For more information visit: <a href="https://github.com/games647/FastLogin/issues/493">...</a>
|
||||
*/
|
||||
public class ManualNameChange extends PacketAdapter {
|
||||
|
||||
private final FloodgateService floodgate;
|
||||
|
||||
public ManualNameChange(FastLoginBukkit plugin, FloodgateService floodgate) {
|
||||
super(params()
|
||||
.plugin(plugin)
|
||||
.types(START));
|
||||
|
||||
this.plugin = plugin;
|
||||
this.floodgate = floodgate;
|
||||
}
|
||||
|
||||
public static void register(FastLoginBukkit plugin, FloodgateService floodgate) {
|
||||
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
|
||||
ProtocolLibrary.getProtocolManager()
|
||||
.getAsynchronousManager()
|
||||
.registerAsyncHandler(new ManualNameChange(plugin, floodgate))
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
String username = readUsername(packet);
|
||||
|
||||
if (floodgate.getBedrockPlayer(username) == null) {
|
||||
//not a Floodgate player, no need to add a prefix
|
||||
return;
|
||||
}
|
||||
|
||||
packet.setMeta("original_name", username);
|
||||
String prefixedName = FloodgateApi.getInstance().getPlayerPrefix() + username;
|
||||
setUsername(packet, prefixedName);
|
||||
}
|
||||
|
||||
private void setUsername(PacketContainer packet, String name) {
|
||||
if (packet.getGameProfiles().size() > 0) {
|
||||
WrappedGameProfile updatedProfile = new WrappedGameProfile(UUID.randomUUID(), name);
|
||||
packet.getGameProfiles().write(0, updatedProfile);
|
||||
} else {
|
||||
packet.getStrings().write(0, name);
|
||||
}
|
||||
}
|
||||
|
||||
private String readUsername(PacketContainer packet) {
|
||||
if (packet.getGameProfiles().size() > 0) {
|
||||
return packet.getGameProfiles().read(0).getName();
|
||||
} else {
|
||||
return packet.getStrings().read(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,11 +30,15 @@ import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.injector.PacketFilterManager;
|
||||
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.Converters;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
||||
@@ -42,6 +46,10 @@ import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
||||
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.util.AttributeKey;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
@@ -51,22 +59,24 @@ import java.security.SecureRandom;
|
||||
import java.security.SignatureException;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
import lombok.var;
|
||||
import lombok.val;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.ENCRYPTION_BEGIN;
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||
|
||||
public class ProtocolLibListener extends PacketAdapter {
|
||||
|
||||
public static final String SOURCE_META_KEY = "source";
|
||||
|
||||
private final FastLoginBukkit plugin;
|
||||
private final PlayerInjectionHandler handler;
|
||||
|
||||
//just create a new once on plugin enable. This used for verify token generation
|
||||
private final SecureRandom random = new SecureRandom();
|
||||
@@ -85,6 +95,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
this.plugin = plugin;
|
||||
this.antiBotService = antiBotService;
|
||||
this.verifyClientKeys = verifyClientKeys;
|
||||
this.handler = getHandler();
|
||||
}
|
||||
|
||||
public static void register(FastLoginBukkit plugin, AntiBotService antiBotService, boolean verifyClientKeys) {
|
||||
@@ -104,16 +115,20 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFastLoginPacket(packetEvent)) {
|
||||
// this is our own packet
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getLog().info("New packet {} from {}", packetEvent.getPacketType(), packetEvent.getPlayer());
|
||||
|
||||
Player sender = packetEvent.getPlayer();
|
||||
PacketType packetType = packetEvent.getPacketType();
|
||||
if (packetType == START) {
|
||||
|
||||
if (plugin.getFloodgateService() != null) {
|
||||
boolean success = processFloodgateTasks(packetEvent);
|
||||
// don't continue execution if the player was kicked by Floodgate
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
|
||||
InetSocketAddress address = sender.getAddress();
|
||||
@@ -139,12 +154,6 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFastLoginPacket(PacketEvent packetEvent) {
|
||||
return packetEvent.getPacket().getMeta(SOURCE_META_KEY)
|
||||
.map(val -> val.equals(plugin.getName()))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
|
||||
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
|
||||
|
||||
@@ -170,7 +179,8 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
private boolean verifyNonce(Player sender, PacketContainer packet,
|
||||
ClientPublicKey clientPublicKey, byte[] expectedToken) {
|
||||
try {
|
||||
if (MinecraftVersion.atOrAbove(new MinecraftVersion(1, 19, 0))) {
|
||||
if (new MinecraftVersion(1, 19, 0).atOrAbove()
|
||||
&& !(new MinecraftVersion(1, 19, 3).atOrAbove())) {
|
||||
Either<byte[], ?> either = packet.getSpecificModifier(Either.class).read(0);
|
||||
if (clientPublicKey == null) {
|
||||
Optional<byte[]> left = either.left();
|
||||
@@ -212,22 +222,32 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
//remove old data every time on a new login in order to keep the session only for one person
|
||||
plugin.removeSession(player.getAddress());
|
||||
|
||||
if (packetEvent.getPacket().getMeta("original_name").isPresent()) {
|
||||
//username has been injected by ManualNameChange.java
|
||||
username = (String) packetEvent.getPacket().getMeta("original_name").get();
|
||||
}
|
||||
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
var profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter())
|
||||
.optionRead(0);
|
||||
Optional<ClientPublicKey> clientKey;
|
||||
if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
|
||||
// public key sent separate
|
||||
clientKey = Optional.empty();
|
||||
} else {
|
||||
val profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter())
|
||||
.optionRead(0);
|
||||
|
||||
var clientKey = profileKey.flatMap(opt -> opt).flatMap(this::verifyPublicKey);
|
||||
if (verifyClientKeys && !clientKey.isPresent()) {
|
||||
// missing or incorrect
|
||||
// expired always not allowed
|
||||
player.kickPlayer(plugin.getCore().getMessage("invalid-public-key"));
|
||||
plugin.getLog().warn("Invalid public key from player {}", username);
|
||||
return;
|
||||
clientKey = profileKey.flatMap(Function.identity()).flatMap(data -> {
|
||||
Instant expires = data.getExpireTime();
|
||||
PublicKey key = data.getKey();
|
||||
byte[] signature = data.getSignature();
|
||||
return Optional.of(ClientPublicKey.of(expires, key, signature));
|
||||
});
|
||||
|
||||
// start reading from index 1, because 0 is already used by the public key
|
||||
Optional<UUID> sessionUUID = packet.getOptionals(Converters.passthrough(UUID.class)).readSafely(1);
|
||||
if (verifyClientKeys && sessionUUID.isPresent() && clientKey.isPresent()
|
||||
&& verifyPublicKey(clientKey.get(), sessionUUID.get())) {
|
||||
// missing or incorrect
|
||||
// expired always not allowed
|
||||
player.kickPlayer(plugin.getCore().getMessage("invalid-public-key"));
|
||||
plugin.getLog().warn("Invalid public key from player {}", username);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
|
||||
@@ -239,20 +259,12 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
plugin.getScheduler().runAsync(nameCheckTask);
|
||||
}
|
||||
|
||||
private Optional<ClientPublicKey> verifyPublicKey(WrappedProfileKeyData profileKey) {
|
||||
Instant expires = profileKey.getExpireTime();
|
||||
PublicKey key = profileKey.getKey();
|
||||
byte[] signature = profileKey.getSignature();
|
||||
ClientPublicKey clientKey = ClientPublicKey.of(expires, key, signature);
|
||||
private boolean verifyPublicKey(ClientPublicKey clientKey, UUID sessionPremiumUUID) {
|
||||
try {
|
||||
if (EncryptionUtil.verifyClientKey(clientKey, Instant.now())) {
|
||||
return Optional.of(clientKey);
|
||||
}
|
||||
return EncryptionUtil.verifyClientKey(clientKey, Instant.now(), sessionPremiumUUID);
|
||||
} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException ex) {
|
||||
return Optional.empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private String getUsername(PacketContainer packet) {
|
||||
@@ -264,4 +276,56 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
//player.getName() won't work at this state
|
||||
return profile.getName();
|
||||
}
|
||||
|
||||
private static PlayerInjectionHandler getHandler() {
|
||||
PacketFilterManager manager = (PacketFilterManager) ProtocolLibrary.getProtocolManager();
|
||||
FieldAccessor accessor = Accessors.getFieldAccessor(manager.getClass(), PlayerInjectionHandler.class, true);
|
||||
return (PlayerInjectionHandler) accessor.get(manager);
|
||||
}
|
||||
|
||||
private FloodgatePlayer getFloodgatePlayer(Player player) {
|
||||
Channel channel = handler.getChannel(player);
|
||||
AttributeKey<FloodgatePlayer> floodgateAttribute = AttributeKey.valueOf("floodgate-player");
|
||||
return channel.attr(floodgateAttribute).get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reimplementation of the tasks injected Floodgate in ProtocolLib that are not run due to a bug
|
||||
* @see <a href="https://github.com/GeyserMC/Floodgate/issues/143">Issue Floodgate#143</a>
|
||||
* @see <a href="https://github.com/GeyserMC/Floodgate/blob/5d5713ed9e9eeab0f4abdaa9cf5cd8619dc1909b/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java#L121-L175">Floodgate/SpigotDataHandler</a>
|
||||
* @param packetEvent the PacketEvent that won't be processed by Floodgate
|
||||
* @return false if the player was kicked
|
||||
*/
|
||||
private boolean processFloodgateTasks(PacketEvent packetEvent) {
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
Player player = packetEvent.getPlayer();
|
||||
FloodgatePlayer floodgatePlayer = getFloodgatePlayer(player);
|
||||
if (floodgatePlayer == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// kick the player, if necessary
|
||||
Channel channel = handler.getChannel(packetEvent.getPlayer());
|
||||
AttributeKey<String> kickMessageAttribute = AttributeKey.valueOf("floodgate-kick-message");
|
||||
String kickMessage = channel.attr(kickMessageAttribute).get();
|
||||
if (kickMessage != null) {
|
||||
player.kickPlayer(kickMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
// add prefix
|
||||
String username = floodgatePlayer.getCorrectUsername();
|
||||
if (packet.getGameProfiles().size() > 0) {
|
||||
packet.getGameProfiles().write(0,
|
||||
new WrappedGameProfile(floodgatePlayer.getCorrectUniqueId(), username));
|
||||
} else {
|
||||
packet.getStrings().write(0, username);
|
||||
}
|
||||
|
||||
// remove real Floodgate data handler
|
||||
ChannelHandler floodgateHandler = channel.pipeline().get("floodgate_data_handler");
|
||||
channel.pipeline().remove(floodgateHandler);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,12 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
||||
import com.comphenix.protocol.injector.temporary.TemporaryPlayerFactory;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
@@ -196,7 +198,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
}
|
||||
|
||||
//try to get the networkManager from ProtocolLib
|
||||
private Object getNetworkManager() throws IllegalAccessException, ClassNotFoundException {
|
||||
private Object getNetworkManager() throws ClassNotFoundException {
|
||||
Object injectorContainer = TemporaryPlayerFactory.getInjectorFromPlayer(player);
|
||||
|
||||
// ChannelInjector
|
||||
@@ -269,10 +271,9 @@ public class VerifyResponseTask implements Runnable {
|
||||
|
||||
//fake a new login packet in order to let the server handle all the other stuff
|
||||
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey) {
|
||||
//see StartPacketListener for packet information
|
||||
PacketContainer startPacket = new PacketContainer(START);
|
||||
|
||||
if (MinecraftVersion.atOrAbove(new MinecraftVersion(1, 19, 0))) {
|
||||
PacketContainer startPacket;
|
||||
if (new MinecraftVersion(1, 19, 0).atOrAbove()) {
|
||||
startPacket = new PacketContainer(START);
|
||||
startPacket.getStrings().write(0, username);
|
||||
|
||||
EquivalentConverter<WrappedProfileKeyData> converter = BukkitConverters.getWrappedPublicKeyDataConverter();
|
||||
@@ -284,11 +285,14 @@ public class VerifyResponseTask implements Runnable {
|
||||
} else {
|
||||
//uuid is ignored by the packet definition
|
||||
WrappedGameProfile fakeProfile = new WrappedGameProfile(UUID.randomUUID(), username);
|
||||
startPacket.getGameProfiles().write(0, fakeProfile);
|
||||
|
||||
Class<?> profileHandleType = fakeProfile.getHandleType();
|
||||
Class<?> packetHandleType = PacketRegistry.getPacketClassFromType(START);
|
||||
ConstructorAccessor startCons = Accessors.getConstructorAccessorOrNull(packetHandleType, profileHandleType);
|
||||
startPacket = new PacketContainer(START, startCons.invoke(fakeProfile.getHandle()));
|
||||
}
|
||||
|
||||
//we don't want to handle our own packets so ignore filters
|
||||
startPacket.setMeta(ProtocolLibListener.SOURCE_META_KEY, plugin.getName());
|
||||
ProtocolLibrary.getProtocolManager().receiveClientPacket(player, startPacket, true);
|
||||
ProtocolLibrary.getProtocolManager().receiveClientPacket(player, startPacket, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import lombok.Value;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -41,4 +43,13 @@ public class ClientPublicKey {
|
||||
public boolean isExpired(Instant verifyTimestamp) {
|
||||
return !verifyTimestamp.isBefore(expiry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringJoiner(", ", ClientPublicKey.class.getSimpleName() + '[', "]")
|
||||
.add("expiry=" + expiry)
|
||||
.add("key=" + Base64.getEncoder().encodeToString(key.getEncoded()))
|
||||
.add("signature=" + Base64.getEncoder().encodeToString(signature))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.security.SignatureException;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
@@ -93,7 +94,7 @@ class EncryptionUtilTest {
|
||||
|
||||
// Client expires at the exact second mentioned, so use it for verification
|
||||
val expiredTimestamp = clientKey.expiry();
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp));
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp, null));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -109,7 +110,7 @@ class EncryptionUtilTest {
|
||||
val clientKey = ResourceLoader.loadClientKey(clientKeySource);
|
||||
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp));
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -117,7 +118,25 @@ class EncryptionUtilTest {
|
||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
|
||||
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp));
|
||||
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValid191ClientKey() throws Exception {
|
||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
|
||||
val ownerPremiumId = UUID.fromString("0aaa2c13-922a-411b-b655-9b8c08404695");
|
||||
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, ownerPremiumId));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIncorrect191ClientOwner() throws Exception {
|
||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
|
||||
val ownerPremiumId = UUID.fromString("61699b2e-d327-4a01-9f1e-0ea8c3f06bc6");
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, ownerPremiumId));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,7 +178,8 @@ class EncryptionUtilTest {
|
||||
assertEquals(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), sessionHash);
|
||||
}
|
||||
|
||||
private static String getServerHash(CharSequence serverId, SecretKey sharedSecret, PublicKey serverPK) {
|
||||
private static String getServerHash(@SuppressWarnings("SameParameterValue") CharSequence serverId,
|
||||
SecretKey sharedSecret, PublicKey serverPK) {
|
||||
// https://wiki.vg/Protocol_Encryption#Client
|
||||
// sha1 := Sha1()
|
||||
// sha1.update(ASCII encoding of the server id string from Encryption Request)
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.time.Instant;
|
||||
@@ -58,7 +59,7 @@ public class ResourceLoader {
|
||||
) {
|
||||
PemObject pemObject = pemReader.readPemObject();
|
||||
byte[] content = pemObject.getContent();
|
||||
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(content);
|
||||
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(content);
|
||||
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
return (RSAPrivateKey) factory.generatePrivate(privateKeySpec);
|
||||
@@ -88,7 +89,7 @@ public class ResourceLoader {
|
||||
) {
|
||||
PemObject pemObject = pemReader.readPemObject();
|
||||
byte[] content = pemObject.getContent();
|
||||
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
|
||||
KeySpec pubKeySpec = new X509EncodedKeySpec(content);
|
||||
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
return (RSAPublicKey) factory.generatePublic(pubKeySpec);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"expires_at": "2022-07-29T12:57:39.011Z",
|
||||
"key": "-----BEGIN RSA PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtYOUXdid0c09/eYoseLf8qG9fKQ/G2DY9wlSyEZaFMflwZ8ZpLFYigxzfaimpT3A5cbFIdIH2W2sYl5PwsKSs128GBh/rxXUEZlLkIkS+EfxyuMp9ITclxAjCqvFgfJbZHugtB9Ofi6knCEEgjFwMDh2efdpOXkCxtHuPFfnVzDJBbHWdlCCtJesMAnA2jCT7CqCwsi7sW2QxuTarqHP/cHKiBeBIu/SngGUB6eWmvAwERW5x2D+O26w8Z5sQCND3xQ4D868RALiPNG94TyKoJV+jKi0tTUmjGGs/1ksbSGDQb5xqIH0NYKZhoZrczYPNmJX4k7g5BA5RHX8AGORaQIDAQAB\n-----END RSA PUBLIC KEY-----\n",
|
||||
"signature": "Fto/GDqEMTWpNrktWSi3tnP3ZZlo8r4Jled/5PKYRvaL/zksfjB2RK2O8pZL+w5mI2VAViTVAQmSJEF2o/BCb2L0zXp3/hC9VhZj5NTVi4KbHfnfMorj7/WJP2vvMgVxIxgLb3EEQXGS2Mmo0w2ikUVauwXgLWECvVt10KAZnTAWNIvpM8NUoZ2oCCxVimYHBtlwWQ7WvowAatP4ypa7fo3xhQg8Im1hvQDsFTNp58pgnd7l3l99xLj1uYOUJM06HGZJ/Xd0kzzJz44Csh4m50Q0RP4Nq5L+fYPeUx990Z1r1lw0sSayk+vA2Qnxgbs/z6KgkxfhBg7oOlp4ykl9cLC2kA/LdV6igqsdr/KoP4GWxwTA7RgQbhMkDFdmIg1W+gh3XqwASFQK2BAN/eAfmDTf8u9BtOEF7Ehn9uPOaiFiGztyaHxXNIkVSPTG2GXMFSijnd3Ms28jHYVY/67INTnDRmN0//KzBAoTRMe1S5idai19kug4EUVIRKDziipowzCPdbD18trdQGpK0dYOrw9XQiQd4N4V3eItpyAULGiZd8KcjgKo4orqgsUfNyhLI1keig7TyJUE3FkBOfX4hlZBm7Q/Wq4hwarlc5yZIjhsuivKV/q4tcnYYPwjP7kNMRsIApWG+yHmSIo8QfZhBiPxvtWSSLZgoFgnlxfaEko="
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
||||
<!-- Located in META-INF/services -->
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
@@ -104,11 +105,6 @@
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>spigotplugins-repo</id>
|
||||
<url>https://maven.gamestrike.de/mvn/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
@@ -173,11 +169,7 @@
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
@@ -185,7 +177,7 @@
|
||||
|
||||
<!-- Bedrock player bridge -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<groupId>org.geysermc.geyser</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
@@ -199,10 +191,16 @@
|
||||
|
||||
<!-- We need the API, but it was excluded above -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<groupId>org.geysermc.geyser</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Login plugin-->
|
||||
@@ -213,18 +211,5 @@
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/lib/BungeeAuth-1.4.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.xxschrandxx.bca</groupId>
|
||||
<artifactId>BungeeCordAuthenticator</artifactId>
|
||||
<version>0.0.3</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package com.github.games647.fastlogin.bungee;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
|
||||
import com.github.games647.fastlogin.bungee.hook.BungeeCordAuthenticatorBungeeHook;
|
||||
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
|
||||
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
@@ -47,7 +46,7 @@ import com.google.common.io.ByteStreams;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
@@ -129,8 +128,9 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
|
||||
private void registerHook() {
|
||||
try {
|
||||
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Arrays.asList(
|
||||
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class);
|
||||
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Collections.singletonList(
|
||||
BungeeAuthHook.class
|
||||
);
|
||||
|
||||
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
|
||||
String pluginName = clazz.getSimpleName();
|
||||
|
||||
@@ -36,9 +36,9 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
/**
|
||||
* GitHub:
|
||||
* <a href="https://github.com/vik1395/BungeeAuth-Minecraft">...</a>
|
||||
*
|
||||
* <p>
|
||||
* Project page:
|
||||
*
|
||||
* <p>
|
||||
* Spigot:
|
||||
* <a href="https://www.spigotmc.org/resources/bungeeauth.493/">...</a>
|
||||
*/
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.bungee.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import de.xxschrandxx.bca.bungee.BungeeCordAuthenticatorBungee;
|
||||
import de.xxschrandxx.bca.bungee.api.BungeeCordAuthenticatorBungeeAPI;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
/**
|
||||
* GitHub:
|
||||
* <a href="https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator">...</a>
|
||||
* <p>
|
||||
* Project page:
|
||||
* <p>
|
||||
* Spigot: <a href="https://www.spigotmc.org/resources/bungeecordauthenticator.87669/">...</a>
|
||||
*/
|
||||
public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlayer> {
|
||||
|
||||
public final BungeeCordAuthenticatorBungeeAPI api;
|
||||
|
||||
public BungeeCordAuthenticatorBungeeHook(FastLoginBungee plugin) {
|
||||
api = ((BungeeCordAuthenticatorBungee) plugin.getProxy().getPluginManager()
|
||||
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
|
||||
plugin.getLog().info("BungeeCordAuthenticatorHook | Hooked successful!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(ProxiedPlayer player) {
|
||||
if (api.isAuthenticated(player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
api.setAuthenticated(player);
|
||||
} catch (SQLException sqlEx) {
|
||||
api.getLogger().log(Level.WARNING, "Failed to force login", sqlEx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(String playerName) {
|
||||
try {
|
||||
return api.getSQL().checkPlayerEntry(playerName);
|
||||
} catch (SQLException sqlEx) {
|
||||
api.getLogger().log(Level.WARNING, "Failed to check registration", sqlEx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(ProxiedPlayer player, String password) {
|
||||
try {
|
||||
return api.createPlayerEntry(player, password);
|
||||
} catch (SQLException sqlEx) {
|
||||
api.getLogger().log(Level.WARNING, "Failed to force register", sqlEx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,7 @@
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<property name="ignorePattern" value="^ *\* *@see.+$"/>
|
||||
</module>
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
|
||||
39
core/pom.xml
39
core/pom.xml
@@ -25,7 +25,7 @@
|
||||
SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>luck-repo</id>
|
||||
<url>https://ci.lucko.me/plugin/repository/everything</url>
|
||||
<url>https://ci.lucko.me/plugin/repository/everything/</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
@@ -70,7 +70,7 @@
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>4.0.3</version>
|
||||
<version>5.0.2-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
|
||||
<!-- We will use the api provided by the jdk14 dependency -->
|
||||
@@ -85,14 +85,14 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>2.0.0-alpha7</version>
|
||||
<version>2.0.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>1.19-R0.1-20220702.004052-16</version>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
@@ -109,11 +109,7 @@
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
@@ -121,7 +117,7 @@
|
||||
|
||||
<!-- Bedrock player bridge -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<groupId>org.geysermc.geyser</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
@@ -135,17 +131,23 @@
|
||||
|
||||
<!-- We need the API, but it was excluded above -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<groupId>org.geysermc.geyser</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Common component for contacting the Mojang API-->
|
||||
<dependency>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>craftapi</artifactId>
|
||||
<version>0.5.3</version>
|
||||
<version>0.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
|
||||
@@ -182,7 +184,14 @@
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.10</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>[3.36,)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.mojang;
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.github.games647.craftapi.model.auth.Verification;
|
||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||
@@ -57,6 +57,6 @@ public class AntiBotService {
|
||||
|
||||
Block,
|
||||
|
||||
Continue;
|
||||
Continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public interface AuthPlugin<P> {
|
||||
|
||||
/**
|
||||
* Login the premium (paid account) player after the player joined successfully the server.
|
||||
*
|
||||
* <p>
|
||||
* <strong>This operation will be performed async while the player successfully
|
||||
* joined the server.</strong>
|
||||
*
|
||||
@@ -48,17 +48,17 @@ public interface AuthPlugin<P> {
|
||||
|
||||
/**
|
||||
* Forces a register in order to protect the paid account.
|
||||
*
|
||||
* <p>
|
||||
* <strong>This operation will be performed async while the player successfully
|
||||
* joined the server.</strong>
|
||||
*
|
||||
* <p>
|
||||
* After a successful registration the player should be logged
|
||||
* in too.
|
||||
*
|
||||
* <p>
|
||||
* The method will be called only for premium accounts.
|
||||
* So it's recommended to set additionally premium property
|
||||
* if possible.
|
||||
*
|
||||
* <p>
|
||||
* Background: If we don't register an account, cracked players
|
||||
* could steal the unregistered account from the paid
|
||||
* player account
|
||||
@@ -71,11 +71,11 @@ public interface AuthPlugin<P> {
|
||||
|
||||
/**
|
||||
* Checks whether an account exists for this player name.
|
||||
*
|
||||
* <p>
|
||||
* This check should check if a cracked player account exists,
|
||||
* so we can be sure the premium player doesn't steal the account
|
||||
* of that player.
|
||||
*
|
||||
* <p>
|
||||
* This operation will be performed async while the player is
|
||||
* connecting.
|
||||
*
|
||||
|
||||
@@ -99,23 +99,11 @@ public class FloodgateService extends BedrockService<FloodgatePlayer> {
|
||||
* The FloodgateApi does not support querying players by name, so this function
|
||||
* iterates over every online FloodgatePlayer and checks if the requested
|
||||
* username can be found
|
||||
* <br>
|
||||
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
|
||||
*
|
||||
* @param prefixedUsername the name of the player with the prefix appended
|
||||
* @return FloodgatePlayer if found, null otherwise
|
||||
*/
|
||||
public FloodgatePlayer getBedrockPlayer(String prefixedUsername) {
|
||||
//prefixes are broken with ProtocolLib, so fall back to name checks without prefixes
|
||||
//this should be removed if #493 gets fixed
|
||||
if (core.getPlugin().isPluginInstalled("ProtocolLib")) {
|
||||
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
||||
if (floodgatePlayer.getUsername().equals(prefixedUsername)) {
|
||||
return floodgatePlayer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
||||
if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) {
|
||||
return floodgatePlayer;
|
||||
|
||||
@@ -31,8 +31,8 @@ import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.network.AuthType;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
|
||||
public class GeyserService extends BedrockService<GeyserSession> {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class GeyserService extends BedrockService<GeyserSession> {
|
||||
super(core);
|
||||
this.geyser = geyser;
|
||||
this.core = core;
|
||||
this.authType = GeyserImpl.getInstance().getConfig().getRemote().getAuthType();
|
||||
this.authType = GeyserImpl.getInstance().getConfig().getRemote().authType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +65,12 @@ public class GeyserService extends BedrockService<GeyserSession> {
|
||||
|
||||
@Override
|
||||
public GeyserSession getBedrockPlayer(String username) {
|
||||
return geyser.connectionByName(username);
|
||||
for (GeyserSession gSess : geyser.getSessionManager().getAllSessions()) {
|
||||
if (username.equals(gSess.getClientData().getUsername())) {
|
||||
return gSess;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,4 +48,12 @@ public class NamespaceKey {
|
||||
public static String getCombined(String namespace, String key) {
|
||||
return new NamespaceKey(namespace, key).combined;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ package com.github.games647.fastlogin.core.shared;
|
||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
|
||||
import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import com.github.games647.fastlogin.core.ProxyAgnosticMojangResolver;
|
||||
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
||||
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
||||
import com.github.games647.fastlogin.core.antibot.RateLimiter;
|
||||
@@ -35,12 +36,10 @@ import com.github.games647.fastlogin.core.antibot.TickingRateLimiter;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
||||
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
||||
import com.github.games647.fastlogin.core.mojang.ProxyAgnosticMojangResolver;
|
||||
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
||||
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
||||
import com.google.common.base.Ticker;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -66,8 +65,6 @@ import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static java.util.function.Function.identity;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
@@ -128,8 +125,8 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
antiBot = createAntiBotService(config.getSection("anti-bot"));
|
||||
Set<Proxy> proxies = config.getStringList("proxies")
|
||||
.stream()
|
||||
.map(HostAndPort::fromString)
|
||||
.map(proxy -> new InetSocketAddress(proxy.getHost(), proxy.getPort()))
|
||||
.map(proxy -> proxy.split(":"))
|
||||
.map(proxy -> new InetSocketAddress(proxy[0], Integer.parseInt(proxy[1])))
|
||||
.map(sa -> new Proxy(Type.HTTP, sa))
|
||||
.collect(toSet());
|
||||
|
||||
@@ -224,20 +221,15 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
}
|
||||
|
||||
public boolean setupDatabase() {
|
||||
String driver = config.getString("driver");
|
||||
if (!checkDriver(driver)) {
|
||||
return false;
|
||||
}
|
||||
String type = config.getString("driver");
|
||||
|
||||
HikariConfig databaseConfig = new HikariConfig();
|
||||
databaseConfig.setDriverClassName(driver);
|
||||
|
||||
String database = config.getString("database");
|
||||
|
||||
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
||||
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
||||
|
||||
if (driver.contains("sqlite")) {
|
||||
if (type.contains("sqlite")) {
|
||||
storage = new SQLiteStorage(this, database, databaseConfig);
|
||||
} else {
|
||||
String host = config.get("host", "");
|
||||
@@ -256,7 +248,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
|
||||
databaseConfig.setUsername(config.get("username", ""));
|
||||
databaseConfig.setPassword(config.getString("password"));
|
||||
storage = new MySQLStorage(this, driver, host, port, database, databaseConfig, useSSL);
|
||||
storage = new MySQLStorage(this, type, host, port, database, databaseConfig, useSSL);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -268,20 +260,6 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkDriver(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException notFoundEx) {
|
||||
Logger log = plugin.getLog();
|
||||
log.warn("This driver {} is not supported on this platform", className);
|
||||
log.warn("Please choose either MySQL (Spigot, BungeeCord), SQLite (Spigot, Sponge) or "
|
||||
+ "MariaDB (Sponge, Velocity)", notFoundEx);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Configuration getConfig() {
|
||||
return config;
|
||||
}
|
||||
@@ -290,6 +268,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
return passwordGenerator;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setPasswordGenerator(PasswordGenerator<P> passwordGenerator) {
|
||||
this.passwordGenerator = passwordGenerator;
|
||||
}
|
||||
|
||||
@@ -91,10 +91,10 @@ public abstract class LoginSession {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringJoiner(", ", LoginSession.class.getSimpleName() + "[", "]")
|
||||
return new StringJoiner(", ", LoginSession.class.getSimpleName() + '[', "]")
|
||||
.add("profile=" + profile)
|
||||
.add("requestUsername='" + requestUsername + "'")
|
||||
.add("username='" + username + "'")
|
||||
.add("requestUsername='" + requestUsername + '\'')
|
||||
.add("username='" + username + '\'')
|
||||
.add("uuid=" + uuid)
|
||||
.add("registered=" + registered)
|
||||
.toString();
|
||||
|
||||
@@ -30,11 +30,43 @@ import com.zaxxer.hikari.HikariConfig;
|
||||
|
||||
public class MySQLStorage extends SQLStorage {
|
||||
|
||||
private static final String JDBC_PROTOCOL = "jdbc:";
|
||||
private static final String MYSQL_DRIVER = "com.mysql.cj.jdbc.Driver";
|
||||
private static final String MARIADB_DRIVER = "fastlogin.mariadb.jdbc.Driver";
|
||||
|
||||
public MySQLStorage(FastLoginCore<?, ?, ?> core, String driver, String host, int port, String database,
|
||||
HikariConfig config, boolean useSSL) {
|
||||
super(core,
|
||||
buildJDBCUrl(driver, host, port, database),
|
||||
setParams(config, useSSL));
|
||||
super(core, setParams(config, driver, host, port, database, useSSL));
|
||||
}
|
||||
|
||||
private static HikariConfig setParams(HikariConfig config,
|
||||
String driver, String host, int port, String database,
|
||||
boolean useSSL) {
|
||||
if ("mysql".equalsIgnoreCase(driver.trim())) {
|
||||
config.setDriverClassName(MYSQL_DRIVER);
|
||||
} else if ("mariadb".equalsIgnoreCase(driver.trim())) {
|
||||
config.setDriverClassName(MARIADB_DRIVER);
|
||||
} else {
|
||||
config.setDriverClassName(driver);
|
||||
}
|
||||
|
||||
// Require SSL on the server if requested in config - this will also verify certificate
|
||||
// Those values are deprecated in favor of sslMode
|
||||
config.addDataSourceProperty("useSSL", useSSL);
|
||||
config.addDataSourceProperty("requireSSL", useSSL);
|
||||
|
||||
//enable leak detection of holding connections
|
||||
config.setLeakDetectionThreshold(10_000);
|
||||
|
||||
// adding paranoid, hides hostname, username, version and so
|
||||
// could be useful for hiding server details
|
||||
config.addDataSourceProperty("paranoid", true);
|
||||
|
||||
config.setJdbcUrl(JDBC_PROTOCOL + buildJDBCUrl(driver, host, port, database));
|
||||
|
||||
// enable MySQL specific optimizations
|
||||
// addPerformanceProperties(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
private static String buildJDBCUrl(String driver, String host, int port, String database) {
|
||||
@@ -46,21 +78,6 @@ public class MySQLStorage extends SQLStorage {
|
||||
return protocol + "://" + host + ':' + port + '/' + database;
|
||||
}
|
||||
|
||||
private static HikariConfig setParams(HikariConfig config, boolean useSSL) {
|
||||
// Require SSL on the server if requested in config - this will also verify certificate
|
||||
// Those values are deprecated in favor of sslMode
|
||||
config.addDataSourceProperty("useSSL", useSSL);
|
||||
config.addDataSourceProperty("requireSSL", useSSL);
|
||||
|
||||
// adding paranoid, hides hostname, username, version and so
|
||||
// could be useful for hiding server details
|
||||
config.addDataSourceProperty("paranoid", true);
|
||||
|
||||
// enable MySQL specific optimizations
|
||||
addPerformanceProperties(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
private static void addPerformanceProperties(HikariConfig config) {
|
||||
// disabled by default - will return the same prepared statement instance
|
||||
config.addDataSourceProperty("cachePrepStmts", true);
|
||||
@@ -71,7 +88,7 @@ public class MySQLStorage extends SQLStorage {
|
||||
// default false - available in newer versions caches the statements server-side
|
||||
config.addDataSourceProperty("useServerPrepStmts", true);
|
||||
// default false - prefer use of local values for autocommit and
|
||||
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
|
||||
// transaction isolation (alwaysSendSetIsolation) should only be enabled if we always use the set* methods
|
||||
// instead of raw SQL
|
||||
// https://forums.mysql.com/read.php?39,626495,626512
|
||||
config.addDataSourceProperty("useLocalSessionState", true);
|
||||
|
||||
@@ -45,8 +45,6 @@ import static java.sql.Statement.RETURN_GENERATED_KEYS;
|
||||
|
||||
public abstract class SQLStorage implements AuthStorage {
|
||||
|
||||
private static final String JDBC_PROTOCOL = "jdbc:";
|
||||
|
||||
protected static final String PREMIUM_TABLE = "premium";
|
||||
protected static final String CREATE_TABLE_STMT = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
|
||||
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||
@@ -70,7 +68,7 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
protected final FastLoginCore<?, ?, ?> core;
|
||||
protected final HikariDataSource dataSource;
|
||||
|
||||
public SQLStorage(FastLoginCore<?, ?, ?> core, String jdbcURL, HikariConfig config) {
|
||||
public SQLStorage(FastLoginCore<?, ?, ?> core, HikariConfig config) {
|
||||
this.core = core;
|
||||
config.setPoolName(core.getPlugin().getName());
|
||||
|
||||
@@ -79,7 +77,6 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
config.setThreadFactory(platformThreadFactory);
|
||||
}
|
||||
|
||||
config.setJdbcUrl(JDBC_PROTOCOL + jdbcURL);
|
||||
this.dataSource = new HikariDataSource(config);
|
||||
}
|
||||
|
||||
@@ -146,11 +143,12 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
|
||||
@Override
|
||||
public void save(StoredProfile playerProfile) {
|
||||
try (Connection con = dataSource.getConnection()) {
|
||||
String uuid = playerProfile.getOptId().map(UUIDAdapter::toMojangId).orElse(null);
|
||||
|
||||
playerProfile.getSaveLock().lock();
|
||||
try {
|
||||
String uuid = playerProfile.getOptId().map(UUIDAdapter::toMojangId).orElse(null);
|
||||
core.getPlugin().getLog().info("Before Lock");
|
||||
synchronized (playerProfile) {
|
||||
core.getPlugin().getLog().info("Inside Lock - Before acquiring connection");
|
||||
try (Connection con = dataSource.getConnection()) {
|
||||
core.getPlugin().getLog().info("Acquired connection");
|
||||
if (playerProfile.isSaved()) {
|
||||
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
|
||||
saveStmt.setString(1, uuid);
|
||||
@@ -177,12 +175,14 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
playerProfile.getSaveLock().unlock();
|
||||
} catch (SQLException ex) {
|
||||
core.getPlugin().getLog().error("Failed to save playerProfile {}", playerProfile, ex);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
core.getPlugin().getLog().error("Failed to save playerProfile {}", playerProfile, ex);
|
||||
|
||||
core.getPlugin().getLog().info("Released connection");
|
||||
}
|
||||
|
||||
core.getPlugin().getLog().info("Released lock");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,26 +37,38 @@ import java.util.UUID;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.sqlite.JDBC;
|
||||
import org.sqlite.SQLiteConfig;
|
||||
|
||||
public class SQLiteStorage extends SQLStorage {
|
||||
|
||||
private static final String SQLITE_DRIVER = "org.sqlite.SQLiteDataSource";
|
||||
private final Lock lock = new ReentrantLock();
|
||||
|
||||
public SQLiteStorage(FastLoginCore<?, ?, ?> core, String databasePath, HikariConfig config) {
|
||||
super(core,
|
||||
"sqlite://" + replacePathVariables(core.getPlugin(), databasePath),
|
||||
setParams(config));
|
||||
super(core, setParams(config, replacePathVariables(core.getPlugin(), databasePath)));
|
||||
}
|
||||
|
||||
private static HikariConfig setParams(HikariConfig config) {
|
||||
private static HikariConfig setParams(HikariConfig config, String path) {
|
||||
config.setDataSourceClassName(SQLITE_DRIVER);
|
||||
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setMaximumPoolSize(1);
|
||||
|
||||
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||
// format strings retrieved by the timestamp column to match them from MySQL
|
||||
config.addDataSourceProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
|
||||
config.addDataSourceProperty("url", JDBC.PREFIX + path);
|
||||
|
||||
// TODO: test first for compatibility
|
||||
// config.addDataSourceProperty("date_precision", "seconds");
|
||||
// a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||
// format strings retrieved by the timestamp column to match them from MySQL
|
||||
// vs the default: yyyy-MM-dd HH:mm:ss.SSS
|
||||
try {
|
||||
SQLiteConfig.class.getDeclaredMethod("setDateStringFormat", String.class);
|
||||
|
||||
SQLiteConfig sqLiteConfig = new SQLiteConfig();
|
||||
sqLiteConfig.setDateStringFormat("yyyy-MM-dd HH:mm:ss");
|
||||
config.addDataSourceProperty("config", sqLiteConfig);
|
||||
} catch (NoSuchMethodException noSuchMethodException) {
|
||||
// Versions below this driver version do set the default timestamp value, so this change is not necessary
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -202,8 +202,8 @@ mojang-request-limit: 600
|
||||
# https://github.com/games647/FastLogin/issues/85
|
||||
auto-register-unknown: false
|
||||
|
||||
# This disables the auto login from fastlogin. So a premium (like a paid account) authentication is requested, but
|
||||
# the player won't be auto logged into the account.
|
||||
# By setting this option to false, you can disable the auto login from fastlogin. So a premium (like a paid account)
|
||||
# authentication is requested, but the player won't be auto logged into the account from the auth plugin.
|
||||
#
|
||||
# This can be used as 2Factor authentication for better security of your accounts. A hacker then needs both passwords.
|
||||
# The password of your Minecraft and the password to login in with your auth plugin
|
||||
@@ -236,8 +236,6 @@ autoLoginFloodgate: false
|
||||
#
|
||||
# To prevent conflicts from two different players having the same name, it is highly recommended using a
|
||||
# 'username-prefix' in floodgate/config.yml
|
||||
# Note: 'username-prefix' is currently broken when used with FastLogin and ProtocolLib.
|
||||
# A solution to this is to enable 'floodgatePrefixWorkaround' below.
|
||||
#
|
||||
# Possible values:
|
||||
# false: Kick Bedrock players, if they are using an existing Premium Java account's name
|
||||
@@ -264,14 +262,6 @@ allowFloodgateNameConflict: false
|
||||
# Enabling this might lead to people gaining unauthorized access to other's accounts!
|
||||
autoRegisterFloodgate: false
|
||||
|
||||
# Make FastLogin inject the Floodgate name prefixes, instead of Floodgate.
|
||||
# This can fix prefixes, if you are using Floodgate alongside ProtocolLib.
|
||||
# If either of those plugins are not installed, this option will have no effect.
|
||||
# For more information visit: https://github.com/games647/FastLogin/issues/493
|
||||
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
|
||||
# Enabling this might lead to people gaining unauthorized access to other's accounts!
|
||||
floodgatePrefixWorkaround: false
|
||||
|
||||
# This option resembles the vanilla configuration option 'enforce-secure-profile' in the 'server.properties' file.
|
||||
# It verifies if the incoming cryptographic key in the login request from the player is signed by Mojang. This key
|
||||
# is necessary for servers where you or other in-game players want to verify that a chat message sent and signed by
|
||||
@@ -285,14 +275,14 @@ verifyClientKeys: false
|
||||
# Recommended is the use of MariaDB (a better version of MySQL)
|
||||
|
||||
# Single file SQLite database
|
||||
driver: 'org.sqlite.JDBC'
|
||||
driver: 'sqlite'
|
||||
# File location
|
||||
database: '{pluginDir}/FastLogin.db'
|
||||
|
||||
# MySQL/MariaDB
|
||||
# If you want to enable it, uncomment only the lines below; this not this line.
|
||||
# If on velocity use 'fastlogin.mariadb.jdbc.Driver' as driver
|
||||
#driver: 'com.mysql.jdbc.Driver'
|
||||
# If on velocity use 'mariadb' as the driver
|
||||
#driver: 'mysql'
|
||||
#host: '127.0.0.1'
|
||||
#port: 3306
|
||||
#database: 'fastlogin'
|
||||
|
||||
14
pom.xml
14
pom.xml
@@ -25,7 +25,7 @@
|
||||
SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven.compiler.release>${java.version}</maven.compiler.release>
|
||||
|
||||
<floodgate.version>2.2.0-SNAPSHOT</floodgate.version>
|
||||
<geyser.version>2.0.0-SNAPSHOT</geyser.version>
|
||||
<floodgate.version>development-2.2.2-SNAPSHOT</floodgate.version>
|
||||
<geyser.version>2.1.0-SNAPSHOT</geyser.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@@ -141,7 +141,7 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.3.1</version>
|
||||
<version>10.9.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -187,14 +187,14 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.24</version>
|
||||
<version>1.18.26</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.2</version>
|
||||
<version>5.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>4.6.1</version>
|
||||
<version>5.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>3.0.6</version>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -46,9 +46,9 @@ import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelRegistrar;
|
||||
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -159,7 +159,7 @@ public class FastLoginVelocity implements PlatformPlugin<CommandSource> {
|
||||
return server;
|
||||
}
|
||||
|
||||
public void sendPluginMessage(RegisteredServer server, ChannelMessage message) {
|
||||
public void sendPluginMessage(ChannelMessageSink server, ChannelMessage message) {
|
||||
if (server != null) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
message.writeTo(dataOutput);
|
||||
|
||||
@@ -48,7 +48,7 @@ public class ForceLoginTask
|
||||
|
||||
private final RegisteredServer server;
|
||||
|
||||
//treat player as if they had a premium account, even when they don't used to do auto login for Floodgate
|
||||
//treat player as if they had a premium account, even when they don't use to do auto login for Floodgate
|
||||
private final boolean forcedOnlineMode;
|
||||
|
||||
public ForceLoginTask(FastLoginCore<Player, CommandSource, FastLoginVelocity> core,
|
||||
|
||||
Reference in New Issue
Block a user