Compare commits

...

132 Commits
test ... 2.0

Author SHA1 Message Date
games647
ad815777d4 Send login command from proxy immediately 2024-05-21 21:55:23 +02:00
games647
9a400f5ae1 Only print premium warning on command sender site 2024-05-21 21:53:30 +02:00
games647
c7254034bb Modularize authentication backends 2024-05-21 17:07:09 +02:00
games647
7a8e5a59d0 Restore older Java compatibility 2024-05-21 17:04:41 +02:00
games647
d04e421927 Migrate to new HTTP client 2024-05-21 15:09:45 +02:00
games647
6005f0db44 Minor clean up 2024-05-21 15:09:28 +02:00
games647
f50004f50d Drop configuration for outgoing IP addresses 2024-05-21 15:08:12 +02:00
games647
b6b95d50e5 Update HikariCP 2024-05-21 14:47:34 +02:00
games647
be2ec1e5a8 Clean up methods names and documentation 2024-05-21 14:41:41 +02:00
games647
e9643ee3e2 Simplify bug report template by dropping expected behavior 2024-05-21 12:37:02 +02:00
games647
f1b780c398 Clarify pending logins methods 2024-05-11 11:15:13 +02:00
games647
33d3c751b9 Sanity check password generator 2024-05-11 11:13:52 +02:00
games647
00c0bd3b7b Reduce build dependency bloat 2024-05-11 11:13:36 +02:00
games647
492a17e7de Re-enable paper release repo to fix retrieving bungeecord and datafix 2024-05-10 12:20:39 +02:00
games647
c063e7b58d Added shouldAuthenticate field for ProtocolLib
Related #1202
2024-05-10 12:10:31 +02:00
games647
0c64597ff0 Override packet types until they are registered at ProtocolLib
Related #1202
2024-05-10 12:07:47 +02:00
games647
9c06401e69 Fail safely if MinecraftEncryption is not found in newer versions 2024-05-10 12:06:52 +02:00
games647
1f9253895c Document missing premium parameter 2024-05-10 12:06:20 +02:00
games647
41a23bb292 Netty is no longer needed for tests 2024-05-10 10:09:24 +02:00
games647
756b777056 Use a better method name for StoredProfile.isPremium 2024-05-10 10:09:12 +02:00
games647
204d25a739 Re-order and remove outdated auth plugin documentation 2024-05-10 10:03:18 +02:00
games647
07e19b590a Fix missing class 2024-05-08 09:33:36 +02:00
games647
bb78043d64 Run delayed velocity tasks under our scheduler too 2024-05-07 20:31:55 +02:00
games647
7b6d2062cf Update license year 2024-05-06 16:40:24 +02:00
games647
3473611b90 Enforce stricter permissions on GitHub actions 2024-05-06 11:18:48 +02:00
games647
9fabc69ba9 Increase dependabot to monthly updates.
There are not many critical changes nowadays.
2024-05-06 11:18:28 +02:00
games647
5a782137af Exclude redundant snakeyaml dependency in BungeeCord 2024-05-06 11:17:44 +02:00
games647
4068fd06db Update platform dependencies 2024-05-06 11:17:16 +02:00
games647
1419b7d357 Use transitive dependencies from craftapi instead of explicitly 2024-05-06 11:16:42 +02:00
games647
690eabaa5e Use reflection for test to fix compiling core to older Java versions 2024-05-06 09:40:07 +02:00
games647
caf5188246 Experimental bump of BungeeCord module to Java 17
Java 17+ and 21 are LTS releases. The other proxy Velocity
also includes Java 17. Ubuntu 24 LTS includes Java 21 already.
However, Ubuntu 22 LTS only uses Java 11, so it might be
necessary to fallback although Ubuntu 23 includes it.
Nevertheless, third-party JDK installations are also a thing
and Minecraft 1.20.6 nowadays also requires Java 21.
2024-05-05 13:29:06 +02:00
games647
c905ca3d33 Move excluded shaded list to dependencies directly
It seems to be easier where the dependencies are coming from.
2024-05-05 13:23:07 +02:00
games647
47b6835f37 Merge pull request #1200 from Freyhold/main
add removed dependency in last commit 8e35c5d that updated dependency
2024-05-05 13:20:07 +02:00
hubert-praca
884a4e0d65 Add critical guava and gson back from craftapi
Co-authored-by: games647 <games647@users.noreply.github.com>
2024-05-05 13:18:07 +02:00
games647
0ac8481d92 Synchronize velocity java version with upstream 2024-05-05 10:18:27 +02:00
games647
f0209170c7 Exclude database windows authentication in velocity
It's very unlikely this is really needed.
2024-05-03 16:00:10 +02:00
games647
e63642b146 Unlock yaml, because we are shipping it now 2024-05-03 15:59:20 +02:00
games647
d58ef6b0a1 Add snakeyaml back 2024-05-03 11:18:15 +02:00
games647
8e35c5df90 Update dependencies 2024-05-03 10:43:57 +02:00
games647
cf4d19aeca Update deps 2024-05-02 10:57:51 +02:00
games647
7479c8be87 Update compiler plugin to fix GH runner 2024-05-02 10:57:42 +02:00
games647
1889c2605e Add unit test for multi-release scheduler 2024-05-02 10:57:10 +02:00
games647
3925b66511 Merge pull request #1179 from games647/dependabot/github_actions/advanced-security/maven-dependency-submission-action-4.0.2
Bump advanced-security/maven-dependency-submission-action from 4.0.0 to 4.0.2
2024-04-30 16:04:10 +02:00
games647
3f47356d35 Merge pull request #1195 from games647/dependabot/maven/production-dependencies-1cdc2e235a
Bump the production-dependencies group across 1 directory with 6 updates
2024-04-30 16:03:51 +02:00
games647
20c2126e53 Merge pull request #1191 from games647/dependabot/maven/development-dependencies-35f3e2a187
Bump the development-dependencies group with 3 updates
2024-04-30 16:03:13 +02:00
dependabot[bot]
e1335dccfe Bump the production-dependencies group across 1 directory with 6 updates
Bumps the production-dependencies group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.7` | `10.16.0` |
| [org.projectlombok:lombok](https://github.com/projectlombok/lombok) | `1.18.30` | `1.18.32` |
| [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) | `3.3.0` | `3.4.1` |
| org.slf4j:slf4j-jdk14 | `2.0.11` | `2.0.13` |
| [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) | `3.5.1` | `3.5.3` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.3.2` | `3.3.3` |



Updates `com.puppycrawl.tools:checkstyle` from 10.12.7 to 10.16.0
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.7...checkstyle-10.16.0)

Updates `org.projectlombok:lombok` from 1.18.30 to 1.18.32
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.30...v1.18.32)

Updates `org.apache.maven.plugins:maven-jar-plugin` from 3.3.0 to 3.4.1
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.1)

Updates `org.slf4j:slf4j-jdk14` from 2.0.11 to 2.0.13

Updates `org.apache.maven.plugins:maven-shade-plugin` from 3.5.1 to 3.5.3
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.1...maven-shade-plugin-3.5.3)

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.3.2 to 3.3.3
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.3.2...3.3.3)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-30 13:59:35 +00:00
games647
b9e94d3020 Improve threading by making use of green threads with Java 21
This is an experiment. The code was checked to keep blocking
of platform threads to a minimum (See [1]). This will keep
overhead to of using threads small while only I/O will
allocate more threads.

The project now uses Multi-Release Jars, so it will detect
correct version during runtime while keeping backwards
compatibility. However, your IDE might be set manually to
Java 21. A multi-project [2] architecture might be necessary,
but not tested if it really fixes it.

[1] https://openjdk.org/jeps/444
[2] https://maven.apache.org/plugins/maven-compiler-plugin/multirelease.html
2024-04-30 15:57:02 +02:00
games647
896e250fa2 Fix setting offline UUID with newer BungeeCord
Fixes #1189
Fixes #1193
2024-04-30 10:11:48 +02:00
dependabot[bot]
815ff39c96 Bump the development-dependencies group with 3 updates
Bumps the development-dependencies group with 3 updates: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5), [org.mockito:mockito-core](https://github.com/mockito/mockito) and [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java).


Updates `org.junit.jupiter:junit-jupiter` from 5.10.1 to 5.10.2
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.10.1...r5.10.2)

Updates `org.mockito:mockito-core` from 5.9.0 to 5.11.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.9.0...v5.11.0)

Updates `org.bouncycastle:bcprov-jdk18on` from 1.77 to 1.78.1
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-22 07:11:16 +00:00
dependabot[bot]
4100daa22a Bump advanced-security/maven-dependency-submission-action
Bumps [advanced-security/maven-dependency-submission-action](https://github.com/advanced-security/maven-dependency-submission-action) from 4.0.0 to 4.0.2.
- [Release notes](https://github.com/advanced-security/maven-dependency-submission-action/releases)
- [Commits](https://github.com/advanced-security/maven-dependency-submission-action/compare/v4.0.0...v4.0.2)

---
updated-dependencies:
- dependency-name: advanced-security/maven-dependency-submission-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 07:57:04 +00:00
games647
a65a5f3020 Make ignore states more verbose in Velocity 2024-02-13 16:54:23 +01:00
games647
8a729e069d Use current link for hastebin 2024-02-13 16:54:22 +01:00
games647
d89d332273 Minor code recommendations 2024-02-13 16:54:22 +01:00
games647
cd3cfef6d4 Do not encapsulate the task twice in Velocity 2024-02-13 16:54:22 +01:00
games647
6ec6e4844d Bump dependencies 2024-02-13 16:54:22 +01:00
games647
60a65377b8 Hint proxy setup guide and out of date versions 2024-02-13 16:54:22 +01:00
games647
ffbf0ae3f4 Merge pull request #1151 from games647/dependabot/github_actions/advanced-security/maven-dependency-submission-action-4.0.0
Bump advanced-security/maven-dependency-submission-action from 3.0.2 to 4.0.0
2024-02-01 11:38:47 +01:00
dependabot[bot]
4cf65cf7e5 Bump advanced-security/maven-dependency-submission-action
Bumps [advanced-security/maven-dependency-submission-action](https://github.com/advanced-security/maven-dependency-submission-action) from 3.0.2 to 4.0.0.
- [Release notes](https://github.com/advanced-security/maven-dependency-submission-action/releases)
- [Commits](https://github.com/advanced-security/maven-dependency-submission-action/compare/v3.0.2...v4.0.0)

---
updated-dependencies:
- dependency-name: advanced-security/maven-dependency-submission-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 07:45:51 +00:00
games647
dbf5ae2fae [Velocity] Fix plugin resuming event processing if login is not handled
This causes login timeouts if this plugin doesn't handle the login for
cases like:

* Anti-Bot is triggered
* Another plugin already denied the login

Fixes #1146
2024-01-23 13:59:49 +01:00
games647
707572a007 Add core module name 2024-01-16 14:08:47 +01:00
games647
108f5ad324 Transform velocity MariaDB transformers too
Otherwise, authentication plugin drivers couldn't be found.
2024-01-15 17:01:02 +01:00
games647
2112d06162 Increase encryption key size for Spigot protocol
1024 bits are very weak keys. This size equals vanillas implementation.
Therefore, 2048 goes out of spec, but works and requires only minimal
additional performance for improved security.

The consequence will be during the login and playing in onlinemode.
First for authenticating and second for the encryption of all following
packets.
2024-01-15 16:37:48 +01:00
games647
aece7f855d Update Java CI version 2024-01-15 16:29:26 +01:00
games647
33b4ac8494 [ci-skip] Fully qualify dependabot versions 2024-01-15 16:29:16 +01:00
games647
09161b86dd Merge pull request #1142 from games647/dependabot/maven/production-dependencies-eb968b0e20
Bump the production-dependencies group with 5 updates
2024-01-15 16:25:55 +01:00
games647
57833bb40b Merge pull request #1133 from games647/dependabot/github_actions/github/codeql-action-3
Bump github/codeql-action from 2 to 3
2024-01-15 16:23:45 +01:00
games647
a1414a38ff Merge pull request #1141 from games647/dependabot/maven/development-dependencies-ca802ab3b6
Bump the development-dependencies group with 1 update
2024-01-15 16:23:24 +01:00
games647
0021bc476d Merge pull request #709 from Smart123s/feature/floodgate/newdb
Differentiate Floodgate players in database
2024-01-15 16:22:34 +01:00
dependabot[bot]
4b1e08a2f8 Bump the production-dependencies group with 5 updates
Bumps the production-dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.5` | `10.12.7` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.2.2` | `3.2.5` |
| org.slf4j:slf4j-jdk14 | `2.0.9` | `2.0.11` |
| com.lenis0012.bukkit:loginsecurity | `3.2.1` | `3.3.0` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.3.1` | `3.3.2` |


Updates `com.puppycrawl.tools:checkstyle` from 10.12.5 to 10.12.7
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.5...checkstyle-10.12.7)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.2.2 to 3.2.5
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.2...surefire-3.2.5)

Updates `org.slf4j:slf4j-jdk14` from 2.0.9 to 2.0.11

Updates `com.lenis0012.bukkit:loginsecurity` from 3.2.1 to 3.3.0

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.3.1 to 3.3.2
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: com.lenis0012.bukkit:loginsecurity
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 07:40:02 +00:00
dependabot[bot]
dbf5b8907e Bump the development-dependencies group with 1 update
Bumps the development-dependencies group with 1 update: [org.mockito:mockito-core](https://github.com/mockito/mockito).


Updates `org.mockito:mockito-core` from 5.8.0 to 5.9.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.8.0...v5.9.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 07:38:05 +00:00
dependabot[bot]
e6dfa97e70 Bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 07:12:00 +00:00
games647
434a276d30 Invert if and document migration flow for better readability 2023-12-11 16:16:16 +01:00
games647
485af5e044 Document states 2023-12-11 16:16:16 +01:00
Smart123s
e566740dde Differentiate Floodgate players during login 2023-12-11 16:16:15 +01:00
Smart123s
db5b818a80 Add Floodgate variable to StoredProfile/Database 2023-12-11 16:16:15 +01:00
Smart123s
b0b998d1aa Use columnName instead of columnIndex
It's safer to rely on names instead of indexes.
It's also easier to add new columns at the end of the table.
2023-12-11 16:16:15 +01:00
Smart123s
62ca46fe6a Add checksytle suppression via comments 2023-12-11 16:16:15 +01:00
games647
cd67797b5b Merge pull request #1122 from games647/dependabot/maven/development-dependencies-a116437099
Bump the development-dependencies group with 3 updates
2023-12-06 16:19:28 +01:00
games647
48e8b45f1e Merge pull request #1123 from games647/dependabot/maven/production-dependencies-d650319dc7
Bump the production-dependencies group with 6 updates
2023-12-06 16:19:09 +01:00
games647
1c9b8cb971 Merge pull request #1120 from games647/dependabot/github_actions/actions/setup-java-4
Bump actions/setup-java from 3 to 4
2023-12-06 16:18:34 +01:00
dependabot[bot]
dcb9540a2f Bump the production-dependencies group with 6 updates
Bumps the production-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.4` | `10.12.5` |
| [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) | `3.3.0` | `3.3.1` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.1.2` | `3.2.2` |
| me.clip:placeholderapi | `2.11.4` | `2.11.5` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.2.0` | `3.3.1` |
| [org.codehaus.mojo:templating-maven-plugin](https://github.com/mojohaus/templating-maven-plugin) | `1.0.0` | `3.0.0` |


Updates `com.puppycrawl.tools:checkstyle` from 10.12.4 to 10.12.5
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.4...checkstyle-10.12.5)

Updates `org.apache.maven.plugins:maven-checkstyle-plugin` from 3.3.0 to 3.3.1
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.3.1)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.1.2 to 3.2.2
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.2)

Updates `me.clip:placeholderapi` from 2.11.4 to 2.11.5

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.2.0 to 3.3.1
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.2.0...3.3.1)

Updates `org.codehaus.mojo:templating-maven-plugin` from 1.0.0 to 3.0.0
- [Release notes](https://github.com/mojohaus/templating-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/templating-maven-plugin/compare/templating-maven-plugin-1.0.0...3.0.0)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.codehaus.mojo:templating-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 07:49:44 +00:00
dependabot[bot]
cacf3c23f1 Bump the development-dependencies group with 3 updates
Bumps the development-dependencies group with 3 updates: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5), [org.mockito:mockito-core](https://github.com/mockito/mockito) and [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java).


Updates `org.junit.jupiter:junit-jupiter` from 5.10.0 to 5.10.1
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.10.1)

Updates `org.mockito:mockito-core` from 5.6.0 to 5.8.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.6.0...v5.8.0)

Updates `org.bouncycastle:bcprov-jdk18on` from 1.76 to 1.77
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 07:48:07 +00:00
dependabot[bot]
67f170694f Bump actions/setup-java from 3 to 4
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-01 07:49:23 +00:00
games647
e15ea9ce85 Restore support for fully qualified storage drivers
Related #1100
2023-10-12 10:47:14 +02:00
games647
70960661b4 [ci-skip] Fix typo in issue templates 2023-10-11 13:42:17 +02:00
games647
ec657faaff Force lowercase SQL driver name to improve type checks 2023-10-11 13:40:57 +02:00
games647
51898b4b34 Migrate enhancement requests to newer issue templates 2023-10-11 13:28:12 +02:00
games647
e30de1b700 Include CI server in issue template 2023-10-11 13:28:11 +02:00
games647
ce17441edb Merge pull request #1097 from games647/dependabot/maven/production-dependencies-84d7f6773a
Bump the production-dependencies group with 6 updates
2023-10-11 12:39:04 +02:00
dependabot[bot]
3244b7a87a Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-11 12:38:02 +02:00
games647
ecacd2a715 Update toolchain for Java 21 compiling 2023-10-11 12:37:07 +02:00
SzczurekYT
ea6d4cf2f6 Add proper support for 1.19.3-1.20.1 2023-10-11 12:37:07 +02:00
SzczurekYT
91b05289ad Add 1.20.2 support 2023-10-11 12:37:07 +02:00
dependabot[bot]
4e0f8cfb65 Bump the production-dependencies group with 6 updates
Bumps the production-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.3` | `10.12.4` |
| [org.projectlombok:lombok](https://github.com/projectlombok/lombok) | `1.18.28` | `1.18.30` |
| com.mycila:license-maven-plugin | `4.2` | `4.3` |
| org.slf4j:slf4j-jdk14 | `2.0.7` | `2.0.9` |
| me.clip:placeholderapi | `2.11.3` | `2.11.4` |
| [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) | `3.5.0` | `3.5.1` |


Updates `com.puppycrawl.tools:checkstyle` from 10.12.3 to 10.12.4
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.3...checkstyle-10.12.4)

Updates `org.projectlombok:lombok` from 1.18.28 to 1.18.30
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.28...v1.18.30)

Updates `com.mycila:license-maven-plugin` from 4.2 to 4.3

Updates `org.slf4j:slf4j-jdk14` from 2.0.7 to 2.0.9

Updates `me.clip:placeholderapi` from 2.11.3 to 2.11.4

Updates `org.apache.maven.plugins:maven-shade-plugin` from 3.5.0 to 3.5.1
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.1)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: com.mycila:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 07:56:41 +00:00
games647
d76690dcbe Merge pull request #1087 from games647/dependabot/maven/production-dependencies-ce791421b1
Bump the production-dependencies group with 7 updates
2023-08-31 15:23:30 +02:00
dependabot[bot]
3559d067ad Bump the production-dependencies group with 7 updates
Bumps the production-dependencies group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.9.3` | `10.12.3` |
| [org.projectlombok:lombok](https://github.com/projectlombok/lombok) | `1.18.26` | `1.18.28` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `2.22.2` | `3.1.2` |
| [com.google.code.gson:gson](https://github.com/google/gson) | `2.10` | `2.10.1` |
| com.lenis0012.bukkit:loginsecurity | `3.1.1` | `3.2.1` |
| [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) | `3.4.1` | `3.5.0` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.1.4` | `3.2.0` |


Updates `com.puppycrawl.tools:checkstyle` from 10.9.3 to 10.12.3
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.9.3...checkstyle-10.12.3)

Updates `org.projectlombok:lombok` from 1.18.26 to 1.18.28
- [Release notes](https://github.com/projectlombok/lombok/releases)
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.26...v1.18.28)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 2.22.2 to 3.1.2
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-2.22.2...surefire-3.1.2)

Updates `com.google.code.gson:gson` from 2.10 to 2.10.1
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.10...gson-parent-2.10.1)

Updates `com.lenis0012.bukkit:loginsecurity` from 3.1.1 to 3.2.1

Updates `org.apache.maven.plugins:maven-shade-plugin` from 3.4.1 to 3.5.0
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.1...maven-shade-plugin-3.5.0)

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.1.4 to 3.2.0
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.4...3.2.0)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: production-dependencies
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: com.lenis0012.bukkit:loginsecurity
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-31 11:53:12 +00:00
games647
48a92ed35e Use wildcard exclude patterns 2023-08-31 13:51:42 +02:00
games647
a4eec19f53 [ci-skip] Fix dependency name 2023-08-31 13:19:17 +02:00
games647
32eda941ee Ignore Hikari and SnakeYAML in dependency updates 2023-08-31 12:42:32 +02:00
games647
92d88caf0a Merge pull request #1085 from games647/dependabot/maven/development-dependencies-424a594065
Bump the development-dependencies group with 2 updates
2023-08-31 12:28:11 +02:00
dependabot[bot]
d2202d7a12 Bump the development-dependencies group with 2 updates
Bumps the development-dependencies group with 2 updates: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) and [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java).


Updates `org.junit.jupiter:junit-jupiter` from 5.9.1 to 5.10.0
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.9.1...r5.10.0)

Updates `org.bouncycastle:bcprov-jdk18on` from 1.75 to 1.76
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-31 10:21:23 +00:00
games647
6a68e04c87 Fix grouping for maven packages 2023-08-31 12:18:10 +02:00
games647
b702f48907 Add version number back 2023-08-31 12:14:06 +02:00
games647
159a6ed37c Add JavaDoc snippets and tiny reformats 2023-08-31 12:08:40 +02:00
games647
b48dfed709 Add NPE check on velocity for logins 2023-08-31 12:08:40 +02:00
games647
2db327ccc4 Group dependency updates together 2023-08-31 12:08:39 +02:00
games647
9d907983a6 Only run CodeQL if successful 2023-08-31 12:08:39 +02:00
games647
4a3d7f448f Merge pull request #1071 from xrh0905/floodgate_enabled
Floodgate enabled
2023-08-31 12:07:53 +02:00
xrh0905
31cbb2ff11 Add floodgate support
Based on: https://github.com/games647/FastLogin/pull/649

Solve hooks not found

Add defination of floodgateservice

Geyser API
2023-08-31 12:04:23 +02:00
games647
1715c08ee6 Merge pull request #1041 from games647/dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.3.0
Bump maven-checkstyle-plugin from 3.1.2 to 3.3.0
2023-07-20 12:02:43 +02:00
games647
5682df9ad5 Merge pull request #1048 from games647/dependabot/maven/org.bouncycastle-bcprov-jdk18on-1.75
Bump bcprov-jdk18on from 1.72 to 1.75
2023-07-20 12:01:27 +02:00
games647
132b560130 Merge pull request #1036 from games647/dependabot/maven/org.mariadb.jdbc-mariadb-java-client-3.1.4
Bump mariadb-java-client from 3.1.0 to 3.1.4
2023-07-20 12:01:13 +02:00
games647
e204c9c579 Merge pull request #1021 from games647/dependabot/maven/com.mycila-license-maven-plugin-4.2
Bump license-maven-plugin from 4.1 to 4.2
2023-07-20 12:00:56 +02:00
games647
f92863e53a Merge branch 'main' into dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.3.0 2023-07-20 12:00:33 +02:00
games647
23fec56ecd Merge branch 'main' into dependabot/maven/org.bouncycastle-bcprov-jdk18on-1.75 2023-07-20 11:57:50 +02:00
games647
5cd10fd795 Run CodeQL after main build to leverage caching 2023-07-17 17:04:28 +02:00
games647
ecbf07c0b2 Manually start build process in CodeQL 2023-07-17 16:26:52 +02:00
games647
053b51e96b Relax java build version requirement
GitHub action seems to always download Java 19 even though it is
already downloaded and installed. This could also help with running
the CodeQL action.
2023-07-17 16:17:57 +02:00
games647
44d365b15d Use java dot file to help autobuild select the correct version 2023-07-17 15:52:54 +02:00
games647
610c49d62c Enable write for dependency graph 2023-07-17 15:49:36 +02:00
games647
dbd12742fa Only upload dependency graph on push 2023-07-17 15:47:02 +02:00
games647
f2fd51d4e2 Use suggestion dependency version 2023-07-17 15:17:29 +02:00
games647
f9ca318775 Apply Java version selection after CodeQL init 2023-07-17 15:13:40 +02:00
games647
f06ace2f5b Add dependency graph to help GitHub find dependencies 2023-07-17 15:09:16 +02:00
games647
ee465e381c Rephrase invalid session warning to make it more clear 2023-07-17 10:10:03 +02:00
games647
6ab81b1a2f Fix formatting errors 2023-07-17 09:55:24 +02:00
games647
36ee52aa6e Print out a warning if we detect local IP addresses during connections
Reference #1055
2023-07-10 15:52:34 +02:00
dependabot[bot]
e5c70d8597 Bump bcprov-jdk18on from 1.72 to 1.75
Bumps [bcprov-jdk18on](https://github.com/bcgit/bc-java) from 1.72 to 1.75.
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 07:58:13 +00:00
dependabot[bot]
8b1485f0b1 Bump maven-checkstyle-plugin from 3.1.2 to 3.3.0
Bumps [maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.1.2 to 3.3.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.1.2...maven-checkstyle-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 07:57:19 +00:00
games647
c106089a72 Include updated yaml for older Spigot platforms
Fixes #1031
2023-05-22 15:16:42 +02:00
dependabot[bot]
5fc27f6c4a Bump mariadb-java-client from 3.1.0 to 3.1.4
Bumps [mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 3.1.0 to 3.1.4.
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/commits/3.1.4)

---
updated-dependencies:
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 07:57:09 +00:00
dependabot[bot]
73720277b3 Bump license-maven-plugin from 4.1 to 4.2
Bumps license-maven-plugin from 4.1 to 4.2.

---
updated-dependencies:
- dependency-name: com.mycila:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 07:58:12 +00:00
135 changed files with 2310 additions and 1266 deletions

View File

@@ -12,10 +12,6 @@ body:
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
@@ -36,7 +32,7 @@ body:
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/
placeholder: https://www.toptal.com/developers/hastebin / https://gist.github.com/
- type: input
attributes:
label: Plugin version
@@ -59,9 +55,11 @@ body:
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)
- label: |
I tried the [latest build](https://ci.codemc.io/job/Games647/job/FastLogin/)
(build refers to development builds not necessary a release version; i.e. v1.10 is out of date)
required: true
- label: |
I checked for existing tickets -
If there are, please vote them with a thumps reaction and not create new ones
If there are, please vote them with a thumbs reaction and not create new ones
required: true

View File

@@ -1,30 +0,0 @@
---
name: 💡 Enhancement request
about: New feature or change request
title: ''
labels: 'enhancement'
assignees: ''
---
[//]: # (Lines in this format are considered as comments and will not be displayed.)
[//]: # (Before reporting make sure you're running the **latest build** of the plugin and checked for existing issues!)
[//]: # (This ticket is about suggestions for a feature or particular enhancement)
### Is your feature request related to a problem? Please describe.
[//]: # (A clear and concise description of what the problem is. Ex. I'm always frustrated when [...])
### Describe the solution you'd like
[//]: # (A clear and concise description of what you want to happen.)
### Describe alternatives you've considered
[//]: # (A clear and concise description of any alternative solutions or features you've considered.)
### Additional context
[//]: # (Add any other context or screenshots about the feature request here.)

View File

@@ -0,0 +1,43 @@
name: 💡 Enhancement request
description: New feature or change request
labels: [ enhancement ]
body:
- type: markdown
attributes:
value: |
This ticket is about suggestions for a feature or particular enhancement.
Feedback about this form is appreciated.
- type: textarea
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
- type: textarea
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
- type: dropdown
attributes:
label: Platform
description: Server software - choose your proxy software if you have multiple servers
options:
- Spigot
- BungeeCord
- Velocity
- All / Shared
validations:
required: true
- type: checkboxes
attributes:
label: Relevance
description: Check list for previous tickets
options:
- label: |
I checked for existing tickets -
If there are, please vote them with a thumbs reaction and not create new ones
required: true

View File

@@ -10,7 +10,18 @@ updates:
interval: "monthly"
# Maven project
- package-ecosystem: maven
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: weekly
interval: "monthly"
groups:
production-dependencies:
dependency-type: "production"
development-dependencies:
dependency-type: "development"
exclude-patterns:
# Create single PR for these
# Plugin require special evaluation about their compatibility
- "com.lenis0012.bukkit:loginsecurity"
- "com.comphenix.protocol:ProtocolLib"

View File

@@ -4,11 +4,11 @@
name: "CodeQL"
on:
# Scan only for push on the primary branch for now
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_run:
workflows: ["Maven Build"]
branches: [main]
types:
- completed
jobs:
# job i
@@ -20,9 +20,12 @@ jobs:
# Environment
runs-on: ubuntu-latest
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
if: ${{ github.event.workflow_run.conclusion == 'success' }}
permissions:
actions: read
contents: read
# Only allow 'write' permission for security, then all others default to read only
security-events: write
strategy:
@@ -33,28 +36,29 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 19
cache: 'maven'
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# 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
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version-file: '.java-version'
cache: 'maven'
# Manually start the autobuild process, because autobuild always selects Java 8 as build toolchain, but
# we are doing cross-crompiling from a newer Java version
- name: Build with Maven
# Extracted from autobuild
run: mvn package -f "pom.xml" --batch-mode -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip -DskipTests -Dmaven.test.skip.exec -Dlicense.skip=true -Drat.skip=true -Dspotless.check.skip=true -t /home/runner/.m2/toolchains.xml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -21,19 +21,20 @@ jobs:
# Environment image - always use the newest OS
runs-on: ubuntu-latest
permissions:
# With at least one permission given, all default to read
contents: read
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 19
java-version-file: '.java-version'
cache: 'maven'
# Build and test (included in package)
@@ -41,3 +42,26 @@ jobs:
# Run non-interactive, package (with compile+test),
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
dependency:
runs-on: ubuntu-latest
permissions:
# Write only necessary for dependency submission all others then default to read
contents: write
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v4
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version-file: '.java-version'
cache: 'maven'
- name: Submit Dependency Snapshot
if: ${{ github.event_name == 'push' }}
uses: advanced-security/maven-dependency-submission-action@v4.0.3

2
.java-version Normal file
View File

@@ -0,0 +1,2 @@
# Latest GitHub Action java release that is installed on the runners
21

View File

@@ -1,3 +1,29 @@
# 2.0
## Major changes
* Bumped minimum Java version to 11 make use of modern Java performance features
* Report back if really still need the old versions
* Then we could make use of versioned code, but that requires more coding effort
## Added
* Support for HTTP/2 for contacting Mojang
## Changed
* Updated many dependencies
## Removed
Dropped some features listed below. Please contact us if you still need them
* Dropped Java support < 11
* Removed configuration option to add multiple outgoing IPv4 towards Mojang
* Dropped support for ProtocolSupport seems to unsupported
[...] A lot of changes
### 1.11
* TODO: Replace reflection with methodhandles

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2023 games647 and contributors
Copyright (c) 2015-2024 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

View File

@@ -8,14 +8,11 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
* Detect paid accounts from others
* Automatically login paid accounts (premium)
* Support various of auth plugins
* Cauldron support
* Forge/Sponge message support
* Premium UUID support
* Forward skins
* Detect username changed and will update the existing database record
* BungeeCord support
* BungeeCord/Velocity support
* Auto register new premium players
* Plugin: ProtocolSupport is supported and can be used as an alternative to ProtocolLib
* No client modifications needed
* Good performance by using async operations
* Locale messages
@@ -46,6 +43,7 @@ You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogi
fastlogin.bukkit.command.premium
fastlogin.bukkit.command.cracked
fastlogin.command.premium.other
fastlogin.command.cracked.other
@@ -60,13 +58,15 @@ Possible values: `Premium`, `Cracked`, `Unknown`
## Requirements
* Java 17+
* Java: 21+ recommended for improved multi-threading code by FastLogin
* Spigot: 8+
* BungeeCord and Velocity: 17+
* Server software in offlinemode:
* Spigot (or a fork e.g. Paper) 1.8.8+
* Protocol plugin:
* [ProtocolLib 5.0+](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolLib 5.2+](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* Latest BungeeCord (or a fork e.g. Waterfall)
* Latest BungeeCord (or a fork e.g. Waterfall) or Velocity proxy
* An auth plugin.
### Supported auth plugins
@@ -85,7 +85,6 @@ Possible values: `Premium`, `Cracked`, `Unknown`
#### BungeeCord/Waterfall
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
* [BungeeAuthenticator](https://www.spigotmc.org/resources/bungeecordauthenticator.87669/)
## Network requests
@@ -101,8 +100,8 @@ 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 `FastLoginBukkit`
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to `false`
### BungeeCord/Waterfall or Velocity
@@ -117,8 +116,8 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
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
* BungeeCord: `mysql` for MySQL/MariaDB
* Velocity: `mariadb` 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.

View File

@@ -4,7 +4,7 @@
The MIT License (MIT)
Copyright (c) 2015-2023 games647 and contributors
Copyright (c) 2015-2024 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
@@ -30,7 +30,7 @@
<modelVersion>4.0.0</modelVersion>
<properties>
<nettyVersion>4.1.79.Final</nettyVersion>
<maven.compiler.release>8</maven.compiler.release>
</properties>
<parent>
@@ -50,11 +50,15 @@
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
<relocations>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>fastlogin.yaml</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fastlogin.hikari</shadedPattern>
@@ -94,7 +98,6 @@
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
@@ -113,7 +116,7 @@
</build>
<repositories>
<!-- PaperSpigot API and PaperLib -->
<!-- PaperSpigot API, PaperLib, datafixupper and bungeecord-chat -->
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
@@ -123,6 +126,9 @@
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- AuthMe Reloaded, xAuth and LoginSecurity -->
@@ -165,7 +171,7 @@
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<version>1.20.6-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
@@ -173,13 +179,25 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>datafixerupper</artifactId>
<version>5.0.28</version>
<version>7.1.15</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -193,7 +211,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>5.0.0</version>
<version>5.1.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -264,7 +282,7 @@
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.3</version>
<version>2.11.5</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -293,7 +311,7 @@
<dependency>
<groupId>com.lenis0012.bukkit</groupId>
<artifactId>loginsecurity</artifactId>
<version>3.1.1</version>
<version>3.3.0</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -364,29 +382,7 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.72</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${nettyVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
<version>${nettyVersion}</version>
<scope>test</scope>
</dependency>
<!-- Provided by the spigot, required for testing ProtocolLib -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<version>1.78.1</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -26,7 +26,7 @@
package com.github.games647.fastlogin.bukkit;
import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import org.jetbrains.annotations.Nullable;
@@ -47,7 +47,6 @@ public class BukkitLoginSession extends LoginSession {
private final ClientPublicKey clientPublicKey;
private boolean verified;
private SkinProperty skinProperty;
public BukkitLoginSession(String username, byte[] verifyToken, ClientPublicKey publicKey, boolean registered,
@@ -109,7 +108,7 @@ public class BukkitLoginSession extends LoginSession {
*
* @param verified whether the player has valid session
*/
public synchronized void setVerified(boolean verified) {
public synchronized void setVerifiedPremium(boolean verified) {
this.verified = verified;
}
@@ -118,7 +117,7 @@ public class BukkitLoginSession extends LoginSession {
*
* @return whether the player has a valid session
*/
public synchronized boolean isVerified() {
public synchronized boolean isVerifiedPremium() {
return verified;
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -25,7 +25,7 @@
*/
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.scheduler.AsyncScheduler;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.slf4j.Logger;
@@ -39,7 +39,7 @@ public class BukkitScheduler extends AsyncScheduler {
public BukkitScheduler(Plugin plugin, Logger logger) {
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
syncExecutor = task -> Bukkit.getScheduler().runTask(plugin, task);
}
public Executor getSyncExecutor() {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -25,15 +25,13 @@
*/
package com.github.games647.fastlogin.bukkit;
import com.comphenix.protocol.ProtocolLibrary;
import com.github.games647.fastlogin.bukkit.auth.AuthenticationBackend;
import com.github.games647.fastlogin.bukkit.auth.ConnectionListener;
import com.github.games647.fastlogin.bukkit.auth.protocollib.ProtocolAuthentication;
import com.github.games647.fastlogin.bukkit.auth.proxy.ProxyAuthentication;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.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.hook.DelayedAuthHook;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
@@ -41,6 +39,7 @@ import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -53,6 +52,9 @@ import org.slf4j.Logger;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@@ -65,19 +67,34 @@ import java.util.concurrent.ConcurrentMap;
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 ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(
Duration.ofMinutes(1), -1
);
@Getter
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
private final Logger logger;
private boolean serverStarted;
private BungeeManager bungeeManager;
private final BukkitScheduler scheduler;
@Getter
private final Collection<UUID> pendingConfirms = new HashSet<>();
@Getter
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
@Getter
private FloodgateService floodgateService;
private GeyserService geyserService;
private PremiumPlaceholder premiumPlaceholder;
@Getter
private AuthenticationBackend backend;
@Getter
private boolean initialized;
public FastLoginBukkit() {
this.logger = CommonUtil.initializeLoggerService(getLogger());
this.scheduler = new BukkitScheduler(this, logger);
@@ -99,52 +116,48 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
setEnabled(false);
}
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
markInitialized();
} else {
if (!core.setupDatabase()) {
setEnabled(false);
return;
}
if (pluginManager.isPluginEnabled("ProtocolSupport")) {
pluginManager.registerEvents(new ProtocolSupportListener(this, core.getAntiBot()), this);
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
ProtocolLibListener.register(this, core.getAntiBot(), core.getConfig().getBoolean("verifyClientKeys"));
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
if (!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;
}
backend = initializeAuthenticationBackend();
if (backend == null) {
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
setEnabled(false);
return;
}
//delay dependency setup because we load the plugin very early where plugins are initialized yet
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
backend.init(getServer().getPluginManager());
PluginManager pluginManager = getServer().getPluginManager();
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 (isPaper()) {
pluginManager.registerEvents(new PaperCacheListener(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)));
registerCommands();
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
premiumPlaceholder = new PremiumPlaceholder(this);
premiumPlaceholder.register();
}
// delay dependency setup because we load the plugin very early where plugins are initialized yet
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
}
private AuthenticationBackend initializeAuthenticationBackend() {
AuthenticationBackend proxyVerifier = new ProxyAuthentication(this);
if (proxyVerifier.isAvailable()) {
return proxyVerifier;
}
logger.warn("Disabling Minecraft proxy configuration. Assuming direct connections from now on.");
AuthenticationBackend protocolAuthentication = new ProtocolAuthentication(this);
if (protocolAuthentication.isAvailable()) {
return protocolAuthentication;
}
return null;
}
private void registerCommands() {
//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)));
}
private boolean initializeFloodgate() {
@@ -172,25 +185,13 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
core.close();
}
if (bungeeManager != null) {
bungeeManager.cleanup();
if (backend != null) {
backend.stop();
}
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
try {
premiumPlaceholder.unregister();
} catch (Exception | NoSuchMethodError exception) {
logger.error("Failed to unregister placeholder", exception);
}
premiumPlaceholder.unregister();
}
if (getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(this);
}
}
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
return core;
}
/**
@@ -222,12 +223,24 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
loginSession.remove(id);
}
public Map<UUID, PremiumStatus> getPremiumPlayers() {
return premiumPlayers;
}
/**
* Fetches the premium status of an online player.
* {@snippet :
* // Bukkit's players object after successful authentication i.e. PlayerJoinEvent
* // except for proxies like BungeeCord and Velocity where the details are sent delayed (1-2 seconds)
* Player player;
* PremiumStatus status = JavaPlugin.getPlugin(FastLoginBukkit.class).getStatus(player.getUniqueId());
* switch (status) {
* case CRACKED:
* // player is offline
* break;
* case PREMIUM:
* // account is premium and player passed the verification
* break;
* case UNKNOWN:
* // no record about this 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
@@ -237,24 +250,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
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;
}
@Override
public Path getPluginFolder() {
return getDataFolder().toPath();
@@ -287,12 +282,21 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
}
public FloodgateService getFloodgateService() {
return floodgateService;
public void setInitialized(boolean hookFound) {
if (backend instanceof ProxyAuthentication) {
logger.info("BungeeCord setting detected. No auth plugin is required");
} else if (!hookFound) {
logger.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. "
+ "Either one or both of the checks have to pass in order to use this plugin");
}
initialized = true;
}
public GeyserService getGeyserService() {
return geyserService;
public ProxyAuthentication getBungeeManager() {
return (ProxyAuthentication) backend;
}
@Override
@@ -300,19 +304,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
private boolean isPaper() {
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
}
private Optional<Class<?>> isClassAvailable(String clazzName) {
try {
return Optional.of(Class.forName(clazzName));
} catch (ClassNotFoundException e) {
return Optional.empty();
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -74,11 +74,13 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
@Override
public @NotNull String getAuthor() {
//noinspection deprecation
return String.join(", ", plugin.getDescription().getAuthors());
}
@Override
public @NotNull String getVersion() {
//noinspection deprecation
return plugin.getDescription().getVersion();
}
}

View File

@@ -0,0 +1,37 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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.auth;
import org.bukkit.plugin.PluginManager;
public interface AuthenticationBackend {
boolean isAvailable();
void init(PluginManager pluginManager);
void stop();
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,23 +23,17 @@
* 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;
import com.github.games647.fastlogin.bukkit.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 org.bukkit.Bukkit;
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.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;
/**
@@ -56,14 +50,6 @@ public class ConnectionListener implements Listener {
this.plugin = plugin;
}
@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)
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
Player player = joinEvent.getPlayer();
@@ -102,21 +88,13 @@ public class ConnectionListener implements Listener {
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();
removeBlockedStatus(player);
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
plugin.getPendingConfirms().remove(player.getUniqueId());
plugin.getPremiumPlayers().remove(player.getUniqueId());
plugin.getBungeeManager().cleanup(player);
}
private void removeBlockedStatus(Metadatable player) {
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.task;
package com.github.games647.fastlogin.bukkit.auth;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -49,7 +49,7 @@ public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
session.setVerified(isAutoAuthAllowed(autoLoginFloodgate));
session.setVerifiedPremium(isAutoAuthAllowed(autoLoginFloodgate));
// run login task
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.task;
package com.github.games647.fastlogin.bukkit.auth;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -80,7 +80,7 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
@Override
public void onForceActionSuccess(LoginSession session) {
if (core.getPlugin().getBungeeManager().isEnabled()) {
if (core.getPlugin().getBungeeManager().isAvailable()) {
core.getPlugin().getBungeeManager().sendPluginMessage(player, new SuccessMessage());
}
}
@@ -103,6 +103,6 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
@Override
public boolean isOnlineMode() {
return session.isVerified();
return session.isVerifiedPremium();
}
}

View File

@@ -0,0 +1,63 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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.auth;
import java.net.InetAddress;
public final class InetUtils {
private InetUtils() {
// Utility
}
/**
* Verifies if the given IP address is from the local network
*
* @param address IP address
* @return true if address is from local network or even from the device itself (loopback)
*/
public static boolean isLocalAddress(InetAddress address) {
// Loopback addresses like 127.0.* (IPv4) or [::1] (IPv6)
return address.isLoopbackAddress()
// Example: 10.0.0.0, 172.16.0.0, 192.168.0.0, fec0::/10 (deprecated)
// Ref: https://en.wikipedia.org/wiki/IP_address#Private_addresses
|| address.isSiteLocalAddress()
// Example: 169.254.0.0/16, fe80::/10
// Ref: https://en.wikipedia.org/wiki/IP_address#Address_autoconfiguration
|| address.isLinkLocalAddress()
// non deprecated unique site-local that java doesn't check yet -> fc00::/7
|| isIPv6UniqueSiteLocal(address);
}
private static boolean isIPv6UniqueSiteLocal(InetAddress address) {
// ref: https://en.wikipedia.org/wiki/Unique_local_address
// currently undefined but could be used in the near future fc00::/8
return (address.getAddress()[0] & 0xFF) == 0xFC
// in use for unique site-local fd00::/8
|| (address.getAddress()[0] & 0xFF) == 0xFD;
}
}

View File

@@ -0,0 +1,70 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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.auth;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.auth.protocollib.SkinApplyListener;
import org.bukkit.plugin.PluginManager;
import java.util.Optional;
public abstract class LocalAuthentication implements AuthenticationBackend {
protected final FastLoginBukkit plugin;
protected LocalAuthentication(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@Override
public void init(PluginManager pluginManager) {
if (!plugin.getCore().setupDatabase()) {
plugin.setEnabled(false);
return;
}
// if server is using paper - we need to add one more listener to correct the user cache usage
if (isPaper()) {
pluginManager.registerEvents(new PaperCacheListener(plugin), plugin);
} else if (plugin.getConfig().getBoolean("forwardSkin")) {
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
pluginManager.registerEvents(new SkinApplyListener(plugin), plugin);
}
}
private boolean isPaper() {
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
}
private Optional<Class<?>> isClassAvailable(String clazzName) {
try {
return Optional.of(Class.forName(clazzName));
} catch (ClassNotFoundException e) {
return Optional.empty();
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener;
package com.github.games647.fastlogin.bukkit.auth;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.github.games647.craftapi.model.skin.Textures;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,10 +23,10 @@
* 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.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.common.io.Resources;
@@ -70,7 +70,7 @@ final class EncryptionUtil {
public static final int VERIFY_TOKEN_LENGTH = 4;
public static final String KEY_PAIR_ALGORITHM = "RSA";
private static final int RSA_LENGTH = 1_024;
private static final int RSA_LENGTH = 2_048;
private static final PublicKey MOJANG_SESSION_KEY;
private static final int LINE_LENGTH = 76;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,14 +23,14 @@
* 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.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.storage.StoredProfile;
@@ -97,7 +97,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
}
String ip = player.getAddress().getAddress().getHostAddress();
core.getPendingLogin().put(ip + username, new Object());
core.addLoginAttempt(ip, username);
byte[] verify = source.getVerifyToken();
ClientPublicKey clientKey = source.getClientKey();

View File

@@ -0,0 +1,72 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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.auth.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.auth.LocalAuthentication;
import com.github.games647.fastlogin.core.antibot.AntiBotService;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import org.bukkit.command.CommandSender;
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.plugin.PluginManager;
public class ProtocolAuthentication extends LocalAuthentication implements Listener {
public ProtocolAuthentication(FastLoginBukkit plugin) {
super(plugin);
}
@Override
public boolean isAvailable() {
return plugin.getServer().getPluginManager().isPluginEnabled("ProtocolLib");
}
@Override
public void init(PluginManager pluginManager) {
pluginManager.registerEvents(this, plugin);
FastLoginCore<Player, CommandSender, FastLoginBukkit> core = plugin.getCore();
AntiBotService antiBotService = core.getAntiBotService();
ProtocolLibListener.register(plugin, antiBotService, core.getConfig().getBoolean("verifyClientKeys"));
}
@Override
public void stop() {
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(plugin);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
if (loginEvent.getResult() == PlayerLoginEvent.Result.ALLOWED && !plugin.isInitialized()) {
loginEvent.disallow(PlayerLoginEvent.Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
@@ -32,6 +32,7 @@ import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.PacketFilterManager;
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
@@ -41,7 +42,7 @@ import com.comphenix.protocol.wrappers.Converters;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.core.antibot.AntiBotService;
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
import com.mojang.datafixers.util.Either;
@@ -51,6 +52,7 @@ import io.netty.util.AttributeKey;
import lombok.val;
import org.bukkit.entity.Player;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.jetbrains.annotations.NotNull;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
@@ -108,49 +110,70 @@ public class ProtocolLibListener extends PacketAdapter {
public void onPacketReceiving(PacketEvent packetEvent) {
if (packetEvent.isCancelled()
|| plugin.getCore().getAuthPluginHook() == null
|| !plugin.isServerFullyStarted()) {
|| !plugin.isInitialized()) {
return;
}
plugin.getLog().info("New packet {} from {}", packetEvent.getPacketType(), packetEvent.getPlayer());
Player sender = packetEvent.getPlayer();
PacketType packetType = packetEvent.getPacketType();
if (packetType == START) {
PacketType packetType = getOverriddenType(packetEvent.getPacketType());
if (plugin.getFloodgateService() != null) {
boolean success = processFloodgateTasks(packetEvent);
// don't continue execution if the player was kicked by Floodgate
if (!success) {
return;
plugin.getLog().info("New packet {} from {}", packetType, sender);
try {
if (packetType == START) {
if (plugin.getFloodgateService() != null) {
boolean success = processFloodgateTasks(packetEvent);
// don't continue execution if the player was kicked by Floodgate
if (!success) {
return;
}
}
PacketContainer packet = packetEvent.getPacket();
InetSocketAddress address = sender.getAddress();
String username = getUsername(packet);
Action action = antiBotService.onIncomingConnection(address, username);
switch (action) {
case Ignore:
// just ignore
return;
case Block:
String message = plugin.getCore().getMessage("kick-antibot");
sender.kickPlayer(message);
break;
case Continue:
default:
//player.getName() won't work at this state
onLoginStart(packetEvent, sender, username);
break;
}
} else if (packetType == ENCRYPTION_BEGIN) {
onEncryptionBegin(packetEvent, sender);
} else {
plugin.getLog().warn("Unknown packet type received {}", packetType);
}
PacketContainer packet = packetEvent.getPacket();
InetSocketAddress address = sender.getAddress();
String username = getUsername(packet);
Action action = antiBotService.onIncomingConnection(address, username);
switch (action) {
case Ignore:
// just ignore
return;
case Block:
String message = plugin.getCore().getMessage("kick-antibot");
sender.kickPlayer(message);
break;
case Continue:
default:
//player.getName() won't work at this state
onLoginStart(packetEvent, sender, username);
break;
}
} else {
onEncryptionBegin(packetEvent, sender);
} catch (FieldAccessException fieldAccessEx) {
plugin.getLog().error("Failed to parse packet {}", packetEvent.getPacketType(), fieldAccessEx);
}
}
private @NotNull PacketType getOverriddenType(PacketType packetType) {
if (packetType.isDynamic()) {
String vanillaName = packetType.getPacketClass().getName();
plugin.getLog().info("Overriding packet type for unregistered packet type to fix ProtocolLib bug");
if (vanillaName.endsWith("ServerboundHelloPacket")) {
return START;
}
if (vanillaName.endsWith("ServerboundKeyPacket")) {
return ENCRYPTION_BEGIN;
}
}
return packetType;
}
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
@@ -177,7 +200,7 @@ public class ProtocolLibListener extends PacketAdapter {
ClientPublicKey clientPublicKey, byte[] expectedToken) {
try {
if (new MinecraftVersion(1, 19, 0).atOrAbove()
&& !(new MinecraftVersion(1, 19, 3).atOrAbove())) {
&& !new MinecraftVersion(1, 19, 3).atOrAbove()) {
Either<byte[], ?> either = packet.getSpecificModifier(Either.class).read(0);
if (clientPublicKey == null) {
Optional<byte[]> left = either.left();
@@ -222,7 +245,7 @@ public class ProtocolLibListener extends PacketAdapter {
PacketContainer packet = packetEvent.getPacket();
Optional<ClientPublicKey> clientKey;
if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
// public key sent separate
// public key is sent separate
clientKey = Optional.empty();
} else {
val profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter())
@@ -247,7 +270,6 @@ public class ProtocolLibListener extends PacketAdapter {
}
}
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
packetEvent.getAsyncMarker().incrementProcessingDelay();

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,14 +23,14 @@
* 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.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.core.shared.LoginSource;
import org.bukkit.entity.Player;
@@ -51,7 +51,6 @@ class ProtocolLibLoginSource implements LoginSource {
private final ClientPublicKey clientKey;
private final PublicKey publicKey;
private final String serverId = "";
private byte[] verifyToken;
ProtocolLibLoginSource(Player player, Random random, PublicKey serverPublicKey, ClientPublicKey clientKey) {
@@ -72,7 +71,7 @@ class ProtocolLibLoginSource implements LoginSource {
*/
PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
newPacket.getStrings().write(0, serverId);
newPacket.getStrings().write(0, "");
StructureModifier<PublicKey> keyModifier = newPacket.getSpecificModifier(PublicKey.class);
int verifyField = 0;
if (keyModifier.getFields().isEmpty()) {
@@ -84,6 +83,8 @@ class ProtocolLibLoginSource implements LoginSource {
}
newPacket.getByteArrays().write(verifyField, verifyToken);
// shouldAuthenticate, but why does this field even exist?
newPacket.getBooleans().writeSafely(0, true);
//serverId is an empty string
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
@@ -115,10 +116,6 @@ class ProtocolLibLoginSource implements LoginSource {
return clientKey;
}
public String getServerId() {
return serverId;
}
public byte[] getVerifyToken() {
return verifyToken.clone();
}
@@ -128,7 +125,6 @@ class ProtocolLibLoginSource implements LoginSource {
return this.getClass().getSimpleName() + '{'
+ "player=" + player
+ ", random=" + random
+ ", serverId='" + serverId + '\''
+ ", verifyToken=" + Arrays.toString(verifyToken)
+ '}';
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
@@ -38,6 +38,7 @@ import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.Converters;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
@@ -46,7 +47,8 @@ import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.InetUtils;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import lombok.val;
import org.bukkit.entity.Player;
@@ -70,13 +72,13 @@ 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 static final String ADDRESS_VERIFY_WARNING = "This indicates the use of reverse-proxy like HAProxy, "
+ "TCPShield, BungeeCord, Velocity, etc. "
+ "By default (configurable in the config) this plugin requests Mojang to verify the connecting IP "
+ "to this server with the one used to log into Minecraft to prevent MITM attacks. In "
+ "order to work this security feature, the actual client IP needs to be forwarding "
+ "(keyword IP forwarding). This process will also be useful for other server "
+ "features like IP banning, so that it doesn't ban the proxy IP.";
private final FastLoginBukkit plugin;
private final PacketEvent packetEvent;
@@ -89,6 +91,8 @@ public class VerifyResponseTask implements Runnable {
private final byte[] sharedSecret;
private static Method encryptMethod;
private static Method encryptKeyMethod;
private static Method cipherMethod;
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent,
@@ -149,10 +153,27 @@ public class VerifyResponseTask implements Runnable {
} else {
//user tried to fake an authentication
disconnect(
"invalid-session",
"GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}",
session.getRequestUsername(), socketAddress, serverId
"invalid-session",
"Session server rejected incoming connection for GameProfile {} ({}). Possible reasons are "
+ "1) Client IP address contacting Mojang and server during server join were different "
+ "(Do you use a reverse proxy? -> Enable IP forwarding, "
+ "or disable the feature in the config). "
+ "2) Player is offline, but tried to bypass the authentication "
+ "3) Client uses an outdated username for connecting (Fix: Restart client)",
requestedUsername, address
);
if (InetUtils.isLocalAddress(address)) {
plugin.getLog().warn(
"The incoming request for player {} uses a local IP address",
requestedUsername
);
} else {
plugin.getLog().warn("If you think this is an error, please verify that the incoming "
+ "IP address {} is not associated with a server hosting company.", address);
}
plugin.getLog().warn(ADDRESS_VERIFY_WARNING);
}
} catch (IOException ioEx) {
disconnect("error-kick", "Failed to connect to session server", ioEx);
@@ -174,10 +195,10 @@ public class VerifyResponseTask implements Runnable {
session.setVerifiedUsername(realUsername);
session.setUuid(verification.getId());
session.setVerified(true);
session.setVerifiedPremium(true);
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(realUsername, session.getClientPublicKey());
receiveFakeStartPacket(realUsername, session.getClientPublicKey(), session.getUuid());
}
private void setPremiumUUID(UUID premiumUUID) {
@@ -211,21 +232,24 @@ public class VerifyResponseTask implements Runnable {
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getAddress());
// Initialize method reflections
if (encryptMethod == null) {
if (encryptKeyMethod == null || encryptMethod == null) {
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
try {
// Try to get the old (pre MC 1.16.4) encryption method
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
.getMethodByParameters("a", SecretKey.class);
encryptKeyMethod = FuzzyReflection.fromClass(networkManagerClass)
.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);
Class<?> encryptionClass = MinecraftReflection.getMinecraftClass(
"util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME
);
// Get the needed Cipher helper method (used to generate ciphers from login key)
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
.getMethodByParameters("a", int.class, Key.class);
cipherMethod = FuzzyReflection.fromClass(encryptionClass)
.getMethodByParameters("a", int.class, Key.class);
}
}
@@ -233,9 +257,9 @@ public class VerifyResponseTask implements Runnable {
Object networkManager = this.getNetworkManager();
// If cipherMethod is null - use old encryption (pre MC 1.16.4), otherwise use the new cipher one
if (cipherMethod == null) {
if (encryptKeyMethod != null) {
// Encrypt/decrypt packet flow, this behaviour is expected by the client
encryptMethod.invoke(networkManager, loginKey);
encryptKeyMethod.invoke(networkManager, loginKey);
} else {
// Create ciphers from login key
Object decryptionCipher = cipherMethod.invoke(null, Cipher.DECRYPT_MODE, loginKey);
@@ -268,15 +292,23 @@ public class VerifyResponseTask implements Runnable {
}
//fake a new login packet in order to let the server handle all the other stuff
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey) {
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey, UUID uuid) {
PacketContainer startPacket;
if (new MinecraftVersion(1, 19, 0).atOrAbove()) {
if (new MinecraftVersion(1, 20, 2).atOrAbove()) {
startPacket = new PacketContainer(START);
startPacket.getStrings().write(0, username);
startPacket.getUUIDs().write(0, uuid);
} else if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
startPacket = new PacketContainer(START);
startPacket.getStrings().write(0, username);
startPacket.getOptionals(Converters.passthrough(UUID.class)).write(0, Optional.of(uuid));
} else if (new MinecraftVersion(1, 19, 0).atOrAbove()) {
startPacket = new PacketContainer(START);
startPacket.getStrings().write(0, username);
EquivalentConverter<WrappedProfileKeyData> converter = BukkitConverters.getWrappedPublicKeyDataConverter();
val wrappedKey = Optional.ofNullable(clientKey).map(key ->
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
);
startPacket.getOptionals(converter).write(0, wrappedKey);

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
package com.github.games647.fastlogin.bukkit.auth.protocollib.packet;
import lombok.Value;
import lombok.experimental.Accessors;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,9 +23,10 @@
* 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.bukkit.auth.AuthenticationBackend;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
@@ -33,105 +34,65 @@ import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.messaging.PluginMessageRecipient;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Stream;
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
import static java.util.stream.Collectors.toSet;
public class BungeeManager {
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
private Set<UUID> proxyIds;
public class ProxyAuthentication implements AuthenticationBackend {
private final FastLoginBukkit plugin;
private boolean enabled;
private ProxyVerifier verifier;
private final Collection<UUID> firedJoinEvents = new HashSet<>();
public BungeeManager(FastLoginBukkit plugin) {
public ProxyAuthentication(FastLoginBukkit plugin) {
this.plugin = plugin;
}
public void cleanup() {
//remove old blocked status
Bukkit.getOnlinePlayers().forEach(player -> player.removeMetadata(plugin.getName(), plugin));
@Override
public boolean isAvailable() {
return detectProxy();
}
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
if (player != null) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
message.writeTo(dataOutput);
@Override
public void init(PluginManager pluginManager) {
verifier = new ProxyVerifier(plugin);
verifier.loadSecrets();
NamespaceKey channel = new NamespaceKey(plugin.getName(), message.getChannelName());
player.sendPluginMessage(plugin, channel.getCombinedName(), dataOutput.toByteArray());
registerPluginChannels();
pluginManager.registerEvents(new ProxyConnectionListener(plugin, verifier), plugin);
plugin.getLog().info("Found enabled proxy configuration");
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
}
private void registerPluginChannels() {
Server server = Bukkit.getServer();
// check for incoming messages from the bungeecord version of this plugin
String groupId = plugin.getName();
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new ProxyListener(plugin, verifier));
// outgoing
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
String changeChannel = new NamespaceKey(groupId, CHANGE_CHANNEL).getCombinedName();
server.getMessenger().registerOutgoingPluginChannel(plugin, successChannel);
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
}
@Override
public void stop() {
if (verifier != null) {
verifier.cleanup();
}
}
public boolean isEnabled() {
return enabled;
}
public void initialize() {
enabled = detectProxy();
if (enabled) {
proxyIds = loadBungeeCordIds();
if (proxyIds.isEmpty()) {
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
}
registerPluginChannels();
plugin.getLog().info("Found enabled proxy configuration");
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
} else {
plugin.getLog().warn("Disabling Minecraft proxy configuration. Assuming direct connections from now on.");
}
}
private boolean isProxySupported(String className, String fieldName)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
}
private boolean isVelocityEnabled()
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException,
NoSuchMethodException, InvocationTargetException {
try {
Class<?> globalConfig = Class.forName("io.papermc.paper.configuration.GlobalConfiguration");
Object global = globalConfig.getDeclaredMethod("get").invoke(null);
Object proxiesConfiguration = global.getClass().getDeclaredField("proxies").get(global);
Field velocitySectionField = proxiesConfiguration.getClass().getDeclaredField("velocity");
Object velocityConfig = velocitySectionField.get(proxiesConfiguration);
return velocityConfig.getClass().getDeclaredField("enabled").getBoolean(velocityConfig);
} catch (ClassNotFoundException classNotFoundException) {
// try again using the older Paper configuration, because the old class file still exists in newer versions
if (isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport")) {
return true;
}
}
return false;
}
private boolean detectProxy() {
try {
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
@@ -155,82 +116,40 @@ public class BungeeManager {
return false;
}
private void registerPluginChannels() {
Server server = Bukkit.getServer();
// check for incoming messages from the bungeecord version of this plugin
String groupId = plugin.getName();
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new BungeeListener(plugin));
// outgoing
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
String changeChannel = new NamespaceKey(groupId, CHANGE_CHANNEL).getCombinedName();
server.getMessenger().registerOutgoingPluginChannel(plugin, successChannel);
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
private boolean isProxySupported(String className, String fieldName)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
}
private Set<UUID> loadBungeeCordIds() {
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
private boolean isVelocityEnabled()
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException,
NoSuchMethodException, InvocationTargetException {
try {
if (Files.notExists(proxiesFile)) {
if (Files.exists(legacyFile)) {
Files.move(legacyFile, proxiesFile);
}
Class<?> globalConfig = Class.forName("io.papermc.paper.configuration.GlobalConfiguration");
Object global = globalConfig.getDeclaredMethod("get").invoke(null);
Object proxiesConfiguration = global.getClass().getDeclaredField("proxies").get(global);
if (Files.notExists(legacyFile)) {
Files.createFile(proxiesFile);
}
}
Field velocitySectionField = proxiesConfiguration.getClass().getDeclaredField("velocity");
Object velocityConfig = velocitySectionField.get(proxiesConfiguration);
Files.deleteIfExists(legacyFile);
try (Stream<String> lines = Files.lines(proxiesFile)) {
return lines.map(String::trim).map(UUID::fromString).collect(toSet());
return velocityConfig.getClass().getDeclaredField("enabled").getBoolean(velocityConfig);
} catch (ClassNotFoundException classNotFoundException) {
// try again using the older Paper configuration, because the old class file still exists in newer versions
if (isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport")) {
return true;
}
} 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);
}
return Collections.emptySet();
return false;
}
public boolean isProxyAllowed(UUID proxyId) {
return proxyIds != null && proxyIds.contains(proxyId);
}
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
if (player != null) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
message.writeTo(dataOutput);
/**
* Mark the event to be fired including the task delay.
*
* @param player joining player
*/
public synchronized void markJoinEventFired(Player player) {
firedJoinEvents.add(player.getUniqueId());
}
/**
* 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.
* <p>
* 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
* @return event fired including delay
*/
public synchronized boolean didJoinEventFired(Player player) {
return firedJoinEvents.contains(player.getUniqueId());
}
/**
* Player quit clean up
*
* @param player joining player
*/
public synchronized void cleanup(Player player) {
firedJoinEvents.remove(player.getUniqueId());
NamespaceKey channel = new NamespaceKey(plugin.getName(), message.getChannelName());
player.sendPluginMessage(plugin, channel.getCombinedName(), dataOutput.toByteArray());
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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.auth.proxy;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.auth.FloodgateAuthTask;
import com.github.games647.fastlogin.bukkit.auth.ForceLoginTask;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import org.bukkit.Bukkit;
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.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.Metadatable;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public class ProxyConnectionListener implements Listener {
private static final long DELAY_LOGIN = 20L / 2;
private final FastLoginBukkit plugin;
private final ProxyVerifier verifier;
public ProxyConnectionListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
this.plugin = plugin;
this.verifier = verifier;
}
private void removeBlockedStatus(Metadatable player) {
player.removeMetadata(plugin.getName(), plugin);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
removeBlockedStatus(loginEvent.getPlayer());
}
@EventHandler(ignoreCancelled = true)
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, () -> {
delayForceLogin(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);
}
verifier.markJoinEventFired(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
Player player = quitEvent.getPlayer();
removeBlockedStatus(player);
verifier.cleanup(player);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,11 +23,11 @@
* 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.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
import com.github.games647.fastlogin.bukkit.auth.ForceLoginTask;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
@@ -47,12 +47,14 @@ import java.util.UUID;
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
* the connection is in online mode.
*/
public class BungeeListener implements PluginMessageListener {
public class ProxyListener implements PluginMessageListener {
private final FastLoginBukkit plugin;
private final ProxyVerifier verifier;
public BungeeListener(FastLoginBukkit plugin) {
public ProxyListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
this.plugin = plugin;
this.verifier = verifier;
}
@Override
@@ -79,7 +81,7 @@ public class BungeeListener implements PluginMessageListener {
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
} else {
UUID sourceId = loginMessage.getProxyId();
if (plugin.getBungeeManager().isProxyAllowed(sourceId)) {
if (verifier.isProxyAllowed(sourceId)) {
readMessage(targetPlayer, loginMessage);
} else {
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
@@ -123,11 +125,11 @@ public class BungeeListener implements PluginMessageListener {
}
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
session.setVerified(true);
session.setVerifiedPremium(true);
plugin.putSession(player.spigot().getRawAddress(), session);
// only start a new login task if the join event fired earlier. This event then didn't
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
boolean result = verifier.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

@@ -0,0 +1,135 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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.auth.proxy;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toSet;
public class ProxyVerifier {
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
private Set<UUID> proxyIds;
private final FastLoginBukkit plugin;
private final Collection<UUID> firedJoinEvents = new HashSet<>();
public ProxyVerifier(FastLoginBukkit plugin) {
this.plugin = plugin;
}
public void cleanup() {
//remove old blocked status
Bukkit.getOnlinePlayers().forEach(player -> player.removeMetadata(plugin.getName(), plugin));
}
public void loadSecrets() {
proxyIds = loadBungeeCordIds();
if (proxyIds.isEmpty()) {
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
}
}
private Set<UUID> loadBungeeCordIds() {
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
try {
if (Files.notExists(proxiesFile)) {
if (Files.exists(legacyFile)) {
Files.move(legacyFile, proxiesFile);
}
if (Files.notExists(legacyFile)) {
Files.createFile(proxiesFile);
}
}
Files.deleteIfExists(legacyFile);
try (Stream<String> lines = Files.lines(proxiesFile)) {
return lines.map(String::trim).map(UUID::fromString).collect(toSet());
}
} 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);
}
return Collections.emptySet();
}
public boolean isProxyAllowed(UUID proxyId) {
return proxyIds != null && proxyIds.contains(proxyId);
}
/**
* Mark the event to be fired including the task delay.
*
* @param player joining player
*/
public synchronized void markJoinEventFired(Player player) {
firedJoinEvents.add(player.getUniqueId());
}
/**
* 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.
* <p>
* 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
* @return event fired including delay
*/
public synchronized boolean didJoinEventFired(Player player) {
return firedJoinEvents.contains(player.getUniqueId());
}
/**
* Player quit clean up
*
* @param player joining player
*/
public synchronized void cleanup(Player player) {
firedJoinEvents.remove(player.getUniqueId());
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -63,10 +63,10 @@ public class CrackedCommand extends ToggleCommand {
// todo: load async if
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
if (profile.isPremium()) {
if (profile.isOnlinemodePreferred()) {
plugin.getCore().sendLocaleMessage("remove-premium", sender);
profile.setPremium(false);
profile.setOnlinemodePreferred(false);
profile.setId(null);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
@@ -95,12 +95,12 @@ public class CrackedCommand extends ToggleCommand {
}
//existing player is already cracked
if (profile.isSaved() && !profile.isPremium()) {
if (profile.isExistingPlayer() && !profile.isOnlinemodePreferred()) {
plugin.getCore().sendLocaleMessage("not-premium-other", sender);
} else {
plugin.getCore().sendLocaleMessage("remove-premium", sender);
profile.setPremium(false);
profile.setOnlinemodePreferred(false);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -64,25 +64,25 @@ public class PremiumCommand extends ToggleCommand {
return;
}
UUID id = ((Player) sender).getUniqueId();
if (plugin.getConfig().getBoolean("premium-warning") && !plugin.getPendingConfirms().contains(id)) {
sender.sendMessage(plugin.getCore().getMessage("premium-warning"));
plugin.getPendingConfirms().add(id);
return;
}
if (forwardPremiumCommand(sender, sender.getName())) {
return;
}
UUID id = ((Player) sender).getUniqueId();
if (plugin.getConfig().getBoolean("premium-warning") && !plugin.getCore().getPendingConfirms().contains(id)) {
sender.sendMessage(plugin.getCore().getMessage("premium-warning"));
plugin.getCore().getPendingConfirms().add(id);
return;
}
plugin.getCore().getPendingConfirms().remove(id);
plugin.getPendingConfirms().remove(id);
//todo: load async
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
if (profile.isPremium()) {
if (profile.isOnlinemodePreferred()) {
plugin.getCore().sendLocaleMessage("already-exists", sender);
} else {
//todo: resolve uuid
profile.setPremium(true);
profile.setOnlinemodePreferred(true);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(
@@ -109,11 +109,11 @@ public class PremiumCommand extends ToggleCommand {
return;
}
if (profile.isPremium()) {
if (profile.isOnlinemodePreferred()) {
plugin.getCore().sendLocaleMessage("already-exists-other", sender);
} else {
//todo: resolve uuid
profile.setPremium(true);
profile.setOnlinemodePreferred(true);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -26,6 +26,7 @@
package com.github.games647.fastlogin.bukkit.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.auth.proxy.ProxyAuthentication;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import org.bukkit.Bukkit;
@@ -55,7 +56,7 @@ public abstract class ToggleCommand implements CommandExecutor {
}
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {
if (plugin.getBungeeManager().isEnabled()) {
if (plugin.getBackend() instanceof ProxyAuthentication) {
sendBungeeActivateMessage(sender, target, activate);
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
return true;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -45,9 +45,9 @@ import java.lang.reflect.Field;
* <p>
* Project page:
* <p>
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/authme-reloaded/">...</a>
* <a href="https://dev.bukkit.org/bukkit-plugins/authme-reloaded/">Bukkit</a>
* <p>
* Spigot: <a href="https://www.spigotmc.org/resources/authme-reloaded.6269/">...</a>
* <a href="https://www.spigotmc.org/resources/authme-reloaded.6269/">Spigot</a>
*/
public class AuthMeHook implements AuthPlugin<Player>, Listener {
@@ -76,7 +76,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
Player player = restoreSessionEvent.getPlayer();
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session != null && session.isVerified()) {
if (session != null && session.isVerifiedPremium()) {
restoreSessionEvent.setCancelled(true);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -46,7 +46,7 @@ import java.util.concurrent.Future;
* <p>
* Project page:
* <p>
* Bukkit: <a href="https://dev.bukkit.org/server-mods/crazylogin/">...</a>
* <a href="https://dev.bukkit.org/server-mods/crazylogin/">Bukkit</a>
*/
public class CrazyLoginHook implements AuthPlugin<Player> {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,15 +23,9 @@
* 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 org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -51,19 +45,7 @@ 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");
} 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. "
+ "Either one or both of the checks have to pass in order to use this plugin");
}
if (hookFound) {
plugin.markInitialized();
}
plugin.setInitialized(isHookFound());
}
private boolean isHookFound() {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -39,9 +39,9 @@ import org.bukkit.entity.Player;
* <p>
* Project page:
* <p>
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/loginsecurity/">...</a>
* <a href="https://dev.bukkit.org/bukkit-plugins/loginsecurity/">Bukkit</a>
* <p>
* Spigot: <a href="https://www.spigotmc.org/resources/loginsecurity.19362/">...</a>
* <a href="https://www.spigotmc.org/resources/loginsecurity.19362/">Spigot</a>
*/
public class LoginSecurityHook implements AuthPlugin<Player> {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -38,9 +38,9 @@ import java.util.concurrent.Future;
/**
* Project page:
* <p>
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/">...</a>
* <a href="https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/">Bukkit</a>
* <p>
* Spigot: <a href="https://www.spigotmc.org/resources/ultraauth.17044/">...</a>
* <a href="https://www.spigotmc.org/resources/ultraauth.17044/">Spigot</a>
*/
public class UltraAuthHook implements AuthPlugin<Player> {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -40,7 +40,7 @@ import java.util.concurrent.Future;
* <p>
* Project page:
* <p>
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/xauth/">...</a>
* <a href="https://dev.bukkit.org/bukkit-plugins/xauth/">Bukkit</a>
*/
public class XAuthHook implements AuthPlugin<Player> {

View File

@@ -1,139 +0,0 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 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.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.antibot.AntiBotService;
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import protocolsupport.api.events.ConnectionCloseEvent;
import protocolsupport.api.events.PlayerLoginStartEvent;
import protocolsupport.api.events.PlayerProfileCompleteEvent;
import java.net.InetSocketAddress;
import java.util.Optional;
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
implements Listener {
private final FastLoginBukkit plugin;
private final AntiBotService antiBotService;
public ProtocolSupportListener(FastLoginBukkit plugin, AntiBotService antiBotService) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin;
this.antiBotService = antiBotService;
}
@EventHandler
public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
if (loginStartEvent.isLoginDenied() || plugin.getCore().getAuthPluginHook() == null) {
return;
}
String username = loginStartEvent.getConnection().getProfile().getName();
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
plugin.getLog().info("Incoming login request for {} from {}", username, address);
Action action = antiBotService.onIncomingConnection(address, username);
switch (action) {
case Ignore:
// just ignore
return;
case Block:
String message = plugin.getCore().getMessage("kick-antibot");
loginStartEvent.denyLogin(message);
break;
case Continue:
default:
//remove old data every time on a new login in order to keep the session only for one person
plugin.removeSession(address);
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
super.onLogin(username, source);
break;
}
}
@EventHandler
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
plugin.removeSession(address);
}
@EventHandler
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
BukkitLoginSession session = plugin.getSession(address);
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
session.setVerified(true);
if (!plugin.getConfig().getBoolean("premiumUuid")) {
String username = Optional.ofNullable(profileCompleteEvent.getForcedName())
.orElse(profileCompleteEvent.getConnection().getProfile().getName());
profileCompleteEvent.setForcedUUID(UUIDAdapter.generateOfflineId(username));
}
}
}
@Override
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLoginSource source,
StoredProfile profile) {
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
plugin.getServer().getPluginManager().callEvent(event);
return event;
}
@Override
public void requestPremiumLogin(ProtocolLoginSource source, StoredProfile profile, String username,
boolean registered) {
source.enableOnlinemode();
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);
}
@Override
public void startCrackedSession(ProtocolLoginSource source, StoredProfile profile, String username) {
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.putSession(source.getAddress(), loginSession);
}
}

View File

@@ -25,12 +25,11 @@ softdepend:
- floodgate
# Auth plugins
- AuthMe
- CrazyLogin
- LoginSecurity
- SodionAuth
- xAuth
- LogIt
- UltraAuth
- CrazyLogin
- xAuth
commands:
${project.parent.name}:

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -41,8 +41,10 @@ class FastLoginBukkitTest {
val msg = CommonUtil.translateColorCodes(message);
assertEquals(msg, "§x00002a00002b§lText");
@SuppressWarnings("deprecation")
val components = TextComponent.fromLegacyText(msg);
val expected = "{\"bold\":true,\"color\":\"#00a00b\",\"text\":\"Text\"}";
//noinspection deprecation
assertEquals(ComponentSerializer.toString(components), expected);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,10 +23,10 @@
* 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.github.games647.fastlogin.bukkit.listener.protocollib.SignatureTestData.SignatureData;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.protocollib.SignatureTestData.SignatureData;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.google.common.hash.Hashing;
import lombok.val;
import org.junit.jupiter.api.Test;
@@ -60,7 +60,7 @@ class EncryptionUtilTest {
@Test
void testVerifyToken() {
val random = ThreadLocalRandom.current();
@SuppressWarnings("SharedThreadLocalRandom") val random = ThreadLocalRandom.current();
byte[] token = EncryptionUtil.generateVerifyToken(random);
assertAll(
@@ -88,7 +88,7 @@ class EncryptionUtilTest {
@Test
void testExpiredClientKey() throws Exception {
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
// Client expires at the exact second mentioned, so use it for verification
val expiredTimestamp = clientKey.expiry();
@@ -105,7 +105,7 @@ class EncryptionUtilTest {
"client_keys/invalid_wrong_signature.json"
})
void testInvalidClientKey(String clientKeySource) throws Exception {
val clientKey = ResourceLoader.loadClientKey(clientKeySource);
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey(clientKeySource);
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp, null));
@@ -113,7 +113,7 @@ class EncryptionUtilTest {
@Test
void testValidClientKey() throws Exception {
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, null));
@@ -121,7 +121,7 @@ class EncryptionUtilTest {
@Test
void testValid191ClientKey() throws Exception {
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
val ownerPremiumId = UUID.fromString("0aaa2c13-922a-411b-b655-9b8c08404695");
@@ -130,7 +130,7 @@ class EncryptionUtilTest {
@Test
void testIncorrect191ClientOwner() throws Exception {
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
val ownerPremiumId = UUID.fromString("61699b2e-d327-4a01-9f1e-0ea8c3f06bc6");
@@ -170,7 +170,7 @@ class EncryptionUtilTest {
void testServerIdHash() throws Exception {
val serverId = "";
val sharedSecret = generateSharedKey();
val serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
val serverPK = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
assertEquals(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), sessionHash);
@@ -200,7 +200,7 @@ class EncryptionUtilTest {
void testServerIdHashWrongSecret() throws Exception {
val serverId = "";
val sharedSecret = generateSharedKey();
val serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
val serverPK = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
assertNotEquals(EncryptionUtil.getServerIdHashString("", generateSharedKey(), serverPK), sessionHash);
@@ -219,7 +219,7 @@ class EncryptionUtilTest {
@Test
void testValidSignedNonce() throws Exception {
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
ClientPublicKey clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
assertTrue(verifySignedNonce(testData, clientKey));
}
@@ -231,7 +231,7 @@ class EncryptionUtilTest {
"signature/incorrect_signature.json",
})
void testIncorrectNonce(String signatureSource) throws Exception {
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
ClientPublicKey clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
SignatureTestData testData = SignatureTestData.fromResource(signatureSource);
assertFalse(verifySignedNonce(testData, clientKey));
}
@@ -239,7 +239,7 @@ class EncryptionUtilTest {
@Test
void testWrongPublicKeySigned() throws Exception {
// load a different public key
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json");
ClientPublicKey clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
assertFalse(verifySignedNonce(testData, clientKey));
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,9 +23,9 @@
* 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.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
@@ -50,6 +50,10 @@ import java.util.Base64;
public class ResourceLoader {
private ResourceLoader() {
// Utility
}
public static RSAPrivateKey parsePrivateKey(String keySpec)
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
try (

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.google.common.io.Resources;
import com.google.gson.Gson;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
package com.github.games647.fastlogin.bukkit.auth.protocollib;
import com.comphenix.protocol.injector.packet.PacketRegistry;
import com.comphenix.protocol.reflect.accessors.Accessors;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.task;
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import lombok.val;

View File

@@ -4,7 +4,7 @@
The MIT License (MIT)
Copyright (c) 2015-2023 games647 and contributors
Copyright (c) 2015-2024 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
@@ -40,6 +40,10 @@
<artifactId>fastlogin.bungee</artifactId>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<!--Represents the main plugin-->
<name>FastLoginBungee</name>
@@ -47,20 +51,12 @@
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.3</version>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
<artifactSet>
<excludes>
<!--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>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
@@ -82,6 +78,7 @@
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>**/module-info</exclude>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
@@ -120,13 +117,33 @@
<groupId>${project.groupId}</groupId>
<artifactId>fastlogin.core</artifactId>
<version>${project.version}</version>
<!--Those classes are already present in BungeeCord version-->
<exclusions>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<!-- Exclude snakeyaml, because it is included in BungeeCord with the correct version -->
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--BungeeCord with also the part outside the API-->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<version>1.20-R0.2-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
@@ -135,13 +152,14 @@
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>mysql</groupId>
<groupId>com.mysql</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-native</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-query</artifactId>
@@ -150,6 +168,11 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>*</artifactId>
@@ -158,6 +181,10 @@
<groupId>org.apache.maven.resolver</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -54,9 +54,15 @@ public class BungeeLoginSource implements LoginSource {
preLoginEvent.setCancelled(true);
if (message == null) {
preLoginEvent.setCancelReason(new ComponentBuilder("Kicked").color(ChatColor.WHITE).create());
preLoginEvent.setReason(
TextComponent.fromArray(
new ComponentBuilder("Kicked").color(ChatColor.WHITE).create()
));
} else {
preLoginEvent.setCancelReason(TextComponent.fromLegacyText(message));
preLoginEvent.setReason(
TextComponent.fromArray(
TextComponent.fromLegacyText(message)
));
}
}
@@ -72,7 +78,7 @@ public class BungeeLoginSource implements LoginSource {
@Override
public String toString() {
return this.getClass().getSimpleName() + '{'
+ "connection=" + connection
+ '}';
+ "connection=" + connection
+ '}';
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -28,7 +28,6 @@ package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
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;
@@ -38,6 +37,7 @@ 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.scheduler.AsyncScheduler;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.MapMaker;
@@ -98,7 +98,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
//events
PluginManager pluginManager = getProxy().getPluginManager();
Listener connectListener = new ConnectListener(this, core.getAntiBot());
Listener connectListener = new ConnectListener(this, core.getAntiBotService());
pluginManager.registerListener(this, connectListener);
pluginManager.registerListener(this, new PluginMessageListener(this));

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -71,25 +71,43 @@ public class ConnectListener implements Listener {
private static final String UUID_FIELD_NAME = "uniqueId";
protected static final MethodHandle UNIQUE_ID_SETTER;
private static final String REWRITE_ID_NAME = "rewriteId";
protected static final MethodHandle REWRITE_ID_SETTER;
static {
MethodHandle setHandle = null;
MethodHandle uniqueIdHandle = null;
MethodHandle rewriterHandle = null;
try {
Lookup lookup = MethodHandles.lookup();
// test for implementation class availability
Class.forName("net.md_5.bungee.connection.InitialHandler");
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
uuidField.setAccessible(true);
setHandle = lookup.unreflectSetter(uuidField);
uniqueIdHandle = getHandlerSetter(lookup, UUID_FIELD_NAME);
try {
rewriterHandle = getHandlerSetter(lookup, REWRITE_ID_NAME);
} catch (NoSuchFieldException noSuchFieldEx) {
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
logger.error(
"Rewrite field not found. Setting only legacy BungeeCord field"
);
}
} catch (ReflectiveOperationException reflectiveOperationException) {
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
logger.error(
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
"Cannot find Bungee UUID field implementation; Disabling premium UUID and skin won't work.",
reflectiveOperationException
);
}
UNIQUE_ID_SETTER = setHandle;
UNIQUE_ID_SETTER = uniqueIdHandle;
REWRITE_ID_SETTER = rewriterHandle;
}
private static MethodHandle getHandlerSetter(Lookup lookup, String fieldName)
throws NoSuchFieldException, IllegalAccessException {
Field uuidField = InitialHandler.class.getDeclaredField(fieldName);
uuidField.setAccessible(true);
return lookup.unreflectSetter(uuidField);
}
private final FastLoginBungee plugin;
@@ -179,6 +197,12 @@ public class ConnectListener implements Listener {
// So we have to do it with reflection
UNIQUE_ID_SETTER.invokeExact(connection, offlineUUID);
// if available set rewrite id to forward the UUID for newer BungeeCord versions since
// https://github.com/SpigotMC/BungeeCord/commit/1be25b6c74ec2be4b15adf8ca53a0497f01e2afe
if (REWRITE_ID_SETTER != null) {
REWRITE_ID_SETTER.invokeExact(connection, offlineUUID);
}
String format = "Overridden UUID from {} to {} (based of {}) on {}";
plugin.getLog().info(format, oldPremiumId, offlineUUID, username, connection);
} catch (Exception ex) {
@@ -209,9 +233,6 @@ public class ConnectListener implements Listener {
return;
}
// delay sending force command, because Paper will process the login event asynchronously
// In this case it means that the force command (plugin message) is already received and processed while
// player is still in the login phase and reported to be offline.
Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server, session);
plugin.getScheduler().runAsync(loginTask);
}
@@ -220,6 +241,5 @@ public class ConnectListener implements Listener {
public void onDisconnect(PlayerDisconnectEvent disconnectEvent) {
ProxiedPlayer player = disconnectEvent.getPlayer();
plugin.getSession().remove(player.getPendingConnection());
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -37,7 +37,6 @@ import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PluginMessageEvent;
@@ -96,15 +95,6 @@ public class PluginMessageListener implements Listener {
String playerName = changeMessage.getPlayerName();
boolean isSourceInvoker = changeMessage.isSourceInvoker();
if (changeMessage.shouldEnable()) {
if (playerName.equals(forPlayer.getName()) && plugin.getCore().getConfig().get("premium-warning", true)
&& !core.getPendingConfirms().contains(forPlayer.getUniqueId())) {
String message = core.getMessage("premium-warning");
forPlayer.sendMessage(TextComponent.fromLegacyText(message));
core.getPendingConfirms().add(forPlayer.getUniqueId());
return;
}
core.getPendingConfirms().remove(forPlayer.getUniqueId());
Runnable task = new AsyncToggleMessage(core, forPlayer, playerName, true, isSourceInvoker);
plugin.getScheduler().runAsync(task);
} else {
@@ -131,7 +121,7 @@ public class PluginMessageListener implements Listener {
loginSession.setRegistered(true);
if (!loginSession.isAlreadySaved()) {
playerProfile.setPremium(true);
playerProfile.setOnlinemodePreferred(true);
plugin.getCore().getStorage().save(playerProfile);
loginSession.setAlreadySaved(true);
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -81,7 +81,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
String ip = source.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogin().put(ip + username, new Object());
plugin.getCore().addLoginAttempt(ip, username);
}
@Override

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -64,12 +64,12 @@ public class AsyncToggleMessage implements Runnable {
private void turnOffPremium() {
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
//existing player is already cracked
if (playerProfile.isSaved() && !playerProfile.isPremium()) {
if (playerProfile.isExistingPlayer() && !playerProfile.isOnlinemodePreferred()) {
sendMessage("not-premium");
return;
}
playerProfile.setPremium(false);
playerProfile.setOnlinemodePreferred(false);
playerProfile.setId(null);
core.getStorage().save(playerProfile);
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName()))
@@ -81,12 +81,12 @@ public class AsyncToggleMessage implements Runnable {
private void activatePremium() {
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
if (playerProfile.isPremium()) {
if (playerProfile.isOnlinemodePreferred()) {
sendMessage("already-exists");
return;
}
playerProfile.setPremium(true);
playerProfile.setOnlinemodePreferred(true);
core.getStorage().save(playerProfile);
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName()))
? PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -11,8 +11,6 @@ author: games647, https://github.com/games647/FastLogin/graphs/contributors
softDepends:
# BungeeCord auth plugins
- BungeeAuth
- BungeeCordAuthenticatorBungee
- SodionAuth
# Bedrock Player Bridge
- Geyser-BungeeCord
- floodgate

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -5,7 +5,7 @@
The MIT License (MIT)
Copyright (c) 2015-2023 games647 and contributors
Copyright (c) 2015-2024 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
@@ -29,35 +29,6 @@
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the sun coding conventions from:
- the Java Language Specification at
https://docs.oracle.com/javase/specs/jls/se11/html/index.html
- the Sun Code Conventions at https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
- the Javadoc guidelines at
https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html
- the JDK Api documentation https://docs.oracle.com/en/java/javase/11/
- some best practices
Checkstyle is very configurable. Be sure to read the documentation at
https://checkstyle.org (or in your downloaded distribution).
Most Checks are configurable, be sure to consult the documentation.
To completely disable a check, just comment it out or delete it from the file.
To suppress certain violations please review suppression filters.
Finally, it is worth reading the documentation.
-->
<module name="Checker">
<!--
If you set the basedir property below, then all reported file
@@ -220,6 +191,12 @@
<property name="optional" value="true"/>
</module>
<!-- Suppress filters via comments -->
<!-- https://stackoverflow.com/a/4023351/9767089 -->
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
<property name="checkFormat" value="$1"/>
</module>
</module>
</module>

View File

@@ -4,7 +4,7 @@
The MIT License (MIT)
Copyright (c) 2015-2023 games647 and contributors
Copyright (c) 2015-2024 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
@@ -39,6 +39,11 @@
<artifactId>fastlogin.core</artifactId>
<packaging>jar</packaging>
<properties>
<!-- Still force Java 8 for the remaining project -->
<maven.compiler.release>8</maven.compiler.release>
</properties>
<name>FastLoginCore</name>
<repositories>
@@ -55,7 +60,7 @@
</repository>
<!-- Floodgate -->
<repository>
<id>opencollab-snapshot</id>
<id>opencollab</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
@@ -63,6 +68,56 @@
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>com.github.games647.fastlogin.core</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jdk21</id>
<activation>
<jdk>[21,)</jdk>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>jdk21</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>21</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java21</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
<dependencies>
<!-- Libraries that we shade into the project -->
@@ -70,7 +125,7 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
<version>5.1.0</version>
<exclusions>
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
<!-- We will use the api provided by the jdk14 dependency -->
@@ -85,20 +140,21 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>2.0.7</version>
<version>2.0.13</version>
</dependency>
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
<!-- snakeyaml is present in Bungee, Spigot, so we could use this independent implementation -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
<version>1.20-R0.2-SNAPSHOT</version>
</dependency>
<!-- This is optional in BungeeCord-config, so we include it here manually -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.2</version>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
@@ -147,46 +203,10 @@
<dependency>
<groupId>com.github.games647</groupId>
<artifactId>craftapi</artifactId>
<version>0.6.2</version>
</dependency>
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
<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>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Database driver included in Spigot -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -32,8 +32,8 @@ import org.slf4j.jul.JDK14LoggerAdapter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.time.Duration;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public final class CommonUtil {
@@ -41,11 +41,11 @@ public final class CommonUtil {
private static final char COLOR_CHAR = '&';
private static final char TRANSLATED_CHAR = '§';
public static <K, V> ConcurrentMap<K, V> buildCache(int expireAfterWrite, int maxSize) {
public static <K, V> ConcurrentMap<K, V> buildCache(Duration expireAfterWrite, int maxSize) {
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
if (expireAfterWrite > 0) {
builder.expireAfterWrite(expireAfterWrite, TimeUnit.MINUTES);
if (expireAfterWrite != null) {
builder.expireAfterWrite(expireAfterWrite);
}
if (maxSize > 0) {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -29,8 +29,6 @@ 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;
@@ -44,38 +42,9 @@ import java.util.Optional;
*/
public class ProxyAgnosticMojangResolver extends MojangResolver {
private static final String HOST = "sessionserver.mojang.com";
/**
* A formatting string containing a URL used to call the {@code hasJoined} method on mojang session servers.
* <p>
* Formatting parameters:
* 1. The username of the player in question
* 2. The serverId of this server
*/
public static final String ENDPOINT = "https://" + HOST + "/session/minecraft/hasJoined?username=%s&serverId=%s";
@Override
public Optional<Verification> hasJoined(String username, String serverHash, InetAddress hostIp)
throws IOException {
String url = String.format(ENDPOINT, 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);
return super.hasJoined(username, serverHash, null);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -107,7 +107,7 @@ public class TickingRateLimiter implements RateLimiter {
}
}
private static class TimeRecord implements Comparable<Long> {
private static class TimeRecord implements Comparable<TimeRecord> {
private final long firstMinuteRecord;
private final long expireTime;
@@ -131,9 +131,9 @@ public class TickingRateLimiter implements RateLimiter {
return firstMinuteRecord + expireTime <= now;
}
@Override
public int compareTo(Long other) {
public int compareTo(long other) {
if (other < firstMinuteRecord) {
// other is earlier
return -1;
}
@@ -143,5 +143,10 @@ public class TickingRateLimiter implements RateLimiter {
return 0;
}
@Override
public int compareTo(TimeRecord other) {
return compareTo(other.firstMinuteRecord);
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -25,8 +25,17 @@
*/
package com.github.games647.fastlogin.core.hooks;
/**
* Password generator for your auth plugin.
* @param <P> platform dependent player class
*/
@FunctionalInterface
public interface PasswordGenerator<P> {
/**
* Generate a password for a non-registered player
* @param player player representation
* @return generated password
*/
String getRandomPassword(P player);
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,44 +23,36 @@
* 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.core.scheduler;
import com.github.games647.fastlogin.core.shared.LoginSource;
import protocolsupport.api.events.PlayerLoginStartEvent;
import org.slf4j.Logger;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
public class ProtocolLoginSource implements LoginSource {
public abstract class AbstractAsyncScheduler {
private final PlayerLoginStartEvent loginStartEvent;
protected final Logger logger;
protected final Executor processingPool;
protected final AtomicInteger currentlyRunning = new AtomicInteger();
public ProtocolLoginSource(PlayerLoginStartEvent loginStartEvent) {
this.loginStartEvent = loginStartEvent;
public AbstractAsyncScheduler(Logger logger, Executor processingPool) {
this.logger = logger;
this.processingPool = processingPool;
}
@Override
public void enableOnlinemode() {
loginStartEvent.setOnlineMode(true);
}
public abstract CompletableFuture<Void> runAsync(Runnable task);
@Override
public void kick(String message) {
loginStartEvent.denyLogin(message);
}
public abstract CompletableFuture<Void> runAsyncDelayed(Runnable task, Duration delay);
@Override
public InetSocketAddress getAddress() {
return loginStartEvent.getConnection().getRawAddress();
}
public PlayerLoginStartEvent getLoginStartEvent() {
return loginStartEvent;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + '{'
+ "loginStartEvent=" + loginStartEvent
+ '}';
protected void process(Runnable task) {
currentlyRunning.incrementAndGet();
try {
task.run();
} finally {
currentlyRunning.getAndDecrement();
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -23,13 +23,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
package com.github.games647.fastlogin.core.scheduler;
import org.slf4j.Logger;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
/**
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
@@ -38,25 +38,14 @@ import java.util.concurrent.atomic.AtomicInteger;
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
* threads.
*/
public class AsyncScheduler {
private static final int MAX_CAPACITY = 1024;
//todo: single thread for delaying and scheduling tasks
private final Logger logger;
// 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 AtomicInteger currentlyRunning = new AtomicInteger();
public class AsyncScheduler extends AbstractAsyncScheduler {
public AsyncScheduler(Logger logger, Executor processingPool) {
this.logger = logger;
this.processingPool = processingPool;
super(logger, processingPool);
logger.info("Using legacy scheduler");
}
@Override
public CompletableFuture<Void> runAsync(Runnable task) {
return CompletableFuture.runAsync(() -> process(task), processingPool).exceptionally(error -> {
logger.warn("Error occurred on thread pool", error);
@@ -64,12 +53,22 @@ public class AsyncScheduler {
});
}
private void process(Runnable task) {
currentlyRunning.incrementAndGet();
try {
task.run();
} finally {
currentlyRunning.getAndDecrement();
}
@Override
public CompletableFuture<Void> runAsyncDelayed(Runnable task, Duration delay) {
return CompletableFuture.runAsync(() -> {
currentlyRunning.incrementAndGet();
try {
Thread.sleep(delay.toMillis());
process(task);
} catch (InterruptedException interruptedException) {
// restore interrupt flag
Thread.currentThread().interrupt();
} finally {
currentlyRunning.getAndDecrement();
}
}, processingPool).exceptionally(error -> {
logger.warn("Error occurred on thread pool", error);
return null;
});
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -55,12 +55,12 @@ import java.net.Proxy.Type;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -78,8 +78,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
private static final long MAX_EXPIRE_RATE = 1_000_000;
private final Map<String, String> localeMessages = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Object> pendingLogin = CommonUtil.buildCache(5, -1);
private final Collection<UUID> pendingConfirms = new HashSet<>();
private final ConcurrentMap<String, Object> pendingLogin = CommonUtil.buildCache(
Duration.ofMinutes(5), -1
);
private final T plugin;
private MojangResolver resolver;
@@ -119,7 +121,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
// Initialize the resolver based on the config parameter
this.resolver = this.config.getBoolean("useProxyAgnosticResolver", false)
? new ProxyAgnosticMojangResolver() : new MojangResolver();
? new ProxyAgnosticMojangResolver() : new MojangResolver();
antiBot = createAntiBotService(config.getSection("anti-bot"));
Set<Proxy> proxies = config.getStringList("proxies")
@@ -140,7 +142,6 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
resolver.setMaxNameRequests(config.getInt("mojang-request-limit"));
resolver.setProxySelector(new RotatingProxySelector(proxies));
resolver.setOutgoingAddresses(addresses);
}
private AntiBotService createAntiBotService(Configuration botSection) {
@@ -160,12 +161,12 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
Action action = Action.Ignore;
switch (botSection.getString("action", "ignore")) {
case "ignore":
action = Action.Ignore;
break;
case "block":
action = Action.Block;
break;
case "ignore":
action = Action.Ignore;
break;
default:
plugin.getLog().warn("Invalid anti bot action - defaulting to ignore");
}
@@ -272,19 +273,23 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
this.passwordGenerator = passwordGenerator;
}
public ConcurrentMap<String, Object> getPendingLogin() {
return pendingLogin;
public void addLoginAttempt(String ip, String username) {
pendingLogin.put(ip + username, new Object());
}
public Collection<UUID> getPendingConfirms() {
return pendingConfirms;
public boolean hasFailedLogin(String ip, String username) {
if (!config.get("secondAttemptCracked", false)) {
return false;
}
return pendingLogin.remove(ip + username) != null;
}
public AuthPlugin<P> getAuthPluginHook() {
return authPlugin;
}
public AntiBotService getAntiBot() {
public AntiBotService getAntiBotService() {
return antiBot;
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -33,6 +33,7 @@ import org.geysermc.floodgate.api.player.FloodgatePlayer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Locale;
import java.util.Optional;
import java.util.UUID;
@@ -61,9 +62,9 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
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();
autoLoginFloodgate = core.getConfig().getString("autoLoginFloodgate").toLowerCase(Locale.ROOT);
autoRegisterFloodgate = core.getConfig().getString("autoRegisterFloodgate").toLowerCase(Locale.ROOT);
allowNameConflict = core.getConfig().getString("allowFloodgateNameConflict").toLowerCase(Locale.ROOT);
}
@Override
@@ -80,13 +81,47 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
}
profile = core.getStorage().loadProfile(username);
if (profile.isExistingPlayer()) {
if (profile.isFloodgateMigrated()) {
if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) {
core.getPlugin().getLog()
.info("Player {} is already stored by FastLogin as a non-linked Bedrock Edition player",
username);
return;
} else if (profile.getFloodgate() == FloodgateState.FALSE && isLinked) {
profile.setFloodgate(FloodgateState.LINKED);
core.getPlugin().getLog().info(
"Player {} will be changed from a Java player to a linked Floodgate player",
username);
}
} else {
if (isLinked) {
profile.setFloodgate(FloodgateState.LINKED);
core.getPlugin().getLog().info(
"Player {} will be migrated to the v2 database schema as a linked Floodgate user",
username);
} else {
profile.setFloodgate(FloodgateState.TRUE);
core.getPlugin().getLog().info(
"Player {} will be migrated to the v2 database schema as a Floodgate user", username);
}
}
} else {
if (isLinked) {
profile.setFloodgate(FloodgateState.LINKED);
} else {
profile.setFloodgate(FloodgateState.TRUE);
}
}
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
try {
//maybe Bungee without auth plugin
if (authPlugin == null) {
if (profile != null) {
isRegistered = profile.isPremium();
isRegistered = profile.isOnlinemodePreferred();
} else {
isRegistered = false;
}
@@ -119,13 +154,17 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
}
}
// defer auto registration, if it's not enabled in the config
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());
// stop the auto login procedure, if the current connection's parameters don't match the one stored in our
// database
// ex. we stored a LINKED account, but the current connection is not linked
if ((profile.getFloodgate() == FloodgateState.LINKED && !isLinked)
|| (profile.getFloodgate() == FloodgateState.TRUE && isLinked)) {
return;
}
//start Bukkit/Bungee specific tasks

View File

@@ -0,0 +1,86 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 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;
public enum FloodgateState {
/**
* Purely Java profile
*/
FALSE(0),
/**
* Purely Bedrock profile
*/
TRUE(1),
/**
* Bedrock profile is bidirectional associated with the Java Mojang profile.
*/
LINKED(2),
/**
* Data before floodgate database migration. Floodgate state is unknown.
*/
NOT_MIGRATED(3);
private final int value;
FloodgateState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
/**
* Convert a number to FloodgateState
* <ol start="0">
* <li>False</li>
* <li>True</li>
* <li>Linked</li>
* <li>Not Migrated</li>
* </ol>
* @param num the number, most likely loaded from the database
* @return FloodgateStatus on success, null otherwise
*/
public static FloodgateState fromInt(int num) {
// using Enum.values()[i] is expensive as per https://stackoverflow.com/a/8762387/9767089
switch (num) {
case 0:
return FloodgateState.FALSE;
case 1:
return FloodgateState.TRUE;
case 2:
return FloodgateState.LINKED;
case 3:
return FloodgateState.NOT_MIGRATED;
default:
return null;
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -62,7 +62,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
//premium player
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
if (authPlugin == null) {
//maybe only bungeecord plugin
// maybe only bungeecord plugin
onForceActionSuccess(session);
} else {
boolean success = true;
@@ -81,7 +81,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
//update only on success to prevent corrupt data
if (playerProfile != null) {
playerProfile.setId(session.getUuid());
playerProfile.setPremium(true);
playerProfile.setOnlinemodePreferred(true);
storage.save(playerProfile);
}
@@ -91,7 +91,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
} else if (playerProfile != null) {
//cracked player
playerProfile.setId(null);
playerProfile.setPremium(false);
playerProfile.setOnlinemodePreferred(false);
storage.save(playerProfile);
}
} catch (Exception ex) {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
* Copyright (c) 2015-2024 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
@@ -48,73 +48,88 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
}
public void onLogin(String username, S source) {
core.getPlugin().getLog().info("Handling player {}", username);
StoredProfile profile = core.getStorage().loadProfile(username);
if (profile == null) {
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
//perform Bedrock specific checks and skip Java checks if no longer needed
if (bedrockService.performChecks(username, source)) {
return;
}
}
callFastLoginPreLoginEvent(username, source, profile);
StoredProfile profile = core.getStorage().loadProfile(username);
//can't be a premium Java player, if it's not saved in the database
if (profile == null) {
return;
}
Configuration config = core.getConfig();
if (profile.isFloodgateMigrated()) {
if (profile.getFloodgate() == FloodgateState.TRUE) {
// migrated and enabled floodgate player, however the above bedrocks fails, so the current connection
// isn't premium
return;
}
} else {
profile.setFloodgate(FloodgateState.FALSE);
core.getPlugin().getLog().info(
"Player {} will be migrated to the v2 database schema as a JAVA user", username
);
}
callFastLoginPreLoginEvent(username, source, profile);
String ip = source.getAddress().getAddress().getHostAddress();
profile.setLastIp(ip);
try {
if (profile.isSaved()) {
if (profile.isPremium()) {
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);
}
}
if (profile.isExistingPlayer()) {
if (profile.isOnlinemodePreferred()) {
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
requestPremiumLogin(source, profile, username, true);
} else {
if (core.getPendingLogin().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
core.getPlugin().getLog().info("Second attempt login -> cracked {}", username);
//first login request failed so make a cracked session
startCrackedSession(source, profile, username);
return;
}
Optional<Profile> premiumUUID = Optional.empty();
if (config.get("nameChangeCheck", false) || config.get("autoRegister", false)) {
premiumUUID = core.getResolver().findProfile(username);
}
if (!premiumUUID.isPresent()
|| (!checkNameChange(source, username, premiumUUID.get())
&& !checkPremiumName(source, username, profile))) {
//nothing detected the player as premium -> start a cracked session
if (core.getConfig().get("switchMode", false)) {
source.kick(core.getMessage("switch-kick-message"));
return;
}
if (isValidUsername(source, profile)) {
startCrackedSession(source, profile, username);
}
}
} else {
performNewPlayerLogin(username, source, ip, profile);
}
}
private void performNewPlayerLogin(String username, S source, String ip, StoredProfile profile) {
try {
if (core.hasFailedLogin(ip, username)) {
core.getPlugin().getLog().info("Second attempt login -> cracked {}", username);
//first login request failed so make a cracked session
startCrackedSession(source, profile, username);
return;
}
Configuration config = core.getConfig();
Optional<Profile> premiumUUID = Optional.empty();
if (config.get("nameChangeCheck", false) || config.get("autoRegister", false)) {
premiumUUID = core.getResolver().findProfile(username);
}
if (premiumUUID.isPresent()
|| (!isNameChanged(source, username, premiumUUID.get())
&& !isUsernameAvailable(source, username, profile))) {
//nothing detected the player as premium -> start a cracked session
if (core.getConfig().get("switchMode", false)) {
source.kick(core.getMessage("switch-kick-message"));
return;
}
startCrackedSession(source, profile, username);
}
} catch (RateLimitException rateLimitEx) {
core.getPlugin().getLog().error("Mojang's rate limit reached for {}. The public IPv4 address of this"
+ " server issued more than 600 Name -> UUID requests within 10 minutes. After those 10"
+ " minutes we can make requests again.", username);
+ " server issued more than 600 Name -> UUID requests within 10 minutes. After those 10"
+ " minutes we can make requests again.", username);
} catch (Exception ex) {
core.getPlugin().getLog().error("Failed to check premium state for {}", username, ex);
core.getPlugin().getLog().error("Failed to check premium state of {}", username, ex);
}
}
protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception {
protected boolean isValidUsername(LoginSource source, StoredProfile profile) {
if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
source.kick("Your username contains illegal characters");
@@ -124,7 +139,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
return true;
}
private boolean checkPremiumName(S source, String username, StoredProfile profile) throws Exception {
private boolean isUsernameAvailable(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))) {
requestPremiumLogin(source, profile, username, false);
@@ -134,11 +149,17 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
return false;
}
private boolean checkNameChange(S source, String username, Profile profile) {
private boolean isNameChanged(S source, String username, Profile profile) {
//user not exists in the db
if (core.getConfig().get("nameChangeCheck", false)) {
StoredProfile storedProfile = core.getStorage().loadProfile(profile.getId());
if (storedProfile != null) {
if (storedProfile.getFloodgate() == FloodgateState.TRUE) {
core.getPlugin().getLog()
.info("Player {} is already stored by FastLogin as a Bedrock Edition player.", username);
return false;
}
//uuid exists in the database
core.getPlugin().getLog().info("GameProfile {} changed it's username", profile);

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