Compare commits

..

5 Commits

Author SHA1 Message Date
games647
c21c7eaeec Generalize references from Bungee to proxies 2021-03-17 11:24:16 +01:00
games647
804a0aec4b Isolate modules in their packages 2021-03-17 11:19:04 +01:00
games647
13bc92f6c3 Migrate to session manager 2021-03-15 14:22:38 +01:00
games647
e88f2e7f8e Fail safely if BungeeCord implementation specific classes are not found 2021-03-15 13:40:28 +01:00
games647
337e01e537 Put configuration values into extra lines to highlight the environment
They are not configuration options

Related #488
2021-03-10 16:50:16 +01:00
128 changed files with 1428 additions and 6483 deletions

41
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,41 @@
---
name: Bug report
about: Something isn't working
title: ''
labels: 'bug'
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!)
### What behaviour is observed:
[//]: # (What happened?)
### What behaviour is expected:
[//]: # (What did you expect?)
### Steps/models to reproduce:
[//]: # (The actions that cause the issue. Please explain it in detail)
### Screenshots (if applicable)
[//]: # (You can drop the files here directly)
### Plugin list:
[//]: # (This can be found by running `/pl`)
### Environment description
[//]: # (Server software with exact version number, Minecraft version, SQLite/MySQL/MariaDB, ...)
### Plugin version or build number (don't write latest):
[//]: # (This can be found by running `/version plugin-name`.)
### Server Log:
[//]: # (No images please - only the textual representation)
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of the error, stacktrace or the complete log (if any)
### Configuration:
[//]: # (No images please - only the textual representation)
[//]: # (remember to delete any sensitive data)
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of your config.yml file

View File

@@ -1,67 +0,0 @@
name: 🐞 Bug Report
description: Something isn't working, broken, not expected behavior
labels: [bug]
body:
- type: markdown
attributes:
value: |
This ticket is about bugs, so broken, not expected behavior. Feedback about this form is appreciated.
- type: textarea
attributes:
label: What happened?
description: What behavior is observed?
validations:
required: true
- type: textarea
attributes:
label: What did you expect?
description: What behavior is expected?
- type: textarea
attributes:
label: Steps to reproduce
description: The actions that cause the issues. Please explain it in detail.
- type: input
attributes:
label: Plugin list
description: This can be found by running `/pl`
placeholder: AuthMe, ProtocolLib, ...
- type: input
attributes:
label: Configuration file
description: |
Link to the contents of your config.yml file.
You can use [GitHub](https://gist.github.com/), [Hastebin](https://hastebin.com) or similar for that.
placeholder: https://gist.github.com/games647/88c4439e1cd7810f21318b1b24a04ee0
- type: textarea
attributes:
label: Server log
description: The error, stacktrace or link the complete log. You can use the links above for long versions.
placeholder: https://hastebin.com/ / https://gist.github.com/
- type: input
attributes:
label: Plugin version
description: Plugin version or build number. This can be found by running `/version plugin-name`
placeholder: v3.1-SNAPSHOT-570b321
validations:
required: true
- type: dropdown
attributes:
label: Platform
description: Server software - choose your proxy software if you have multiple servers
options:
- Spigot
- BungeeCord
- Velocity
validations:
required: true
- type: checkboxes
attributes:
label: Relevance
description: Check list for previous tickets
options:
- label: I tried the latest build (build refers to development builds not necessary a release version)
required: true
- label: |
I checked for existing tickets -
If there are, please vote them with a thumps reaction and not create new ones
required: true

View File

@@ -1,12 +0,0 @@
# General configuration for issue templates
# Allow issues without a template
#blank_issues_enabled: false
# Extra section on creating issues to redirect to another site
contact_links:
- name: 📌 Questions
url: https://github.com/games647/FastLogin/discussions
about:
You want to ask something - general questions. Example includes how to set it up or how it is working internally

View File

@@ -1,5 +1,5 @@
---
name: 💡 Enhancement request
name: Enhancement request
about: New feature or change request
title: ''
labels: 'enhancement'
@@ -8,9 +8,6 @@ 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 [...])

10
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Question
about: You want to ask something
title: ''
labels: 'question'
assignees: ''
---

View File

@@ -1,35 +0,0 @@
version: 2
updates:
# Updates for workflow files
- package-ecosystem: "github-actions"
# Workflow files stored in the
# default location of `.github/workflows`
directory: "/"
schedule:
interval: "monthly"
# Maven project
- package-ecosystem: maven
directory: "/"
schedule:
interval: weekly
ignore:
- dependency-name: com.google.code.gson:gson
versions:
- "> 2.2.4"
- dependency-name: com.google.guava
- dependency-name: me.clip:placeholderapi
versions:
- "> 2.10.8, < 2.11"
- dependency-name: net.md-5:bungeecord-config
versions:
- "> 1.12-SNAPSHOT"
- dependency-name: de.xxschrandxx.bca:BungeeCordAuthenticator
versions:
- 0.0.3
- dependency-name: com.zaxxer:HikariCP
versions:
- 4.0.0
- 4.0.2
- 4.0.3

View File

@@ -1,67 +0,0 @@
# GitHub automatic code security scanning using CodeQL
# Human-readable name in the actions tab
name: "CodeQL"
on:
# Scan only for push on the primary branch for now
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
# job i
analyze:
# Display name
name: Analyze
# Environment
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
# Languages to scan
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
# Use Java 16+, because it's minimum required version by Geyser
java-version: 17
cache: 'maven'
# 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.1
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
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -1,43 +1,49 @@
# Automatically build, run unit and integration tests to detect errors early (CI provided by GitHub)
# including making pull requests review easier
# Human-readable name in the actions tab
# Human readable name in the actions tab
name: Java CI
# Build on every pull request regardless of the branch
# Build on every push and 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
- pull_request
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 newest OS
runs-on: ubuntu-latest
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v3
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v2.3.4
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
# Use Java 16+, because it's minimum required version by Geyser
java-version: 17
cache: 'maven'
# Cache artifacts - however this has the downside that we don't get notified of
# artifact resolution failures like invalid repository
# Nevertheless the repositories should be more stable and it makes no sense to pull
# a same version every time
# A dry run would make more sense
- uses: actions/cache@v2.1.4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-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 --no-snapshot-updates --strict-checksums --file pom.xml
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v1.4.3
with:
# Use Java 11, because it's minimum required version
java-version: 11
# 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 package test --batch-mode --no-snapshot-updates --strict-checksums --file pom.xml

3
.gitignore vendored
View File

@@ -13,9 +13,6 @@ nb-configuration.xml
*.iws
.idea/
# VSCode
.vscode/
# Maven
target/
pom.xml.versionsBackup

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2022 games647 and contributors
Copyright (c) 2015-2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -12,7 +12,7 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
* Forge/Sponge message support
* Premium UUID support
* Forward skins
* Detect username changed and will update the existing database record
* Detect user name changed and will update the existing database record
* BungeeCord support
* Auto register new premium players
* Plugin: ProtocolSupport is supported and can be used as an alternative to ProtocolLib
@@ -23,17 +23,21 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
## Issues
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
can be voted up by adding up vote to the original post. Closing issues means that they are marked as resolved. Comments
are still allowed and it could be re-opened.
## Development builds
Development builds contain the latest changes from the Source-Code. They are bleeding edge and could introduce new bugs,
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
side on `Changes`, you can see iterative change sets leading to a specific build.
Development builds of this project can be acquired at the provided CI (continuous integration) server. It contains the
latest changes from the Source-Code in preparation for the following release. This means they could contain new
features, bug fixes and other changes since the last release.
You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogin/
They **could** contain new bugs and are likely to be less stable than released versions.
Specific builds can be grabbed by clicking on the build number on the left side or by clicking on status to retrieve the
latest build.
https://ci.codemc.org/job/Games647/job/FastLogin/changes
***
@@ -51,22 +55,21 @@ You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogi
## Placeholder
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
already successful joined the server. This takes about a couple of milliseconds. In this case the value
will be `Unknown`.
will be `Unknown`.
Possible values: `Premium`, `Cracked`, `Unknown`
Possible values: `Premium`, `Cracked`, `Unknown`
## Requirements
* Plugin:
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* [Spigot](https://www.spigotmc.org) 1.8.8+
* Java 8+
* Server software in offlinemode:
* Spigot (or a fork e.g. Paper) 1.8.8+
* Protocol plugin:
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* Latest BungeeCord (or a fork e.g. Waterfall)
* Run Spigot (or a fork e.g. Paper) and/or BungeeCord (or a fork e.g. Waterfall) in offline mode
* An auth plugin.
### Supported auth plugins
@@ -78,7 +81,7 @@ Possible values: `Premium`, `Cracked`, `Unknown`
* [CrazyLogin](https://dev.bukkit.org/bukkit-plugins/crazylogin/)
* [LoginSecurity](https://dev.bukkit.org/bukkit-plugins/loginsecurity/)
* [LogIt](https://github.com/games647/LogIt)
* [SodionAuth (2.0+)](https://github.com/MohistMC/SodionAuth)
* [SodionAuth (2.0+)](https://github.com/Mohist-Community/SodionAuth)
* [UltraAuth](https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/)
* [UserLogin](https://www.spigotmc.org/resources/userlogin.80669/)
* [xAuth](https://dev.bukkit.org/bukkit-plugins/xauth/)
@@ -87,7 +90,6 @@ Possible values: `Premium`, `Cracked`, `Unknown`
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
* [BungeeAuthenticator](https://www.spigotmc.org/resources/bungeecordauthenticator.87669/)
* [SodionAuth (2.0+)](https://github.com/MohistMC/SodionAuth)
## Network requests
@@ -103,28 +105,20 @@ This plugin performs network requests to:
### Spigot/Paper
1. Download and install ProtocolLib/ProtocolSupport
2. Download and install FastLogin (or `FastLoginBukkit` for newer versions)
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to false
2. Download and install FastLogin (or FastLoginBukkit for newer versions)
3. Set your server in offline mode by setting the value onlinemode in your server.properties to false
### BungeeCord/Waterfall or Velocity
### BungeeCord/Waterfall
Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and backend server (Spigot).
1. Activate proxy support in the server configuration
* 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
* 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
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB
* Note the embedded file storage SQLite is not available
* MySQL/MariaDB requires an external database server running. Check your server provider if there is one available
or install one.
6. Set proxy and Spigot in offline mode by setting the value `onlinemode` in your `config.yml` to false
7. You should *always* configure the firewall for your Spigot server so that it's only accessible through your proxy
* This is also the case without this plugin
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
1. Activate BungeeCord in the Spigot configuration
2. Restart your server
3. Now there is `allowed-proxies.txt` file in the FastLogin folder
Put your stats id from the BungeeCord config into this file
4. Activate ipForward in your BungeeCord config
5. Download and Install FastLogin (or FastLoginBungee in newer versions) on BungeeCord AND Spigot
(on the servers where your login plugin is or where player should be able to execute the commands of FastLogin)
6. Check your database settings in the config of FastLogin on BungeeCord
7. Set proxy and Spigot in offline mode by setting the value onlinemode in your config.yml to false
8. You should *always* firewall your Spigot server that it's only accessible through BungeeCord
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
* BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB

View File

@@ -1,30 +1,3 @@
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
@@ -36,7 +9,7 @@
<relativePath>../pom.xml</relativePath>
</parent>
<!--This has to be in lowercase because it's used by plugin.yml-->
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin.bukkit</artifactId>
<packaging>jar</packaging>
@@ -47,7 +20,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.2.4</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
@@ -68,33 +41,11 @@
<pattern>com.google.gson</pattern>
<shadedPattern>fastlogin.gson</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>fastlogin.guava</shadedPattern>
<excludes>
<exclude>com.google.common.collect.Multimap</exclude>
</excludes>
</relocation>
<relocation>
<pattern>io.papermc.lib</pattern>
<shadedPattern>fastlogin.paperlib</shadedPattern>
</relocation>
</relocations>
<!-- 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"/>
</transformers>
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
@@ -128,6 +79,12 @@
<repository>
<id>codemc-releases</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
<!-- GitHub automatic maven builds -->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -141,15 +98,6 @@
<enabled>false</enabled>
</snapshots>
</repository>
<!-- GitHub automatic maven builds -->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
@@ -160,40 +108,28 @@
<version>${project.version}</version>
</dependency>
<!-- PaperSpigot API for correcting user cache usage -->
<!-- PaperSpigot API for correcting usercache usage -->
<dependency>
<groupId>io.papermc.paper</groupId>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.18-R0.1-SNAPSHOT</version>
<version>1.15.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- PaperLib for checking if server uses PaperSpigot -->
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.7</version>
<version>1.0.6</version>
<scope>compile</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.8.0</version>
<version>4.6.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Changing onlinemode on login process-->
@@ -203,59 +139,13 @@
<!--4.29.dev after commit about API improvements-->
<version>3a80c661fe</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need the API, but it was excluded above -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>geyser-api</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
</dependency>
<!--Provide premium placeholders-->
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.1</version>
<version>2.10.8</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -284,7 +174,7 @@
<dependency>
<groupId>com.lenis0012.bukkit</groupId>
<artifactId>loginsecurity</artifactId>
<version>3.1</version>
<version>3.0.2</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -351,5 +241,19 @@
<scope>system</scope>
<systemPath>${project.basedir}/lib/UltraAuth v2.1.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Bukkit</artifactId>
<version>b74392aa34</version>
<exclusions>
<exclusion>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Libs</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,33 +1,9 @@
/*
* 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;
import com.github.games647.fastlogin.core.AsyncScheduler;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
@@ -35,10 +11,12 @@ import org.slf4j.Logger;
public class BukkitScheduler extends AsyncScheduler {
private final Plugin plugin;
private final Executor syncExecutor;
public BukkitScheduler(Plugin plugin, Logger logger) {
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
public BukkitScheduler(Plugin plugin, Logger logger, ThreadFactory threadFactory) {
super(logger, threadFactory);
this.plugin = plugin;
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
}

View File

@@ -0,0 +1,24 @@
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.core.SessionManager;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
public class BukkitSessionManager extends SessionManager<PlayerQuitEvent, InetSocketAddress, BukkitLoginSession>
implements Listener {
@EventHandler
@Override
public void onPlayQuit(PlayerQuitEvent quitEvent) {
Player player = quitEvent.getPlayer();
UUID playerId = player.getUniqueId();
endPlaySession(playerId);
}
}

View File

@@ -1,67 +1,31 @@
/*
* 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;
import com.destroystokyo.paper.event.player.PlayerHandshakeEvent;
import com.github.games647.fastlogin.bukkit.auth.proxy.ProxyManager;
import com.github.games647.fastlogin.bukkit.auth.protocollib.ProtocolLibListener;
import com.github.games647.fastlogin.bukkit.auth.protocolsupport.ProtocolSupportListener;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.hook.DelayedAuthHook;
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;
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
import com.github.games647.fastlogin.bukkit.listener.PaperPreLoginListener;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import io.papermc.lib.PaperLib;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.geyser.GeyserImpl;
import org.slf4j.Logger;
/**
@@ -69,57 +33,38 @@ import org.slf4j.Logger;
*/
public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<CommandSender> {
//1 minutes should be enough as a timeout for bad internet connection (Server, Client and Mojang)
private final ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(1, -1);
private final BukkitSessionManager sessionManager = new BukkitSessionManager();
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
private final Logger logger;
private final FastLoginCore<Player, CommandSender, FastLoginBukkit> core = new FastLoginCore<>(this);
private boolean serverStarted;
private BungeeManager bungeeManager;
private final Logger logger;
private final BukkitScheduler scheduler;
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
private FloodgateService floodgateService;
private GeyserService geyserService;
private ProxyManager proxyManager;
private PremiumPlaceholder premiumPlaceholder;
public FastLoginBukkit() {
this.logger = CommonUtil.initializeLoggerService(getLogger());
this.scheduler = new BukkitScheduler(this, logger);
this.logger = CommonUtil.createLoggerFromJDK(getLogger());
this.scheduler = new BukkitScheduler(this, logger, getThreadFactory());
}
@Override
public void onEnable() {
core = new FastLoginCore<>(this);
core.load();
if (getServer().getOnlineMode()) {
//we need to require offline to prevent a loginSession request for an offline player
//we need to require offline to prevent a loginSession request for a offline player
logger.error("Server has to be in offline mode");
setEnabled(false);
return;
}
if (!initializeFloodgate()) {
setEnabled(false);
}
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
// getServer().getPluginManager().registerEvents(new Listener() {
//
// @EventHandler
// void onHandshake(PlayerHandshakeEvent handshakeEvent) {
// handshakeEvent.setCancelled(false);
// handshakeEvent.setSocketAddressHostname("192.168.0.1");
// }
// }, this);
proxyManager = new ProxyManager(this);
proxyManager.initialize();
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
markInitialized();
} else {
if (!proxyManager.isEnabled()) {
if (!core.setupDatabase()) {
setEnabled(false);
return;
@@ -129,30 +74,8 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
pluginManager.registerEvents(new ProtocolSupportListener(this, core.getRateLimiter()), this);
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
ProtocolLibListener.register(this, core.getRateLimiter());
if (isPluginInstalled("floodgate")) {
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");
}
}
//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);
}
} else {
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
setEnabled(false);
return;
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use proxies");
}
}
@@ -161,58 +84,29 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
pluginManager.registerEvents(new ConnectionListener(this), this);
//if server is using paper - we need to add one more listener to correct the user cache usage
//if server is using paper - we need to add one more listener to correct the usercache usage
if (PaperLib.isPaper()) {
pluginManager.registerEvents(new PaperCacheListener(this), this);
pluginManager.registerEvents(new PaperPreLoginListener(this), this);
}
//register commands using a unique name
Optional.ofNullable(getCommand("premium")).ifPresent(c -> c.setExecutor(new PremiumCommand(this)));
Optional.ofNullable(getCommand("cracked")).ifPresent(c -> c.setExecutor(new CrackedCommand(this)));
getCommand("premium").setExecutor(new PremiumCommand(this));
getCommand("cracked").setExecutor(new CrackedCommand(this));
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
premiumPlaceholder = new PremiumPlaceholder(this);
premiumPlaceholder.register();
}
dependencyWarnings();
}
private boolean initializeFloodgate() {
if (getServer().getPluginManager().getPlugin("Geyser-Spigot") != null) {
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
}
if (getServer().getPluginManager().getPlugin("floodgate") != null) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
// Check Floodgate config values and return
return floodgateService.isValidFloodgateConfigString("autoLoginFloodgate")
&& floodgateService.isValidFloodgateConfigString("allowFloodgateNameConflict");
}
return true;
}
@Override
public void onDisable() {
loginSession.clear();
premiumPlayers.clear();
core.close();
if (core != null) {
core.close();
}
if (bungeeManager != null) {
bungeeManager.cleanup();
}
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
try {
premiumPlaceholder.unregister();
} catch (Exception | NoSuchMethodError exception) {
logger.error("Failed to unregister placeholder", exception);
}
proxyManager.cleanup();
if (getServer().getPluginManager().isPluginEnabled("PlaceholderAPI") && premiumPlaceholder != null) {
premiumPlaceholder.unregister();
}
}
@@ -220,66 +114,40 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return core;
}
/**
* Fetches the premium status of an online player.
*
* @param onlinePlayer
* @return the online status or unknown if an error happened, the player isn't online or a proxy doesn't send
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
* @deprecated this method could be removed in future versions and exists only as a temporarily solution
*/
@Deprecated
public PremiumStatus getStatus(UUID onlinePlayer) {
StoredProfile playSession = sessionManager.getPlaySession(onlinePlayer);
return Optional.ofNullable(playSession).map(profile -> {
if (profile.isPremium())
return PremiumStatus.PREMIUM;
return PremiumStatus.CRACKED;
}).orElse(PremiumStatus.UNKNOWN);
}
/**
* Gets a thread-safe map about players which are connecting to the server are being checked to be premium (paid
* account)
*
* @return a thread-safe loginSession map
*/
public ConcurrentMap<String, BukkitLoginSession> getLoginSessions() {
return loginSession;
}
public BukkitLoginSession getSession(InetSocketAddress address) {
String id = getSessionId(address);
return loginSession.get(id);
}
public String getSessionId(InetSocketAddress address) {
return address.getAddress().getHostAddress() + ':' + address.getPort();
}
public void putSession(InetSocketAddress address, BukkitLoginSession session) {
String id = getSessionId(address);
loginSession.put(id, session);
}
public void removeSession(InetSocketAddress address) {
String id = getSessionId(address);
loginSession.remove(id);
public BukkitSessionManager getSessionManager() {
return sessionManager;
}
public Map<UUID, PremiumStatus> getPremiumPlayers() {
return premiumPlayers;
}
/**
* Fetches the premium status of an online player.
*
* @param onlinePlayer player that is currently online player (play state)
* @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) {
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
}
/**
* Wait before the server is fully started. This is workaround, because connections right on startup are not
* injected by ProtocolLib
*
* @return true if ProtocolLib can now intercept packets
*/
public boolean isServerFullyStarted() {
return serverStarted;
}
public void markInitialized() {
this.serverStarted = true;
}
public BungeeManager getBungeeManager() {
return bungeeManager;
public ProxyManager getProxyManager() {
return proxyManager;
}
@Override
@@ -301,46 +169,4 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
public void sendMessage(CommandSender receiver, String message) {
receiver.sendMessage(message);
}
/**
* Checks if a plugin is installed on the server
*
* @param name the name of the plugin
* @return true if the plugin is installed
*/
@Override
public boolean isPluginInstalled(String name) {
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
}
public FloodgateService getFloodgateService() {
return floodgateService;
}
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
if (floodgateService != null) {
return floodgateService;
}
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/");
}
}
}

View File

@@ -1,39 +1,13 @@
/*
* 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.task;
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginAutoLoginEvent;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.message.SuccessMessage;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.auth.ForceLoginManagement;
import com.github.games647.fastlogin.core.auth.LoginSession;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import java.util.concurrent.ExecutionException;
@@ -52,7 +26,7 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
@Override
public void run() {
// block this target player for BungeeCord ID brute force attacks
// block this target player for proxy ID brute force attacks
FastLoginBukkit plugin = core.getPlugin();
player.setMetadata(core.getPlugin().getName(), new FixedMetadataValue(plugin, true));
@@ -81,8 +55,8 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
@Override
public void onForceActionSuccess(LoginSession session) {
if (core.getPlugin().getBungeeManager().isEnabled()) {
core.getPlugin().getBungeeManager().sendPluginMessage(player, new SuccessMessage());
if (core.getPlugin().getProxyManager().isEnabled()) {
core.getPlugin().getProxyManager().sendPluginMessage(player, new SuccessMessage());
}
}

View File

@@ -1,34 +1,8 @@
/*
* 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;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
public class PremiumPlaceholder extends PlaceholderExpansion {
@@ -41,7 +15,7 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
}
@Override
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
public String onRequest(OfflinePlayer player, String identifier) {
// player is null if offline
if (player != null && PLACEHOLDER_VARIABLE.equals(identifier)) {
return plugin.getStatus(player.getUniqueId()).getReadableName();
@@ -51,7 +25,7 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
}
@Override
public @NotNull String getIdentifier() {
public String getIdentifier() {
return plugin.getName();
}
@@ -61,12 +35,12 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
}
@Override
public @NotNull String getAuthor() {
public String getAuthor() {
return String.join(", ", plugin.getDescription().getAuthors());
}
@Override
public @NotNull String getVersion() {
public String getVersion() {
return plugin.getDescription().getVersion();
}
}

View File

@@ -1,33 +1,8 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth;
import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSession;
import java.util.Optional;
@@ -40,40 +15,42 @@ public class BukkitLoginSession extends LoginSession {
private static final byte[] EMPTY_ARRAY = {};
private final String serverId;
private final byte[] verifyToken;
private boolean verified;
private SkinProperty skinProperty;
public BukkitLoginSession(String username, byte[] verifyToken, boolean registered
public BukkitLoginSession(String username, String serverId, byte[] verifyToken, boolean registered
, StoredProfile profile) {
super(username, registered, profile);
this.serverId = serverId;
this.verifyToken = verifyToken.clone();
}
//available for BungeeCord
// available for proxies
public BukkitLoginSession(String username, boolean registered) {
this(username, EMPTY_ARRAY, registered, null);
this(username, "", EMPTY_ARRAY, registered, null);
}
//cracked player
public BukkitLoginSession(String username, StoredProfile profile) {
this(username, EMPTY_ARRAY, false, profile);
this(username, "", EMPTY_ARRAY, false, profile);
}
//ProtocolSupport
public BukkitLoginSession(String username, boolean registered, StoredProfile profile) {
this(username, EMPTY_ARRAY, registered, profile);
this(username, "", EMPTY_ARRAY, registered, profile);
}
/**
* Gets the verify-token the server sent to the client.
* Gets the verify token the server sent to the client.
*
* Empty if it's a BungeeCord connection
* Empty if it's a proxy connection
*
* @return verify token from the server
* @return the verify token from the server
*/
public synchronized byte[] getVerifyToken() {
return verifyToken.clone();

View File

@@ -1,29 +1,4 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
@@ -35,7 +10,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@@ -56,7 +30,7 @@ public class EncryptionUtil {
}
/**
* Generate an RSA key pair
* Generate a RSA key pair
*
* @return The RSA key pair.
*/

View File

@@ -0,0 +1,23 @@
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
public class InitializedListener implements Listener {
private final ProtocolLibListener module;
protected InitializedListener(ProtocolLibListener protocolLibModule) {
this.module = protocolLibModule;
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
if (loginEvent.getResult() == Result.ALLOWED && !module.isReadyToInject()) {
loginEvent.disallow(Result.KICK_OTHER, module.getPlugin().getCore().getMessage("not-started"));
}
}
}

View File

@@ -1,37 +1,12 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.security.PublicKey;
@@ -52,9 +27,9 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
private final Player player;
private final String username;
public NameCheckTask(FastLoginBukkit plugin, Random random, Player player, PacketEvent packetEvent,
String username, PublicKey publicKey) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
protected NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
Player player, String username, PublicKey publicKey) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin;
this.packetEvent = packetEvent;
@@ -67,15 +42,14 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
@Override
public void run() {
try {
super.onLogin(username, new ProtocolLibLoginSource(player, random, publicKey));
super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
} finally {
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
}
}
@Override
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source,
StoredProfile profile) {
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source, StoredProfile profile) {
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
plugin.getServer().getPluginManager().callEvent(event);
return event;
@@ -87,7 +61,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
public void requestPremiumLogin(ProtocolLibLoginSource source, StoredProfile profile
, String username, boolean registered) {
try {
source.enableOnlinemode();
source.setOnlineMode();
} catch (Exception ex) {
plugin.getLog().error("Cannot send encryption packet. Falling back to cracked login for: {}", profile, ex);
return;
@@ -96,10 +70,11 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
String ip = player.getAddress().getAddress().getHostAddress();
core.getPendingLogin().put(ip + username, new Object());
String serverId = source.getServerId();
byte[] verify = source.getVerifyToken();
BukkitLoginSession playerSession = new BukkitLoginSession(username, verify, registered, profile);
plugin.putSession(player.getAddress(), playerSession);
BukkitLoginSession playerSession = new BukkitLoginSession(username, serverId, verify, registered, profile);
plugin.getSessionManager().startLoginSession(player.getAddress(), playerSession);
//cancel only if the player has a paid account otherwise login as normal offline player
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
packetEvent.setCancelled(true);
@@ -109,6 +84,6 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
@Override
public void startCrackedSession(ProtocolLibLoginSource source, StoredProfile profile, String username) {
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.putSession(player.getAddress(), loginSession);
plugin.getSessionManager().startLoginSession(player.getAddress(), loginSession);
}
}

View File

@@ -1,29 +1,4 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
@@ -31,20 +6,22 @@ import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.auth.RateLimiter;
import io.papermc.lib.PaperLib;
import java.security.KeyPair;
import java.security.SecureRandom;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
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;
//just create a new once on plugin enable. This used for verify token generation
@@ -52,7 +29,11 @@ public class ProtocolLibListener extends PacketAdapter {
private final KeyPair keyPair = EncryptionUtil.generateKeyPair();
private final RateLimiter rateLimiter;
public ProtocolLibListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
// Wait before the server is fully started. This is workaround, because connections right on startup are not
// injected by ProtocolLib
private boolean serverStarted;
protected ProtocolLibListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
//run async in order to not block the server, because we are making api calls to Mojang
super(params()
.plugin(plugin)
@@ -64,32 +45,35 @@ public class ProtocolLibListener extends PacketAdapter {
}
public static void register(FastLoginBukkit plugin, RateLimiter rateLimiter) {
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
// TODO: make synchronous processing, but do web or database requests async
//they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
ProtocolLibListener packetListener = new ProtocolLibListener(plugin, rateLimiter);
ProtocolLibrary.getProtocolManager()
.getAsynchronousManager()
.registerAsyncHandler(new ProtocolLibListener(plugin, rateLimiter))
.registerAsyncHandler(packetListener)
.start();
PluginManager pluginManager = Bukkit.getServer().getPluginManager();
pluginManager.registerEvents(new InitializedListener(packetListener), plugin);
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
if (!PaperLib.isPaper() && plugin.getConfig().getBoolean("forwardSkin")) {
pluginManager.registerEvents(new SkinApplyListener(plugin), plugin);
}
}
@Override
public void onPacketReceiving(PacketEvent packetEvent) {
if (packetEvent.isCancelled()
|| plugin.getCore().getAuthPluginHook() == null
|| !plugin.isServerFullyStarted()) {
if (packetEvent.isCancelled() || plugin.getCore().getAuthPluginHook() == null) {
return;
}
if (isFastLoginPacket(packetEvent)) {
// this is our own packet
return;
}
markReadyToInject();
Player sender = packetEvent.getPlayer();
PacketType packetType = packetEvent.getPacketType();
if (packetType == START) {
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", sender);
plugin.getLog().warn("Join limit hit - Ignoring player {}", sender);
return;
}
@@ -99,12 +83,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);
@@ -118,22 +96,29 @@ public class ProtocolLibListener extends PacketAdapter {
String sessionKey = player.getAddress().toString();
//remove old data every time on a new login in order to keep the session only for one person
plugin.removeSession(player.getAddress());
plugin.getSessionManager().endLoginSession(player.getAddress());
//player.getName() won't work at this state
PacketContainer packet = packetEvent.getPacket();
String username = packet.getGameProfiles().read(0).getName();
if (packetEvent.getPacket().getMeta("original_name").isPresent()) {
//username has been injected by ManualNameChange.java
username = (String) packetEvent.getPacket().getMeta("original_name").get();
}
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
packetEvent.getAsyncMarker().incrementProcessingDelay();
Runnable nameCheckTask = new NameCheckTask(plugin, random, player, packetEvent, username, keyPair.getPublic());
Runnable nameCheckTask = new NameCheckTask(plugin, packetEvent, random, player, username, keyPair.getPublic());
plugin.getScheduler().runAsync(nameCheckTask);
}
public void markReadyToInject() {
this.serverStarted = true;
}
public boolean isReadyToInject() {
return serverStarted;
}
@Override
public FastLoginBukkit getPlugin() {
return plugin;
}
}

View File

@@ -1,36 +1,12 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.github.games647.fastlogin.core.shared.LoginSource;
import com.github.games647.fastlogin.core.auth.LoginSource;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress;
@@ -45,6 +21,7 @@ import static com.comphenix.protocol.PacketType.Login.Server.ENCRYPTION_BEGIN;
class ProtocolLibLoginSource implements LoginSource {
private final PacketEvent packetEvent;
private final Player player;
private final Random random;
@@ -53,14 +30,15 @@ class ProtocolLibLoginSource implements LoginSource {
private final String serverId = "";
private byte[] verifyToken;
public ProtocolLibLoginSource(Player player, Random random, PublicKey publicKey) {
protected ProtocolLibLoginSource(PacketEvent packetEvent, Player player, Random random, PublicKey publicKey) {
this.packetEvent = packetEvent;
this.player = player;
this.random = random;
this.publicKey = publicKey;
}
@Override
public void enableOnlinemode() throws InvocationTargetException {
public void setOnlineMode() throws Exception {
verifyToken = EncryptionUtil.generateVerifyToken(random);
/*
@@ -83,7 +61,7 @@ class ProtocolLibLoginSource implements LoginSource {
newPacket.getByteArrays().write(verifyField, verifyToken);
//serverId is an empty string
//serverId is a empty string
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
}
@@ -106,7 +84,7 @@ class ProtocolLibLoginSource implements LoginSource {
@Override
public InetSocketAddress getAddress() {
return player.getAddress();
return packetEvent.getPlayer().getAddress();
}
public String getServerId() {
@@ -120,7 +98,8 @@ class ProtocolLibLoginSource implements LoginSource {
@Override
public String toString() {
return this.getClass().getSimpleName() + '{' +
"player=" + player +
"packetEvent=" + packetEvent +
", player=" + player +
", random=" + random +
", serverId='" + serverId + '\'' +
", verifyToken=" + Arrays.toString(verifyToken) +

View File

@@ -0,0 +1,52 @@
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
public class SkinApplyListener implements Listener {
private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
private static final MethodAccessor GET_PROPERTIES = Accessors.getMethodAccessor(GAME_PROFILE, "getProperties");
private final FastLoginBukkit plugin;
protected SkinApplyListener(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.LOW)
//run this on the loginEvent to let skins plugins see the skin like in normal Minecraft behaviour
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
if (loginEvent.getResult() != Result.ALLOWED) {
return;
}
Player player = loginEvent.getPlayer();
//go through every session, because player.getAddress is null
//loginEvent.getAddress is just a InetAddress not InetSocketAddress, so not unique enough
BukkitLoginSession session = plugin.getSessionManager().getLoginSession(player.getAddress());
if (session.getUsername().equals(player.getName())) {
session.getSkin().ifPresent(skin -> applySkin(player, skin.getValue(), skin.getSignature()));
}
}
private void applySkin(Player player, String skinData, String signature) {
WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player);
WrappedSignedProperty skin = WrappedSignedProperty.fromValues(Textures.KEY, skinData, signature);
gameProfile.getProperties().put(Textures.KEY, skin);
}
}

View File

@@ -1,29 +1,4 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
@@ -36,18 +11,15 @@ import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.craftapi.model.auth.Verification;
import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.craftapi.resolver.AbstractResolver;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyPair;
@@ -66,13 +38,6 @@ import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
public class VerifyResponseTask implements Runnable {
private static final String ENCRYPTION_CLASS_NAME = "MinecraftEncryption";
private static final Class<?> ENCRYPTION_CLASS;
static {
ENCRYPTION_CLASS = MinecraftReflection.getMinecraftClass("util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME);
}
private final FastLoginBukkit plugin;
private final PacketEvent packetEvent;
private final KeyPair serverKey;
@@ -84,7 +49,7 @@ public class VerifyResponseTask implements Runnable {
private static Method encryptMethod;
private static Method cipherMethod;
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent, Player player,
protected VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent, Player player,
byte[] sharedSecret, KeyPair keyPair) {
this.plugin = plugin;
this.packetEvent = packetEvent;
@@ -96,16 +61,15 @@ public class VerifyResponseTask implements Runnable {
@Override
public void run() {
try {
BukkitLoginSession session = plugin.getSession(player.getAddress());
BukkitLoginSession session = plugin.getSessionManager().getLoginSession(player.getAddress());
if (session == null) {
disconnect("invalid-request",
"GameProfile {0} tried to send encryption response at invalid state",
player.getAddress());
disconnect("invalid-request", true
, "GameProfile {0} tried to send encryption response at invalid state", player.getAddress());
} else {
verifyResponse(session);
}
} finally {
//this is a fake packet; it shouldn't be sent to the server
//this is a fake packet; it shouldn't be send to the server
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
packetEvent.setCancelled(true);
}
@@ -121,7 +85,7 @@ public class VerifyResponseTask implements Runnable {
try {
loginKey = EncryptionUtil.decryptSharedKey(privateKey, sharedSecret);
} catch (GeneralSecurityException securityEx) {
disconnect("error-kick", "Cannot decrypt received contents", securityEx);
disconnect("error-kick", false, "Cannot decrypt received contents", securityEx);
return;
}
@@ -130,7 +94,7 @@ public class VerifyResponseTask implements Runnable {
return;
}
} catch (Exception ex) {
disconnect("error-kick", "Cannot decrypt received contents", ex);
disconnect("error-kick", false, "Cannot decrypt received contents", ex);
return;
}
@@ -144,10 +108,10 @@ public class VerifyResponseTask implements Runnable {
Optional<Verification> response = resolver.hasJoined(requestedUsername, serverId, address);
if (response.isPresent()) {
Verification verification = response.get();
plugin.getLog().info("Profile {} has a verified premium account", requestedUsername);
plugin.getLog().info("Profile {} has a verified premium account: {}", requestedUsername, verification);
String realUsername = verification.getName();
if (realUsername == null) {
disconnect("invalid-session", "Username field null for {}", requestedUsername);
disconnect("invalid-session", true, "Username field null for {}", requestedUsername);
return;
}
@@ -163,11 +127,13 @@ public class VerifyResponseTask implements Runnable {
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(realUsername);
} else {
//user tried to fake an authentication
disconnect("invalid-session", "GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}", session.getRequestUsername(), socketAddress, serverId);
//user tried to fake a authentication
disconnect("invalid-session", true
, "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
, session.getRequestUsername(), socketAddress, serverId);
}
} catch (IOException ioEx) {
disconnect("error-kick", "Failed to connect to session server", ioEx);
disconnect("error-kick", false, "Failed to connect to session server", ioEx);
}
}
@@ -190,10 +156,10 @@ public class VerifyResponseTask implements Runnable {
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(serverKey.getPrivate(), responseVerify))) {
//check if the verify-token are equal to the server sent one
disconnect("invalid-verify-token",
"GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}",
session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
//check if the verify token are equal to the server sent one
disconnect("invalid-verify-token", true
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
, session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
return false;
}
@@ -204,14 +170,13 @@ public class VerifyResponseTask implements Runnable {
private Object getNetworkManager() throws IllegalAccessException, ClassNotFoundException {
Object injectorContainer = TemporaryPlayerFactory.getInjectorFromPlayer(player);
// ChannelInjector
//ChannelInjector
Class<?> injectorClass = Class.forName("com.comphenix.protocol.injector.netty.Injector");
Object rawInjector = FuzzyReflection.getFieldValue(injectorContainer, injectorClass, true);
return FieldUtils.readField(rawInjector, "networkManager", true);
}
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getAddress());
// Initialize method reflections
if (encryptMethod == null) {
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
@@ -219,15 +184,16 @@ public class VerifyResponseTask implements Runnable {
try {
// Try to get the old (pre MC 1.16.4) encryption method
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
.getMethodByParameters("a", SecretKey.class);
.getMethodByParameters("a", SecretKey.class);
} catch (IllegalArgumentException exception) {
// Get the new encryption method
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
.getMethodByParameters("a", Cipher.class, Cipher.class);
.getMethodByParameters("a", Cipher.class, Cipher.class);
// Get the needed Cipher helper method (used to generate ciphers from login key)
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
.getMethodByParameters("a", int.class, Key.class);
Class<?> encryptionClass = MinecraftReflection.getMinecraftClass("MinecraftEncryption");
cipherMethod = FuzzyReflection.fromClass(encryptionClass)
.getMethodByParameters("a", int.class, Key.class);
}
}
@@ -247,15 +213,20 @@ public class VerifyResponseTask implements Runnable {
encryptMethod.invoke(networkManager, decryptionCipher, encryptionCipher);
}
} catch (Exception ex) {
disconnect("error-kick", "Couldn't enable encryption", ex);
disconnect("error-kick", false, "Couldn't enable encryption", ex);
return false;
}
return true;
}
private void disconnect(String reasonKey, String logMessage, Object... arguments) {
plugin.getLog().error(logMessage, arguments);
private void disconnect(String reasonKey, boolean debug, String logMessage, Object... arguments) {
if (debug) {
plugin.getLog().debug(logMessage, arguments);
} else {
plugin.getLog().error(logMessage, arguments);
}
kickPlayer(plugin.getCore().getMessage(reasonKey));
}
@@ -283,8 +254,7 @@ public class VerifyResponseTask implements Runnable {
startPacket.getGameProfiles().write(0, fakeProfile);
try {
//we don't want to handle our own packets so ignore filters
startPacket.setMeta(ProtocolLibListener.SOURCE_META_KEY, plugin.getName());
ProtocolLibrary.getProtocolManager().recieveClientPacket(player, startPacket, true);
ProtocolLibrary.getProtocolManager().recieveClientPacket(player, startPacket, false);
} catch (InvocationTargetException | IllegalAccessException ex) {
plugin.getLog().warn("Failed to fake a new start packet for: {}", username, ex);
//cancel the event in order to prevent the server receiving an invalid packet

View File

@@ -0,0 +1,42 @@
package com.github.games647.fastlogin.bukkit.auth.protocolsupport;
import com.github.games647.fastlogin.core.auth.LoginSource;
import java.net.InetSocketAddress;
import protocolsupport.api.events.PlayerLoginStartEvent;
public class ProtocolLoginSource implements LoginSource {
private final PlayerLoginStartEvent loginStartEvent;
protected ProtocolLoginSource(PlayerLoginStartEvent loginStartEvent) {
this.loginStartEvent = loginStartEvent;
}
@Override
public void setOnlineMode() {
loginStartEvent.setOnlineMode(true);
}
@Override
public void kick(String message) {
loginStartEvent.denyLogin(message);
}
@Override
public InetSocketAddress getAddress() {
return loginStartEvent.getAddress();
}
public PlayerLoginStartEvent getLoginStartEvent() {
return loginStartEvent;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + '{' +
"loginStartEvent=" + loginStartEvent +
'}';
}
}

View File

@@ -1,37 +1,12 @@
/*
* 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.protocolsupport;
package com.github.games647.fastlogin.bukkit.auth.protocolsupport;
import com.github.games647.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.auth.RateLimiter;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.net.InetSocketAddress;
@@ -52,7 +27,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
private final RateLimiter rateLimiter;
public ProtocolSupportListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin;
this.rateLimiter = rateLimiter;
@@ -65,31 +40,29 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
}
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", loginStartEvent.getConnection());
plugin.getLog().warn("Join limit hit - Ignoring player {}", loginStartEvent.getConnection());
return;
}
String username = loginStartEvent.getConnection().getProfile().getName();
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
InetSocketAddress address = loginStartEvent.getAddress();
//remove old data every time on a new login in order to keep the session only for one person
plugin.removeSession(address);
plugin.getSessionManager().endLoginSession(address);
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
super.onLogin(username, source);
super.onLogin(username, new ProtocolLoginSource(loginStartEvent));
}
@EventHandler
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
plugin.removeSession(address);
InetSocketAddress address = closeEvent.getConnection().getAddress();
plugin.getSessionManager().endLoginSession(address);
}
@EventHandler
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
BukkitLoginSession session = plugin.getSession(address);
InetSocketAddress address = profileCompleteEvent.getAddress();
BukkitLoginSession session = plugin.getSessionManager().getLoginSession(address);
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
session.setVerified(true);
@@ -112,18 +85,18 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
@Override
public void requestPremiumLogin(ProtocolLoginSource source, StoredProfile profile, String username
, boolean registered) {
source.enableOnlinemode();
source.setOnlineMode();
String ip = source.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogin().put(ip + username, new Object());
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
plugin.putSession(source.getAddress(), playerSession);
plugin.getSessionManager().startLoginSession(source.getAddress(), playerSession);
}
@Override
public void startCrackedSession(ProtocolLoginSource source, StoredProfile profile, String username) {
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.putSession(source.getAddress(), loginSession);
plugin.getSessionManager().startLoginSession(source.getAddress(), loginSession);
}
}

View File

@@ -1,31 +1,6 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.proxy;
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
@@ -50,12 +25,12 @@ import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CH
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
import static java.util.stream.Collectors.toSet;
public class BungeeManager {
public class ProxyManager {
private static final String LEGACY_FILE_NAME = "proxy-whitelist.txt";
private static final String FILE_NAME = "allowed-proxies.txt";
//null if proxies allowed list is empty so bungeecord support is disabled
//null if proxies allowed list is empty so proxy support is disabled
private Set<UUID> proxyIds;
private final FastLoginBukkit plugin;
@@ -63,7 +38,7 @@ public class BungeeManager {
private final Set<UUID> firedJoinEvents = new HashSet<>();
public BungeeManager(FastLoginBukkit plugin) {
public ProxyManager(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@@ -94,35 +69,30 @@ public class BungeeManager {
}
if (enabled) {
proxyIds = loadBungeeCordIds();
proxyIds = loadProxyIds();
registerPluginChannels();
}
}
private boolean isProxySupported(String className, String fieldName) {
private boolean detectProxy() throws Exception {
try {
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
enabled = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
return enabled;
} catch (ClassNotFoundException notFoundEx) {
//ignore server has no proxy support
} catch (NoSuchFieldException | IllegalAccessException noSuchFieldException) {
plugin.getLog().warn("Cannot access proxy field", noSuchFieldException);
return false;
} catch (Exception ex) {
throw ex;
}
return false;
}
private boolean detectProxy() {
return isProxySupported("org.spigotmc.SpigotConfig", "bungee")
|| isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport");
}
private void registerPluginChannels() {
Server server = Bukkit.getServer();
// check for incoming messages from the bungeecord version of this plugin
// check for incoming messages from the proxy version of this plugin
String groupId = plugin.getName();
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new BungeeListener(plugin));
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new ProxyMessagingListener(plugin));
// outgoing
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
@@ -131,7 +101,7 @@ public class BungeeManager {
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
}
private Set<UUID> loadBungeeCordIds() {
private Set<UUID> loadProxyIds() {
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
try {
@@ -154,7 +124,7 @@ public class BungeeManager {
} catch (IOException ex) {
plugin.getLog().error("Failed to read proxies", ex);
} catch (Exception ex) {
plugin.getLog().error("Failed to retrieve proxy Id. Disabling BungeeCord support", ex);
plugin.getLog().error("Failed to retrieve proxy Id. Disabling proxy support", ex);
}
return Collections.emptySet();
@@ -167,7 +137,7 @@ public class BungeeManager {
/**
* Mark the event to be fired including the task delay.
*
* @param player joining player
* @param player
*/
public synchronized void markJoinEventFired(Player player) {
firedJoinEvents.add(player.getUniqueId());
@@ -175,13 +145,13 @@ public class BungeeManager {
/**
* Check if the event fired including with the task delay. This necessary to restore the order of processing the
* BungeeCord messages after the PlayerJoinEvent fires including the delay.
* proxy messages after the PlayerJoinEvent fires including the delay.
*
* If the join event fired, the delay exceeded, but it ran earlier and couldn't find the recently started login
* session. If not fired, we can start a new force login task. This will still match the requirement that we wait
* a certain time after the player join event fired.
*
* @param player joining player
* @param player
* @return event fired including delay
*/
public synchronized boolean didJoinEventFired(Player player) {
@@ -191,7 +161,7 @@ public class BungeeManager {
/**
* Player quit clean up
*
* @param player joining player
* @param player
*/
public synchronized void cleanup(Player player) {
firedJoinEvents.remove(player.getUniqueId());

View File

@@ -1,33 +1,8 @@
/*
* 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;
package com.github.games647.fastlogin.bukkit.auth.proxy;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
import com.github.games647.fastlogin.bukkit.ForceLoginTask;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
@@ -41,24 +16,23 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import org.jetbrains.annotations.NotNull;
/**
* Responsible for receiving messages from a BungeeCord instance.
* Responsible for receiving messages from a proxy instance.
*
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
* This class also receives the plugin message from the proxy version of this plugin in order to get notified if
* the connection is in online mode.
*/
public class BungeeListener implements PluginMessageListener {
public class ProxyMessagingListener implements PluginMessageListener {
private final FastLoginBukkit plugin;
public BungeeListener(FastLoginBukkit plugin) {
protected ProxyMessagingListener(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, Player player, byte[] message) {
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
ByteArrayDataInput dataInput = ByteStreams.newDataInput(message);
LoginActionMessage loginMessage = new LoginActionMessage();
@@ -68,7 +42,7 @@ public class BungeeListener implements PluginMessageListener {
Player targetPlayer = player;
if (!loginMessage.getPlayerName().equals(player.getName())) {
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());;
}
if (targetPlayer == null) {
@@ -76,12 +50,12 @@ public class BungeeListener implements PluginMessageListener {
return;
}
// fail if target player is blocked because already authenticated or wrong bungeecord id
// fail if target player is blocked because already authenticated or wrong proxy id
if (targetPlayer.hasMetadata(plugin.getName())) {
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
} else {
UUID sourceId = loginMessage.getProxyId();
if (plugin.getBungeeManager().isProxyAllowed(sourceId)) {
if (plugin.getProxyManager().isProxyAllowed(sourceId)) {
readMessage(targetPlayer, loginMessage);
} else {
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
@@ -127,10 +101,10 @@ public class BungeeListener implements PluginMessageListener {
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
session.setVerified(true);
plugin.putSession(player.spigot().getRawAddress(), session);
plugin.getSessionManager().startLoginSession(player.getAddress(), session);
// only start a new login task if the join event fired earlier. This event then didn't
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
// only start a new login task if the join event fired earlier. This event then didn
boolean result = plugin.getProxyManager().didJoinEventFired(player);
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
if (result) {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);

View File

@@ -1,39 +1,13 @@
/*
* 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.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.*;
public class CrackedCommand extends ToggleCommand {
@@ -42,7 +16,7 @@ public class CrackedCommand extends ToggleCommand {
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
onCrackedSelf(sender, command, args);
} else {
@@ -61,8 +35,8 @@ public class CrackedCommand extends ToggleCommand {
return;
}
if (plugin.getBungeeManager().isEnabled()) {
sendBungeeActivateMessage(sender, sender.getName(), false);
if (plugin.getProxyManager().isEnabled()) {
sendProxyActivateMessage(sender, sender.getName(), false);
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
} else {
//todo: load async if
@@ -115,6 +89,6 @@ public class CrackedCommand extends ToggleCommand {
}
private boolean forwardCrackedCommand(CommandSender sender, String target) {
return forwardBungeeCommand(sender, target, false);
return forwardProxyCommand(sender, target, false);
}
}

View File

@@ -1,45 +1,19 @@
/*
* 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.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import java.util.UUID;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Let users activate fast login by command. This only be accessible if
* the user has access to its account. So we can make sure that not another
* the user has access to it's account. So we can make sure that not another
* person with a paid account and the same username can steal their account.
*/
public class PremiumCommand extends ToggleCommand {
@@ -49,7 +23,7 @@ public class PremiumCommand extends ToggleCommand {
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
onPremiumSelf(sender, command, args);
} else {
@@ -125,6 +99,6 @@ public class PremiumCommand extends ToggleCommand {
}
private boolean forwardPremiumCommand(CommandSender sender, String target) {
return forwardBungeeCommand(sender, target, true);
return forwardProxyCommand(sender, target, true);
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -47,17 +22,17 @@ public abstract class ToggleCommand implements CommandExecutor {
}
protected boolean hasOtherPermission(CommandSender sender, Command cmd) {
if (sender.hasPermission(cmd.getPermission() + ".other")) {
return true;
if (!sender.hasPermission(cmd.getPermission() + ".other")) {
plugin.getCore().sendLocaleMessage("no-permission", sender);
return false;
}
plugin.getCore().sendLocaleMessage("no-permission", sender);
return false;
return true;
}
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {
if (plugin.getBungeeManager().isEnabled()) {
sendBungeeActivateMessage(sender, target, activate);
protected boolean forwardProxyCommand(CommandSender sender, String target, boolean activate) {
if (plugin.getProxyManager().isEnabled()) {
sendProxyActivateMessage(sender, target, activate);
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
return true;
}
@@ -75,20 +50,20 @@ public abstract class ToggleCommand implements CommandExecutor {
return true;
}
protected void sendBungeeActivateMessage(CommandSender invoker, String target, boolean activate) {
protected void sendProxyActivateMessage(CommandSender invoker, String target, boolean activate) {
if (invoker instanceof PluginMessageRecipient) {
ChannelMessage message = new ChangePremiumMessage(target, activate, true);
plugin.getBungeeManager().sendPluginMessage((PluginMessageRecipient) invoker, message);
plugin.getProxyManager().sendPluginMessage((PluginMessageRecipient) invoker, message);
} else {
Optional<? extends Player> optPlayer = Bukkit.getServer().getOnlinePlayers().stream().findFirst();
if (optPlayer.isEmpty()) {
if (!optPlayer.isPresent()) {
plugin.getLog().info("No player online to send a plugin message to the proxy");
return;
}
Player sender = optPlayer.get();
ChannelMessage message = new ChangePremiumMessage(target, activate, false);
plugin.getBungeeManager().sendPluginMessage(sender, message);
plugin.getProxyManager().sendPluginMessage(sender, message);
}
}
}

View File

@@ -1,37 +1,11 @@
/*
* 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSession;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAutoLoginEvent, Cancellable {
@@ -68,7 +42,7 @@ public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAut
}
@Override
public @NotNull HandlerList getHandlers() {
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -1,36 +1,10 @@
/*
* 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSource;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSource;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
@@ -63,7 +37,7 @@ public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreL
}
@Override
public @NotNull HandlerList getHandlers() {
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -1,35 +1,9 @@
/*
* 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
@@ -54,7 +28,7 @@ public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLogi
}
@Override
public @NotNull HandlerList getHandlers() {
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -1,32 +1,7 @@
/*
* 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.hook;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import fr.xephi.authme.api.v3.AuthMeApi;
@@ -58,7 +33,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
private final AuthMeApi authmeAPI;
private Management authmeManagement;
public AuthMeHook(FastLoginBukkit plugin) {
protected AuthMeHook(FastLoginBukkit plugin) {
this.plugin = plugin;
this.authmeAPI = AuthMeApi.getInstance();
@@ -77,8 +52,8 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
Player player = restoreSessionEvent.getPlayer();
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session != null && session.isVerified()) {
StoredProfile session = plugin.getSessionManager().getPlaySession(player.getUniqueId());
if (session != null && session.isPremium()) {
restoreSessionEvent.setCancelled(true);
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.hook;
import com.comphenix.protocol.reflect.FieldUtils;
@@ -56,7 +31,7 @@ public class CrazyLoginHook implements AuthPlugin<Player> {
private final CrazyLogin crazyLoginPlugin;
private final PlayerListener playerListener;
public CrazyLoginHook(FastLoginBukkit plugin) {
protected CrazyLoginHook(FastLoginBukkit plugin) {
this.plugin = plugin;
crazyLoginPlugin = CrazyLogin.getPlugin();
@@ -121,11 +96,11 @@ public class CrazyLoginHook implements AuthPlugin<Player> {
public boolean forceRegister(Player player, String password) {
CrazyLoginDataDatabase crazyDatabase = crazyLoginPlugin.getCrazyDatabase();
//this executes a sql query and accesses only thread safe collections, so we can run it async
//this executes a sql query and accesses only thread safe collections so we can run it async
LoginPlayerData playerData = crazyLoginPlugin.getPlayerData(player.getName());
if (playerData == null) {
//create a fake account - this will be saved to the database with the password=FAILEDLOADING
//user cannot log in with that password unless the admin uses plain text
//user cannot login with that password unless the admin uses plain text
//this automatically marks the player as logged in
crazyDatabase.save(new LoginPlayerData(player));
return forceLogin(player);

View File

@@ -1,37 +1,6 @@
/*
* 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.task;
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.hook.AuthMeHook;
import com.github.games647.fastlogin.bukkit.hook.CrazyLoginHook;
import com.github.games647.fastlogin.bukkit.hook.LogItHook;
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
import com.github.games647.fastlogin.bukkit.hook.xAuthHook;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.lang.reflect.Constructor;
@@ -53,18 +22,14 @@ public class DelayedAuthHook implements Runnable {
@Override
public void run() {
boolean hookFound = isHookFound();
if (plugin.getBungeeManager().isEnabled()) {
plugin.getLog().info("BungeeCord setting detected. No auth plugin is required");
if (plugin.getProxyManager().isEnabled()) {
plugin.getLog().info("Proxy setting detected. No auth plugin is required");
} else if (!hookFound) {
plugin.getLog().warn("No auth plugin were found by this plugin "
+ "(other plugins could hook into this after the initialization of this plugin)"
+ "and BungeeCord is deactivated. "
+ "and BungeeCord (or similar proxies) is deactivated. "
+ "Either one or both of the checks have to pass in order to use this plugin");
}
if (hookFound) {
plugin.markInitialized();
}
}
private boolean isHookFound() {
@@ -93,13 +58,13 @@ public class DelayedAuthHook implements Runnable {
private AuthPlugin<Player> getAuthHook() {
try {
@SuppressWarnings("unchecked")
List<Class<? extends AuthPlugin<Player>>> hooks = Arrays.asList(AuthMeHook.class,
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class,
xAuthHook.class);
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class,
SodionAuthHook.class, UltraAuthHook.class, xAuthHook.class);
for (Class<? extends AuthPlugin<Player>> clazz : hooks) {
String pluginName = clazz.getSimpleName();
pluginName = pluginName.substring(0, pluginName.length() - "Hook".length());
String pluginName = clazz.getSimpleName().replace("Hook", "");
//uses only member classes which uses AuthPlugin interface (skip interfaces)
if (Bukkit.getPluginManager().isPluginEnabled(pluginName)) {
//check only for enabled plugins. A single plugin could be disabled by plugin managers

View File

@@ -1,28 +1,3 @@
/*
* 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.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -50,7 +25,7 @@ public class LogItHook implements AuthPlugin<Player> {
private final FastLoginBukkit plugin;
public LogItHook(FastLoginBukkit plugin) {
protected LogItHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}

View File

@@ -1,28 +1,3 @@
/*
* 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.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -48,7 +23,7 @@ public class LoginSecurityHook implements AuthPlugin<Player> {
private final FastLoginBukkit plugin;
public LoginSecurityHook(FastLoginBukkit plugin) {
protected LoginSecurityHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}

View File

@@ -0,0 +1,53 @@
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import org.bukkit.entity.Player;
import red.mohist.sodionauth.bukkit.implementation.BukkitPlayer;
import red.mohist.sodionauth.core.SodionAuthApi;
import red.mohist.sodionauth.core.exception.AuthenticatedException;
/**
* GitHub: https://github.com/Mohist-Community/SodionAuth
* <p>
* Project page:
* <p>
* Bukkit: Unknown
* <p>
* Spigot: Unknown
*/
public class SodionAuthHook implements AuthPlugin<Player> {
private final FastLoginBukkit plugin;
protected SodionAuthHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@Override
public boolean forceLogin(Player player) {
try {
SodionAuthApi.login(new BukkitPlayer(player));
} catch (AuthenticatedException e) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
return true;
}
@Override
public boolean forceRegister(Player player, String password) {
try{
return SodionAuthApi.register(new BukkitPlayer(player), password);
} catch (UnsupportedOperationException e){
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
"It may be caused by unsupported AuthBackend");
return false;
}
}
@Override
public boolean isRegistered(String playerName) {
return SodionAuthApi.isRegistered(playerName);
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -33,7 +8,9 @@ import java.util.concurrent.Future;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import ultraauth.api.UltraAuthAPI;
import ultraauth.main.Main;
import ultraauth.managers.PlayerManager;
/**
@@ -45,9 +22,10 @@ import ultraauth.managers.PlayerManager;
*/
public class UltraAuthHook implements AuthPlugin<Player> {
private final Plugin ultraAuthPlugin = Main.main;
private final FastLoginBukkit plugin;
public UltraAuthHook(FastLoginBukkit plugin) {
protected UltraAuthHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}

View File

@@ -1,28 +1,3 @@
/*
* 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.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -49,7 +24,7 @@ public class xAuthHook implements AuthPlugin<Player> {
private final xAuth xAuthPlugin = xAuth.getPlugin();
private final FastLoginBukkit plugin;
public xAuthHook(FastLoginBukkit plugin) {
protected xAuthHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}

View File

@@ -1,35 +1,8 @@
/*
* 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;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.bukkit.ForceLoginTask;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -38,13 +11,10 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.Metadatable;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
/**
* This listener tells authentication plugins weather the player has a premium account. So the
* This listener tells authentication plugins if the player has a premium account and we checked it successfully. So the
* plugin can skip authentication.
*/
public class ConnectionListener implements Listener {
@@ -60,9 +30,6 @@ public class ConnectionListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
removeBlockedStatus(loginEvent.getPlayer());
if (loginEvent.getResult() == Result.ALLOWED && !plugin.isServerFullyStarted()) {
loginEvent.disallow(Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
}
}
@EventHandler(ignoreCancelled = true)
@@ -70,43 +37,21 @@ public class ConnectionListener implements Listener {
Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, () -> {
delayForceLogin(player);
// session exists so the player is ready for force login
// cases: Paper (firing proxy message before PlayerJoinEvent) or not running proxy and already
// having the login session from the login process
BukkitLoginSession session = plugin.getSessionManager().getLoginSession(player.getAddress());
if (session != null) {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
plugin.getProxyManager().markJoinEventFired(player);
// delay the login process to let auth plugins initialize the player
// Magic number however as there is no direct event from those plugins
}, DELAY_LOGIN);
}
private void delayForceLogin(Player player) {
// session exists so the player is ready for force login
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
// having the login session from the login process
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session == null) {
// Floodgate players usually don't have a session at this point
// exception: if force login by bungee message had been delayed
FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
return;
}
}
String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
plugin.getLog().info("No on-going login session for player: {} with ID {}. ", player, sessionId);
plugin.getLog().info("Setups using Minecraft proxies will start delayed " +
"when the command from the proxy is received");
} else {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
plugin.getBungeeManager().markJoinEventFired(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
Player player = quitEvent.getPlayer();
@@ -114,10 +59,10 @@ public class ConnectionListener implements Listener {
removeBlockedStatus(player);
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
plugin.getPremiumPlayers().remove(player.getUniqueId());
plugin.getBungeeManager().cleanup(player);
plugin.getProxyManager().cleanup(player);
}
private void removeBlockedStatus(Metadatable player) {
private void removeBlockedStatus(Player player) {
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@@ -1,66 +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;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
public class PaperCacheListener implements Listener {
private final FastLoginBukkit plugin;
public PaperCacheListener(final FastLoginBukkit plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST)
//if paper is used - player skin must be set at pre login, otherwise user cache is used
// user cache makes premium name change basically impossible
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != Result.ALLOWED) {
return;
}
// event gives us only IP, not the port, so we need to loop through all the sessions
for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
if (!event.getName().equals(session.getUsername())) {
continue;
}
session.getSkin().ifPresent(skin -> event.getPlayerProfile().setProperty(new ProfileProperty(Textures.KEY,
skin.getValue(), skin.getSignature())));
break;
}
}
}

View File

@@ -0,0 +1,42 @@
package com.github.games647.fastlogin.bukkit.listener;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.auth.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
public class PaperPreLoginListener implements Listener {
private final FastLoginBukkit plugin;
public PaperPreLoginListener(final FastLoginBukkit plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST)
//if paper is used - player skin must be set at pre login, otherwise usercache is used
//using usercache makes premium name change basically impossible
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != Result.ALLOWED) {
return;
}
// event gives us only IP, not the port, so we need to loop through all the sessions
for (BukkitLoginSession session : plugin.getSessionManager().getLoginSessions().values()) {
if (!event.getName().equals(session.getUsername())) {
continue;
}
session.getSkin().ifPresent(skin -> event.getPlayerProfile().setProperty(new ProfileProperty(Textures.KEY,
skin.getValue(), skin.getSignature())));
break;
}
}
}

View File

@@ -1,85 +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.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 org.geysermc.floodgate.api.FloodgateApi;
import static com.comphenix.protocol.PacketType.Login.Client.START;
import com.comphenix.protocol.ProtocolLibrary;
/**
* 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: https://github.com/games647/FastLogin/issues/493
*/
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();
WrappedGameProfile originalProfile = packet.getGameProfiles().read(0);
if (floodgate.getBedrockPlayer(originalProfile.getName()) == null) {
//not a Floodgate player, no need to add a prefix
return;
}
packet.setMeta("original_name", originalProfile.getName());
String prefixedName = FloodgateApi.getInstance().getPlayerPrefix() + originalProfile.getName();
WrappedGameProfile updatedProfile = originalProfile.withName(prefixedName);
packet.getGameProfiles().write(0, updatedProfile);
}
}

View File

@@ -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.bukkit.listener.protocollib;
import com.comphenix.protocol.reflect.MethodUtils;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import java.lang.reflect.InvocationTargetException;
public class SkinApplyListener implements Listener {
private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
private static final MethodAccessor GET_PROPERTIES = Accessors.getMethodAccessor(GAME_PROFILE, "getProperties");
private final FastLoginBukkit plugin;
public SkinApplyListener(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.LOW)
//run this on the loginEvent to let skins plugins see the skin like in normal Minecraft behaviour
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
if (loginEvent.getResult() != Result.ALLOWED) {
return;
}
Player player = loginEvent.getPlayer();
//go through every session, because player.getAddress is null
//loginEvent.getAddress is just a InetAddress not InetSocketAddress, so not unique enough
for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
if (session.getUsername().equals(player.getName())) {
session.getSkin().ifPresent(skin -> applySkin(player, skin.getValue(), skin.getSignature()));
break;
}
}
}
private void applySkin(Player player, String skinData, String signature) {
WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player);
WrappedSignedProperty skin = WrappedSignedProperty.fromValues(Textures.KEY, skinData, signature);
try {
gameProfile.getProperties().put(Textures.KEY, skin);
} catch (ClassCastException castException) {
//Cauldron, MCPC, Thermos, ...
Object map = GET_PROPERTIES.invoke(gameProfile.getHandle());
try {
MethodUtils.invokeMethod(map, "put", new Object[]{Textures.KEY, skin.getHandle()});
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
plugin.getLog().error("Error setting premium skin of: {}", player, ex);
}
}
}
}

View File

@@ -1,67 +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.protocolsupport;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.net.InetSocketAddress;
import protocolsupport.api.events.PlayerLoginStartEvent;
public class ProtocolLoginSource implements LoginSource {
private final PlayerLoginStartEvent loginStartEvent;
public ProtocolLoginSource(PlayerLoginStartEvent loginStartEvent) {
this.loginStartEvent = loginStartEvent;
}
@Override
public void enableOnlinemode() {
loginStartEvent.setOnlineMode(true);
}
@Override
public void kick(String message) {
loginStartEvent.denyLogin(message);
}
@Override
public InetSocketAddress getAddress() {
return loginStartEvent.getConnection().getRawAddress();
}
public PlayerLoginStartEvent getLoginStartEvent() {
return loginStartEvent;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + '{' +
"loginStartEvent=" + loginStartEvent +
'}';
}
}

View File

@@ -1,71 +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.task;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
public FloodgateAuthTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player, FloodgatePlayer floodgatePlayer) {
super(core, player, floodgatePlayer);
}
@Override
protected void startLogin() {
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
session.setVerified(isAutoAuthAllowed(autoLoginFloodgate));
// run login task
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(core.getPlugin(), forceLoginTask);
}
protected String getName(Player player) {
return player.getName();
}
protected UUID getUUID(Player player) {
return player.getUniqueId();
}
protected InetSocketAddress getAddress(Player player) {
return player.getAddress();
}
}

View File

@@ -1,4 +1,4 @@
# project data for Bukkit in order to register our plugin with all it's components
# project data for Bukkit in order to register our plugin with all it components
# ${-} are variables from Maven (pom.xml) which will be replaced after the build
name: ${project.parent.name}
version: ${project.version}-${git.commit.id.abbrev}
@@ -11,22 +11,18 @@ description: |
website: ${project.url}
dev-url: ${project.url}
# This plugin doesn't have to be transformed for compatibility with Minecraft >= 1.13
# This plugin don't have to be transformed for compatibility with Minecraft >= 1.13
api-version: '1.13'
softdepend:
# We depend on either ProtocolLib or ProtocolSupport
# We depend either ProtocolLib or ProtocolSupport
- ProtocolSupport
- ProtocolLib
# Premium variable
- PlaceholderAPI
# Bedrock Player Bridge
- Geyser-Spigot
- floodgate
# Auth plugins
- AuthMe
- LoginSecurity
- SodionAuth
- xAuth
- LogIt
- UltraAuth

View File

@@ -1,30 +1,7 @@
/*
* 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.github.games647.fastlogin.bukkit.auth.protocollib.EncryptionUtil;
import java.security.SecureRandom;
import org.junit.Test;
@@ -36,11 +13,31 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class EncryptionUtilTest {
@Test
public void testVerifyToken() {
public void testVerifyToken() throws Exception {
SecureRandom random = new SecureRandom();
byte[] token = EncryptionUtil.generateVerifyToken(random);
assertThat(token, notNullValue());
assertThat(token.length, is(4));
}
// @Test
// public void testDecryptSharedSecret() throws Exception {
//
// }
//
// @Test
// public void testDecryptData() throws Exception {
//
// }
// private static SecretKey createNewSharedKey() {
// try {
// KeyGenerator keygenerator = KeyGenerator.getInstance("AES");
// keygenerator.init(128);
// return keygenerator.generateKey();
// } catch (NoSuchAlgorithmException nosuchalgorithmexception) {
// throw new Error(nosuchalgorithmexception);
// }
// }
}

View File

@@ -1,30 +1,3 @@
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
@@ -36,7 +9,7 @@
<relativePath>../pom.xml</relativePath>
</parent>
<!--This has to be in lowercase because it's used by plugin.yml-->
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin.bungee</artifactId>
<packaging>jar</packaging>
@@ -48,7 +21,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.2.4</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
@@ -57,7 +30,6 @@
<!--Those classes are already present in BungeeCord version-->
<exclude>net.md-5:bungeecord-config</exclude>
<exclude>com.google.code.gson:gson</exclude>
<exclude>com.google.guava:guava</exclude>
</excludes>
</artifactSet>
<relocations>
@@ -70,20 +42,6 @@
<shadedPattern>fastlogin.slf4j</shadedPattern>
</relocation>
</relocations>
<!-- 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"/>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
@@ -104,16 +62,13 @@
</repository>
<repository>
<id>spigotplugins-repo</id>
<url>https://maven.gamestrike.de/mvn/</url>
<id>nukkitx-repo</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>spigotplugins-repo</id>
<url>https://maven.gamestrike.de/mvn/</url>
</repository>
</repositories>
@@ -129,54 +84,15 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<version>1.16-R0.5-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>${floodgate.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need the API, but it was excluded above -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>geyser-api</artifactId>
<version>${geyser.version}</version>
<artifactId>floodgate-bungee</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -192,14 +108,8 @@
<dependency>
<groupId>de.xxschrandxx.bca</groupId>
<artifactId>BungeeCordAuthenticator</artifactId>
<version>0.0.2</version>
<version>0.0.2-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@@ -1,32 +1,7 @@
/*
* 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;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSession;
public class BungeeLoginSession extends LoginSession {

View File

@@ -1,31 +1,6 @@
/*
* 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;
import com.github.games647.fastlogin.core.shared.LoginSource;
import com.github.games647.fastlogin.core.auth.LoginSource;
import java.net.InetSocketAddress;
@@ -46,7 +21,7 @@ public class BungeeLoginSource implements LoginSource {
}
@Override
public void enableOnlinemode() {
public void setOnlineMode() {
connection.setOnlineMode(true);
}

View File

@@ -0,0 +1,23 @@
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.SessionManager;
import java.util.UUID;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public class BungeeSessionManager extends SessionManager<PlayerDisconnectEvent, PendingConnection, BungeeLoginSession>
implements Listener {
//todo: memory leak on cancelled login event
@EventHandler
public void onPlayQuit(PlayerDisconnectEvent disconnectEvent) {
ProxiedPlayer player = disconnectEvent.getPlayer();
UUID playerId = player.getUniqueId();
endPlaySession(playerId);
}
}

View File

@@ -1,68 +1,32 @@
/*
* 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;
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
import com.github.games647.fastlogin.bungee.hook.BungeeCordAuthenticatorBungeeHook;
import com.github.games647.fastlogin.bungee.hook.BungeeCordAuthenticatorHook;
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.github.games647.fastlogin.core.message.SuccessMessage;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.MapMaker;
import com.google.common.io.ByteArrayDataOutput;
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.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.geyser.GeyserImpl;
import org.slf4j.Logger;
/**
@@ -70,18 +34,16 @@ import org.slf4j.Logger;
*/
public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSender> {
private final ConcurrentMap<PendingConnection, BungeeLoginSession> session = new MapMaker().weakKeys().makeMap();
private final BungeeSessionManager sessionManager = new BungeeSessionManager();
private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
private AsyncScheduler scheduler;
private FloodgateService floodgateService;
private GeyserService geyserService;
private Logger logger;
@Override
public void onEnable() {
logger = CommonUtil.initializeLoggerService(getLogger());
scheduler = new AsyncScheduler(logger, task -> getProxy().getScheduler().runAsync(this, task));
logger = CommonUtil.createLoggerFromJDK(getLogger());
scheduler = new AsyncScheduler(logger, getThreadFactory());
core = new FastLoginCore<>(this);
core.load();
@@ -89,18 +51,11 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
return;
}
if (isPluginInstalled("floodgate")) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
}
if (isPluginInstalled("Geyser-BungeeCord")) {
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
}
//events
PluginManager pluginManager = getProxy().getPluginManager();
boolean floodgateAvail = pluginManager.getPlugin("floodgate") != null;
ConnectListener connectListener = new ConnectListener(this, core.getRateLimiter(), floodgateAvail);
ConnectListener connectListener = new ConnectListener(this, core.getRateLimiter());
pluginManager.registerListener(this, connectListener);
pluginManager.registerListener(this, new PluginMessageListener(this));
@@ -122,29 +77,17 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
return core;
}
public ConcurrentMap<PendingConnection, BungeeLoginSession> getSession() {
return session;
}
private void registerHook() {
try {
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Arrays.asList(
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class);
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
String pluginName = clazz.getSimpleName();
pluginName = pluginName.substring(0, pluginName.length() - "Hook".length());
//uses only member classes which uses AuthPlugin interface (skip interfaces)
Plugin plugin = getProxy().getPluginManager().getPlugin(pluginName);
if (plugin != null) {
logger.info("Hooking into auth plugin: {}", pluginName);
core.setAuthPluginHook(
clazz.getDeclaredConstructor(FastLoginBungee.class).newInstance(this));
break;
}
}
} catch (ReflectiveOperationException ex) {
logger.error("Couldn't load the auth hook class", ex);
Plugin BungeeAuth = getProxy().getPluginManager().getPlugin("BungeeAuth");
if (BungeeAuth != null) {
core.setAuthPluginHook(new BungeeAuthHook());
logger.info("Hooked into BungeeAuth");
}
Plugin BungeeCordAuthenticatorBungee = getProxy().getPluginManager().getPlugin("BungeeCordAuthenticatorBungee");
if (BungeeCordAuthenticatorBungee != null) {
logger.info("Try to hook into BungeeCordAuthenticatorBungee...");
BungeeCordAuthenticatorHook hook = new BungeeCordAuthenticatorHook(BungeeCordAuthenticatorBungee, logger);
core.setAuthPluginHook(hook);
}
}
@@ -193,25 +136,4 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
public AsyncScheduler getScheduler() {
return scheduler;
}
@Override
public boolean isPluginInstalled(String name) {
return getProxy().getPluginManager().getPlugin(name) != null;
}
public FloodgateService getFloodgateService() {
return floodgateService;
}
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
}

View File

@@ -1,32 +1,7 @@
/*
* 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSession;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;

View File

@@ -1,32 +1,7 @@
/*
* 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSource;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSource;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import net.md_5.bungee.api.plugin.Event;

View File

@@ -1,33 +1,7 @@
/*
* 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
import net.md_5.bungee.api.plugin.Event;
public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
@@ -46,7 +20,7 @@ public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLogi
}
@Override
public PremiumToggleReason getReason() {
public FastLoginPremiumToggleEvent.PremiumToggleReason getReason() {
return reason;
}
}

View File

@@ -1,31 +1,5 @@
/*
* 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 me.vik1395.BungeeAuth.Main;
@@ -44,9 +18,6 @@ public class BungeeAuthHook implements AuthPlugin<ProxiedPlayer> {
private final RequestHandler requestHandler = new RequestHandler();
public BungeeAuthHook(FastLoginBungee plugin) {
}
@Override
public boolean forceLogin(ProxiedPlayer player) {
String playerName = player.getName();

View File

@@ -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:
* https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator
* <p>
* Project page:
* <p>
* Spigot: https://www.spigotmc.org/resources/bungeecordauthenticator.87669/
*/
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;
}
}
}

View File

@@ -0,0 +1,70 @@
package com.github.games647.fastlogin.bungee.hook;
import java.sql.SQLException;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import org.slf4j.Logger;
import de.xxschrandxx.bca.bungee.BungeeCordAuthenticatorBungee;
import de.xxschrandxx.bca.bungee.api.BungeeCordAuthenticatorBungeeAPI;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
/**
* GitHub:
* https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator
*
* Project page:
*
* Spigot: https://www.spigotmc.org/resources/bungeecordauthenticator.87669/
*/
public class BungeeCordAuthenticatorHook implements AuthPlugin<ProxiedPlayer> {
public final BungeeCordAuthenticatorBungeeAPI api;
public BungeeCordAuthenticatorHook(Plugin plugin, Logger logger) {
BungeeCordAuthenticatorBungee bcab = (BungeeCordAuthenticatorBungee) plugin;
api = bcab.getAPI();
logger.info("BungeeCordAuthenticatorHook | Hooked successful!");
}
@Override
public boolean forceLogin(ProxiedPlayer player) {
if (api.isAuthenticated(player)) {
return true;
} else {
try {
api.setAuthenticated(player);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
return true;
}
}
@Override
public boolean isRegistered(String playerName) {
try {
return api.getSQL().checkPlayerEntry(playerName);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean forceRegister(ProxiedPlayer player, String password) {
try {
return api.createPlayerEntry(player, password);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}

View File

@@ -1,40 +1,13 @@
/*
* 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.listener;
import com.github.games647.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.task.AsyncPremiumCheck;
import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.auth.RateLimiter;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.LoginSession;
import com.google.common.base.Throwables;
import java.lang.invoke.MethodHandle;
@@ -53,11 +26,11 @@ import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.LoginResult;
import net.md_5.bungee.connection.LoginResult.Property;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import net.md_5.bungee.protocol.Property;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.FloodgateAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,47 +41,55 @@ import org.slf4j.LoggerFactory;
public class ConnectListener implements Listener {
private static final String UUID_FIELD_NAME = "uniqueId";
private static final boolean initialHandlerClazzFound;
private static final MethodHandle uniqueIdSetter;
static {
MethodHandle setHandle = null;
boolean handlerFound = false;
try {
Lookup lookup = MethodHandles.lookup();
Class.forName("net.md_5.bungee.connection.InitialHandler");
handlerFound = true;
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
uuidField.setAccessible(true);
setHandle = lookup.unreflectSetter(uuidField);
} catch (ReflectiveOperationException reflectiveOperationException) {
} catch (ClassNotFoundException classNotFoundException) {
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
logger.error(
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
reflectiveOperationException
classNotFoundException
);
} catch (ReflectiveOperationException reflectiveOperationException) {
reflectiveOperationException.printStackTrace();
}
initialHandlerClazzFound = handlerFound;
uniqueIdSetter = setHandle;
}
private final FastLoginBungee plugin;
private final RateLimiter rateLimiter;
private final Property[] emptyProperties = {};
private final boolean floodGateAvailable;
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter) {
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter, boolean floodgateAvailable) {
this.plugin = plugin;
this.rateLimiter = rateLimiter;
this.floodGateAvailable = floodgateAvailable;
}
@EventHandler
public void onPreLogin(PreLoginEvent preLoginEvent) {
PendingConnection connection = preLoginEvent.getConnection();
if (preLoginEvent.isCancelled()) {
if (preLoginEvent.isCancelled() || isBedrockPlayer(connection.getUniqueId())) {
return;
}
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", connection);
plugin.getLog().warn("Join limit hit - Ignoring player {}", connection);
return;
}
@@ -159,8 +140,8 @@ public class ConnectListener implements Listener {
private void setOfflineId(InitialHandler connection, String username) {
try {
UUID oldPremiumId = connection.getUniqueId();
UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
final UUID oldPremiumId = connection.getUniqueId();
final UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
// BungeeCord only allows setting the UUID in PreLogin events and before requesting online mode
// However if online mode is requested, it will override previous values
@@ -172,7 +153,7 @@ public class ConnectListener implements Listener {
} catch (Exception ex) {
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
} catch (Throwable throwable) {
// throw remaining exceptions like out of memory that we shouldn't handle ourselves
// throw remaining exceptions like outofmemory that we shouldn't handle ourself
Throwables.throwIfUnchecked(throwable);
}
}
@@ -182,16 +163,6 @@ public class ConnectListener implements Listener {
ProxiedPlayer player = serverConnectedEvent.getPlayer();
Server server = serverConnectedEvent.getServer();
FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server);
plugin.getScheduler().runAsync(floodgateAuthTask);
return;
}
}
BungeeLoginSession session = plugin.getSession().get(player.getPendingConnection());
if (session == null) {
return;
@@ -210,4 +181,11 @@ public class ConnectListener implements Listener {
plugin.getSession().remove(player.getPendingConnection());
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
}
private boolean isBedrockPlayer(UUID correctedUUID) {
// Floodgate will set a correct UUID at the beginning of the PreLoginEvent
// and will cancel the online mode login for those players
// Therefore we just ignore those
return floodGateAvailable && FloodgateAPI.isBedrockPlayer(correctedUUID);
}
}

View File

@@ -1,35 +1,9 @@
/*
* 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.listener;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.github.games647.fastlogin.core.message.SuccessMessage;
@@ -69,7 +43,7 @@ public class PluginMessageListener implements Listener {
}
//the client shouldn't be able to read the messages in order to know something about server internal states
//moreover the client shouldn't be able to fake a running premium check by sending the result message
//moreover the client shouldn't be able fake a running premium check by sending the result message
pluginMessageEvent.setCancelled(true);
if (!(pluginMessageEvent.getSender() instanceof Server)) {
@@ -116,15 +90,7 @@ public class PluginMessageListener implements Listener {
}
private void onSuccessMessage(ProxiedPlayer forPlayer) {
boolean shouldPersist = forPlayer.getPendingConnection().isOnlineMode();
FloodgateService floodgateService = plugin.getFloodgateService();
if (!shouldPersist && floodgateService != null) {
// always save floodgate players to lock this username
shouldPersist = floodgateService.isBedrockPlayer(forPlayer.getUniqueId());
}
if (shouldPersist) {
if (forPlayer.getPendingConnection().isOnlineMode()) {
//bukkit module successfully received and force logged in the user
//update only on success to prevent corrupt data
BungeeLoginSession loginSession = plugin.getSession().get(forPlayer.getPendingConnection());

View File

@@ -1,36 +1,11 @@
/*
* 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.task;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.BungeeLoginSource;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.auth.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import net.md_5.bungee.api.CommandSender;
@@ -49,7 +24,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection,
String username) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin;
this.preLoginEvent = preLoginEvent;
@@ -78,7 +53,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
@Override
public void requestPremiumLogin(BungeeLoginSource source, StoredProfile profile,
String username, boolean registered) {
source.enableOnlinemode();
source.setOnlineMode();
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
String ip = source.getAddress().getAddress().getHostAddress();

View File

@@ -1,33 +1,8 @@
/*
* 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.task;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;

View File

@@ -1,79 +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.task;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
public class FloodgateAuthTask
extends FloodgateManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
private final Server server;
public FloodgateAuthTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core, ProxiedPlayer player,
FloodgatePlayer floodgatePlayer, Server server) {
super(core, player, floodgatePlayer);
this.server = server;
}
@Override
protected void startLogin() {
BungeeLoginSession session = new BungeeLoginSession(player.getName(), isRegistered, profile);
core.getPlugin().getSession().put(player.getPendingConnection(), session);
// run login task
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session,
isAutoAuthAllowed(autoLoginFloodgate));
core.getPlugin().getScheduler().runAsync(forceLoginTask);
}
@Override
protected String getName(ProxiedPlayer player) {
return player.getName();
}
@Override
protected UUID getUUID(ProxiedPlayer player) {
return player.getUniqueId();
}
@Override
protected InetSocketAddress getAddress(ProxiedPlayer player) {
return player.getAddress();
}
}

View File

@@ -1,40 +1,15 @@
/*
* 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.task;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginAutoLoginEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.auth.ForceLoginManagement;
import com.github.games647.fastlogin.core.auth.LoginSession;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import java.util.UUID;
@@ -49,21 +24,11 @@ public class ForceLoginTask
private final Server server;
//treat player as if they had a premium account, even when they don't
//use for Floodgate auto login/register
private final boolean forcedOnlineMode;
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core,
ProxiedPlayer player, Server server, BungeeLoginSession session, boolean forcedOnlineMode) {
ProxiedPlayer player, Server server, BungeeLoginSession session) {
super(core, player, session);
this.server = server;
this.forcedOnlineMode = forcedOnlineMode;
}
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core, ProxiedPlayer player,
Server server, BungeeLoginSession session) {
this(core, player, server, session, false);
}
@Override
@@ -126,6 +91,6 @@ public class ForceLoginTask
@Override
public boolean isOnlineMode() {
return forcedOnlineMode || player.getPendingConnection().isOnlineMode();
return player.getPendingConnection().isOnlineMode();
}
}

View File

@@ -12,10 +12,6 @@ softDepends:
# BungeeCord auth plugins
- BungeeAuth
- BungeeCordAuthenticatorBungee
- SodionAuth
# Bedrock Player Bridge
- Geyser-BungeeCord
- floodgate
description: |
${project.description}

View File

@@ -1,30 +1,3 @@
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
@@ -52,17 +25,6 @@
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Floodgate -->
<repository>
<id>opencollab-snapshot</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
@@ -73,29 +35,21 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</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 -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
<version>4.0.1</version>
</dependency>
<!--Logging framework implements slf4j which is required by hikari-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>2.0.0-alpha7</version>
<version>1.7.30</version>
</dependency>
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
<!-- snakeyaml is present in Bungee, Spigot, Cauldron and so we could use this independent implementation -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.16-R0.4</version>
<version>1.12-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
@@ -104,88 +58,25 @@
</exclusions>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>${floodgate.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need the API, but it was excluded above -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>geyser-api</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
</dependency>
<!--Common component for contacting the Mojang API-->
<dependency>
<groupId>com.github.games647</groupId>
<artifactId>craftapi</artifactId>
<version>0.5.3</version>
<version>0.4</version>
</dependency>
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee) -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<!-- Old version for velocity -->
<version>25.1-jre</version>
<!-- Exclude compile time dependencies not marked as such on upstream -->
<exclusions>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-annotations</artifactId>
</exclusion>
</exclusions>
<version>17.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
<version>2.2.4</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,40 +1,20 @@
/*
* 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.core;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
/**
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
* context switching between threads too. However, we need many threads for blocking HTTP and database calls.
* Nevertheless, this number can be further limited, because the number of actually working database threads
* context switching between threads too. However we need many threads for blocking HTTP and database calls.
* Nevertheless this number can be further limited, because the number of actually working database threads
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
* threads.
*/
@@ -48,26 +28,42 @@ public class AsyncScheduler {
// 30 threads are still too many - the optimal solution is to separate into processing and blocking threads
// where processing threads could only be max number of cores while blocking threads could be minimized using
// non-blocking I/O and a single event executor
private final Executor processingPool;
private final ExecutorService processingPool;
private final AtomicInteger currentlyRunning = new AtomicInteger();
/*
private final ExecutorService databaseExecutor = new ThreadPoolExecutor(1, 10,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(MAX_CAPACITY));
*/
public AsyncScheduler(Logger logger, Executor processingPool) {
public AsyncScheduler(Logger logger, ThreadFactory threadFactory) {
this.logger = logger;
this.processingPool = processingPool;
processingPool = new ThreadPoolExecutor(6, 32,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(MAX_CAPACITY), threadFactory);
}
/*
public <R> CompletableFuture<R> runDatabaseTask(Supplier<R> databaseTask) {
return CompletableFuture.supplyAsync(databaseTask, databaseExecutor)
.exceptionally(error -> {
logger.warn("Error occurred on thread pool", error);
return null;
})
// change context to the processing pool
.thenApplyAsync(r -> r, processingPool);
}
*/
public CompletableFuture<Void> runAsync(Runnable task) {
return CompletableFuture.runAsync(() -> {
currentlyRunning.incrementAndGet();
try {
task.run();
} finally {
currentlyRunning.getAndDecrement();
}
}, processingPool).exceptionally(error -> {
return CompletableFuture.runAsync(task, processingPool).exceptionally(error -> {
logger.warn("Error occurred on thread pool", error);
return null;
});
}
public void shutdown() {
MoreExecutors.shutdownAndAwaitTermination(processingPool, 1, TimeUnit.MINUTES);
//MoreExecutors.shutdownAndAwaitTermination(databaseExecutor, 1, TimeUnit.MINUTES);
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.core;
import com.github.games647.craftapi.cache.SafeCacheBuilder;
@@ -35,7 +10,7 @@ import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.jul.JDK14LoggerAdapter;
import org.slf4j.impl.JDK14LoggerAdapter;
public class CommonUtil {
@@ -70,27 +45,7 @@ public class CommonUtil {
return new String(chars);
}
/**
* This creates a SLF4J logger. In the process it initializes the SLF4J service provider. This method looks
* for the provider in the plugin jar instead of in the server jar when creating a Logger. The provider is only
* initialized once, so this method should be called early.
*
* The provider is bound to the service class `SLF4JServiceProvider`. Relocating this class makes it available
* for exclusive own usage. Other dependencies will use the relocated service too, and therefore will find the
* initialized provider.
*
* @param parent JDK logger
* @return slf4j logger
*/
public static Logger initializeLoggerService(java.util.logging.Logger parent) {
// set the class loader to the plugin one to find our own SLF4J provider in the plugin jar and not in the global
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
ClassLoader pluginLoader = CommonUtil.class.getClassLoader();
Thread.currentThread().setContextClassLoader(pluginLoader);
// Trigger provider search
LoggerFactory.getLogger(parent.getName()).info("Initialize logging service");
public static Logger createLoggerFromJDK(java.util.logging.Logger parent) {
try {
parent.setLevel(Level.ALL);
@@ -102,9 +57,6 @@ public class CommonUtil {
parent.log(Level.WARNING, "Cannot create slf4j logging adapter", reflectEx);
parent.log(Level.WARNING, "Creating logger instance manually...");
return LoggerFactory.getLogger(parent.getName());
} finally {
// restore previous class loader
Thread.currentThread().setContextClassLoader(oldLoader);
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.core;
public enum PremiumStatus {

View File

@@ -1,32 +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.core;
@FunctionalInterface
public interface RateLimiter {
boolean tryAcquire();
}

View File

@@ -0,0 +1,62 @@
package com.github.games647.fastlogin.core;
import com.github.games647.fastlogin.core.auth.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.google.common.collect.MapMaker;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
/**
* Manages player connection sessions. Login sessions that are only valid through the login process and play
* sessions that hold the stored profile object after the login process is finished and until the player leaves the
* server (Spigot) or proxy (BungeeCord).
*
* @param <C> connection object
* @param <S> platform dependent login session
*/
public abstract class SessionManager<E, C, S extends LoginSession> {
// 1 minutes should be enough as a timeout for bad internet connection (Server, Client and Mojang)
// these login sessions are only meant for during the login process not be used after
private final ConcurrentMap<C, S> loginSessions = CommonUtil.buildCache(1, 0);
private final ConcurrentMap<UUID, StoredProfile> playSessions = new MapMaker().makeMap();
public void startLoginSession(C connectionId, S session) {
loginSessions.put(connectionId, session);
}
public S getLoginSession(C connectionId) {
return loginSessions.get(connectionId);
}
public void endLoginSession(C connectionId) {
loginSessions.remove(connectionId);
}
public ConcurrentMap<C, S> getLoginSessions() {
return loginSessions;
}
public S promoteSession(C connectionId, UUID playerId) {
S loginSession = loginSessions.remove(connectionId);
StoredProfile profile = loginSession.getProfile();
playSessions.put(playerId, profile);
return loginSession;
}
public StoredProfile getPlaySession(UUID playerId) {
return playSessions.get(playerId);
}
public void endPlaySession(UUID playerId) {
playSessions.remove(playerId);
}
public abstract void onPlayQuit(E quitEvent);
public void clear() {
loginSessions.clear();
playSessions.clear();
}
}

View File

@@ -1,147 +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.core;
import com.google.common.base.Ticker;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
/**
* Limit the number of requests with a maximum size. Each requests expire after the specified time making it available
* for another request.
*/
public class TickingRateLimiter implements RateLimiter {
private final Ticker ticker;
// amount of milliseconds to expire
private final long expireTime;
// total request limit
private final int requestLimit;
private final Deque<TimeRecord> records;
private int totalRequests;
public TickingRateLimiter(Ticker ticker, int maxLimit, long expireTime) {
this.ticker = ticker;
this.requestLimit = maxLimit;
this.expireTime = expireTime;
records = new ArrayDeque<>(10);
}
/**
* Ask if access is allowed. If so register the request.
*
* @return true if allowed - false otherwise without any side effects
*/
@Override
public boolean tryAcquire() {
// current time millis is not monotonic - it can jump back depending on user choice or NTP
long nowMilli = ticker.read() / 1_000_000;
synchronized (this) {
// having synchronized will limit the amount of concurrency a lot
TimeRecord oldest = records.peekFirst();
if (oldest != null && oldest.hasExpired(nowMilli)) {
records.pop();
totalRequests -= oldest.getRequestCount();
}
// total requests reached block any further requests
if (totalRequests >= requestLimit) {
return false;
}
TimeRecord latest = records.peekLast();
if (latest == null) {
// empty list - add new record
records.add(new TimeRecord(nowMilli, expireTime));
totalRequests++;
return true;
}
int res = latest.compareTo(nowMilli);
if (res < 0) {
// now is before than the record means time jumps
throw new IllegalStateException("Time jumped back");
}
if (res == 0) {
// same minute record
latest.hit();
totalRequests++;
return true;
}
// now is one minute newer
records.add(new TimeRecord(nowMilli, expireTime));
totalRequests++;
return true;
}
}
private static class TimeRecord implements Comparable<Long> {
private final long firstMinuteRecord;
private final long expireTime;
private int count;
public TimeRecord(long firstMinuteRecord, long expireTime) {
this.firstMinuteRecord = firstMinuteRecord;
this.expireTime = expireTime;
this.count = 1;
}
public void hit() {
count++;
}
public int getRequestCount() {
return count;
}
public boolean hasExpired(long now) {
return firstMinuteRecord + expireTime <= now;
}
@Override
public int compareTo(Long other) {
if (other < firstMinuteRecord) {
return -1;
}
if (other > firstMinuteRecord + TimeUnit.MINUTES.toMillis(1)) {
return +1;
}
return 0;
}
}
}

View File

@@ -1,32 +1,9 @@
/*
* 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.core.shared;
package com.github.games647.fastlogin.core.auth;
import com.github.games647.fastlogin.core.storage.SQLStorage;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.github.games647.fastlogin.core.storage.AuthStorage;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
@@ -55,7 +32,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
return;
}
SQLStorage storage = core.getStorage();
AuthStorage storage = core.getStorage();
StoredProfile playerProfile = session.getProfile();
try {
if (isOnlineMode()) {

View File

@@ -1,35 +1,10 @@
/*
* 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.core.shared;
package com.github.games647.fastlogin.core.auth;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.util.Optional;
@@ -40,12 +15,10 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
protected final FastLoginCore<P, C, ?> core;
protected final AuthPlugin<P> authHook;
private final BedrockService<?> bedrockService;
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook, BedrockService<?> bedrockService) {
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
this.core = core;
this.authHook = authHook;
this.bedrockService = bedrockService;
}
public void onLogin(String username, S source) {
@@ -55,14 +28,6 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
return;
}
//check if the player is connecting through Bedrock Edition
if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
//perform Bedrock specific checks and skip Java checks, if they are not needed
if (bedrockService.performChecks(username, source)) {
return;
}
}
callFastLoginPreLoginEvent(username, source, profile);
Configuration config = core.getConfig();
@@ -75,9 +40,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
requestPremiumLogin(source, profile, username, true);
} else {
if (isValidUsername(source, profile)) {
startCrackedSession(source, profile, username);
}
startCrackedSession(source, profile, username);
}
} else {
if (core.getPendingLogin().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
@@ -93,7 +56,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
premiumUUID = core.getResolver().findProfile(username);
}
if (premiumUUID.isEmpty()
if (!premiumUUID.isPresent()
|| (!checkNameChange(source, username, premiumUUID.get())
&& !checkPremiumName(source, username, profile))) {
//nothing detected the player as premium -> start a cracked session
@@ -115,16 +78,6 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
}
}
protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception {
if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
source.kick("Your username contains illegal characters");
return false;
}
return true;
}
private boolean checkPremiumName(S source, String username, StoredProfile profile) throws Exception {
core.getPlugin().getLog().info("GameProfile {} uses a premium username", username);
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {

View File

@@ -1,32 +1,7 @@
/*
* 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.core.shared;
package com.github.games647.fastlogin.core.auth;
import com.github.games647.fastlogin.core.StoredProfile;
import com.google.common.base.MoreObjects;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.google.common.base.Objects;
import java.util.UUID;
@@ -34,7 +9,7 @@ public abstract class LoginSession {
private final StoredProfile profile;
private final String requestUsername;
private String requestUsername;
private String username;
private UUID uuid;
@@ -91,7 +66,7 @@ public abstract class LoginSession {
@Override
public synchronized String toString() {
return MoreObjects.toStringHelper(this)
return Objects.toStringHelper(this)
.add("profile", profile)
.add("requestUsername", requestUsername)
.add("username", username)

View File

@@ -0,0 +1,12 @@
package com.github.games647.fastlogin.core.auth;
import java.net.InetSocketAddress;
public interface LoginSource {
void setOnlineMode() throws Exception;
void kick(String message) throws Exception;
InetSocketAddress getAddress();
}

View File

@@ -0,0 +1,41 @@
package com.github.games647.fastlogin.core.auth;
/**
* Limit the number of requests with a maximum size. Each requests expires after the specified time making it available
* for another request.
*/
public class RateLimiter {
private final long[] requests;
private final long expireTime;
private int position;
public RateLimiter(int maxLimit, long expireTime) {
this.requests = new long[maxLimit];
this.expireTime = expireTime;
}
/**
* Ask if access is allowed. If so register the request.
*
* @return true if allowed - false otherwise without any side effects
*/
public boolean tryAcquire() {
// current time millis is not monotonic - it can jump back depending on user choice or NTP
long now = System.nanoTime() / 1_000_000;
// after this the request should be expired
long toBeExpired = now - expireTime;
synchronized (this) {
// having synchronized will limit the amount of concurrency a lot
long oldest = requests[position];
if (oldest < toBeExpired) {
requests[position] = now;
position = (position + 1) % requests.length;
return true;
}
return false;
}
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.core.hooks;
/**
@@ -72,7 +47,7 @@ public interface AuthPlugin<P> {
/**
* Checks whether an account exists for this player name.
*
* This check should check if a cracked player account exists,
* 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.
*

View File

@@ -1,28 +1,3 @@
/*
* 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.core.hooks;
import java.security.SecureRandom;

View File

@@ -1,28 +1,3 @@
/*
* 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.core.hooks;
@FunctionalInterface

View File

@@ -1,135 +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.core.hooks.bedrock;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.io.IOException;
import java.util.Optional;
import java.util.UUID;
/**
* @param <B> is an instance of either FloodgatePlayer or GeyserSession
*/
public abstract class BedrockService<B> {
protected final FastLoginCore<?, ?, ?> core;
protected final String allowConflict;
public BedrockService(FastLoginCore<?, ?, ?> core) {
this.core = core;
this.allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
}
/**
* Perform every packet level check needed on a Bedrock player.
*
* @param username the name of the player
* @param source an instance of LoginSource
* @return true if Java specific checks can be skipped
*/
public abstract boolean performChecks(String username, LoginSource source);
/**
* Check if the player's name conflicts an existing Java player's name, and kick
* them if it does
*
* @param username the name of the player
* @param source an instance of LoginSource
*/
protected void checkNameConflict(String username, LoginSource source) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException ioEx) {
core.getPlugin().getLog().error(
"Could not check whether Bedrock Player {}'s name conflicts a premium Java player's name.",
username);
kickPlayer(source, username, "Could not check if your name conflicts an existing " +
"premium Java account's name. This is usually a serverside error.");
} catch (RateLimitException rateLimitException) {
core.getPlugin().getLog().warn("Mojang API rate limit hit");
kickPlayer(source, username, "Could not check if your name conflicts an existing premium " +
"Java account's name. Try again in a few minutes");
}
if (premiumUUID.isPresent()) {
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
username);
kickPlayer(source, username, "Your name conflicts an existing premium Java account's name");
}
}
private void kickPlayer(LoginSource source, String username, String message) {
try {
source.kick(message);
} catch (Exception ex) {
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
}
}
/**
* The Floodgate / Geyser API does not support querying players by name, so this function
* iterates over every online Bedrock Player 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 Bedrock Player if found, null otherwise
*/
public B getBedrockPlayer(String prefixedUsername) {
return null;
}
public B getBedrockPlayer(UUID uuid) {
return null;
}
public boolean isBedrockPlayer(UUID uuid) {
return getBedrockPlayer(uuid) != null;
}
public boolean isBedrockConnection(String username) {
return getBedrockPlayer(username) != null;
}
/**
* Checks if a profile's name starts with the Floodgate prefix, if it's available
* @param profile profile of the connecting player
* @return true if the username is forbidden
*/
public boolean isUsernameForbidden(StoredProfile profile) {
return false;
}
}

View File

@@ -1,136 +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.core.hooks.bedrock;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.util.Locale;
import java.util.UUID;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public class FloodgateService extends BedrockService<FloodgatePlayer> {
private final FloodgateApi floodgate;
public FloodgateService(FloodgateApi floodgate, FastLoginCore<?, ?, ?> core) {
super(core);
this.floodgate = floodgate;
}
/**
* Checks if a config entry (related to Floodgate) is valid. <br>
* Writes to Log if the value is invalid.
* <p>
* This should be used for:
* <ul>
* <li>allowFloodgateNameConflict
* <li>autoLoginFloodgate
* <li>autoRegisterFloodgate
* </ul>
* </p>
*
* @param key the key of the entry in config.yml
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
*/
public boolean isValidFloodgateConfigString(String key) {
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
core.getPlugin().getLog().error("Invalid value detected for {} in FastLogin/config.yml.", key);
return false;
}
return true;
}
@Override
public boolean isUsernameForbidden(StoredProfile profile) {
String playerPrefix = floodgate.getPlayerPrefix();
return profile.getName().startsWith(playerPrefix) && !playerPrefix.isEmpty();
}
@Override
public boolean performChecks(String username, LoginSource source) {
// check if the Bedrock player is linked to a Java account
FloodgatePlayer floodgatePlayer = getBedrockPlayer(username);
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
if ("false".equals(allowConflict)
|| "linked".equals(allowConflict) && !isLinked) {
super.checkNameConflict(username, source);
} else {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
}
//Floodgate users don't need Java specific checks
return true;
}
/**
* 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;
}
}
return null;
}
public FloodgatePlayer getBedrockPlayer(UUID uuid) {
return floodgate.getPlayer(uuid);
}
public boolean isBedrockPlayer(UUID uuid) {
return getBedrockPlayer(uuid) != null;
}
public boolean isBedrockConnection(String username) {
return getBedrockPlayer(username) != null;
}
}

View File

@@ -1,75 +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.core.hooks.bedrock;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.util.UUID;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.auth.AuthType;
public class GeyserService extends BedrockService<GeyserSession> {
private final GeyserImpl geyser;
private final FastLoginCore<?, ?, ?> core;
private final AuthType authType;
public GeyserService(GeyserImpl geyser, FastLoginCore<?, ?, ?> core) {
super(core);
this.geyser = geyser;
this.core = core;
this.authType = GeyserImpl.getInstance().getConfig().getRemote().getAuthType();
}
@Override
public boolean performChecks(String username, LoginSource source) {
// AuthType.FLOODGATE will be handled by FloodgateService
if (authType == AuthType.ONLINE) {
// authenticate everyone, as if they were Java players, since they have signed
// in through Mojang
return false;
}
if ("true".equals(allowConflict)) {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
} else {
super.checkNameConflict(username, source);
}
return true;
}
@Override
public GeyserSession getBedrockPlayer(String username) {
return geyser.connectionByName(username);
}
@Override
public GeyserSession getBedrockPlayer(UUID uuid) {
return geyser.connectionByUuid(uuid);
}
}

View File

@@ -1,28 +1,3 @@
/*
* 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.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -1,28 +1,3 @@
/*
* 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.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -1,28 +1,3 @@
/*
* 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.core.message;
import com.google.common.io.ByteArrayDataInput;
@@ -80,7 +55,7 @@ public class LoginActionMessage implements ChannelMessage {
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
output.writeUTF(playerName);
//proxy identifier to check if it's an acceptable proxy
//proxy identifier to check if it's a acceptable proxy
output.writeLong(proxyId.getMostSignificantBits());
output.writeLong(proxyId.getLeastSignificantBits());
}

View File

@@ -1,28 +1,3 @@
/*
* 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.core.message;
public class NamespaceKey {

View File

@@ -1,28 +1,3 @@
/*
* 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.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -1,25 +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.
*/

View File

@@ -1,77 +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.core.mojang;
import com.github.games647.craftapi.model.auth.Verification;
import com.github.games647.craftapi.resolver.MojangResolver;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.util.Optional;
/**
* An extension to {@link MojangResolver} which allows connection using transparent reverse proxies.
* The significant difference is that unlike MojangResolver from the CraftAPI implementation, which sends the "ip" parameter
* when the hostIp parameter is an IPv4 address, but skips it for IPv6, this implementation leaves out the "ip" parameter
* also for IPv4, effectively enabling transparent proxies to work.
* @author games647, Enginecrafter77
*/
public class ProxyAgnosticMojangResolver extends MojangResolver {
/**
* A formatting string containing an URL used to call the {@code hasJoined} method on mojang session servers.
*
* Formatting parameters:
* 1. The username of the player in question
* 2. The serverId of this server
*/
public static final String MOJANG_SESSIONSERVER_HASJOINED_CALL_URLFMT = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s";
@Override
public Optional<Verification> hasJoined(String username, String serverHash, InetAddress hostIp) throws IOException
{
String url = String.format(MOJANG_SESSIONSERVER_HASJOINED_CALL_URLFMT, username, serverHash);
HttpURLConnection conn = this.getConnection(url);
int responseCode = conn.getResponseCode();
Verification verification = null;
// Mojang session servers send HTTP 204 (NO CONTENT) when the authentication seems invalid
// If that's not our case, the authentication is valid, and so we can parse the response.
if(responseCode != HttpURLConnection.HTTP_NO_CONTENT)
verification = this.parseRequest(conn, this::parseVerification);
return Optional.ofNullable(verification);
}
// Functional implementation of InputStreamAction, used in hasJoined method in parseRequest call
protected Verification parseVerification(InputStream input) throws IOException
{
return this.readJson(input, Verification.class);
}
}

View File

@@ -1,25 +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.
*/

View File

@@ -1,43 +1,13 @@
/*
* 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.core.shared;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
import com.github.games647.fastlogin.core.storage.AuthStorage;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.TickingRateLimiter;
import com.github.games647.fastlogin.core.auth.RateLimiter;
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;
@@ -84,10 +54,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
private final Collection<UUID> pendingConfirms = new HashSet<>();
private final T plugin;
private MojangResolver resolver;
private final MojangResolver resolver = new MojangResolver();
private Configuration config;
private SQLStorage storage;
private AuthStorage storage;
private RateLimiter rateLimiter;
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
private AuthPlugin<P> authPlugin;
@@ -119,14 +89,17 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
return;
}
// Initialize the resolver based on the config parameter
this.resolver = this.config.getBoolean("useProxyAgnosticResolver", false) ? new ProxyAgnosticMojangResolver() : new MojangResolver();
int maxCon = config.getInt("anti-bot.connections", 200);
long expireTime = config.getLong("anti-bot.expire", 5) * 60 * 1_000L;
if (expireTime > MAX_EXPIRE_RATE) {
expireTime = MAX_EXPIRE_RATE;
}
rateLimiter = createRateLimiter(config.getSection("anti-bot"));
rateLimiter = new RateLimiter(maxCon, expireTime);
Set<Proxy> proxies = config.getStringList("proxies")
.stream()
.map(HostAndPort::fromString)
.map(proxy -> new InetSocketAddress(proxy.getHost(), proxy.getPort()))
.map(proxy -> new InetSocketAddress(proxy.getHostText(), proxy.getPort()))
.map(sa -> new Proxy(Type.HTTP, sa))
.collect(toSet());
@@ -144,22 +117,6 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
resolver.setOutgoingAddresses(addresses);
}
private RateLimiter createRateLimiter(Configuration botSection) {
boolean enabled = botSection.getBoolean("enabled", true);
if (!enabled) {
// no-op rate limiter
return () -> true;
}
int maxCon = botSection.getInt("anti-bot.connections", 200);
long expireTime = botSection.getLong("anti-bot.expire", 5) * 60 * 1_000L;
if (expireTime > MAX_EXPIRE_RATE) {
expireTime = MAX_EXPIRE_RATE;
}
return new TickingRateLimiter(Ticker.systemTicker(), maxCon, expireTime);
}
private Configuration loadFile(String fileName) throws IOException {
ConfigurationProvider configProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
@@ -187,7 +144,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
return resolver;
}
public SQLStorage getStorage() {
public AuthStorage getStorage() {
return storage;
}
@@ -207,37 +164,26 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
}
public boolean setupDatabase() {
String driver = config.getString("driver");
if (!checkDriver(driver)) {
if (!checkDriver(config.getString("driver"))) {
return false;
}
HikariConfig databaseConfig = new HikariConfig();
databaseConfig.setDriverClassName(driver);
databaseConfig.setDriverClassName(config.getString("driver"));
String host = config.get("host", "");
int port = config.get("port", 3306);
String database = config.getString("database");
boolean useSSL = config.get("useSSL", false);
databaseConfig.setUsername(config.get("username", ""));
databaseConfig.setPassword(config.getString("password"));
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
if (driver.contains("sqlite")) {
storage = new SQLiteStorage(this, database, databaseConfig);
} else {
String host = config.get("host", "");
int port = config.get("port", 3306);
boolean useSSL = config.get("useSSL", false);
if (useSSL) {
databaseConfig.addDataSourceProperty("allowPublicKeyRetrieval", config.getBoolean("allowPublicKeyRetrieval", false));
databaseConfig.addDataSourceProperty("serverRSAPublicKeyFile", config.getString("ServerRSAPublicKeyFile"));
databaseConfig.addDataSourceProperty("sslMode", config.getString("sslMode", "Required"));
}
databaseConfig.setUsername(config.get("username", ""));
databaseConfig.setPassword(config.getString("password"));
storage = new MySQLStorage(this, driver, host, port, database, databaseConfig, useSSL);
}
storage = new AuthStorage(this, host, port, database, databaseConfig, useSSL);
try {
storage.createTables();
return true;
@@ -254,8 +200,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
} 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);
log.warn("Please choose MySQL (Spigot+BungeeCord), SQLite (Spigot+Sponge) or MariaDB (Sponge)", notFoundEx);
}
return false;
@@ -312,6 +257,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
public void close() {
plugin.getLog().info("Safely shutting down scheduler. This could take up to one minute.");
plugin.getScheduler().shutdown();
if (storage != null) {
storage.close();

View File

@@ -1,178 +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.core.shared;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Optional;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public abstract class FloodgateManagement<P extends C, C, L extends LoginSession, T extends PlatformPlugin<C>>
implements Runnable {
protected final FastLoginCore<P, C, T> core;
protected final P player;
private final FloodgatePlayer floodgatePlayer;
private final String username;
//config.yml values that might be accessed by multiple methods
protected final String autoLoginFloodgate;
protected final String autoRegisterFloodgate;
protected final String allowNameConflict;
//variables initialized through run() and accesses by subclass
protected boolean isRegistered;
protected StoredProfile profile;
protected boolean isLinked;
public FloodgateManagement(FastLoginCore<P, C, T> core, P player, FloodgatePlayer floodgatePlayer) {
this.core = core;
this.player = player;
this.floodgatePlayer = floodgatePlayer;
this.username = getName(player);
//load values from config.yml
autoLoginFloodgate = core.getConfig().get("autoLoginFloodgate").toString().toLowerCase();
autoRegisterFloodgate = core.getConfig().get("autoRegisterFloodgate").toString().toLowerCase();
allowNameConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
}
@Override
public void run() {
core.getPlugin().getLog().info("Player {} is connecting through Geyser Floodgate.", username);
// check if the Bedrock player is linked to a Java account
isLinked = floodgatePlayer.getLinkedPlayer() != null;
//this happens on Bukkit if it's connected to Bungee
//if that's the case, players will be logged in via plugin messages
if (core.getStorage() == null) {
return;
}
profile = core.getStorage().loadProfile(username);
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
try {
//maybe Bungee without auth plugin
if (authPlugin == null) {
if (profile != null) {
isRegistered = profile.isPremium();
} else {
isRegistered = false;
}
} else {
isRegistered = authPlugin.isRegistered(username);
}
} catch (Exception ex) {
core.getPlugin().getLog().error(
"An error has occurred while checking if player {} is registered",
username, ex);
return;
}
//decide if checks should be made for conflicting Java player names
if (isNameCheckRequired()) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID;
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check whether Floodgate Player {}'s name conflicts a premium Java account's name.",
username, e);
return;
}
//stop execution if player's name is conflicting
if (premiumUUID.isPresent()) {
return;
}
}
if (!isRegistered && !isAutoAuthAllowed(autoRegisterFloodgate)) {
return;
}
//logging in from bedrock for a second time threw an error with UUID
if (profile == null) {
profile = new StoredProfile(getUUID(player), username, true, getAddress(player).toString());
}
//start Bukkit/Bungee specific tasks
startLogin();
}
/**
* Decide if the player can be automatically registered or logged in.<br>
* The config option 'non-conflicting' is ignored by this function, as name
* conflicts are checked by a different part of the code.
*
* @param configValue the value of either 'autoLoginFloodgate' or
* 'autoRegisterFloodgate' from config.yml
* @return true if the Player can be registered automatically
*/
protected boolean isAutoAuthAllowed(String configValue) {
return "true".equals(configValue)
|| "no-conflict".equals(configValue) // this was checked before
|| ("linked".equals(configValue) && isLinked);
}
/**
* Decides whether checks for conflicting Java names should be made
* @return ture if an API call to Mojang is needed
*/
private boolean isNameCheckRequired() {
//linked players have the same name as their Java profile
//OR
//if allowNameConflict is 'false' or 'linked' and the player had a conflicting
//name, then they would have been kicked in FloodgateHook#checkNameConflict
if (isLinked || !"true".equals(allowNameConflict)) {
return false;
}
//autoRegisterFloodgate should only be checked if then player is not yet registered
if (!isRegistered && "no-conflict".equals(autoRegisterFloodgate)) {
return true;
}
return "no-conflict".equals(autoLoginFloodgate);
}
protected abstract void startLogin();
protected abstract String getName(P player);
protected abstract UUID getUUID(P player);
protected abstract InetSocketAddress getAddress(P player);
}

View File

@@ -1,37 +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.core.shared;
import java.net.InetSocketAddress;
public interface LoginSource {
void enableOnlinemode() throws Exception;
void kick(String message) throws Exception;
InetSocketAddress getAddress();
}

View File

@@ -1,32 +1,6 @@
/*
* 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.core.shared;
import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path;
@@ -46,21 +20,17 @@ public interface PlatformPlugin<C> {
AsyncScheduler getScheduler();
boolean isPluginInstalled(String name);
default void sendMultiLineMessage(C receiver, String message) {
for (String line : message.split("%nl%")) {
sendMessage(receiver, line);
}
}
BedrockService<?> getBedrockService();
default ThreadFactory getThreadFactory() {
return new ThreadFactoryBuilder()
.setNameFormat(getName() + " Pool Thread #%1$d")
// Hikari create daemons by default. We could daemon threads for our own scheduler too
// because we safely shut down
// Hikari create daemons by default and we could daemon threads for our own scheduler too
// because we safely shutdown
.setDaemon(true)
.build();
}

Some files were not shown because too many files have changed in this diff Show More